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 gboolean _enter_event_cb (ClutterActor *actor, ClutterCrossingEvent *event, gpointer data) { MxFocusable *focusable; MxFocusManager *f_manager; f_manager = mx_focus_manager_get_for_stage (CLUTTER_STAGE (clutter_actor_get_stage (actor))); focusable = mx_focus_manager_get_focused (f_manager); /* hide the hover state on a button that has accepted focus via the default * focus as we're navigating by mouse and not keys we don't want to move * the focus as we may still want it in the place e.g. search bar */ if ((focusable) && (MNB_IS_LAUNCHER_BUTTON (focusable)) && (CLUTTER_ACTOR (focusable) != actor)) mx_stylable_set_style_pseudo_class (MX_STYLABLE (focusable), NULL); mx_stylable_set_style_pseudo_class (MX_STYLABLE (actor), "hover"); return FALSE; }
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 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 void mex_column_unmap (ClutterActor *actor) { MxFocusManager *manager = mx_focus_manager_get_for_stage ((ClutterStage *) clutter_actor_get_stage (actor)); g_signal_handlers_disconnect_by_func (manager, mex_column_notify_focused_cb, actor); CLUTTER_ACTOR_CLASS (mex_column_parent_class)->unmap (actor); }
static void mex_column_map (ClutterActor *actor) { MxFocusManager *manager; MexColumn *self = MEX_COLUMN (actor); CLUTTER_ACTOR_CLASS (mex_column_parent_class)->map (actor); manager = mx_focus_manager_get_for_stage ((ClutterStage *) clutter_actor_get_stage (actor)); g_signal_connect (manager, "notify::focused", G_CALLBACK (mex_column_notify_focused_cb), actor); mex_column_notify_focused_cb (manager, NULL, self); }
static void mex_tile_map (ClutterActor *actor) { MxFocusManager *manager; CLUTTER_ACTOR_CLASS (mex_tile_parent_class)->map (actor); manager = mx_focus_manager_get_for_stage ((ClutterStage *) clutter_actor_get_stage (actor)); if (manager) { g_signal_connect (manager, "notify::focused", G_CALLBACK (mex_tile_notify_focused_cb), actor); mex_tile_notify_focused_cb (manager, NULL, (MexTile *)actor); } }
int main (int argc, char *argv[]) { ClutterActor *button, *box, *stage; MxApplication *application; MxWindow *window; application = mx_application_new (&argc, &argv, "Test Mx focus handling", MX_APPLICATION_SINGLE_INSTANCE); window = mx_application_create_window (application); stage = (ClutterActor *)mx_window_get_clutter_stage (window); box = mx_box_layout_new (); mx_box_layout_set_orientation (MX_BOX_LAYOUT (box), MX_ORIENTATION_VERTICAL); mx_window_set_child (window, box); button = mx_button_new_with_label ("button #1 (activate to remove)"); g_signal_connect (button, "clicked", G_CALLBACK (button_clicked_cb), NULL); mx_box_layout_insert_actor (MX_BOX_LAYOUT (box), button, -1); mx_focus_manager_push_focus (mx_focus_manager_get_for_stage (CLUTTER_STAGE (stage)), MX_FOCUSABLE (button)); button = mx_button_new_with_label ("button #2 (activate to remove)"); g_signal_connect (button, "clicked", G_CALLBACK (button_clicked_cb), NULL); mx_box_layout_insert_actor (MX_BOX_LAYOUT (box), button, -1); button = mx_button_new_with_label ("button #3 (activate to remove)"); g_signal_connect (button, "clicked", G_CALLBACK (button_clicked_cb), NULL); mx_box_layout_insert_actor (MX_BOX_LAYOUT (box), button, -1); button = mx_button_new_with_label ("button #4 (activate to remove)"); g_signal_connect (button, "clicked", G_CALLBACK (button_clicked_cb), NULL); mx_box_layout_insert_actor (MX_BOX_LAYOUT (box), button, -1); clutter_actor_show (stage); mx_application_run (application); return EXIT_SUCCESS; }
static void mex_clock_bin_map (ClutterActor *actor) { ClutterActor *stage; MxFocusManager *manager; MexClockBinPrivate *priv = MEX_CLOCK_BIN (actor)->priv; CLUTTER_ACTOR_CLASS (mex_clock_bin_parent_class)->map (actor); clutter_actor_map (priv->clock_hbox); stage = clutter_actor_get_stage (actor); manager = mx_focus_manager_get_for_stage (CLUTTER_STAGE (stage)); g_signal_connect (manager, "notify::focused", G_CALLBACK (mex_clock_bin_notify_focused_cb), actor); }
static void mex_menu_map (ClutterActor *actor) { MxFocusManager *manager; MexMenu *self = MEX_MENU (actor); CLUTTER_ACTOR_CLASS (mex_menu_parent_class)->map (actor); manager = mx_focus_manager_get_for_stage ((ClutterStage *) clutter_actor_get_stage (actor)); if (manager) { g_signal_connect (manager, "notify::focused", G_CALLBACK (mex_menu_notify_focused_cb), self); mex_menu_notify_focused_cb (manager, NULL, self); } }
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 void mex_clock_bin_unmap (ClutterActor *actor) { ClutterActor *stage; MxFocusManager *manager; MexClockBinPrivate *priv = MEX_CLOCK_BIN (actor)->priv; stage = clutter_actor_get_stage (actor); manager = mx_focus_manager_get_for_stage (CLUTTER_STAGE (stage)); g_signal_handlers_disconnect_by_func (manager, mex_clock_bin_notify_focused_cb, actor); clutter_actor_unmap (priv->clock_hbox); CLUTTER_ACTOR_CLASS (mex_clock_bin_parent_class)->unmap (actor); }
static void mx_menu_show (ClutterActor *actor) { ClutterStage *stage; 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 mex_telepathy_channel_on_video_shown (ClutterActor *actor, gpointer user_data) { MexTelepathyChannel *self = MEX_TELEPATHY_CHANNEL (user_data); MexTelepathyChannelPrivate *priv = self->priv; ClutterStage *stage; MxFocusManager *fmanager; clutter_actor_hide (CLUTTER_ACTOR (priv->full_frame) ); stage = CLUTTER_STAGE (clutter_actor_get_stage (CLUTTER_ACTOR (actor))); if (stage) { fmanager = mx_focus_manager_get_for_stage (stage); mx_focus_manager_push_focus (fmanager, MX_FOCUSABLE (priv->end_button)); } }
static gboolean mx_menu_button_enter_event_cb (ClutterActor *box, ClutterEvent *event, gpointer user_data) { MxMenuPrivate *priv = MX_MENU (user_data)->priv; ClutterStage *stage; /* each menu item grabs focus when hovered */ stage = (ClutterStage *) clutter_actor_get_stage (box); /* ensure the menu is not closed when focus is pushed to another actor */ priv->internal_focus_push = TRUE; mx_focus_manager_push_focus (mx_focus_manager_get_for_stage (stage), MX_FOCUSABLE (box)); /* prevent the hover pseudo-class from being applied */ return TRUE; }
void mex_column_set_collapse_on_focus (MexColumn *column, gboolean collapse) { MexColumnPrivate *priv; g_return_if_fail (MEX_IS_COLUMN (column)); priv = column->priv; if (priv->collapse != collapse) { ClutterActor *stage; priv->collapse = collapse; g_object_notify (G_OBJECT (column), "collapse-on-focus"); if ((stage = clutter_actor_get_stage (CLUTTER_ACTOR (column)))) { MxFocusManager *manager = mx_focus_manager_get_for_stage (CLUTTER_STAGE (stage)); mex_column_notify_focused_cb (manager, NULL, column); } } }
void mex_epg_grid_add_events (MexEpgGrid *grid, MexChannel *channel, GPtrArray *events) { MexEpgGridPrivate *priv; MexChannelManager *channel_manager; MxFocusManager *focus_manager; GPtrArray *row; gint position; guint i; g_return_if_fail (MEX_IS_EPG_GRID (grid)); g_return_if_fail (MEX_IS_CHANNEL (channel)); g_return_if_fail (events); priv = grid->priv; channel_manager = mex_channel_manager_get_default (); position = mex_channel_manager_get_channel_position (channel_manager, channel); if (G_UNLIKELY (position == -1)) { MEX_WARN (EPG, "Could not find position of channel %s", mex_channel_get_name (channel)); return; } /* no events for this channel */ if (G_UNLIKELY (events->len == 0)) { /* signal that we won't have data for that row */ row_loaded (grid, position); return; } /* we insert tiles in bulk, removing the existing tiles if needed */ row = g_ptr_array_index (priv->rows, position); /* If we already have data for that row, we assume the caller wants to * replace the data. If we don't we signal that a new row is loaded */ if (row) remove_row (grid, position); else row_loaded (grid, position); row = g_ptr_array_new (); g_ptr_array_set_size (row, events->len); /* We are adding events, it's a good time to check if we have a valid * current date */ if (priv->current_date == NULL) priv->current_date = g_date_time_new_now_local (); for (i = 0; i < events->len; i++) { MexEpgEvent *event = g_ptr_array_index (events, i); ClutterActor *tile; tile = mex_epg_tile_new_with_event (event); g_signal_connect (tile, "clicked", G_CALLBACK (on_tile_clicked), grid); clutter_actor_set_parent (tile, CLUTTER_ACTOR (grid)); g_ptr_array_index (row, i) = tile; #if 0 /* Disabled because we don't need to style differently the events that * are occuring now in the current design, might come back though */ if (mex_epg_event_is_date_in_between (event, priv->current_date)) mx_stylable_set_style_class (MX_STYLABLE (tile), "EpgTileNow"); #endif } g_ptr_array_index (priv->rows, position) = row; /* If the EpgGrid had the focus before we had a chance to add events, * it's a good time to push the focus to one of the EpgTile */ /* FIXME: default to the channel we are watching, not row 0 */ if (priv->has_focus_but_no_tile && position == 0 && row->len > 0) { ClutterActor *focused_tile = g_ptr_array_index (row, 0); ClutterActor *stage; stage = clutter_actor_get_stage (focused_tile); focus_manager = mx_focus_manager_get_for_stage (CLUTTER_STAGE (stage)); mx_focus_manager_push_focus (focus_manager, MX_FOCUSABLE (focused_tile)); g_signal_emit (grid, signals[SIGNAL_ROW_SELECTED], 0, 0); priv->has_focus_but_no_tile = FALSE; } /* We have a new row, relayout */ clutter_actor_queue_relayout (CLUTTER_ACTOR (grid)); }
void mex_shell_present (MexShell *shell, ClutterActor *actor, MexShellDirection in) { GList *l; ClutterActor *stage; ClutterActorBox box; MexShellPrivate *priv; MexShellChildData *data; gfloat x, y, width, height; g_return_if_fail (MEX_IS_SHELL (shell)); g_return_if_fail (CLUTTER_IS_ACTOR (actor)); priv = shell->priv; l = g_list_find_custom (priv->children, actor, mex_shell_find_child); if (!l) { g_warning (G_STRLOC ": Attempted to present an unknown child."); return; } data = l->data; clutter_actor_get_allocation_box (CLUTTER_ACTOR (shell), &box); width = box.x2 - box.x1; height = box.y2 - box.y1; x = 0; y = 0; if (clutter_actor_get_opacity (data->child) == 0x00) { switch (in) { case MEX_SHELL_DIRECTION_NONE: clutter_actor_set_position (data->child, 0, 0); break; case MEX_SHELL_DIRECTION_TOP: clutter_actor_set_position (data->child, x, -height); break; case MEX_SHELL_DIRECTION_RIGHT: clutter_actor_set_position (data->child, width, y); break; default: case MEX_SHELL_DIRECTION_BOTTOM: clutter_actor_set_position (data->child, x, height); break; case MEX_SHELL_DIRECTION_LEFT: clutter_actor_set_position (data->child, -width, y); break; } data->last_direction = in; } clutter_animator_remove_key (data->animator, (GObject *)data->child, NULL, -1); clutter_animator_set (data->animator, data->child, "x", CLUTTER_LINEAR, 0.0, 0.f, data->child, "x", CLUTTER_EASE_OUT_QUAD, 1.0, x, data->child, "y", CLUTTER_LINEAR, 0.0, 0.f, data->child, "y", CLUTTER_EASE_OUT_QUAD, 1.0, y, data->child, "opacity", CLUTTER_LINEAR, 0.0, 0x00, data->child, "opacity", CLUTTER_EASE_OUT_QUAD, 0.1, 0xff, NULL); clutter_animator_property_set_ease_in (data->animator, (GObject *)data->child, "x", TRUE); clutter_animator_property_set_ease_in (data->animator, (GObject *)data->child, "y", TRUE); clutter_animator_property_set_ease_in (data->animator, (GObject *)data->child, "opacity", TRUE); data->start_animator = TRUE; if (priv->presented && (priv->presented != actor)) { MexShellDirection dir; l = g_list_find_custom (priv->children, priv->presented, mex_shell_find_child); if (!l) { g_warning (G_STRLOC ": Former presented actor is unknown"); return; } data = l->data; x = y = 0; switch (in) { case 0: x = y = 0; dir = 0; break; case MEX_SHELL_DIRECTION_TOP: y = height; dir = MEX_SHELL_DIRECTION_BOTTOM; break; case MEX_SHELL_DIRECTION_RIGHT: x = -width; dir = MEX_SHELL_DIRECTION_LEFT; break; case MEX_SHELL_DIRECTION_BOTTOM: y = -height; dir = MEX_SHELL_DIRECTION_TOP; break; default: case MEX_SHELL_DIRECTION_LEFT: x = width; dir = MEX_SHELL_DIRECTION_RIGHT; break; } data->last_direction = dir; clutter_animator_remove_key (data->animator, (GObject *)data->child, NULL, -1); clutter_animator_set (data->animator, data->child, "x", CLUTTER_LINEAR, 0.0, 0.f, data->child, "x", CLUTTER_EASE_OUT_QUAD, 1.0, x, data->child, "y", CLUTTER_LINEAR, 0.0, 0.f, data->child, "y", CLUTTER_EASE_OUT_QUAD, 1.0, y, data->child, "opacity", CLUTTER_LINEAR, 0.9, 0xff, data->child, "opacity", CLUTTER_EASE_OUT_QUAD, 1.0, 0x00, NULL); clutter_animator_property_set_ease_in (data->animator, (GObject *)data->child, "x", TRUE); clutter_animator_property_set_ease_in (data->animator, (GObject *)data->child, "y", TRUE); clutter_animator_property_set_ease_in (data->animator, (GObject *)data->child, "opacity", TRUE); data->start_animator = TRUE; } priv->presented = actor; stage = clutter_actor_get_stage (actor); if (stage) { MxFocusManager *manager = mx_focus_manager_get_for_stage ((ClutterStage *)stage); if (manager) { if (MX_IS_FOCUSABLE (actor)) mx_focus_manager_push_focus_with_hint (manager, MX_FOCUSABLE (shell), MX_FOCUS_HINT_PRIOR); else mx_focus_manager_move_focus (manager, MX_FOCUS_DIRECTION_OUT); } } clutter_actor_queue_redraw (CLUTTER_ACTOR (shell)); }
static gboolean mex_player_key_press_event (ClutterActor *actor, ClutterKeyEvent *event) { MexPlayerPrivate *priv = MEX_PLAYER (actor)->priv; ClutterStage *stage; MxFocusManager *fmanager; stage = (ClutterStage*) clutter_actor_get_stage (actor); fmanager = mx_focus_manager_get_for_stage (stage); switch (event->keyval) { case CLUTTER_KEY_Down: { if (!priv->controls_visible && !priv->info_visible) return mex_player_set_controls_visible (MEX_PLAYER (actor), TRUE); break; } case MEX_KEY_INFO: { MexContent *content; content = priv->content; if (priv->info_visible) { /* hide the info panel */ clutter_actor_animate (priv->info_panel, CLUTTER_EASE_IN_SINE, 250, "opacity", 0x00, NULL); mx_widget_set_disabled (MX_WIDGET (priv->info_panel), TRUE); mx_widget_set_disabled (MX_WIDGET (priv->controls), FALSE); priv->info_visible = FALSE; if (priv->controls_prev_visible) mex_player_set_controls_visible (MEX_PLAYER (actor), TRUE); } else { /* if you're pressing info button while the media controls are up set them as previously visible */ if (priv->controls_visible) priv->controls_prev_visible = TRUE; MxFocusable *focusable; focusable = mx_focus_manager_get_focused (fmanager); if (MEX_IS_CONTENT_TILE (focusable) && priv->controls_prev_visible == TRUE) { content = mex_content_view_get_content (MEX_CONTENT_VIEW (focusable)); /* to avoid any accidental leak */ if (priv->related_tile) { g_object_unref (priv->related_tile); priv->related_tile = NULL; } priv->related_tile = g_object_ref (focusable); } mex_content_view_set_content (MEX_CONTENT_VIEW (priv->info_panel), content); /* show the info panel */ clutter_actor_animate (priv->info_panel, CLUTTER_EASE_IN_SINE, 250, "opacity", 0xff, NULL); mx_widget_set_disabled (MX_WIDGET (priv->info_panel), FALSE); mx_widget_set_disabled (MX_WIDGET (priv->controls), TRUE); priv->info_visible = TRUE; mex_player_set_controls_visible (MEX_PLAYER (actor), FALSE); mex_push_focus (MX_FOCUSABLE (priv->info_panel)); } return TRUE; } } return FALSE; }