/* GObject stuff */ static void astro_applet_paint (ClutterActor *applet) { AstroAppletPrivate *priv; GList *c; gint width = 0; g_return_if_fail (ASTRO_IS_APPLET (applet)); priv = ASTRO_APPLET (applet)->priv; c = clutter_container_get_children (CLUTTER_CONTAINER (applet)); for (c = c; c; c = c->next) { gint total = clutter_actor_get_y (c->data) + clutter_actor_get_width (c->data); if (total > width && c->data != priv->texture) width = total; } clutter_actor_set_size (priv->texture, width, clutter_actor_get_height (applet)); c = clutter_container_get_children (CLUTTER_CONTAINER (applet)); for (c = c; c; c = c->next) clutter_actor_paint (c->data); }
static void clutter_bin_layout_get_preferred_height (ClutterLayoutManager *manager, ClutterContainer *container, gfloat for_width, gfloat *min_height_p, gfloat *nat_height_p) { GList *children = clutter_container_get_children (container); GList *l; gfloat min_height, nat_height; min_height = nat_height = 0.0; for (l = children; l != NULL; l = l->next) { ClutterActor *child = l->data; gfloat minimum, natural; 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; }
NtfNotification * ntf_tray_find_notification (NtfTray *tray, gint subsystem, gint id) { NtfTrayPrivate *priv; GList *notifiers, *l; NtfNotification *ntf = NULL; g_return_val_if_fail (NTF_IS_TRAY (tray), NULL); priv = tray->priv; notifiers = clutter_container_get_children (CLUTTER_CONTAINER (priv->notifiers)); for (l = notifiers; l; l = l->next) { gint s = ntf_notification_get_subsystem (NTF_NOTIFICATION (l->data)); gint i = ntf_notification_get_id (NTF_NOTIFICATION (l->data)); if (subsystem == s && id == i) { ntf = l->data; break; } } g_list_free (notifiers); return ntf; }
static void ensure_visible (ClutterText *text, MxGrid *grid) { GList *children; ClutterActor *child; const gchar *string = clutter_text_get_text (text); gint number = atoi (string) - 1; children = clutter_container_get_children (CLUTTER_CONTAINER (grid)); child = g_list_nth_data (children, number); if (child) { ClutterGeometry geom; MxScrollView *scroll = (MxScrollView *) clutter_actor_get_parent (CLUTTER_ACTOR (grid)); clutter_actor_get_allocation_geometry (child, &geom); mx_scroll_view_ensure_visible (scroll, &geom); printf ("Making child %d visible\n", number); } else printf ("Couldn't make child %d visible\n", number); g_list_free (children); }
/** * mex_menu_clear_all: * @menu: A #MexMenu * * Removes all items from the menu. */ void mex_menu_clear_all (MexMenu *menu) { gboolean direction; GList *l, *children; MexMenuPrivate *priv; g_return_if_fail (MEX_IS_MENU (menu)); priv = menu->priv; if (priv->depth == 0) return; children = clutter_container_get_children (CLUTTER_CONTAINER (menu)); direction = (priv->depth >= 0); for (l = g_list_find (children, clutter_actor_get_parent (priv->layout)); l; l = direction ? l->next : l->prev) { ClutterActor *child = l->data; clutter_container_remove_actor (CLUTTER_CONTAINER (menu), child); if (--priv->depth == 0) break; } g_list_free (children); priv->layout = mex_menu_create_layout (menu, FALSE); g_object_notify (G_OBJECT (menu), "depth"); }
static void shell_overflow_list_get_preferred_height (ClutterActor *actor, gfloat for_width, gfloat *min_height_p, gfloat *natural_height_p) { ShellOverflowList *self = SHELL_OVERFLOW_LIST (actor); ShellOverflowListPrivate *priv = self->priv; GList *children; if (min_height_p) *min_height_p = 0; if (natural_height_p) { int n_children; children = clutter_container_get_children (CLUTTER_CONTAINER (self)); n_children = g_list_length (children); if (n_children == 0) *natural_height_p = 0; else *natural_height_p = (n_children - 1) * (priv->item_height + priv->spacing) + priv->item_height; g_list_free (children); } }
void mex_menu_set_min_width (MexMenu *menu, gfloat min_width) { MexMenuPrivate *priv; g_return_if_fail (MEX_IS_MENU (menu)); priv = menu->priv; if (priv->min_width != min_width) { gint depth; gboolean direction; GList *l, *children; priv->min_width = min_width; children = clutter_container_get_children (CLUTTER_CONTAINER (menu)); direction = (priv->depth >= 0); depth = priv->depth; for (l = g_list_find (children, clutter_actor_get_parent (priv->layout)); l; l = direction ? l->next : l->prev) { g_object_set (G_OBJECT (l->data), "min-width", priv->min_width, NULL); if (--depth == 0) break; } g_list_free (children); g_object_notify (G_OBJECT (menu), "min-menu-width"); } }
static void key_group_paint (ClutterActor *actor) { KeyGroup *self = KEY_GROUP (actor); GList *children, *l; gint i; children = clutter_container_get_children (CLUTTER_CONTAINER (self)); for (l = children, i = 0; l != NULL; l = l->next, i++) { ClutterActor *child = l->data; /* paint the selection rectangle */ if (i == self->selected_index) { ClutterActorBox box = { 0, }; clutter_actor_get_allocation_box (child, &box); box.x1 -= 2; box.y1 -= 2; box.x2 += 2; box.y2 += 2; cogl_set_source_color4ub (255, 255, 0, 224); cogl_rectangle (box.x1, box.y1, box.x2, box.y2); } clutter_actor_paint (child); } g_list_free (children); }
static void bar_pane_gps_update(PaneGPSData *pgd) { GList *list; GList *work; /* The widget does not have a parent during bar_pane_gps_new, so calling gtk_widget_show_all there gives a * "Gtk-CRITICAL **: gtk_widget_realize: assertion `GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed" * error. gtk_widget_show_all can be given after it has been added to the bar. */ if (gtk_widget_get_parent(pgd->widget) != NULL) gtk_widget_show_all(pgd->widget); /* If a create-marker background process is running, kill it * and start again */ if (pgd->create_markers_id != 0) { if (g_idle_remove_by_data(pgd)) { pgd->create_markers_id = 0; } else { return; } } /* Delete any markers currently displayed */ work = clutter_container_get_children(CLUTTER_CONTAINER(pgd->icon_layer)); while (work) { clutter_container_remove(CLUTTER_CONTAINER(pgd->icon_layer), work->data, NULL); work = work->next; } g_list_free(work); if (!pgd->enable_markers_checked) { return; } /* For each selected photo that has GPS data, create a marker containing * a single, small text character the same colour as the marker background. * Use a background process in case the user selects a large number of files. */ list = layout_selection_list(pgd->pane.lw); list = file_data_process_groups_in_selection(list, FALSE, NULL); if (list != NULL) { pgd->selection_list = g_list_copy(list); pgd->marker_list = g_ptr_array_new(); pgd->selection_count = g_list_length(pgd->selection_list); pgd->create_markers_id = g_idle_add(bar_pane_gps_create_markers_cb, pgd); } g_list_free(list); g_list_free(work); }
static MxFocusable * mx_stack_accept_focus (MxFocusable *focusable, MxFocusHint hint) { GList *c, *children; MxStackPrivate *priv = MX_STACK (focusable)->priv; ClutterContainer *container = CLUTTER_CONTAINER (focusable); focusable = NULL; switch (hint) { default: case MX_FOCUS_HINT_PRIOR: if (priv->current_focus && (!MX_IS_WIDGET (priv->current_focus) || !mx_widget_get_disabled ((MxWidget *)priv->current_focus))) { focusable = mx_focusable_accept_focus (MX_FOCUSABLE (priv->current_focus), hint); if (focusable) break; } /* This purposefully runs into the next case statement */ case MX_FOCUS_HINT_FIRST: case MX_FOCUS_HINT_LAST: children = clutter_container_get_children (container); if (hint == MX_FOCUS_HINT_LAST) children = g_list_reverse (children); if (children) { c = children; while (c && !focusable) { ClutterActor *child = c->data; c = c->next; if (!MX_IS_FOCUSABLE (child)) continue; if (MX_IS_WIDGET (child) && mx_widget_get_disabled ((MxWidget *)child)) continue; priv->current_focus = child; focusable = mx_focusable_accept_focus (MX_FOCUSABLE (child), hint); } g_list_free (children); } break; } return focusable; }
static void mex_shell_destroy (ClutterActor *actor) { GList *children = clutter_container_get_children (CLUTTER_CONTAINER (actor)); g_list_foreach (children, (GFunc)clutter_actor_destroy, NULL); g_list_free (children); if (CLUTTER_ACTOR_CLASS (mex_shell_parent_class)->destroy) CLUTTER_ACTOR_CLASS (mex_shell_parent_class)->destroy (actor); }
static void clutter_bin_layout_allocate (ClutterLayoutManager *manager, ClutterContainer *container, const ClutterActorBox *allocation, ClutterAllocationFlags flags) { GList *children = clutter_container_get_children (container); GList *l; gfloat available_w, available_h; available_w = clutter_actor_box_get_width (allocation); available_h = clutter_actor_box_get_height (allocation); for (l = children; l != NULL; l = l->next) { ClutterActor *child = l->data; ClutterLayoutMeta *meta; ClutterBinLayer *layer; ClutterActorBox child_alloc = { 0, }; gdouble x_align, y_align; gboolean x_fill, y_fill; meta = clutter_layout_manager_get_child_meta (manager, container, child); layer = CLUTTER_BIN_LAYER (meta); if (layer->x_align == CLUTTER_BIN_ALIGNMENT_FIXED) child_alloc.x1 = clutter_actor_get_x (child); else child_alloc.x1 = 0.0f; if (layer->y_align == CLUTTER_BIN_ALIGNMENT_FIXED) child_alloc.y1 = clutter_actor_get_y (child); else child_alloc.y1 = 0.0f; child_alloc.x2 = available_w; child_alloc.y2 = available_h; x_fill = (layer->x_align == CLUTTER_BIN_ALIGNMENT_FILL); y_fill = (layer->y_align == CLUTTER_BIN_ALIGNMENT_FILL); x_align = get_bin_alignment_factor (layer->x_align); y_align = get_bin_alignment_factor (layer->y_align); clutter_actor_allocate_align_fill (child, &child_alloc, x_align, y_align, x_fill, y_fill, flags); } g_list_free (children); }
static void shell_overflow_list_get_preferred_width (ClutterActor *actor, gfloat for_height, gfloat *min_width_p, gfloat *natural_width_p) { ShellOverflowList *self = SHELL_OVERFLOW_LIST (actor); gboolean first = TRUE; float min = 0, natural = 0; GList *iter; GList *children; children = clutter_container_get_children (CLUTTER_CONTAINER (self)); for (iter = children; iter; iter = iter->next) { ClutterActor *child = iter->data; float child_min, child_natural; clutter_actor_get_preferred_width (child, for_height, &child_min, &child_natural); if (first) { first = FALSE; min = child_min; natural = child_natural; } else { if (child_min > min) min = child_min; if (child_natural > natural) natural = child_natural; } } if (min_width_p) *min_width_p = min; if (natural_width_p) *natural_width_p = natural; g_list_free (children); }
static void ntf_tray_dismiss_all_cb (ClutterActor *button, NtfTray *tray) { NtfTrayPrivate *priv = tray->priv; GList *child, *children; clutter_actor_hide (CLUTTER_ACTOR (tray)); child = children = clutter_container_get_children (CLUTTER_CONTAINER (priv->notifiers)); while (child != NULL) { g_signal_emit_by_name (child->data, "closed", 0); child = child->next; } g_list_free (children); }
/** * test_conform_simple_fixture_setup: * * Initialise stuff before each test is run */ void test_conform_simple_fixture_setup (TestConformSimpleFixture *fixture, gconstpointer data) { /* const TestConformSharedState *shared_state = data; */ ClutterActor *stage = clutter_stage_get_default (); GList *actors = clutter_container_get_children (CLUTTER_CONTAINER (stage)); GList *tmp; /* To help reduce leakage between unit tests, we destroy all children of the stage */ for (tmp = actors; tmp != NULL; tmp = tmp->next) { ClutterActor *leaked_actor = tmp->data; if (g_test_verbose ()) g_print ("Freeing leaked actor %p\n", leaked_actor); clutter_actor_destroy (leaked_actor); } }
/** * mex_menu_push: * @menu: A #MexMenu * * Increments the current depth of the menu. If the current depth is %0, * or positive, this will add a new menu level. If the depth is negative, * this will remove a menu level. * * Returns: The new menu depth */ gint mex_menu_push (MexMenu *menu) { MexMenuPrivate *priv; g_return_val_if_fail (MEX_IS_MENU (menu), 0); priv = menu->priv; if (priv->depth < 0) { GList *l; GList *children = clutter_container_get_children (CLUTTER_CONTAINER (menu)); l = g_list_find (children, clutter_actor_get_parent (priv->layout)); priv->layout = l->next->data; priv->action_layout = g_object_get_data (G_OBJECT (priv->layout), "action-layout"); clutter_container_remove_actor (CLUTTER_CONTAINER (menu), CLUTTER_ACTOR (l->data)); g_list_free (children); priv->depth ++; priv->focus_on_add = priv->has_focus; mex_menu_uncheck_buttons (menu); } else { priv->depth ++; priv->layout = mex_menu_create_layout (menu, FALSE); g_object_set_qdata (G_OBJECT (priv->layout), mex_menu_depth_quark, GINT_TO_POINTER (priv->depth)); if (priv->has_focus) priv->focus_on_add = TRUE; } g_object_notify (G_OBJECT (menu), "depth"); return priv->depth; }
/** * clutter_container_find_child_by_name: * @container: a #ClutterContainer * @child_name: the name of the requested child. * * Finds a child actor of a container by its name. Search recurses * into any child container. * * Return value: (transfer none): The child actor with the requested name, * or %NULL if no actor with that name was found. * * Since: 0.6 */ ClutterActor * clutter_container_find_child_by_name (ClutterContainer *container, const gchar *child_name) { GList *children; GList *iter; ClutterActor *actor = NULL; g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), NULL); g_return_val_if_fail (child_name != NULL, NULL); children = clutter_container_get_children (container); for (iter = children; iter; iter = g_list_next (iter)) { ClutterActor *a; const gchar *iter_name; a = CLUTTER_ACTOR (iter->data); iter_name = clutter_actor_get_name (a); if (iter_name && !strcmp (iter_name, child_name)) { actor = a; break; } if (CLUTTER_IS_CONTAINER (a)) { ClutterContainer *c = CLUTTER_CONTAINER (a); actor = clutter_container_find_child_by_name (c, child_name); if (actor) break; } } g_list_free (children); return actor; }
void shell_overflow_list_paint (ClutterActor *actor) { ShellOverflowList *self = SHELL_OVERFLOW_LIST (actor); ShellOverflowListPrivate *priv = self->priv; GList *children, *iter; int i; children = clutter_container_get_children (CLUTTER_CONTAINER (self)); if (children == NULL) return; iter = g_list_nth (children, (priv->page) * priv->items_per_page); i = 0; for (;iter && i < priv->items_per_page; iter = iter->next, i++) { ClutterActor *actor = CLUTTER_ACTOR (iter->data); clutter_actor_paint (actor); } g_list_free (children); }
void mex_media_controls_focus_content (MexMediaControls *self, MexContent *content) { MexMediaControlsPrivate *priv = self->priv; ClutterContainer *container; GList *children, *l; container = CLUTTER_CONTAINER (clutter_script_get_object (priv->script, "related-box")); children = clutter_container_get_children (container); for (l = children; l; l = g_list_next (l)) { if (mex_content_view_get_content (l->data) == content) { mex_push_focus (l->data); return; } } return; }
static void mex_menu_uncheck_buttons (MexMenu *menu) { GList *children; MexMenuPrivate *priv = menu->priv; children = clutter_container_get_children (CLUTTER_CONTAINER (priv->action_layout)); while (children) { if (g_object_get_qdata (children->data, mex_menu_item_quark)) { mx_button_set_toggled (MX_BUTTON (children->data), FALSE); if (priv->focus_on_add) { mex_push_focus (MX_FOCUSABLE (children->data)); priv->focus_on_add = FALSE; } } children = g_list_delete_link (children, children); } }
static void sync_actor_stacking (MetaCompScreen *info) { GList *children; GList *tmp; GList *old; gboolean reordered; /* NB: The first entries in the lists are stacked the lowest */ /* Restacking will trigger full screen redraws, so it's worth a * little effort to make sure we actually need to restack before * we go ahead and do it */ children = clutter_container_get_children (CLUTTER_CONTAINER (info->window_group)); reordered = FALSE; old = children; /* We allow for actors in the window group other than the actors we * know about, but it's up to a plugin to try and keep them stacked correctly * (we really need extra API to make that reliable.) */ /* Of the actors we know, the bottom actor should be the background actor */ while (old && old->data != info->background_actor && !META_IS_WINDOW_ACTOR (old->data)) old = old->next; if (old == NULL || old->data != info->background_actor) { reordered = TRUE; goto done_with_check; } /* Then the window actors should follow in sequence */ old = old->next; for (tmp = info->windows; tmp != NULL; tmp = tmp->next) { while (old && !META_IS_WINDOW_ACTOR (old->data)) old = old->next; /* old == NULL: someone reparented a window out of the window group, * order undefined, always restack */ if (old == NULL || old->data != tmp->data) { reordered = TRUE; goto done_with_check; } old = old->next; } done_with_check: g_list_free (children); if (!reordered) return; for (tmp = g_list_last (info->windows); tmp != NULL; tmp = tmp->prev) { MetaWindowActor *window_actor = tmp->data; clutter_actor_lower_bottom (CLUTTER_ACTOR (window_actor)); } clutter_actor_lower_bottom (info->background_actor); }
static void ntf_tray_notification_closed_cb (NtfNotification *ntf, NtfTray *tray) { NtfTrayPrivate *priv = tray->priv; ClutterActor *ntfa = CLUTTER_ACTOR (ntf); ClutterAnimation *anim; priv->n_notifiers--; if (priv->n_notifiers < 0) { g_warning ("Bug in notifier accounting, attempting to fix"); priv->n_notifiers = 0; } /* fade out closed notifier */ if (ntfa == priv->active_notifier) { anim = clutter_actor_animate (CLUTTER_ACTOR (ntfa), CLUTTER_EASE_IN_SINE, FADE_DURATION, "opacity", 0, NULL); g_signal_connect_after (anim, "completed", G_CALLBACK (ntf_tray_hide_ntf_completed_cb), tray); } else { clutter_actor_destroy (ntfa); } /* Fade in newer notifier from below stack */ if (ntfa == priv->active_notifier && priv->n_notifiers > 0) { gint prev_height, new_height; GList *notifiers; prev_height = clutter_actor_get_height (ntfa); notifiers = clutter_container_get_children (CLUTTER_CONTAINER (priv->notifiers)); priv->active_notifier = notifiers->next != NULL ? (ClutterActor *) notifiers->next->data : NULL; g_list_free (notifiers); if (priv->active_notifier) { clutter_actor_set_opacity (priv->active_notifier, 0); clutter_actor_show (CLUTTER_ACTOR (priv->active_notifier)); clutter_actor_animate (CLUTTER_ACTOR (priv->active_notifier), CLUTTER_EASE_IN_SINE, FADE_DURATION, "opacity", 0xff, NULL); new_height = clutter_actor_get_height (priv->active_notifier); if (prev_height != new_height && priv->n_notifiers > 1) { gfloat new_y; new_y = clutter_actor_get_y (priv->control) - (prev_height - new_height); clutter_actor_animate (priv->control, CLUTTER_EASE_IN_SINE, FADE_DURATION, "y", new_y, NULL); } } } if (priv->n_notifiers == 0) { priv->active_notifier = NULL; #pragma TODO /* mnb_notification_gtk_hide (); */ } else if (priv->n_notifiers == 1) { /* slide the control out of view */ ClutterAnimation *anim; anim = clutter_actor_animate (priv->control, CLUTTER_EASE_IN_SINE, FADE_DURATION, "opacity", 0x0, "y", clutter_actor_get_height (priv->active_notifier) - clutter_actor_get_height (priv->control), NULL); g_signal_connect_after (anim, "completed", G_CALLBACK (ntf_tray_control_hide_completed_cb), tray); } else { /* Just Update control text */ gchar *msg; msg = g_strdup_printf (_("%i pending messages"), priv->n_notifiers); mx_label_set_text (MX_LABEL (priv->control_text), msg); g_free (msg); } }
static void shell_overflow_list_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { ShellOverflowList *self = SHELL_OVERFLOW_LIST (actor); ShellOverflowListPrivate *priv = self->priv; GList *children, *iter; int n_pages; int n_children; int n_fits; float width; float curheight; float avail_height; gboolean overflow; /* chain up to set actor->allocation */ (CLUTTER_ACTOR_CLASS (g_type_class_peek (clutter_actor_get_type ())))->allocate (actor, box, flags); width = box->x2 - box->x1; curheight = 0; avail_height = box->y2 - box->y1; children = clutter_container_get_children (CLUTTER_CONTAINER (self)); n_children = g_list_length (children); n_fits = 0; n_pages = 1; overflow = FALSE; for (iter = children; iter; iter = iter->next) { ClutterActor *actor = CLUTTER_ACTOR (iter->data); ClutterActorBox child_box; if ((curheight + priv->item_height) > avail_height) { overflow = TRUE; curheight = 0; n_pages++; } else if (!overflow) n_fits++; child_box.x1 = 0; child_box.x2 = width; child_box.y1 = curheight; child_box.y2 = child_box.y1 + priv->item_height; clutter_actor_allocate (actor, &child_box, flags); curheight += priv->item_height; if (iter != children) curheight += priv->spacing; } priv->items_per_page = n_fits; if (n_pages != priv->n_pages) { priv->n_pages = n_pages; g_object_notify (G_OBJECT (self), "n-pages"); } g_list_free (children); }
static void clutter_flow_layout_allocate (ClutterLayoutManager *manager, ClutterContainer *container, const ClutterActorBox *allocation, ClutterAllocationFlags flags) { ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv; GList *l, *children = clutter_container_get_children (container); gfloat avail_width, avail_height; gfloat item_x, item_y; gint line_item_count; gint items_per_line; gint line_index; if (children == NULL) return; clutter_actor_box_get_size (allocation, &avail_width, &avail_height); items_per_line = compute_lines (CLUTTER_FLOW_LAYOUT (manager), avail_width, avail_height); item_x = item_y = 0; line_item_count = 0; line_index = 0; for (l = children; l != NULL; l = l->next) { ClutterActor *child = l->data; ClutterActorBox child_alloc; gfloat item_width, item_height; gfloat new_x, new_y; if (!CLUTTER_ACTOR_IS_VISIBLE (child)) continue; new_x = new_y = 0; if (priv->orientation == CLUTTER_FLOW_HORIZONTAL) { if (line_item_count == items_per_line && line_item_count > 0) { item_y += g_array_index (priv->line_natural, gfloat, line_index); if (line_index >= 0) item_y += priv->row_spacing; line_item_count = 0; line_index += 1; item_x = 0; } new_x = ((line_item_count + 1) * (avail_width + priv->col_spacing)) / items_per_line; item_width = new_x - item_x - priv->col_spacing; item_height = g_array_index (priv->line_natural, gfloat, line_index); if (!priv->is_homogeneous) { gfloat child_min, child_natural; clutter_actor_get_preferred_width (child, item_height, &child_min, &child_natural); item_width = MIN (item_width, child_natural); clutter_actor_get_preferred_height (child, item_width, &child_min, &child_natural); item_height = MIN (item_height, child_natural); } } else { if (line_item_count == items_per_line && line_item_count > 0) { item_x += g_array_index (priv->line_natural, gfloat, line_index); if (line_index >= 0) item_x += priv->col_spacing; line_item_count = 0; line_index += 1; item_y = 0; } new_y = ((line_item_count + 1) * (avail_height + priv->row_spacing)) / items_per_line; item_height = new_y - item_y - priv->row_spacing; item_width = g_array_index (priv->line_natural, gfloat, line_index); if (!priv->is_homogeneous) { gfloat child_min, child_natural; clutter_actor_get_preferred_width (child, item_height, &child_min, &child_natural); item_width = MIN (item_width, child_natural); clutter_actor_get_preferred_height (child, item_width, &child_min, &child_natural); item_height = MIN (item_height, child_natural); } } CLUTTER_NOTE (LAYOUT, "flow[line:%d, item:%d/%d] =" "{ %.2f, %.2f, %.2f, %.2f }", line_index, line_item_count + 1, items_per_line, item_x, item_y, item_width, item_height); child_alloc.x1 = ceil (item_x); child_alloc.y1 = ceil (item_y); child_alloc.x2 = ceil (child_alloc.x1 + item_width); child_alloc.y2 = ceil (child_alloc.y1 + item_height); clutter_actor_allocate (child, &child_alloc, flags); if (priv->orientation == CLUTTER_FLOW_HORIZONTAL) item_x = new_x; else item_y = new_y; line_item_count += 1; } g_list_free (children); }
static void clutter_flow_layout_get_preferred_height (ClutterLayoutManager *manager, ClutterContainer *container, gfloat for_width, gfloat *min_height_p, gfloat *nat_height_p) { ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv; GList *l, *children = clutter_container_get_children (container); gint n_columns, line_item_count, line_count; gfloat total_min_height, total_natural_height; gfloat line_min_height, line_natural_height; gfloat max_min_height, max_natural_height; gfloat item_x; n_columns = get_columns (CLUTTER_FLOW_LAYOUT (manager), for_width); total_min_height = 0; total_natural_height = 0; line_min_height = 0; line_natural_height = 0; line_item_count = 0; line_count = 0; item_x = 0; /* clear the line height arrays */ if (priv->line_min != NULL) g_array_free (priv->line_min, TRUE); if (priv->line_natural != NULL) g_array_free (priv->line_natural, TRUE); priv->line_min = g_array_sized_new (FALSE, FALSE, sizeof (gfloat), 16); priv->line_natural = g_array_sized_new (FALSE, FALSE, sizeof (gfloat), 16); if (children) line_count = 1; max_min_height = max_natural_height = 0; for (l = children; l != NULL; l = l->next) { ClutterActor *child = l->data; gfloat child_min, child_natural; gfloat new_x, item_width; if (!CLUTTER_ACTOR_IS_VISIBLE (child)) continue; if (priv->orientation == CLUTTER_FLOW_HORIZONTAL && for_width > 0) { if (line_item_count == n_columns) { total_min_height += line_min_height; total_natural_height += line_natural_height; g_array_append_val (priv->line_min, line_min_height); g_array_append_val (priv->line_natural, line_natural_height); line_min_height = line_natural_height = 0; line_item_count = 0; line_count += 1; item_x = 0; } new_x = ((line_item_count + 1) * (for_width + priv->col_spacing)) / n_columns; item_width = new_x - item_x - priv->col_spacing; clutter_actor_get_preferred_height (child, item_width, &child_min, &child_natural); line_min_height = MAX (line_min_height, child_min); line_natural_height = MAX (line_natural_height, child_natural); item_x = new_x; line_item_count += 1; max_min_height = MAX (max_min_height, line_min_height); max_natural_height = MAX (max_natural_height, line_natural_height); } else { clutter_actor_get_preferred_height (child, for_width, &child_min, &child_natural); max_min_height = MAX (max_min_height, child_min); max_natural_height = MAX (max_natural_height, child_natural); total_min_height += max_min_height; total_natural_height += max_natural_height; line_count += 1; } } g_list_free (children); priv->row_height = max_natural_height; if (priv->max_row_height > 0 && priv->row_height > priv->max_row_height) priv->row_height = MAX (priv->max_row_height, max_min_height); if (priv->row_height < priv->min_row_height) priv->row_height = priv->min_row_height; if (priv->orientation == CLUTTER_FLOW_HORIZONTAL && for_width > 0) { /* if we have a non-full row we need to add it */ if (line_item_count > 0) { total_min_height += line_min_height; total_natural_height += line_natural_height; g_array_append_val (priv->line_min, line_min_height); g_array_append_val (priv->line_natural, line_natural_height); } priv->line_count = line_count; if (priv->line_count > 0) { gfloat total_spacing; total_spacing = priv->row_spacing * (priv->line_count - 1); total_min_height += total_spacing; total_natural_height += total_spacing; } } else { g_array_append_val (priv->line_min, line_min_height); g_array_append_val (priv->line_natural, line_natural_height); priv->line_count = line_count; if (priv->line_count > 0) { gfloat total_spacing; total_spacing = priv->col_spacing * priv->line_count; total_min_height += total_spacing; total_natural_height += total_spacing; } } CLUTTER_NOTE (LAYOUT, "Flow[h]: %d lines (%d per line): w [ %.2f, %.2f ] for h %.2f", n_columns, priv->line_count, total_min_height, total_natural_height, for_width); if (min_height_p) *min_height_p = total_min_height; if (nat_height_p) *nat_height_p = total_natural_height; }
static void meta_window_group_paint (ClutterActor *actor) { cairo_region_t *visible_region; cairo_region_t *unredirected_window_region = NULL; ClutterActor *stage; cairo_rectangle_int_t visible_rect, unredirected_rect; GList *children, *l; MetaWindowGroup *window_group = META_WINDOW_GROUP (actor); MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen); if (info->unredirected_window != NULL) { meta_window_actor_get_shape_bounds (META_WINDOW_ACTOR (info->unredirected_window), &unredirected_rect); unredirected_window_region = cairo_region_create_rectangle (&unredirected_rect); } /* We walk the list from top to bottom (opposite of painting order), * and subtract the opaque area of each window out of the visible * region that we pass to the windows below. */ children = clutter_container_get_children (CLUTTER_CONTAINER (actor)); children = g_list_reverse (children); /* Get the clipped redraw bounds from Clutter so that we can avoid * painting shadows on windows that don't need to be painted in this * frame. In the case of a multihead setup with mismatched monitor * sizes, we could intersect this with an accurate union of the * monitors to avoid painting shadows that are visible only in the * holes. */ stage = clutter_actor_get_stage (actor); clutter_stage_get_redraw_clip_bounds (CLUTTER_STAGE (stage), &visible_rect); visible_region = cairo_region_create_rectangle (&visible_rect); if (unredirected_window_region) cairo_region_subtract (visible_region, unredirected_window_region); for (l = children; l; l = l->next) { if (!CLUTTER_ACTOR_IS_VISIBLE (l->data)) continue; /* If an actor has effects applied, then that can change the area * it paints and the opacity, so we no longer can figure out what * portion of the actor is obscured and what portion of the screen * it obscures, so we skip the actor. * * This has a secondary beneficial effect: if a ClutterOffscreenEffect * is applied to an actor, then our clipped redraws interfere with the * caching of the FBO - even if we only need to draw a small portion * of the window right now, ClutterOffscreenEffect may use other portions * of the FBO later. So, skipping actors with effects applied also * prevents these bugs. * * Theoretically, we should check clutter_actor_get_offscreen_redirect() * as well for the same reason, but omitted for simplicity in the * hopes that no-one will do that. */ if (clutter_actor_has_effects (l->data)) continue; if (META_IS_WINDOW_ACTOR (l->data)) { MetaWindowActor *window_actor = l->data; int x, y; if (!actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y)) continue; /* Temporarily move to the coordinate system of the actor */ cairo_region_translate (visible_region, - x, - y); meta_window_actor_set_visible_region (window_actor, visible_region); if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff) { cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor); if (obscured_region) cairo_region_subtract (visible_region, obscured_region); } meta_window_actor_set_visible_region_beneath (window_actor, visible_region); cairo_region_translate (visible_region, x, y); } else if (META_IS_BACKGROUND_ACTOR (l->data)) { MetaBackgroundActor *background_actor = l->data; meta_background_actor_set_visible_region (background_actor, visible_region); } } cairo_region_destroy (visible_region); if (unredirected_window_region) cairo_region_destroy (unredirected_window_region); CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor); /* Now that we are done painting, unset the visible regions (they will * mess up painting clones of our actors) */ for (l = children; l; l = l->next) { if (META_IS_WINDOW_ACTOR (l->data)) { MetaWindowActor *window_actor = l->data; window_actor = l->data; meta_window_actor_reset_visible_regions (window_actor); } else if (META_IS_BACKGROUND_ACTOR (l->data)) { MetaBackgroundActor *background_actor = l->data; meta_background_actor_set_visible_region (background_actor, NULL); } } g_list_free (children); }
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; }
/* snap size, as affected by resizing lower right corner, * will need extension if other corners are to be supported, * it seems possible to do all needed alignments through * simple workarounds when only snapping for lower right). */ static void snap_size (ClutterActor *actor, gfloat in_width, gfloat in_height, gfloat *out_width, gfloat *out_height) { *out_width = in_width; *out_height = in_height; ClutterActor *parent; parent = clutter_actor_get_parent (actor); if (CLUTTER_IS_CONTAINER (parent)) { gfloat in_x = clutter_actor_get_x (actor); gfloat in_y = clutter_actor_get_y (actor); gfloat in_end_x = in_x + in_width; gfloat in_end_y = in_y + in_height; gfloat best_x = 0; gfloat best_x_diff = 4096; gfloat best_y = 0; gfloat best_y_diff = 4096; GList *children, *c; children = clutter_container_get_children (CLUTTER_CONTAINER (parent)); hor_pos = 0; ver_pos = 0; /* We only search our siblings for snapping... * perhaps we should search more. */ for (c=children; c; c = c->next) { gfloat this_x = clutter_actor_get_x (c->data); gfloat this_width = clutter_actor_get_width (c->data); gfloat this_height = clutter_actor_get_height (c->data); gfloat this_end_x = this_x + this_width; gfloat this_y = clutter_actor_get_y (c->data); gfloat this_end_y = this_y + this_height; /* skip self */ if (c->data == actor) continue; /* end aligned with start this_x this_mid_x this_end_x in_x in_mid_x in_end_x */ if (abs (this_x - in_end_x) < best_x_diff) { best_x_diff = abs (this_x - in_end_x); best_x = this_x; hor_pos=3; } if (abs (this_y - in_end_y) < best_y_diff) { best_y_diff = abs (this_y - in_end_y); best_y = this_y; ver_pos=3; } /* ends aligned this_x this_mid_x this_end_x in_x in_mid_x in_end_x */ if (abs (this_end_x - in_end_x) < best_x_diff) { best_x_diff = abs (this_end_x - in_end_x); best_x = this_end_x; hor_pos=3; } if (abs (this_end_y - in_end_y) < best_y_diff) { best_y_diff = abs (this_end_y - in_end_y); best_y = this_end_y; ver_pos=3; } } { if (best_x_diff < SNAP_THRESHOLD) { *out_width = best_x-in_x; } else { hor_pos = 0; } if (best_y_diff < SNAP_THRESHOLD) { *out_height = best_y-in_y; } else { ver_pos = 0; } } } }
/* Private functions */ static void ensure_layout (AstroAppview *view) { AstroAppviewPrivate *priv; GList *l; gint groupx = 0; gint center = 0; gint i = 0; priv = view->priv; groupx = clutter_actor_get_x (CLUTTER_ACTOR (view)); center = CSW()/2; l = clutter_container_get_children (CLUTTER_CONTAINER (view)); for (l = l; l; l = l->next) { ClutterActor *icon = l->data; gint realx, diff, y_diff;; gfloat scale; realx = clutter_actor_get_x (icon) + groupx; if (realx > center && realx < CSW ()) { diff = center - (realx - center); } else if (realx > 0 && realx <= center) { diff = realx; } else { diff = 0; } scale = (gfloat)diff/center; scale = 0.2 + (0.8 * scale); clutter_actor_set_scale (icon, scale, scale); if (realx < center) { gfloat angle, sine; angle = scale * (3.14*2); sine = sin (0.5 *angle); y_diff = (CSH()/2) + (VARIANCE * sine); } else { gfloat angle, sine; angle = scale * (3.14*2); sine = sin (0.5*angle); y_diff = (CSH()/2) - (VARIANCE * sine); } clutter_actor_set_y (icon, y_diff); astro_appicon_set_blur (ASTRO_APPICON (icon), (1.0 - scale) * MAX_BLUR); i++; } }