Merge branch 'stage-window-object'

* stage-window-object:
  [x11] Fix Stage user-initiated resize
  [x11] Remove a useless forced paint
  [stage] Rework the Stage implementation class
This commit is contained in:
Emmanuele Bassi 2009-10-05 12:37:08 +01:00
commit 72243081b5
13 changed files with 261 additions and 222 deletions

View File

@ -89,6 +89,7 @@ source_h = \
$(srcdir)/clutter-shader-types.h \ $(srcdir)/clutter-shader-types.h \
$(srcdir)/clutter-stage.h \ $(srcdir)/clutter-stage.h \
$(srcdir)/clutter-stage-manager.h \ $(srcdir)/clutter-stage-manager.h \
$(srcdir)/clutter-stage-window.h \
$(srcdir)/clutter-texture.h \ $(srcdir)/clutter-texture.h \
$(srcdir)/clutter-text.h \ $(srcdir)/clutter-text.h \
$(srcdir)/clutter-timeline.h \ $(srcdir)/clutter-timeline.h \
@ -202,7 +203,6 @@ source_h_priv = \
$(srcdir)/clutter-private.h \ $(srcdir)/clutter-private.h \
$(srcdir)/clutter-id-pool.h \ $(srcdir)/clutter-id-pool.h \
$(srcdir)/clutter-script-private.h \ $(srcdir)/clutter-script-private.h \
$(srcdir)/clutter-stage-window.h \
$(srcdir)/clutter-timeout-interval.h \ $(srcdir)/clutter-timeout-interval.h \
$(NULL) $(NULL)

View File

@ -258,14 +258,14 @@ _clutter_backend_post_parse (ClutterBackend *backend,
return TRUE; return TRUE;
} }
ClutterActor * ClutterStageWindow *
_clutter_backend_create_stage (ClutterBackend *backend, _clutter_backend_create_stage (ClutterBackend *backend,
ClutterStage *wrapper, ClutterStage *wrapper,
GError **error) GError **error)
{ {
ClutterBackendClass *klass; ClutterBackendClass *klass;
ClutterStageManager *stage_manager; 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_BACKEND (backend), FALSE);
g_return_val_if_fail (CLUTTER_IS_STAGE (wrapper), 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); klass = CLUTTER_BACKEND_GET_CLASS (backend);
if (klass->create_stage) 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; return NULL;
g_assert (CLUTTER_IS_STAGE_WINDOW (stage)); g_assert (CLUTTER_IS_STAGE_WINDOW (stage_window));
_clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage)); _clutter_stage_set_window (wrapper, stage_window);
_clutter_stage_manager_add_stage (stage_manager, wrapper); _clutter_stage_manager_add_stage (stage_manager, wrapper);
return stage; return stage_window;
} }
void void

View File

@ -33,9 +33,10 @@
#include <pango/pango.h> #include <pango/pango.h>
#include <clutter/clutter-actor.h> #include <clutter/clutter-actor.h>
#include <clutter/clutter-stage.h>
#include <clutter/clutter-event.h> #include <clutter/clutter-event.h>
#include <clutter/clutter-feature.h> #include <clutter/clutter-feature.h>
#include <clutter/clutter-stage.h>
#include <clutter/clutter-stage-window.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -67,7 +68,7 @@ struct _ClutterBackendClass
GError **error); GError **error);
gboolean (* post_parse) (ClutterBackend *backend, gboolean (* post_parse) (ClutterBackend *backend,
GError **error); GError **error);
ClutterActor * (* create_stage) (ClutterBackend *backend, ClutterStageWindow *(* create_stage) (ClutterBackend *backend,
ClutterStage *wrapper, ClutterStage *wrapper,
GError **error); GError **error);
void (* init_events) (ClutterBackend *backend); void (* init_events) (ClutterBackend *backend);

View File

@ -188,7 +188,7 @@ GType _clutter_backend_impl_get_type (void);
void _clutter_backend_redraw (ClutterBackend *backend, void _clutter_backend_redraw (ClutterBackend *backend,
ClutterStage *stage); ClutterStage *stage);
ClutterActor *_clutter_backend_create_stage (ClutterBackend *backend, ClutterStageWindow *_clutter_backend_create_stage (ClutterBackend *backend,
ClutterStage *wrapper, ClutterStage *wrapper,
GError **error); GError **error);
void _clutter_backend_ensure_context (ClutterBackend *backend, void _clutter_backend_ensure_context (ClutterBackend *backend,

View File

@ -26,8 +26,85 @@ clutter_stage_window_get_type (void)
&stage_window_info, 0); &stage_window_info, 0);
g_type_interface_add_prerequisite (stage_window_type, g_type_interface_add_prerequisite (stage_window_type,
CLUTTER_TYPE_ACTOR); G_TYPE_OBJECT);
} }
return stage_window_type; 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);
}

View File

@ -28,13 +28,46 @@ struct _ClutterStageWindowIface
void (* set_user_resizable) (ClutterStageWindow *stage_window, void (* set_user_resizable) (ClutterStageWindow *stage_window,
gboolean is_resizable); gboolean is_resizable);
gboolean (* realize) (ClutterStageWindow *stage_window);
void (* unrealize) (ClutterStageWindow *stage_window);
void (* show) (ClutterStageWindow *stage_window, void (* show) (ClutterStageWindow *stage_window,
gboolean do_raise); gboolean do_raise);
void (* hide) (ClutterStageWindow *stage_window); 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; 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 G_END_DECLS
#endif /* __CLUTTER_STAGE_WINDOW_H__ */ #endif /* __CLUTTER_STAGE_WINDOW_H__ */

View File

@ -78,7 +78,7 @@ G_DEFINE_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP);
struct _ClutterStagePrivate struct _ClutterStagePrivate
{ {
/* the stage implementation */ /* the stage implementation */
ClutterActor *impl; ClutterStageWindow *impl;
ClutterColor color; ClutterColor color;
ClutterPerspective perspective; ClutterPerspective perspective;
@ -134,14 +134,18 @@ clutter_stage_get_preferred_width (ClutterActor *self,
gfloat *natural_width_p) gfloat *natural_width_p)
{ {
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
ClutterGeometry geom = { 0, };
if (priv->impl == NULL) if (priv->impl == NULL)
return; return;
CLUTTER_ACTOR_GET_CLASS (priv->impl)->get_preferred_width (priv->impl, _clutter_stage_window_get_geometry (priv->impl, &geom);
for_height,
min_width_p, if (min_width_p)
natural_width_p); *min_width_p = geom.width;
if (natural_width_p)
*natural_width_p = geom.width;
} }
static void static void
@ -151,14 +155,18 @@ clutter_stage_get_preferred_height (ClutterActor *self,
gfloat *natural_height_p) gfloat *natural_height_p)
{ {
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
ClutterGeometry geom = { 0, };
if (priv->impl == NULL) if (priv->impl == NULL)
return; return;
CLUTTER_ACTOR_GET_CLASS (priv->impl)->get_preferred_height (priv->impl, _clutter_stage_window_get_geometry (priv->impl, &geom);
for_width,
min_height_p, if (min_height_p)
natural_height_p); *min_height_p = geom.height;
if (natural_height_p)
*natural_height_p = geom.height;
} }
static void static void
clutter_stage_allocate (ClutterActor *self, clutter_stage_allocate (ClutterActor *self,
@ -167,12 +175,16 @@ clutter_stage_allocate (ClutterActor *self,
{ {
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
gboolean origin_changed; gboolean origin_changed;
gint width, height;
origin_changed = (flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED) ? TRUE : FALSE; origin_changed = (flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED) ? TRUE : FALSE;
if (priv->impl == NULL) if (priv->impl == NULL)
return; 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) /* if the stage is fixed size (for instance, it's using a frame-buffer)
* then we simply ignore any allocation request and override the * then we simply ignore any allocation request and override the
* allocation chain. * allocation chain.
@ -183,41 +195,31 @@ clutter_stage_allocate (ClutterActor *self,
CLUTTER_NOTE (LAYOUT, CLUTTER_NOTE (LAYOUT,
"Following allocation to %dx%d (origin %s)", "Following allocation to %dx%d (origin %s)",
(int) (box->x2 - box->x1), width, height,
(int) (box->y2 - box->y1),
origin_changed ? "changed" : "not changed"); origin_changed ? "changed" : "not changed");
klass = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class); klass = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class);
klass->allocate (self, box, flags); klass->allocate (self, box, flags);
klass = CLUTTER_ACTOR_GET_CLASS (priv->impl); _clutter_stage_window_resize (priv->impl, width, height);
klass->allocate (priv->impl, box, flags);
} }
else else
{ {
ClutterActorBox override = { 0, }; ClutterActorBox override = { 0, };
ClutterGeometry geom = { 0, };
ClutterActorClass *klass; ClutterActorClass *klass;
gfloat natural_width, natural_height;
/* propagate the allocation */ _clutter_stage_window_get_geometry (priv->impl, &geom);
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);
override.x1 = 0; override.x1 = 0;
override.y1 = 0; override.y1 = 0;
override.x2 = natural_width; override.x2 = geom.width;
override.y2 = natural_height; override.y2 = geom.height;
CLUTTER_NOTE (LAYOUT, CLUTTER_NOTE (LAYOUT,
"Overrigin original allocation of %dx%d " "Overrigin original allocation of %dx%d "
"with %dx%d (origin %s)", "with %dx%d (origin %s)",
(int) (box->x2 - box->x1), width, height,
(int) (box->y2 - box->y1),
(int) (override.x2), (int) (override.x2),
(int) (override.y2), (int) (override.y2),
origin_changed ? "changed" : "not changed"); origin_changed ? "changed" : "not changed");
@ -260,8 +262,10 @@ clutter_stage_paint (ClutterActor *self)
else else
cogl_disable_fog (); cogl_disable_fog ();
#if 0
CLUTTER_NOTE (PAINT, "Proxying the paint to the stage implementation"); 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 */ /* this will take care of painting every child */
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (self); CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (self);
@ -283,6 +287,7 @@ static void
clutter_stage_realize (ClutterActor *self) clutter_stage_realize (ClutterActor *self)
{ {
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
gboolean is_realized;
/* Make sure the viewport and projection matrix are valid for the /* Make sure the viewport and projection matrix are valid for the
* first paint (which will likely occur before the ConfigureNotify * 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); CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_SYNC_MATRICES);
g_assert (priv->impl != NULL); 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 /* ensure that the stage is using the context if the
* realization sequence was successful * realization sequence was successful
*/ */
if (CLUTTER_ACTOR_IS_REALIZED (priv->impl)) if (is_realized)
clutter_stage_ensure_current (CLUTTER_STAGE (self)); {
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
clutter_stage_ensure_current (CLUTTER_STAGE (self));
}
else else
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED); CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
} }
@ -309,7 +317,9 @@ clutter_stage_unrealize (ClutterActor *self)
/* and then unrealize the implementation */ /* and then unrealize the implementation */
g_assert (priv->impl != NULL); 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)); clutter_stage_ensure_current (CLUTTER_STAGE (self));
} }
@ -318,7 +328,6 @@ static void
clutter_stage_show (ClutterActor *self) clutter_stage_show (ClutterActor *self)
{ {
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
ClutterStageWindow *impl;
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->show (self); CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->show (self);
@ -327,19 +336,16 @@ clutter_stage_show (ClutterActor *self)
_clutter_stage_maybe_relayout (self); _clutter_stage_maybe_relayout (self);
g_assert (priv->impl != NULL); g_assert (priv->impl != NULL);
impl = CLUTTER_STAGE_WINDOW (priv->impl); _clutter_stage_window_show (priv->impl, TRUE);
CLUTTER_STAGE_WINDOW_GET_IFACE (impl)->show (impl, TRUE);
} }
static void static void
clutter_stage_hide (ClutterActor *self) clutter_stage_hide (ClutterActor *self)
{ {
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
ClutterStageWindow *impl;
g_assert (priv->impl != NULL); g_assert (priv->impl != NULL);
impl = CLUTTER_STAGE_WINDOW (priv->impl); _clutter_stage_window_hide (priv->impl);
CLUTTER_STAGE_WINDOW_GET_IFACE (impl)->hide (impl);
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->hide (self); CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->hide (self);
} }
@ -375,7 +381,7 @@ static void
clutter_stage_real_fullscreen (ClutterStage *stage) clutter_stage_real_fullscreen (ClutterStage *stage)
{ {
ClutterStagePrivate *priv = stage->priv; ClutterStagePrivate *priv = stage->priv;
gfloat natural_width, natural_height; ClutterGeometry geom;
ClutterActorBox box; ClutterActorBox box;
/* we need to force an allocation here because the size /* 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 * the fact that fullscreening the stage on the X11 backends
* is really an asynchronous operation * is really an asynchronous operation
*/ */
clutter_actor_get_preferred_size (CLUTTER_ACTOR (priv->impl), _clutter_stage_window_get_geometry (priv->impl, &geom);
NULL, NULL,
&natural_width, &natural_height);
box.x1 = 0; box.x1 = 0;
box.y1 = 0; box.y1 = 0;
box.x2 = natural_width; box.x2 = geom.width;
box.y2 = natural_height; box.y2 = geom.height;
clutter_actor_allocate (CLUTTER_ACTOR (stage), clutter_actor_allocate (CLUTTER_ACTOR (stage),
&box, &box,
@ -723,11 +727,11 @@ clutter_stage_dispose (GObject *object)
_clutter_stage_manager_remove_stage (stage_manager, stage); _clutter_stage_manager_remove_stage (stage_manager, stage);
if (priv->impl) if (priv->impl != NULL)
{ {
CLUTTER_NOTE (BACKEND, "Disposing of the stage implementation"); 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; priv->impl = NULL;
} }
@ -1008,16 +1012,11 @@ clutter_stage_init (ClutterStage *self)
{ {
g_warning ("Unable to create a new stage, falling back to the " g_warning ("Unable to create a new stage, falling back to the "
"default stage."); "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 */ /* at this point we must have a default stage, or we're screwed */
g_assert (priv->impl != NULL); 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 (); priv->event_queue = g_queue_new ();
@ -2044,7 +2043,7 @@ _clutter_stage_set_window (ClutterStage *stage,
if (stage->priv->impl) if (stage->priv->impl)
g_object_unref (stage->priv->impl); g_object_unref (stage->priv->impl);
stage->priv->impl = CLUTTER_ACTOR (stage_window); stage->priv->impl = stage_window;
} }
ClutterStageWindow * ClutterStageWindow *

View File

@ -67,6 +67,7 @@
#include "clutter-shader-types.h" #include "clutter-shader-types.h"
#include "clutter-stage.h" #include "clutter-stage.h"
#include "clutter-stage-manager.h" #include "clutter-stage-manager.h"
#include "clutter-stage-window.h"
#include "clutter-texture.h" #include "clutter-texture.h"
#include "clutter-text.h" #include "clutter-text.h"
#include "clutter-timeline.h" #include "clutter-timeline.h"

View File

@ -585,22 +585,22 @@ clutter_backend_glx_redraw (ClutterBackend *backend,
} }
} }
static ClutterActor * static ClutterStageWindow *
clutter_backend_glx_create_stage (ClutterBackend *backend, clutter_backend_glx_create_stage (ClutterBackend *backend,
ClutterStage *wrapper, ClutterStage *wrapper,
GError **error) GError **error)
{ {
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
ClutterStageX11 *stage_x11; ClutterStageWindow *stage_window;
ClutterActor *stage; ClutterStageX11 *stage_x11;
CLUTTER_NOTE (BACKEND, "Creating stage of type '%s'", CLUTTER_NOTE (BACKEND, "Creating stage of type '%s'",
g_type_name (CLUTTER_STAGE_TYPE)); 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 */ /* 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->xdpy = backend_x11->xdpy;
stage_x11->xwin_root = backend_x11->xwin_root; stage_x11->xwin_root = backend_x11->xwin_root;
stage_x11->xscreen = backend_x11->xscreen_num; stage_x11->xscreen = backend_x11->xscreen_num;
@ -609,13 +609,13 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
CLUTTER_NOTE (BACKEND, CLUTTER_NOTE (BACKEND,
"GLX stage created[%p] (dpy:%p, screen:%d, root:%u, wrap:%p)", "GLX stage created[%p] (dpy:%p, screen:%d, root:%u, wrap:%p)",
stage, stage_window,
stage_x11->xdpy, stage_x11->xdpy,
stage_x11->xscreen, stage_x11->xscreen,
(unsigned int) stage_x11->xwin_root, (unsigned int) stage_x11->xwin_root,
wrapper); wrapper);
return stage; return stage_window;
} }
static XVisualInfo * static XVisualInfo *

View File

@ -49,6 +49,8 @@
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
static ClutterStageWindowIface *clutter_stage_glx_parent_iface = NULL;
G_DEFINE_TYPE_WITH_CODE (ClutterStageGLX, G_DEFINE_TYPE_WITH_CODE (ClutterStageGLX,
clutter_stage_glx, clutter_stage_glx,
CLUTTER_TYPE_STAGE_X11, CLUTTER_TYPE_STAGE_X11,
@ -56,10 +58,10 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageGLX,
clutter_stage_window_iface_init)); clutter_stage_window_iface_init));
static void static void
clutter_stage_glx_unrealize (ClutterActor *actor) clutter_stage_glx_unrealize (ClutterStageWindow *stage_window)
{ {
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor); ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor); ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
gboolean was_offscreen; gboolean was_offscreen;
/* Note unrealize should free up any backend stage related resources */ /* 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); 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 (); clutter_x11_trap_x_errors ();
if (G_UNLIKELY (was_offscreen)) if (G_UNLIKELY (was_offscreen))
@ -110,19 +109,19 @@ clutter_stage_glx_unrealize (ClutterActor *actor)
CLUTTER_MARK (); CLUTTER_MARK ();
} }
static void static gboolean
clutter_stage_glx_realize (ClutterActor *actor) clutter_stage_glx_realize (ClutterStageWindow *stage_window)
{ {
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor); ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor); ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
ClutterBackend *backend; ClutterBackend *backend;
ClutterBackendGLX *backend_glx; ClutterBackendGLX *backend_glx;
ClutterBackendX11 *backend_x11; ClutterBackendX11 *backend_x11;
gboolean is_offscreen; gboolean is_offscreen;
CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]", CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]",
G_OBJECT_TYPE_NAME (actor), G_OBJECT_TYPE_NAME (stage_window),
actor); stage_window);
g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL); 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) if (stage_x11->xvisinfo == None)
{ {
g_critical ("Unable to find suitable GL visual."); g_critical ("Unable to find suitable GL visual.");
goto fail; return FALSE;
} }
if (stage_x11->xwin == None) 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_critical ("Unable to realize stage: %s", error->message);
g_error_free (error); g_error_free (error);
goto fail; return FALSE;
} }
CLUTTER_NOTE (BACKEND, "Successfully realized stage"); CLUTTER_NOTE (BACKEND, "Successfully realized stage");
@ -230,7 +229,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
if (stage_x11->xvisinfo == None) if (stage_x11->xvisinfo == None)
{ {
g_critical ("Unable to find suitable GL visual."); g_critical ("Unable to find suitable GL visual.");
goto fail; return FALSE;
} }
stage_x11->xpixmap = XCreatePixmap (stage_x11->xdpy, 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_critical ("Unable to realize stage: %s", error->message);
g_error_free (error); g_error_free (error);
goto fail; return FALSE;
} }
CLUTTER_NOTE (BACKEND, "Successfully realized stage"); CLUTTER_NOTE (BACKEND, "Successfully realized stage");
} }
/* we need to chain up to the X11 stage implementation in order to /* chain up to the StageX11 implementation */
* set the window state in case we set it before realizing the stage return clutter_stage_glx_parent_iface->realize (stage_window);
*/
CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->realize (actor);
return;
fail:
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
} }
static void static void
@ -283,12 +276,8 @@ static void
clutter_stage_glx_class_init (ClutterStageGLXClass *klass) clutter_stage_glx_class_init (ClutterStageGLXClass *klass)
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
gobject_class->dispose = clutter_stage_glx_dispose; gobject_class->dispose = clutter_stage_glx_dispose;
actor_class->realize = clutter_stage_glx_realize;
actor_class->unrealize = clutter_stage_glx_unrealize;
} }
static void static void
@ -299,5 +288,10 @@ clutter_stage_glx_init (ClutterStageGLX *stage)
static void static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface) 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 */ /* the rest is inherited from ClutterStageX11 */
} }

View File

@ -479,8 +479,9 @@ event_translate (ClutterBackend *backend,
xevent->xconfigure.width, xevent->xconfigure.width,
xevent->xconfigure.height); xevent->xconfigure.height);
stage_x11->xwin_width = xevent->xconfigure.width; clutter_actor_set_size (CLUTTER_ACTOR (stage),
stage_x11->xwin_height = xevent->xconfigure.height; xevent->xconfigure.width,
xevent->xconfigure.height);
CLUTTER_UNSET_PRIVATE_FLAGS (stage_x11->wrapper, CLUTTER_UNSET_PRIVATE_FLAGS (stage_x11->wrapper,
CLUTTER_STAGE_IN_RESIZE); CLUTTER_STAGE_IN_RESIZE);
@ -489,8 +490,6 @@ event_translate (ClutterBackend *backend,
* to set up the GL viewport with the new size * to set up the GL viewport with the new size
*/ */
clutter_stage_ensure_viewport (stage); clutter_stage_ensure_viewport (stage);
clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_x11->wrapper));
} }
res = FALSE; res = FALSE;
break; break;

View File

@ -50,7 +50,7 @@ static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterStageX11, G_DEFINE_TYPE_WITH_CODE (ClutterStageX11,
clutter_stage_x11, clutter_stage_x11,
CLUTTER_TYPE_GROUP, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init)); 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); 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; XSizeHints *size_hints;
gfloat min_width, min_height;
size_hints = XAllocSizeHints(); size_hints = XAllocSizeHints();
_clutter_stage_window_get_geometry (CLUTTER_STAGE_WINDOW (stage_x11),
&min_size);
if (new_width < 0) if (new_width < 0)
clutter_actor_get_preferred_width (CLUTTER_ACTOR (stage_x11), min_width = min_size.width;
-1,
&min_width, NULL);
else else
min_width = new_width; min_width = new_width;
if (new_height < 0) if (new_height < 0)
clutter_actor_get_preferred_height (CLUTTER_ACTOR (stage_x11), min_height = min_size.height;
min_width,
&min_height, NULL);
else else
min_height = new_height; min_height = new_height;
@ -122,8 +122,8 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
restrictions on the window size */ restrictions on the window size */
if (!stage_x11->fullscreen_on_map) if (!stage_x11->fullscreen_on_map)
{ {
size_hints->min_width = (int) min_width; size_hints->min_width = min_width;
size_hints->min_height = (int) min_height; size_hints->min_height = min_height;
size_hints->flags = PMinSize; size_hints->flags = PMinSize;
if (!resize) if (!resize)
@ -154,12 +154,10 @@ clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11)
} }
static void static void
clutter_stage_x11_get_preferred_width (ClutterActor *self, clutter_stage_x11_get_geometry (ClutterStageWindow *stage_window,
gfloat for_height, ClutterGeometry *geometry)
gfloat *min_width_p,
gfloat *natural_width_p)
{ {
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (self); ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
gboolean is_fullscreen, resize; gboolean is_fullscreen, resize;
is_fullscreen = FALSE; is_fullscreen = FALSE;
@ -169,110 +167,56 @@ clutter_stage_x11_get_preferred_width (ClutterActor *self,
if (is_fullscreen || stage_x11->fullscreen_on_map) if (is_fullscreen || stage_x11->fullscreen_on_map)
{ {
int width; geometry->width = DisplayWidth (stage_x11->xdpy, stage_x11->xscreen);
geometry->height = DisplayHeight (stage_x11->xdpy, stage_x11->xscreen);
width = DisplayWidth (stage_x11->xdpy, stage_x11->xscreen);
if (min_width_p)
*min_width_p = width;
if (natural_width_p)
*natural_width_p = width;
return; return;
} }
resize = clutter_stage_get_user_resizable (stage_x11->wrapper); resize = clutter_stage_get_user_resizable (stage_x11->wrapper);
if (min_width_p) if (resize)
{ {
if (resize) /* FIXME need API to set this */
*min_width_p = 1; /* FIXME need API to set this */ geometry->width = 1;
else geometry->height = 1;
*min_width_p = stage_x11->xwin_width; }
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 static void
clutter_stage_x11_get_preferred_height (ClutterActor *self, clutter_stage_x11_resize (ClutterStageWindow *stage_window,
gfloat for_width, gint width,
gfloat *min_height_p, gint height)
gfloat *natural_height_p)
{ {
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (self); ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
gboolean is_fullscreen, resize; gboolean resize;
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); resize = clutter_stage_get_user_resizable (stage_x11->wrapper);
if (min_height_p) if (width == 0 || height == 0)
{
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)
{ {
/* Should not happen, if this turns up we need to debug it and /* Should not happen, if this turns up we need to debug it and
* determine the cleanest way to fix. * determine the cleanest way to fix.
*/ */
g_warning ("X11 stage not allowed to have 0 width or height"); g_warning ("X11 stage not allowed to have 0 width or height");
new_width = 1; width = 1;
new_height = 1; height = 1;
} }
CLUTTER_NOTE (BACKEND, "New allocation received: (%d, %d)", CLUTTER_NOTE (BACKEND, "New size received: (%d, %d)", width, height);
new_width,
new_height);
if (new_width != stage_x11->xwin_width || if (width != stage_x11->xwin_width ||
new_height != stage_x11->xwin_height) height != stage_x11->xwin_height)
{ {
stage_x11->xwin_width = new_width; stage_x11->xwin_width = width;
stage_x11->xwin_height = new_height; stage_x11->xwin_height = height;
if (stage_x11->xwin != None && if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin)
!stage_x11->is_foreign_xwin)
{ {
CLUTTER_NOTE (BACKEND, "%s: XResizeWindow[%x] (%d, %d)", CLUTTER_NOTE (BACKEND, "%s: XResizeWindow[%x] (%d, %d)",
G_STRLOC, G_STRLOC,
@ -289,18 +233,17 @@ clutter_stage_x11_allocate (ClutterActor *self,
stage_x11->xwin_height); stage_x11->xwin_height);
} }
clutter_stage_x11_fix_window_size (stage_x11, new_width, new_height); if (!resize)
clutter_stage_x11_fix_window_size (stage_x11, width, height);
if (stage_x11->xpixmap != None) if (stage_x11->xpixmap != None)
{ {
/* Need to recreate to resize */ /* 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 static inline void
@ -395,14 +338,16 @@ set_cursor_visible (ClutterStageX11 *stage_x11)
} }
} }
static void static gboolean
clutter_stage_x11_realize (ClutterActor *actor) 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_pid (stage_x11);
set_wm_title (stage_x11); set_wm_title (stage_x11);
set_cursor_visible (stage_x11); set_cursor_visible (stage_x11);
return TRUE;
} }
static void static void
@ -599,14 +544,8 @@ clutter_stage_x11_show (ClutterStageWindow *stage_window,
g_assert (STAGE_X11_IS_MAPPED (stage_x11)); g_assert (STAGE_X11_IS_MAPPED (stage_x11));
clutter_actor_map (CLUTTER_ACTOR (stage_x11));
clutter_actor_map (CLUTTER_ACTOR (stage_x11->wrapper)); clutter_actor_map (CLUTTER_ACTOR (stage_x11->wrapper));
/* we force a redraw here, so that by the time we have
* been mapped, the window has contents
*/
_clutter_do_redraw (CLUTTER_STAGE (stage_x11->wrapper));
XMapWindow (stage_x11->xdpy, stage_x11->xwin); XMapWindow (stage_x11->xdpy, stage_x11->xwin);
} }
} }
@ -623,7 +562,6 @@ clutter_stage_x11_hide (ClutterStageWindow *stage_window)
g_assert (!STAGE_X11_IS_MAPPED (stage_x11)); g_assert (!STAGE_X11_IS_MAPPED (stage_x11));
clutter_actor_unmap (CLUTTER_ACTOR (stage_x11));
clutter_actor_unmap (CLUTTER_ACTOR (stage_x11->wrapper)); clutter_actor_unmap (CLUTTER_ACTOR (stage_x11->wrapper));
XWithdrawWindow (stage_x11->xdpy, XWithdrawWindow (stage_x11->xdpy,
@ -658,16 +596,9 @@ static void
clutter_stage_x11_class_init (ClutterStageX11Class *klass) clutter_stage_x11_class_init (ClutterStageX11Class *klass)
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
gobject_class->finalize = clutter_stage_x11_finalize; gobject_class->finalize = clutter_stage_x11_finalize;
gobject_class->dispose = clutter_stage_x11_dispose; 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 static void
@ -705,6 +636,9 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
iface->set_user_resizable = clutter_stage_x11_set_user_resizable; iface->set_user_resizable = clutter_stage_x11_set_user_resizable;
iface->show = clutter_stage_x11_show; iface->show = clutter_stage_x11_show;
iface->hide = clutter_stage_x11_hide; 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;
} }
/** /**

View File

@ -159,6 +159,7 @@ test_actors_main (int argc, char *argv[])
clutter_stage_set_title (CLUTTER_STAGE (stage), "Clone Test"); clutter_stage_set_title (CLUTTER_STAGE (stage), "Clone Test");
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
oh = g_new (SuperOH, 1); oh = g_new (SuperOH, 1);
oh->stage = stage; oh->stage = stage;