/* Sort drop action targets */ static gint _xfdashboard_drag_action_sort_targets_callback(gconstpointer inLeft, gconstpointer inRight) { ClutterActor *actor1, *actor2; gfloat depth1, depth2; gfloat x1, y1, w1, h1; gfloat x2, y2, w2, h2; ClutterActorBox *box1, *box2; gint numberPoint1, numberPoint2; g_return_val_if_fail(XFDASHBOARD_IS_DROP_ACTION(inLeft) && XFDASHBOARD_IS_DROP_ACTION(inRight), 0); actor1=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(inLeft)); actor2=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(inRight)); /* Return -1 if actor in inLeft should be inserted before actor in inRight * and return 1 if otherwise. If both actors can be handled equal then * return 0. But how to decide? * The actor with higher z-depth should be inserted before. If both actors * have equal z-depth then the actor with the most edge points within the * other actor (overlap) should be inserted before. Edge points are: * [left,top], [right,top], [left,bottom] and [right, bottom]. */ depth1=clutter_actor_get_z_position(actor1); depth2=clutter_actor_get_z_position(actor2); if(depth1>depth2) return(-1); else if(depth1<depth2) return(1); clutter_actor_get_transformed_position(actor1, &x1, &y1); clutter_actor_get_transformed_size(actor1, &w1, &h1); box1=clutter_actor_box_new(x1, y1, x1+w1, y1+h1); clutter_actor_get_transformed_position(actor2, &x2, &y2); clutter_actor_get_transformed_size(actor2, &w2, &h2); box2=clutter_actor_box_new(x2, y2, x2+w2, y2+h2); numberPoint1 =(clutter_actor_box_contains(box1, x2, y2) ? 1 : 0); numberPoint1+=(clutter_actor_box_contains(box1, x2+w2, y2) ? 1 : 0); numberPoint1+=(clutter_actor_box_contains(box1, x2, y2+h2) ? 1 : 0); numberPoint1+=(clutter_actor_box_contains(box1, x2+w2, y2+h2) ? 1 : 0); numberPoint2 =(clutter_actor_box_contains(box2, x1, y1) ? 1 : 0); numberPoint2+=(clutter_actor_box_contains(box2, x1+w1, y1) ? 1 : 0); numberPoint2+=(clutter_actor_box_contains(box2, x1, y1+h1) ? 1 : 0); numberPoint2+=(clutter_actor_box_contains(box2, x1+w1, y1+h1) ? 1 : 0); clutter_actor_box_free(box1); clutter_actor_box_free(box2); /* Return result */ if(numberPoint1>numberPoint2) return(1); else if(numberPoint2>numberPoint1) return(-1); return(0); }
/* Find drop target at position */ static XfdashboardDropAction* _xfdashboard_drag_action_find_drop_traget_at_coord(XfdashboardDragAction *self, gfloat inStageX, gfloat inStageY) { XfdashboardDragActionPrivate *priv; GSList *list; g_return_val_if_fail(XFDASHBOARD_IS_DRAG_ACTION(self), NULL); priv=self->priv; /* Iterate through list and return first drop target in list * where coordinates fit in */ for(list=priv->targets; list; list=g_slist_next(list)) { ClutterActorMeta *actorMeta=CLUTTER_ACTOR_META(list->data); ClutterActor *actor=clutter_actor_meta_get_actor(actorMeta); gfloat x, y, w, h; /* 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); /* If given stage coordinates fit in actor we found it */ if(inStageX>=x && inStageX<(x+w) && inStageY>=y && inStageY<(y+h)) { return(XFDASHBOARD_DROP_ACTION(actorMeta)); } } /* If we get here no drop target was found */ return(NULL); }
static void get_pointer_and_view_coords (ClutterActor *self, gint *mouse_x, gint *mouse_y, gfloat *box_x, gfloat *box_y, gfloat *width, gfloat *height) { StScrollViewPrivate *priv = ST_SCROLL_VIEW (self)->priv; clutter_input_device_get_device_coords (priv->mouse_pointer, mouse_x, mouse_y); clutter_actor_get_transformed_position (self, box_x, box_y); clutter_actor_get_transformed_size (self, width, height); }
//FIXME: ClutterClone seems to have problem rendering children, so badges are stay in grandpar static void create_window_badge(MosesOverview* self, ClutterActor* parent, int order) { ClutterActor* badge = clutter_actor_new(); clutter_actor_insert_child_above(clutter_actor_get_parent(parent), badge, NULL); gfloat tw, th; clutter_actor_get_transformed_size(parent, &tw, &th); gfloat w = 60.0, h = 60.0, x = (tw - w) / 2.0 + clutter_actor_get_x(parent), y = (th - h) / 2.0 + clutter_actor_get_y(parent); clutter_actor_set_position(badge, x, y); clutter_actor_set_size(badge, w, h); g_object_set_qdata(G_OBJECT(badge), moses_overview_window_clone_order(), GINT_TO_POINTER(order)); g_object_set_qdata(G_OBJECT(parent), moses_overview_window_clone_order(), GINT_TO_POINTER(order)); ClutterContent* canvas = clutter_canvas_new(); clutter_canvas_set_size(CLUTTER_CANVAS(canvas), w, h); clutter_actor_set_content(badge, canvas); g_object_unref(canvas); g_signal_connect(canvas, "draw", G_CALLBACK(on_badge_draw), badge); clutter_content_invalidate(canvas); clutter_actor_set_scale(badge, 0.0, 0.0); //do animated show clutter_actor_save_easing_state(badge); clutter_actor_set_easing_mode(badge, CLUTTER_EASE_OUT_BACK); clutter_actor_set_easing_duration(badge, 350); clutter_actor_set_pivot_point(badge, 0.5, 0.5); clutter_actor_set_scale(badge, 1.0, 1.0); clutter_actor_restore_easing_state(badge); g_ptr_array_add(self->priv->badges, badge); }
static void position_menu (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data) { ShellStatusMenu *status = SHELL_STATUS_MENU (user_data); ClutterActor *parent; float src_x, src_y; float width, height; int menu_width; gtk_widget_get_size_request (GTK_WIDGET (menu), &menu_width, NULL); /* Encapsulation breakage: it looks better if the menu is * aligned with the bottom of the actor's grandparent - the * panel, rather than with the bottom of the actor. We just * assume what the hierarchy is and where we are positioned * in the panel. */ parent = clutter_actor_get_parent (CLUTTER_ACTOR (status)); parent = clutter_actor_get_parent (parent); clutter_actor_get_transformed_position (parent, &src_x, &src_y); clutter_actor_get_transformed_size (parent, &width, &height); *x = (gint)(0.5 + src_x + width - menu_width); *y = (gint)(0.5 + src_y + height); }
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 manipulate_lasso_capture (ClutterActor *stage, ClutterEvent *event, gpointer data) { switch (event->any.type) { case CLUTTER_MOTION: { gfloat ex=event->motion.x; gfloat ey=event->motion.y; gint mx = MIN (ex, lx); gint my = MIN (ey, ly); gint mw = MAX (ex, lx) - mx; gint mh = MAX (ey, ly) - my; clutter_actor_set_position (lasso, mx - LASSO_BORDER, my - LASSO_BORDER); clutter_actor_set_size (lasso, mw + LASSO_BORDER*2, mh+LASSO_BORDER*2); manipulate_x=ex; manipulate_y=ey; { gint no; GList *j, *list; g_hash_table_remove_all (selection); list = clutter_container_get_children (CLUTTER_CONTAINER (cs_get_current_container ())); for (no = 0, j=list; j;no++,j=j->next) { gfloat cx, cy; gfloat cw, ch; clutter_actor_get_transformed_position (j->data, &cx, &cy); clutter_actor_get_transformed_size (j->data, &cw, &ch); if (contains (mx, mx + mw, cx, cx + cw) && contains (my, my + mh, cy, cy + ch)) { g_hash_table_insert (selection, j->data, j->data); } } g_list_free (list); } } break; case CLUTTER_BUTTON_RELEASE: { ClutterModifierType state = event->button.modifier_state; GHashTableIter iter; gpointer key, value; g_hash_table_iter_init (&iter, selection); while (g_hash_table_iter_next (&iter, &key, &value)) { if (state & CLUTTER_CONTROL_MASK) { if (cs_selected_has_actor (key)) cs_selected_remove (key); else cs_selected_add (key); } else { cs_selected_add (key); } } } g_hash_table_remove_all (selection); g_signal_handlers_disconnect_by_func (stage, manipulate_lasso_capture, data); clutter_actor_destroy (lasso); clutter_actor_queue_redraw (stage); lasso = NULL; SELECT_ACTION_POST("select lasso"); default: break; } return TRUE; }
/* 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); } } } } }