Browse Source

Do not allow Input to directly close the rendering window and cause engine main loop termination. Instead send an event. Engine::SetAutoExit() controls whether to exit automatically as a response.
Do not pump OS events inside static mutex, as SDL's own event queue is already thread-safe.

Lasse Öörni 12 years ago
parent
commit
a18ad2b45d

+ 14 - 0
Engine/Engine/Engine.cpp

@@ -30,6 +30,7 @@
 #include "FileSystem.h"
 #include "FileSystem.h"
 #include "Graphics.h"
 #include "Graphics.h"
 #include "Input.h"
 #include "Input.h"
+#include "InputEvents.h"
 #include "Log.h"
 #include "Log.h"
 #include "Navigation.h"
 #include "Navigation.h"
 #include "Network.h"
 #include "Network.h"
@@ -84,12 +85,14 @@ Engine::Engine(Context* context) :
     maxFps_(200),
     maxFps_(200),
     maxInactiveFps_(60),
     maxInactiveFps_(60),
     pauseMinimized_(false),
     pauseMinimized_(false),
+    autoExit_(true),
     #endif
     #endif
     initialized_(false),
     initialized_(false),
     exiting_(false),
     exiting_(false),
     headless_(false),
     headless_(false),
     audioPaused_(false)
     audioPaused_(false)
 {
 {
+    SubscribeToEvent(E_EXITREQUESTED, HANDLER(Engine, HandleExitRequested));
 }
 }
 
 
 Engine::~Engine()
 Engine::~Engine()
@@ -345,6 +348,11 @@ void Engine::SetPauseMinimized(bool enable)
     pauseMinimized_ = enable;
     pauseMinimized_ = enable;
 }
 }
 
 
+void Engine::SetAutoExit(bool enable)
+{
+    autoExit_ = enable;
+}
+
 void Engine::Exit()
 void Engine::Exit()
 {
 {
     Graphics* graphics = GetSubsystem<Graphics>();
     Graphics* graphics = GetSubsystem<Graphics>();
@@ -662,4 +670,10 @@ void Engine::RegisterSubsystems()
     #endif
     #endif
 }
 }
 
 
+void Engine::HandleExitRequested(StringHash eventType, VariantMap& eventData)
+{
+    if (autoExit_)
+        Exit();
+}
+
 }
 }

+ 8 - 0
Engine/Engine/Engine.h

@@ -58,6 +58,8 @@ public:
     void SetMaxInactiveFps(int fps);
     void SetMaxInactiveFps(int fps);
     /// Set whether to pause update events and audio when minimized.
     /// Set whether to pause update events and audio when minimized.
     void SetPauseMinimized(bool enable);
     void SetPauseMinimized(bool enable);
+    /// Set whether to exit automatically on exit request (window close button.)
+    void SetAutoExit(bool enable);
     /// Close the application window and set the exit flag.
     /// Close the application window and set the exit flag.
     void Exit();
     void Exit();
     /// Dump profiling information to the log.
     /// Dump profiling information to the log.
@@ -75,6 +77,8 @@ public:
     int GetMaxInactiveFps() const { return maxInactiveFps_; }
     int GetMaxInactiveFps() const { return maxInactiveFps_; }
     /// Return whether to pause update events and audio when minimized.
     /// Return whether to pause update events and audio when minimized.
     bool GetPauseMinimized() const { return pauseMinimized_; }
     bool GetPauseMinimized() const { return pauseMinimized_; }
+    /// Return whether to exit automatically on exit request.
+    bool GetAutoExit() const { return autoExit_; }
     /// Return whether engine has been initialized.
     /// Return whether engine has been initialized.
     bool IsInitialized() const { return initialized_; }
     bool IsInitialized() const { return initialized_; }
     /// Return whether exit has been requested.
     /// Return whether exit has been requested.
@@ -99,6 +103,8 @@ public:
 private:
 private:
     /// Create and register subsystems. In headless mode graphics, input & UI are not created.
     /// Create and register subsystems. In headless mode graphics, input & UI are not created.
     void RegisterSubsystems();
     void RegisterSubsystems();
+    /// Handle exit requested event.
+    void HandleExitRequested(StringHash eventType, VariantMap& eventData);
     
     
     /// Frame update timer.
     /// Frame update timer.
     HiresTimer frameTimer_;
     HiresTimer frameTimer_;
@@ -112,6 +118,8 @@ private:
     unsigned maxInactiveFps_;
     unsigned maxInactiveFps_;
     /// Pause when minimized flag.
     /// Pause when minimized flag.
     bool pauseMinimized_;
     bool pauseMinimized_;
+    /// Auto-exit flag.
+    bool autoExit_;
     /// Initialized flag.
     /// Initialized flag.
     bool initialized_;
     bool initialized_;
     /// Exiting flag.
     /// Exiting flag.

+ 14 - 4
Engine/Input/Input.cpp

@@ -38,6 +38,8 @@
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"
 
 
+// Require a click inside window before re-hiding mouse cursor on OSX, otherwise dragging the window
+// can be incorrectly interpreted as mouse movement inside the window
 #if defined(__APPLE__) && !defined(IOS)
 #if defined(__APPLE__) && !defined(IOS)
     #define REQUIRE_CLICK_TO_FOCUS
     #define REQUIRE_CLICK_TO_FOCUS
 #endif
 #endif
@@ -124,11 +126,13 @@ void Input::Update()
     }
     }
     
     
     // Check for SDL events
     // Check for SDL events
+    SDL_PumpEvents();
+    
     {
     {
         MutexLock lock(GetStaticMutex());
         MutexLock lock(GetStaticMutex());
         
         
         SDL_Event evt;
         SDL_Event evt;
-        while (SDL_PollEvent(&evt))
+        while (SDL_PeepEvents(&evt, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) > 0)
         {
         {
             // If only one instance, can handle event directly. Otherwise put to the correct input instance's event queue
             // If only one instance, can handle event directly. Otherwise put to the correct input instance's event queue
             if (inputInstances.Size() > 1)
             if (inputInstances.Size() > 1)
@@ -170,6 +174,10 @@ void Input::Update()
                     case SDL_WINDOWEVENT:
                     case SDL_WINDOWEVENT:
                         storeEvent = evt.window.windowID == (*i)->windowID_;
                         storeEvent = evt.window.windowID == (*i)->windowID_;
                         break;
                         break;
+                        
+                    case SDL_QUIT:
+                        storeEvent = true;
+                        break;
                     }
                     }
                     
                     
                     if (storeEvent)
                     if (storeEvent)
@@ -587,8 +595,6 @@ void Input::SendInputFocusEvent()
 void Input::SetMouseButton(int button, bool newState)
 void Input::SetMouseButton(int button, bool newState)
 {
 {
 #ifdef REQUIRE_CLICK_TO_FOCUS
 #ifdef REQUIRE_CLICK_TO_FOCUS
-    // OSX only: after losing focus in windowed hidden mouse mode, regain focus only after a left-click inside the window.
-    // This allows glitchfree window dragging
     if (!mouseVisible_ && !graphics_->GetFullscreen())
     if (!mouseVisible_ && !graphics_->GetFullscreen())
     {
     {
         if (!inputFocus_ && newState && button == MOUSEB_LEFT)
         if (!inputFocus_ && newState && button == MOUSEB_LEFT)
@@ -875,7 +881,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
             switch (evt.window.event)
             switch (evt.window.event)
             {
             {
             case SDL_WINDOWEVENT_CLOSE:
             case SDL_WINDOWEVENT_CLOSE:
-                graphics_->Close();
+                SendEvent(E_EXITREQUESTED);
                 break;
                 break;
                 
                 
             case SDL_WINDOWEVENT_MINIMIZED:
             case SDL_WINDOWEVENT_MINIMIZED:
@@ -914,6 +920,10 @@ void Input::HandleSDLEvent(void* sdlEvent)
             }
             }
         }
         }
         break;
         break;
+        
+    case SDL_QUIT:
+        SendEvent(E_EXITREQUESTED);
+        break;
     }
     }
 }
 }
 
 

+ 5 - 0
Engine/Input/InputEvents.h

@@ -155,6 +155,11 @@ EVENT(E_INPUTFOCUS, InputFocus)
     PARAM(P_MINIMIZED, Minimized);          // bool
     PARAM(P_MINIMIZED, Minimized);          // bool
 }
 }
 
 
+/// Application exit requested.
+EVENT(E_EXITREQUESTED, ExitRequested)
+{
+}
+
 static const int MOUSEB_LEFT = 1;
 static const int MOUSEB_LEFT = 1;
 static const int MOUSEB_MIDDLE = 2;
 static const int MOUSEB_MIDDLE = 2;
 static const int MOUSEB_RIGHT = 4;
 static const int MOUSEB_RIGHT = 4;

+ 2 - 0
Engine/Script/EngineAPI.cpp

@@ -113,6 +113,8 @@ static void RegisterEngine(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Engine", "int get_maxInactiveFps() const", asMETHOD(Engine, GetMaxInactiveFps), asCALL_THISCALL);
     engine->RegisterObjectMethod("Engine", "int get_maxInactiveFps() const", asMETHOD(Engine, GetMaxInactiveFps), asCALL_THISCALL);
     engine->RegisterObjectMethod("Engine", "void set_pauseMinimized(bool)", asMETHOD(Engine, SetPauseMinimized), asCALL_THISCALL);
     engine->RegisterObjectMethod("Engine", "void set_pauseMinimized(bool)", asMETHOD(Engine, SetPauseMinimized), asCALL_THISCALL);
     engine->RegisterObjectMethod("Engine", "bool get_pauseMinimized() const", asMETHOD(Engine, GetPauseMinimized), asCALL_THISCALL);
     engine->RegisterObjectMethod("Engine", "bool get_pauseMinimized() const", asMETHOD(Engine, GetPauseMinimized), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Engine", "void set_autoExit(bool)", asMETHOD(Engine, SetAutoExit), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Engine", "bool get_autoExit() const", asMETHOD(Engine, GetAutoExit), asCALL_THISCALL);
     engine->RegisterObjectMethod("Engine", "bool get_initialized() const", asMETHOD(Engine, IsInitialized), asCALL_THISCALL);
     engine->RegisterObjectMethod("Engine", "bool get_initialized() const", asMETHOD(Engine, IsInitialized), asCALL_THISCALL);
     engine->RegisterObjectMethod("Engine", "bool get_exiting() const", asMETHOD(Engine, IsExiting), asCALL_THISCALL);
     engine->RegisterObjectMethod("Engine", "bool get_exiting() const", asMETHOD(Engine, IsExiting), asCALL_THISCALL);
     engine->RegisterObjectMethod("Engine", "bool get_headless() const", asMETHOD(Engine, IsHeadless), asCALL_THISCALL);
     engine->RegisterObjectMethod("Engine", "bool get_headless() const", asMETHOD(Engine, IsHeadless), asCALL_THISCALL);