Exemplo n.º 1
0
static MxFocusable*
mex_content_box_move_focus (MxFocusable      *focusable,
                            MxFocusDirection  direction,
                            MxFocusable      *from)
{
  MexContentBoxPrivate *priv = MEX_CONTENT_BOX (focusable)->priv;
  MxFocusable *result = NULL;

  if (priv->is_open)
    {
      if (direction == MX_FOCUS_DIRECTION_RIGHT &&
          (ClutterActor *) from != priv->action_list)
        result = mx_focusable_accept_focus (MX_FOCUSABLE (priv->action_list), 0);
      else if (direction == MX_FOCUS_DIRECTION_LEFT &&
               (ClutterActor *) from != priv->tile)
        result = mx_focusable_accept_focus (MX_FOCUSABLE (priv->tile), 0);

      if (result == NULL)
        {
          /* close the content box if it is open */
          if (priv->is_open && !priv->is_closing)
            mex_content_box_toggle_open (MEX_CONTENT_BOX (focusable));
        }
    }

  return result;
}
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;
}
Exemplo n.º 3
0
static MxFocusable *
mex_column_move_focus (MxFocusable      *focusable,
                       MxFocusDirection  direction,
                       MxFocusable      *from)
{
  MxFocusHint hint;

  GList *link_ = NULL;
  MexColumn *self = MEX_COLUMN (focusable);
  MexColumnPrivate *priv = self->priv;

  focusable = NULL;

  link_ = g_list_find (priv->children, from);
  if (!link_)
    return NULL;

  switch (direction)
    {
    case MX_FOCUS_DIRECTION_PREVIOUS:
    case MX_FOCUS_DIRECTION_UP:
      hint = (direction == MX_FOCUS_DIRECTION_PREVIOUS) ?
        MX_FOCUS_HINT_LAST : MX_FOCUS_HINT_FROM_BELOW;
      link_ = g_list_previous (link_);
      if (link_)
        focusable = mx_focusable_accept_focus (
                       MX_FOCUSABLE (link_->data), hint);
      break;

    case MX_FOCUS_DIRECTION_NEXT:
    case MX_FOCUS_DIRECTION_DOWN:
      hint = (direction == MX_FOCUS_DIRECTION_NEXT) ?
        MX_FOCUS_HINT_FIRST : MX_FOCUS_HINT_FROM_ABOVE;
      link_ = g_list_next (link_);

      if (link_)
        focusable = mx_focusable_accept_focus (
                       MX_FOCUSABLE (link_->data), hint);
      break;

    case MX_FOCUS_DIRECTION_OUT:
      if (from &&
          (clutter_actor_get_parent (CLUTTER_ACTOR (from)) ==
           CLUTTER_ACTOR (self)))
        priv->current_focus = CLUTTER_ACTOR (from);
      break;

    default:
      break;
    }

  return focusable;
}
Exemplo n.º 4
0
static MxFocusable *
mex_column_view_accept_focus (MxFocusable *focusable,
                              MxFocusHint  hint)
{
  MexColumnView *self = MEX_COLUMN_VIEW (focusable);
  MexColumnViewPrivate *priv = self->priv;

  focusable = NULL;

  switch (hint)
    {
    case MX_FOCUS_HINT_FROM_LEFT:
    case MX_FOCUS_HINT_FROM_RIGHT:
    case MX_FOCUS_HINT_PRIOR:
      if (priv->current_focus &&
          (focusable = mx_focusable_accept_focus (
             MX_FOCUSABLE (priv->current_focus), hint)))
        break;
      /* If there's no prior focus, or the prior focus rejects focus,
       * try to just focus the first actor.
       */

    case MX_FOCUS_HINT_FIRST:
    case MX_FOCUS_HINT_FROM_ABOVE:
      if ((focusable =
           mx_focusable_accept_focus (MX_FOCUSABLE (priv->header), hint)))
        priv->current_focus = priv->header;
      else if (!mex_column_is_empty (MEX_COLUMN (priv->column)) &&
               (focusable =
                mx_focusable_accept_focus (MX_FOCUSABLE (priv->column),
                                           hint)))
        priv->current_focus = priv->column;
      break;

    case MX_FOCUS_HINT_LAST:
    case MX_FOCUS_HINT_FROM_BELOW:
      if (!mex_column_is_empty (MEX_COLUMN (priv->column))
          && (focusable =
              mx_focusable_accept_focus (MX_FOCUSABLE (priv->column), hint)))
        priv->current_focus = priv->column;
      else if ((focusable =
                mx_focusable_accept_focus (MX_FOCUSABLE (priv->header), hint)))
        priv->current_focus = priv->header;
      break;
    }

  return focusable;
}
Exemplo n.º 5
0
static MxFocusable *
mex_column_accept_focus (MxFocusable *focusable,
                         MxFocusHint  hint)
{
  GList *link_;

  MexColumn *self = MEX_COLUMN (focusable);
  MexColumnPrivate *priv = self->priv;

  focusable = NULL;

  switch (hint)
    {
    case MX_FOCUS_HINT_FROM_LEFT:
    case MX_FOCUS_HINT_FROM_RIGHT:
    case MX_FOCUS_HINT_PRIOR:
      if (priv->current_focus &&
          (focusable = mx_focusable_accept_focus (
             MX_FOCUSABLE (priv->current_focus), hint)))
        break;
      /* If there's no prior focus, or the prior focus rejects focus,
       * try to just focus the first actor.
       */

    case MX_FOCUS_HINT_FIRST:
    case MX_FOCUS_HINT_FROM_ABOVE:
      if ((focusable = mx_focusable_accept_focus (MX_FOCUSABLE (priv->header),
                                                  hint)))
        priv->current_focus = priv->header;
      else if (priv->n_items &&
               (focusable = mx_focusable_accept_focus (
                  MX_FOCUSABLE (priv->children->data), hint)))
        priv->current_focus = priv->children->data;
      break;

    case MX_FOCUS_HINT_LAST:
    case MX_FOCUS_HINT_FROM_BELOW:
      link_ = g_list_last (priv->children);
      if (link_ && (focusable = mx_focusable_accept_focus (
                     MX_FOCUSABLE (link_->data), hint)))
        {
          priv->current_focus = link_->data;
          break;
        }
    }

  return focusable;
}
Exemplo n.º 6
0
static MxFocusable *
mex_epg_grid_accept_focus (MxFocusable *focusable,
                           MxFocusHint  hint)
{
  MexEpgGrid *grid = MEX_EPG_GRID (focusable);
  MexEpgGridPrivate *priv = grid->priv;
  MxFocusable *focused, *focused_tile;
  GPtrArray *focused_row;

  if (priv->focused_row_idx == -1)
    {
      priv->has_focus_but_no_tile = TRUE;
      return focusable;
    }

  focused_row = g_ptr_array_index (priv->rows, priv->focused_row_idx);
  if (G_UNLIKELY (focused_row == NULL))
    {
      priv->has_focus_but_no_tile = TRUE;
      return focusable;
    }

  focused_tile = g_ptr_array_index (focused_row, 0);

  update_focused_date (grid, MEX_EPG_TILE (focused_tile));

  focused = mx_focusable_accept_focus (focused_tile, hint);


  g_signal_emit (focusable, signals[SIGNAL_ROW_SELECTED], 0, 0);

  return focused;
}
Exemplo n.º 7
0
/* focusable implementation */
static MxFocusable *
mex_grid_view_accept_focus (MxFocusable *focusable,
                            MxFocusHint  hint)
{
  MexGridViewPrivate *priv = MEX_GRID_VIEW (focusable)->priv;

  return mx_focusable_accept_focus (MX_FOCUSABLE (priv->grid_layout), hint);
}
Exemplo n.º 8
0
static MxFocusable *
mex_column_view_move_focus (MxFocusable      *focusable,
                            MxFocusDirection  direction,
                            MxFocusable      *from)
{
  MxFocusHint hint;
  MexColumnView *self = MEX_COLUMN_VIEW (focusable);
  MexColumnViewPrivate *priv = self->priv;

  focusable = NULL;

  switch (direction)
    {
    case MX_FOCUS_DIRECTION_NEXT:
    case MX_FOCUS_DIRECTION_DOWN:
      if (((ClutterActor *) from == priv->header) &&
          !mex_column_is_empty (MEX_COLUMN (priv->column)))
        {
          hint = (direction == MX_FOCUS_DIRECTION_NEXT) ?
            MX_FOCUS_HINT_FIRST : MX_FOCUS_HINT_FROM_ABOVE;
          focusable = mx_focusable_accept_focus (MX_FOCUSABLE (priv->scroll),
                                                 hint);
          if (focusable)
            priv->current_focus = priv->scroll;
        }
      break;

    case MX_FOCUS_DIRECTION_PREVIOUS:
    case MX_FOCUS_DIRECTION_UP:
      if ((ClutterActor *) from == priv->scroll)
        {
          hint = (direction == MX_FOCUS_DIRECTION_NEXT) ?
            MX_FOCUS_HINT_FIRST : MX_FOCUS_HINT_FROM_ABOVE;
          focusable = mx_focusable_accept_focus (MX_FOCUSABLE (priv->header),
                                                 hint);
          if (focusable)
            priv->current_focus = priv->header;
        }
      break;

    default:
      break;
    }

  return focusable;
}
Exemplo n.º 9
0
static MxFocusable*
mex_music_player_accept_focus (MxFocusable *focusable,
                               MxFocusHint  hint)
{
  MexMusicPlayerPrivate *priv = MEX_MUSIC_PLAYER (focusable)->priv;

  return mx_focusable_accept_focus (MX_FOCUSABLE (priv->play_button), hint);
}
Exemplo n.º 10
0
static MxFocusable *
mex_media_controls_accept_focus (MxFocusable *focusable,
                                 MxFocusHint  hint)
{
    MexMediaControlsPrivate *priv = MEX_MEDIA_CONTROLS (focusable)->priv;

    return mx_focusable_accept_focus (MX_FOCUSABLE (priv->vbox),
                                      MX_FOCUS_HINT_FIRST);
}
Exemplo n.º 11
0
static MxFocusable *
mex_info_bar_accept_focus (MxFocusable *focusable,
                           MxFocusHint  hint)
{
  MexInfoBarPrivate *priv = MEX_INFO_BAR (focusable)->priv;

  return mx_focusable_accept_focus (MX_FOCUSABLE (priv->group),
                                    MX_FOCUS_HINT_FIRST);
}
Exemplo n.º 12
0
static MxFocusable *
mex_grid_view_move_focus (MxFocusable      *focusable,
                          MxFocusDirection  direction,
                          MxFocusable      *from)
{
  MexGridViewPrivate *priv = MEX_GRID_VIEW (focusable)->priv;

  if (direction == MX_FOCUS_DIRECTION_LEFT
      && from == MX_FOCUSABLE (priv->grid_layout))
    return mx_focusable_accept_focus (MX_FOCUSABLE (priv->menu_layout),
                                      MX_FOCUS_HINT_PRIOR);
  else if (direction == MX_FOCUS_DIRECTION_RIGHT
           && from == MX_FOCUSABLE (priv->menu_layout))
    return mx_focusable_accept_focus (MX_FOCUSABLE (priv->grid_layout),
                                      MX_FOCUS_HINT_PRIOR);
  else
    return NULL;
}
Exemplo n.º 13
0
static MxFocusable*
mx_bin_accept_focus (MxFocusable *focusable, MxFocusHint hint)
{
  MxBinPrivate *priv = MX_BIN (focusable)->priv;

  if (MX_IS_FOCUSABLE (priv->child))
    return mx_focusable_accept_focus (MX_FOCUSABLE (priv->child), hint);
  else
    return NULL;
}
Exemplo n.º 14
0
static MxFocusable *
mex_shell_accept_focus (MxFocusable *focusable, MxFocusHint hint)
{
  MexShellPrivate *priv = MEX_SHELL (focusable)->priv;

  if (priv->presented)
    return mx_focusable_accept_focus (MX_FOCUSABLE (priv->presented), hint);
  else
    return NULL;
}
Exemplo n.º 15
0
static MxFocusable *
ntf_tray_accept_focus (MxFocusable *focusable, MxFocusHint hint)
{
  NtfTrayPrivate *priv = NTF_TRAY (focusable)->priv;

  if (!priv->active_notifier)
    return NULL;

  return mx_focusable_accept_focus (MX_FOCUSABLE (priv->active_notifier), hint);
}
Exemplo n.º 16
0
/* MxFocusableIface */
static MxFocusable*
mex_content_box_accept_focus (MxFocusable *focusable,
                              MxFocusHint  hint)
{
  MexContentBoxPrivate *priv = MEX_CONTENT_BOX (focusable)->priv;
  MxFocusable *focus = MX_FOCUSABLE (priv->tile);

  clutter_actor_grab_key_focus (CLUTTER_ACTOR (focusable));

  return mx_focusable_accept_focus (focus, hint);
}
Exemplo n.º 17
0
static MxFocusable *
mx_notebook_accept_focus (MxFocusable *focusable,
                          MxFocusHint  hint)
{
  MxNotebookPrivate *priv = MX_NOTEBOOK (focusable)->priv;

  if (priv->current_page && MX_IS_FOCUSABLE (priv->current_page))
    return mx_focusable_accept_focus (MX_FOCUSABLE (priv->current_page), hint);
  else
    return NULL;
}
Exemplo n.º 18
0
static MxFocusable*
mx_menu_accept_focus (MxFocusable *focusable,
                      MxFocusHint  hint)
{
    MxMenuPrivate *priv = MX_MENU (focusable)->priv;
    MxMenuChild *child;

    child = &g_array_index (priv->children, MxMenuChild, 0);

    return mx_focusable_accept_focus (MX_FOCUSABLE (child->box), 0);
}
Exemplo n.º 19
0
static MxFocusable *
mx_toolbar_move_focus (MxFocusable      *self,
                       MxFocusDirection  direction,
                       MxFocusable      *from)
{
  MxFocusable *focusable;
  MxToolbarPrivate *priv = MX_TOOLBAR (self)->priv;

  if (priv->child && !MX_IS_FOCUSABLE (priv->child))
    priv->child = NULL;

  focusable = NULL;
  switch (direction)
    {
    case MX_FOCUS_DIRECTION_LEFT:
    case MX_FOCUS_DIRECTION_PREVIOUS:
      if (!priv->child_has_focus && priv->child)
        {
          priv->child_has_focus = TRUE;
          focusable = mx_focusable_accept_focus (MX_FOCUSABLE (priv->child),
                                                 MX_FOCUS_HINT_LAST);
        }
      break;

    case MX_FOCUS_DIRECTION_RIGHT:
    case MX_FOCUS_DIRECTION_NEXT:
      if (priv->child_has_focus && priv->has_close_button)
        {
          priv->child_has_focus = FALSE;
          focusable =
            mx_focusable_accept_focus (MX_FOCUSABLE (priv->close_button),
                                       MX_FOCUS_HINT_FIRST);
        }

    default:
      break;
    }

  return focusable;
}
Exemplo n.º 20
0
static MxFocusable *
ntf_tray_move_focus (MxFocusable      *focusable,
                     MxFocusDirection  direction,
                     MxFocusable      *from)
{
  NtfTrayPrivate *priv = NTF_TRAY (focusable)->priv;

  if (!priv->active_notifier)
    return NULL;

  return mx_focusable_accept_focus (MX_FOCUSABLE (priv->active_notifier),
                                    mx_focus_hint_from_direction (direction));
}
Exemplo n.º 21
0
static MxFocusable *
mex_info_bar_accept_focus (MxFocusable *focusable,
                           MxFocusHint  hint)
{
  MexInfoBarPrivate *priv = MEX_INFO_BAR (focusable)->priv;

  MxFocusable *result;

  ClutterActor *buttons_area;

 buttons_area =
    CLUTTER_ACTOR (clutter_script_get_object (priv->script, "buttons-area"));

  /* try the previous focusable first */
  result = mx_focusable_accept_focus (MX_FOCUSABLE (buttons_area),
                                      MX_FOCUS_HINT_PRIOR);

  if (!result)
    result = mx_focusable_accept_focus (MX_FOCUSABLE (buttons_area),
                                        MX_FOCUS_HINT_FIRST);

  return result;
}
Exemplo n.º 22
0
static MxFocusable *
mx_toolbar_accept_focus (MxFocusable *self,
                         MxFocusHint  hint)
{
  MxFocusable *focusable;
  MxToolbarPrivate *priv = MX_TOOLBAR (self)->priv;

  if (priv->child && !MX_IS_FOCUSABLE (priv->child))
    priv->child = NULL;

  focusable = NULL;
  switch (hint)
    {
    default:
    case MX_FOCUS_HINT_PRIOR:
      if (priv->child && priv->child_has_focus)
        focusable = mx_focusable_accept_focus (MX_FOCUSABLE (priv->child), hint);
      if (focusable)
        break;

    case MX_FOCUS_HINT_LAST:
      priv->child_has_focus = FALSE;
      if (priv->has_close_button)
        focusable =
          mx_focusable_accept_focus (MX_FOCUSABLE (priv->close_button), hint);
      if (focusable)
        break;

    case MX_FOCUS_HINT_FIRST:
      priv->child_has_focus = TRUE;
      if (priv->child)
        focusable = mx_focusable_accept_focus (MX_FOCUSABLE (priv->child), hint);
      break;
    }

  return focusable;
}
Exemplo n.º 23
0
static MxFocusable*
mx_table_accept_focus (MxFocusable *focusable, MxFocusHint hint)
{
  MxTablePrivate *priv = MX_TABLE (focusable)->priv;
  MxFocusable *return_focusable;
  GList* list, *l, *children;

  return_focusable = NULL;

  children = clutter_actor_get_children (CLUTTER_ACTOR (focusable));

  /* find the first/last focusable widget */
  switch (hint)
    {
    case MX_FOCUS_HINT_LAST:
      list = g_list_reverse (g_list_copy (children));
      break;

    case MX_FOCUS_HINT_PRIOR:
      if (priv->last_focus)
        {
          list = g_list_copy (g_list_find (children, priv->last_focus));
          if (list)
            break;
        }
      /* This intentionally runs into the next switch case */

    default:
    case MX_FOCUS_HINT_FIRST:
      list = g_list_copy (children);
      break;
    }

  for (l = list; l; l = g_list_next (l))
    {
      if (MX_IS_FOCUSABLE (l->data))
        {
          return_focusable = mx_focusable_accept_focus (MX_FOCUSABLE (l->data),
                                                        hint);
          if (return_focusable)
            break;
        }
    }

  g_list_free (list);
  g_list_free (children);

  return return_focusable;
}
static MxFocusable *
mx_stack_move_focus (MxFocusable      *focusable,
                    MxFocusDirection  direction,
                    MxFocusable      *from)
{
  GList *c;

  MxStackPrivate *priv = MX_STACK (focusable)->priv;

  if (direction == MX_FOCUS_DIRECTION_OUT)
    return NULL;

  focusable = NULL;

  c = g_list_find (priv->children, from);
  while (c && !focusable)
    {
      ClutterActor *child;

      switch (direction)
        {
        case MX_FOCUS_DIRECTION_PREVIOUS :
        case MX_FOCUS_DIRECTION_LEFT :
        case MX_FOCUS_DIRECTION_UP :
          c = c->prev;
          break;
        default:
          c = c->next;
          break;
        }

      if (!c)
        continue;

      child = c->data;
      if (!MX_IS_FOCUSABLE (child))
        continue;

      focusable = mx_focusable_accept_focus (MX_FOCUSABLE (child),
                                             MX_FOCUS_HINT_PRIOR);
      if (focusable)
        priv->current_focus = child;
    }

  return focusable;
}
Exemplo n.º 25
0
static MxFocusable *
mex_epg_grid_move_focus (MxFocusable      *focusable,
                         MxFocusDirection  direction,
                         MxFocusable      *from)
{
  MexEpgGrid *grid = MEX_EPG_GRID (focusable);
  MexEpgGridPrivate *priv = grid->priv;
  MxFocusable *new_focused = NULL;
  GPtrArray *focused_row;
  MexEpgEvent *event;
  MxFocusHint hint = MX_FOCUS_HINT_FIRST;;
  gint new_tile_position = -1;

  focused_row = g_ptr_array_index (priv->rows, priv->focused_row_idx);
  if (focused_row == NULL)
    return NULL;

  /* just ignore the move if there is no tile in the grid */
  if (priv->has_focus_but_no_tile)
    return NULL;

  switch (direction)
    {
    case MX_FOCUS_DIRECTION_RIGHT:
    case MX_FOCUS_DIRECTION_NEXT:
      if (priv->focused_tile_idx == focused_row->len - 1)
          return NULL;

      priv->focused_tile_idx++;
      new_focused = g_ptr_array_index (focused_row, priv->focused_tile_idx);

      update_focused_date (grid, MEX_EPG_TILE (new_focused));
      break;

    case MX_FOCUS_DIRECTION_LEFT:
    case MX_FOCUS_DIRECTION_PREVIOUS:
      if (priv->focused_tile_idx == 0)
          return NULL;

      priv->focused_tile_idx--;
      new_focused = g_ptr_array_index (focused_row, priv->focused_tile_idx);

      update_focused_date (grid, MEX_EPG_TILE (new_focused));
      break;

    case MX_FOCUS_DIRECTION_UP:
      if (priv->focused_row_idx == 0)
        return NULL;

      /* from can be either the EpgGrid itself or an EpgTile */
      if (MEX_IS_EPG_TILE (from))
        {
          event = mex_epg_tile_get_event (MEX_EPG_TILE (from));
          new_tile_position = find_similar_event (grid,
                                                  priv->focused_row_idx - 1,
                                                  event);
        }

      if (new_tile_position == -1)
        return NULL;

      priv->focused_row_idx--;
      priv->focused_tile_idx = new_tile_position;
      focused_row = g_ptr_array_index (priv->rows, priv->focused_row_idx);
      new_focused = g_ptr_array_index (focused_row, priv->focused_tile_idx);

      g_signal_emit (focusable, signals[SIGNAL_ROW_SELECTED], 0,
                     priv->focused_row_idx);
      break;

    case MX_FOCUS_DIRECTION_DOWN:
      if (priv->focused_row_idx == priv->rows->len - 1)
        return NULL;

      /* from can be either the EpgGrid itself or an EpgTile */
      if (MEX_IS_EPG_TILE (from))
        {
          event = mex_epg_tile_get_event (MEX_EPG_TILE (from));
          new_tile_position = find_similar_event (grid,
                                                  priv->focused_row_idx + 1,
                                                  event);
        }

      if (new_tile_position == -1)
        return NULL;

      priv->focused_row_idx++;
      priv->focused_tile_idx = new_tile_position;
      focused_row = g_ptr_array_index (priv->rows, priv->focused_row_idx);
      new_focused = g_ptr_array_index (focused_row, priv->focused_tile_idx);

      g_signal_emit (focusable, signals[SIGNAL_ROW_SELECTED], 0,
                     priv->focused_row_idx);
      break;

    case MX_FOCUS_DIRECTION_OUT:
      priv->has_focus_but_no_tile = FALSE;
      break;

    default:
      break;
    }

  if (new_focused)
    return mx_focusable_accept_focus (new_focused, hint);

  return NULL;
}
Exemplo n.º 26
0
static MxFocusable*
mx_table_move_focus (MxFocusable      *focusable,
                     MxFocusDirection  direction,
                     MxFocusable      *from)
{
  MxTablePrivate *priv = MX_TABLE (focusable)->priv;
  MxTable *table = MX_TABLE (focusable);
  GList *l, *childlink, *children;
  MxTableChild *child_meta;
  ClutterActor *child_actor;
  MxFocusable *focused;
  gint row, column;
  ClutterActor *found;

  /* find the current focus */

  child_actor = CLUTTER_ACTOR (from);
  child_meta = (MxTableChild *) clutter_container_get_child_meta (CLUTTER_CONTAINER (focusable),
                                                                  child_actor);

  if (!child_meta)
    return NULL;

  priv->last_focus = from;


  /* find the next widget to focus */
  switch (direction)
    {
    case MX_FOCUS_DIRECTION_NEXT:
      children = clutter_actor_get_children (CLUTTER_ACTOR (focusable));
      childlink = g_list_find (children, from);

      for (l = childlink->next; l; l = g_list_next (l))
        {
          if (MX_IS_FOCUSABLE (l->data))
            {
              focused = mx_focusable_accept_focus (MX_FOCUSABLE (l->data),
                                                   MX_FOCUS_HINT_FIRST);

              if (focused)
                {
                  g_list_free (children);
                  return focused;
                }
            }
        }

      /* no next widgets to focus */
      g_list_free (children);
      return NULL;

    case MX_FOCUS_DIRECTION_PREVIOUS:

      children = clutter_actor_get_children (CLUTTER_ACTOR (focusable));
      childlink = g_list_find (children, from);
      for (l = g_list_previous (childlink); l; l = g_list_previous (l))
        {
          if (MX_IS_FOCUSABLE (l->data))
            {
              focused = mx_focusable_accept_focus (MX_FOCUSABLE (l->data),
                                                   MX_FOCUS_HINT_LAST);

              if (focused)
                {
                  g_list_free (children);
                  return focused;
                }
            }
        }

      /* no widget found in the previous position */
      g_list_free (children);
      return NULL;

    case MX_FOCUS_DIRECTION_UP:
      /* move focus up */

      row = child_meta->row - 1;
      column = child_meta->col;

      focused = NULL;

      while (!focused && row >= 0)
        {
          found = mx_table_find_actor_at (table, row, column);

          if (found)
            {
              if (MX_IS_FOCUSABLE (found))
                {
                  focused = mx_focusable_accept_focus (MX_FOCUSABLE (found),
                                                       MX_FOCUS_HINT_FIRST);
                  if (focused)
                    break;
                }

              child_meta = (MxTableChild *) clutter_container_get_child_meta
                (CLUTTER_CONTAINER (focusable), found);

              /* row might not be the top row if @found is a spanned actor */
              row = child_meta->row - 1;
            }
          else
            row --;
        }

      return focused;


    case MX_FOCUS_DIRECTION_DOWN:
      /* move focus down */

      row = child_meta->row + child_meta->row_span;
      column = child_meta->col;

      focused = NULL;

      while (!focused && row < priv->n_rows)
        {
          found = mx_table_find_actor_at (table, row, column);

          if (found)
            {
              if (MX_IS_FOCUSABLE (found))
                {
                  focused = mx_focusable_accept_focus (MX_FOCUSABLE (found),
                                                       MX_FOCUS_HINT_FIRST);
                  if (focused)
                    break;
                }

              child_meta = (MxTableChild *) clutter_container_get_child_meta
                (CLUTTER_CONTAINER (focusable), found);

              row = child_meta->row + child_meta->row_span;
            }
          else
            row ++;
        }

      return focused;


    case MX_FOCUS_DIRECTION_LEFT:
      /* move focus left */

      row = child_meta->row;
      column = child_meta->col - 1;

      focused = NULL;

      while (!focused && column >= 0)
        {
          found = mx_table_find_actor_at (table, row, column);

          if (found)
            {
              if (MX_IS_FOCUSABLE (found))
                {
                  focused = mx_focusable_accept_focus (MX_FOCUSABLE (found),
                                                       MX_FOCUS_HINT_FIRST);
                  if (focused)
                    break;
                }

              child_meta = (MxTableChild *) clutter_container_get_child_meta
                (CLUTTER_CONTAINER (focusable), found);

              /* col might not be the first column if @found is a spanned actor */
              column = child_meta->col - 1;
            }
          else
            column --;
        }

      return focused;


    case MX_FOCUS_DIRECTION_RIGHT:
      /* move focus right */

      row = child_meta->row;
      column = child_meta->col + child_meta->col_span;

      focused = NULL;

      while (!focused && column < priv->n_cols)
        {
          found = mx_table_find_actor_at (table, row, column);

          if (found)
            {
              if (MX_IS_FOCUSABLE (found))
                {
                  focused = mx_focusable_accept_focus (MX_FOCUSABLE (found),
                                                       MX_FOCUS_HINT_FIRST);
                  if (focused)
                    break;
                }

              child_meta = (MxTableChild *) clutter_container_get_child_meta
                (CLUTTER_CONTAINER (focusable), found);

              column = child_meta->col + child_meta->col_span;
            }
          else
            column ++;
        }

      return focused;

    default:
      break;
    }

  return NULL;
}
Exemplo n.º 27
0
static MxFocusable*
mx_menu_move_focus (MxFocusable      *focusable,
                    MxFocusDirection  direction,
                    MxFocusable      *from)
{
    MxMenuPrivate *priv = MX_MENU (focusable)->priv;
    MxFocusable *result;
    MxMenuChild *child;
    gint i, start;

    /* find the current focused child */
    for (i = 0; i < priv->children->len; i++)
    {
        child = &g_array_index (priv->children, MxMenuChild, i);
        if ((MxFocusable*) child->box == from)
            break;
        else
            child = NULL;
    }

    if (!child)
        return NULL;

    start = i;

    switch (direction)
    {
    case MX_FOCUS_DIRECTION_UP:
        if (i == 0)
        {
            i = priv->children->len - 1;
            gint nb_elts = priv->last_shown_id - priv->id_offset;
            priv->id_offset = i - nb_elts;
            clutter_actor_queue_redraw (CLUTTER_ACTOR(focusable));
        }
        else
        {
            i--;
            if (i < priv->id_offset)
            {
                priv->id_offset--;
                clutter_actor_queue_redraw (CLUTTER_ACTOR(focusable));
            }
        }

        while (i >= 0)
        {
            if (i == start)
                break;

            child = &g_array_index (priv->children, MxMenuChild, i);

            result = mx_focusable_accept_focus (MX_FOCUSABLE (child->box), 0);

            if (result)
                return result;

            /* loop */
            if (i == 0)
                i = priv->children->len;

            i--;
        }


    case MX_FOCUS_DIRECTION_DOWN:
        if (i == priv->children->len - 1)
        {
            priv->id_offset = 0;
            i = 0;
            clutter_actor_queue_redraw (CLUTTER_ACTOR(focusable));
        }
        else
        {
            i++;
            if (i > priv->last_shown_id)
            {
                priv->id_offset++;
                clutter_actor_queue_redraw (CLUTTER_ACTOR(focusable));
            }
        }

        while (i < priv->children->len)
        {
            if (i == start)
                break;

            child = &g_array_index (priv->children, MxMenuChild, i);

            result = mx_focusable_accept_focus (MX_FOCUSABLE (child->box), 0);

            if (result)
                return result;

            /* loop */
            if (i == priv->children->len - 1)
                i = -1;

            i++;
        }

    case MX_FOCUS_DIRECTION_OUT:
        if (priv->internal_focus_push)
        {
            /* do nothing if this notification was caused internally */
            priv->internal_focus_push = FALSE;
            return NULL;
        }

    default:
        break;
    }

    clutter_actor_hide (CLUTTER_ACTOR (focusable));
    return NULL;
}