win32: stop fullscreen window from moving while dragging hack is active

The mouse down handler checks w32->current_fs to determine whether
to begin the dragging hack. Unfortunately, the w32->current_fs value
is stale, because the input is handled asynchronously, and we cannot
wait for an up-to-date value if dragging needs to be kept resonsive.

As a result, when the fullscreen state changes after the dragging
model loop is entered, the opposite value is used, so the window stays
draggable after entering fullscreen, and becomes undraggable after
exiting fullscreen.

With the resonsiveness and model loop constraints, the up-to-date
state must be queried inside WM_MOVING messages which are sent while
dragging. The message handler now checks if the dragging hack is active
while the window is in fullscreen, and overrides the new window position
with the current one, in effect prevents the window from being moved.

The old check is also removed, so the window is now draggable after
exiting fullscreen while dragging hack is active.
This commit is contained in:
nanahi 2023-11-21 05:46:37 -05:00 committed by sfan5
parent 5cc810e7f8
commit 5736737750
1 changed files with 17 additions and 3 deletions

20
video/out/w32_common.c Normal file → Executable file
View File

@ -181,6 +181,7 @@ struct vo_w32_state {
HANDLE avrt_handle;
bool cleared;
bool dragging;
};
static void adjust_window_rect(struct vo_w32_state *w32, HWND hwnd, RECT *rc)
@ -474,12 +475,19 @@ static bool handle_mouse_down(struct vo_w32_state *w32, int btn, int x, int y)
btn |= mod_state(w32);
mp_input_put_key(w32->input_ctx, btn | MP_KEY_STATE_DOWN);
if (btn == MP_MBTN_LEFT && !w32->current_fs &&
!mp_input_test_dragging(w32->input_ctx, x, y))
{
if (btn == MP_MBTN_LEFT && !mp_input_test_dragging(w32->input_ctx, x, y)) {
// Window dragging hack
ReleaseCapture();
// The dragging model loop is entered at SendMessage() here.
// Unfortunately, the w32->current_fs value is stale because the
// input is handled in a different thread, and we cannot wait for
// an up-to-date value before entering the model loop if dragging
// needs to be kept resonsive.
// Workaround this by intercepting the loop in the WM_MOVING message,
// where the up-to-date value is available.
w32->dragging = true;
SendMessage(w32->window, WM_NCLBUTTONDOWN, HTCAPTION, 0);
w32->dragging = false;
mp_input_put_key(w32->input_ctx, MP_MBTN_LEFT | MP_KEY_STATE_UP);
// Indicate the message was handled, so DefWindowProc won't be called
@ -1241,6 +1249,12 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
case WM_MOVING: {
w32->moving = true;
RECT *rc = (RECT*)lParam;
// Prevent the window from being moved if the window dragging hack
// is active, and the window is currently in fullscreen.
if (w32->dragging && w32->current_fs) {
*rc = w32->windowrc;
return TRUE;
}
if (snap_to_screen_edges(w32, rc))
return TRUE;
break;