[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.
This commit is contained in:
parent
c69209a253
commit
6988744db7
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -33,9 +33,10 @@
|
||||
#include <pango/pango.h>
|
||||
|
||||
#include <clutter/clutter-actor.h>
|
||||
#include <clutter/clutter-stage.h>
|
||||
#include <clutter/clutter-event.h>
|
||||
#include <clutter/clutter-feature.h>
|
||||
#include <clutter/clutter-stage.h>
|
||||
#include <clutter/clutter-stage-window.h>
|
||||
|
||||
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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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))
|
||||
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 *
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
ClutterStageWindow *stage_window;
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterActor *stage;
|
||||
|
||||
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 *
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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)
|
||||
*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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user