Преглед изворни кода

Fixed a Linux platform bug that caused a crash on exiting a game, cleanup added for when the window is closed through the window manager (e.g. X button on the title bar)

pooerh пре 13 година
родитељ
комит
eb7dc7f167
1 измењених фајлова са 24 додато и 2 уклоњено
  1. 24 2
      gameplay/src/PlatformLinux.cpp

+ 24 - 2
gameplay/src/PlatformLinux.cpp

@@ -30,6 +30,7 @@ static Window   __window;
 static int __windowSize[2];
 static int __windowSize[2];
 static GLXContext __context;
 static GLXContext __context;
 static Window __attachToWindow;
 static Window __attachToWindow;
+static Atom __atomWmDeleteWindow;
 
 
 namespace gameplay
 namespace gameplay
 {
 {
@@ -487,6 +488,10 @@ Platform* Platform::create(Game* game, void* attachToWindow)
                             visualInfo->depth, InputOutput, visualInfo->visual, winMask,
                             visualInfo->depth, InputOutput, visualInfo->visual, winMask,
                             &winAttribs); 
                             &winAttribs); 
 
 
+    // Tell the window manager that it should send the delete window notification through ClientMessage
+    __atomWmDeleteWindow = XInternAtom(__display, "WM_DELETE_WINDOW", False);
+    XSetWMProtocols(__display, __window, &__atomWmDeleteWindow, 1);
+
     XMapWindow(__display, __window);
     XMapWindow(__display, __window);
 
 
     // Send fullscreen atom message to the window; most window managers respect WM_STATE messages
     // Send fullscreen atom message to the window; most window managers respect WM_STATE messages
@@ -494,8 +499,8 @@ Platform* Platform::create(Game* game, void* attachToWindow)
     if (fullscreen)
     if (fullscreen)
     {
     {
         XEvent xev;
         XEvent xev;
-        Atom atomWm_state = XInternAtom(__display, "_NET_WM_STATE", false);
-        Atom atomFullscreen = XInternAtom(__display, "_NET_WM_STATE_FULLSCREEN", false);
+        Atom atomWm_state = XInternAtom(__display, "_NET_WM_STATE", False);
+        Atom atomFullscreen = XInternAtom(__display, "_NET_WM_STATE_FULLSCREEN", False);
 
 
         memset(&xev, 0, sizeof(xev));
         memset(&xev, 0, sizeof(xev));
         xev.type = ClientMessage;
         xev.type = ClientMessage;
@@ -612,6 +617,17 @@ int Platform::enterMessagePump()
         
         
             switch (evt.type) 
             switch (evt.type) 
             {
             {
+            case ClientMessage:
+                {
+                    // Handle destroy window message correctly
+                    if (evt.xclient.data.l[0] == __atomWmDeleteWindow)
+                    {
+                        _game->exit();
+                        cleanupX11();
+                        exit(0);
+                    }
+                    break;
+                }
             case DestroyNotify :
             case DestroyNotify :
                 {
                 {
                     cleanupX11();
                     cleanupX11();
@@ -741,7 +757,13 @@ int Platform::enterMessagePump()
         }
         }
 
 
         if (_game)
         if (_game)
+        {
+            // Game state will be uninitialized if game was closed through Game::exit()
+            if (_game->getState() == Game::UNINITIALIZED)
+                break;            
+            
             _game->frame();
             _game->frame();
+        }
 
 
         glXSwapBuffers(__display, __window);
         glXSwapBuffers(__display, __window);
     }
     }