fix for fullscreen on X11 (used by the BGE, not blender application),
authorCampbell Barton <ideasman42@gmail.com>
Sun, 24 Feb 2013 05:05:29 +0000 (05:05 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 24 Feb 2013 05:05:29 +0000 (05:05 +0000)
changing the screen resolution wasn't still allowed for larger virtual desktops.

added an exclusive option to ghost so the fullscreen window is ignored by the window manager and we get all events. (common practice for games on X11).

12 files changed:
intern/ghost/GHOST_ISystem.h
intern/ghost/GHOST_IWindow.h
intern/ghost/intern/GHOST_System.cpp
intern/ghost/intern/GHOST_System.h
intern/ghost/intern/GHOST_SystemX11.cpp
intern/ghost/intern/GHOST_SystemX11.h
intern/ghost/intern/GHOST_Window.cpp
intern/ghost/intern/GHOST_Window.h
intern/ghost/intern/GHOST_WindowManager.cpp
intern/ghost/intern/GHOST_WindowX11.cpp
intern/ghost/intern/GHOST_WindowX11.h
source/gameengine/GamePlayer/ghost/GPG_Application.cpp

index 841293e09e4bc8b6352af73f0c4bb4da5e234d8f..e0b483d07fe56e133eb10dab6381eab38be2645e 100644 (file)
@@ -253,6 +253,7 @@ public:
            GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height,
            GHOST_TWindowState state, GHOST_TDrawingContextType type,
            const bool stereoVisual = false,
+           const bool exclusive = false,
            const GHOST_TUns16 numOfAASamples = 0,
            const GHOST_TEmbedderWindowID parentWindow = 0) = 0;
 
index 4cf0dbfb82042a0b2fc8c052a01da886613cec36..a2d3e9b91fbb884822450548a0a888c605d865b8 100644 (file)
@@ -305,7 +305,10 @@ public:
         */
        virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]) { return GHOST_kSuccess; }
 
-       
+       /** */
+       virtual GHOST_TSuccess beginFullScreen() const = 0;
+       virtual GHOST_TSuccess endFullScreen() const = 0;
+
        virtual float getNativePixelSize(void) = 0;
 
        
index 080619bc0ac117d29a1fcf45e99df57a0ff5de3a..5405fe7efe8769f4605d7f345b7deb0e91675e5f 100644 (file)
@@ -152,7 +152,7 @@ GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting
                        success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
                        if (success == GHOST_kSuccess) {
                                //GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n");
-                               success = createFullScreenWindow((GHOST_Window **)window, stereoVisual, numOfAASamples);
+                               success = createFullScreenWindow((GHOST_Window **)window, setting, stereoVisual, numOfAASamples);
                                if (success == GHOST_kSuccess) {
                                        m_windowManager->beginFullScreen(*window, stereoVisual);
                                }
@@ -347,26 +347,22 @@ GHOST_TSuccess GHOST_System::exit()
        return GHOST_kSuccess;
 }
 
-
-GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
+GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
+                                                    const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
 {
-       GHOST_TSuccess success;
+       /* note: don't use getCurrentDisplaySetting() because on X11 we may
+        * be zoomed in and the desktop may be bigger then the viewport. */
        GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager");
-       GHOST_DisplaySetting settings;
-
-       success = m_displayManager->getCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, settings);
-       if (success) {
-               //GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
-               *window = (GHOST_Window *)createWindow(
-                   STR_String(""),
-                   0, 0, settings.xPixels, settings.yPixels,
-                   GHOST_kWindowStateFullScreen,
-                   GHOST_kDrawingContextTypeOpenGL,
-                   stereoVisual,
-                   numOfAASamples);
-               success = *window == 0 ? GHOST_kFailure : GHOST_kSuccess;
-       }
-       return success;
+       //GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
+       *window = (GHOST_Window *)createWindow(
+           STR_String(""),
+           0, 0, settings.xPixels, settings.yPixels,
+           GHOST_kWindowStateNormal,
+           GHOST_kDrawingContextTypeOpenGL,
+           stereoVisual,
+           true,  /* exclusive */
+           numOfAASamples);
+       return (*window == NULL) ? GHOST_kFailure : GHOST_kSuccess;
 }
 
 
index 928bbe6a31b6332421f38a72e693779100b71f0c..0d18dfe532ff05ef62c2594008a3fd8d1080279b 100644 (file)
@@ -330,7 +330,7 @@ protected:
         * \param window The window created.
         * \return Indication of success.
         */
-       virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window **window,
+       virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
                                                      const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0);
 
        /** The display manager (platform dependant). */
index 48fb8375303e36c0a9283b0f3c02765cd244359e..d00265fbd9b2c3688d3f975e5a3a948bacf90114 100644 (file)
@@ -278,6 +278,8 @@ getAllDisplayDimensions(
  * \param      state   The state of the window when opened.
  * \param      type    The type of drawing context installed in this window.
  * \param      stereoVisual    Stereo visual for quad buffered stereo.
+ * \param      exclusive       Use to show the window ontop and ignore others
+ *                                             (used fullscreen).
  * \param      numOfAASamples  Number of samples used for AA (zero if no AA)
  * \param      parentWindow    Parent (embedder) window
  * \return     The new window (or 0 if creation failed).
@@ -292,7 +294,8 @@ createWindow(
                GHOST_TUns32 height,
                GHOST_TWindowState state,
                GHOST_TDrawingContextType type,
-               bool stereoVisual,
+               const bool stereoVisual,
+               const bool exclusive,
                const GHOST_TUns16 numOfAASamples,
                const GHOST_TEmbedderWindowID parentWindow)
 {
@@ -305,7 +308,9 @@ createWindow(
 
        window = new GHOST_WindowX11(this, m_display, title,
                                     left, top, width, height,
-                                    state, parentWindow, type, stereoVisual, numOfAASamples);
+                                    state, parentWindow, type,
+                                    stereoVisual, exclusive,
+                                    numOfAASamples);
 
        if (window) {
                /* Both are now handle in GHOST_WindowX11.cpp
index a11aea240bee12b94ef25d34117844b51550d94b..6a492f64b4157fc9eaa2abde88abaeecf164b5fe 100644 (file)
@@ -137,7 +137,9 @@ public:
         * \param       height          The height the window.
         * \param       state           The state of the window when opened.
         * \param       type            The type of drawing context installed in this window.
-        * \param       stereoVisual    Create a stereo visual for quad buffered stereo.
+        * \param       stereoVisual    Create a stereo visual for quad buffered stereo.
+        * \param       exclusive       Use to show the window ontop and ignore others
+        *                                              (used fullscreen).
         * \param       parentWindow    Parent (embedder) window
         * \return      The new window (or 0 if creation failed).
         */
@@ -151,6 +153,7 @@ public:
            GHOST_TWindowState state,
            GHOST_TDrawingContextType type,
            const bool stereoVisual,
+           const bool exclusive = false,
            const GHOST_TUns16 numOfAASamples = 0,
            const GHOST_TEmbedderWindowID parentWindow = 0
            );
index ca12abe7324232c3ce54de7eb57540c68f31aae8..6c2d7350cd91163e1a39aab03c6bd15894c54da7 100644 (file)
@@ -45,6 +45,7 @@ GHOST_Window::GHOST_Window(
     GHOST_TWindowState state,
     GHOST_TDrawingContextType type,
     const bool stereoVisual,
+    const bool exclusive,
     const GHOST_TUns16 numOfAASamples)
        :
        m_drawingContextType(type),
index f7c67bf7be601e7d44ee92ea8de3c5a1808a02cc..588de0911e302576c7d616d3cc06ec162e175146 100644 (file)
@@ -80,6 +80,8 @@ public:
         * \param state                         The state the window is initially opened with.
         * \param type                          The type of drawing context installed in this window.
         * \param stereoVisual          Stereo visual for quad buffered stereo.
+        * \param exclusive                     Use to show the window ontop and ignore others
+        *                                                      (used fullscreen).
         * \param numOfAASamples        Number of samples used for AA (zero if no AA)
         */
        GHOST_Window(
@@ -88,6 +90,7 @@ public:
            GHOST_TWindowState state,
            GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
            const bool stereoVisual = false,
+           const bool exclusive = false,
            const GHOST_TUns16 numOfAASamples = 0);
 
        /**
index daf1c2f2d22bd7510e6a30325198b9f72b69a39f..1f20e01ca738af9a3ecd304e15b794637743635c 100644 (file)
@@ -130,12 +130,12 @@ GHOST_TSuccess GHOST_WindowManager::beginFullScreen(GHOST_IWindow *window,
                m_fullScreenWindow = window;
                m_activeWindowBeforeFullScreen = getActiveWindow();
                setActiveWindow(m_fullScreenWindow);
+               m_fullScreenWindow->beginFullScreen();
                success = GHOST_kSuccess;
        }
        return success;
 }
 
-
 GHOST_TSuccess GHOST_WindowManager::endFullScreen(void)
 {
        GHOST_TSuccess success = GHOST_kFailure;
@@ -143,6 +143,7 @@ GHOST_TSuccess GHOST_WindowManager::endFullScreen(void)
                if (m_fullScreenWindow != 0) {
                        //GHOST_PRINT("GHOST_WindowManager::endFullScreen(): deleting full-screen window\n");
                        setWindowInactive(m_fullScreenWindow);
+                       m_fullScreenWindow->endFullScreen();
                        delete m_fullScreenWindow;
                        //GHOST_PRINT("GHOST_WindowManager::endFullScreen(): done\n");
                        m_fullScreenWindow = 0;
index 8184475b610c5c59fc9586007227c322d864b54d..05ab24492c2dc54cea01992a7ba80ff27cc6130d 100644 (file)
@@ -165,9 +165,10 @@ GHOST_WindowX11(
     const GHOST_TEmbedderWindowID parentWindow,
     GHOST_TDrawingContextType type,
     const bool stereoVisual,
+    const bool exclusive,
     const GHOST_TUns16 numOfAASamples
     ) :
-       GHOST_Window(width, height, state, type, stereoVisual, numOfAASamples),
+       GHOST_Window(width, height, state, type, stereoVisual, exclusive, numOfAASamples),
        m_context(NULL),
        m_display(display),
        m_normal_state(GHOST_kWindowStateNormal),
@@ -254,6 +255,7 @@ GHOST_WindowX11(
         * This seems pretty much a legacy feature as we are in rgba mode anyway. */
 
        XSetWindowAttributes xattributes;
+       unsigned int xattributes_valuemask = (CWBorderPixel | CWColormap | CWEventMask);
        memset(&xattributes, 0, sizeof(xattributes));
 
        xattributes.colormap = XCreateColormap(m_display,
@@ -274,6 +276,11 @@ GHOST_WindowX11(
                PointerMotionMask | FocusChangeMask |
                PropertyChangeMask | KeymapStateMask;
 
+       if (exclusive) {
+               xattributes_valuemask |= CWOverrideRedirect;
+               xattributes.override_redirect = True;
+       }
+
        /* create the window! */
        if (parentWindow == 0) {
                m_window =  XCreateWindow(m_display,
@@ -286,7 +293,7 @@ GHOST_WindowX11(
                                          m_visual->depth,
                                          InputOutput,
                                          m_visual->visual,
-                                         CWBorderPixel | CWColormap | CWEventMask,
+                                         xattributes_valuemask,
                                          &xattributes
                                          );
        }
@@ -315,7 +322,7 @@ GHOST_WindowX11(
                                         m_visual->depth,
                                         InputOutput,
                                         m_visual->visual,
-                                        CWBorderPixel | CWColormap | CWEventMask,
+                                        xattributes_valuemask,
                                         &xattributes
                                         );
 
@@ -486,7 +493,12 @@ GHOST_WindowX11(
                GHOST_PRINT("Created window\n");
        }
 
-       XMapWindow(m_display, m_window);
+       if (exclusive) {
+               XMapRaised(m_display, m_window);
+       }
+       else {
+               XMapWindow(m_display, m_window);
+       }
        GHOST_PRINT("Mapped window\n");
 
        XFlush(m_display);
@@ -1498,3 +1510,44 @@ setWindowCustomCursorShape(
 
        return GHOST_kSuccess;
 }
+
+
+GHOST_TSuccess
+GHOST_WindowX11::
+beginFullScreen() const
+{
+       {
+               Window root_return;
+               int x_return, y_return;
+               unsigned int w_return, h_return, border_w_return, depth_return;
+
+               XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
+                            &w_return, &h_return, &border_w_return, &depth_return);
+
+               m_system->setCursorPosition(w_return / 2, h_return / 2);
+       }
+
+
+       /* Grab Keyboard & Mouse */
+       int err;
+
+       err = XGrabKeyboard(m_display, m_window, False,
+                           GrabModeAsync, GrabModeAsync, CurrentTime);
+       if (err != GrabSuccess) printf("XGrabKeyboard failed %d\n", err);
+
+       err = XGrabPointer(m_display, m_window, False,  PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
+                          GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
+       if (err != GrabSuccess) printf("XGrabPointer failed %d\n", err);
+
+       return GHOST_kSuccess;
+}
+
+GHOST_TSuccess
+GHOST_WindowX11::
+endFullScreen() const
+{
+       XUngrabKeyboard(m_display, CurrentTime);
+       XUngrabPointer(m_display, CurrentTime);
+
+       return GHOST_kSuccess;
+}
index 10d44987647fa4278e222b56e20bf3c1417a93dd..c009512a831d0d819e80def96483d3a6350d9145 100644 (file)
@@ -87,6 +87,7 @@ public:
            const GHOST_TEmbedderWindowID parentWindow,
            GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
            const bool stereoVisual = false,
+           const bool exclusive = false,
            const GHOST_TUns16 numOfAASamples = 0
            );
 
@@ -308,6 +309,12 @@ protected:
            int bg_color
            );
 
+       GHOST_TSuccess
+       beginFullScreen() const;
+
+       GHOST_TSuccess
+       endFullScreen() const;
+
 private:
 
        /// Force use of public constructor.
index 89d11515bb33d36525d88f69e85adb6fe3be6e31..f3f4c31149a41af191aca15478897174eb61f64a 100644 (file)
@@ -386,6 +386,7 @@ bool GPG_Application::startFullScreen(
 
        fSystem->beginFullScreen(setting, &m_mainWindow, stereoVisual, samples);
        m_mainWindow->setCursorVisibility(false);
+       /* note that X11 ignores this (it uses a window internally for fullscreen) */
        m_mainWindow->setState(GHOST_kWindowStateFullScreen);
 
        success = initEngine(m_mainWindow, stereoMode);