Putting in the "glutFullScreen" support for Gnome and other X window managers per...
authorJohn F. Fay <johnffay@nettally.com>
Wed, 18 Nov 2009 01:52:13 +0000 (01:52 +0000)
committerJohn F. Fay <johnffay@nettally.com>
Wed, 18 Nov 2009 01:52:13 +0000 (01:52 +0000)
git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@849 7f0cb862-5218-0410-a997-914c9d46530a

src/freeglut_internal.h
src/freeglut_state.c
src/freeglut_structure.c
src/freeglut_window.c

index 5b2784a..7c71873 100644 (file)
@@ -436,6 +436,8 @@ struct tagSFG_WindowState
     GLboolean       KeyRepeating;       /* Currently in repeat mode          */
 
     GLboolean       NeedToResize;       /* Do we need to resize the window?  */
+
+    GLboolean       IsFullscreen;       /* is the window fullscreen? */
 };
 
 
index a763d27..589f8ff 100644 (file)
@@ -68,23 +68,9 @@ static int fghGetConfig( int attribute )
 static int fghCheckFullScreen(void)
 {
 #if TARGET_HOST_POSIX_X11
-
-  int result;
-
-  result = 0;
-  if (fgDisplay.StateFullScreen != None)
-    {
-      result = fgHintPresent(fgStructure.CurrentWindow->Window.Handle,
-                            fgDisplay.State,
-                            fgDisplay.StateFullScreen);
-    }
-
-  return result;
-
+    return fgStructure.CurrentWindow->State.IsFullscreen;
 #else
-
-  return 0;
-
+    return 0;
 #endif
 }
 
index c1b9145..e092429 100644 (file)
@@ -97,6 +97,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title,
 
     window->State.IgnoreKeyRepeat = GL_FALSE;
     window->State.KeyRepeating    = GL_FALSE;
+    window->State.IsFullscreen    = GL_FALSE;
 
     /*
      * Open the window now. The fgOpenWindow() function is system
index 1327b1e..e19eaff 100644 (file)
@@ -1559,41 +1559,111 @@ void FGAPIENTRY glutPopWindow( void )
 #endif
 }
 
-/*
- * Resize the current window so that it fits the whole screen
- */
-void FGAPIENTRY glutFullScreen( void )
+#if TARGET_HOST_POSIX_X11
+static int ewmh_fullscr_toggle(void);
+static int resize_fullscr_toogle(void);
+
+static int toggle_fullscreen(void)
 {
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
-    FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
+    /* first try the EWMH (_NET_WM_STATE) method ... */
+    if(ewmh_fullscr_toggle() != -1) {
+        return 0;
+    }
 
-    if (glutGet(GLUT_FULL_SCREEN))
-    {
-      /*  Leave full screen state before resizing. */
-      glutFullScreenToggle();
+    /* fall back to resizing the window */
+    if(resize_fullscr_toogle() != -1) {
+        return 0;
     }
+    return -1;
+}
 
-    {
-#if TARGET_HOST_POSIX_X11
+#define _NET_WM_STATE_TOGGLE    2
+static int ewmh_fullscr_toggle(void)
+{
+    XEvent xev;
+    long evmask = SubstructureRedirectMask | SubstructureNotifyMask;
 
-        Status status;  /* Returned by XGetWindowAttributes(), not checked. */
-        XWindowAttributes attributes;
+    if(!fgDisplay.State || !fgDisplay.StateFullScreen) {
+        return -1;
+    }
+
+    xev.type = ClientMessage;
+    xev.xclient.window = fgStructure.CurrentWindow->Window.Handle;
+    xev.xclient.message_type = fgDisplay.State;
+    xev.xclient.format = 32;
+    xev.xclient.data.l[0] = _NET_WM_STATE_TOGGLE;
+    xev.xclient.data.l[1] = fgDisplay.StateFullScreen;
+    xev.xclient.data.l[2] = 0; /* no second property to toggle */
+    xev.xclient.data.l[3] = 1; /* source indication: application */
+    xev.xclient.data.l[4] = 0; /* unused */
+
+    if(!XSendEvent(fgDisplay.Display, fgDisplay.RootWindow, 0, evmask, &xev)) {
+        return -1;
+    }
+    return 0;
+}
 
-        status = XGetWindowAttributes(fgDisplay.Display,
-                                      fgStructure.CurrentWindow->Window.Handle,
-                                      &attributes);
+static int resize_fullscr_toogle(void)
+{
+    XWindowAttributes attributes;
+
+    if(glutGet(GLUT_FULL_SCREEN)) {
+        /* restore original window size */
+        SFG_Window *win = fgStructure.CurrentWindow;
+        fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
+        fgStructure.CurrentWindow->State.Width  = win->State.OldWidth;
+        fgStructure.CurrentWindow->State.Height = win->State.OldHeight;
+
+    } else {
+        /* resize the window to cover the entire screen */
+        XGetWindowAttributes(fgDisplay.Display,
+                fgStructure.CurrentWindow->Window.Handle,
+                &attributes);
+        
         /*
          * The "x" and "y" members of "attributes" are the window's coordinates
          * relative to its parent, i.e. to the decoration window.
          */
         XMoveResizeWindow(fgDisplay.Display,
-                          fgStructure.CurrentWindow->Window.Handle,
-                          -attributes.x,
-                          -attributes.y,
-                          fgDisplay.ScreenWidth,
-                          fgDisplay.ScreenHeight);
+                fgStructure.CurrentWindow->Window.Handle,
+                -attributes.x,
+                -attributes.y,
+                fgDisplay.ScreenWidth,
+                fgDisplay.ScreenHeight);
+    }
+    return 0;
+}
+#endif /* TARGET_HOST_POSIX_X11 */
+
+
+/*
+ * Resize the current window so that it fits the whole screen
+ */
+void FGAPIENTRY glutFullScreen( void )
+{
+    SFG_Window *win;
+
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
+    FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
+
+    win = fgStructure.CurrentWindow;
+
+#if TARGET_HOST_POSIX_X11
+    if(!glutGet(GLUT_FULL_SCREEN)) {
+        if(toggle_fullscreen() != -1) {
+            win->State.IsFullscreen = GL_TRUE;
+        }
+    }
 
 #elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) /* FIXME: what about WinCE */
+
+    if (glutGet(GLUT_FULL_SCREEN))
+    {
+        /*  Leave full screen state before resizing. */
+        glutFullScreenToggle();
+    }
+
+    {
         RECT rect;
 
         /* For fullscreen mode, force the top-left corner to 0,0
@@ -1625,8 +1695,10 @@ void FGAPIENTRY glutFullScreen( void )
                       SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
                       SWP_NOZORDER
                     );
-#endif
+        
+        win->State.IsFullscreen = GL_TRUE;
     }
+#endif
 }
 
 /*
@@ -1634,54 +1706,21 @@ void FGAPIENTRY glutFullScreen( void )
  */
 void FGAPIENTRY glutFullScreenToggle( void )
 {
+    SFG_Window *win;
+
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" );
     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" );
 
-    {
-#if TARGET_HOST_POSIX_X11
+    win = fgStructure.CurrentWindow;
 
-      if (fgDisplay.StateFullScreen != None)
-      {
-        XEvent xevent;
-        long event_mask;
-        int status;
-
-        xevent.type = ClientMessage;
-        xevent.xclient.type = ClientMessage;
-        xevent.xclient.serial = 0;
-        xevent.xclient.send_event = True;
-        xevent.xclient.display = fgDisplay.Display;
-        xevent.xclient.window = fgStructure.CurrentWindow->Window.Handle;
-        xevent.xclient.message_type = fgDisplay.State;
-        xevent.xclient.format = 32;
-        xevent.xclient.data.l[0] = 2;  /* _NET_WM_STATE_TOGGLE */
-        xevent.xclient.data.l[1] = fgDisplay.StateFullScreen;
-        xevent.xclient.data.l[2] = 0;
-        xevent.xclient.data.l[3] = 0;
-        xevent.xclient.data.l[4] = 0;
-
-        /*** Don't really understand how event masks work... ***/
-        event_mask = SubstructureRedirectMask | SubstructureNotifyMask;
-
-        status = XSendEvent(fgDisplay.Display,
-          fgDisplay.RootWindow,
-          False,
-          event_mask,
-          &xevent);
-        FREEGLUT_INTERNAL_ERROR_EXIT(status != 0,
-          "XSendEvent failed",
-          "glutFullScreenToggle");
-      }
-      else
-#endif
-      {
-        /*
-         * If the window manager is not Net WM compliant, fall back to legacy
-         * behaviour.
-         */
-        glutFullScreen();
-      }
+#if TARGET_HOST_POSIX_X11
+    if(toggle_fullscreen() != -1) {
+        win->State.IsFullscreen = !win->State.IsFullscreen;
     }
+#elif TARGET_HOST_MS_WINDOWS
+    glutFullScreen();
+    win->State.IsFullscreen = !win->State.IsFullscreen;
+#endif
 }
 
 /*