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 void mex_content_box_toggle_open (MexContentBox *box) { MexContentBoxPrivate *priv = box->priv; gboolean close_notified, next_is_open; const gchar *mimetype; /* search history items should not appear in the "open" state */ mimetype = mex_content_get_metadata (priv->content, MEX_CONTENT_METADATA_MIMETYPE); if (!g_strcmp0 (mimetype, "x-mex/search")) return; /* if the close animation was cancelled then no notify for the closed state * will have been sent, therefore notify for the opened state does not need * to be emitted */ close_notified = (!priv->is_open && !clutter_timeline_is_playing (priv->timeline)); next_is_open = !priv->is_open; if (next_is_open) { /* opening */ clutter_timeline_set_direction (priv->timeline, CLUTTER_TIMELINE_FORWARD); mx_stylable_set_style_class (MX_STYLABLE (box), "open"); /* refresh the action list */ mex_content_view_set_content (MEX_CONTENT_VIEW (priv->action_list), priv->content); priv->extras_visible = TRUE; if (close_notified) g_object_notify_by_pspec (G_OBJECT (box), properties[PROP_OPEN]); mex_push_focus (MX_FOCUSABLE (priv->action_list)); } else { priv->is_closing = TRUE; /* closing */ mex_push_focus (MX_FOCUSABLE (priv->tile)); clutter_timeline_set_direction (priv->timeline, CLUTTER_TIMELINE_BACKWARD); priv->is_closing = FALSE; priv->extras_visible = TRUE; } if (!clutter_timeline_is_playing (priv->timeline)) clutter_timeline_rewind (priv->timeline); clutter_timeline_start (priv->timeline); priv->is_open = next_is_open; }
static gboolean mex_player_set_controls_visible (MexPlayer *player, gboolean visible) { MexPlayerPrivate *priv = player->priv; gfloat pos; ClutterStage *stage; MxFocusManager *fmanager; stage = (ClutterStage*) clutter_actor_get_stage (CLUTTER_ACTOR (player)); fmanager = mx_focus_manager_get_for_stage (stage); pos = clutter_actor_get_height (priv->controls); if (visible) { priv->controls_prev_visible = FALSE; priv->controls_visible = TRUE; mx_widget_set_disabled (MX_WIDGET (priv->controls), FALSE); clutter_actor_animate (priv->controls, CLUTTER_EASE_IN_SINE, 250, "opacity", 0xff, "anchor-y", 0.0, NULL); mex_player_restart_timer (player); if (priv->related_tile) { mx_focus_manager_push_focus_with_hint (fmanager, MX_FOCUSABLE (priv->related_tile), MX_FOCUS_HINT_PRIOR); g_object_unref (priv->related_tile); priv->related_tile = NULL; } else { mx_focus_manager_push_focus (fmanager, MX_FOCUSABLE (priv->controls)); } } if (!visible) { priv->controls_visible = FALSE; clutter_actor_animate (priv->controls, CLUTTER_EASE_IN_SINE, 250, "opacity", 0x00, "anchor-y", -pos, NULL); if (priv->hide_controls_source) { g_source_remove (priv->hide_controls_source); priv->hide_controls_source = 0; } } return TRUE; }
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 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; }
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; }
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; }
/** * mex_menu_add_action: * @menu: A #MexMenu * @action: A #MxAction * @type: The menu action type * * Adds a menu item to @menu at the current depth. @action must be a uniquely * named action, if an action with that name already exists in the menu, this * function will do nothing. */ void mex_menu_add_action (MexMenu *menu, MxAction *action, MexMenuActionType type) { ClutterActor *item; MexMenuPrivate *priv; g_return_if_fail (MEX_IS_MENU (menu)); g_return_if_fail (MX_IS_ACTION (action)); priv = menu->priv; if (mex_menu_find_action (menu, mx_action_get_name (action), NULL)) { g_warning (G_STRLOC ": Action '%s' is already contained in this menu", mx_action_get_name (action)); return; } item = mex_menu_item_new (menu, action, type); g_hash_table_insert (priv->action_to_item, action, item); clutter_container_add_actor (CLUTTER_CONTAINER (priv->action_layout), item); if (priv->focus_on_add) { mex_push_focus (MX_FOCUSABLE (item)); priv->focus_on_add = FALSE; } }
static void mx_menu_show (ClutterActor *actor) { ClutterAnimation *animation = NULL; ClutterStage *stage; /* set reactive and opacity, since these may have been set by the fade-out * animation (e.g. from captured_event_handler or button_release_cb) */ if ((animation = clutter_actor_get_animation (actor))) { clutter_animation_completed (animation); } clutter_actor_set_reactive (actor, TRUE); clutter_actor_set_opacity (actor, 0xff); /* chain up to run show after re-setting properties above */ CLUTTER_ACTOR_CLASS (mx_menu_parent_class)->show (actor); clutter_actor_grab_key_focus (actor); stage = (ClutterStage*) clutter_actor_get_stage (actor); mx_focus_manager_push_focus (mx_focus_manager_get_for_stage (stage), MX_FOCUSABLE (actor)); }
static void ntf_libnotify_update_modal (void) { NtfTray *tray = ntf_overlay_get_tray (TRUE); MetaPlugin *plugin = dawati_netbook_get_plugin_singleton (); if (ntf_tray_get_n_notifications (tray) > 0) { if (!overlay_focused) { MetaScreen *screen = meta_plugin_get_screen (plugin); ClutterActor *stage = meta_get_stage_for_screen (screen); MxFocusManager *manager = mx_focus_manager_get_for_stage (CLUTTER_STAGE (stage)); dawati_netbook_stash_window_focus (plugin, CurrentTime); mx_focus_manager_push_focus (manager, MX_FOCUSABLE (tray)); overlay_focused = TRUE; } } else { if (overlay_focused) { dawati_netbook_unstash_window_focus (plugin, CurrentTime); overlay_focused = FALSE; } } }
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; }
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); }
/* 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); }
static void mex_content_box_notify_open_cb (MexExpanderBox *box, GParamSpec *pspec) { GList *actions; ClutterStage *stage = CLUTTER_STAGE ( clutter_actor_get_stage (CLUTTER_ACTOR (box))); MxFocusManager *fmanager = mx_focus_manager_get_for_stage (stage); MexActionManager *manager = mex_action_manager_get_default (); MexContentBoxPrivate *priv = MEX_CONTENT_BOX (box)->priv; gboolean open = mex_expander_box_get_open (box); if (!open) { /* If the action list has focus, push it back onto the tile */ if (mex_actor_has_focus (fmanager, priv->action_list)) mx_focus_manager_push_focus (fmanager, MX_FOCUSABLE (priv->tile)); return; } /* Refresh the info panel and the action list */ mex_content_view_set_content (MEX_CONTENT_VIEW (priv->panel), priv->content); mex_action_list_refresh (MEX_ACTION_LIST (priv->action_list)); /* See if we have any actions */ actions = mex_action_manager_get_actions_for_content (manager, priv->content); /* Push focus onto the action list if we have actions, otherwise onto * the tile. */ if (actions) { clutter_actor_show (priv->action_list); mx_focus_manager_push_focus (fmanager, MX_FOCUSABLE (priv->action_list)); g_list_free (actions); } else { clutter_actor_hide (priv->action_list); mx_focus_manager_push_focus (fmanager, MX_FOCUSABLE (priv->tile)); } }
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; }
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); }
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); }
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); }
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; }
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; }
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); }
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; }
/* 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); }
static gboolean _close_dialog_cb (gpointer unused, MexInfoBar *self) { MexInfoBarPrivate *priv = self->priv; if (CLUTTER_ACTOR_IS_VISIBLE (priv->settings_dialog)) clutter_actor_hide (priv->settings_dialog); mex_push_focus (MX_FOCUSABLE (self)); return FALSE; }
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; }
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)); }
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; }
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; }
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 gboolean mex_content_box_tile_clicked_cb (ClutterActor *tile, ClutterButtonEvent *event, MexContentBox *self) { /* Because key based interactions moving the focus involve opening/closing the content box, we have to be careful about the order in which we change focus and open/close the box with mouse interactions. */ if (mex_content_box_get_open (self)) { mex_content_box_toggle_open (MEX_CONTENT_BOX (self)); mex_push_focus (MX_FOCUSABLE (tile)); } else { mex_push_focus (MX_FOCUSABLE (tile)); mex_content_box_toggle_open (MEX_CONTENT_BOX (self)); } return TRUE; }