2007-11-26 Emmanuele Bassi <ebassi@openedhand.com>

* clutter/clutter-actor.c:
	(clutter_actor_real_show),
	(clutter_actor_real_hide): Do not set the MAPPED flag on the actor
	if it is a top-level one (like ClutterStage); the backends are
	responsible for setting that flag, as it might be the result of an
	asynchronous operation (e.g. on X11).
	
	* clutter/eglnative/clutter-stage-egl.c:
	(clutter_stage_egl_show),
	(clutter_stage_egl_hide): Set/unset the CLUTTER_ACTOR_MAPPED flag
	on show and hide respectively.

	* clutter/osx/clutter-stage-osx.c:
	(clutter_stage_osx_show),
	(clutter_stage_osx_hide): Ditto as above.

	* clutter/sdl/clutter-stage-sdl.c:
	(clutter_stage_sdl_show),
	(clutter_stage_sdl_hide): Ditto as above, plus chain up to the
	parent class show/hide virtual functions.

	* clutter/x11/clutter-event-x11.c (event_translate): Use the MapNotify
	and UnmapNotify events to call the X11 stage map/unmap functions.

	* clutter/x11/clutter-stage-x11.[ch]:
	(clutter_stage_x11_set_fullscreen): Set the fullscreen_on_map flag
	with the fullscreen value.

	(clutter_stage_x11_map), (clutter_stage_x11_unmap): Set the MAPPED
	flag on the stage actor and redraw; also, if the fullscreen_on_map
	flag was set, call clutter_stage_fullscreen() as well. (#648)

	* tests/Makefile.am:
	* tests/test-fullscreen.c: Add a fullscreen test case for checking
	whether fullscreen works on every backend/platform.
This commit is contained in:
Emmanuele Bassi 2007-11-26 12:07:25 +00:00
parent 99daccf1f3
commit a02e20a14a
10 changed files with 301 additions and 104 deletions

View File

@ -1,3 +1,41 @@
2007-11-26 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-actor.c:
(clutter_actor_real_show),
(clutter_actor_real_hide): Do not set the MAPPED flag on the actor
if it is a top-level one (like ClutterStage); the backends are
responsible for setting that flag, as it might be the result of an
asynchronous operation (e.g. on X11).
* clutter/eglnative/clutter-stage-egl.c:
(clutter_stage_egl_show),
(clutter_stage_egl_hide): Set/unset the CLUTTER_ACTOR_MAPPED flag
on show and hide respectively.
* clutter/osx/clutter-stage-osx.c:
(clutter_stage_osx_show),
(clutter_stage_osx_hide): Ditto as above.
* clutter/sdl/clutter-stage-sdl.c:
(clutter_stage_sdl_show),
(clutter_stage_sdl_hide): Ditto as above, plus chain up to the
parent class show/hide virtual functions.
* clutter/x11/clutter-event-x11.c (event_translate): Use the MapNotify
and UnmapNotify events to call the X11 stage map/unmap functions.
* clutter/x11/clutter-stage-x11.[ch]:
(clutter_stage_x11_set_fullscreen): Set the fullscreen_on_map flag
with the fullscreen value.
(clutter_stage_x11_map), (clutter_stage_x11_unmap): Set the MAPPED
flag on the stage actor and redraw; also, if the fullscreen_on_map
flag was set, call clutter_stage_fullscreen() as well. (#648)
* tests/Makefile.am:
* tests/test-fullscreen.c: Add a fullscreen test case for checking
whether fullscreen works on every backend/platform.
2007-11-23 Emmanuele Bassi <ebassi@openedhand.com> 2007-11-23 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-actor.c: * clutter/clutter-actor.c:

View File

@ -233,6 +233,10 @@ clutter_actor_real_show (ClutterActor *self)
if (!CLUTTER_ACTOR_IS_REALIZED (self)) if (!CLUTTER_ACTOR_IS_REALIZED (self))
clutter_actor_realize (self); clutter_actor_realize (self);
/* the mapped flag on the top-level actors is set by the
* per-backend implementation because it might be asynchronous
*/
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL))
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED); CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED);
if (CLUTTER_ACTOR_IS_VISIBLE (self)) if (CLUTTER_ACTOR_IS_VISIBLE (self))
@ -286,7 +290,12 @@ clutter_actor_real_hide (ClutterActor *self)
{ {
if (CLUTTER_ACTOR_IS_VISIBLE (self)) if (CLUTTER_ACTOR_IS_VISIBLE (self))
{ {
/* see comment in clutter_actor_real_show() on why we don't set
* the mapped flag on the top-level actors
*/
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL))
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_MAPPED); CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_MAPPED);
clutter_actor_queue_redraw (self); clutter_actor_queue_redraw (self);
} }
} }

View File

@ -22,9 +22,7 @@ clutter_stage_egl_show (ClutterActor *actor)
{ {
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor); ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
/* we are always shown... */ CLUTTER_ACTOR_SET_FLAGS (stage_egl, CLUTTER_ACTOR_MAPPED);
return;
} }
static void static void
@ -32,9 +30,7 @@ clutter_stage_egl_hide (ClutterActor *actor)
{ {
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor); ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
/* we are always shown... */ CLUTTER_ACTOR_UNSET_FLAGS (stage_egl, CLUTTER_ACTOR_MAPPED);
return;
} }
static void static void

View File

@ -322,6 +322,8 @@ clutter_stage_osx_show (ClutterActor *actor)
CLUTTER_NOTE (BACKEND, "show"); CLUTTER_NOTE (BACKEND, "show");
CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show) if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show)
CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show (actor); CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show (actor);
@ -347,6 +349,8 @@ clutter_stage_osx_hide (ClutterActor *actor)
CLUTTER_OSX_POOL_RELEASE(); CLUTTER_OSX_POOL_RELEASE();
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->hide) if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->hide)
CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->hide (actor); CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->hide (actor);
} }

View File

@ -22,14 +22,18 @@ G_DEFINE_TYPE (ClutterStageSDL, clutter_stage_sdl, CLUTTER_TYPE_STAGE);
static void static void
clutter_stage_sdl_show (ClutterActor *actor) clutter_stage_sdl_show (ClutterActor *actor)
{ {
; CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
CLUTTER_ACTOR_CLASS (clutter_stage_sdl_parent_class)->show (actor);
} }
static void static void
clutter_stage_sdl_hide (ClutterActor *actor) clutter_stage_sdl_hide (ClutterActor *actor)
{ {
/* No way to easily unmap SDL window ? */ /* No way to easily unmap SDL window ? */
; CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
CLUTTER_ACTOR_CLASS (clutter_stage_sdl_parent_class)->hide (actor);
} }
static void static void

View File

@ -233,11 +233,11 @@ translate_key_event (ClutterBackend *backend,
event->key.hardware_keycode = xevent->xkey.keycode; event->key.hardware_keycode = xevent->xkey.keycode;
/* FIXME: We need to handle other modifiers rather than just shift */ /* FIXME: We need to handle other modifiers rather than just shift */
event->key.keyval event->key.keyval =
= XKeycodeToKeysym (xevent->xkey.display, XKeycodeToKeysym (xevent->xkey.display,
xevent->xkey.keycode, xevent->xkey.keycode,
(event->key.modifier_state & CLUTTER_SHIFT_MASK) (event->key.modifier_state & CLUTTER_SHIFT_MASK) ? 1
? 1 : 0); : 0);
} }
static gboolean static gboolean
@ -256,7 +256,7 @@ handle_wm_protocols_event (ClutterBackendX11 *backend_x11,
* we relay the event to the application and we let it * we relay the event to the application and we let it
* handle the request * handle the request
*/ */
CLUTTER_NOTE (EVENT, "delete window:\twindow: %ld", CLUTTER_NOTE (EVENT, "delete window:\txid: %ld",
xevent->xclient.window); xevent->xclient.window);
set_user_time (backend_x11, set_user_time (backend_x11,
@ -380,52 +380,58 @@ event_translate (ClutterBackend *backend,
switch (xevent->type) switch (xevent->type)
{ {
case ConfigureNotify: case ConfigureNotify:
if (xevent->xconfigure.width {
!= clutter_actor_get_width (CLUTTER_ACTOR (stage)) guint stage_width, stage_height;
||
xevent->xconfigure.height clutter_actor_get_size (CLUTTER_ACTOR (stage),
!= clutter_actor_get_height (CLUTTER_ACTOR (stage))) &stage_width,
&stage_height);
if (xevent->xconfigure.width != stage_width ||
xevent->xconfigure.height != stage_height)
{
clutter_actor_set_size (CLUTTER_ACTOR (stage), clutter_actor_set_size (CLUTTER_ACTOR (stage),
xevent->xconfigure.width, xevent->xconfigure.width,
xevent->xconfigure.height); xevent->xconfigure.height);
}
}
res = FALSE; res = FALSE;
break; break;
case PropertyNotify: case PropertyNotify:
{
if (xevent->xproperty.atom == backend_x11->atom_NET_WM_STATE) if (xevent->xproperty.atom == backend_x11->atom_NET_WM_STATE)
{ {
Atom type; Atom type;
gint format; gint format;
gulong nitems, bytes_after; gulong n_items, bytes_after;
guchar *data = NULL; guchar *data = NULL;
Atom *atoms = NULL;
gulong i;
gboolean fullscreen_set = FALSE; gboolean fullscreen_set = FALSE;
clutter_x11_trap_x_errors (); clutter_x11_trap_x_errors ();
XGetWindowProperty (backend_x11->xdpy, XGetWindowProperty (backend_x11->xdpy, stage_xwindow,
stage_xwindow,
backend_x11->atom_NET_WM_STATE, backend_x11->atom_NET_WM_STATE,
0, G_MAXLONG, 0, G_MAXLONG,
False, XA_ATOM, False, XA_ATOM,
&type, &format, &nitems, &type, &format, &n_items,
&bytes_after, &data); &bytes_after, &data);
clutter_x11_untrap_x_errors (); clutter_x11_untrap_x_errors ();
if (type != None && data != NULL) if (type != None && data != NULL)
{ {
atoms = (Atom *)data; Atom *atoms = (Atom *) data;
gulong i;
gboolean is_fullscreen = FALSE;
i = 0; for (i = 0; i < n_items; i++)
while (i < nitems)
{ {
if (atoms[i] == backend_x11->atom_NET_WM_STATE_FULLSCREEN) if (atoms[i] == backend_x11->atom_NET_WM_STATE_FULLSCREEN)
fullscreen_set = TRUE; fullscreen_set = TRUE;
i++;
} }
if (fullscreen_set is_fullscreen =
!= !!(stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN)) (stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN);
if (fullscreen_set != is_fullscreen)
{ {
if (fullscreen_set) if (fullscreen_set)
stage_x11->state |= CLUTTER_STAGE_STATE_FULLSCREEN; stage_x11->state |= CLUTTER_STAGE_STATE_FULLSCREEN;
@ -433,8 +439,8 @@ event_translate (ClutterBackend *backend,
stage_x11->state &= ~CLUTTER_STAGE_STATE_FULLSCREEN; stage_x11->state &= ~CLUTTER_STAGE_STATE_FULLSCREEN;
event->type = CLUTTER_STAGE_STATE; event->type = CLUTTER_STAGE_STATE;
event->stage_state.changed_mask event->stage_state.changed_mask =
= CLUTTER_STAGE_STATE_FULLSCREEN; CLUTTER_STAGE_STATE_FULLSCREEN;
event->stage_state.new_state = stage_x11->state; event->stage_state.new_state = stage_x11->state;
} }
else else
@ -442,11 +448,21 @@ event_translate (ClutterBackend *backend,
XFree (data); XFree (data);
} }
}
else else
res = FALSE; res = FALSE;
} }
break; break;
case MapNotify:
clutter_stage_x11_map (stage_x11);
res = FALSE;
break;
case UnmapNotify:
clutter_stage_x11_unmap (stage_x11);
res = FALSE;
break;
case FocusIn: case FocusIn:
if (!(stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED)) if (!(stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED))
{ {
@ -460,6 +476,7 @@ event_translate (ClutterBackend *backend,
else else
res = FALSE; res = FALSE;
break; break;
case FocusOut: case FocusOut:
if (stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED) if (stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED)
{ {
@ -472,6 +489,7 @@ event_translate (ClutterBackend *backend,
else else
res = FALSE; res = FALSE;
break; break;
case Expose: case Expose:
{ {
XEvent foo_xev; XEvent foo_xev;
@ -489,15 +507,18 @@ event_translate (ClutterBackend *backend,
res = FALSE; res = FALSE;
} }
break; break;
case KeyPress: case KeyPress:
event->type = CLUTTER_KEY_PRESS; event->type = CLUTTER_KEY_PRESS;
translate_key_event (backend, event, xevent); translate_key_event (backend, event, xevent);
set_user_time (backend_x11, &xwindow, xevent->xkey.time); set_user_time (backend_x11, &xwindow, xevent->xkey.time);
break; break;
case KeyRelease: case KeyRelease:
event->type = CLUTTER_KEY_RELEASE; event->type = CLUTTER_KEY_RELEASE;
translate_key_event (backend, event, xevent); translate_key_event (backend, event, xevent);
break; break;
case ButtonPress: case ButtonPress:
switch (xevent->xbutton.button) switch (xevent->xbutton.button)
{ {
@ -535,6 +556,7 @@ event_translate (ClutterBackend *backend,
set_user_time (backend_x11, &xwindow, event->button.time); set_user_time (backend_x11, &xwindow, event->button.time);
break; break;
case ButtonRelease: case ButtonRelease:
/* scroll events don't have a corresponding release */ /* scroll events don't have a corresponding release */
if (xevent->xbutton.button == 4 || if (xevent->xbutton.button == 4 ||
@ -553,6 +575,7 @@ event_translate (ClutterBackend *backend,
event->button.modifier_state = xevent->xbutton.state; event->button.modifier_state = xevent->xbutton.state;
event->button.button = xevent->xbutton.button; event->button.button = xevent->xbutton.button;
break; break;
case MotionNotify: case MotionNotify:
event->motion.type = event->type = CLUTTER_MOTION; event->motion.type = event->type = CLUTTER_MOTION;
event->motion.time = xevent->xmotion.time; event->motion.time = xevent->xmotion.time;
@ -560,11 +583,13 @@ event_translate (ClutterBackend *backend,
event->motion.y = xevent->xmotion.y; event->motion.y = xevent->xmotion.y;
event->motion.modifier_state = xevent->xmotion.state; event->motion.modifier_state = xevent->xmotion.state;
break; break;
case DestroyNotify: case DestroyNotify:
CLUTTER_NOTE (EVENT, "destroy notify:\twindow: %ld", CLUTTER_NOTE (EVENT, "destroy notify:\txid: %ld",
xevent->xdestroywindow.window); xevent->xdestroywindow.window);
event->type = event->any.type = CLUTTER_DESTROY_NOTIFY; event->type = event->any.type = CLUTTER_DESTROY_NOTIFY;
break; break;
case ClientMessage: case ClientMessage:
CLUTTER_NOTE (EVENT, "client message"); CLUTTER_NOTE (EVENT, "client message");
@ -578,6 +603,7 @@ event_translate (ClutterBackend *backend,
event->type = event->any.type = CLUTTER_DELETE; event->type = event->any.type = CLUTTER_DELETE;
} }
break; break;
default: default:
/* ignore every other event */ /* ignore every other event */
res = FALSE; res = FALSE;

View File

@ -94,10 +94,10 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11)
if (!resize) if (!resize)
{ {
size_hints->max_width size_hints->max_width = size_hints->min_width =
= size_hints->min_width = stage_x11->xwin_width; stage_x11->xwin_width;
size_hints->max_height size_hints->max_height = size_hints->min_height =
= size_hints->min_height = stage_x11->xwin_height; stage_x11->xwin_height;
size_hints->flags = PMinSize|PMaxSize; size_hints->flags = PMinSize|PMaxSize;
} }
@ -112,19 +112,18 @@ clutter_stage_x11_show (ClutterActor *actor)
{ {
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor); ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
/* Chain up to set mapped flags */
CLUTTER_ACTOR_CLASS (clutter_stage_x11_parent_class)->show(actor);
if (stage_x11->xwin) if (stage_x11->xwin)
{ {
/* Fire off a redraw to avoid flicker on first map. /* Fire off a redraw to avoid flicker on first map.
* Appears not to work perfectly on intel drivers at least. * Appears not to work perfectly on intel drivers at least.
*/ */
clutter_redraw(); clutter_redraw();
XSync (stage_x11->xdpy, FALSE); XSync (stage_x11->xdpy, FALSE);
XMapWindow (stage_x11->xdpy, stage_x11->xwin); XMapWindow (stage_x11->xdpy, stage_x11->xwin);
} }
/* chain up */
CLUTTER_ACTOR_CLASS (clutter_stage_x11_parent_class)->show (actor); CLUTTER_ACTOR_CLASS (clutter_stage_x11_parent_class)->show (actor);
} }
@ -136,6 +135,7 @@ clutter_stage_x11_hide (ClutterActor *actor)
if (stage_x11->xwin) if (stage_x11->xwin)
XUnmapWindow (stage_x11->xdpy, stage_x11->xwin); XUnmapWindow (stage_x11->xdpy, stage_x11->xwin);
/* chain up */
CLUTTER_ACTOR_CLASS (clutter_stage_x11_parent_class)->hide (actor); CLUTTER_ACTOR_CLASS (clutter_stage_x11_parent_class)->hide (actor);
} }
@ -219,7 +219,12 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
{ {
if (stage_x11->xwin != None) if (stage_x11->xwin != None)
{ {
if (!CLUTTER_ACTOR_IS_MAPPED(CLUTTER_ACTOR (stage_x11))) /* if the actor is not mapped we resize the stage window to match
* the size of the screen; this is useful for e.g. EGLX to avoid
* a resize when calling clutter_stage_fullscreen() before showing
* the stage
*/
if (!CLUTTER_ACTOR_IS_MAPPED (stage_x11))
{ {
gint width, height; gint width, height;
@ -228,14 +233,13 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
clutter_actor_set_size (CLUTTER_ACTOR (stage_x11), clutter_actor_set_size (CLUTTER_ACTOR (stage_x11),
width, height); width, height);
/* FIXME: This wont work if we support more states */ /* FIXME: This wont work if we support more states */
XChangeProperty XChangeProperty (stage_x11->xdpy,
(stage_x11->xdpy,
stage_x11->xwin, stage_x11->xwin,
backend_x11->atom_NET_WM_STATE, XA_ATOM, 32, backend_x11->atom_NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, PropModeReplace,
(unsigned char *)&backend_x11->atom_NET_WM_STATE_FULLSCREEN, (unsigned char *) &backend_x11->atom_NET_WM_STATE_FULLSCREEN, 1);
1);
} }
else else
{ {
@ -247,18 +251,19 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
else else
clutter_stage_set_user_resizable (stage, TRUE); clutter_stage_set_user_resizable (stage, TRUE);
send_wmspec_change_state(backend_x11, send_wmspec_change_state(backend_x11, stage_x11->xwin,
stage_x11->xwin,
backend_x11->atom_NET_WM_STATE_FULLSCREEN, backend_x11->atom_NET_WM_STATE_FULLSCREEN,
TRUE); TRUE);
} }
stage_x11->fullscreen_on_map = TRUE;
} }
} }
else else
{ {
if (stage_x11->xwin != None) if (stage_x11->xwin != None)
{ {
if (!CLUTTER_ACTOR_IS_MAPPED(CLUTTER_ACTOR (stage_x11))) if (!CLUTTER_ACTOR_IS_MAPPED (stage_x11))
{ {
/* FIXME: This wont work if we support more states */ /* FIXME: This wont work if we support more states */
XDeleteProperty (stage_x11->xdpy, XDeleteProperty (stage_x11->xdpy,
@ -280,6 +285,8 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
was_resizeable = FALSE; was_resizeable = FALSE;
} }
stage_x11->fullscreen_on_map = FALSE;
} }
} }
@ -301,9 +308,7 @@ clutter_stage_x11_set_cursor_visible (ClutterStage *stage,
if (show_cursor) if (show_cursor)
{ {
#if 0 /* HAVE_XFIXES - borked on fiesty at least so disabled until further #if 0 /* HAVE_XFIXES */
* investigation.
*/
XFixesShowCursor (stage_x11->xdpy, stage_x11->xwin); XFixesShowCursor (stage_x11->xdpy, stage_x11->xwin);
#else #else
XUndefineCursor (stage_x11->xdpy, stage_x11->xwin); XUndefineCursor (stage_x11->xdpy, stage_x11->xwin);
@ -311,7 +316,7 @@ clutter_stage_x11_set_cursor_visible (ClutterStage *stage,
} }
else else
{ {
#if 0 /* HAVE_XFIXES - borked */ #if 0 /* HAVE_XFIXES */
XFixesHideCursor (stage_x11->xdpy, stage_x11->xwin); XFixesHideCursor (stage_x11->xdpy, stage_x11->xwin);
#else #else
XColor col; XColor col;
@ -420,6 +425,7 @@ clutter_stage_x11_init (ClutterStageX11 *stage)
stage->xvisinfo = None; stage->xvisinfo = None;
stage->is_foreign_xwin = FALSE; stage->is_foreign_xwin = FALSE;
stage->fullscreen_on_map = FALSE;
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES); CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
} }
@ -522,3 +528,23 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
return TRUE; return TRUE;
} }
void
clutter_stage_x11_map (ClutterStageX11 *stage_x11)
{
CLUTTER_ACTOR_SET_FLAGS (stage_x11, CLUTTER_ACTOR_MAPPED);
if (stage_x11->fullscreen_on_map)
clutter_stage_fullscreen (CLUTTER_STAGE (stage_x11));
else
clutter_stage_unfullscreen (CLUTTER_STAGE (stage_x11));
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage_x11));
}
void
clutter_stage_x11_unmap (ClutterStageX11 *stage_x11)
{
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11, CLUTTER_ACTOR_MAPPED);
}

View File

@ -45,7 +45,8 @@ struct _ClutterStageX11
{ {
ClutterStage parent_instance; ClutterStage parent_instance;
int is_foreign_xwin :1; guint is_foreign_xwin : 1;
guint fullscreen_on_map : 1;
Display *xdpy; Display *xdpy;
Window xwin_root; Window xwin_root;
@ -68,11 +69,11 @@ struct _ClutterStageX11Class
GType clutter_stage_x11_get_type (void) G_GNUC_CONST; GType clutter_stage_x11_get_type (void) G_GNUC_CONST;
/* Private to subclasses */ /* Private to subclasses */
void void clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11);
clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11); void clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11);
void void clutter_stage_x11_map (ClutterStageX11 *stage_x11);
clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11); void clutter_stage_x11_unmap (ClutterStageX11 *stage_x11);
G_END_DECLS G_END_DECLS

View File

@ -2,7 +2,7 @@ noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \
test-actors test-behave test-text test-entry test-project \ test-actors test-behave test-text test-entry test-project \
test-boxes test-perspective test-rotate test-depth \ test-boxes test-perspective test-rotate test-depth \
test-threads test-timeline test-score test-script \ test-threads test-timeline test-score test-script \
test-model test-grab test-effects test-model test-grab test-effects test-fullscreen
INCLUDES = -I$(top_srcdir)/ INCLUDES = -I$(top_srcdir)/
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
@ -29,5 +29,6 @@ test_score_SOURCES = test-score.c
test_script_SOURCES = test-script.c test_script_SOURCES = test-script.c
test_model_SOURCES = test-model.c test_model_SOURCES = test-model.c
test_effects_SOURCES = test-effects.c test_effects_SOURCES = test-effects.c
test_fullscreen_SOURCES = test-fullscreen.c
EXTRA_DIST = redhand.png test-script.json EXTRA_DIST = redhand.png test-script.json

92
tests/test-fullscreen.c Normal file
View File

@ -0,0 +1,92 @@
#include <stdlib.h>
#include <clutter/clutter.h>
enum
{
START,
HIDE,
SHOW,
DONE
};
static int state = START;
static void
on_fullscreen (ClutterStage *stage)
{
g_debug ("fullscreen set, size: %dx%d, mapped: %s",
clutter_actor_get_width (CLUTTER_ACTOR (stage)),
clutter_actor_get_height (CLUTTER_ACTOR (stage)),
CLUTTER_ACTOR_IS_MAPPED (stage) ? "true" : "false");
}
static void
on_unfullscreen (ClutterStage *stage)
{
g_debug ("fullscreen unset, size: %dx%d, mapped: %s",
clutter_actor_get_width (CLUTTER_ACTOR (stage)),
clutter_actor_get_height (CLUTTER_ACTOR (stage)),
CLUTTER_ACTOR_IS_MAPPED (stage) ? "true" : "false");
}
static gboolean
toggle_fullscreen (gpointer dummy)
{
ClutterActor *stage = clutter_stage_get_default ();
gboolean is_fullscreen = FALSE;
g_object_get (G_OBJECT (stage), "fullscreen", &is_fullscreen, NULL);
switch (state)
{
case START:
g_debug ("start: is_fullscreen := %s", is_fullscreen ? "true" : "false");
clutter_actor_hide (stage);
state = HIDE;
return TRUE;
case HIDE:
g_debug ("hide: is_fullscreen := %s", is_fullscreen ? "true" : "false");
clutter_actor_show (stage);
state = SHOW;
return TRUE;
case SHOW:
g_debug ("show: is_fullscreen := %s", is_fullscreen ? "true" : "false");
clutter_stage_unfullscreen (CLUTTER_STAGE (stage));
state = DONE;
return TRUE;
case DONE:
g_debug ("done: is_fullscreen := %s", is_fullscreen ? "true" : "false");
clutter_main_quit ();
break;
}
return FALSE;
}
int
main (int argc, char *argv[])
{
ClutterActor *stage;
clutter_init (&argc, &argv);
stage = clutter_stage_get_default ();
g_signal_connect (stage,
"fullscreen", G_CALLBACK (on_fullscreen),
NULL);
g_signal_connect (stage,
"unfullscreen", G_CALLBACK (on_unfullscreen),
NULL);
clutter_stage_fullscreen (CLUTTER_STAGE (stage));
clutter_actor_show (stage);
g_timeout_add (1000, toggle_fullscreen, NULL);
clutter_main ();
return EXIT_SUCCESS;
}