Browse Source

Updated mouse suppression and relative code.

hdunderscore 9 years ago
parent
commit
97a94f9022
3 changed files with 219 additions and 129 deletions
  1. 198 125
      Source/Urho3D/Input/Input.cpp
  2. 20 3
      Source/Urho3D/Input/Input.h
  3. 1 1
      Source/Urho3D/Input/InputEvents.h

+ 198 - 125
Source/Urho3D/Input/Input.cpp

@@ -161,7 +161,7 @@ void EmscriptenInput::RequestPointerLock(MouseMode mode, bool suppressEvent)
 {
     requestedMouseMode_ = mode;
     suppressMouseModeEvent_ = suppressEvent;
-    emscripten_request_pointerlock(NULL, false);
+    emscripten_request_pointerlock(NULL, true);
 }
 
 void EmscriptenInput::ExitPointerLock(bool suppressEvent)
@@ -212,7 +212,7 @@ EM_BOOL EmscriptenInput::HandlePointerLockChange(int eventType, const Emscripten
         // Pointer Lock is now active
         inputInst->emscriptenPointerLock_ = true;
         inputInst->emscriptenEnteredPointerLock_ = true;
-        inputInst->SetMouseModeEmscripten(requestedMouseMode_, suppressMouseModeEvent_);
+        inputInst->SetMouseModeEmscriptenFinal(requestedMouseMode_, suppressMouseModeEvent_);
     }
     else
     {
@@ -220,9 +220,9 @@ EM_BOOL EmscriptenInput::HandlePointerLockChange(int eventType, const Emscripten
         inputInst->emscriptenPointerLock_ = false;
 
         if (inputInst->mouseMode_ == MM_RELATIVE)
-            inputInst->SetMouseModeEmscripten(MM_FREE, suppressMouseModeEvent_);
+            inputInst->SetMouseModeEmscriptenFinal(MM_FREE, suppressMouseModeEvent_);
         else if (inputInst->mouseMode_ == MM_ABSOLUTE)
-            inputInst->SetMouseModeEmscripten(MM_ABSOLUTE, suppressMouseModeEvent_);
+            inputInst->SetMouseModeEmscriptenFinal(MM_ABSOLUTE, suppressMouseModeEvent_);
 
         inputInst->emscriptenExitingPointerLock_ = false;
     }
@@ -252,7 +252,7 @@ EM_BOOL EmscriptenInput::HandleFocusChange(int eventType, const EmscriptenFocusE
 {
     Input* const inputInst = (Input*)userData;
 
-    inputInst->suppressNextMouseMove_ = true;
+    inputInst->SuppressNextMouseMove();
 
     if (eventType == EMSCRIPTEN_EVENT_FOCUSOUT)
         inputInst->LoseFocus();
@@ -278,7 +278,7 @@ EM_BOOL EmscriptenInput::HandleMouseJump(int eventType, const EmscriptenMouseEve
     }
 
     if (suppress)
-        inputInst->suppressNextMouseMove_ = true;
+        inputInst->SuppressNextMouseMove();
 
     return EM_FALSE;
 }
@@ -331,7 +331,9 @@ Input::Input(Context* context) :
     lastMouseGrabbed_(false),
     mouseMode_(MM_ABSOLUTE),
     lastMouseMode_(MM_ABSOLUTE),
-#ifdef __EMSCRIPTEN__
+#ifndef __EMSCRIPTEN__
+    sdlMouseRelative_(false),
+#else
     emscriptenPointerLock_(false),
     emscriptenEnteredPointerLock_(false),
     emscriptenExitingPointerLock_(false),
@@ -375,11 +377,18 @@ void Input::Update()
     URHO3D_PROFILE(UpdateInput);
 
 #ifndef __EMSCRIPTEN__
+    bool mouseMoved = false;
+    if (mouseMove_ != IntVector2::ZERO)
+        mouseMoved = true;
+
     ResetInputAccumulation();
 
     SDL_Event evt;
     while (SDL_PollEvent(&evt))
         HandleSDLEvent(&evt);
+
+    if (suppressNextMouseMove_ && (mouseMove_ != IntVector2::ZERO || mouseMoved))
+        UnsuppressMouseMove();
 #endif
 
     // Check for focus change this frame
@@ -412,8 +421,10 @@ void Input::Update()
     // Handle mouse mode MM_WRAP
     if (mouseVisible_ && mouseMode_ == MM_WRAP)
     {
+        IntVector2 windowPos = graphics_->GetWindowPosition();
         IntVector2 mpos;
-        SDL_GetMouseState(&mpos.x_, &mpos.y_);
+        SDL_GetGlobalMouseState(&mpos.x_, &mpos.y_);
+        mpos -= windowPos;
 
         const int buffer = 5;
         const int width = graphics_->GetWidth() - buffer * 2;
@@ -447,7 +458,7 @@ void Input::Update()
         if (warp)
         {
             SetMousePosition(mpos);
-            SDL_FlushEvent(SDL_MOUSEMOTION);
+            SuppressNextMouseMove();
         }
     }
 #else
@@ -455,10 +466,8 @@ void Input::Update()
         return;
 #endif
 
-    // Check for relative mode mouse move
-    // Note that Emscripten will use SDL mouse move events for relative mode instead
 #ifndef __EMSCRIPTEN__
-    if (!touchEmulation_ && (graphics_->GetExternalWindow() || ((!mouseVisible_ && mouseMode_ != MM_FREE) && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS))))
+    if (!touchEmulation_ && (graphics_->GetExternalWindow() || ((!sdlMouseRelative_ && !mouseVisible_ && mouseMode_ != MM_FREE) && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS))))
 #else
     if (!touchEmulation_ && !emscriptenPointerLock_ && (graphics_->GetExternalWindow() || (!mouseVisible_ && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS))))
 #endif
@@ -472,19 +481,14 @@ void Input::Update()
         else
         {
             // Recenter the mouse cursor manually after move
-            const IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
-            if (mousePosition != center)
-            {
-                SetMousePosition(center);
-                lastMousePosition_ = center;
-            }
+            CenterMousePosition();
         }
 #else
         if (mouseMode_ == MM_ABSOLUTE || mouseMode_ == MM_FREE)
             lastMousePosition_ = mousePosition;
 
         if (emscriptenExitingPointerLock_)
-            suppressNextMouseMove_ = true;
+            SuppressNextMouseMove();
 #endif
         // Send mouse move event if necessary
         if (mouseMove_ != IntVector2::ZERO)
@@ -505,14 +509,11 @@ void Input::Update()
             }
         }
     }
-
 #ifndef __EMSCRIPTEN__
-    // Suppress all mouse movement this tick
-    if (suppressNextMouseMove_ && mouseMove_ != IntVector2::ZERO)
+    else if (!touchEmulation_ && !mouseVisible_ && sdlMouseRelative_ && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS))
     {
-        lastMousePosition_ = GetMousePosition();
-        mouseMove_ = IntVector2::ZERO;
-        suppressNextMouseMove_ = false;
+        // Keep the cursor trapped in window.
+        CenterMousePosition();
     }
 #endif
 }
@@ -530,6 +531,7 @@ void Input::SetMouseVisible(bool enable, bool suppressEvent)
     {
         if (!suppressEvent)
             lastMouseVisible_ = enable;
+
         enable = false;
     }
 
@@ -537,8 +539,6 @@ void Input::SetMouseVisible(bool enable, bool suppressEvent)
 #ifndef RPI
     if (enable != mouseVisible_)
     {
-        mouseVisible_ = enable;
-
         if (initialized_)
         {
             // External windows can only support visible mouse cursor
@@ -550,71 +550,72 @@ void Input::SetMouseVisible(bool enable, bool suppressEvent)
                 return;
             }
 
-            if (!mouseVisible_ && inputFocus_)
+            if (!enable && inputFocus_)
             {
 #ifndef __EMSCRIPTEN__
-                lastVisibleMousePosition_ = GetMousePosition();
-                if (mouseMode_ != MM_FREE)
-                {
-                    // Recenter the mouse cursor manually when hiding it to avoid erratic mouse move for one frame
-                    IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
-                    SetMousePosition(center);
-                    lastMousePosition_ = center;
-                }
+                if (mouseVisible_)
+                    lastVisibleMousePosition_ = GetMousePosition();
+
+                if (mouseMode_ == MM_ABSOLUTE)
+                    SetMouseModeAbsolute(SDL_TRUE);
 #else
                 if (mouseMode_ == MM_ABSOLUTE && !emscriptenPointerLock_)
-                {
-                    UI* ui = GetSubsystem<UI>();
-                    Cursor* cursor = ui->GetCursor();
-                    if (!cursor)
-                    {
-                        mouseVisible_ = true;
-                        SDL_ShowCursor(SDL_TRUE);
-                    }
-
-                    emscriptenInput_->RequestPointerLock(MM_ABSOLUTE, suppressEvent);
-                }
+                    emscriptenInput_->RequestPointerLock(MM_ABSOLUTE, suppressEvent);      
 #endif
-                if (mouseVisible_ == enable)
-                    SDL_ShowCursor(SDL_FALSE);
+                SDL_ShowCursor(SDL_FALSE);
+                mouseVisible_ = false;
             }
-            else
+            else if (mouseMode_ != MM_RELATIVE)
             {
-                SDL_ShowCursor(SDL_TRUE);
                 SetMouseGrabbed(false, suppressEvent);
+                
+                SDL_ShowCursor(SDL_TRUE);
+                mouseVisible_ = true;
+
 #ifndef __EMSCRIPTEN__
+                if (mouseMode_ == MM_ABSOLUTE)
+                    SetMouseModeAbsolute(SDL_FALSE);
+
+                // Update cursor position
                 UI* ui = GetSubsystem<UI>();
                 Cursor* cursor = ui->GetCursor();
                 // If the UI Cursor was visible, use that position instead of last visible OS cursor position
                 if (cursor && cursor->IsVisible())
                 {
                     IntVector2 pos = cursor->GetScreenPosition();
-                    if (pos.x_ != MOUSE_POSITION_OFFSCREEN.x_ &&
-                        pos.y_ != MOUSE_POSITION_OFFSCREEN.y_)
+                    if (pos != MOUSE_POSITION_OFFSCREEN)
+                    {
                         SetMousePosition(pos);
-                    lastMousePosition_ = pos;
+                        lastMousePosition_ = pos;
+                    }
                 }
                 else
                 {
-                    if (lastVisibleMousePosition_.x_ != MOUSE_POSITION_OFFSCREEN.x_ &&
-                        lastVisibleMousePosition_.y_ != MOUSE_POSITION_OFFSCREEN.y_)
+                    if (lastVisibleMousePosition_ != MOUSE_POSITION_OFFSCREEN)
+                    {
                         SetMousePosition(lastVisibleMousePosition_);
-                    lastMousePosition_ = lastVisibleMousePosition_;
+                        lastMousePosition_ = lastVisibleMousePosition_;
+                    } 
                 }
 #else
-                emscriptenInput_->ExitPointerLock(suppressEvent);
+                if (mouseMode_ == MM_ABSOLUTE && emscriptenPointerLock_)
+                    emscriptenInput_->ExitPointerLock(suppressEvent);
 #endif
             }
         }
 
-        if (!suppressEvent && mouseVisible_ != startMouseVisible)
+        if (mouseVisible_ != startMouseVisible)
         {
-            lastMouseVisible_ = mouseVisible_;
-            using namespace MouseVisibleChanged;
+            SuppressNextMouseMove();
+            if (!suppressEvent)
+            {
+                lastMouseVisible_ = mouseVisible_;
+                using namespace MouseVisibleChanged;
 
-            VariantMap& eventData = GetEventDataMap();
-            eventData[P_VISIBLE] = mouseVisible_;
-            SendEvent(E_MOUSEVISIBLECHANGED, eventData);
+                VariantMap& eventData = GetEventDataMap();
+                eventData[P_VISIBLE] = mouseVisible_;
+                SendEvent(E_MOUSEVISIBLECHANGED, eventData);
+            }
         }
     }
 #endif
@@ -664,7 +665,7 @@ void Input::SetMouseVisibleEmscripten(bool enable, bool suppressEvent)
         lastMouseVisible_ = mouseVisible_;
 }
 
-void Input::SetMouseModeEmscripten(MouseMode mode, bool suppressEvent)
+void Input::SetMouseModeEmscriptenFinal(MouseMode mode, bool suppressEvent)
 {
     if (!suppressEvent)
         lastMouseMode_ = mode;
@@ -675,14 +676,16 @@ void Input::SetMouseModeEmscripten(MouseMode mode, bool suppressEvent)
     {
         if (emscriptenPointerLock_)
         {
-            SetMouseGrabbed(true, suppressEvent);
             SetMouseVisibleEmscripten(false, suppressEvent);
         }
         else
         {
-            SetMouseGrabbed(false, suppressEvent);
             SetMouseVisibleEmscripten(true, suppressEvent);
         }
+
+        UI* const ui = GetSubsystem<UI>();
+        Cursor* const cursor = ui->GetCursor();
+        SetMouseGrabbed(!(mouseVisible_ || (cursor && cursor->IsVisible())), suppressEvent);
     }
     else if (mode == MM_RELATIVE && emscriptenPointerLock_)
     {
@@ -693,39 +696,25 @@ void Input::SetMouseModeEmscripten(MouseMode mode, bool suppressEvent)
     {
         SetMouseGrabbed(false, suppressEvent);
     }
-    suppressNextMouseMove_ = true;
+
+    SuppressNextMouseMove();
 
     if (!suppressEvent)
     {
         VariantMap& eventData = GetEventDataMap();
         eventData[MouseModeChanged::P_MODE] = mode;
-        eventData[MouseModeChanged::P_MOUSELOCK] = IsMouseLocked();
+        eventData[MouseModeChanged::P_MOUSELOCKED] = IsMouseLocked();
         SendEvent(E_MOUSEMODECHANGED, eventData);
     }
 }
-#endif
 
-void Input::SetMouseGrabbed(bool grab, bool suppressEvent)
-{
-    mouseGrabbed_ = grab;
-
-    if (!suppressEvent)
-        lastMouseGrabbed_ = grab;
-}
-
-void Input::ResetMouseGrabbed()
-{
-    mouseGrabbed_ = lastMouseGrabbed_;
-}
-
-void Input::SetMouseMode(MouseMode mode, bool suppressEvent)
+void Input::SetMouseModeEmscripten(MouseMode mode, bool suppressEvent)
 {
     if (mode != mouseMode_)
-        suppressNextMouseMove_ = true;
+        SuppressNextMouseMove();
 
     const MouseMode previousMode = mouseMode_;
     mouseMode_ = mode;
-    SDL_Window* const window = graphics_->GetImpl()->GetWindow();
 
     UI* const ui = GetSubsystem<UI>();
     Cursor* const cursor = ui->GetCursor();
@@ -737,26 +726,17 @@ void Input::SetMouseMode(MouseMode mode, bool suppressEvent)
     // Handle changing to new mode
     if (mode == MM_FREE)
     {
-        SetMouseGrabbed(!(mouseVisible_ || (cursor && cursor->IsVisible())), suppressEvent);
-#ifndef __EMSCRIPTEN__
-        SDL_SetWindowGrab(window, SDL_FALSE);
-#else
         // Attempt to cancel pending pointer-lock requests
         emscriptenInput_->ExitPointerLock(suppressEvent);
-#endif
+        SetMouseGrabbed(!(mouseVisible_ || (cursor && cursor->IsVisible())), suppressEvent);
     }
     else if (mode == MM_ABSOLUTE)
     {
-#ifndef __EMSCRIPTEN__
-        SetMouseGrabbed(!(mouseVisible_ || (cursor && cursor->IsVisible())), suppressEvent);
-        SDL_SetWindowGrab(window, SDL_FALSE);
-#else
         if (!mouseVisible_)
         {
             if (emscriptenPointerLock_)
             {
                 SetMouseVisibleEmscripten(false, suppressEvent);
-                SetMouseGrabbed(true, suppressEvent);
             }
             else
             {
@@ -766,35 +746,112 @@ void Input::SetMouseMode(MouseMode mode, bool suppressEvent)
                 mouseMode_ = previousMode;
                 emscriptenInput_->RequestPointerLock(MM_ABSOLUTE, suppressEvent);
             }
+
+            SetMouseGrabbed(!(mouseVisible_ || (cursor && cursor->IsVisible())), suppressEvent);
         }
-#endif
     }
     else if (mode == MM_RELATIVE)
     {
-#ifndef __EMSCRIPTEN__
-        SDL_SetWindowGrab(window, SDL_TRUE);
-        SetMouseGrabbed(true, suppressEvent);
-        SetMouseVisible(false, true);
-#else
         if (emscriptenPointerLock_)
         {
-            SetMouseGrabbed(true, suppressEvent);
             SetMouseVisibleEmscripten(false, true);
+            SetMouseGrabbed(!(cursor && cursor->IsVisible()), suppressEvent);
         }
         else
         {
             // Defer mouse mode change to pointer-lock callback
+            SetMouseGrabbed(false, true);
             mouseMode_ = previousMode;
             emscriptenInput_->RequestPointerLock(MM_RELATIVE, suppressEvent);
         }
-#endif
     }
+}
+#endif
+
+void Input::SetMouseGrabbed(bool grab, bool suppressEvent)
+{
+    mouseGrabbed_ = grab;
+
+    if (!suppressEvent)
+        lastMouseGrabbed_ = grab;
+}
+
+void Input::ResetMouseGrabbed()
+{
+    SetMouseGrabbed(lastMouseGrabbed_, true);
+}
+
+
 #ifndef __EMSCRIPTEN__
-    else if (mode == MM_WRAP)
+void Input::SetMouseModeAbsolute(SDL_bool enable)
+{
+    SDL_Window* const window = graphics_->GetImpl()->GetWindow();
+
+    SDL_SetWindowGrab(window, enable);
+}
+
+void Input::SetMouseModeRelative(SDL_bool enable)
+{
+    SDL_Window* const window = graphics_->GetImpl()->GetWindow();
+
+    int result = SDL_SetRelativeMouseMode(enable);
+    sdlMouseRelative_ = enable && (result == 0);
+
+    if (result == -1)
+        SDL_SetWindowGrab(window, enable);
+}
+#endif
+
+void Input::SetMouseMode(MouseMode mode, bool suppressEvent)
+{
+    const MouseMode previousMode = mouseMode_;
+
+#ifdef __EMSCRIPTEN__
+    SetMouseModeEmscripten(mode, suppressEvent);
+#else
+    if (mode != mouseMode_)
     {
-        SetMouseGrabbed(true, suppressEvent);
-        /// \todo When SDL 2.0.4 is integrated, use SDL_CaptureMouse() and global mouse functions for MM_WRAP mode.
-        SDL_SetWindowGrab(window, SDL_TRUE);
+        SuppressNextMouseMove();
+
+        mouseMode_ = mode;
+        SDL_Window* const window = graphics_->GetImpl()->GetWindow();
+
+        UI* const ui = GetSubsystem<UI>();
+        Cursor* const cursor = ui->GetCursor();
+
+        // Handle changing from previous mode
+        if (previousMode == MM_ABSOLUTE)
+        {
+            if (!mouseVisible_)
+                SetMouseModeAbsolute(SDL_FALSE);
+        }
+        if (previousMode == MM_RELATIVE)
+        {
+            SetMouseModeRelative(SDL_FALSE);
+            ResetMouseVisible();
+        }
+        else if (previousMode == MM_WRAP)
+            SDL_SetWindowGrab(window, SDL_FALSE);
+
+        // Handle changing to new mode
+        if (mode == MM_ABSOLUTE)
+        {
+            if (!mouseVisible_)
+                SetMouseModeAbsolute(SDL_TRUE);
+        }
+        else if (mode == MM_RELATIVE)
+        {
+            SetMouseVisible(false, true);
+            SetMouseModeRelative(SDL_TRUE);
+        }
+        else if (mode == MM_WRAP)
+        {
+            SetMouseGrabbed(true, suppressEvent);
+            SDL_SetWindowGrab(window, SDL_TRUE);
+        }
+
+        if (mode != MM_WRAP)
+            SetMouseGrabbed(!(mouseVisible_ || (cursor && cursor->IsVisible())), suppressEvent);
     }
 #endif
 
@@ -806,7 +863,7 @@ void Input::SetMouseMode(MouseMode mode, bool suppressEvent)
         {
             VariantMap& eventData = GetEventDataMap();
             eventData[MouseModeChanged::P_MODE] = mode;
-            eventData[MouseModeChanged::P_MOUSELOCK] = IsMouseLocked();
+            eventData[MouseModeChanged::P_MOUSELOCKED] = IsMouseLocked();
             SendEvent(E_MOUSEMODECHANGED, eventData);
         }
     }
@@ -1386,7 +1443,7 @@ bool Input::IsMouseLocked() const
 #ifdef __EMSCRIPTEN__
     return emscriptenPointerLock_;
 #else
-    return mouseMode_ == MM_RELATIVE || (mouseMode_ == MM_ABSOLUTE && !mouseVisible_);
+    return !((mouseMode_ == MM_ABSOLUTE && mouseVisible_) || mouseMode_ == MM_FREE);
 #endif
 }
 
@@ -1430,6 +1487,7 @@ void Input::Initialize()
 #ifdef __EMSCRIPTEN__
     SubscribeToEvent(E_ENDFRAME, URHO3D_HANDLER(Input, HandleEndFrame));
 #endif
+    
     URHO3D_LOGINFO("Initialized input");
 }
 
@@ -1480,7 +1538,7 @@ void Input::GainFocus()
     SetMouseMode(mm, true);
 #endif
 
-    suppressNextMouseMove_ = true;
+    SuppressNextMouseMove();
 
     // Re-establish mouse cursor hiding as necessary
     if (!mouseVisible_)
@@ -1713,6 +1771,29 @@ void Input::SetMousePosition(const IntVector2& position)
     SDL_WarpMouseInWindow(graphics_->GetImpl()->GetWindow(), position.x_, position.y_);
 }
 
+void Input::CenterMousePosition()
+{
+    const IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
+    if (GetMousePosition() != center)
+    {
+        SetMousePosition(center);
+        lastMousePosition_ = center;
+    }
+}
+
+void Input::SuppressNextMouseMove()
+{
+    suppressNextMouseMove_ = true;
+    mouseMove_ = IntVector2::ZERO;
+}
+
+void Input::UnsuppressMouseMove()
+{
+    suppressNextMouseMove_ = false;
+    mouseMove_ = IntVector2::ZERO;
+    lastMousePosition_ = GetMousePosition();
+}
+
 void Input::HandleSDLEvent(void* sdlEvent)
 {
     SDL_Event& evt = *static_cast<SDL_Event*>(sdlEvent);
@@ -1820,10 +1901,8 @@ void Input::HandleSDLEvent(void* sdlEvent)
         break;
 
     case SDL_MOUSEMOTION:
-        // Emscripten will use SDL mouse move events for relative mode, as repositioning the mouse and
-        // measuring distance from window center is not supported
 #ifndef __EMSCRIPTEN__
-        if ((mouseVisible_ || mouseMode_ == MM_FREE) && !touchEmulation_)
+        if ((sdlMouseRelative_ || mouseVisible_ || mouseMode_ == MM_FREE) && !touchEmulation_)
 #else
         if ((mouseVisible_ || emscriptenPointerLock_ || mouseMode_ == MM_FREE) && !touchEmulation_)
 #endif
@@ -1831,7 +1910,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
 #ifdef __EMSCRIPTEN__
             if (emscriptenExitingPointerLock_)
             {
-                suppressNextMouseMove_ = true;
+                SuppressNextMouseMove();
                 break;
             }
 #endif
@@ -1898,7 +1977,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
 
             // Finger touch may move the mouse cursor. Suppress next mouse move when cursor hidden to prevent jumps
             if (!mouseVisible_)
-                suppressNextMouseMove_ = true;
+                SuppressNextMouseMove();
         }
         break;
 
@@ -1951,7 +2030,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
 
             // Finger touch may move the mouse cursor. Suppress next mouse move when cursor hidden to prevent jumps
             if (!mouseVisible_)
-                suppressNextMouseMove_ = true;
+                SuppressNextMouseMove();
         }
         break;
 
@@ -2240,9 +2319,7 @@ void Input::HandleScreenMode(StringHash eventType, VariantMap& eventData)
     // If screen mode happens due to mouse drag resize, do not recenter the mouse as that would lead to erratic window sizes
     if (!mouseVisible_ && mouseMode_ != MM_FREE && !inResize_)
     {
-        IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
-        SetMousePosition(center);
-        lastMousePosition_ = center;
+        CenterMousePosition();
         focusedThisFrame_ = true;
     }
     else
@@ -2277,11 +2354,7 @@ void Input::HandleBeginFrame(StringHash eventType, VariantMap& eventData)
 void Input::HandleEndFrame(StringHash eventType, VariantMap& eventData)
 {
     if (suppressNextMouseMove_ && mouseMove_ != IntVector2::ZERO)
-    {
-        mouseMove_ = IntVector2::ZERO;
-        lastMousePosition_ = GetMousePosition();
-        suppressNextMouseMove_ = false;
-    }
+        UnsuppressMouseMove();
 
     ResetInputAccumulation();
 }

+ 20 - 3
Source/Urho3D/Input/Input.h

@@ -328,6 +328,12 @@ private:
     void SetMouseWheel(int delta);
     /// Internal function to set the mouse cursor position.
     void SetMousePosition(const IntVector2& position);
+    /// Center the mouse position.
+    void CenterMousePosition();
+    /// Suppress next mouse movement.
+    void SuppressNextMouseMove();
+    /// Unsuppress mouse movement.
+    void UnsuppressMouseMove();
     /// Handle screen mode event.
     void HandleScreenMode(StringHash eventType, VariantMap& eventData);
     /// Handle frame start event.
@@ -337,11 +343,18 @@ private:
     /// Handle SDL event.
     void HandleSDLEvent(void* sdlEvent);
 
-#ifdef __EMSCRIPTEN__
+#ifndef __EMSCRIPTEN__
+    /// Set SDL mouse mode relative.
+    void SetMouseModeRelative(SDL_bool enable);
+    /// Set SDL mouse mode absolute.
+    void SetMouseModeAbsolute(SDL_bool enable);
+#else
     /// Set whether the operating system mouse cursor is visible (Emscripten platform only).
     void SetMouseVisibleEmscripten(bool enable, bool suppressEvent = false);
-    /// Set mouse mode (Emscripten platform only).
-    void SetMouseModeEmscripten(MouseMode mode, bool suppressEvent = false);
+    /// Set mouse mode final resolution (Emscripten platform only).
+    void SetMouseModeEmscriptenFinal(MouseMode mode, bool suppressEvent = false);
+    /// SetMouseMode  (Emscripten platform only).
+    void SetMouseModeEmscripten(MouseMode mode, bool suppressEvent);
     /// Handle frame end event.
     void HandleEndFrame(StringHash eventType, VariantMap& eventData);
 #endif
@@ -394,6 +407,10 @@ private:
     MouseMode mouseMode_;
     /// The last mouse mode set by SetMouseMode.
     MouseMode lastMouseMode_;
+#ifndef __EMSCRIPTEN__
+    /// Flag to determine whether SDL mouse relative was used.
+    bool sdlMouseRelative_;
+#endif
     /// Touch emulation mode flag.
     bool touchEmulation_;
     /// Input focus flag.

+ 1 - 1
Source/Urho3D/Input/InputEvents.h

@@ -213,7 +213,7 @@ URHO3D_EVENT(E_MOUSEVISIBLECHANGED, MouseVisibleChanged)
 URHO3D_EVENT(E_MOUSEMODECHANGED, MouseModeChanged)
 {
     URHO3D_PARAM(P_MODE, Mode);                    // MouseMode
-    URHO3D_PARAM(P_MOUSELOCK, PointerLock);      // bool
+    URHO3D_PARAM(P_MOUSELOCKED, MouseLocked);      // bool
 }
 
 /// Application exit requested.