Fix fullscreening when the stage is unrealized and on dual-head
authorNeil Roberts <neil@linux.intel.com>
Tue, 7 Apr 2009 14:24:48 +0000 (15:24 +0100)
committerNeil Roberts <neil@linux.intel.com>
Tue, 7 Apr 2009 14:24:48 +0000 (15:24 +0100)
If the stage is unrealized (such as will be the case if the stage was
created with clutter_stage_new) then it would set the size of the
stage display but it was not setting the fullscreen_on_map flag so it
never got the _NET_WM_STATE_FULLSCREEN property. Now it always sets
the flag regardless of whether the window is created yet.

There was also problems with dual-headed displays because in that case
DisplayWidth/Height will return the size of the combined display but
Metacity (and presumably other WMs) will sensibly try fit the window
to only one of the monitors. However we were setting the size hints so
that the minimum size is that of the combined display. Metacity tries
to honour this by setting the minimum size but then it no longer
positions the window at the top left of the screen.

The patch makes it avoid setting the minimum size when the stage is
fullscreen by checking the fullscreen_on_map flag. This also means we
can remove the static was_resizable flag which would presumably have
caused problems for multi-stage.

clutter/x11/clutter-stage-x11.c

index 725a756..aa09171 100644 (file)
@@ -105,15 +105,22 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11)
                                           min_width,
                                           &min_height, NULL);
 
-      size_hints->min_width = CLUTTER_UNITS_TO_DEVICE (min_width);
-      size_hints->min_height = CLUTTER_UNITS_TO_DEVICE (min_height);
-      size_hints->flags = PMinSize;
+      size_hints->flags = 0;
 
-      if (!resize)
+      /* If we are going fullscreen then we don't want any
+         restrictions on the window size */
+      if (!stage_x11->fullscreen_on_map)
         {
-          size_hints->max_width = size_hints->min_width;
-          size_hints->max_height = size_hints->min_height;
-          size_hints->flags |= PMaxSize;
+          size_hints->min_width = CLUTTER_UNITS_TO_DEVICE (min_width);
+          size_hints->min_height = CLUTTER_UNITS_TO_DEVICE (min_height);
+          size_hints->flags = PMinSize;
+
+          if (!resize)
+            {
+              size_hints->max_width = size_hints->min_width;
+              size_hints->max_height = size_hints->min_height;
+              size_hints->flags |= PMaxSize;
+            }
         }
 
       XSetWMNormalHints (stage_x11->xdpy, stage_x11->xwin, size_hints);
@@ -384,7 +391,6 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
   ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
   ClutterBackendX11 *backend_x11 = stage_x11->backend;
   ClutterStage *stage = stage_x11->wrapper;
-  static gboolean was_resizeable = FALSE;
 
   if (!stage)
     return;
@@ -395,6 +401,11 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
     {
       int width, height;
 
+      /* FIXME: this will do the wrong thing for dual-headed
+         displays. This will return the size of the combined display
+         but Metacity (at least) will fullscreen to only one of the
+         displays. This will cause the actor to report the wrong size
+         until the ConfigureNotify for the correct size is received */
       width  = DisplayWidth (stage_x11->xdpy, stage_x11->xscreen);
       height = DisplayHeight (stage_x11->xdpy, stage_x11->xscreen);
 
@@ -409,10 +420,10 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
 
       clutter_actor_set_size (CLUTTER_ACTOR (stage), width, height);
 
+      stage_x11->fullscreen_on_map = TRUE;
+
       if (stage_x11->xwin != None)
         {
-          stage_x11->fullscreen_on_map = TRUE;
-
           /* 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
@@ -429,13 +440,11 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
             }
           else
             {
-              /* We need to set window user resize-able for metacity at 
-               * at least to allow the window to fullscreen *sigh*  
-              */
-              if (clutter_stage_get_user_resizable (stage) == TRUE)
-                was_resizeable = TRUE;
-              else
-                 clutter_stage_set_user_resizable (stage, TRUE);
+              /* 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
+                 fullscreen correctly. */
+              clutter_stage_x11_fix_window_size (stage_x11);
 
               send_wmspec_change_state (backend_x11, stage_x11->xwin,
                                         backend_x11->atom_NET_WM_STATE_FULLSCREEN,
@@ -445,6 +454,8 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
     }
   else
     {
+      stage_x11->fullscreen_on_map = FALSE;
+
       if (stage_x11->xwin != None)
         {
           if (!CLUTTER_ACTOR_IS_MAPPED (stage_x11))
@@ -456,21 +467,15 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
             }
           else
             {
-              clutter_stage_set_user_resizable (stage, TRUE);
-
               send_wmspec_change_state (backend_x11,
                                         stage_x11->xwin,
                                         backend_x11->atom_NET_WM_STATE_FULLSCREEN,
                                         FALSE);
 
-              /* reset the windows state - this isn't fun - see above */
-              if (!was_resizeable)
-                clutter_stage_set_user_resizable (stage, FALSE);
-
-              was_resizeable = FALSE;
+              /* Fix the window size to restore the minimum/maximum
+                 restriction */
+              clutter_stage_x11_fix_window_size (stage_x11);
             }
-
-          stage_x11->fullscreen_on_map = FALSE;
         }
     }
 }