static gboolean actor_captured_event_cb (ClutterActor *actor, ClutterEvent *event, ClutterGestureAction *action) { ClutterGestureActionPrivate *priv = action->priv; GesturePoint *point G_GNUC_UNUSED; if ((clutter_event_type (event) != CLUTTER_BUTTON_PRESS) && (clutter_event_type (event) != CLUTTER_TOUCH_BEGIN)) return CLUTTER_EVENT_PROPAGATE; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) return CLUTTER_EVENT_PROPAGATE; point = gesture_register_point (action, event); if (priv->stage == NULL) priv->stage = clutter_actor_get_stage (actor); if (priv->stage_capture_id == 0) priv->stage_capture_id = g_signal_connect_after (priv->stage, "captured-event", G_CALLBACK (stage_captured_event_cb), action); /* Start the gesture immediately if the gesture has no * _TRIGGER_EDGE_AFTER drag threshold. */ if ((priv->points->len >= priv->requested_nb_points) && (priv->edge != CLUTTER_GESTURE_TRIGGER_EDGE_AFTER)) begin_gesture (action, actor); return CLUTTER_EVENT_PROPAGATE; }
static gboolean st_scroll_view_fade_pre_paint (ClutterEffect *effect) { StScrollViewFade *self = ST_SCROLL_VIEW_FADE (effect); ClutterEffectClass *parent_class; if (self->shader == COGL_INVALID_HANDLE) return FALSE; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; if (self->actor == NULL) return FALSE; if (self->program == COGL_INVALID_HANDLE) self->program = cogl_create_program (); if (!self->is_attached) { g_assert (self->shader != COGL_INVALID_HANDLE); g_assert (self->program != COGL_INVALID_HANDLE); cogl_program_attach_shader (self->program, self->shader); cogl_program_link (self->program); cogl_handle_unref (self->shader); self->is_attached = TRUE; self->tex_uniform = cogl_program_get_uniform_location (self->program, "tex"); self->height_uniform = cogl_program_get_uniform_location (self->program, "height"); self->width_uniform = cogl_program_get_uniform_location (self->program, "width"); self->scrollbar_width_uniform = cogl_program_get_uniform_location (self->program, "scrollbar_width"); self->scrollbar_height_uniform = cogl_program_get_uniform_location (self->program, "scrollbar_height"); self->rtl_uniform = cogl_program_get_uniform_location (self->program, "rtl"); self->offset_top_uniform = cogl_program_get_uniform_location (self->program, "offset_top"); self->offset_bottom_uniform = cogl_program_get_uniform_location (self->program, "offset_bottom"); } parent_class = CLUTTER_EFFECT_CLASS (st_scroll_view_fade_parent_class); return parent_class->pre_paint (effect); }
static gboolean on_button_press (ClutterActor *actor, ClutterEvent *event, ClutterDragAction *action) { ClutterDragActionPrivate *priv = action->priv; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) return FALSE; if (clutter_event_get_button (event) != 1) return FALSE; if (priv->stage == NULL) priv->stage = CLUTTER_STAGE (clutter_actor_get_stage (actor)); clutter_event_get_coords (event, &priv->press_x, &priv->press_y); priv->press_state = clutter_event_get_state (event); priv->last_motion_x = priv->press_x; priv->last_motion_y = priv->press_y; priv->transformed_press_x = priv->press_x; priv->transformed_press_y = priv->press_y; clutter_actor_transform_stage_point (actor, priv->press_x, priv->press_y, &priv->transformed_press_x, &priv->transformed_press_y); priv->motion_events_enabled = _clutter_stage_get_motion_events_enabled (priv->stage); if (priv->x_drag_threshold == 0 || priv->y_drag_threshold == 0) emit_drag_begin (action, actor, event); else priv->emit_delayed_press = TRUE; priv->in_drag = TRUE; priv->capture_id = g_signal_connect_after (priv->stage, "captured-event", G_CALLBACK (on_captured_event), action); return FALSE; }
static gboolean shell_grid_desaturate_effect_pre_paint (ClutterEffect *effect) { ShellGridDesaturateEffect *self = SHELL_GRID_DESATURATE_EFFECT (effect); ClutterEffectClass *parent_class; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShaderEffect: the graphics hardware " "or the current GL driver does not implement support " "for the GLSL shading language."); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); return FALSE; } parent_class = CLUTTER_EFFECT_CLASS (shell_grid_desaturate_effect_parent_class); if (parent_class->pre_paint (effect)) { ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect); CoglHandle texture; texture = clutter_offscreen_effect_get_texture (offscreen_effect); self->tex_width = cogl_texture_get_width (texture); self->tex_height = cogl_texture_get_height (texture); if (self->unshaded_uniform_dirty) update_unshaded_uniform (self); cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); return TRUE; } else return FALSE; }
/* Default signal handler for "begin" */ static gboolean _xfdashboard_drop_action_class_real_begin(XfdashboardDropAction *self, XfdashboardDragAction *inDragAction) { XfdashboardDropActionPrivate *priv; ClutterActorMeta *actorMeta; g_return_val_if_fail(XFDASHBOARD_IS_DROP_ACTION(self), FALSE); g_return_val_if_fail(self->priv->actor, FALSE); priv=self->priv; actorMeta=CLUTTER_ACTOR_META(self); /* Return TRUE means we can handle dragged actor on this drop target. This is only * possible if drop target is active, visible and reactive. Otherwise we have to * return FALSE to indicate that we cannot handle dragged actor. */ return(clutter_actor_meta_get_enabled(actorMeta) && CLUTTER_ACTOR_IS_VISIBLE(priv->actor) && CLUTTER_ACTOR_IS_REACTIVE(priv->actor)); }
static gboolean shell_anamorphosis_effect_pre_paint (ClutterEffect *effect) { ShellAnamorphosisEffect *self = SHELL_ANAMORPHOSIS_EFFECT (effect); ShellAnamorphosisEffectPrivate *priv = shell_anamorphosis_effect_get_instance_private (self); if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; /* If we're not doing any bending, we're not needed. */ if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShellAnamorphosisEffect: the " "graphics hardware or the current GL driver does not " "implement support for the GLSL shading language. The " "effect will be disabled."); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); return FALSE; } if (!CLUTTER_EFFECT_CLASS (shell_anamorphosis_effect_parent_class)->pre_paint (effect)) return FALSE; ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect); CoglObject *texture; texture = clutter_offscreen_effect_get_texture (offscreen_effect); cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture); priv->tex_width = cogl_texture_get_width (texture); priv->tex_height = cogl_texture_get_height (texture); cogl_pipeline_set_uniform_1i (priv->pipeline, priv->tex_width_uniform, priv->tex_width); cogl_pipeline_set_uniform_1i (priv->pipeline, priv->tex_height_uniform, priv->tex_height); return TRUE; }
static gboolean st_background_effect_pre_paint (ClutterEffect *effect) { StBackgroundEffect *self = ST_BACKGROUND_EFFECT (effect); ClutterEffectClass *parent_class; gfloat width; gfloat height; gfloat posx; gfloat posy; guchar *data; guint size; guint rowstride; glong new_time; gdouble time_used; ClutterActor *stage; gfloat stage_width; gfloat stage_height; if (self->bg_bumpmap == NULL) return FALSE; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); if (self->actor == NULL) return FALSE; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShaderEffect: the graphics hardware " "or the current GL driver does not implement support " "for the GLSL shading language."); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); return FALSE; } new_time = clock(); time_used = ((double) (new_time - self->old_time)*100) / (double) CLOCKS_PER_SEC; self->old_time = new_time; posx = 0.0f; posy = 0.0f; width = 0.0f; height = 0.0f; stage_width = 0.0f; stage_height = 0.0f; clutter_actor_get_transformed_position (self->actor, &posx, &posy); clutter_actor_get_transformed_size (self->actor, &width, &height); self->opacity = clutter_actor_get_paint_opacity (self->actor); stage = clutter_actor_get_stage (self->actor); clutter_actor_get_size (stage, &stage_width, &stage_height); if ((posx < 0) || (posy < 0) || ((posx + width) > stage_width) || ((posy + height) > stage_height)) return FALSE; if (( posx != self->posx_old) || ( posy != self->posy_old) || ( width != self->width_old) || ( height != self->height_old) || (time_used > 50.0)) { self->posx_old = posx; self->posy_old = posy; self->width_old = width; self->height_old = height; self->bg_posx_i = round(posx)+2; self->bg_posy_i = round(posy)+2; self->bg_width_i = round(width)-4; self->bg_height_i = round(height)-4; size = (self->bg_width_i) * (self->bg_height_i) * 4; if (((self->opacity == 0xff) || (self->bg_texture == NULL)) && (size > 400)) { rowstride = (self->bg_width_i) * 4; data = g_malloc (size); cogl_read_pixels (self->bg_posx_i, self->bg_posy_i, self->bg_width_i, self->bg_height_i, COGL_READ_PIXELS_COLOR_BUFFER, COGL_PIXEL_FORMAT_RGBA_8888_PRE, data); if (data != NULL) { if (self->bg_texture != NULL) { cogl_handle_unref (self->bg_texture); self->bg_texture = NULL; } self->bg_texture = st_cogl_texture_new_from_data_wrapper (self->bg_width_i, self->bg_height_i, COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_PIXEL_FORMAT_RGBA_8888_PRE, rowstride, data); g_free (data); } } } parent_class = CLUTTER_EFFECT_CLASS (st_background_effect_parent_class); if (parent_class->pre_paint (effect)) { ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect); CoglHandle fg_texture; fg_texture = clutter_offscreen_effect_get_texture (offscreen_effect); if (fg_texture != COGL_INVALID_HANDLE) { self->fg_width_i = cogl_texture_get_width (fg_texture); self->fg_height_i = cogl_texture_get_height (fg_texture); if ((self->bg_texture != NULL) && (self->opacity == 0xff)) { if (self->pixel_step_uniform0 > -1) { gfloat pixel_step[3]; pixel_step[0] = 1.0f / (self->bg_width_i); pixel_step[1] = 1.0f / (self->bg_height_i); pixel_step[2] = 0.0f; cogl_pipeline_set_uniform_float (self->pipeline0, self->pixel_step_uniform0, 3, 1, pixel_step); } if (self->BumpTex_uniform > -1) { cogl_pipeline_set_uniform_1i (self->pipeline0, self->BumpTex_uniform, 1); } if (self->bump_step_uniform > -1) { gfloat bump_step[2]; bump_step[0] = 1.0f / (self->bumptex_width_i); bump_step[1] = 1.0f / (self->bumptex_height_i); cogl_pipeline_set_uniform_float (self->pipeline0, self->bump_step_uniform, 2, 1, bump_step); } if (self->bg_sub_texture != NULL) { cogl_handle_unref (self->bg_sub_texture); self->bg_sub_texture = NULL; } self->bg_sub_texture = st_cogl_texture_new_with_size_wrapper (self->bg_width_i, self->bg_height_i, COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_RGBA_8888_PRE); cogl_pipeline_set_layer_texture (self->pipeline0, 0, self->bg_texture); if (self->pixel_step_uniform1 > -1) { gfloat pixel_step[3]; pixel_step[0] = 1.0f / (self->bg_width_i); pixel_step[1] = 1.0f / (self->bg_height_i); pixel_step[2] = 1.0f; cogl_pipeline_set_uniform_float (self->pipeline1, self->pixel_step_uniform1, 3, 1, pixel_step); } if (self->pixel_step_uniform2 > -1) { gfloat pixel_step[3]; pixel_step[0] = 1.0f / (self->fg_width_i); pixel_step[1] = 1.0f / (self->fg_height_i); pixel_step[2] = 2.0f; cogl_pipeline_set_uniform_float (self->pipeline3, self->pixel_step_uniform2, 3, 1, pixel_step); } } cogl_pipeline_set_layer_texture (self->pipeline2, 0, fg_texture); cogl_pipeline_set_layer_texture (self->pipeline3, 0, fg_texture); cogl_pipeline_set_layer_texture (self->pipeline4, 0, fg_texture); } return TRUE; } else { return FALSE; } }
static gboolean on_event (ClutterActor *actor, ClutterEvent *event, ClutterClickAction *action) { ClutterClickActionPrivate *priv = action->priv; gboolean has_button = TRUE; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) return CLUTTER_EVENT_PROPAGATE; switch (clutter_event_type (event)) { case CLUTTER_TOUCH_BEGIN: has_button = FALSE; case CLUTTER_BUTTON_PRESS: if (has_button && clutter_event_get_click_count (event) != 1) return CLUTTER_EVENT_PROPAGATE; if (priv->is_held) return CLUTTER_EVENT_STOP; if (!clutter_actor_contains (actor, clutter_event_get_source (event))) return CLUTTER_EVENT_PROPAGATE; priv->press_button = has_button ? clutter_event_get_button (event) : 0; priv->press_device_id = clutter_event_get_device_id (event); priv->press_sequence = clutter_event_get_event_sequence (event); priv->modifier_state = clutter_event_get_state (event); clutter_event_get_coords (event, &priv->press_x, &priv->press_y); if (priv->long_press_threshold < 0) { ClutterSettings *settings = clutter_settings_get_default (); g_object_get (settings, "dnd-drag-threshold", &priv->drag_threshold, NULL); } else priv->drag_threshold = priv->long_press_threshold; if (priv->stage == NULL) priv->stage = clutter_actor_get_stage (actor); priv->capture_id = g_signal_connect_after (priv->stage, "captured-event", G_CALLBACK (on_captured_event), action); click_action_set_pressed (action, TRUE); click_action_set_held (action, TRUE); click_action_query_long_press (action); break; case CLUTTER_ENTER: click_action_set_pressed (action, priv->is_held); break; case CLUTTER_LEAVE: click_action_set_pressed (action, priv->is_held); click_action_cancel_long_press (action); break; default: break; } return CLUTTER_EVENT_PROPAGATE; }
/* 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); }
static gboolean clutter_colorize_effect_pre_paint (ClutterEffect *effect) { ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect); ClutterEffectClass *parent_class; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); if (self->actor == NULL) return FALSE; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShaderEffect: the graphics hardware " "or the current GL driver does not implement support " "for the GLSL shading language."); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); return FALSE; } if (self->shader == COGL_INVALID_HANDLE) { self->shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); cogl_shader_source (self->shader, colorize_glsl_shader); self->is_compiled = FALSE; self->tex_uniform = -1; self->tint_uniform = -1; } if (self->program == COGL_INVALID_HANDLE) self->program = cogl_create_program (); if (!self->is_compiled) { g_assert (self->shader != COGL_INVALID_HANDLE); g_assert (self->program != COGL_INVALID_HANDLE); cogl_shader_compile (self->shader); if (!cogl_shader_is_compiled (self->shader)) { gchar *log_buf = cogl_shader_get_info_log (self->shader); g_warning (G_STRLOC ": Unable to compile the colorize shader: %s", log_buf); g_free (log_buf); cogl_handle_unref (self->shader); cogl_handle_unref (self->program); self->shader = COGL_INVALID_HANDLE; self->program = COGL_INVALID_HANDLE; } else { cogl_program_attach_shader (self->program, self->shader); cogl_program_link (self->program); cogl_handle_unref (self->shader); self->is_compiled = TRUE; self->tex_uniform = cogl_program_get_uniform_location (self->program, "tex"); self->tint_uniform = cogl_program_get_uniform_location (self->program, "tint"); } } parent_class = CLUTTER_EFFECT_CLASS (clutter_colorize_effect_parent_class); return parent_class->pre_paint (effect); }
static gboolean cd_icc_effect_pre_paint (ClutterEffect *effect) { CdIccEffect *self = CD_ICC_EFFECT (effect); ClutterEffectClass *parent_class; ClutterActorBox allocation; gfloat width, height; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); if (self->actor == NULL) return FALSE; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShaderEffect: the graphics hardware " "or the current GL driver does not implement support " "for the GLSL shading language."); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); return FALSE; } clutter_actor_get_allocation_box (self->actor, &allocation); clutter_actor_box_get_size (&allocation, &width, &height); if (self->shader == COGL_INVALID_HANDLE) { self->shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); cogl_shader_source (self->shader, glsl_shader); self->is_compiled = FALSE; self->main_texture_uniform = -1; self->indirect_texture_uniform = -1; self->color_data1_uniform = -1; self->color_data2_uniform = -1; } if (self->program == COGL_INVALID_HANDLE) self->program = cogl_create_program (); if (!self->is_compiled) { g_assert (self->shader != COGL_INVALID_HANDLE); g_assert (self->program != COGL_INVALID_HANDLE); cogl_shader_compile (self->shader); if (!cogl_shader_is_compiled (self->shader)) { gchar *log_buf = cogl_shader_get_info_log (self->shader); g_warning (G_STRLOC ": Unable to compile the icc shader: %s", log_buf); g_free (log_buf); cogl_handle_unref (self->shader); cogl_handle_unref (self->program); self->shader = COGL_INVALID_HANDLE; self->program = COGL_INVALID_HANDLE; } else { cogl_program_attach_shader (self->program, self->shader); cogl_program_link (self->program); cogl_handle_unref (self->shader); self->is_compiled = TRUE; self->main_texture_uniform = cogl_program_get_uniform_location (self->program, "main_texture"); self->indirect_texture_uniform = cogl_program_get_uniform_location (self->program, "indirect_texture"); self->color_data1_uniform = cogl_program_get_uniform_location (self->program, "color_data1"); self->color_data2_uniform = cogl_program_get_uniform_location (self->program, "color_data2"); } } parent_class = CLUTTER_EFFECT_CLASS (cd_icc_effect_parent_class); return parent_class->pre_paint (effect); }
/* Dragged actor moved */ static void _xfdashboard_drag_action_drag_motion(ClutterDragAction *inAction, ClutterActor *inActor, gfloat inDeltaX, gfloat inDeltaY) { XfdashboardDragAction *self; XfdashboardDragActionPrivate *priv; ClutterDragActionClass *dragActionClass; gfloat stageX, stageY; XfdashboardDropAction *dropTarget; gfloat dropX, dropY; const ClutterEvent *event; g_return_if_fail(XFDASHBOARD_IS_DRAG_ACTION(inAction)); self=XFDASHBOARD_DRAG_ACTION(inAction); priv=self->priv; dragActionClass=CLUTTER_DRAG_ACTION_CLASS(xfdashboard_drag_action_parent_class); /* Call parent's class method */ if(dragActionClass->drag_motion) dragActionClass->drag_motion(inAction, inActor, inDeltaX, inDeltaY); /* Remember motion delta coordinates */ priv->lastDeltaX=inDeltaX; priv->lastDeltaY=inDeltaY; /* Get event coordinates relative to stage */ clutter_drag_action_get_motion_coords(inAction, &stageX, &stageY); /* Find drop target at stage coordinate */ dropTarget=_xfdashboard_drag_action_find_drop_traget_at_coord(self, stageX, stageY); /* If found drop target is not the same as the last one emit "drag-leave" * signal at last drop target and "drag-enter" in new drop target */ if(priv->lastDropTarget!=dropTarget) { /* Emit "drag-leave" signal on last drop target */ if(priv->lastDropTarget) { g_signal_emit_by_name(priv->lastDropTarget, "drag-leave", self, NULL); priv->lastDropTarget=NULL; } /* Check if new drop target is active and emit "drag-enter" signal */ if(dropTarget) { ClutterActorMeta *actorMeta=CLUTTER_ACTOR_META(dropTarget); ClutterActor *dropActor=clutter_actor_meta_get_actor(actorMeta); if(clutter_actor_meta_get_enabled(actorMeta) && clutter_actor_is_visible(dropActor) && clutter_actor_get_reactive(dropActor)) { g_signal_emit_by_name(dropTarget, "drag-enter", self, NULL); priv->lastDropTarget=dropTarget; } } } /* Transform event coordinates relative to last drop target which * should be the drop target under pointer device if it is active * and emit "drag-motion" signal */ if(priv->lastDropTarget) { dropX=dropY=0.0f; _xfdashboard_drag_action_transform_stage_point(priv->lastDropTarget, stageX, stageY, &dropX, &dropY); g_signal_emit_by_name(priv->lastDropTarget, "drag-motion", self, dropX, dropY, NULL); } /* We are derived from ClutterDragAction and this one disables stage motion * so no "enter-event", "motion-event" and "leave-event" will be emitted while * dragging. We need to do it on our own. */ event=clutter_get_current_event(); if(event && clutter_event_type(event)==CLUTTER_MOTION) { GSList *list, *next; ClutterStage *stage; ClutterActor *motionActor; gboolean newMotionActor; ClutterActor *actor; gfloat x, y, w, h; gboolean result; ClutterEvent *actorEvent; /* Get stage where event happened */ stage=clutter_event_get_stage(event); if(stage) { /* Get actor under pointer */ newMotionActor=TRUE; motionActor=clutter_stage_get_actor_at_pos(stage, CLUTTER_PICK_REACTIVE, stageX, stageY); /* Iterate through list of crossed actors so far and check if pointer * is still inside. If pointer is outside of an actor emit "leave-event". * For each actor the pointer is still inside emit this "motion-event". * Also check if actor under pointer is already is list to prevent * "enter-event" to be emitted more than once. */ list=priv->lastMotionActors; while(list) { /* Get next entry now as this entry might get deleted */ next=g_slist_next(list); /* Get actor from entry */ actor=CLUTTER_ACTOR(list->data); /* Actor must be one same stage where event happened */ if(clutter_actor_get_stage(actor)!=CLUTTER_ACTOR(stage)) continue; /* Get position and size of actor in stage coordinates */ clutter_actor_get_transformed_position(actor, &x, &y); clutter_actor_get_transformed_size(actor, &w, &h); /* Check if pointer is still inside actor */ if(stageX>=x && stageX<(x+w) && stageY>=y && stageY<(y+h)) { /* Check if actor is the "new" motion actor. If so set flag. */ if(actor==motionActor) newMotionActor=FALSE; /* Emit "motion-event" */ actorEvent=clutter_event_copy(event); actorEvent->motion.source=actor; g_signal_emit_by_name(actor, "motion-event", actorEvent, &result); clutter_event_free(actorEvent); } /* Pointer is not inside actor anymore so remove actor from list * of last known "motion actors" and send "leave-event" */ else { /* Disconnect signal */ g_signal_handlers_disconnect_by_func(actor, G_CALLBACK(_xfdashboard_drag_action_on_motion_actor_destroyed), self); /* Remove from list */ priv->lastMotionActors=g_slist_remove_link(priv->lastMotionActors, list); g_slist_free_1(list); /* Create and emit "leave-event" */ actorEvent=clutter_event_new(CLUTTER_LEAVE); actorEvent->crossing.time=event->motion.time; actorEvent->crossing.flags=event->motion.flags; actorEvent->crossing.stage=event->motion.stage; actorEvent->crossing.source=actor; actorEvent->crossing.x=event->motion.x; actorEvent->crossing.y=event->motion.y; actorEvent->crossing.device=event->motion.device; actorEvent->crossing.related=event->motion.source; g_signal_emit_by_name(actor, "leave-event", actorEvent, &result); clutter_event_free(actorEvent); } /* Proceed with next actor */ list=next; } /* We have an actor under pointer and was not seen while iterating * through list of all last known "motion actors" then add this actor * to list and emit "enter-event" and also all parent actors because * if pointer is inside their child then it is also inside them. */ if(motionActor && newMotionActor) { while(motionActor) { /* Avoid duplicates */ if(!g_slist_find(priv->lastMotionActors, motionActor)) { /* Add to list */ priv->lastMotionActors=g_slist_append(priv->lastMotionActors, motionActor); /* Create and emit "enter-event" */ actorEvent=clutter_event_new(CLUTTER_ENTER); actorEvent->crossing.time=event->motion.time; actorEvent->crossing.flags=event->motion.flags; actorEvent->crossing.stage=event->motion.stage; actorEvent->crossing.source=event->motion.source; actorEvent->crossing.x=event->motion.x; actorEvent->crossing.y=event->motion.y; actorEvent->crossing.device=event->motion.device; actorEvent->crossing.related=motionActor; g_signal_emit_by_name(motionActor, "enter-event", actorEvent, &result); clutter_event_free(actorEvent); /* To prevent emiting these motion events on actors being * destroyed while drag is in progress we connect to 'destroy' * signal of each "motion actor" added to list. The signal * handler will be removed either on actor's destruction by * signal handler's callback, when pointer leaves actor or on * end of drag. */ g_signal_connect(motionActor, "destroy", G_CALLBACK(_xfdashboard_drag_action_on_motion_actor_destroyed), self); } /* Get parent */ motionActor=clutter_actor_get_parent(motionActor); } } } } }