static void show_tile_preview (MetaPlugin *plugin, MetaWindow *window, MetaRectangle *tile_rect, int tile_monitor_number) { MetaScreen *screen = meta_plugin_get_screen (plugin); ScreenTilePreview *preview = get_screen_tile_preview (screen); ClutterActor *window_actor; if (clutter_actor_is_visible (preview->actor) && preview->tile_rect.x == tile_rect->x && preview->tile_rect.y == tile_rect->y && preview->tile_rect.width == tile_rect->width && preview->tile_rect.height == tile_rect->height) return; /* nothing to do */ clutter_actor_set_position (preview->actor, tile_rect->x, tile_rect->y); clutter_actor_set_size (preview->actor, tile_rect->width, tile_rect->height); clutter_actor_show (preview->actor); window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window)); clutter_actor_lower (preview->actor, window_actor); preview->tile_rect = *tile_rect; }
/* Dump actors */ static void _xfdashboard_dump_actor_internal(ClutterActor *inActor, gint inLevel) { ClutterActorIter iter; ClutterActor *child; gint i; g_return_if_fail(CLUTTER_IS_ACTOR(inActor)); g_return_if_fail(inLevel>=0); clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inActor)); while(clutter_actor_iter_next(&iter, &child)) { for(i=0; i<inLevel; i++) g_print(" "); g_print("+- %s@%p - name: %s - geometry: %.2f,%.2f [%.2fx%.2f], mapped: %s, visible: %s, children: %d\n", G_OBJECT_TYPE_NAME(child), child, clutter_actor_get_name(child), clutter_actor_get_x(child), clutter_actor_get_y(child), clutter_actor_get_width(child), clutter_actor_get_height(child), clutter_actor_is_mapped(child) ? "yes" : "no", clutter_actor_is_visible(child) ? "yes" : "no", clutter_actor_get_n_children(child)); if(clutter_actor_get_n_children(child)>0) _xfdashboard_dump_actor_internal(child, inLevel+1); } }
static void st_bin_get_preferred_height (ClutterActor *self, gfloat for_width, gfloat *min_height_p, gfloat *natural_height_p) { StBinPrivate *priv = ST_BIN (self)->priv; StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self)); st_theme_node_adjust_for_width (theme_node, &for_width); if (priv->child == NULL || !clutter_actor_is_visible (priv->child)) { if (min_height_p) *min_height_p = 0; if (natural_height_p) *natural_height_p = 0; } else { _st_actor_get_preferred_height (priv->child, for_width, priv->x_fill, min_height_p, natural_height_p); } st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); }
/* Dump actors */ static void _xfdashboard_dump_actor_print(ClutterActor *inActor, gint inLevel) { XfdashboardStylable *stylable; ClutterActorBox allocation; gint i; g_return_if_fail(CLUTTER_IS_ACTOR(inActor)); g_return_if_fail(inLevel>=0); /* Check if actor is stylable to retrieve style configuration */ stylable=NULL; if(XFDASHBOARD_IS_STYLABLE(inActor)) stylable=XFDASHBOARD_STYLABLE(inActor); /* Dump actor */ for(i=0; i<inLevel; i++) g_print(" "); clutter_actor_get_allocation_box(inActor, &allocation); g_print("+- %s@%p [%s%s%s%s%s%s] - geometry: %.2f,%.2f [%.2fx%.2f], mapped: %s, visible: %s, layout: %s, children: %d\n", G_OBJECT_TYPE_NAME(inActor), inActor, clutter_actor_get_name(inActor) ? " #" : "", clutter_actor_get_name(inActor) ? clutter_actor_get_name(inActor) : "", stylable && xfdashboard_stylable_get_classes(stylable) ? "." : "", stylable && xfdashboard_stylable_get_classes(stylable) ? xfdashboard_stylable_get_classes(stylable) : "", stylable && xfdashboard_stylable_get_pseudo_classes(stylable) ? ":" : "", stylable && xfdashboard_stylable_get_pseudo_classes(stylable) ? xfdashboard_stylable_get_pseudo_classes(stylable) : "", allocation.x1, allocation.y1, allocation.x2-allocation.x1, allocation.y2-allocation.y1, clutter_actor_is_mapped(inActor) ? "yes" : "no", clutter_actor_is_visible(inActor) ? "yes" : "no", clutter_actor_get_layout_manager(inActor) ? G_OBJECT_TYPE_NAME(clutter_actor_get_layout_manager(inActor)) : "none", clutter_actor_get_n_children(inActor)); }
static double get_scrollbar_width (StScrollView *scroll, gfloat for_height) { StScrollViewPrivate *priv = scroll->priv; if (clutter_actor_is_visible (priv->vscroll)) { gfloat min_size; clutter_actor_get_preferred_width (CLUTTER_ACTOR (priv->vscroll), for_height, &min_size, NULL); return min_size; } else return 0; }
static GList * cinnamon_generic_container_get_focus_chain (StWidget *widget) { CinnamonGenericContainer *self = CINNAMON_GENERIC_CONTAINER (widget); ClutterActor *child; GList *focus_chain; focus_chain = NULL; for (child = clutter_actor_get_first_child (CLUTTER_ACTOR (self)); child != NULL; child = clutter_actor_get_next_sibling (child)) { if (clutter_actor_is_visible (child) && !cinnamon_generic_container_get_skip_paint (self, child)) focus_chain = g_list_prepend (focus_chain, child); } return g_list_reverse (focus_chain); }
/* Check if actor can get focus */ static gboolean _xfdashboard_actor_focusable_can_focus(XfdashboardFocusable *inFocusable) { XfdashboardActor *self; XfdashboardActorPrivate *priv; g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE); g_return_val_if_fail(XFDASHBOARD_IS_ACTOR(inFocusable), FALSE); self=XFDASHBOARD_ACTOR(inFocusable); priv=self->priv; /* This actor can only be focused if it is mapped, visible and reactive */ if(priv->canFocus && clutter_actor_is_mapped(CLUTTER_ACTOR(self)) && clutter_actor_is_visible(CLUTTER_ACTOR(self)) && clutter_actor_get_reactive(CLUTTER_ACTOR(self))) { return(TRUE); } /* If we get here this actor does not fulfill the requirements to get focus */ return(FALSE); }
static void clutter_bin_layout_get_preferred_height (ClutterLayoutManager *manager, ClutterContainer *container, gfloat for_width, gfloat *min_height_p, gfloat *nat_height_p) { ClutterActor *actor = CLUTTER_ACTOR (container); ClutterActorIter iter; ClutterActor *child; gfloat min_height, nat_height; min_height = nat_height = 0.0; clutter_actor_iter_init (&iter, actor); while (clutter_actor_iter_next (&iter, &child)) { gfloat minimum, natural; if (!clutter_actor_is_visible (child)) continue; clutter_actor_get_preferred_height (child, for_width, &minimum, &natural); min_height = MAX (min_height, minimum); nat_height = MAX (nat_height, natural); } if (min_height_p) *min_height_p = min_height; if (nat_height_p) *nat_height_p = nat_height; }
static void st_bin_allocate (ClutterActor *self, const ClutterActorBox *box, ClutterAllocationFlags flags) { StBinPrivate *priv = ST_BIN (self)->priv; clutter_actor_set_allocation (self, box, flags); if (priv->child && clutter_actor_is_visible (priv->child)) { StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self)); ClutterActorBox childbox; gdouble x_align_f, y_align_f; st_theme_node_get_content_box (theme_node, box, &childbox); _st_get_align_factors (priv->x_align, priv->y_align, &x_align_f, &y_align_f); clutter_actor_allocate_align_fill (priv->child, &childbox, x_align_f, y_align_f, priv->x_fill, priv->y_fill, flags); } }
/* Updates the minimum number of rows and columns needed for layout */ static void _xfdashboard_scaled_table_layout_update_rows_and_columns(XfdashboardScaledTableLayout *self, ClutterContainer *inContainer) { XfdashboardScaledTableLayoutPrivate *priv; ClutterRequestMode requestMode; ClutterActorIter iter; ClutterActor *child; gint numberChildren; gint rows; gint columns; g_return_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self)); g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer)); g_return_if_fail(CLUTTER_IS_ACTOR(inContainer)); priv=self->priv; /* Freeze notification */ g_object_freeze_notify(G_OBJECT(self)); /* Get number of visible child actors */ numberChildren=0; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { if(clutter_actor_is_visible(child)) numberChildren++; } if(numberChildren!=priv->numberChildren) { priv->numberChildren=numberChildren; g_object_notify_by_pspec(G_OBJECT(self), XfdashboardScaledTableLayoutProperties[PROP_NUMBER_CHILDREN]); } /* Get request mode to determine if more rows than colums are needed * or the opposite */ requestMode=clutter_actor_get_request_mode(CLUTTER_ACTOR(inContainer)); /* Calculate and update number of rows and columns */ if(requestMode==CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) { rows=ceil(sqrt((double)priv->numberChildren)); columns=ceil((double)priv->numberChildren / (double)priv->rows); } else { columns=ceil(sqrt((double)priv->numberChildren)); rows=ceil((double)priv->numberChildren / (double)priv->columns); } if(rows!=priv->rows) { priv->rows=rows; g_object_notify_by_pspec(G_OBJECT(self), XfdashboardScaledTableLayoutProperties[PROP_ROWS]); } if(columns!=priv->columns) { priv->columns=columns; g_object_notify_by_pspec(G_OBJECT(self), XfdashboardScaledTableLayoutProperties[PROP_COLUMNS]); } /* Thaw notification */ g_object_thaw_notify(G_OBJECT(self)); }
/* 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); } } } } }
/* Allocate position and size of actor and its children */ static void _xfdashboard_text_box_allocate(ClutterActor *self, const ClutterActorBox *inBox, ClutterAllocationFlags inFlags) { XfdashboardTextBoxPrivate *priv=XFDASHBOARD_TEXT_BOX(self)->priv; ClutterActorBox *box=NULL; gfloat left, right, top, bottom; gfloat iconWidth, iconHeight; /* Chain up to store the allocation of the actor */ CLUTTER_ACTOR_CLASS(xfdashboard_text_box_parent_class)->allocate(self, inBox, inFlags); /* Initialize bounding box of allocation used in actors */ left=top=priv->padding; right=clutter_actor_box_get_width(inBox)-priv->padding; bottom=clutter_actor_box_get_height(inBox)-priv->padding; /* Set allocation of primary icon if visible */ if(clutter_actor_is_visible(priv->actorPrimaryIcon)) { gfloat childRight; /* Get scale size of primary icon */ iconWidth=iconHeight=0.0f; clutter_actor_get_size(priv->actorPrimaryIcon, &iconWidth, &iconHeight); if(iconHeight>0.0f) iconWidth=(bottom-top)*(iconWidth/iconHeight); /* Set allocation */ childRight=left+iconWidth; box=clutter_actor_box_new(floor(left), floor(top), floor(childRight), floor(bottom)); clutter_actor_allocate(CLUTTER_ACTOR(priv->actorPrimaryIcon), box, inFlags); clutter_actor_box_free(box); /* Adjust bounding box for next actor */ left=childRight+priv->spacing; } /* Set allocation of secondary icon if visible */ if(clutter_actor_is_visible(priv->actorSecondaryIcon)) { gfloat childLeft; /* Get scale size of secondary icon */ iconWidth=0.0f; clutter_actor_get_size(priv->actorSecondaryIcon, &iconWidth, &iconHeight); if(iconHeight>0.0f) iconWidth=(bottom-top)*(iconWidth/iconHeight); /* Set allocation */ childLeft=right-iconWidth; box=clutter_actor_box_new(floor(childLeft), floor(top), floor(right), floor(bottom)); clutter_actor_allocate(CLUTTER_ACTOR(priv->actorSecondaryIcon), box, inFlags); clutter_actor_box_free(box); /* Adjust bounding box for next actor */ right=childLeft-priv->spacing; } /* Set allocation of editable text box if visible */ if(clutter_actor_is_visible(priv->actorTextBox)) { gfloat textHeight; /* Get height of text */ clutter_actor_get_preferred_size(CLUTTER_ACTOR(priv->actorTextBox), NULL, NULL, NULL, &textHeight); /* Set allocation */ box=clutter_actor_box_new(floor(left), floor(bottom-textHeight), floor(right), floor(bottom)); clutter_actor_allocate(CLUTTER_ACTOR(priv->actorTextBox), box, inFlags); clutter_actor_box_free(box); } /* Set allocation of hint label if visible */ if(clutter_actor_is_visible(priv->actorHintLabel)) { gfloat textHeight; /* Get height of label */ clutter_actor_get_preferred_size(CLUTTER_ACTOR(priv->actorHintLabel), NULL, NULL, NULL, &textHeight); /* Set allocation */ box=clutter_actor_box_new(floor(left), floor(bottom-textHeight), floor(right), floor(bottom)); clutter_actor_allocate(CLUTTER_ACTOR(priv->actorHintLabel), box, inFlags); clutter_actor_box_free(box); } }
static void _xfdashboard_text_box_get_preferred_width(ClutterActor *self, gfloat inForHeight, gfloat *outMinWidth, gfloat *outNaturalWidth) { XfdashboardTextBoxPrivate *priv=XFDASHBOARD_TEXT_BOX(self)->priv; gfloat minWidth, naturalWidth; gfloat childMinWidth, childNaturalWidth; gint numberChildren=0; minWidth=naturalWidth=0.0f; /* Determine size of primary icon if visible */ if(clutter_actor_is_visible(priv->actorPrimaryIcon)) { clutter_actor_get_preferred_width(CLUTTER_ACTOR(priv->actorPrimaryIcon), inForHeight, &childMinWidth, &childNaturalWidth); minWidth+=childMinWidth; naturalWidth+=childNaturalWidth; numberChildren++; } /* Determine size of editable text box if visible */ if(clutter_actor_is_visible(priv->actorTextBox)) { clutter_actor_get_preferred_width(CLUTTER_ACTOR(priv->actorTextBox), inForHeight, &childMinWidth, &childNaturalWidth); minWidth+=childMinWidth; naturalWidth+=childNaturalWidth; numberChildren++; } /* Determine size of hint label if visible */ if(clutter_actor_is_visible(priv->actorHintLabel)) { clutter_actor_get_preferred_width(CLUTTER_ACTOR(priv->actorHintLabel), inForHeight, &childMinWidth, &childNaturalWidth); minWidth+=childMinWidth; naturalWidth+=childNaturalWidth; numberChildren++; } /* Determine size of secondary icon if visible */ if(clutter_actor_is_visible(priv->actorSecondaryIcon)) { clutter_actor_get_preferred_width(CLUTTER_ACTOR(priv->actorSecondaryIcon), inForHeight, &childMinWidth, &childNaturalWidth); minWidth+=childMinWidth; naturalWidth+=childNaturalWidth; } /* Add spacing for each child except the last one */ if(numberChildren>1) { numberChildren--; minWidth+=(numberChildren*priv->spacing); naturalWidth+=(numberChildren*priv->spacing); } // Add padding minWidth+=2*priv->padding; naturalWidth+=2*priv->padding; /* Store sizes computed */ if(outMinWidth) *outMinWidth=minWidth; if(outNaturalWidth) *outNaturalWidth=naturalWidth; }
/* Get largest minimum and natural size of all visible children * for calculation of one child and returns the number of visible ones */ static gint _xfdashboard_fill_box_layout_get_largest_sizes(XfdashboardFillBoxLayout *self, ClutterContainer *inContainer, gfloat *outMinWidth, gfloat *outNaturalWidth, gfloat *outMinHeight, gfloat *outNaturalHeight) { XfdashboardFillBoxLayoutPrivate *priv; ClutterActor *child; ClutterActorIter iter; gint numberChildren; gfloat largestMinWidth, largestNaturalWidth; gfloat largestMinHeight, largestNaturalHeight; gfloat childMinWidth, childNaturalWidth; gfloat childMinHeight, childNaturalHeight; ClutterActor *parent; gfloat parentWidth, parentHeight; gfloat aspectRatio; g_return_val_if_fail(XFDASHBOARD_IS_FILL_BOX_LAYOUT(self), 0); g_return_val_if_fail(CLUTTER_IS_CONTAINER(inContainer), 0); g_return_val_if_fail(CLUTTER_IS_ACTOR(inContainer), 0); priv=self->priv; /* Iterate through all children and determine sizes */ numberChildren=0; largestMinWidth=largestNaturalWidth=largestMinHeight=largestNaturalHeight=0.0f; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { /* Only check visible children */ if(!clutter_actor_is_visible(child)) continue; /* Check for largest size */ clutter_actor_get_preferred_size(child, &childMinWidth, &childNaturalWidth, &childMinHeight, &childNaturalHeight); if(childMinWidth>largestMinWidth) largestMinWidth=childMinWidth; if(childNaturalWidth>largestNaturalWidth) largestNaturalWidth=childNaturalWidth; if(childMinHeight>largestMinHeight) largestMinHeight=childMinHeight; if(childNaturalHeight>largestNaturalHeight) largestNaturalHeight=childNaturalHeight; /* Count visible children */ numberChildren++; } /* Depending on orientation set sizes to fit into parent actor */ parent=clutter_actor_get_parent(CLUTTER_ACTOR(inContainer)); if(parent) { aspectRatio=1.0f; clutter_actor_get_size(CLUTTER_ACTOR(parent), &parentWidth, &parentHeight); if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { if(priv->keepAspect==TRUE) { aspectRatio=largestMinWidth/largestMinHeight; largestMinHeight=parentHeight; largestMinWidth=largestMinHeight*aspectRatio; aspectRatio=largestNaturalWidth/largestNaturalHeight; largestNaturalHeight=parentHeight; largestNaturalWidth=largestNaturalHeight*aspectRatio; } else { largestMinHeight=parentHeight; largestNaturalHeight=parentHeight; } } else { if(priv->keepAspect==TRUE) { aspectRatio=largestMinHeight/largestMinWidth; largestMinWidth=parentWidth; largestMinHeight=largestMinWidth*aspectRatio; aspectRatio=largestNaturalHeight/largestNaturalWidth; largestNaturalWidth=parentWidth; largestNaturalHeight=largestNaturalWidth*aspectRatio; } else { largestMinWidth=parentWidth; largestNaturalWidth=parentWidth; } } } /* Set return values */ if(outMinWidth) *outMinWidth=largestMinWidth; if(outNaturalWidth) *outNaturalWidth=largestNaturalWidth; if(outMinHeight) *outMinHeight=largestMinHeight; if(outNaturalHeight) *outNaturalHeight=largestNaturalHeight; /* Return number of visible children */ return(numberChildren); }
/* Re-layout and allocate children of container we manage */ static void _xfdashboard_fill_box_layout_allocate(ClutterLayoutManager *inLayoutManager, ClutterContainer *inContainer, const ClutterActorBox *inAllocation, ClutterAllocationFlags inFlags) { XfdashboardFillBoxLayout *self; XfdashboardFillBoxLayoutPrivate *priv; ClutterActor *child; ClutterActorIter iter; gfloat parentWidth, parentHeight; gfloat homogeneousSize; gfloat x, y, w, h; gfloat aspectRatio; ClutterActorBox childAllocation; g_return_if_fail(XFDASHBOARD_IS_FILL_BOX_LAYOUT(inLayoutManager)); g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer)); self=XFDASHBOARD_FILL_BOX_LAYOUT(inLayoutManager); priv=self->priv; /* Get dimension of allocation */ parentWidth=clutter_actor_box_get_width(inAllocation); parentHeight=clutter_actor_box_get_height(inAllocation); /* If homogeneous determine sizes for all children */ if(priv->isHomogeneous==TRUE) { if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { _xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, NULL, &homogeneousSize, NULL, NULL); } else { _xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, NULL, NULL, NULL, &homogeneousSize); } } /* Iterate through children and set their sizes */ x=y=0.0f; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { /* Only set sizes on visible children */ if(!clutter_actor_is_visible(child)) continue; /* Calculate and set new allocation of child */ if(priv->isHomogeneous==FALSE) { clutter_actor_get_size(CLUTTER_ACTOR(inContainer), &w, &h); if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { aspectRatio=w/h; h=parentHeight; w=h*aspectRatio; } else { aspectRatio=h/w; w=parentWidth; h=w*aspectRatio; } } else { if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { w=homogeneousSize; h=parentHeight; } else { w=parentWidth; h=homogeneousSize; } } /* Set new allocation of child */ childAllocation.x1=ceil(x); childAllocation.y1=ceil(y); childAllocation.x2=ceil(childAllocation.x1+w); childAllocation.y2=ceil(childAllocation.y1+h); clutter_actor_allocate(child, &childAllocation, inFlags); /* Set up for next child */ if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) x+=(w+priv->spacing); else y+=(h+priv->spacing); } }
/* Get minimum and natural size of all visible children */ static void _xfdashboard_fill_box_layout_get_sizes_for_all(XfdashboardFillBoxLayout *self, ClutterContainer *inContainer, gfloat *outMinWidth, gfloat *outNaturalWidth, gfloat *outMinHeight, gfloat *outNaturalHeight) { XfdashboardFillBoxLayoutPrivate *priv; ClutterActor *child; ClutterActorIter iter; gint numberChildren; gfloat minWidth, naturalWidth; gfloat minHeight, naturalHeight; gfloat childMinWidth, childNaturalWidth; gfloat childMinHeight, childNaturalHeight; ClutterActor *parent; gfloat parentWidth, parentHeight; gfloat aspectRatio; g_return_if_fail(XFDASHBOARD_IS_FILL_BOX_LAYOUT(self)); g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer)); g_return_if_fail(CLUTTER_IS_ACTOR(inContainer)); priv=self->priv; /* Initialize return values */ numberChildren=0; minWidth=naturalWidth=minHeight=naturalHeight=0.0f; /* If not homogeneous then iterate through all children and determine sizes ... */ if(priv->isHomogeneous==FALSE) { /* Iterate through children and calculate sizes */ clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { /* Only get sizes of visible children */ if(!clutter_actor_is_visible(child)) continue; /* Count visible children */ numberChildren++; /* Determine sizes of visible child */ clutter_actor_get_preferred_size(child, &childMinWidth, &childNaturalWidth, &childMinHeight, &childNaturalHeight); if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { minWidth+=childMinWidth; naturalWidth+=childNaturalWidth; if(childMinHeight>minHeight) minHeight=childMinHeight; if(childNaturalHeight>naturalHeight) naturalHeight=childNaturalHeight; } else { minHeight+=childMinHeight; naturalHeight+=childNaturalHeight; if(childMinWidth>naturalWidth) minWidth=naturalWidth; if(childNaturalWidth>naturalHeight) naturalHeight=childNaturalWidth; } } } /* ... otherwise get largest minimum and natural size and add spacing */ else { /* Get number of visible children and also largest minimum * and natural size */ numberChildren=_xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, &childMinWidth, &childNaturalWidth, &childMinHeight, &childNaturalHeight); /* Multiply largest sizes with number visible children */ if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { minWidth=(numberChildren*childMinWidth); naturalWidth=(numberChildren*childNaturalWidth); minHeight=childMinHeight; naturalHeight=childNaturalHeight; } else { minWidth=childMinWidth; naturalWidth=childNaturalWidth; minHeight=(numberChildren*childMinHeight); naturalHeight=(numberChildren*childNaturalHeight); } } /* Add spacing */ if(numberChildren>0) { numberChildren--; if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { minWidth+=numberChildren*priv->spacing; naturalWidth+=numberChildren*priv->spacing; } else { minHeight+=numberChildren*priv->spacing; naturalHeight+=numberChildren*priv->spacing; } } /* Depending on orientation set sizes to fit into parent actor */ parent=clutter_actor_get_parent(CLUTTER_ACTOR(inContainer)); if(parent) { aspectRatio=1.0f; clutter_actor_get_size(CLUTTER_ACTOR(parent), &parentWidth, &parentHeight); if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { if(priv->keepAspect==TRUE) { aspectRatio=minWidth/minHeight; minHeight=parentHeight; minWidth=minHeight*aspectRatio; aspectRatio=naturalWidth/naturalHeight; naturalHeight=parentHeight; naturalWidth=naturalHeight*aspectRatio; } else { minHeight=parentHeight; naturalHeight=parentHeight; } } else { if(priv->keepAspect==TRUE) { aspectRatio=minHeight/minWidth; minWidth=parentWidth; minHeight=minWidth*aspectRatio; aspectRatio=naturalHeight/naturalWidth; naturalWidth=parentWidth; naturalHeight=naturalWidth*aspectRatio; } else { minWidth=parentWidth; naturalWidth=parentWidth; } } } /* Set return values */ if(outMinWidth) *outMinWidth=minWidth; if(outNaturalWidth) *outNaturalWidth=naturalWidth; if(outMinHeight) *outMinHeight=minHeight; if(outNaturalHeight) *outNaturalHeight=naturalHeight; }
static void st_scroll_view_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { ClutterActorBox content_box, child_box; gfloat avail_width, avail_height, sb_width, sb_height; gboolean hscrollbar_visible, vscrollbar_visible; StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv; StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); clutter_actor_set_allocation (actor, box, flags); st_theme_node_get_content_box (theme_node, box, &content_box); avail_width = content_box.x2 - content_box.x1; avail_height = content_box.y2 - content_box.y1; if (clutter_actor_get_request_mode (actor) == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) { sb_width = get_scrollbar_width (ST_SCROLL_VIEW (actor), -1); sb_height = get_scrollbar_height (ST_SCROLL_VIEW (actor), sb_width); } else { sb_height = get_scrollbar_height (ST_SCROLL_VIEW (actor), -1); sb_width = get_scrollbar_width (ST_SCROLL_VIEW (actor), sb_height); } /* Determine what scrollbars are visible. The basic idea of the * handling of an automatic scrollbars is that we start off with the * assumption that we don't need any scrollbars, see if that works, * and if not add horizontal and vertical scrollbars until we are no * longer overflowing. */ if (priv->child) { gfloat child_min_width; gfloat child_min_height; clutter_actor_get_preferred_width (priv->child, -1, &child_min_width, NULL); if (priv->vscrollbar_policy == GTK_POLICY_AUTOMATIC) { if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC) { /* Pass one, try without a vertical scrollbar */ clutter_actor_get_preferred_height (priv->child, avail_width, &child_min_height, NULL); vscrollbar_visible = child_min_height > avail_height; hscrollbar_visible = child_min_width > avail_width - (vscrollbar_visible ? sb_width : 0); vscrollbar_visible = child_min_height > avail_height - (hscrollbar_visible ? sb_height : 0); /* Pass two - if we needed a vertical scrollbar, get a new preferred height */ if (vscrollbar_visible) { clutter_actor_get_preferred_height (priv->child, MAX (avail_width - sb_width, 0), &child_min_height, NULL); hscrollbar_visible = child_min_width > avail_width - sb_width; } } else { hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER; /* try without a vertical scrollbar */ clutter_actor_get_preferred_height (priv->child, avail_width, &child_min_height, NULL); vscrollbar_visible = child_min_height > avail_height - (hscrollbar_visible ? sb_height : 0); } } else { vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER; if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC) hscrollbar_visible = child_min_width > avail_height - (vscrollbar_visible ? 0 : sb_width); else hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER; } } else { hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER; vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER; } /* Whether or not we show the scrollbars, if the scrollbars are visible * actors, we need to give them some allocation, so we unconditionally * give them the "right" allocation; that might overlap the child when * the scrollbars are not visible, but it doesn't matter because we * don't include them in pick or paint. */ /* Vertical scrollbar */ if (clutter_actor_is_visible (priv->vscroll)) { if (st_widget_get_direction (ST_WIDGET (actor)) == ST_TEXT_DIRECTION_RTL) { child_box.x1 = content_box.x1; child_box.x2 = content_box.x1 + sb_width; } else { child_box.x1 = content_box.x2 - sb_width; child_box.x2 = content_box.x2; } child_box.y1 = content_box.y1; child_box.y2 = content_box.y2 - (hscrollbar_visible ? sb_height : 0); clutter_actor_allocate (priv->vscroll, &child_box, flags); } /* Horizontal scrollbar */ if (clutter_actor_is_visible (priv->hscroll)) { if (st_widget_get_direction (ST_WIDGET (actor)) == ST_TEXT_DIRECTION_RTL) { child_box.x1 = content_box.x1 + (vscrollbar_visible ? sb_width : 0); child_box.x2 = content_box.x2; } else { child_box.x1 = content_box.x1; child_box.x2 = content_box.x2 - (vscrollbar_visible ? sb_width : 0); } child_box.y1 = content_box.y2 - sb_height; child_box.y2 = content_box.y2; clutter_actor_allocate (priv->hscroll, &child_box, flags); } /* Now fold visibility into the scrollbar sizes to simplify the rest * of the computations. */ if (!hscrollbar_visible) sb_height = 0; if (!vscrollbar_visible) sb_width = 0; /* Child */ if (st_widget_get_direction (ST_WIDGET (actor)) == ST_TEXT_DIRECTION_RTL) { child_box.x1 = content_box.x1 + sb_width; child_box.x2 = content_box.x2; } else { child_box.x1 = content_box.x1; child_box.x2 = content_box.x2 - sb_width; } child_box.y1 = content_box.y1; child_box.y2 = content_box.y2 - sb_height; if (priv->child) clutter_actor_allocate (priv->child, &child_box, flags); if (priv->hscrollbar_visible != hscrollbar_visible) { g_object_freeze_notify (G_OBJECT (actor)); priv->hscrollbar_visible = hscrollbar_visible; g_object_notify (G_OBJECT (actor), "hscrollbar-visible"); g_object_thaw_notify (G_OBJECT (actor)); } if (priv->vscrollbar_visible != vscrollbar_visible) { g_object_freeze_notify (G_OBJECT (actor)); priv->vscrollbar_visible = vscrollbar_visible; g_object_notify (G_OBJECT (actor), "vscrollbar-visible"); g_object_thaw_notify (G_OBJECT (actor)); } }
/* Re-layout and allocate children of container we manage */ static void _xfdashboard_scaled_table_layout_allocate(ClutterLayoutManager *self, ClutterContainer *inContainer, const ClutterActorBox *inAllocation, ClutterAllocationFlags inFlags) { XfdashboardScaledTableLayoutPrivate *priv; gint row, col; ClutterActor *child; ClutterActorIter iter; gfloat cellWidth, cellHeight; gfloat childWidth, childHeight; gfloat scaledChildWidth, scaledChildHeight; gfloat largestWidth, largestHeight; gfloat scaleWidth, scaleHeight; gfloat aspectRatio; gfloat x, y; ClutterActorBox childAllocation; g_return_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self)); g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer)); priv=XFDASHBOARD_SCALED_TABLE_LAYOUT(self)->priv; /* Get size of container holding children to layout and * determine size of a cell */ clutter_actor_get_size(CLUTTER_ACTOR(inContainer), &childWidth, &childHeight); cellWidth=childWidth-((priv->columns-1)*priv->columnSpacing); cellWidth=floor(cellWidth/priv->columns); cellHeight=childHeight-((priv->rows-1)*priv->rowSpacing); cellHeight=floor(cellHeight/priv->rows); /* Iterate through children and find largest one * if relative scale was set */ largestWidth=largestHeight=0.0f; if(priv->relativeScale==TRUE) { gfloat w, h; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { if(!clutter_actor_is_visible(child)) continue; clutter_actor_get_preferred_size(child, NULL, NULL, &w, &h); if(w>largestWidth) largestWidth=w; if(h>largestHeight) largestHeight=h; } } /* Iterate through child actors and set their new allocation */ row=col=0; x=y=0.0f; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { if(!clutter_actor_is_visible(child)) continue; /* Get natural size of actor */ clutter_actor_get_preferred_size(child, NULL, NULL, &childWidth, &childHeight); /* If either width or height is 0 then it is visually hidden and we * skip expensive calculation. This also has the nice effect that * do not perform invalid divisions by zero ;) */ if(childWidth>0.0f && childHeight>0.0f) { /* Get scale factor needed to apply to width and height. * If no relative scaling should be performed the scale is always 1.0 * otherwise it is the scale factor for this actor to the largest one. */ if(priv->relativeScale==TRUE) { /* Get scale factors */ scaleWidth=childWidth/largestWidth; scaleHeight=childHeight/largestHeight; } else scaleWidth=scaleHeight=1.0f; /* Get aspect ratio factor */ aspectRatio=childHeight/childWidth; /* Calculate new size of child */ scaledChildWidth=cellWidth*scaleWidth; scaledChildHeight=scaledChildWidth*aspectRatio; if(scaledChildHeight>cellHeight) { scaledChildHeight=cellHeight*scaleHeight; scaledChildWidth=scaledChildHeight/aspectRatio; } /* If upscaling should be prevent check if we are upscaling now */ if(priv->preventUpscaling) { if(scaledChildWidth>childWidth) { scaledChildWidth=childWidth; scaledChildHeight=childWidth*aspectRatio; } if(scaledChildHeight>childHeight) { scaledChildHeight=childHeight; scaledChildWidth=childHeight/aspectRatio; } } } else { /* Visually hidden so do not allocate any space */ scaledChildWidth=0.0f; scaledChildHeight=0.0f; } /* Set new allocation of child */ childAllocation.x1=ceil(x+((cellWidth-scaledChildWidth)/2.0f)); childAllocation.y1=ceil(y+((cellHeight-scaledChildHeight)/2.0f)); childAllocation.x2=ceil(childAllocation.x1+scaledChildWidth); childAllocation.y2=ceil(childAllocation.y1+scaledChildHeight); clutter_actor_allocate(child, &childAllocation, inFlags); /* Set up for next child */ col=(col+1) % priv->columns; if(col==0) row++; x=col*(cellWidth+priv->columnSpacing); y=row*(cellHeight+priv->rowSpacing); } }
static void clutter_bin_layout_allocate (ClutterLayoutManager *manager, ClutterContainer *container, const ClutterActorBox *allocation, ClutterAllocationFlags flags) { gfloat allocation_x, allocation_y; gfloat available_w, available_h; ClutterActor *actor, *child; ClutterActorIter iter; clutter_actor_box_get_origin (allocation, &allocation_x, &allocation_y); clutter_actor_box_get_size (allocation, &available_w, &available_h); actor = CLUTTER_ACTOR (container); clutter_actor_iter_init (&iter, actor); while (clutter_actor_iter_next (&iter, &child)) { ClutterLayoutMeta *meta; ClutterBinLayer *layer; ClutterActorBox child_alloc = { 0, }; gdouble x_align, y_align; gboolean x_fill, y_fill, is_fixed_position_set; float fixed_x, fixed_y; if (!clutter_actor_is_visible (child)) continue; meta = clutter_layout_manager_get_child_meta (manager, container, child); layer = CLUTTER_BIN_LAYER (meta); fixed_x = fixed_y = 0.f; g_object_get (child, "fixed-position-set", &is_fixed_position_set, "fixed-x", &fixed_x, "fixed-y", &fixed_y, NULL); /* XXX:2.0 - remove the FIXED alignment, and just use the fixed position * of the actor if one is set */ if (is_fixed_position_set || layer->x_align == CLUTTER_BIN_ALIGNMENT_FIXED) { if (is_fixed_position_set) child_alloc.x1 = fixed_x; else child_alloc.x1 = clutter_actor_get_x (child); } else child_alloc.x1 = allocation_x; if (is_fixed_position_set || layer->y_align == CLUTTER_BIN_ALIGNMENT_FIXED) { if (is_fixed_position_set) child_alloc.y1 = fixed_y; else child_alloc.y1 = clutter_actor_get_y (child); } else child_alloc.y1 = allocation_y; child_alloc.x2 = allocation_x + available_w; child_alloc.y2 = allocation_y + available_h; if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_HORIZONTAL)) { ClutterActorAlign align; align = clutter_actor_get_x_align (child); x_fill = align == CLUTTER_ACTOR_ALIGN_FILL; x_align = get_actor_align_factor (align); } else { ClutterTextDirection text_dir; x_fill = (layer->x_align == CLUTTER_BIN_ALIGNMENT_FILL); text_dir = clutter_actor_get_text_direction (child); if (!is_fixed_position_set) x_align = get_bin_alignment_factor (layer->x_align, text_dir); else x_align = 0.0; } if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_VERTICAL)) { ClutterActorAlign align; align = clutter_actor_get_y_align (child); y_fill = align == CLUTTER_ACTOR_ALIGN_FILL; y_align = get_actor_align_factor (align); } else { y_fill = (layer->y_align == CLUTTER_BIN_ALIGNMENT_FILL); if (!is_fixed_position_set) y_align = get_bin_alignment_factor (layer->y_align, CLUTTER_TEXT_DIRECTION_LTR); else y_align = 0.0; } clutter_actor_allocate_align_fill (child, &child_alloc, x_align, y_align, x_fill, y_fill, flags); } }