ClutterActor * _clutter_backend_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error) { ClutterBackendClass *klass; ClutterStageManager *stage_manager; ClutterActor *stage = NULL; g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), FALSE); g_return_val_if_fail (CLUTTER_IS_STAGE (wrapper), FALSE); stage_manager = clutter_stage_manager_get_default (); klass = CLUTTER_BACKEND_GET_CLASS (backend); if (klass->create_stage) stage = klass->create_stage (backend, wrapper, error); if (!stage) return NULL; g_assert (CLUTTER_IS_STAGE_WINDOW (stage)); _clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage)); _clutter_stage_manager_add_stage (stage_manager, wrapper); return stage; }
/** * clutter_test_check_color_at_point: * @stage: a #ClutterStage * @point: coordinates to check * @color: expected color * @result: (out caller-allocates): color at the given coordinates * * Checks the color at the given coordinates on @stage, and matches * it with the red, green, and blue channels of @color. The alpha * component of @color and @result is ignored. * * Returns: %TRUE if the colors match * * Since: 1.18 */ gboolean clutter_test_check_color_at_point (ClutterActor *stage, const ClutterPoint *point, const ClutterColor *color, ClutterColor *result) { ValidateData *data; gboolean retval; guint8 *buffer; guint press_id = 0; g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); g_return_val_if_fail (point != NULL, FALSE); g_return_val_if_fail (color != NULL, FALSE); g_return_val_if_fail (result != NULL, FALSE); data = g_new0 (ValidateData, 1); data->stage = stage; data->point = *point; data->check_color = TRUE; if (g_test_verbose ()) { g_printerr ("Press ESC to close the stage and resume the test\n"); press_id = g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press_event), data); } clutter_actor_show (stage); clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT, validate_stage, data, NULL); while (!data->was_painted) g_main_context_iteration (NULL, TRUE); if (press_id != 0) g_signal_handler_disconnect (stage, press_id); buffer = data->result; clutter_color_init (result, buffer[0], buffer[1], buffer[2], 255); /* we only check the color channels, so we can't use clutter_color_equal() */ retval = buffer[0] == color->red && buffer[1] == color->green && buffer[2] == color->blue; g_free (data->result); g_free (data); return retval; }
void _clutter_backend_ensure_context (ClutterBackend *backend, ClutterStage *stage) { static ClutterStage *current_context_stage = NULL; ClutterBackendClass *klass; g_return_if_fail (CLUTTER_IS_BACKEND (backend)); g_return_if_fail (CLUTTER_IS_STAGE (stage)); if (current_context_stage != stage || !CLUTTER_ACTOR_IS_REALIZED (stage)) { ClutterStage *new_stage = NULL; if (!CLUTTER_ACTOR_IS_REALIZED (stage)) { new_stage = NULL; CLUTTER_NOTE (MULTISTAGE, "Stage [%p] is not realized, unsetting the stage", stage); } else { new_stage = stage; CLUTTER_NOTE (MULTISTAGE, "Setting the new stage [%p]", new_stage); } klass = CLUTTER_BACKEND_GET_CLASS (backend); if (G_LIKELY (klass->ensure_context)) klass->ensure_context (backend, new_stage); /* FIXME: With a NULL stage and thus no active context it may make more * sense to clean the context but then re call with the default stage * so at least there is some kind of context in place (as to avoid * potential issue of GL calls with no context) */ current_context_stage = new_stage; /* if the new stage has a different size than the previous one * we need to update the viewport; we do it by simply setting the * SYNC_MATRICES flag and letting the next redraw cycle take care * of calling glViewport() */ if (current_context_stage) { CLUTTER_SET_PRIVATE_FLAGS (current_context_stage, CLUTTER_ACTOR_SYNC_MATRICES); } } else CLUTTER_NOTE (MULTISTAGE, "Stage is the same"); }
/** * clutter_win32_set_stage_foreign: * @stage: a #ClutterStage * @hwnd: an existing window handle * * Target the #ClutterStage to use an existing external window handle. * * Return value: %TRUE if foreign window is valid * * Since: 0.8 */ gboolean clutter_win32_set_stage_foreign (ClutterStage *stage, HWND hwnd) { ClutterStageWin32 *stage_win32; ClutterStageWindow *impl; ClutterActor *actor; RECT client_rect; ForeignWindowData fwd; g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); g_return_val_if_fail (hwnd != NULL, FALSE); actor = CLUTTER_ACTOR (stage); impl = _clutter_stage_get_window (stage); stage_win32 = CLUTTER_STAGE_WIN32 (impl); if (!GetClientRect (hwnd, &client_rect)) { g_warning ("Unable to retrieve the new window geometry"); return FALSE; } fwd.stage_win32 = stage_win32; fwd.hwnd = hwnd; /* destroy the old HWND, if we have one and it's ours */ if (stage_win32->hwnd != NULL && !stage_win32->is_foreign_win) fwd.destroy_old_hwnd = TRUE; else fwd.destroy_old_hwnd = FALSE; fwd.geom.x = 0; fwd.geom.y = 0; fwd.geom.width = client_rect.right - client_rect.left; fwd.geom.height = client_rect.bottom - client_rect.top; _clutter_actor_rerealize (actor, set_foreign_window_callback, &fwd); /* Queue a relayout - so the stage will be allocated the new * window size. * * Note also that when the stage gets allocated the new * window size that will result in the stage's * priv->viewport being changed, which will in turn result * in the Cogl viewport changing when _clutter_do_redraw * calls _clutter_stage_maybe_setup_viewport(). */ clutter_actor_queue_relayout (CLUTTER_ACTOR (stage)); return TRUE; }
/** * clutter_event_set_stage: * @event: a #ClutterEvent * @stage: (allow-none): a #ClutterStage, or %NULL * * Sets the source #ClutterStage of the event. * * Since: 1.8 */ void clutter_event_set_stage (ClutterEvent *event, ClutterStage *stage) { g_return_if_fail (event != NULL); g_return_if_fail (stage == NULL || CLUTTER_IS_STAGE (stage)); if (event->any.stage == stage) return; event->any.stage = stage; }
/** * clutter_x11_get_stage_window: (skip) * @stage: a #ClutterStage * * Gets the stages X Window. * * Return value: An XID for the stage window. * * */ Window clutter_x11_get_stage_window (ClutterStage *stage) { ClutterStageWindow *impl; g_return_val_if_fail (CLUTTER_IS_STAGE (stage), None); impl = _clutter_stage_get_window (stage); g_assert (CLUTTER_IS_STAGE_X11 (impl)); return CLUTTER_STAGE_X11 (impl)->xwin; }
/** * clutter_win32_get_stage_window: * @stage: a #ClutterStage * * Gets the stage's window handle * * Return value: An HWND for the stage window. * * Since: 0.8 */ HWND clutter_win32_get_stage_window (ClutterStage *stage) { ClutterStageWindow *impl; g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); impl = _clutter_stage_get_window (stage); g_return_val_if_fail (CLUTTER_IS_STAGE_WIN32 (impl), NULL); return CLUTTER_STAGE_WIN32 (impl)->hwnd; }
/** * clutter_win32_set_stage_foreign: * @stage: a #ClutterStage * @hwnd: an existing window handle * * Target the #ClutterStage to use an existing external window handle. * * Return value: %TRUE if foreign window is valid * * Since: 0.8 */ gboolean clutter_win32_set_stage_foreign (ClutterStage *stage, HWND hwnd) { ClutterStageWin32 *stage_win32; ClutterStageWindow *impl; ClutterActor *actor; RECT client_rect; POINT window_pos; ClutterGeometry geom; g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); g_return_val_if_fail (hwnd != NULL, FALSE); actor = CLUTTER_ACTOR (stage); impl = _clutter_stage_get_window (stage); stage_win32 = CLUTTER_STAGE_WIN32 (impl); /* FIXME this needs updating to use _clutter_actor_rerealize(), * see the analogous code in x11 backend. Probably best if * win32 maintainer does it so they can be sure it compiles * and works. */ clutter_actor_unrealize (actor); if (!GetClientRect (hwnd, &client_rect)) { g_warning ("Unable to retrieve the new window geometry"); return FALSE; } window_pos.x = client_rect.left; window_pos.y = client_rect.right; ClientToScreen (hwnd, &window_pos); CLUTTER_NOTE (BACKEND, "Setting foreign window (0x%x)", (int) hwnd); stage_win32->hwnd = hwnd; stage_win32->is_foreign_win = TRUE; geom.x = 0; geom.y = 0; geom.width = client_rect.right - client_rect.left; geom.height = client_rect.bottom - client_rect.top; clutter_actor_set_geometry (actor, &geom); clutter_actor_realize (actor); return TRUE; }
/** * clutter_stage_manager_set_default_stage: * @stage_manager: a #ClutterStageManager * @stage: a #ClutterStage * * Sets @stage as the default stage. * * Since: 0.8 */ void clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager, ClutterStage *stage) { g_return_if_fail (CLUTTER_IS_STAGE_MANAGER (stage_manager)); g_return_if_fail (CLUTTER_IS_STAGE (stage)); if (!g_slist_find (stage_manager->stages, stage)) _clutter_stage_manager_add_stage (stage_manager, stage); default_stage = stage; g_object_notify (G_OBJECT (stage_manager), "default-stage"); }
/** * clutter_gdk_set_stage_foreign: * @stage: a #ClutterStage * @window: an existing #GdkWindow * * Target the #ClutterStage to use an existing external #GdkWindow * * Return value: %TRUE if foreign window is valid * * Since: 1.10 */ gboolean clutter_gdk_set_stage_foreign (ClutterStage *stage, GdkWindow *window) { ForeignWindowClosure closure; ClutterStageGdk *stage_gdk; ClutterStageWindow *impl; ClutterActor *actor; g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); g_return_val_if_fail (!CLUTTER_ACTOR_IN_DESTRUCTION (stage), FALSE); g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE); impl = _clutter_stage_get_window (stage); if (!CLUTTER_IS_STAGE_GDK (impl)) { g_critical ("The Clutter backend is not a GDK backend"); return FALSE; } stage_gdk = CLUTTER_STAGE_GDK (impl); if (g_object_get_data (G_OBJECT (window), "clutter-stage-window") != NULL) { g_critical ("The provided GdkWindow is already in use by another ClutterStage"); return FALSE; } closure.stage_gdk = stage_gdk; closure.window = g_object_ref (window); actor = CLUTTER_ACTOR (stage); _clutter_actor_rerealize (actor, set_foreign_window_callback, &closure); /* Queue a relayout - so the stage will be allocated the new * window size. * * Note also that when the stage gets allocated the new * window size that will result in the stage's * priv->viewport being changed, which will in turn result * in the Cogl viewport changing when _clutter_do_redraw * calls _clutter_stage_maybe_setup_viewport(). */ clutter_actor_queue_relayout (actor); return TRUE; }
void penge_utils_signal_activated (ClutterActor *actor) { while (actor) { if (clutter_actor_get_parent (actor) && CLUTTER_IS_STAGE (clutter_actor_get_parent (actor))) { g_signal_emit_by_name (actor, "activated", NULL); return; } actor = clutter_actor_get_parent (actor); } }
/** * clutter_gdk_get_stage_window: * @stage: a #ClutterStage * * Gets the stages GdkWindow. * * Return value: (transfer none): A GdkWindow* for the stage window. * * Since: 1.10 */ GdkWindow * clutter_gdk_get_stage_window (ClutterStage *stage) { ClutterStageWindow *impl; g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); impl = _clutter_stage_get_window (stage); if (!CLUTTER_IS_STAGE_GDK (impl)) { g_critical ("The Clutter backend is not a GDK backend"); return NULL; } return CLUTTER_STAGE_GDK (impl)->window; }
/** * clutter_test_check_actor_at_point: * @stage: a #ClutterStage * @point: coordinates to check * @actor: the expected actor at the given coordinates * @result: (out) (nullable): actor at the coordinates * * Checks the given coordinates of the @stage and compares the * actor found there with the given @actor. * * Returns: %TRUE if the actor at the given coordinates matches * * Since: 1.18 */ gboolean clutter_test_check_actor_at_point (ClutterActor *stage, const ClutterPoint *point, ClutterActor *actor, ClutterActor **result) { ValidateData *data; guint press_id = 0; g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); g_return_val_if_fail (point != NULL, FALSE); g_return_val_if_fail (CLUTTER_IS_ACTOR (stage), FALSE); g_return_val_if_fail (result != NULL, FALSE); data = g_new0 (ValidateData, 1); data->stage = stage; data->point = *point; data->check_actor = TRUE; if (g_test_verbose ()) { g_printerr ("Press ESC to close the stage and resume the test\n"); press_id = g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press_event), data); } clutter_actor_show (stage); clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT, validate_stage, data, NULL); while (!data->was_painted) g_main_context_iteration (NULL, TRUE); *result = data->result; if (press_id != 0) g_signal_handler_disconnect (stage, press_id); g_free (data); return *result == actor; }
/** * st_theme_context_get_for_stage: * @stage: a #ClutterStage * * Gets a singleton theme context associated with the stage. * * Return value: (transfer none): the singleton theme context for the stage */ StThemeContext * st_theme_context_get_for_stage (ClutterStage *stage) { StThemeContext *context; g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); context = g_object_get_data (G_OBJECT (stage), "st-theme-context"); if (context) return context; context = st_theme_context_new (); g_object_set_data (G_OBJECT (stage), "st-theme-context", context); g_signal_connect (stage, "destroy", G_CALLBACK (on_stage_destroy), NULL); return context; }
static void key_focus_in_cb (ClutterActor *actor, gpointer data) { ClutterActor *focus_box = CLUTTER_ACTOR (data); if (CLUTTER_IS_STAGE (actor)) clutter_actor_hide (focus_box); else { clutter_actor_set_position (focus_box, clutter_actor_get_x (actor) - 5, clutter_actor_get_y (actor) - 5); clutter_actor_set_size (focus_box, clutter_actor_get_width (actor) + 10, clutter_actor_get_height (actor) + 10); clutter_actor_show (focus_box); } }
/** * st_widget_get_theme_node: * @widget: a #StWidget * * Gets the theme node holding style information for the widget. * The theme node is used to access standard and custom CSS * properties of the widget. * * Return value: (transfer none): the theme node for the widget. * This is owned by the widget. When attributes of the widget * or the environment that affect the styling change (for example * the style_class property of the widget), it will be recreated, * and the ::style-changed signal will be emitted on the widget. */ StThemeNode * st_widget_get_theme_node (StWidget *widget) { StWidgetPrivate *priv = widget->priv; if (priv->theme_node == NULL) { StThemeNode *parent_node = NULL; ClutterStage *stage = NULL; ClutterActor *parent; parent = clutter_actor_get_parent (CLUTTER_ACTOR (widget)); while (parent != NULL) { if (parent_node == NULL && ST_IS_WIDGET (parent)) parent_node = st_widget_get_theme_node (ST_WIDGET (parent)); else if (CLUTTER_IS_STAGE (parent)) stage = CLUTTER_STAGE (parent); parent = clutter_actor_get_parent (parent); } if (stage == NULL) { g_error ("st_widget_get_theme_node called on a widget not in a stage"); } if (parent_node == NULL) parent_node = get_root_theme_node (CLUTTER_STAGE (stage)); priv->theme_node = st_theme_node_new (st_theme_context_get_for_stage (stage), parent_node, priv->theme, G_OBJECT_TYPE (widget), clutter_actor_get_name (CLUTTER_ACTOR (widget)), priv->style_class, priv->pseudo_class, priv->inline_style); } return priv->theme_node; }
ClutterStageWindow * _clutter_backend_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error) { ClutterBackendClass *klass; ClutterStageWindow *stage_window; g_assert (CLUTTER_IS_BACKEND (backend)); g_assert (CLUTTER_IS_STAGE (wrapper)); klass = CLUTTER_BACKEND_GET_CLASS (backend); if (klass->create_stage != NULL) stage_window = klass->create_stage (backend, wrapper, error); else stage_window = NULL; if (stage_window == NULL) return NULL; g_assert (CLUTTER_IS_STAGE_WINDOW (stage_window)); return stage_window; }
void _clutter_backend_ensure_context (ClutterBackend *backend, ClutterStage *stage) { static ClutterStage *current_context_stage = NULL; g_assert (CLUTTER_IS_BACKEND (backend)); g_assert (CLUTTER_IS_STAGE (stage)); if (current_context_stage != stage || !CLUTTER_ACTOR_IS_REALIZED (stage)) { ClutterStage *new_stage = NULL; if (!CLUTTER_ACTOR_IS_REALIZED (stage)) { new_stage = NULL; CLUTTER_NOTE (BACKEND, "Stage [%p] is not realized, unsetting the stage", stage); } else { new_stage = stage; CLUTTER_NOTE (BACKEND, "Setting the new stage [%p]", new_stage); } /* XXX: Until Cogl becomes fully responsible for backend windows * Clutter need to manually keep it informed of the current window size * * NB: This must be done after we ensure_context above because Cogl * always assumes there is a current GL context. */ if (new_stage != NULL) { float width, height; _clutter_backend_ensure_context_internal (backend, new_stage); clutter_actor_get_size (CLUTTER_ACTOR (stage), &width, &height); cogl_onscreen_clutter_backend_set_size (width, height); /* Eventually we will have a separate CoglFramebuffer for * each stage and each one will track private projection * matrix and viewport state, but until then we need to make * sure we update the projection and viewport whenever we * switch between stages. * * This dirty mechanism will ensure they are asserted before * the next paint... */ _clutter_stage_dirty_viewport (stage); _clutter_stage_dirty_projection (stage); } /* FIXME: With a NULL stage and thus no active context it may make more * sense to clean the context but then re call with the default stage * so at least there is some kind of context in place (as to avoid * potential issue of GL calls with no context). */ current_context_stage = new_stage; } else CLUTTER_NOTE (BACKEND, "Stage is the same"); }
static void moses_overview_dispose(GObject *object) { MosesOverview *overview = MOSES_OVERVIEW(object); MosesOverviewPrivate* priv = overview->priv; if (priv->disposed) return; priv->disposed = TRUE; g_clear_pointer(&priv->ov_head, g_object_unref); MetaScreen* screen = meta_plugin_get_screen(priv->plugin); ClutterActor* stage = meta_get_stage_for_screen(screen); ClutterActor* to_focus = NULL; if (priv->selected_actor) { to_focus = clutter_clone_get_source(CLUTTER_CLONE(priv->selected_actor)); } for (int i = 0; priv->clones && i < priv->clones->len; i++) { ClutterActor* clone = g_ptr_array_index(priv->clones, i); ClutterActor* orig = clutter_clone_get_source(CLUTTER_CLONE(clone)); clutter_actor_show(orig); // FIXME: maybe some actors had not been shown. clutter_actor_destroy(clone); } for (int i = 0; priv->badges && i < priv->badges->len; i++) { clutter_actor_destroy(CLUTTER_ACTOR(g_ptr_array_index(priv->badges, i))); } if (priv->background_actor) { clutter_actor_show(clutter_clone_get_source(CLUTTER_CLONE(priv->background_actor))); g_clear_pointer(&priv->background_actor, clutter_actor_destroy); } if (priv->modaled) { meta_plugin_end_modal(priv->plugin, clutter_get_current_event_time()); meta_enable_unredirect_for_screen(screen); if (priv->selected_workspace) { meta_workspace_activate(priv->selected_workspace, CLUTTER_CURRENT_TIME); MetaDisplay* display = meta_screen_get_display(screen); meta_compositor_switch_workspace(meta_display_get_compositor(display), meta_screen_get_active_workspace(screen), priv->selected_workspace, META_MOTION_DOWN); } else if (to_focus) { clutter_stage_set_key_focus(CLUTTER_STAGE(stage), to_focus); MetaWindowActor* actor = META_WINDOW_ACTOR(to_focus); MetaWindow* win = meta_window_actor_get_meta_window(actor); meta_window_raise(win); meta_window_focus(win, CLUTTER_CURRENT_TIME); } else if (priv->previous_focused) { if (!CLUTTER_IS_STAGE(priv->previous_focused)) { clutter_stage_set_key_focus(CLUTTER_STAGE(stage), priv->previous_focused); } } } G_OBJECT_CLASS(moses_overview_parent_class)->dispose(object); }
/** * clutter_x11_set_stage_foreign: * @stage: a #ClutterStage * @xwindow: an existing X Window id * * Target the #ClutterStage to use an existing external X Window * * Return value: %TRUE if foreign window is valid * * */ gboolean clutter_x11_set_stage_foreign (ClutterStage *stage, Window xwindow) { ClutterBackendX11 *backend_x11; ClutterStageX11 *stage_x11; ClutterStageCogl *stage_cogl; ClutterStageWindow *impl; ClutterActor *actor; gint x, y; guint width, height, border, depth; Window root_return; Status status; ForeignWindowData fwd; XVisualInfo *xvisinfo; g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); g_return_val_if_fail (!CLUTTER_ACTOR_IN_DESTRUCTION (stage), FALSE); g_return_val_if_fail (xwindow != None, FALSE); impl = _clutter_stage_get_window (stage); stage_x11 = CLUTTER_STAGE_X11 (impl); stage_cogl = CLUTTER_STAGE_COGL (impl); backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); xvisinfo = _clutter_backend_x11_get_visual_info (backend_x11); g_return_val_if_fail (xvisinfo != NULL, FALSE); clutter_x11_trap_x_errors (); status = XGetGeometry (backend_x11->xdpy, xwindow, &root_return, &x, &y, &width, &height, &border, &depth); if (clutter_x11_untrap_x_errors () || !status) { g_critical ("Unable to retrieve the geometry of the foreign window: " "XGetGeometry() failed (status code: %d)", status); return FALSE; } if (width == 0 || height == 0) { g_warning ("The size of the foreign window is 0x0"); return FALSE; } if (depth != xvisinfo->depth) { g_warning ("The depth of the visual of the foreign window is %d, but " "Clutter has been initialized to require a visual depth " "of %d", depth, xvisinfo->depth); return FALSE; } fwd.stage_x11 = stage_x11; fwd.xwindow = xwindow; /* destroy the old Window, if we have one and it's ours */ if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin) fwd.destroy_old_xwindow = TRUE; else fwd.destroy_old_xwindow = FALSE; fwd.geom.x = x; fwd.geom.y = y; fwd.geom.width = width; fwd.geom.height = height; actor = CLUTTER_ACTOR (stage); _clutter_actor_rerealize (actor, set_foreign_window_callback, &fwd); /* Queue a relayout - so the stage will be allocated the new * window size. * * Note also that when the stage gets allocated the new * window size that will result in the stage's * priv->viewport being changed, which will in turn result * in the Cogl viewport changing when _clutter_do_redraw * calls _clutter_stage_maybe_setup_viewport(). */ clutter_actor_queue_relayout (actor); return TRUE; }