static gboolean sagarmatha_stack_navigate_focus (StWidget *widget, ClutterActor *from, GtkDirectionType direction) { ClutterActor *top_actor; GList *children; /* If the stack is itself focusable, then focus into or out of * it, as appropriate. */ if (st_widget_get_can_focus (widget)) { if (from && clutter_actor_contains (CLUTTER_ACTOR (widget), from)) return FALSE; clutter_actor_grab_key_focus (CLUTTER_ACTOR (widget)); return TRUE; } /* Otherwise, navigate into its top-most child only */ children = st_container_get_children_list (ST_CONTAINER (widget)); if (!children) return FALSE; top_actor = g_list_last (children)->data; if (ST_IS_WIDGET (top_actor)) return st_widget_navigate_focus (ST_WIDGET (top_actor), from, direction, FALSE); else return FALSE; }
static gboolean shell_stack_navigate_focus (StWidget *widget, ClutterActor *from, GtkDirectionType direction) { ClutterActor *top_actor; /* If the stack is itself focusable, then focus into or out of * it, as appropriate. */ if (st_widget_get_can_focus (widget)) { if (from && clutter_actor_contains (CLUTTER_ACTOR (widget), from)) return FALSE; if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (widget))) { clutter_actor_grab_key_focus (CLUTTER_ACTOR (widget)); return TRUE; } else { return FALSE; } } top_actor = clutter_actor_get_last_child (CLUTTER_ACTOR (widget)); if (ST_IS_WIDGET (top_actor)) return st_widget_navigate_focus (ST_WIDGET (top_actor), from, direction, FALSE); else return FALSE; }
static gboolean st_bin_navigate_focus (StWidget *widget, ClutterActor *from, GtkDirectionType direction) { StBinPrivate *priv = ST_BIN (widget)->priv; ClutterActor *bin_actor = CLUTTER_ACTOR (widget); if (st_widget_get_can_focus (widget)) { if (from && clutter_actor_contains (bin_actor, from)) return FALSE; clutter_actor_grab_key_focus (bin_actor); return TRUE; } else if (priv->child && ST_IS_WIDGET (priv->child)) return st_widget_navigate_focus (ST_WIDGET (priv->child), from, direction, FALSE); else return FALSE; }
static gboolean st_entry_navigate_focus (StWidget *widget, ClutterActor *from, GtkDirectionType direction) { StEntryPrivate *priv = ST_ENTRY_PRIV (widget); /* This is basically the same as st_widget_real_navigate_focus(), * except that widget is behaving as a proxy for priv->entry (which * isn't an StWidget and so has no can-focus flag of its own). */ if (from == priv->entry) return FALSE; else if (st_widget_get_can_focus (widget)) { clutter_actor_grab_key_focus (priv->entry); return TRUE; } else return FALSE; }
static gboolean st_container_navigate_focus (StWidget *widget, ClutterActor *from, GtkDirectionType direction) { StContainer *container = ST_CONTAINER (widget); ClutterActor *container_actor, *focus_child; GList *children, *l; container_actor = CLUTTER_ACTOR (widget); if (from == container_actor) return FALSE; /* Figure out if @from is a descendant of @container, and if so, * set @focus_child to the immediate child of @container that * contains (or *is*) @from. */ focus_child = from; while (focus_child && clutter_actor_get_parent (focus_child) != container_actor) focus_child = clutter_actor_get_parent (focus_child); if (st_widget_get_can_focus (widget)) { if (!focus_child) { /* Accept focus from outside */ clutter_actor_grab_key_focus (container_actor); return TRUE; } else { /* Yield focus from within: since @container itself is * focusable we don't allow the focus to be navigated * within @container. */ return FALSE; } } /* See if we can navigate within @focus_child */ if (focus_child && ST_IS_WIDGET (focus_child)) { if (st_widget_navigate_focus (ST_WIDGET (focus_child), from, direction, FALSE)) return TRUE; } /* At this point we know that we want to navigate focus to one of * @container's immediate children; the next one after @focus_child, * or the first one if @focus_child is %NULL. (With "next" and * "first" being determined by @direction.) */ children = st_container_get_focus_chain (container); if (direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD) { if (direction == GTK_DIR_TAB_BACKWARD) children = g_list_reverse (children); if (focus_child) { /* Remove focus_child and any earlier children */ while (children && children->data != focus_child) children = g_list_delete_link (children, children); if (children) children = g_list_delete_link (children, children); } } else /* direction is an arrow key, not tab */ { StContainerChildSortData sort_data; /* Compute the allocation box of the previous focused actor, in * @container's coordinate space. If there was no previous focus, * use the coordinates of the appropriate edge of @container. * * Note that all of this code assumes the actors are not * transformed (or at most, they are all scaled by the same * amount). If @container or any of its children is rotated, or * any child is inconsistently scaled, then the focus chain will * probably be unpredictable. */ if (focus_child) { clutter_actor_get_allocation_box (focus_child, &sort_data.box); } else { clutter_actor_get_allocation_box (CLUTTER_ACTOR (container), &sort_data.box); switch (direction) { case GTK_DIR_UP: sort_data.box.y1 = sort_data.box.y2; break; case GTK_DIR_DOWN: sort_data.box.y2 = sort_data.box.y1; break; case GTK_DIR_LEFT: sort_data.box.x1 = sort_data.box.x2; break; case GTK_DIR_RIGHT: sort_data.box.x2 = sort_data.box.x1; break; default: g_warn_if_reached (); } } sort_data.direction = direction; if (focus_child) children = filter_by_position (children, &sort_data.box, direction); if (children) children = g_list_sort_with_data (children, sort_by_position, &sort_data); } /* Now try each child in turn */ for (l = children; l; l = l->next) { if (ST_IS_WIDGET (l->data)) { if (st_widget_navigate_focus (l->data, from, direction, FALSE)) { g_list_free (children); return TRUE; } } } g_list_free (children); return FALSE; }