From 1117b6a9ac974dd5855c5e76965c15329c608ff4 Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Tue, 16 Feb 2010 14:50:14 +0000 Subject: [PATCH] [stage-x11] Fix switching fullscreen mode Setting/unsetting fullscreen on a mapped or unmapped window now works correctly. If you unfullscreen a window that was initially full-screened, it will unset the fullscreen hint and the WM will likely push the size down to the largest valid size. If the window was previously un-fullscreened, Clutter will restore the previous size. Fullscreening also now works if the WM switches the hint without the application's knowledge (as happens when you resize a window to the size of the screen, for example, with stock metacity). --- clutter/clutter-stage.c | 3 +- clutter/x11/clutter-event-x11.c | 13 +++++- clutter/x11/clutter-stage-x11.c | 71 +++++++++++++++++++-------------- clutter/x11/clutter-stage-x11.h | 2 +- 4 files changed, 54 insertions(+), 35 deletions(-) diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 6df81efc3..9d1daa7db 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -216,7 +216,8 @@ clutter_stage_allocate (ClutterActor *self, klass->allocate (self, box, flags); /* Ensure the window is sized correctly */ - if ((geom.width != width) || (geom.height != height)) + if (!priv->is_fullscreen && + ((geom.width != width) || (geom.height != height))) _clutter_stage_window_resize (priv->impl, width, height); } else diff --git a/clutter/x11/clutter-event-x11.c b/clutter/x11/clutter-event-x11.c index 6a74cf249..7be186984 100644 --- a/clutter/x11/clutter-event-x11.c +++ b/clutter/x11/clutter-event-x11.c @@ -482,8 +482,15 @@ event_translate (ClutterBackend *backend, xevent->xconfigure.width, xevent->xconfigure.height); - stage_x11->xwin_width = xevent->xconfigure.width; - stage_x11->xwin_height = xevent->xconfigure.height; + /* If we're fullscreened, we want these variables to + * represent the size of the window before it was set + * to fullscreen. + */ + if (!(stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN)) + { + stage_x11->xwin_width = xevent->xconfigure.width; + stage_x11->xwin_height = xevent->xconfigure.height; + } clutter_actor_set_size (CLUTTER_ACTOR (stage), xevent->xconfigure.width, @@ -552,6 +559,8 @@ event_translate (ClutterBackend *backend, else stage_x11->state &= ~CLUTTER_STAGE_STATE_FULLSCREEN; + stage_x11->fullscreening = fullscreen_set; + event->type = CLUTTER_STAGE_STATE; event->stage_state.changed_mask = CLUTTER_STAGE_STATE_FULLSCREEN; diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c index 3bd0ecde6..231546c3f 100644 --- a/clutter/x11/clutter-stage-x11.c +++ b/clutter/x11/clutter-stage-x11.c @@ -66,6 +66,8 @@ send_wmspec_change_state (ClutterBackendX11 *backend_x11, { XClientMessageEvent xclient; + CLUTTER_NOTE (BACKEND, "%s NET_WM state", add ? "adding" : "removing"); + memset (&xclient, 0, sizeof (xclient)); xclient.type = ClientMessage; @@ -121,7 +123,7 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11, /* If we are going fullscreen then we don't want any restrictions on the window size */ - if (!stage_x11->fullscreen_on_map) + if (!stage_x11->fullscreening) { if (resize) { @@ -169,17 +171,13 @@ clutter_stage_x11_get_geometry (ClutterStageWindow *stage_window, ClutterBackend *backend = clutter_get_default_backend (); ClutterBackendX11 *backend_x11; ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); - gboolean is_fullscreen; g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend)); backend_x11 = CLUTTER_BACKEND_X11 (backend); - is_fullscreen = FALSE; - g_object_get (G_OBJECT (stage_x11->wrapper), - "fullscreen-set", &is_fullscreen, - NULL); - - if (is_fullscreen || stage_x11->fullscreen_on_map) + /* If we're fullscreen, return the size of the display. */ + if ((stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN) && + stage_x11->fullscreening) { geometry->width = DisplayWidth (backend_x11->xdpy, backend_x11->xscreen_num); geometry->height = DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num); @@ -202,6 +200,10 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window, ClutterStage *stage = stage_x11->wrapper; gboolean resize; + /* If we're going fullscreen, don't mess with the size */ + if (stage_x11->fullscreening) + return; + resize = clutter_stage_get_user_resizable (stage_x11->wrapper); g_return_if_fail (CLUTTER_IS_BACKEND_X11 (backend)); @@ -389,6 +391,11 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, if (stage == NULL) return; + if (!!(stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN) == is_fullscreen) + return; + + CLUTTER_NOTE (BACKEND, "%ssetting fullscreen", is_fullscreen ? "" : "un"); + CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES); if (is_fullscreen) @@ -403,17 +410,8 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, width = DisplayWidth (backend_x11->xdpy, backend_x11->xscreen_num); height = DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num); - /* we force the stage to the screen size here, in order to - * get the fullscreen stage size right after the call to - * clutter_stage_fullscreen(). XXX this might break in case - * the stage is not fullscreened, but if that does not happen - * we are massively screwed anyway - */ - stage_x11->xwin_width = width; - stage_x11->xwin_height = height; - - if (!STAGE_X11_IS_MAPPED (stage_x11)) - stage_x11->fullscreen_on_map = TRUE; + /* Set the fullscreen hint so we can retain the old size of the window. */ + stage_x11->fullscreening = TRUE; if (stage_x11->xwin != None) { @@ -422,8 +420,10 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, * a resize when calling clutter_stage_fullscreen() before showing * the stage */ - if (!CLUTTER_ACTOR_IS_MAPPED (stage_x11)) + if (!/*CLUTTER_ACTOR_IS_MAPPED (stage_x11->wrapper)*/ STAGE_X11_IS_MAPPED (stage_x11)) { + CLUTTER_NOTE (BACKEND, "Fullscreening unmapped stage"); + /* FIXME: This wont work if we support more states */ XChangeProperty (backend_x11->xdpy, stage_x11->xwin, @@ -433,6 +433,8 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, } else { + CLUTTER_NOTE (BACKEND, "Fullscreening mapped stage"); + /* We need to fix the window size so that it will remove the maximum and minimum window hints. Otherwise metacity will honour the restrictions and not @@ -447,13 +449,14 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, } else { - if (!STAGE_X11_IS_MAPPED (stage_x11)) - stage_x11->fullscreen_on_map = FALSE; + stage_x11->fullscreening = FALSE; if (stage_x11->xwin != None) { - if (!CLUTTER_ACTOR_IS_MAPPED (stage_x11)) + if (!/*CLUTTER_ACTOR_IS_MAPPED (stage_x11->wrapper)*/ STAGE_X11_IS_MAPPED (stage_x11)) { + CLUTTER_NOTE (BACKEND, "Un-fullscreening unmapped stage"); + /* FIXME: This wont work if we support more states */ XDeleteProperty (backend_x11->xdpy, stage_x11->xwin, @@ -461,6 +464,8 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, } else { + CLUTTER_NOTE (BACKEND, "Un-fullscreening mapped stage"); + send_wmspec_change_state (backend_x11, stage_x11->xwin, backend_x11->atom_NET_WM_STATE_FULLSCREEN, @@ -468,7 +473,9 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, /* Fix the window size to restore the minimum/maximum restriction */ - clutter_stage_x11_fix_window_size (stage_x11, -1, -1); + clutter_stage_x11_fix_window_size (stage_x11, + stage_x11->xwin_width, + stage_x11->xwin_height); } } } @@ -504,7 +511,9 @@ clutter_stage_x11_set_user_resizable (ClutterStageWindow *stage_window, { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); - clutter_stage_x11_fix_window_size (stage_x11, -1, -1); + clutter_stage_x11_fix_window_size (stage_x11, + stage_x11->xwin_width, + stage_x11->xwin_height); } static void @@ -575,14 +584,14 @@ clutter_stage_x11_show (ClutterStageWindow *stage_window, CLUTTER_NOTE (BACKEND, "Mapping stage[%lu]", (unsigned long) stage_x11->xwin); - if (stage_x11->fullscreen_on_map) - clutter_stage_x11_set_fullscreen (stage_window, TRUE); - else - clutter_stage_x11_set_fullscreen (stage_window, FALSE); - set_stage_state (stage_x11, STAGE_X11_WITHDRAWN, 0); update_wm_hints (stage_x11); + + if (stage_x11->fullscreening) + clutter_stage_x11_set_fullscreen (stage_window, TRUE); + else + clutter_stage_x11_set_fullscreen (stage_window, FALSE); } g_assert (STAGE_X11_IS_MAPPED (stage_x11)); @@ -659,7 +668,7 @@ clutter_stage_x11_init (ClutterStageX11 *stage) stage->wm_state = STAGE_X11_WITHDRAWN; stage->is_foreign_xwin = FALSE; - stage->fullscreen_on_map = FALSE; + stage->fullscreening = FALSE; stage->is_cursor_visible = TRUE; stage->viewport_initialized = FALSE; diff --git a/clutter/x11/clutter-stage-x11.h b/clutter/x11/clutter-stage-x11.h index 71b66e348..4631235e1 100644 --- a/clutter/x11/clutter-stage-x11.h +++ b/clutter/x11/clutter-stage-x11.h @@ -51,7 +51,7 @@ struct _ClutterStageX11 ClutterGroup parent_instance; guint is_foreign_xwin : 1; - guint fullscreen_on_map : 1; + guint fullscreening : 1; guint is_cursor_visible : 1; guint viewport_initialized : 1;