From 6988744db750dc3430a6c8cdd6274bc7e855aaf5 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 13 Aug 2009 12:34:07 +0100 Subject: [PATCH] [stage] Rework the Stage implementation class Instead of using ClutterActor for the base class of the Stage implementation we should extend the StageWindow interface with the required bits (geometry, realization) and use a simple object class. This require a wee bit of changes across Backend, Stage and StageWindow, even though it's mostly re-shuffling. First of all, StageWindow should get new virtual functions: * geometry: - resize() - get_geometry() * realization - realize() - unrealize() This covers all the bits that we use from ClutterActor currently inside the stage implementations. The ClutterBackend::create_stage() virtual function should create a StageWindow, and not an Actor (it should always have been; the fact that it returned an Actor was a leak of the black magic going on underneath). Since we never guaranteed ABI compatibility for the Backend class, this is not a problem. Internally to ClutterStage we can finally drop the shenanigans of setting/unsetting actor flags on the implementation: if the realization succeeds, for instance, we set the REALIZED flag on the Stage and we're done. As an initial proof of concept, the X11 and GLX stage implementations have been ported to the New World Order(tm) and show no regressions. --- clutter/Makefile.am | 2 +- clutter/clutter-backend.c | 14 +-- clutter/clutter-backend.h | 5 +- clutter/clutter-private.h | 2 +- clutter/clutter-stage-window.c | 79 +++++++++++++- clutter/clutter-stage-window.h | 33 ++++++ clutter/clutter-stage.c | 105 ++++++++++--------- clutter/clutter.h | 1 + clutter/glx/clutter-backend-glx.c | 14 +-- clutter/glx/clutter-stage-glx.c | 50 ++++----- clutter/x11/clutter-stage-x11.c | 165 +++++++++--------------------- 11 files changed, 255 insertions(+), 215 deletions(-) diff --git a/clutter/Makefile.am b/clutter/Makefile.am index fd4dbef49..7c62f7b6e 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -93,6 +93,7 @@ source_h = \ $(srcdir)/clutter-shader-types.h \ $(srcdir)/clutter-stage.h \ $(srcdir)/clutter-stage-manager.h \ + $(srcdir)/clutter-stage-window.h \ $(srcdir)/clutter-texture.h \ $(srcdir)/clutter-text.h \ $(srcdir)/clutter-timeline.h \ @@ -206,7 +207,6 @@ source_h_priv = \ $(srcdir)/clutter-private.h \ $(srcdir)/clutter-id-pool.h \ $(srcdir)/clutter-script-private.h \ - $(srcdir)/clutter-stage-window.h \ $(srcdir)/clutter-timeout-interval.h \ $(NULL) diff --git a/clutter/clutter-backend.c b/clutter/clutter-backend.c index 6e8dac0a2..c95ac9bc7 100644 --- a/clutter/clutter-backend.c +++ b/clutter/clutter-backend.c @@ -258,14 +258,14 @@ _clutter_backend_post_parse (ClutterBackend *backend, return TRUE; } -ClutterActor * +ClutterStageWindow * _clutter_backend_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error) { ClutterBackendClass *klass; ClutterStageManager *stage_manager; - ClutterActor *stage = NULL; + ClutterStageWindow *stage_window; g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), FALSE); g_return_val_if_fail (CLUTTER_IS_STAGE (wrapper), FALSE); @@ -274,16 +274,16 @@ _clutter_backend_create_stage (ClutterBackend *backend, klass = CLUTTER_BACKEND_GET_CLASS (backend); if (klass->create_stage) - stage = klass->create_stage (backend, wrapper, error); + stage_window = klass->create_stage (backend, wrapper, error); - if (!stage) + if (!stage_window) return NULL; - g_assert (CLUTTER_IS_STAGE_WINDOW (stage)); - _clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage)); + g_assert (CLUTTER_IS_STAGE_WINDOW (stage_window)); + _clutter_stage_set_window (wrapper, stage_window); _clutter_stage_manager_add_stage (stage_manager, wrapper); - return stage; + return stage_window; } void diff --git a/clutter/clutter-backend.h b/clutter/clutter-backend.h index 6529100c4..f6bd519c6 100644 --- a/clutter/clutter-backend.h +++ b/clutter/clutter-backend.h @@ -33,9 +33,10 @@ #include #include -#include #include #include +#include +#include G_BEGIN_DECLS @@ -67,7 +68,7 @@ struct _ClutterBackendClass GError **error); gboolean (* post_parse) (ClutterBackend *backend, GError **error); - ClutterActor * (* create_stage) (ClutterBackend *backend, + ClutterStageWindow *(* create_stage) (ClutterBackend *backend, ClutterStage *wrapper, GError **error); void (* init_events) (ClutterBackend *backend); diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index f5d958780..bd6f5dbe2 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -188,7 +188,7 @@ GType _clutter_backend_impl_get_type (void); void _clutter_backend_redraw (ClutterBackend *backend, ClutterStage *stage); -ClutterActor *_clutter_backend_create_stage (ClutterBackend *backend, +ClutterStageWindow *_clutter_backend_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error); void _clutter_backend_ensure_context (ClutterBackend *backend, diff --git a/clutter/clutter-stage-window.c b/clutter/clutter-stage-window.c index e74810503..e413aee36 100644 --- a/clutter/clutter-stage-window.c +++ b/clutter/clutter-stage-window.c @@ -26,8 +26,85 @@ clutter_stage_window_get_type (void) &stage_window_info, 0); g_type_interface_add_prerequisite (stage_window_type, - CLUTTER_TYPE_ACTOR); + G_TYPE_OBJECT); } return stage_window_type; } + +ClutterActor * +_clutter_stage_window_get_wrapper (ClutterStageWindow *window) +{ + return CLUTTER_STAGE_WINDOW_GET_IFACE (window)->get_wrapper (window); +} + +void +_clutter_stage_window_set_title (ClutterStageWindow *window, + const gchar *title) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->set_title (window, title); +} + +void +_clutter_stage_window_set_fullscreen (ClutterStageWindow *window, + gboolean is_fullscreen) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->set_fullscreen (window, + is_fullscreen); +} + +void +_clutter_stage_window_set_cursor_visible (ClutterStageWindow *window, + gboolean is_visible) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->set_cursor_visible (window, + is_visible); +} + +void +_clutter_stage_window_set_user_resizable (ClutterStageWindow *window, + gboolean is_resizable) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->set_user_resizable (window, + is_resizable); +} + +gboolean +_clutter_stage_window_realize (ClutterStageWindow *window) +{ + return CLUTTER_STAGE_WINDOW_GET_IFACE (window)->realize (window); +} + +void +_clutter_stage_window_unrealize (ClutterStageWindow *window) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->unrealize (window); +} + +void +_clutter_stage_window_show (ClutterStageWindow *window, + gboolean do_raise) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->show (window, do_raise); +} + +void +_clutter_stage_window_hide (ClutterStageWindow *window) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->hide (window); +} + +void +_clutter_stage_window_resize (ClutterStageWindow *window, + gint width, + gint height) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->resize (window, width, height); +} + +void +_clutter_stage_window_get_geometry (ClutterStageWindow *window, + ClutterGeometry *geometry) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->get_geometry (window, geometry); +} diff --git a/clutter/clutter-stage-window.h b/clutter/clutter-stage-window.h index a46662acd..c5a5e0426 100644 --- a/clutter/clutter-stage-window.h +++ b/clutter/clutter-stage-window.h @@ -28,13 +28,46 @@ struct _ClutterStageWindowIface void (* set_user_resizable) (ClutterStageWindow *stage_window, gboolean is_resizable); + gboolean (* realize) (ClutterStageWindow *stage_window); + void (* unrealize) (ClutterStageWindow *stage_window); + void (* show) (ClutterStageWindow *stage_window, gboolean do_raise); void (* hide) (ClutterStageWindow *stage_window); + + void (* resize) (ClutterStageWindow *stage_window, + gint width, + gint height); + void (* get_geometry) (ClutterStageWindow *stage_window, + ClutterGeometry *geometry); }; GType clutter_stage_window_get_type (void) G_GNUC_CONST; +ClutterActor *_clutter_stage_window_get_wrapper (ClutterStageWindow *window); + +void _clutter_stage_window_set_title (ClutterStageWindow *window, + const gchar *title); +void _clutter_stage_window_set_fullscreen (ClutterStageWindow *window, + gboolean is_fullscreen); +void _clutter_stage_window_set_cursor_visible (ClutterStageWindow *window, + gboolean is_visible); +void _clutter_stage_window_set_user_resizable (ClutterStageWindow *window, + gboolean is_resizable); + +gboolean _clutter_stage_window_realize (ClutterStageWindow *window); +void _clutter_stage_window_unrealize (ClutterStageWindow *window); + +void _clutter_stage_window_show (ClutterStageWindow *window, + gboolean do_raise); +void _clutter_stage_window_hide (ClutterStageWindow *window); + +void _clutter_stage_window_resize (ClutterStageWindow *window, + gint width, + gint height); +void _clutter_stage_window_get_geometry (ClutterStageWindow *window, + ClutterGeometry *geometry); + G_END_DECLS #endif /* __CLUTTER_STAGE_WINDOW_H__ */ diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index dd1c03832..f93ec786e 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -78,7 +78,7 @@ G_DEFINE_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP); struct _ClutterStagePrivate { /* the stage implementation */ - ClutterActor *impl; + ClutterStageWindow *impl; ClutterColor color; ClutterPerspective perspective; @@ -134,14 +134,18 @@ clutter_stage_get_preferred_width (ClutterActor *self, gfloat *natural_width_p) { ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; + ClutterGeometry geom = { 0, }; if (priv->impl == NULL) return; - CLUTTER_ACTOR_GET_CLASS (priv->impl)->get_preferred_width (priv->impl, - for_height, - min_width_p, - natural_width_p); + _clutter_stage_window_get_geometry (priv->impl, &geom); + + if (min_width_p) + *min_width_p = geom.width; + + if (natural_width_p) + *natural_width_p = geom.width; } static void @@ -151,14 +155,18 @@ clutter_stage_get_preferred_height (ClutterActor *self, gfloat *natural_height_p) { ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; + ClutterGeometry geom = { 0, }; if (priv->impl == NULL) return; - CLUTTER_ACTOR_GET_CLASS (priv->impl)->get_preferred_height (priv->impl, - for_width, - min_height_p, - natural_height_p); + _clutter_stage_window_get_geometry (priv->impl, &geom); + + if (min_height_p) + *min_height_p = geom.height; + + if (natural_height_p) + *natural_height_p = geom.height; } static void clutter_stage_allocate (ClutterActor *self, @@ -167,12 +175,16 @@ clutter_stage_allocate (ClutterActor *self, { ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; gboolean origin_changed; + gint width, height; origin_changed = (flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED) ? TRUE : FALSE; if (priv->impl == NULL) return; + width = clutter_actor_box_get_width (box); + height = clutter_actor_box_get_height (box); + /* if the stage is fixed size (for instance, it's using a frame-buffer) * then we simply ignore any allocation request and override the * allocation chain. @@ -183,41 +195,31 @@ clutter_stage_allocate (ClutterActor *self, CLUTTER_NOTE (LAYOUT, "Following allocation to %dx%d (origin %s)", - (int) (box->x2 - box->x1), - (int) (box->y2 - box->y1), + width, height, origin_changed ? "changed" : "not changed"); klass = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class); klass->allocate (self, box, flags); - klass = CLUTTER_ACTOR_GET_CLASS (priv->impl); - klass->allocate (priv->impl, box, flags); + _clutter_stage_window_resize (priv->impl, width, height); } else { ClutterActorBox override = { 0, }; + ClutterGeometry geom = { 0, }; ClutterActorClass *klass; - gfloat natural_width, natural_height; - /* propagate the allocation */ - klass = CLUTTER_ACTOR_GET_CLASS (priv->impl); - klass->allocate (self, box, flags); - - /* get the preferred size from the backend */ - clutter_actor_get_preferred_size (priv->impl, - NULL, NULL, - &natural_width, &natural_height); + _clutter_stage_window_get_geometry (priv->impl, &geom); override.x1 = 0; override.y1 = 0; - override.x2 = natural_width; - override.y2 = natural_height; + override.x2 = geom.width; + override.y2 = geom.height; CLUTTER_NOTE (LAYOUT, "Overrigin original allocation of %dx%d " "with %dx%d (origin %s)", - (int) (box->x2 - box->x1), - (int) (box->y2 - box->y1), + width, height, (int) (override.x2), (int) (override.y2), origin_changed ? "changed" : "not changed"); @@ -260,8 +262,10 @@ clutter_stage_paint (ClutterActor *self) else cogl_disable_fog (); +#if 0 CLUTTER_NOTE (PAINT, "Proxying the paint to the stage implementation"); - clutter_actor_paint (priv->impl); + _clutter_stage_window_paint (priv->impl); +#endif /* this will take care of painting every child */ CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (self); @@ -283,6 +287,7 @@ static void clutter_stage_realize (ClutterActor *self) { ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; + gboolean is_realized; /* Make sure the viewport and projection matrix are valid for the * first paint (which will likely occur before the ConfigureNotify @@ -291,13 +296,16 @@ clutter_stage_realize (ClutterActor *self) CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_SYNC_MATRICES); g_assert (priv->impl != NULL); - clutter_actor_realize (priv->impl); + is_realized = _clutter_stage_window_realize (priv->impl); /* ensure that the stage is using the context if the * realization sequence was successful */ - if (CLUTTER_ACTOR_IS_REALIZED (priv->impl)) - clutter_stage_ensure_current (CLUTTER_STAGE (self)); + if (is_realized) + { + CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED); + clutter_stage_ensure_current (CLUTTER_STAGE (self)); + } else CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED); } @@ -309,7 +317,9 @@ clutter_stage_unrealize (ClutterActor *self) /* and then unrealize the implementation */ g_assert (priv->impl != NULL); - clutter_actor_unrealize (priv->impl); + _clutter_stage_window_unrealize (priv->impl); + + CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED); clutter_stage_ensure_current (CLUTTER_STAGE (self)); } @@ -318,7 +328,6 @@ static void clutter_stage_show (ClutterActor *self) { ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; - ClutterStageWindow *impl; CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->show (self); @@ -327,19 +336,16 @@ clutter_stage_show (ClutterActor *self) _clutter_stage_maybe_relayout (self); g_assert (priv->impl != NULL); - impl = CLUTTER_STAGE_WINDOW (priv->impl); - CLUTTER_STAGE_WINDOW_GET_IFACE (impl)->show (impl, TRUE); + _clutter_stage_window_show (priv->impl, TRUE); } static void clutter_stage_hide (ClutterActor *self) { ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; - ClutterStageWindow *impl; g_assert (priv->impl != NULL); - impl = CLUTTER_STAGE_WINDOW (priv->impl); - CLUTTER_STAGE_WINDOW_GET_IFACE (impl)->hide (impl); + _clutter_stage_window_hide (priv->impl); CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->hide (self); } @@ -375,7 +381,7 @@ static void clutter_stage_real_fullscreen (ClutterStage *stage) { ClutterStagePrivate *priv = stage->priv; - gfloat natural_width, natural_height; + ClutterGeometry geom; ClutterActorBox box; /* we need to force an allocation here because the size @@ -385,14 +391,12 @@ clutter_stage_real_fullscreen (ClutterStage *stage) * the fact that fullscreening the stage on the X11 backends * is really an asynchronous operation */ - clutter_actor_get_preferred_size (CLUTTER_ACTOR (priv->impl), - NULL, NULL, - &natural_width, &natural_height); + _clutter_stage_window_get_geometry (priv->impl, &geom); box.x1 = 0; box.y1 = 0; - box.x2 = natural_width; - box.y2 = natural_height; + box.x2 = geom.width; + box.y2 = geom.height; clutter_actor_allocate (CLUTTER_ACTOR (stage), &box, @@ -723,11 +727,11 @@ clutter_stage_dispose (GObject *object) _clutter_stage_manager_remove_stage (stage_manager, stage); - if (priv->impl) + if (priv->impl != NULL) { CLUTTER_NOTE (BACKEND, "Disposing of the stage implementation"); - clutter_actor_hide (priv->impl); - clutter_actor_destroy (priv->impl); + + g_object_unref (priv->impl); priv->impl = NULL; } @@ -1008,16 +1012,11 @@ clutter_stage_init (ClutterStage *self) { g_warning ("Unable to create a new stage, falling back to the " "default stage."); - priv->impl = CLUTTER_ACTOR (_clutter_stage_get_default_window ()); + priv->impl = _clutter_stage_get_default_window (); /* at this point we must have a default stage, or we're screwed */ g_assert (priv->impl != NULL); } - else - g_object_ref_sink (priv->impl); - - /* make sure that the implementation is considered a top level */ - CLUTTER_SET_PRIVATE_FLAGS (priv->impl, CLUTTER_ACTOR_IS_TOPLEVEL); priv->event_queue = g_queue_new (); @@ -2044,7 +2043,7 @@ _clutter_stage_set_window (ClutterStage *stage, if (stage->priv->impl) g_object_unref (stage->priv->impl); - stage->priv->impl = CLUTTER_ACTOR (stage_window); + stage->priv->impl = stage_window; } ClutterStageWindow * diff --git a/clutter/clutter.h b/clutter/clutter.h index 3ae479e2d..701cf3176 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -67,6 +67,7 @@ #include "clutter-shader-types.h" #include "clutter-stage.h" #include "clutter-stage-manager.h" +#include "clutter-stage-window.h" #include "clutter-texture.h" #include "clutter-text.h" #include "clutter-timeline.h" diff --git a/clutter/glx/clutter-backend-glx.c b/clutter/glx/clutter-backend-glx.c index 39d2c26c6..4b4e59610 100644 --- a/clutter/glx/clutter-backend-glx.c +++ b/clutter/glx/clutter-backend-glx.c @@ -585,22 +585,22 @@ clutter_backend_glx_redraw (ClutterBackend *backend, } } -static ClutterActor * +static ClutterStageWindow * clutter_backend_glx_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error) { ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); - ClutterStageX11 *stage_x11; - ClutterActor *stage; + ClutterStageWindow *stage_window; + ClutterStageX11 *stage_x11; CLUTTER_NOTE (BACKEND, "Creating stage of type '%s'", g_type_name (CLUTTER_STAGE_TYPE)); - stage = g_object_new (CLUTTER_TYPE_STAGE_GLX, NULL); + stage_window = g_object_new (CLUTTER_TYPE_STAGE_GLX, NULL); /* copy backend data into the stage */ - stage_x11 = CLUTTER_STAGE_X11 (stage); + stage_x11 = CLUTTER_STAGE_X11 (stage_window); stage_x11->xdpy = backend_x11->xdpy; stage_x11->xwin_root = backend_x11->xwin_root; stage_x11->xscreen = backend_x11->xscreen_num; @@ -609,13 +609,13 @@ clutter_backend_glx_create_stage (ClutterBackend *backend, CLUTTER_NOTE (BACKEND, "GLX stage created[%p] (dpy:%p, screen:%d, root:%u, wrap:%p)", - stage, + stage_window, stage_x11->xdpy, stage_x11->xscreen, (unsigned int) stage_x11->xwin_root, wrapper); - return stage; + return stage_window; } static XVisualInfo * diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index f36a849b6..67d0afb4e 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -49,6 +49,8 @@ static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); +static ClutterStageWindowIface *clutter_stage_glx_parent_iface = NULL; + G_DEFINE_TYPE_WITH_CODE (ClutterStageGLX, clutter_stage_glx, CLUTTER_TYPE_STAGE_X11, @@ -56,10 +58,10 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageGLX, clutter_stage_window_iface_init)); static void -clutter_stage_glx_unrealize (ClutterActor *actor) +clutter_stage_glx_unrealize (ClutterStageWindow *stage_window) { - ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor); - ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor); + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window); gboolean was_offscreen; /* Note unrealize should free up any backend stage related resources */ @@ -67,9 +69,6 @@ clutter_stage_glx_unrealize (ClutterActor *actor) g_object_get (stage_x11->wrapper, "offscreen", &was_offscreen, NULL); - if (CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->unrealize != NULL) - CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->unrealize (actor); - clutter_x11_trap_x_errors (); if (G_UNLIKELY (was_offscreen)) @@ -110,19 +109,19 @@ clutter_stage_glx_unrealize (ClutterActor *actor) CLUTTER_MARK (); } -static void -clutter_stage_glx_realize (ClutterActor *actor) +static gboolean +clutter_stage_glx_realize (ClutterStageWindow *stage_window) { - ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor); - ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor); + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window); ClutterBackend *backend; ClutterBackendGLX *backend_glx; ClutterBackendX11 *backend_x11; gboolean is_offscreen; CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]", - G_OBJECT_TYPE_NAME (actor), - actor); + G_OBJECT_TYPE_NAME (stage_window), + stage_window); g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL); @@ -140,7 +139,7 @@ clutter_stage_glx_realize (ClutterActor *actor) if (stage_x11->xvisinfo == None) { g_critical ("Unable to find suitable GL visual."); - goto fail; + return FALSE; } if (stage_x11->xwin == None) @@ -209,7 +208,7 @@ clutter_stage_glx_realize (ClutterActor *actor) { g_critical ("Unable to realize stage: %s", error->message); g_error_free (error); - goto fail; + return FALSE; } CLUTTER_NOTE (BACKEND, "Successfully realized stage"); @@ -230,7 +229,7 @@ clutter_stage_glx_realize (ClutterActor *actor) if (stage_x11->xvisinfo == None) { g_critical ("Unable to find suitable GL visual."); - goto fail; + return FALSE; } stage_x11->xpixmap = XCreatePixmap (stage_x11->xdpy, @@ -257,20 +256,14 @@ clutter_stage_glx_realize (ClutterActor *actor) { g_critical ("Unable to realize stage: %s", error->message); g_error_free (error); - goto fail; + return FALSE; } CLUTTER_NOTE (BACKEND, "Successfully realized stage"); } - /* we need to chain up to the X11 stage implementation in order to - * set the window state in case we set it before realizing the stage - */ - CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->realize (actor); - return; - -fail: - CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); + /* chain up to the StageX11 implementation */ + return clutter_stage_glx_parent_iface->realize (stage_window); } static void @@ -283,12 +276,8 @@ static void clutter_stage_glx_class_init (ClutterStageGLXClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); gobject_class->dispose = clutter_stage_glx_dispose; - - actor_class->realize = clutter_stage_glx_realize; - actor_class->unrealize = clutter_stage_glx_unrealize; } static void @@ -299,5 +288,10 @@ clutter_stage_glx_init (ClutterStageGLX *stage) static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface) { + clutter_stage_glx_parent_iface = g_type_interface_peek_parent (iface); + + iface->realize = clutter_stage_glx_realize; + iface->unrealize = clutter_stage_glx_unrealize; + /* the rest is inherited from ClutterStageX11 */ } diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c index 722998f66..0b41112e7 100644 --- a/clutter/x11/clutter-stage-x11.c +++ b/clutter/x11/clutter-stage-x11.c @@ -50,7 +50,7 @@ static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); G_DEFINE_TYPE_WITH_CODE (ClutterStageX11, clutter_stage_x11, - CLUTTER_TYPE_GROUP, + G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, clutter_stage_window_iface_init)); @@ -95,24 +95,24 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11, resize = clutter_stage_get_user_resizable (stage_x11->wrapper); - if (stage_x11->xwin != None && stage_x11->is_foreign_xwin == FALSE) + if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin) { + gint min_width, min_height; + ClutterGeometry min_size; XSizeHints *size_hints; - gfloat min_width, min_height; size_hints = XAllocSizeHints(); + _clutter_stage_window_get_geometry (CLUTTER_STAGE_WINDOW (stage_x11), + &min_size); + if (new_width < 0) - clutter_actor_get_preferred_width (CLUTTER_ACTOR (stage_x11), - -1, - &min_width, NULL); + min_width = min_size.width; else min_width = new_width; if (new_height < 0) - clutter_actor_get_preferred_height (CLUTTER_ACTOR (stage_x11), - min_width, - &min_height, NULL); + min_height = min_size.height; else min_height = new_height; @@ -122,8 +122,8 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11, restrictions on the window size */ if (!stage_x11->fullscreen_on_map) { - size_hints->min_width = (int) min_width; - size_hints->min_height = (int) min_height; + size_hints->min_width = min_width; + size_hints->min_height = min_height; size_hints->flags = PMinSize; if (!resize) @@ -154,12 +154,10 @@ clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11) } static void -clutter_stage_x11_get_preferred_width (ClutterActor *self, - gfloat for_height, - gfloat *min_width_p, - gfloat *natural_width_p) +clutter_stage_x11_get_geometry (ClutterStageWindow *stage_window, + ClutterGeometry *geometry) { - ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (self); + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); gboolean is_fullscreen, resize; is_fullscreen = FALSE; @@ -169,110 +167,53 @@ clutter_stage_x11_get_preferred_width (ClutterActor *self, if (is_fullscreen || stage_x11->fullscreen_on_map) { - int width; - - width = DisplayWidth (stage_x11->xdpy, stage_x11->xscreen); - - if (min_width_p) - *min_width_p = width; - - if (natural_width_p) - *natural_width_p = width; + geometry->width = DisplayWidth (stage_x11->xdpy, stage_x11->xscreen); + geometry->height = DisplayHeight (stage_x11->xdpy, stage_x11->xscreen); return; } resize = clutter_stage_get_user_resizable (stage_x11->wrapper); - if (min_width_p) + if (resize) { - if (resize) - *min_width_p = 1; /* FIXME need API to set this */ - else - *min_width_p = stage_x11->xwin_width; + /* FIXME need API to set this */ + geometry->width = 1; + geometry->height = 1; + } + else + { + geometry->width = stage_x11->xwin_width; + geometry->height = stage_x11->xwin_height; } - - if (natural_width_p) - *natural_width_p = stage_x11->xwin_width; } static void -clutter_stage_x11_get_preferred_height (ClutterActor *self, - gfloat for_width, - gfloat *min_height_p, - gfloat *natural_height_p) +clutter_stage_x11_resize (ClutterStageWindow *stage_window, + gint width, + gint height) { - ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (self); - gboolean is_fullscreen, resize; + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); - is_fullscreen = FALSE; - g_object_get (G_OBJECT (stage_x11->wrapper), - "fullscreen-set", &is_fullscreen, - NULL); - - if (is_fullscreen || stage_x11->fullscreen_on_map) - { - int height; - - height = DisplayHeight (stage_x11->xdpy, stage_x11->xscreen); - - if (min_height_p) - *min_height_p = height; - - if (natural_height_p) - *natural_height_p = height; - - return; - } - - resize = clutter_stage_get_user_resizable (stage_x11->wrapper); - - if (min_height_p) - { - if (resize) - *min_height_p = 1; /* FIXME need API to set this */ - else - *min_height_p = stage_x11->xwin_height; - } - - if (natural_height_p) - *natural_height_p = stage_x11->xwin_height; -} - -static void -clutter_stage_x11_allocate (ClutterActor *self, - const ClutterActorBox *box, - ClutterAllocationFlags flags) -{ - ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (self); - ClutterActorClass *parent_class; - gint new_width, new_height; - - new_width = ABS ((int) (box->x2 - box->x1)); - new_height = ABS ((int) (box->y2 - box->y1)); - - if (new_width == 0 || new_height == 0) + if (width == 0 || height == 0) { /* Should not happen, if this turns up we need to debug it and * determine the cleanest way to fix. */ g_warning ("X11 stage not allowed to have 0 width or height"); - new_width = 1; - new_height = 1; + width = 1; + height = 1; } - CLUTTER_NOTE (BACKEND, "New allocation received: (%d, %d)", - new_width, - new_height); + CLUTTER_NOTE (BACKEND, "New size received: (%d, %d)", width, height); - if (new_width != stage_x11->xwin_width || - new_height != stage_x11->xwin_height) + if (width != stage_x11->xwin_width || + height != stage_x11->xwin_height) { - stage_x11->xwin_width = new_width; - stage_x11->xwin_height = new_height; + stage_x11->xwin_width = width; + stage_x11->xwin_height = height; - if (stage_x11->xwin != None && - !stage_x11->is_foreign_xwin) + if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin) { CLUTTER_NOTE (BACKEND, "%s: XResizeWindow[%x] (%d, %d)", G_STRLOC, @@ -289,18 +230,16 @@ clutter_stage_x11_allocate (ClutterActor *self, stage_x11->xwin_height); } - clutter_stage_x11_fix_window_size (stage_x11, new_width, new_height); + clutter_stage_x11_fix_window_size (stage_x11, width, height); if (stage_x11->xpixmap != None) { /* Need to recreate to resize */ - _clutter_actor_rerealize (self, NULL, NULL); + _clutter_actor_rerealize (CLUTTER_ACTOR (stage_x11->wrapper), + NULL, + NULL); } } - - /* chain up to fill in actor->priv->allocation */ - parent_class = CLUTTER_ACTOR_CLASS (clutter_stage_x11_parent_class); - parent_class->allocate (self, box, flags); } static inline void @@ -395,14 +334,16 @@ set_cursor_visible (ClutterStageX11 *stage_x11) } } -static void -clutter_stage_x11_realize (ClutterActor *actor) +static gboolean +clutter_stage_x11_realize (ClutterStageWindow *stage_window) { - ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor); + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); set_wm_pid (stage_x11); set_wm_title (stage_x11); set_cursor_visible (stage_x11); + + return TRUE; } static void @@ -599,7 +540,6 @@ clutter_stage_x11_show (ClutterStageWindow *stage_window, g_assert (STAGE_X11_IS_MAPPED (stage_x11)); - clutter_actor_map (CLUTTER_ACTOR (stage_x11)); clutter_actor_map (CLUTTER_ACTOR (stage_x11->wrapper)); /* we force a redraw here, so that by the time we have @@ -623,7 +563,6 @@ clutter_stage_x11_hide (ClutterStageWindow *stage_window) g_assert (!STAGE_X11_IS_MAPPED (stage_x11)); - clutter_actor_unmap (CLUTTER_ACTOR (stage_x11)); clutter_actor_unmap (CLUTTER_ACTOR (stage_x11->wrapper)); XWithdrawWindow (stage_x11->xdpy, @@ -658,16 +597,9 @@ static void clutter_stage_x11_class_init (ClutterStageX11Class *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); gobject_class->finalize = clutter_stage_x11_finalize; gobject_class->dispose = clutter_stage_x11_dispose; - - actor_class->realize = clutter_stage_x11_realize; - - actor_class->get_preferred_width = clutter_stage_x11_get_preferred_width; - actor_class->get_preferred_height = clutter_stage_x11_get_preferred_height; - actor_class->allocate = clutter_stage_x11_allocate; } static void @@ -705,6 +637,9 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface) iface->set_user_resizable = clutter_stage_x11_set_user_resizable; iface->show = clutter_stage_x11_show; iface->hide = clutter_stage_x11_hide; + iface->resize = clutter_stage_x11_resize; + iface->get_geometry = clutter_stage_x11_get_geometry; + iface->realize = clutter_stage_x11_realize; } /**