2008-05-12 Emmanuele Bassi <ebassi@openedhand.com>

Rework the stage wrapper/implementation relation: remove
	duplicated code and all the bookkeeping from the backends into
	ClutterStage whenever possible, to reduce the amount of	work a
	backend must do (and possibly get wrong). Thanks to Tommi
	Komulainen.

	* clutter/clutter-main.c:
	(clutter_init_with_args), (clutter_init): Realize the default
	stage after creation. The default stage is special, because we
	use it in the initialization sequence. This removes the burden
	from the backends and reduces the things a backend can get
	wrong.

	* clutter/clutter-stage.c:
	(clutter_stage_show): Make sure to realize the implementation if
	it hasn't been realized yet.

	(clutter_stage_realize): Set the REALIZED flag and call
	clutter_stage_ensure_current() if the implementation was
	successfully realized.

	(clutter_stage_unrealized): Call clutter_stage_ensure_current()
	on unrealize.

	* clutter/glx/clutter-backend-glx.c:
	(clutter_backend_glx_create_stage): Do not realize the stage anymore
	when creating it, and let the normal realization sequence take
	place.

	(clutter_backend_glx_ensure_context): Trap for X11 errors.

	* clutter/glx/clutter-stage-glx.c:
	(clutter_stage_glx_realize): Chain up to the X11 implementation
	so that we can set up the window state (title, cursor visibility)
	when we actually have a X window. Also, do not call
	clutter_stage_ensure_current(), and rely on the wrapper to do
	it for us. This means we can drop setting the REALIZED flag on
	the wrapper.

	(clutter_stage_glx_unrealize): Do not call
	clutter_stage_ensure_current() ourselves, and rely on the wrapper
	to do it for us.

	* clutter/x11/clutter-stage-x11.c:
	(set_wm_title),	(set_cursor_visible): Move the WM title and
	cursor visibility code inside their own functions.

	(clutter_stage_x11_realize): Set the window title and whether the
	cursor is visible or not after realizing the stage.

	(clutter_stage_x11_set_cursor_visible),
	(clutter_stage_x11_set_title): Call set_wm_title() and
	set_cursor_visible().

	(clutter_stage_x11_finalize): Free the title string.

	* clutter/x11/clutter-stage-x11.h: Save more of the stage state,
	so that we can set it even when the stage hasn't been realized
	yet.

	* clutter/eglnative/clutter-backend-egl.c:
	(clutter_backend_egl_create_stage):
	* clutter/eglnative/clutter-stage-egl.c:
	(clutter_stage_egl_unrealize),
	(clutter_stage_egl_realize): Update the eglnative backend.

	* clutter/eglx/clutter-backend-egl.c:
	(clutter_backend_egl_ensure_context),
	(clutter_backend_egl_create_stage):
	* clutter/eglx/clutter-stage-egl.c:
	(clutter_stage_egl_unrealize),
	(clutter_stage_egl_realize): Update the eglx backend.

	* clutter/sdl/clutter-backend-sdl.c:
	(clutter_backend_sdl_create_stage):
	* clutter/sdl/clutter-stage-sdl.c:
	(clutter_stage_sdl_realize): Update the sdl backend.

	* clutter/fruity/clutter-backend-fruity.c:
	(clutter_backend_fruity_create_stage):
	* clutter/sdl/clutter-stage-fruity.c:
	(clutter_stage_fruity_realize): Update the fruity backend.

	* tests/test-multistage.c (on_button_press): Bail out if
	clutter_stage_new() returns NULL.

	* HACKING.backends: Update backend writing documentation.
This commit is contained in:
Emmanuele Bassi
2008-05-12 15:26:37 +00:00
parent c76e576141
commit 101a3cac4e
17 changed files with 315 additions and 241 deletions

View File

@ -1103,6 +1103,16 @@ clutter_init_with_args (int *argc,
return CLUTTER_INIT_ERROR_INTERNAL;
}
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to realize the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
_clutter_backend_init_events (clutter_context->backend);
_clutter_feature_init ();
@ -1195,6 +1205,14 @@ clutter_init (int *argc,
return CLUTTER_INIT_ERROR_INTERNAL;
}
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
g_critical ("Unable to realize the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
/* Initiate event collection */
_clutter_backend_init_events (context->backend);

View File

@ -187,13 +187,16 @@ clutter_stage_realize (ClutterActor *self)
{
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
/* then realize the implementation */
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
g_assert (priv->impl != NULL);
CLUTTER_ACTOR_GET_CLASS (priv->impl)->realize (priv->impl);
/* set the flag on the wrapper if the implementation was successful */
/* ensure that the stage is using the context if the
* realization sequence was successful
*/
if (CLUTTER_ACTOR_IS_REALIZED (priv->impl))
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
clutter_stage_ensure_current (CLUTTER_STAGE (self));
else
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
}
@ -209,6 +212,8 @@ clutter_stage_unrealize (ClutterActor *self)
/* and then unrealize the implementation */
g_assert (priv->impl != NULL);
CLUTTER_ACTOR_GET_CLASS (priv->impl)->unrealize (priv->impl);
clutter_stage_ensure_current (CLUTTER_STAGE (self));
}
static void
@ -217,6 +222,10 @@ clutter_stage_show (ClutterActor *self)
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
g_assert (priv->impl != NULL);
if (!CLUTTER_ACTOR_IS_REALIZED (priv->impl))
clutter_actor_realize (priv->impl);
clutter_actor_show (priv->impl);
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->show (self);

View File

@ -100,19 +100,6 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
_clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage));
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to realize the main stage");
g_object_unref (stage);
return NULL;
}
backend_egl->stage = CLUTTER_ACTOR (stage_egl);
return stage;

View File

@ -62,8 +62,6 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
eglDestroySurface (clutter_egl_display (), stage_egl->egl_surface);
stage_egl->egl_surface = EGL_NO_SURFACE;
}
clutter_stage_ensure_current (stage_egl->wrapper);
}
static void
@ -179,7 +177,6 @@ clutter_stage_egl_realize (ClutterActor *actor)
}
CLUTTER_NOTE (BACKEND, "Marking stage as realized and setting context");
CLUTTER_ACTOR_SET_FLAGS (stage_egl->wrapper, CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_SET_FLAGS (stage_egl, CLUTTER_ACTOR_REALIZED);
/* eglnative can have only one stage */
@ -202,8 +199,6 @@ clutter_stage_egl_realize (ClutterActor *actor)
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
CLUTTER_SET_PRIVATE_FLAGS (stage_egl->wrapper, CLUTTER_ACTOR_SYNC_MATRICES);
}
static void

View File

@ -81,6 +81,8 @@ clutter_backend_egl_ensure_context (ClutterBackend *backend,
if (!backend_egl->egl_context)
return;
clutter_x11_trap_x_errors ();
/* we might get here inside the final dispose cycle, so we
* need to handle this gracefully
*/
@ -100,6 +102,11 @@ clutter_backend_egl_ensure_context (ClutterBackend *backend,
stage_egl->egl_surface,
stage_egl->egl_surface,
backend_egl->egl_context);
if (clutter_x11_untrap_x_errors ())
g_critical ("Unable to make the stage window 0x%x the current "
"EGLX drawable",
(int) stage_x11->xwin);
}
}
@ -245,19 +252,6 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
stage_x11->xscreen,
(unsigned int) stage_x11->xwin_root);
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to realize the main stage");
g_object_unref (stage);
return NULL;
}
return stage;
}

View File

@ -63,8 +63,6 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
stage_egl->egl_surface = EGL_NO_SURFACE;
}
clutter_stage_ensure_current (stage_x11->wrapper);
XSync (stage_x11->xdpy, False);
clutter_x11_untrap_x_errors ();
@ -91,6 +89,11 @@ clutter_stage_egl_realize (ClutterActor *actor)
if (G_LIKELY (!is_offscreen))
{
int c;
int num_configs;
int max_tex_units;
EGLConfig *all_configs;
EGLint cfg_attribs[] = {
EGL_BUFFER_SIZE, EGL_DONT_CARE,
EGL_RED_SIZE, 5,
@ -104,49 +107,48 @@ clutter_stage_egl_realize (ClutterActor *actor)
2,
&config_count);
int c;
int num_configs;
EGLConfig *all_configs;
eglGetConfigs (clutter_eglx_display(), NULL, 0, &num_configs);
eglGetConfigs (clutter_eglx_display (), NULL, 0, &num_configs);
all_configs = g_malloc (num_configs * sizeof (EGLConfig));
eglGetConfigs (clutter_eglx_display(),
eglGetConfigs (clutter_eglx_display (),
all_configs,
num_configs,
&num_configs);
for (c=0; c<num_configs; ++c)
for (c = 0; c < num_configs; ++c)
{
EGLint red=-1, green=-1, blue=-1, alpha=-1, stencil=-1;
eglGetConfigAttrib (clutter_eglx_display(),
EGLint red = -1, green = -1, blue = -1, alpha = -1, stencil = -1;
eglGetConfigAttrib (clutter_eglx_display (),
all_configs[c],
EGL_RED_SIZE, &red);
eglGetConfigAttrib (clutter_eglx_display(),
eglGetConfigAttrib (clutter_eglx_display (),
all_configs[c],
EGL_GREEN_SIZE, &green);
eglGetConfigAttrib (clutter_eglx_display(),
eglGetConfigAttrib (clutter_eglx_display (),
all_configs[c],
EGL_BLUE_SIZE, &blue);
eglGetConfigAttrib (clutter_eglx_display(),
eglGetConfigAttrib (clutter_eglx_display (),
all_configs[c],
EGL_ALPHA_SIZE, &alpha);
eglGetConfigAttrib (clutter_eglx_display(),
eglGetConfigAttrib (clutter_eglx_display (),
all_configs[c],
EGL_STENCIL_SIZE, &stencil);
printf("EGLConfig === R:%d G:%d B:%d A:%d S:%d \n",
red, green, blue, alpha, stencil);
CLUTTER_NOTE (BACKEND, "EGLConfig == R:%d G:%d B:%d A:%d S:%d \n",
red, green, blue, alpha, stencil);
}
int max_tex_units = 0;
max_tex_units = 0;
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_tex_units);
printf("Texture units: %d\n", max_tex_units);
CLUTTER_NOTE (BACKEND, "Texture units: %d\n", max_tex_units);
g_free (all_configs);
if (status != EGL_TRUE)
g_warning ("eglGetConfigs failed");
{
g_critical ("eglGetConfigs failed");
goto fail;
}
status = eglChooseConfig (backend_egl->edpy,
cfg_attribs,
@ -155,7 +157,10 @@ clutter_stage_egl_realize (ClutterActor *actor)
&config_count);
if (status != EGL_TRUE)
g_warning ("eglChooseConfig failed");
{
g_critical ("eglChooseConfig failed");
goto fail;
}
if (stage_x11->xwin == None)
stage_x11->xwin =
@ -198,9 +203,7 @@ clutter_stage_egl_realize (ClutterActor *actor)
if (stage_egl->egl_surface == EGL_NO_SURFACE)
{
g_critical ("Unable to create an EGL surface");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
goto fail;
}
if (G_UNLIKELY (backend_egl->egl_context == None))
@ -215,26 +218,26 @@ clutter_stage_egl_realize (ClutterActor *actor)
if (backend_egl->egl_context == EGL_NO_CONTEXT)
{
g_critical ("Unable to create a suitable EGL context");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
goto fail;
}
}
/* this will make sure to set the current context */
CLUTTER_NOTE (BACKEND, "Marking stage as realized and setting context");
CLUTTER_ACTOR_SET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_SET_FLAGS (stage_x11, CLUTTER_ACTOR_REALIZED);
clutter_stage_ensure_current (stage_x11->wrapper);
CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
}
else
{
g_warning("EGLX Backend does not support offscreen rendering");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
g_critical ("EGLX Backend does not support offscreen rendering");
goto fail;
}
CLUTTER_SET_PRIVATE_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_SYNC_MATRICES);
/* 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);
}
static void

View File

@ -99,19 +99,6 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
_clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage));
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to realize the main stage");
g_object_unref (stage);
return NULL;
}
backend_egl->stage = CLUTTER_ACTOR (stage_egl);
return stage;

View File

@ -61,8 +61,6 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
eglDestroySurface (clutter_egl_display (), stage_egl->egl_surface);
stage_egl->egl_surface = EGL_NO_SURFACE;
}
clutter_stage_ensure_current (stage_egl->wrapper);
}
static void
@ -108,7 +106,11 @@ clutter_stage_egl_realize (ClutterActor *actor)
&config_count);
if (status != EGL_TRUE)
g_warning ("eglChooseConfig failed");
{
g_critical ("eglChooseConfig failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
if (stage_egl->egl_surface != EGL_NO_SURFACE)
{
@ -133,7 +135,6 @@ clutter_stage_egl_realize (ClutterActor *actor)
if (stage_egl->egl_surface == EGL_NO_SURFACE)
{
g_critical ("Unable to create an EGL surface");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
@ -173,29 +174,24 @@ clutter_stage_egl_realize (ClutterActor *actor)
/* this will make sure to set the current context */
CLUTTER_NOTE (BACKEND, "Marking stage as realized and setting context");
CLUTTER_ACTOR_SET_FLAGS (stage_egl->wrapper, CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_SET_FLAGS (stage_egl, CLUTTER_ACTOR_REALIZED);
/* this should be done in ClutterBackend::ensure_context */
status = eglMakeCurrent (backend_egl->edpy,
stage_egl->egl_surface,
stage_egl->egl_surface,
backend_egl->egl_context);
if (status != EGL_TRUE)
g_warning ("eglMakeCurrent");
/*clutter_stage_ensure_current (stage_egl->wrapper);*/
{
g_critical ("eglMakeCurrent failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
}
}
else
{
g_warning("EGL Backend does not yet support offscreen rendering\n");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
CLUTTER_SET_PRIVATE_FLAGS (stage_egl->wrapper, CLUTTER_ACTOR_SYNC_MATRICES);
}
static void

View File

@ -382,6 +382,8 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
if (backend_glx->gl_context == None)
return;
clutter_x11_trap_x_errors ();
/* we might get here inside the final dispose cycle, so we
* need to handle this gracefully
*/
@ -408,6 +410,11 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
stage_x11->xwin,
backend_glx->gl_context);
}
if (clutter_x11_untrap_x_errors ())
g_critical ("Unable to make the stage window 0x%x the current "
"GLX drawable",
(int) stage_x11->xwin);
}
}
@ -459,7 +466,7 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
CLUTTER_NOTE (BACKEND, "Creating stage of type `%s'",
g_type_name (CLUTTER_STAGE_TYPE));
stage = g_object_new (CLUTTER_STAGE_TYPE, NULL);
stage = g_object_new (CLUTTER_TYPE_STAGE_GLX, NULL);
/* copy backend data into the stage */
stage_x11 = CLUTTER_STAGE_X11 (stage);
@ -477,24 +484,6 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
stage_x11->xscreen,
(unsigned int) stage_x11->xwin_root);
/* needed ? */
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
/* FIXME - is this needed? we should call realize inside the clutter
* init sequence for the default stage, and let the usual realization
* sequence be used for any other stage
*/
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to realize the main stage");
g_object_unref (stage);
return NULL;
}
return stage;
}

View File

@ -102,9 +102,6 @@ clutter_stage_glx_unrealize (ClutterActor *actor)
stage_x11->xwin = None;
}
/* As unrealised the context will now get cleared */
clutter_stage_ensure_current (stage_x11->wrapper);
XSync (stage_x11->xdpy, False);
clutter_x11_untrap_x_errors ();
@ -115,10 +112,10 @@ clutter_stage_glx_unrealize (ClutterActor *actor)
static void
clutter_stage_glx_realize (ClutterActor *actor)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
ClutterBackendGLX *backend_glx;
gboolean is_offscreen;
gboolean is_offscreen;
CLUTTER_NOTE (MISC, "Realizing main stage");
@ -214,11 +211,8 @@ clutter_stage_glx_realize (ClutterActor *actor)
}
}
/* this will make sure to set the current context */
CLUTTER_NOTE (BACKEND, "Marking stage as realized and setting context");
CLUTTER_ACTOR_SET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
CLUTTER_NOTE (BACKEND, "Marking stage as realized");
CLUTTER_ACTOR_SET_FLAGS (stage_x11, CLUTTER_ACTOR_REALIZED);
clutter_stage_ensure_current (stage_x11->wrapper);
}
else
{
@ -281,20 +275,14 @@ clutter_stage_glx_realize (ClutterActor *actor)
}
}
clutter_x11_trap_x_errors ();
/* below will call glxMakeCurrent */
CLUTTER_ACTOR_SET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
CLUTTER_NOTE (BACKEND, "Marking stage as realized");
CLUTTER_ACTOR_SET_FLAGS (stage_x11, CLUTTER_ACTOR_REALIZED);
clutter_stage_ensure_current (stage_x11->wrapper);
if (clutter_x11_untrap_x_errors ())
{
g_critical ("Unable to set up offscreen context.");
goto fail;
}
}
/* 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:

View File

@ -95,19 +95,6 @@ clutter_backend_sdl_create_stage (ClutterBackend *backend,
_clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage));
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to realize the main stage");
g_object_unref (stage);
return NULL;
}
backend_sdl->stage = stage_sdl;
return stage;

View File

@ -80,31 +80,21 @@ clutter_stage_sdl_realize (ClutterActor *actor)
0, flags) == NULL)
{
CLUTTER_NOTE (BACKEND, "SDL appears not to handle this mode - %s",
SDL_GetError());
SDL_GetError ());
CLUTTER_ACTOR_UNSET_FLAGS (stage_sdl, CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_UNSET_FLAGS (stage_sdl->wrapper,
CLUTTER_ACTOR_REALIZED);
return;
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
else
{
CLUTTER_ACTOR_SET_FLAGS (stage_sdl, CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_SET_FLAGS (stage_sdl->wrapper, CLUTTER_ACTOR_REALIZED);
clutter_stage_ensure_current (stage_sdl->wrapper);
}
CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
}
else
{
/* FIXME */
g_warning("SDL Backend does not yet support offscreen rendering\n");
g_critical ("SDL Backend does not yet support offscreen rendering");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
CLUTTER_NOTE (BACKEND, "SDL stage realized");
CLUTTER_SET_PRIVATE_FLAGS (stage_sdl->wrapper, CLUTTER_ACTOR_SYNC_MATRICES);
}
static void

View File

@ -229,6 +229,83 @@ clutter_stage_x11_request_coords (ClutterActor *self,
box);
}
static inline void
set_wm_title (ClutterStageX11 *stage_x11)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
if (stage_x11->xwin == None)
return;
if (stage_x11->title == NULL)
{
XDeleteProperty (stage_x11->xdpy,
stage_x11->xwin,
backend_x11->atom_NET_WM_NAME);
}
else
{
XChangeProperty (stage_x11->xdpy,
stage_x11->xwin,
backend_x11->atom_NET_WM_NAME,
backend_x11->atom_UTF8_STRING,
8,
PropModeReplace,
(unsigned char *) stage_x11->title,
(int) strlen (stage_x11->title));
}
}
static inline void
set_cursor_visible (ClutterStageX11 *stage_x11)
{
if (stage_x11->xwin == None)
return;
CLUTTER_NOTE (BACKEND, "setting cursor state ('%s') over stage window (%u)",
stage_x11->is_cursor_visible ? "visible" : "invisible",
(unsigned int) stage_x11->xwin);
if (stage_x11->is_cursor_visible)
{
#if 0 /* HAVE_XFIXES - seems buggy/unreliable */
XFixesShowCursor (stage_x11->xdpy, stage_x11->xwin);
#else
XUndefineCursor (stage_x11->xdpy, stage_x11->xwin);
#endif /* HAVE_XFIXES */
}
else
{
#if 0 /* HAVE_XFIXES - seems buggy/unreliable, check cursor in firefox
* loading page after hiding.
*/
XFixesHideCursor (stage_x11->xdpy, stage_x11->xwin);
#else
XColor col;
Pixmap pix;
Cursor curs;
pix = XCreatePixmap (stage_x11->xdpy, stage_x11->xwin, 1, 1, 1);
memset (&col, 0, sizeof (col));
curs = XCreatePixmapCursor (stage_x11->xdpy,
pix, pix,
&col, &col,
1, 1);
XFreePixmap (stage_x11->xdpy, pix);
XDefineCursor (stage_x11->xdpy, stage_x11->xwin, curs);
#endif /* HAVE_XFIXES */
}
}
static void
clutter_stage_x11_realize (ClutterActor *actor)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
set_wm_title (stage_x11);
set_cursor_visible (stage_x11);
}
static void
clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
gboolean is_fullscreen)
@ -325,42 +402,9 @@ clutter_stage_x11_set_cursor_visible (ClutterStageWindow *stage_window,
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
if (stage_x11->xwin == None)
return;
stage_x11->is_cursor_visible = (cursor_visible == TRUE);
CLUTTER_NOTE (BACKEND, "setting cursor state ('%s') over stage window (%u)",
cursor_visible ? "visible" : "invisible",
(unsigned int) stage_x11->xwin);
if (cursor_visible)
{
#if 0 /* HAVE_XFIXES - seems buggy/unreliable */
XFixesShowCursor (stage_x11->xdpy, stage_x11->xwin);
#else
XUndefineCursor (stage_x11->xdpy, stage_x11->xwin);
#endif /* HAVE_XFIXES */
}
else
{
#if 0 /* HAVE_XFIXES - seems buggy/unreliable, check cursor in firefox
* loading page after hiding.
*/
XFixesHideCursor (stage_x11->xdpy, stage_x11->xwin);
#else
XColor col;
Pixmap pix;
Cursor curs;
pix = XCreatePixmap (stage_x11->xdpy, stage_x11->xwin, 1, 1, 1);
memset (&col, 0, sizeof (col));
curs = XCreatePixmapCursor (stage_x11->xdpy,
pix, pix,
&col, &col,
1, 1);
XFreePixmap (stage_x11->xdpy, pix);
XDefineCursor (stage_x11->xdpy, stage_x11->xwin, curs);
#endif /* HAVE_XFIXES */
}
set_cursor_visible (stage_x11);
}
static void
@ -368,28 +412,11 @@ clutter_stage_x11_set_title (ClutterStageWindow *stage_window,
const gchar *title)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterBackendX11 *backend_x11 = stage_x11->backend;
if (stage_x11->xwin == None)
return;
g_free (stage_x11->title);
stage_x11->title = g_strdup (title);
if (title == NULL)
{
XDeleteProperty (stage_x11->xdpy,
stage_x11->xwin,
backend_x11->atom_NET_WM_NAME);
}
else
{
XChangeProperty (stage_x11->xdpy,
stage_x11->xwin,
backend_x11->atom_NET_WM_NAME,
backend_x11->atom_UTF8_STRING,
8,
PropModeReplace,
(unsigned char*)title,
(int)strlen(title));
}
set_wm_title (stage_x11);
}
static void
@ -407,6 +434,16 @@ clutter_stage_x11_get_wrapper (ClutterStageWindow *stage_window)
return CLUTTER_ACTOR (CLUTTER_STAGE_X11 (stage_window)->wrapper);
}
static void
clutter_stage_x11_finalize (GObject *gobject)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
g_free (stage_x11->title);
G_OBJECT_CLASS (clutter_stage_x11_parent_class)->finalize (gobject);
}
static void
clutter_stage_x11_dispose (GObject *gobject)
{
@ -424,8 +461,10 @@ 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->show = clutter_stage_x11_show;
actor_class->hide = clutter_stage_x11_hide;
actor_class->request_coords = clutter_stage_x11_request_coords;
@ -447,13 +486,13 @@ clutter_stage_x11_init (ClutterStageX11 *stage)
stage->is_foreign_xwin = FALSE;
stage->fullscreen_on_map = FALSE;
stage->handling_configure = FALSE;
stage->is_cursor_visible = TRUE;
stage->title = NULL;
stage->wrapper = NULL;
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_IS_TOPLEVEL);
#if 0
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
#endif
}
static void

View File

@ -45,8 +45,10 @@ struct _ClutterStageX11
{
ClutterGroup parent_instance;
guint is_foreign_xwin : 1;
guint fullscreen_on_map : 1;
guint is_foreign_xwin : 1;
guint fullscreen_on_map : 1;
guint handling_configure : 1;
guint is_cursor_visible : 1;
Display *xdpy;
Window xwin_root;
@ -56,7 +58,7 @@ struct _ClutterStageX11
gint xwin_width;
gint xwin_height; /* FIXME target_width / height */
Pixmap xpixmap;
gboolean handling_configure;
gchar *title;
ClutterBackendX11 *backend;
ClutterStageState state;