Revert "Fix erratic mouse wrapping movement on Windows (2)"
This reverts commita3a9459050
. And fixes T103337.a3a9459050
has some flaws and it needs to go through review (See D16803). Conflicts: intern/ghost/intern/GHOST_SystemWin32.cpp
This commit is contained in:
parent
4cb2204d3a
commit
1a986f7eba
Notes:
blender-bot
2023-02-14 10:11:54 +01:00
Referenced by issue #103596, Blender 3.5: Cursor warping usable on windows remote desktop (RDP) Referenced by issue #103337, Regression: Infinite drag in the 3D viewport sometimes gets stuck on the edge of the screen.
|
@ -1061,16 +1061,11 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
|||
|
||||
int32_t x_screen = screen_co[0], y_screen = screen_co[1];
|
||||
if (window->getCursorGrabModeIsWarp()) {
|
||||
static uint64_t last_warp_time = 0;
|
||||
{
|
||||
/* WORKAROUND: Check the mouse event timestamp so we can ignore mouse-move events that were
|
||||
* already in the queue before we changed the cursor position. */
|
||||
MOUSEMOVEPOINT mp = {x_screen, y_screen};
|
||||
::GetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &mp, &mp, 1, GMMP_USE_DISPLAY_POINTS);
|
||||
if (mp.time <= last_warp_time) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* WORKAROUND:
|
||||
* Sometimes Windows ignores `SetCursorPos()` or `SendInput()` calls or the mouse event is
|
||||
* outdated. Identify these cases by checking if the cursor is not yet within bounds. */
|
||||
static bool is_warping_x = false;
|
||||
static bool is_warping_y = false;
|
||||
|
||||
int32_t x_new = x_screen;
|
||||
int32_t y_new = y_screen;
|
||||
|
@ -1117,35 +1112,31 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
|||
|
||||
window->getCursorGrabAccum(x_accum, y_accum);
|
||||
if (x_new != x_screen || y_new != y_screen) {
|
||||
/* WORKAROUND: Store the current time so that we ignore outdated mouse-move events. */
|
||||
last_warp_time = ::GetTickCount64();
|
||||
system->setCursorPosition(x_new, y_new); /* wrap */
|
||||
|
||||
/* For more control over which timestamp to store in the event, we use `SendInput` instead of
|
||||
* `SetCursorPos` here.
|
||||
* It is quite unlikely to happen, but still possible that some event between
|
||||
* `last_warp_time` and `GHOST_SystemWin32::setCursorPosition` is sent. */
|
||||
INPUT input[3] = {0};
|
||||
input[0].type = INPUT_MOUSE;
|
||||
input[0].mi.dx = (LONG)(x_new * (65535.0f / GetSystemMetrics(SM_CXSCREEN)));
|
||||
input[0].mi.dy = (LONG)(y_new * (65535.0f / GetSystemMetrics(SM_CYSCREEN)));
|
||||
input[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
|
||||
input[0].mi.time = last_warp_time;
|
||||
/* Do not update the accum values if we are an outdated or failed pos-warp event. */
|
||||
if (!is_warping_x) {
|
||||
is_warping_x = x_new != x_screen;
|
||||
if (is_warping_x) {
|
||||
x_accum += (x_screen - x_new);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send 3 events with a jitter to make sure Windows does not occasionally and
|
||||
* inexplicably ignore `SetCursorPos` or `SendInput`. */
|
||||
input[2] = input[1] = input[0];
|
||||
input[1].mi.dx += 1;
|
||||
::SendInput(3, input, sizeof(INPUT));
|
||||
|
||||
x_accum += (x_screen - x_new);
|
||||
y_accum += (y_screen - y_new);
|
||||
if (!is_warping_y) {
|
||||
is_warping_y = y_new != y_screen;
|
||||
if (is_warping_y) {
|
||||
y_accum += (y_screen - y_new);
|
||||
}
|
||||
}
|
||||
window->setCursorGrabAccum(x_accum, y_accum);
|
||||
|
||||
/* When wrapping we don't need to add an event because the `SendInput` call will cause new
|
||||
* events after. */
|
||||
/* When wrapping we don't need to add an event because the setCursorPosition call will cause
|
||||
* a new event after. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
is_warping_x = false;
|
||||
is_warping_y = false;
|
||||
x_screen += x_accum;
|
||||
y_screen += y_accum;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue