Fix CursorLockMode.Locked not working
This commit is contained in:
@@ -106,25 +106,11 @@ void Screen::SetCursorVisible(const bool value)
|
|||||||
#else
|
#else
|
||||||
const auto win = Engine::MainWindow;
|
const auto win = Engine::MainWindow;
|
||||||
#endif
|
#endif
|
||||||
bool focused = false;
|
|
||||||
if (win && Engine::HasGameViewportFocus())
|
if (win && Engine::HasGameViewportFocus())
|
||||||
{
|
|
||||||
win->SetCursor(value ? CursorType::Default : CursorType::Hidden);
|
win->SetCursor(value ? CursorType::Default : CursorType::Hidden);
|
||||||
focused = true;
|
|
||||||
}
|
|
||||||
else if (win)
|
else if (win)
|
||||||
win->SetCursor(CursorType::Default);
|
win->SetCursor(CursorType::Default);
|
||||||
CursorVisible = value;
|
CursorVisible = value;
|
||||||
|
|
||||||
// Just enable relative mode when cursor is constrained and not visible
|
|
||||||
if (CursorLock != CursorLockMode::None && !CursorVisible && focused)
|
|
||||||
{
|
|
||||||
Input::Mouse->SetRelativeMode(true, win);
|
|
||||||
}
|
|
||||||
else if (CursorLock == CursorLockMode::None || CursorVisible || !focused)
|
|
||||||
{
|
|
||||||
Input::Mouse->SetRelativeMode(false, win);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CursorLockMode Screen::GetCursorLock()
|
CursorLockMode Screen::GetCursorLock()
|
||||||
@@ -136,34 +122,35 @@ void Screen::SetCursorLock(CursorLockMode mode)
|
|||||||
{
|
{
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
const auto win = Editor::Managed->GetGameWindow(true);
|
const auto win = Editor::Managed->GetGameWindow(true);
|
||||||
|
Rectangle bounds(Editor::Managed->GameViewportToScreen(Float2::Zero), Editor::Managed->GetGameWindowSize());
|
||||||
#else
|
#else
|
||||||
const auto win = Engine::MainWindow;
|
const auto win = Engine::MainWindow;
|
||||||
|
Rectangle bounds = win != nullptr ? win->GetClientBounds() : Rectangle();
|
||||||
#endif
|
#endif
|
||||||
|
bool inRelativeMode = Input::Mouse->IsRelative();
|
||||||
if (win && mode == CursorLockMode::Clipped)
|
if (win && mode == CursorLockMode::Clipped)
|
||||||
{
|
|
||||||
#if USE_EDITOR
|
|
||||||
Rectangle bounds(Editor::Managed->GameViewportToScreen(Float2::Zero), Editor::Managed->GetGameWindowSize());
|
|
||||||
#else
|
|
||||||
Rectangle bounds = win->GetClientBounds();
|
|
||||||
#endif
|
|
||||||
win->StartClippingCursor(bounds);
|
win->StartClippingCursor(bounds);
|
||||||
}
|
else if (win && mode == CursorLockMode::Locked)
|
||||||
else if (win && CursorLock == CursorLockMode::Clipped)
|
|
||||||
{
|
{
|
||||||
win->EndClippingCursor();
|
// Use mouse clip region to restrict the cursor in one spot
|
||||||
|
Rectangle centerBounds;
|
||||||
|
auto mousePosition = win->GetMousePosition();
|
||||||
|
if (bounds.Contains(mousePosition))
|
||||||
|
centerBounds = Rectangle(mousePosition, Float2(1, 1));
|
||||||
|
else
|
||||||
|
centerBounds = Rectangle(bounds.GetCenter(), Float2(1, 1));
|
||||||
|
win->StartClippingCursor(centerBounds);
|
||||||
}
|
}
|
||||||
|
else if (win && (CursorLock == CursorLockMode::Locked || CursorLock == CursorLockMode::Clipped))
|
||||||
|
win->EndClippingCursor();
|
||||||
CursorLock = mode;
|
CursorLock = mode;
|
||||||
|
|
||||||
// Just enable relative mode when cursor is constrained and not visible
|
// Enable relative mode when cursor is restricted
|
||||||
bool focused = win && Engine::HasGameViewportFocus();
|
bool focused = win && Engine::HasGameViewportFocus();
|
||||||
if (CursorLock != CursorLockMode::None && !CursorVisible && focused)
|
if (CursorLock != CursorLockMode::None)
|
||||||
{
|
|
||||||
Input::Mouse->SetRelativeMode(true, win);
|
Input::Mouse->SetRelativeMode(true, win);
|
||||||
}
|
else if (CursorLock == CursorLockMode::None && inRelativeMode)
|
||||||
else if (CursorLock == CursorLockMode::None || CursorVisible || !focused)
|
|
||||||
{
|
|
||||||
Input::Mouse->SetRelativeMode(false, win);
|
Input::Mouse->SetRelativeMode(false, win);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GameWindowMode Screen::GetGameWindowMode()
|
GameWindowMode Screen::GetGameWindowMode()
|
||||||
|
|||||||
@@ -357,9 +357,9 @@ public:
|
|||||||
class SDLMouse : public Mouse
|
class SDLMouse : public Mouse
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Float2 oldPosition = Float2::Zero;
|
Float2 _oldPosition = Float2::Zero;
|
||||||
Window* relativeModeWindow = nullptr;
|
Window* _relativeModeWindow = nullptr;
|
||||||
const SDL_Rect* oldScreenRect = nullptr;
|
const SDL_Rect* _oldScreenRect = nullptr;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -377,8 +377,8 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Float2 GetOldMousePosition() const
|
Float2 GetOldMousePosition() const
|
||||||
{
|
{
|
||||||
ASSERT(relativeModeWindow != nullptr);
|
ASSERT(_relativeModeWindow != nullptr);
|
||||||
return relativeModeWindow->ClientToScreen(oldPosition);
|
return _relativeModeWindow->ClientToScreen(_oldPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
// [Mouse]
|
// [Mouse]
|
||||||
@@ -405,27 +405,27 @@ public:
|
|||||||
auto windowHandle = static_cast<SDLWindow*>(window)->_window;
|
auto windowHandle = static_cast<SDLWindow*>(window)->_window;
|
||||||
if (relativeMode)
|
if (relativeMode)
|
||||||
{
|
{
|
||||||
relativeModeWindow = window;
|
_relativeModeWindow = window;
|
||||||
SDL_GetMouseState(&oldPosition.X, &oldPosition.Y);
|
SDL_GetMouseState(&_oldPosition.X, &_oldPosition.Y);
|
||||||
if (!SDL_CursorVisible())
|
if (!SDL_CursorVisible())
|
||||||
{
|
{
|
||||||
// Trap the cursor in current location
|
// Trap the cursor in current location
|
||||||
SDL_Rect clipRect = { (int)oldPosition.X, (int)oldPosition.Y, 1, 1 };
|
SDL_Rect clipRect = { (int)_oldPosition.X, (int)_oldPosition.Y, 1, 1 };
|
||||||
oldScreenRect = SDL_GetWindowMouseRect(windowHandle);
|
_oldScreenRect = SDL_GetWindowMouseRect(windowHandle);
|
||||||
SDL_SetWindowMouseRect(windowHandle, &clipRect);
|
SDL_SetWindowMouseRect(windowHandle, &clipRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (relativeModeWindow != window)
|
if (_relativeModeWindow != window)
|
||||||
{
|
{
|
||||||
// FIXME: When floating game window is focused and editor viewport activated, the relative mode gets stuck
|
// FIXME: When floating game window is focused and editor viewport activated, the relative mode gets stuck
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SDL_SetWindowMouseRect(windowHandle, nullptr);//oldScreenRect);
|
SDL_SetWindowMouseRect(windowHandle, nullptr);//oldScreenRect);
|
||||||
SDL_WarpMouseInWindow(windowHandle, oldPosition.X, oldPosition.Y);
|
SDL_WarpMouseInWindow(windowHandle, _oldPosition.X, _oldPosition.Y);
|
||||||
oldScreenRect = nullptr;
|
_oldScreenRect = nullptr;
|
||||||
relativeModeWindow = nullptr;
|
_relativeModeWindow = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mouse::SetRelativeMode(relativeMode, window);
|
Mouse::SetRelativeMode(relativeMode, window);
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ bool SDLPlatform::Init()
|
|||||||
|
|
||||||
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, "0");
|
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, "0");
|
||||||
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, "1"); // Needed for tracking mode
|
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, "1"); // Needed for tracking mode
|
||||||
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, "0"); //
|
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, "0"); // Relative mode can be active when cursor is shown and clipped
|
||||||
SDL_SetHint(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS, "8"); // Reduce the default mouse double-click radius
|
SDL_SetHint(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS, "8"); // Reduce the default mouse double-click radius
|
||||||
|
|
||||||
//SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); // Disables raw mouse input
|
//SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); // Disables raw mouse input
|
||||||
@@ -118,6 +118,7 @@ bool SDLPlatform::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDLInput::Init();
|
SDLInput::Init();
|
||||||
|
SDLWindow::Init();
|
||||||
|
|
||||||
SystemDpi = (int)(SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()) * DefaultDPI);
|
SystemDpi = (int)(SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()) * DefaultDPI);
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ void* GetNativeWindowPointer(SDL_Window* window)
|
|||||||
return windowPtr;
|
return windowPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDLWindow::Init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
SDLWindow::SDLWindow(const CreateWindowSettings& settings)
|
SDLWindow::SDLWindow(const CreateWindowSettings& settings)
|
||||||
: WindowBase(settings)
|
: WindowBase(settings)
|
||||||
, _handle(nullptr)
|
, _handle(nullptr)
|
||||||
@@ -420,26 +424,29 @@ void SDLWindow::HandleEvent(SDL_Event& event)
|
|||||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||||
{
|
{
|
||||||
OnGotFocus();
|
OnGotFocus();
|
||||||
if (IsPopupWindow(_settings.Type))
|
|
||||||
_window = _window;
|
|
||||||
if (_settings.AllowInput && !SDLPlatform::UsesX11())
|
if (_settings.AllowInput && !SDLPlatform::UsesX11())
|
||||||
SDL_StartTextInput(_window);
|
SDL_StartTextInput(_window);
|
||||||
const SDL_Rect* currentClippingRect = SDL_GetWindowMouseRect(_window);
|
if (_isClippingCursor)
|
||||||
if (_isClippingCursor && currentClippingRect == nullptr)
|
|
||||||
{
|
{
|
||||||
|
// The relative mode needs to be disabled for clipping to take effect
|
||||||
|
bool inRelativeMode = Input::Mouse->IsRelative(this) || _restoreRelativeMode;
|
||||||
|
if (inRelativeMode)
|
||||||
|
Input::Mouse->SetRelativeMode(false, this);
|
||||||
|
|
||||||
|
// Restore previous clipping region
|
||||||
SDL_Rect rect{ (int)_clipCursorRect.GetX(), (int)_clipCursorRect.GetY(), (int)_clipCursorRect.GetWidth(), (int)_clipCursorRect.GetHeight() };
|
SDL_Rect rect{ (int)_clipCursorRect.GetX(), (int)_clipCursorRect.GetY(), (int)_clipCursorRect.GetWidth(), (int)_clipCursorRect.GetHeight() };
|
||||||
SDL_SetWindowMouseRect(_window, &rect);
|
SDL_SetWindowMouseRect(_window, &rect);
|
||||||
|
|
||||||
|
if (inRelativeMode)
|
||||||
|
Input::Mouse->SetRelativeMode(true, this);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||||
{
|
{
|
||||||
if (IsPopupWindow(_settings.Type))
|
|
||||||
_window = _window;
|
|
||||||
if (_settings.AllowInput && !SDLPlatform::UsesX11())
|
if (_settings.AllowInput && !SDLPlatform::UsesX11())
|
||||||
SDL_StopTextInput(_window);
|
SDL_StopTextInput(_window);
|
||||||
const SDL_Rect* currentClippingRect = SDL_GetWindowMouseRect(_window);
|
if (_isClippingCursor)
|
||||||
if (currentClippingRect != nullptr)
|
|
||||||
SDL_SetWindowMouseRect(_window, nullptr);
|
SDL_SetWindowMouseRect(_window, nullptr);
|
||||||
OnLostFocus();
|
OnLostFocus();
|
||||||
return;
|
return;
|
||||||
@@ -802,9 +809,23 @@ void SDLWindow::StartClippingCursor(const Rectangle& bounds)
|
|||||||
if (!IsFocused())
|
if (!IsFocused())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if PLATFORM_LINUX
|
||||||
|
{
|
||||||
|
auto oldValue = SDL_GetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION);
|
||||||
|
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, "1");
|
||||||
|
|
||||||
|
// The cursor is not fully constrained when positioned outside of the clip region...
|
||||||
|
Float2 center = bounds.GetCenter();
|
||||||
|
SDL_WarpMouseInWindow(_window, center.X, center.Y);
|
||||||
|
|
||||||
|
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, oldValue);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
_isClippingCursor = true;
|
_isClippingCursor = true;
|
||||||
SDL_Rect rect{ (int)bounds.GetX(), (int)bounds.GetY(), (int)bounds.GetWidth(), (int)bounds.GetHeight() };
|
SDL_Rect rect{ (int)bounds.GetX(), (int)bounds.GetY(), (int)bounds.GetWidth(), (int)bounds.GetHeight() };
|
||||||
SDL_SetWindowMouseRect(_window, &rect);
|
SDL_SetWindowMouseRect(_window, &rect);
|
||||||
|
_clipCursorRect = bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDLWindow::EndClippingCursor()
|
void SDLWindow::EndClippingCursor()
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ private:
|
|||||||
Rectangle _clipCursorRect;
|
Rectangle _clipCursorRect;
|
||||||
Rectangle _cachedClientRectangle;
|
Rectangle _cachedClientRectangle;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void Init();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SDLWindow"/> class.
|
/// Initializes a new instance of the <see cref="SDLWindow"/> class.
|
||||||
|
|||||||
Reference in New Issue
Block a user