RawInput: fix input latching when dragging and switching between windows

This commit is contained in:
2022-06-11 21:55:55 +03:00
parent 66b0b4c965
commit 753a6c73f8
2 changed files with 56 additions and 17 deletions

View File

@@ -346,6 +346,10 @@ namespace FlaxEditor.GUI.Docking
{ {
if (button == MouseButton.Left) if (button == MouseButton.Left)
{ {
// Workaround to make sure the mouse down event which initiated dragging in moved window gets properly
// released when this window gets destroyed.
_toMove.Window.Window.Internal_OnMouseUp(ref location, button);
Dispose(); Dispose();
} }
} }

View File

@@ -112,7 +112,13 @@ namespace WindowsInputImpl
bool XInputGamepads[XUSER_MAX_COUNT] = { false }; bool XInputGamepads[XUSER_MAX_COUNT] = { false };
WindowsMouse* Mouse = nullptr; WindowsMouse* Mouse = nullptr;
WindowsKeyboard* Keyboard = nullptr; WindowsKeyboard* Keyboard = nullptr;
bool RawInputEnabled = true; }
namespace WindowsRawInputImpl
{
bool UseRawInput = true;
Window* LastLeaveWindow = nullptr;
Window* CurrentInputWindow = nullptr;
} }
void WindowsInput::Init() void WindowsInput::Init()
@@ -120,7 +126,7 @@ void WindowsInput::Init()
Input::Mouse = WindowsInputImpl::Mouse = New<WindowsMouse>(); Input::Mouse = WindowsInputImpl::Mouse = New<WindowsMouse>();
Input::Keyboard = WindowsInputImpl::Keyboard = New<WindowsKeyboard>(); Input::Keyboard = WindowsInputImpl::Keyboard = New<WindowsKeyboard>();
if (WindowsInputImpl::RawInputEnabled) if (WindowsRawInputImpl::UseRawInput)
{ {
RAWINPUTDEVICE rid[2] = {}; RAWINPUTDEVICE rid[2] = {};
@@ -176,6 +182,8 @@ bool WindowsInput::WndProc(Window* window, Windows::UINT msg, Windows::WPARAM wP
bool OnRawInput(Vector2 mousePosition, Window* window, HRAWINPUT input) bool OnRawInput(Vector2 mousePosition, Window* window, HRAWINPUT input)
{ {
// TODO: use GetRawInputBuffer to avoid filling the message queue with high polling rate mice
static BYTE* dataBuffer = nullptr; static BYTE* dataBuffer = nullptr;
static uint32 dataBufferSize = 0; static uint32 dataBufferSize = 0;
@@ -191,6 +199,13 @@ bool OnRawInput(Vector2 mousePosition, Window* window, HRAWINPUT input)
GetRawInputData(input, RID_INPUT, dataBuffer, &dataSize, sizeof(RAWINPUTHEADER)); GetRawInputData(input, RID_INPUT, dataBuffer, &dataSize, sizeof(RAWINPUTHEADER));
// Workaround to send the input to the topmost window after focusing the window from other applications.
if (WindowsRawInputImpl::LastLeaveWindow == window || WindowsRawInputImpl::LastLeaveWindow == nullptr)
{
if (WindowsRawInputImpl::CurrentInputWindow != nullptr)
window = WindowsRawInputImpl::CurrentInputWindow;
}
const RAWINPUT* rawInput = reinterpret_cast<RAWINPUT*>(dataBuffer); const RAWINPUT* rawInput = reinterpret_cast<RAWINPUT*>(dataBuffer);
if (rawInput->header.dwType == RIM_TYPEKEYBOARD) if (rawInput->header.dwType == RIM_TYPEKEYBOARD)
{ {
@@ -227,11 +242,8 @@ bool OnRawInput(Vector2 mousePosition, Window* window, HRAWINPUT input)
mousePos += mouseDelta; mousePos += mouseDelta;
if (!mouseDelta.IsZero()) if (!mouseDelta.IsZero())
{
//Input::Mouse->OnMouseMove(mousePos, window);
Input::Mouse->OnMouseMoveDelta(mouseDelta, window); Input::Mouse->OnMouseMoveDelta(mouseDelta, window);
} }
}
if ((rawMouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) != 0) if ((rawMouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) != 0)
Input::Mouse->OnMouseDown(mousePos, MouseButton::Left, window); Input::Mouse->OnMouseDown(mousePos, MouseButton::Left, window);
@@ -268,7 +280,7 @@ bool OnRawInput(Vector2 mousePosition, Window* window, HRAWINPUT input)
bool WindowsKeyboard::WndProc(Window* window, const Windows::UINT msg, Windows::WPARAM wParam, Windows::LPARAM lParam) bool WindowsKeyboard::WndProc(Window* window, const Windows::UINT msg, Windows::WPARAM wParam, Windows::LPARAM lParam)
{ {
if (WindowsInputImpl::RawInputEnabled && WndProcRawInput(window, msg, wParam, lParam)) if (WindowsRawInputImpl::UseRawInput && WndProcRawInput(window, msg, wParam, lParam))
return true; return true;
bool result = false; bool result = false;
@@ -324,7 +336,7 @@ bool WindowsKeyboard::WndProcRawInput(Window* window, const Windows::UINT msg, W
bool WindowsMouse::WndProc(Window* window, const UINT msg, WPARAM wParam, LPARAM lParam) bool WindowsMouse::WndProc(Window* window, const UINT msg, WPARAM wParam, LPARAM lParam)
{ {
if (WindowsInputImpl::RawInputEnabled && WndProcRawInput(window, msg, wParam, lParam)) if (WindowsRawInputImpl::UseRawInput && WndProcRawInput(window, msg, wParam, lParam))
return true; return true;
bool result = false; bool result = false;
@@ -341,6 +353,9 @@ bool WindowsMouse::WndProc(Window* window, const UINT msg, WPARAM wParam, LPARAM
{ {
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
{ {
if (!WindowsRawInputImpl::UseRawInput)
{
// Calculate mouse deltas since last message
static Vector2 lastPos = mousePos; static Vector2 lastPos = mousePos;
if (_state.MouseWasReset) if (_state.MouseWasReset)
{ {
@@ -352,6 +367,7 @@ bool WindowsMouse::WndProc(Window* window, const UINT msg, WPARAM wParam, LPARAM
if (!deltaPos.IsZero()) if (!deltaPos.IsZero())
OnMouseMoveDelta(deltaPos, window); OnMouseMoveDelta(deltaPos, window);
lastPos = mousePos; lastPos = mousePos;
}
OnMouseMove(mousePos, window); OnMouseMove(mousePos, window);
result = true; result = true;
@@ -475,11 +491,15 @@ bool WindowsMouse::WndProcRawInput(Window* window, const UINT msg, WPARAM wParam
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
{ {
// Ignored with raw input // Ignored with raw input
WindowsRawInputImpl::CurrentInputWindow = window;
result = true; result = true;
break; break;
} }
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
case WM_MOUSELEAVE: {
WindowsRawInputImpl::CurrentInputWindow = window;
break;
}
case WM_LBUTTONDBLCLK: case WM_LBUTTONDBLCLK:
case WM_RBUTTONDBLCLK: case WM_RBUTTONDBLCLK:
case WM_MBUTTONDBLCLK: case WM_MBUTTONDBLCLK:
@@ -487,6 +507,21 @@ bool WindowsMouse::WndProcRawInput(Window* window, const UINT msg, WPARAM wParam
// Might need to be handled here // Might need to be handled here
break; break;
} }
case WM_MOUSELEAVE:
{
WindowsRawInputImpl::LastLeaveWindow = window;
break;
}
case WM_ACTIVATE:
{
break;
}
case WM_ACTIVATEAPP:
{
// Reset when switching between apps
WindowsRawInputImpl::LastLeaveWindow = nullptr;
break;
}
case WM_INPUT: case WM_INPUT:
{ {
result = OnRawInput(_state.MousePosition, window, reinterpret_cast<HRAWINPUT>(lParam)); result = OnRawInput(_state.MousePosition, window, reinterpret_cast<HRAWINPUT>(lParam));