/* 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); }
/* Class functions */ gboolean scim_bridge_client_imcontext_filter_key_event (ClutterIMContext *context, ClutterKeyEvent *event) { scim_bridge_pdebugln (8, "scim_bridge_client_imcontext_filter_key_event ()"); ScimBridgeClientIMContext *imcontext = SCIM_BRIDGE_CLIENT_IMCONTEXT (context); if (scim_bridge_client_is_messenger_opened () && imcontext != NULL ) { if (context->actor != NULL) { ClutterActor *stage = clutter_actor_get_stage (context->actor); Window current_window, root, parent, *childs; unsigned int nchild; XWindowAttributes winattr; Display *xdpy; int new_window_x; int new_window_y; clutter_actor_get_transformed_position (context->actor, &new_window_x, &new_window_y); xdpy = clutter_x11_get_default_display (); current_window = clutter_x11_get_stage_window(CLUTTER_STAGE(stage)); while(1) { XGetWindowAttributes (xdpy, current_window, &winattr); new_window_x += winattr.x; new_window_y += winattr.y; XQueryTree(xdpy, current_window, &root, &parent, &childs, &nchild); current_window = parent; if (root == parent) break; } if (imcontext->window_x != new_window_x || imcontext->window_y != new_window_y) { imcontext->window_x = new_window_x; imcontext->window_y = new_window_y; scim_bridge_pdebugln (1, "The cursor location is changed: x = %d + %d\ty = %d + %d", imcontext->window_x, imcontext->cursor_x, imcontext->window_y, imcontext->cursor_y); if (set_cursor_location (imcontext, new_window_x, new_window_y, imcontext->cursor_x, imcontext->cursor_y)) { scim_bridge_perrorln ("An IOException occurred at scim_bridge_client_imcontext_filter_key_event ()"); return clutter_im_context_filter_keypress (fallback_imcontext, event); } } } boolean consumed = FALSE; if (filter_key_event (imcontext, event, &consumed)) { scim_bridge_perrorln ("An IOException occurred at scim_bridge_client_imcontext_filter_key_event ()"); } else if (consumed) { return TRUE; } } if (imcontext == NULL || !imcontext->enabled) { return clutter_im_context_filter_keypress (fallback_imcontext, event); } return FALSE; }
/* 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); }
/** * st_widget_show_tooltip: * @widget: A #StWidget * * Show the tooltip for @widget * */ void st_widget_show_tooltip (StWidget *widget) { gfloat x, y, width, height; ClutterGeometry area; g_return_if_fail (ST_IS_WIDGET (widget)); /* XXX not necceary, but first allocate transform is wrong */ clutter_actor_get_transformed_position ((ClutterActor*) widget, &x, &y); clutter_actor_get_size ((ClutterActor*) widget, &width, &height); area.x = x; area.y = y; area.width = width; area.height = height; if (widget->priv->tooltip) { st_tooltip_set_tip_area (widget->priv->tooltip, &area); st_tooltip_show (widget->priv->tooltip); } }
static void mnp_clock_tile_drag_begin (MxDraggable *draggable, gfloat event_x, gfloat event_y, gint event_button, ClutterModifierType modifiers) { ClutterActor *self = CLUTTER_ACTOR (draggable); ClutterActor *stage = clutter_actor_get_stage (self); gfloat orig_x, orig_y; MnpClockTile *tile = (MnpClockTile *)draggable; gfloat width, height; MnpClockTilePriv *priv = tile->priv; clutter_actor_get_size (self, &width, &height); g_object_ref (self); if (priv->clone) clutter_actor_destroy (priv->clone); priv->clone = clutter_clone_new (self); tile->priv->depth = clutter_actor_get_depth (self); clutter_actor_get_transformed_position (self, &orig_x, &orig_y); //clutter_actor_reparent (self, stage); //clutter_actor_set_size (self, width, -1); //clutter_actor_raise_top (self); //clutter_actor_set_position (self, orig_x, orig_y); clutter_container_add_actor (CLUTTER_CONTAINER (stage), priv->clone); clutter_actor_set_position (priv->clone, orig_x, orig_y); clutter_actor_set_size (priv->clone, width, height); g_object_unref (self); clutter_actor_animate (self, CLUTTER_EASE_OUT_CUBIC, 250, "opacity", 0, NULL); }
static void _set_cursor_location_internal(FcitxIMContext *fcitxcontext) { ClutterIMContext* context = CLUTTER_IM_CONTEXT(fcitxcontext); ClutterActor *stage = clutter_actor_get_stage (context->actor); Window current_window, root, parent, *childs; unsigned int nchild; XWindowAttributes winattr; Display *xdpy; float fx, fy; gint x, y; if (!stage) return; clutter_actor_get_transformed_position (context->actor, &fx, &fy); x = fx; y = fy; xdpy = clutter_x11_get_default_display (); current_window = clutter_x11_get_stage_window(CLUTTER_STAGE(stage)); if (!xdpy || !current_window) return; while(1) { XGetWindowAttributes (xdpy, current_window, &winattr); x += winattr.x; y += winattr.y; XQueryTree(xdpy, current_window, &root, &parent, &childs, &nchild); current_window = parent; if (root == parent) break; } if (fcitxcontext->area.x != x || fcitxcontext->area.y != y) { fcitxcontext->area.x = x; fcitxcontext->area.y = y; } if (context->actor == NULL || !IsFcitxIMClientValid(fcitxcontext->client)) { return; } ClutterIMRectangle area = fcitxcontext->area; if (area.x == -1 && area.y == -1 && area.width == 0 && area.height == 0) { area.y = 0; area.x = 0; } FcitxIMClientSetCursorLocation(fcitxcontext->client, area.x, area.y + area.height); return; }
static void position_menu (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data) { ShellStatusMenu *status = SHELL_STATUS_MENU (user_data); int src_x, src_y; clutter_actor_get_transformed_position (CLUTTER_ACTOR (status), &src_x, &src_y); *x = src_x; *y = src_y; }
static void on_drag_end (ClutterDragAction *action, ClutterActor *actor, gfloat event_x, gfloat event_y, ClutterModifierType modifiers) { ClutterActor *handle = clutter_drag_action_get_drag_handle (action); g_print ("Drag ended at: %.0f, %.0f\n", event_x, event_y); clutter_actor_save_easing_state (actor); clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR); clutter_actor_set_opacity (actor, 255); clutter_actor_restore_easing_state (actor); clutter_actor_save_easing_state (handle); if (!drop_successful) { ClutterActor *parent = clutter_actor_get_parent (actor); gfloat x_pos, y_pos; clutter_actor_save_easing_state (parent); clutter_actor_set_easing_mode (parent, CLUTTER_LINEAR); clutter_actor_set_opacity (parent, 255); clutter_actor_restore_easing_state (parent); clutter_actor_get_transformed_position (actor, &x_pos, &y_pos); clutter_actor_set_easing_mode (handle, CLUTTER_EASE_OUT_BOUNCE); clutter_actor_set_position (handle, x_pos, y_pos); clutter_actor_set_opacity (handle, 0); clutter_actor_restore_easing_state (handle); } else { clutter_actor_set_easing_mode (handle, CLUTTER_LINEAR); clutter_actor_set_opacity (handle, 0); } clutter_actor_restore_easing_state (handle); g_signal_connect (handle, "transitions-completed", G_CALLBACK (clutter_actor_destroy), 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); }
static void mnp_clock_tile_drag_motion (MxDraggable *draggable, gfloat delta_x, gfloat delta_y) { gfloat orig_x, orig_y; MnpClockTile *tile = (MnpClockTile *)draggable; MnpClockTilePriv *priv = tile->priv; clutter_actor_get_transformed_position (CLUTTER_ACTOR (draggable), &orig_x, &orig_y); clutter_actor_set_position (CLUTTER_ACTOR (priv->clone), orig_x + delta_x, orig_y + delta_y); g_signal_emit (G_OBJECT (draggable), signals[DRAG_Y_POS], 0, (int)orig_y+(int)delta_y); //clutter_actor_move_by (CLUTTER_ACTOR (draggable), delta_x, delta_y); }
static void mnp_clock_tile_drag_end (MxDraggable *draggable, gfloat event_x, gfloat event_y) { ClutterActor *self = CLUTTER_ACTOR (draggable); MnpClockTile *tile = (MnpClockTile *)draggable; MnpClockTilePriv *priv = tile->priv; gfloat x, y, width, height; clutter_actor_destroy (priv->clone); priv->clone = NULL; clutter_actor_get_size (CLUTTER_ACTOR (draggable), &width, &height); clutter_actor_get_transformed_position (CLUTTER_ACTOR (draggable), &x, &y); clutter_actor_set_opacity (CLUTTER_ACTOR (draggable), 0xff); clutter_actor_animate (self, CLUTTER_EASE_OUT_CUBIC, 250, "opacity", 255, NULL); tile->priv->depth = 0.0; }
static void update_im_cursor_location (StIMText *self) { StIMTextPrivate *priv = self->priv; ClutterText *clutter_text = CLUTTER_TEXT (self); gint position; gfloat cursor_x, cursor_y, cursor_height; gfloat actor_x, actor_y; GdkRectangle area; position = clutter_text_get_cursor_position (clutter_text); clutter_text_position_to_coords (clutter_text, position, &cursor_x, &cursor_y, &cursor_height); clutter_actor_get_transformed_position (CLUTTER_ACTOR (self), &actor_x, &actor_y); area.x = (int)(0.5 + cursor_x + actor_x); area.y = (int)(0.5 + cursor_y + actor_y); area.width = 0; area.height = (int)(0.5 + cursor_height); gtk_im_context_set_cursor_location (priv->im_context, &area); }
static void draggable_rectangle_drag_begin (MxDraggable *draggable, gfloat event_x, gfloat event_y, gint event_button, ClutterModifierType modifiers) { ClutterActor *self = CLUTTER_ACTOR (draggable); ClutterActor *stage = clutter_actor_get_stage (self); gfloat orig_x, orig_y; g_object_ref (self); clutter_actor_get_transformed_position (self, &orig_x, &orig_y); clutter_actor_reparent (self, stage); clutter_actor_set_position (self, orig_x, orig_y); g_object_unref (self); clutter_actor_animate (self, CLUTTER_EASE_OUT_CUBIC, 250, "opacity", 224, NULL); }
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 event_cb (ClutterStage * stage, ClutterEvent * event, UserInterface * ui) { gboolean handled = FALSE; switch (event->type) { case CLUTTER_KEY_PRESS: { /* Clutter key codes based on */ /* http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h */ ClutterVertex center = { 0, }; ClutterAnimation *animation = NULL; center.x - clutter_actor_get_width (ui->texture) / 2; guint keyval = clutter_event_get_key_symbol (event); switch (keyval) { case CLUTTER_q: case CLUTTER_Escape: { clutter_main_quit (); handled = TRUE; break; } case CLUTTER_f: { // Fullscreen button toggle_fullscreen (ui); handled = TRUE; break; } case CLUTTER_space: { // Spacebar toggle_playing (ui); handled = TRUE; break; } case CLUTTER_l: { ui->engine->loop = !ui->engine->loop; handled = TRUE; break; } case CLUTTER_8: { // Mute button gdouble volume; gboolean muteval; g_object_get (G_OBJECT (ui->engine->player), "mute", &muteval, NULL); g_object_set (G_OBJECT (ui->engine->player), "mute", !muteval, NULL); update_volume (ui, volume); handled = TRUE; break; } case CLUTTER_9: case CLUTTER_0: { gdouble volume; g_object_get (G_OBJECT (ui->engine->player), "volume", &volume, NULL); // Volume Down if (keyval == CLUTTER_9 && volume > 0.0) { volume -= 0.05; if (volume < 0.01) volume = 0; g_object_set (G_OBJECT (ui->engine->player), "volume", volume, NULL); // Volume Up } else if (keyval == CLUTTER_0 && volume < 1.0) { volume += 0.05; if (volume > 1) volume = 1; g_object_set (G_OBJECT (ui->engine->player), "volume", volume, NULL); } update_volume (ui, volume); handled = TRUE; break; } case CLUTTER_Up: case CLUTTER_Down: case CLUTTER_Left: case CLUTTER_Right: case CLUTTER_Page_Up: case CLUTTER_Page_Down: { gint64 pos, second; gfloat progress; pos = query_position (ui->engine); second = ui->engine->second; if (keyval == CLUTTER_Up) { // Seek 1 minute foward pos += 60 * second; } else if (keyval == CLUTTER_Down) { // Seek 1 minute back pos -= 60 * second; } else if (keyval == CLUTTER_Right) { // Seek 10 seconds foward pos += 10 * second; } else if (keyval == CLUTTER_Left) { // Seek 10 seconds back pos -= 10 * second; } else if (keyval == CLUTTER_Page_Up) { // Seek 10 minutes foward pos += 600 * second; } else if (keyval == CLUTTER_Page_Down) { // Seek 10 minutes back pos -= 600 * second; } /* clamp the timestamp to be within the media */ pos = CLAMP (pos, 0, ui->engine->media_duration); engine_seek (ui->engine, pos, TRUE); progress = (float) pos / ui->engine->media_duration; clutter_actor_set_size (ui->control_seekbar, progress * ui->seek_width, ui->seek_height); progress_update_text (ui); handled = TRUE; break; } case CLUTTER_i: { // set in point for segment gint64 in_point; in_point = query_position (ui->engine); ui->engine->in_point = in_point; engine_seek (ui->engine, in_point, TRUE); handled = TRUE; break; } case CLUTTER_o: { // set out point for segment gint64 out_point; out_point = query_position (ui->engine); ui->engine->out_point = out_point; engine_seek (ui->engine, out_point, FALSE); handled = TRUE; break; } case CLUTTER_r: { // rotate texture 90 degrees. rotate_video (ui); handled = TRUE; break; } case CLUTTER_c: { // show or hide controls penalty_box (ui); ui->keep_showing_controls = !ui->controls_showing; show_controls (ui, !ui->controls_showing); handled = TRUE; break; } case CLUTTER_period: { frame_stepping (ui->engine, TRUE); handled = TRUE; break; } case CLUTTER_comma: { frame_stepping (ui->engine, FALSE); handled = TRUE; break; } default: { handled = FALSE; break; } } break; } case CLUTTER_BUTTON_PRESS: { if (ui->controls_showing) { ClutterActor *actor; ClutterButtonEvent *bev = (ClutterButtonEvent *) event; actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, bev->x, bev->y); if (actor == ui->control_play_toggle) { toggle_playing (ui); } else if (actor == ui->control_seek1 || actor == ui->control_seek2 || actor == ui->control_seekbar) { gfloat x, y, dist; gint64 progress; clutter_actor_get_transformed_position (ui->control_seekbar, &x, &y); dist = bev->x - x; dist = CLAMP (dist, 0, ui->seek_width); if (ui->engine->media_duration == -1) { update_media_duration (ui->engine); } progress = ui->engine->media_duration * (dist / ui->seek_width); engine_seek (ui->engine, progress, TRUE); clutter_actor_set_size (ui->control_seekbar, dist, ui->seek_height); progress_update_text (ui); } else if (actor == ui->vol_int || actor == ui->vol_int_bg) { gfloat x, y, dist; gdouble volume; clutter_actor_get_transformed_position (ui->vol_int_bg, &x, &y); dist = bev->x - x; dist = CLAMP (dist, 0, ui->volume_width); volume = dist / ui->volume_width; g_object_set (G_OBJECT (ui->engine->player), "volume", volume, NULL); clutter_actor_set_size (ui->vol_int, dist, ui->volume_height); } else if (actor == ui->control_bg || actor == ui->control_title || actor == ui->control_pos) { ui->keep_showing_controls = !ui->keep_showing_controls; if (ui->keep_showing_controls) { clutter_stage_hide_cursor (CLUTTER_STAGE (ui->stage)); } else { penalty_box (ui); show_controls (ui, FALSE); } } else if (actor == ui->texture || actor == ui->stage) { if (!ui->penalty_box_active) { penalty_box (ui); show_controls (ui, FALSE); } } } handled = TRUE; break; } case CLUTTER_MOTION: { if (!ui->penalty_box_active) show_controls (ui, TRUE); handled = TRUE; break; } } return handled; }
/* 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); } } } } }
static void mx_combo_box_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { MxComboBoxPrivate *priv = MX_COMBO_BOX (actor)->priv; MxPadding padding; gfloat x, y, width, height; gfloat min_menu_h, nat_menu_h; gfloat label_h; gfloat nat_icon_h, icon_h, icon_w; gfloat nat_marker_h, marker_h, marker_w; ClutterActorBox childbox; ClutterActor *menu, *stage; CLUTTER_ACTOR_CLASS (mx_combo_box_parent_class)->allocate (actor, box, flags); mx_widget_get_padding (MX_WIDGET (actor), &padding); x = padding.left; y = padding.top; width = box->x2 - box->x1 - padding.left - padding.right; height = box->y2 - box->y1 - padding.top - padding.bottom; icon_w = marker_w = 0; if (priv->icon) { /* Allocate the icon, if there is one, the space not used by the text */ clutter_actor_get_preferred_height (priv->icon, -1, NULL, &nat_icon_h); if (height >= nat_icon_h) { icon_h = nat_icon_h; clutter_actor_get_preferred_width (priv->icon, -1, NULL, &icon_w); } else { icon_h = height; clutter_actor_get_preferred_width (priv->icon, icon_h, NULL, &icon_w); } childbox.x1 = (int)(x); childbox.y1 = (int)(y + (height - icon_h) / 2); childbox.x2 = (int)(x + icon_w); childbox.y2 = (int)(childbox.y1 + icon_h); clutter_actor_allocate (priv->icon, &childbox, flags); icon_w += priv->spacing; } if (priv->marker) { clutter_actor_get_preferred_height (priv->marker, -1, NULL, &nat_marker_h); if (height >= nat_marker_h) { marker_h = nat_marker_h; clutter_actor_get_preferred_width (priv->marker, -1, NULL, &marker_w); } else { marker_h = height; clutter_actor_get_preferred_width (priv->marker, marker_h, NULL, &marker_w); } childbox.x2 = (int)(x + width); childbox.x1 = (int)(childbox.x2 - marker_w); childbox.y1 = (int)(y + (height - marker_h) / 2); childbox.y2 = (int)(childbox.y1 + marker_h); clutter_actor_allocate (priv->marker, &childbox, flags); marker_w += priv->spacing; } clutter_actor_get_preferred_height (priv->label, -1, NULL, &label_h); childbox.x1 = (int)(x + icon_w); childbox.y1 = (int)(y + (height / 2 - label_h / 2)); childbox.x2 = (int)(x + width - marker_w); childbox.y2 = (int)(childbox.y1 + label_h); clutter_actor_allocate (priv->label, &childbox, flags); menu = (ClutterActor*) mx_widget_get_menu (MX_WIDGET (actor)); clutter_actor_get_preferred_height (menu, (box->x2 - box->x1), &min_menu_h, &nat_menu_h); childbox.x1 = 0; childbox.x2 = (box->x2 - box->x1); childbox.y1 = (box->y2 - box->y1); childbox.y2 = childbox.y1 + nat_menu_h; stage = clutter_actor_get_stage (actor); if (stage != NULL) { ClutterVertex point = { 0, }; gfloat stage_w, stage_h, combo_h = box->y2 - box->y1; clutter_actor_get_size (stage, &stage_w, &stage_h); point.y = combo_h + nat_menu_h; clutter_actor_apply_transform_to_point (actor, &point, &point); /* If the menu would appear off the stage, flip it around. */ if ((point.y < 0) || (point.y >= stage_h)) { childbox.y1 = -nat_menu_h; point.y = -nat_menu_h; clutter_actor_apply_transform_to_point (actor, &point, &point); /* if the menu would still appear out of the stage, force * it to appear on the top of the stage. */ if (point.y < 0) { gfloat xactor, yactor; clutter_actor_get_transformed_position (actor, &xactor, &yactor); childbox.y1 = -yactor; } } point.y = childbox.y1 + nat_menu_h; clutter_actor_apply_transform_to_point (actor, &point, &point); if (point.y >= stage_h) { gfloat xactor, yactor; clutter_actor_get_transformed_position (actor, &xactor, &yactor); /* * clamp so that the menu doesn't appear out of the screen */ clutter_actor_transform_stage_point (actor, xactor, stage_h, NULL, &childbox.y2); /* * The previous transformation can lead to negative height * allocation if the top-left corner of the menu is already * flipped around. This happens when you put a combobox deep * enough in a scrollview taller that the stage. */ childbox.y2 = MAX (childbox.y1, childbox.y2); } else { childbox.y2 = childbox.y1 + nat_menu_h; } } clutter_actor_allocate (menu, &childbox, flags); }
static void mx_tooltip_update_position (MxTooltip *tooltip) { MxTooltipPrivate *priv = tooltip->priv; ClutterGeometry tip_area = *tooltip->priv->tip_area; gfloat tooltip_w, tooltip_h, tooltip_x, tooltip_y, abs_x, abs_y; ClutterActor *stage, *parent; gfloat stage_w, stage_h, parent_w, parent_h; MxWindow *window; /* If there's no stage, bail out - there's nothing we can do */ stage = clutter_actor_get_stage ((ClutterActor *) tooltip); if (!stage) return; /* find out the stage's size to keep the tooltip on-screen */ clutter_actor_get_size (stage, &stage_w, &stage_h); parent = clutter_actor_get_parent ((ClutterActor *) tooltip); clutter_actor_get_transformed_position (parent, &abs_x, &abs_y); clutter_actor_get_size (parent, &parent_w, &parent_h); /* ensure the tooltip with is not fixed size */ clutter_actor_set_size ((ClutterActor*) tooltip, -1, -1); /* if no area set, just position ourselves top left */ if (!priv->tip_area) { clutter_actor_set_position ((ClutterActor*) tooltip, abs_x, abs_y); return; } /* check if we're in a window and if there's rotation */ window = mx_window_get_for_stage (CLUTTER_STAGE (stage)); if (window) { MxWindowRotation rotation; gfloat old_x; g_object_get (G_OBJECT (window), "window-rotation", &rotation, NULL); if (rotation == MX_WINDOW_ROTATION_90 || rotation == MX_WINDOW_ROTATION_270) { /* swap stage width and height */ old_x = stage_w; stage_w = stage_h; stage_h = old_x; /* swap tip area width and height */ old_x = tip_area.width; tip_area.width = tip_area.height; tip_area.height = old_x; } switch (rotation) { case MX_WINDOW_ROTATION_90: /* absolute position */ old_x = abs_x; abs_x = abs_y; abs_y = stage_h - old_x; /* tip area */ old_x = tip_area.x; tip_area.x = tip_area.y; tip_area.y = stage_h - old_x - tip_area.height; break; case MX_WINDOW_ROTATION_180: tip_area.x = stage_w - tip_area.x - tip_area.width; tip_area.y = stage_h - tip_area.y - tip_area.height; abs_x = stage_w - abs_x; abs_y = stage_h - abs_y; break; case MX_WINDOW_ROTATION_270: /* absolute position */ old_x = abs_x; abs_x = stage_w - abs_y; abs_y = old_x; /* tip area */ old_x = tip_area.x; tip_area.x = stage_w - tip_area.y - tip_area.width; tip_area.y = old_x; break; default: break; } } /* we need to have a style in case there are padding values to take into * account when calculating width/height */ mx_stylable_style_changed (MX_STYLABLE (tooltip), MX_STYLE_CHANGED_FORCE); /* find out the tooltip's size */ clutter_actor_get_size ((ClutterActor*) tooltip, &tooltip_w, &tooltip_h); /* attempt to place the tooltip */ /* This special-cases the 4 window rotations, as doing this with * arbitrary rotations would massively complicate the code for * little benefit. */ priv->actor_below = FALSE; tooltip_x = (int)(tip_area.x + (tip_area.width / 2) - (tooltip_w / 2)); tooltip_y = (int)(tip_area.y + tip_area.height); /* Keep on the screen vertically */ if (tooltip_y + tooltip_h > stage_h) { priv->actor_below = TRUE; /* re-query size as may have changed */ clutter_actor_get_preferred_height ((ClutterActor*) tooltip, -1, NULL, &tooltip_h); tooltip_y = MAX (0, tip_area.y - tooltip_h); } /* Keep on the screen horizontally */ if (tooltip_w > stage_w) { tooltip_x = 0; clutter_actor_set_width ((ClutterActor*) tooltip, stage_w); } else if (tooltip_x < 0) tooltip_x = 0; else if (tooltip_x + tooltip_w > stage_w) tooltip_x = (int)(stage_w) - tooltip_w; gfloat pos_x, pos_y; pos_x = tooltip_x - abs_x; pos_y = tooltip_y - abs_y; /* calculate the arrow offset */ priv->arrow_offset = tip_area.x + tip_area.width / 2 - tooltip_x; clutter_actor_set_position ((ClutterActor*) tooltip, pos_x, pos_y); }
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; }