/** * 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_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; }
/** * 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; }