示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
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;
}
示例#4
0
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;
}