2007-11-26 Emmanuele Bassi <ebassi@openedhand.com>
authorEmmanuele Bassi <ebassi@openedhand.com>
Mon, 26 Nov 2007 12:07:25 +0000 (12:07 +0000)
committerEmmanuele Bassi <ebassi@openedhand.com>
Mon, 26 Nov 2007 12:07:25 +0000 (12:07 +0000)
* 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.

ChangeLog
clutter/clutter-actor.c
clutter/eglnative/clutter-stage-egl.c
clutter/osx/clutter-stage-osx.c
clutter/sdl/clutter-stage-sdl.c
clutter/x11/clutter-event-x11.c
clutter/x11/clutter-stage-x11.c
clutter/x11/clutter-stage-x11.h
tests/Makefile.am
tests/test-fullscreen.c [new file with mode: 0644]

index 8108d2b..7cb2aa8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        * clutter/clutter-actor.c:
index ae76f87..12083ca 100644 (file)
@@ -233,7 +233,11 @@ clutter_actor_real_show (ClutterActor *self)
       if (!CLUTTER_ACTOR_IS_REALIZED (self))
         clutter_actor_realize (self);
 
-      CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED);
+      /* 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);
 
       if (CLUTTER_ACTOR_IS_VISIBLE (self))
         clutter_actor_queue_redraw (self);
@@ -286,7 +290,12 @@ clutter_actor_real_hide (ClutterActor *self)
 {
   if (CLUTTER_ACTOR_IS_VISIBLE (self))
     {
-      CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_MAPPED);
+      /* 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_queue_redraw (self);
     }
 }
index 35b54f3..dcad992 100644 (file)
@@ -22,9 +22,7 @@ clutter_stage_egl_show (ClutterActor *actor)
 {
   ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
 
-  /* we are always shown... */
-
-  return;
+  CLUTTER_ACTOR_SET_FLAGS (stage_egl, CLUTTER_ACTOR_MAPPED);
 }
 
 static void
@@ -32,9 +30,7 @@ clutter_stage_egl_hide (ClutterActor *actor)
 {
   ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
 
-  /* we are always shown... */
-
-  return;
+  CLUTTER_ACTOR_UNSET_FLAGS (stage_egl, CLUTTER_ACTOR_MAPPED);
 }
 
 static void
index 79c6da2..096acbb 100644 (file)
@@ -322,6 +322,8 @@ clutter_stage_osx_show (ClutterActor *actor)
 
   CLUTTER_NOTE (BACKEND, "show");
 
+  CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
+
   if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show)
     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_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
+
   if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->hide)
     CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->hide (actor);
 }
index 92b7d2c..893ab92 100644 (file)
@@ -22,14 +22,18 @@ G_DEFINE_TYPE (ClutterStageSDL, clutter_stage_sdl, CLUTTER_TYPE_STAGE);
 static void
 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
 clutter_stage_sdl_hide (ClutterActor *actor)
 {
   /* 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
index da162fb..b7c8f8e 100644 (file)
@@ -233,11 +233,11 @@ translate_key_event (ClutterBackend *backend,
   event->key.hardware_keycode = xevent->xkey.keycode;
 
   /* FIXME: We need to handle other modifiers rather than just shift */
-  event->key.keyval 
-    XKeycodeToKeysym (xevent->xkey.display, 
-                       xevent->xkey.keycode,
-                       (event->key.modifier_state & CLUTTER_SHIFT_MASK) 
-                          ? 1 : 0);
+  event->key.keyval 
+    XKeycodeToKeysym (xevent->xkey.display, 
+                      xevent->xkey.keycode,
+                      (event->key.modifier_state & CLUTTER_SHIFT_MASK) ? 1
+                                                                       : 0);
 }
 
 static gboolean
@@ -256,7 +256,7 @@ handle_wm_protocols_event (ClutterBackendX11 *backend_x11,
        * we relay the event to the application and we let it
        * handle the request
        */
-      CLUTTER_NOTE (EVENT, "delete window:\twindow: %ld",
+      CLUTTER_NOTE (EVENT, "delete window:\txid: %ld",
                     xevent->xclient.window);
 
       set_user_time (backend_x11,
@@ -380,73 +380,89 @@ event_translate (ClutterBackend *backend,
   switch (xevent->type)
     {
     case ConfigureNotify:
-      if (xevent->xconfigure.width 
-         != clutter_actor_get_width (CLUTTER_ACTOR (stage))
-         ||
-         xevent->xconfigure.height 
-         != clutter_actor_get_height (CLUTTER_ACTOR (stage)))
-       clutter_actor_set_size (CLUTTER_ACTOR (stage),
-                               xevent->xconfigure.width,
-                               xevent->xconfigure.height);
+      {
+        guint stage_width, stage_height;
+
+        clutter_actor_get_size (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),
+                                    xevent->xconfigure.width,
+                                    xevent->xconfigure.height);
+          }
+      }
       res = FALSE;
       break;
+
     case PropertyNotify:
-      {
-       if (xevent->xproperty.atom == backend_x11->atom_NET_WM_STATE)
-         {
-           Atom     type;
-           gint     format;
-           gulong   nitems, bytes_after;
-           guchar  *data = NULL;
-           Atom    *atoms = NULL;
-           gulong   i;
-           gboolean fullscreen_set = FALSE;
-
-           clutter_x11_trap_x_errors ();
-           XGetWindowProperty (backend_x11->xdpy, 
-                               stage_xwindow,
-                               backend_x11->atom_NET_WM_STATE,
-                               0, G_MAXLONG, 
-                               False, XA_ATOM, 
-                               &type, &format, &nitems,
-                               &bytes_after, &data);
-           clutter_x11_untrap_x_errors ();
-
-           if (type != None && data != NULL)
-             {
-               atoms = (Atom *)data;
-
-               i = 0;
-               while (i < nitems)
-                 {
-                   if (atoms[i] == backend_x11->atom_NET_WM_STATE_FULLSCREEN)
-                     fullscreen_set = TRUE;
-                   i++;
-                 }
-
-               if (fullscreen_set 
-                     != !!(stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN))
-                 {
-                   if (fullscreen_set)
-                     stage_x11->state |= CLUTTER_STAGE_STATE_FULLSCREEN;
-                   else
-                     stage_x11->state &= ~CLUTTER_STAGE_STATE_FULLSCREEN;
-
-                   event->type = CLUTTER_STAGE_STATE;
-                   event->stage_state.changed_mask 
-                               = CLUTTER_STAGE_STATE_FULLSCREEN;
-                   event->stage_state.new_state = stage_x11->state;
-                 }
-               else
-                 res = FALSE;
-
-               XFree (data);
-             }
-         }
-       else
-         res = FALSE;
-      }
+      if (xevent->xproperty.atom == backend_x11->atom_NET_WM_STATE)
+        {
+          Atom     type;
+          gint     format;
+          gulong   n_items, bytes_after;
+          guchar  *data = NULL;
+          gboolean fullscreen_set = FALSE;
+
+          clutter_x11_trap_x_errors ();
+          XGetWindowProperty (backend_x11->xdpy, stage_xwindow,
+                              backend_x11->atom_NET_WM_STATE,
+                              0, G_MAXLONG, 
+                              False, XA_ATOM,
+                              &type, &format, &n_items,
+                              &bytes_after, &data);
+          clutter_x11_untrap_x_errors ();
+
+          if (type != None && data != NULL)
+            {
+              Atom *atoms = (Atom *) data;
+              gulong i;
+              gboolean is_fullscreen = FALSE;
+
+              for (i = 0; i < n_items; i++)
+                {
+                  if (atoms[i] == backend_x11->atom_NET_WM_STATE_FULLSCREEN)
+                    fullscreen_set = TRUE;
+               }
+
+              is_fullscreen =
+                (stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN);
+
+              if (fullscreen_set != is_fullscreen)
+               {
+                 if (fullscreen_set)
+                    stage_x11->state |= CLUTTER_STAGE_STATE_FULLSCREEN;
+                 else
+                    stage_x11->state &= ~CLUTTER_STAGE_STATE_FULLSCREEN;
+
+                  event->type = CLUTTER_STAGE_STATE;
+                  event->stage_state.changed_mask =
+                    CLUTTER_STAGE_STATE_FULLSCREEN;
+                  event->stage_state.new_state = stage_x11->state;
+                }
+              else
+                res = FALSE;
+              
+              XFree (data);
+           }
+         else
+            res = FALSE;
+        }
+      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:
       if (!(stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED))
        {
@@ -460,6 +476,7 @@ event_translate (ClutterBackend *backend,
       else
        res = FALSE;
       break;
+
     case FocusOut:
       if (stage_x11->state & CLUTTER_STAGE_STATE_ACTIVATED)
        {
@@ -472,6 +489,7 @@ event_translate (ClutterBackend *backend,
       else
        res = FALSE;
       break;
+
     case Expose:
       {
         XEvent foo_xev;
@@ -489,15 +507,18 @@ event_translate (ClutterBackend *backend,
         res = FALSE;
       }
       break;
+
     case KeyPress:
       event->type = CLUTTER_KEY_PRESS;
       translate_key_event (backend, event, xevent);
       set_user_time (backend_x11, &xwindow, xevent->xkey.time);
       break;
+
     case KeyRelease:
       event->type = CLUTTER_KEY_RELEASE;
       translate_key_event (backend, event, xevent);
       break;
+
     case ButtonPress:
       switch (xevent->xbutton.button)
         {
@@ -535,6 +556,7 @@ event_translate (ClutterBackend *backend,
 
       set_user_time (backend_x11, &xwindow, event->button.time);
       break;
+
     case ButtonRelease:
       /* scroll events don't have a corresponding release */
       if (xevent->xbutton.button == 4 ||
@@ -553,6 +575,7 @@ event_translate (ClutterBackend *backend,
       event->button.modifier_state = xevent->xbutton.state;
       event->button.button = xevent->xbutton.button;
       break;
+
     case MotionNotify:
       event->motion.type = event->type = CLUTTER_MOTION;
       event->motion.time = xevent->xmotion.time;
@@ -560,11 +583,13 @@ event_translate (ClutterBackend *backend,
       event->motion.y = xevent->xmotion.y;
       event->motion.modifier_state = xevent->xmotion.state;
       break;
+
     case DestroyNotify:
-      CLUTTER_NOTE (EVENT, "destroy notify:\twindow: %ld",
+      CLUTTER_NOTE (EVENT, "destroy notify:\txid: %ld",
                     xevent->xdestroywindow.window);
       event->type = event->any.type = CLUTTER_DESTROY_NOTIFY;
       break;
+
     case ClientMessage:
       CLUTTER_NOTE (EVENT, "client message");
       
@@ -578,6 +603,7 @@ event_translate (ClutterBackend *backend,
           event->type = event->any.type = CLUTTER_DELETE;
         }
       break;
+
     default:
       /* ignore every other event */
       res = FALSE;
index d79d24a..f891b14 100644 (file)
@@ -94,10 +94,10 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11)
 
       if (!resize)
        {
-         size_hints->max_width  
-           = size_hints->min_width = stage_x11->xwin_width;
-         size_hints->max_height 
-           = size_hints->min_height = stage_x11->xwin_height;
+         size_hints->max_width = size_hints->min_width =
+            stage_x11->xwin_width;
+         size_hints->max_height = size_hints->min_height =
+            stage_x11->xwin_height;
          size_hints->flags = PMinSize|PMaxSize;
        }
 
@@ -112,19 +112,18 @@ clutter_stage_x11_show (ClutterActor *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)
     {
       /* Fire off a redraw to avoid flicker on first map.
        * Appears not to work perfectly on intel drivers at least.
       */
       clutter_redraw();
+
       XSync (stage_x11->xdpy, FALSE);
       XMapWindow (stage_x11->xdpy, stage_x11->xwin);
     }
 
+  /* chain up */
   CLUTTER_ACTOR_CLASS (clutter_stage_x11_parent_class)->show (actor);
 }
 
@@ -136,6 +135,7 @@ clutter_stage_x11_hide (ClutterActor *actor)
   if (stage_x11->xwin)
     XUnmapWindow (stage_x11->xdpy, stage_x11->xwin);
 
+  /* chain up */
   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 (!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;
 
@@ -228,14 +233,13 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
 
              clutter_actor_set_size (CLUTTER_ACTOR (stage_x11), 
                                      width, height);
+
              /* FIXME: This wont work if we support more states */
-             XChangeProperty 
-               (stage_x11->xdpy,
-                stage_x11->xwin,
-                backend_x11->atom_NET_WM_STATE, XA_ATOM, 32,
-                PropModeReplace,
-                (unsigned char *)&backend_x11->atom_NET_WM_STATE_FULLSCREEN,
-                1);
+             XChangeProperty (stage_x11->xdpy,
+                               stage_x11->xwin,
+                               backend_x11->atom_NET_WM_STATE, XA_ATOM, 32,
+                               PropModeReplace,
+                               (unsigned char *) &backend_x11->atom_NET_WM_STATE_FULLSCREEN, 1);
            }
          else
            {
@@ -247,18 +251,19 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
              else
                clutter_stage_set_user_resizable (stage, TRUE);
 
-             send_wmspec_change_state(backend_x11,
-                                      stage_x11->xwin,
+             send_wmspec_change_state(backend_x11, stage_x11->xwin,
                                       backend_x11->atom_NET_WM_STATE_FULLSCREEN,
                                       TRUE);
            }
+
+          stage_x11->fullscreen_on_map = TRUE;
        }
     }
   else
     {
       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 */
              XDeleteProperty (stage_x11->xdpy, 
@@ -280,10 +285,12 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
 
              was_resizeable = FALSE;
            }
+
+          stage_x11->fullscreen_on_map = FALSE;
        }
     }
 
-  CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
+  CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
 }
 
 static void
@@ -301,9 +308,7 @@ clutter_stage_x11_set_cursor_visible (ClutterStage *stage,
 
   if (show_cursor)
     {
-#if 0 /* HAVE_XFIXES - borked on fiesty at least so disabled until further 
-       *               investigation.   
-       */
+#if 0 /* HAVE_XFIXES */
       XFixesShowCursor (stage_x11->xdpy, stage_x11->xwin);
 #else
       XUndefineCursor (stage_x11->xdpy, stage_x11->xwin);
@@ -311,7 +316,7 @@ clutter_stage_x11_set_cursor_visible (ClutterStage *stage,
     }
   else
     {
-#if 0 /* HAVE_XFIXES - borked */
+#if 0 /* HAVE_XFIXES */
       XFixesHideCursor (stage_x11->xdpy, stage_x11->xwin);
 #else
       XColor col;
@@ -420,8 +425,9 @@ clutter_stage_x11_init (ClutterStageX11 *stage)
   stage->xvisinfo = None;
 
   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;
 }
+
+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);
+}
+
index 194d6e9..9a00741 100644 (file)
@@ -45,7 +45,8 @@ struct _ClutterStageX11
 {
   ClutterStage parent_instance;
 
-  int          is_foreign_xwin :1;
+  guint        is_foreign_xwin   : 1;
+  guint        fullscreen_on_map : 1;
 
   Display     *xdpy;
   Window       xwin_root;
@@ -68,11 +69,11 @@ struct _ClutterStageX11Class
 GType clutter_stage_x11_get_type (void) G_GNUC_CONST;
 
 /* Private to subclasses */
-void
-clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11);
+void clutter_stage_x11_fix_window_size  (ClutterStageX11 *stage_x11);
+void clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11);
 
-void
-clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11);
+void clutter_stage_x11_map   (ClutterStageX11 *stage_x11);
+void clutter_stage_x11_unmap (ClutterStageX11 *stage_x11);
 
 G_END_DECLS
 
index 1fa4ec0..ae9a057 100644 (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-boxes test-perspective test-rotate test-depth \
                  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)/
 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_model_SOURCES       = test-model.c
 test_effects_SOURCES     = test-effects.c
+test_fullscreen_SOURCES  = test-fullscreen.c
 
 EXTRA_DIST = redhand.png test-script.json
diff --git a/tests/test-fullscreen.c b/tests/test-fullscreen.c
new file mode 100644 (file)
index 0000000..a6f6a04
--- /dev/null
@@ -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;
+}