Exemple #1
0
/* Query if long-press events should be handled and signals emitted */
static void _xfdashboard_click_action_query_long_press(XfdashboardClickAction *self)
{
    XfdashboardClickActionPrivate	*priv;
    ClutterActor					*actor;
    gboolean						result;
    gint							timeout;

    g_return_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self));

    priv=self->priv;
    result=FALSE;

    /* If no duration was set get default one from settings */
    if(priv->longPressDuration<0)
    {
        ClutterSettings				*settings=clutter_settings_get_default();

        g_object_get(settings, "long-press-duration", &timeout, NULL);
    }
    else timeout=priv->longPressDuration;

    /* Emit signal to determine if long-press should be supported */
    actor=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(self));
    g_signal_emit(self, XfdashboardClickActionSignals[SIGNAL_LONG_PRESS], 0, actor, CLUTTER_LONG_PRESS_QUERY, &result);

    if(result)
    {
        priv->longPressID=clutter_threads_add_timeout(timeout,
                          _xfdashboard_click_action_emit_long_press,
                          self);
    }
}
Exemple #2
0
/**
 * xfdashboard_click_action_get_coords:
 * @self: A #XfdashboardClickAction
 * @outPressX: (out): Return location for the X coordinate or %NULL
 * @outPressY: (out): Return location for the Y coordinate or %NULL
 *
 * Retrieves the screen coordinates of the button press.
 */
void xfdashboard_click_action_get_coords(XfdashboardClickAction *self, gfloat *outPressX, gfloat *outPressY)
{
    g_return_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self));

    if(outPressX!=NULL) *outPressX=self->priv->pressX;
    if(outPressY!=NULL) *outPressY=self->priv->pressY;
}
Exemple #3
0
/* Emit "long-press" signal */
static gboolean _xfdashboard_click_action_emit_long_press(gpointer inUserData)
{
    XfdashboardClickAction			*self;
    XfdashboardClickActionPrivate	*priv;
    ClutterActor					*actor;
    gboolean						result;

    g_return_val_if_fail(XFDASHBOARD_IS_CLICK_ACTION(inUserData), FALSE);

    self=XFDASHBOARD_CLICK_ACTION(inUserData);
    priv=self->priv;

    /* Reset variables */
    priv->longPressID=0;

    /* Emit signal */
    actor=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(inUserData));
    g_signal_emit(self, XfdashboardClickActionSignals[SIGNAL_LONG_PRESS], 0, actor, CLUTTER_LONG_PRESS_ACTIVATE, &result);

    /* Disconnect signal handlers */
    if(priv->captureID!=0)
    {
        g_signal_handler_disconnect(priv->stage, priv->captureID);
        priv->captureID=0;
    }

    /* Reset state of this action */
    _xfdashboard_click_action_set_pressed(self, FALSE);
    _xfdashboard_click_action_set_held(self, FALSE);

    /* Event handled */
    return(FALSE);
}
Exemple #4
0
/* Set press state */
static void _xfdashboard_click_action_set_pressed(XfdashboardClickAction *self, gboolean isPressed)
{
    XfdashboardClickActionPrivate	*priv;
    ClutterActor					*actor;

    g_return_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self));

    priv=self->priv;

    /* Set value if changed */
    isPressed=!!isPressed;

    if(priv->isPressed!=isPressed)
    {
        /* Set value */
        priv->isPressed=isPressed;

        /* Style state */
        actor=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(self));
        if(XFDASHBOARD_IS_ACTOR(actor))
        {
            if(priv->isPressed) xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(actor), "pressed");
            else xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(actor), "pressed");
        }

        /* Notify about property change */
        g_object_notify_by_pspec(G_OBJECT(self), XfdashboardClickActionProperties[PROP_PRESSED]);
    }
}
/* A menu item was clicked */
static void _xfdashboard_popup_menu_item_meta_clicked(XfdashboardPopupMenuItemMeta *self,
														ClutterActor *inActor,
														gpointer inUserData)
{
	g_return_if_fail(XFDASHBOARD_IS_POPUP_MENU_ITEM_META(self));
	g_return_if_fail(CLUTTER_IS_ACTOR(inActor));
	g_return_if_fail(XFDASHBOARD_IS_CLICK_ACTION(inUserData));

	/* Activate menu item */
	xfdashboard_popup_menu_item_meta_activate(self);
}
Exemple #6
0
/* Called when attaching and detaching a ClutterActorMeta instance to a ClutterActor */
static void _xfdashboard_click_action_set_actor(ClutterActorMeta *inActorMeta, ClutterActor *inActor)
{
    XfdashboardClickAction			*self;
    XfdashboardClickActionPrivate	*priv;

    g_return_if_fail(XFDASHBOARD_IS_CLICK_ACTION(inActorMeta));

    self=XFDASHBOARD_CLICK_ACTION(inActorMeta);
    priv=self->priv;

    /* Disconnect signals and remove sources */
    if(priv->eventID!=0)
    {
        ClutterActor				*oldActor=clutter_actor_meta_get_actor(inActorMeta);

        if(oldActor!=NULL) g_signal_handler_disconnect(oldActor, priv->eventID);
        priv->eventID=0;
    }

    if(priv->captureID!=0)
    {
        if(priv->stage!=NULL) g_signal_handler_disconnect(priv->stage, priv->captureID);
        priv->captureID=0;
        priv->stage=NULL;
    }

    if(priv->longPressID!=0)
    {
        g_source_remove(priv->longPressID);
        priv->longPressID=0;
    }

    /* Reset state of this action */
    _xfdashboard_click_action_set_pressed(self, FALSE);
    _xfdashboard_click_action_set_held(self, FALSE);

    /* Connect signals */
    if(inActor!=NULL)
    {
        priv->eventID=g_signal_connect_swapped(inActor,
                                               "event",
                                               G_CALLBACK(_xfdashboard_click_action_on_event),
                                               self);
    }

    /* Call parent's class method */
    if(CLUTTER_ACTOR_META_CLASS(xfdashboard_click_action_parent_class)->set_actor)
    {
        CLUTTER_ACTOR_META_CLASS(xfdashboard_click_action_parent_class)->set_actor(inActorMeta, inActor);
    }
}
Exemple #7
0
/* Proxy ClickAction signals */
static void _xfdashboard_button_clicked(XfdashboardClickAction *inAction,
										ClutterActor *self,
										gpointer inUserData)
{
	g_return_if_fail(XFDASHBOARD_IS_CLICK_ACTION(inAction));
	g_return_if_fail(XFDASHBOARD_IS_BUTTON(self));

	/* Only emit signal if click was perform with left button */
	if(xfdashboard_click_action_get_button(inAction)==XFDASHBOARD_CLICK_ACTION_LEFT_BUTTON)
	{
		/* Emit 'clicked' signal */
		g_signal_emit(self, XfdashboardButtonSignals[SIGNAL_CLICKED], 0);
	}
}
Exemple #8
0
/* Set held state */
static void _xfdashboard_click_action_set_held(XfdashboardClickAction *self, gboolean isHeld)
{
    XfdashboardClickActionPrivate	*priv;

    g_return_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self));

    priv=self->priv;

    /* Set value if changed */
    isHeld=!!isHeld;

    if(priv->isHeld!=isHeld)
    {
        /* Set value */
        priv->isHeld=isHeld;

        /* Notify about property change */
        g_object_notify_by_pspec(G_OBJECT(self), XfdashboardClickActionProperties[PROP_HELD]);
    }
}
Exemple #9
0
/**
 * xfdashboard_click_action_release:
 * @self: A #XfdashboardClickAction
 *
 * Emulates a release of the pointer button, which ungrabs the pointer
 * and unsets the #XfdashboardClickAction:pressed state.
 *
 * This function will also cancel the long press gesture if one was
 * initiated.
 *
 * This function is useful to break a grab, for instance after a certain
 * amount of time has passed.
 */
void xfdashboard_click_action_release(XfdashboardClickAction *self)
{
    XfdashboardClickActionPrivate	*priv;

    g_return_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self));

    priv=self->priv;

    /* Only release pointer button if it is held by this action */
    if(!priv->isHeld) return;

    /* Disconnect signal handlers */
    if(priv->captureID!=0)
    {
        g_signal_handler_disconnect(priv->stage, priv->captureID);
        priv->captureID=0;
    }

    /* Reset state of this action */
    _xfdashboard_click_action_cancel_long_press(self);
    _xfdashboard_click_action_set_held(self, FALSE);
    _xfdashboard_click_action_set_pressed(self, FALSE);
}
Exemple #10
0
/* Cancel long-press handling */
static void _xfdashboard_click_action_cancel_long_press(XfdashboardClickAction *self)
{
    XfdashboardClickActionPrivate	*priv;

    g_return_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self));

    priv=self->priv;

    /* Remove signals/sources and emit cancel signal */
    if(priv->longPressID!=0)
    {
        ClutterActor				*actor;
        gboolean					result;

        /* Remove source */
        g_source_remove(priv->longPressID);
        priv->longPressID=0;

        /* Emit signal */
        actor=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(self));
        g_signal_emit(self, XfdashboardClickActionSignals[SIGNAL_LONG_PRESS], 0, actor, CLUTTER_LONG_PRESS_CANCEL, &result);
    }
}
Exemple #11
0
/**
 * xfdashboard_click_action_get_state:
 * @self: A #XfdashboardClickAction
 *
 * Retrieves the modifier state of the click action.
 *
 * Return value: The modifier state parameter or 0
 */
ClutterModifierType xfdashboard_click_action_get_state(XfdashboardClickAction *self)
{
    g_return_val_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self), 0);

    return(self->priv->modifierState);
}
Exemple #12
0
/**
 * xfdashboard_click_action_get_button:
 * @self: A #XfdashboardClickAction
 *
 * Retrieves the button that was pressed.
 *
 * Return value: The button value
 */
guint xfdashboard_click_action_get_button(XfdashboardClickAction *self)
{
    g_return_val_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self), 0);

    return(self->priv->pressButton);
}
Exemple #13
0
/* An event was received */
static gboolean _xfdashboard_click_action_on_event(XfdashboardClickAction *self, ClutterEvent *inEvent, gpointer inUserData)
{
    XfdashboardClickActionPrivate	*priv;
    gboolean						hasButton;
    ClutterActor					*actor;

    g_return_val_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self), CLUTTER_EVENT_PROPAGATE);
    g_return_val_if_fail(CLUTTER_IS_ACTOR(inUserData), CLUTTER_EVENT_PROPAGATE);

    priv=self->priv;
    hasButton=TRUE;
    actor=CLUTTER_ACTOR(inUserData);

    /* Check if actor is enabled to handle events */
    if(!clutter_actor_meta_get_enabled(CLUTTER_ACTOR_META(self))) return(CLUTTER_EVENT_PROPAGATE);

    /* Handle event */
    switch(clutter_event_type(inEvent))
    {
    case CLUTTER_TOUCH_BEGIN:
        hasButton=FALSE;

    case CLUTTER_BUTTON_PRESS:
        /* We only handle single clicks if it is pointer device */
        if(hasButton && clutter_event_get_click_count(inEvent)!=1)
        {
            return(CLUTTER_EVENT_PROPAGATE);
        }

        /* Do we already held the press? */
        if(priv->isHeld) return(CLUTTER_EVENT_STOP);

        /* Is the source of event a child of this actor. If not do
         * not handle this event but any other.
         */
        if(!clutter_actor_contains(actor, clutter_event_get_source(inEvent)))
        {
            return(CLUTTER_EVENT_PROPAGATE);
        }

        /* Remember event data */
        priv->pressButton=hasButton ? clutter_event_get_button(inEvent) : 0;
        priv->pressDeviceID=clutter_event_get_device_id(inEvent);
        priv->pressSequence=clutter_event_get_event_sequence(inEvent);
        priv->modifierState=clutter_event_get_state(inEvent);
        clutter_event_get_coords(inEvent, &priv->pressX, &priv->pressY);

        if(priv->longPressThreshold<0)
        {
            ClutterSettings		*settings=clutter_settings_get_default();

            g_object_get(settings, "dnd-drag-threshold", &priv->dragThreshold, NULL);
        }
        else priv->dragThreshold=priv->longPressThreshold;

        if(priv->stage==NULL) priv->stage=clutter_actor_get_stage(actor);

        /* Connect signals */
        priv->captureID=g_signal_connect_object(priv->stage,
                                                "captured-event",
                                                G_CALLBACK(_xfdashboard_click_action_on_captured_event),
                                                self,
                                                G_CONNECT_AFTER | G_CONNECT_SWAPPED);

        /* Set state of this action */
        _xfdashboard_click_action_set_pressed(self, TRUE);
        _xfdashboard_click_action_set_held(self, TRUE);
        _xfdashboard_click_action_query_long_press(self);
        break;

    case CLUTTER_ENTER:
        _xfdashboard_click_action_set_pressed(self, priv->isHeld);
        break;

    case CLUTTER_LEAVE:
        _xfdashboard_click_action_set_pressed(self, priv->isHeld);
        _xfdashboard_click_action_cancel_long_press(self);
        break;

    default:
        break;
    }

    return(CLUTTER_EVENT_PROPAGATE);
}
Exemple #14
0
/* An event was captured */
static gboolean _xfdashboard_click_action_on_captured_event(XfdashboardClickAction *self,
        ClutterEvent *inEvent,
        gpointer inUserData)
{
    XfdashboardClickActionPrivate	*priv;
    ClutterActor					*stage G_GNUC_UNUSED;
    ClutterActor					*actor;
    ClutterModifierType				modifierState;
    gboolean						hasButton;

    g_return_val_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self), CLUTTER_EVENT_PROPAGATE);
    g_return_val_if_fail(CLUTTER_IS_ACTOR(inUserData), CLUTTER_EVENT_PROPAGATE);

    priv=self->priv;
    stage=CLUTTER_ACTOR(inUserData);
    hasButton=TRUE;

    /* Handle captured event */
    actor=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(self));
    switch(clutter_event_type(inEvent))
    {
    case CLUTTER_TOUCH_END:
        hasButton=FALSE;

    case CLUTTER_BUTTON_RELEASE:
        if(!priv->isHeld) return(CLUTTER_EVENT_STOP);

        if((hasButton && clutter_event_get_button(inEvent)!=priv->pressButton) ||
                (hasButton && clutter_event_get_click_count(inEvent)!=1) ||
                clutter_event_get_device_id(inEvent)!=priv->pressDeviceID ||
                clutter_event_get_event_sequence(inEvent)!=priv->pressSequence)
        {
            return(CLUTTER_EVENT_PROPAGATE);
        }

        _xfdashboard_click_action_set_held(self, FALSE);
        _xfdashboard_click_action_cancel_long_press(self);

        /* Disconnect the capture */
        if(priv->captureID!=0)
        {
            g_signal_handler_disconnect(priv->stage, priv->captureID);
            priv->captureID = 0;
        }

        if(priv->longPressID!=0)
        {
            g_source_remove(priv->longPressID);
            priv->longPressID=0;
        }

        if(!clutter_actor_contains(actor, clutter_event_get_source(inEvent)))
        {
            return(CLUTTER_EVENT_PROPAGATE);
        }

        /* Exclude any button-mask so that we can compare
         * the press and release states properly
         */
        modifierState=clutter_event_get_state(inEvent) &
                      ~(CLUTTER_BUTTON1_MASK |
                        CLUTTER_BUTTON2_MASK |
                        CLUTTER_BUTTON3_MASK |
                        CLUTTER_BUTTON4_MASK |
                        CLUTTER_BUTTON5_MASK);

        /* If press and release states don't match we simply ignore
         * modifier keys. i.e. modifier keys are expected to be pressed
         * throughout the whole click
         */
        if(modifierState!=priv->modifierState) priv->modifierState=0;

        _xfdashboard_click_action_set_pressed(self, FALSE);
        g_signal_emit(self, XfdashboardClickActionSignals[SIGNAL_CLICKED], 0, actor);
        break;

    case CLUTTER_MOTION:
    case CLUTTER_TOUCH_UPDATE:
    {
        gfloat				motionX, motionY;
        gfloat				deltaX, deltaY;

        if(!priv->isHeld) return(CLUTTER_EVENT_PROPAGATE);

        clutter_event_get_coords (inEvent, &motionX, &motionY);

        deltaX=ABS(motionX-priv->pressX);
        deltaY=ABS(motionY-priv->pressY);

        if(deltaX>priv->dragThreshold || deltaY>priv->dragThreshold)
        {
            _xfdashboard_click_action_cancel_long_press(self);
        }
    }
    break;

    default:
        break;
    }

    /* This is line changed in returning CLUTTER_EVENT_PROPAGATE
     * instead of CLUTTER_EVENT_STOP
     */
    return(CLUTTER_EVENT_PROPAGATE);
}