When we are clipping (due to fullscreen), certain operations are bugged (such as creating another window on top, grabbing the window during a size-move operation, changing mouse capture, etc) so we must temporarily unclip first.
Seems unclipping it temporarily during such operation is enough to fix this.
This probably wasn't very obvious in practice because most times "fullscreen" means a single non-resizeable window with no menus and so on (e.g. fullscreen games), but that's not always the case.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
When we are clipping (due to fullscreen), certain operations are bugged (such as creating another window on top, grabbing the window during a size-move operation, changing mouse capture, etc) so we must temporarily unclip first.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53831 Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/winex11.drv/mouse.c | 13 ++++++++++++- dlls/winex11.drv/window.c | 19 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 96be81df6e3..a51d697aef7 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -557,6 +557,7 @@ BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) release_win_data( data ); if (!fullscreen) return FALSE; if (!(thread_data = x11drv_thread_data())) return FALSE; + if (thread_data->grab_hwnd) return FALSE; if (NtGetTickCount() - thread_data->clip_reset < 1000) return FALSE; if (!reset && clipping_cursor && thread_data->clip_hwnd) return FALSE; /* already clipping */
@@ -1641,6 +1642,7 @@ void move_resize_window( HWND hwnd, int dir ) POINT pos; int button = 0; XEvent xev; + BOOL was_clipped = FALSE; Window win, root, child; unsigned int xstate;
@@ -1670,7 +1672,15 @@ void move_resize_window( HWND hwnd, int dir )
/* need to ungrab the pointer that may have been automatically grabbed * with a ButtonPress event */ - XUngrabPointer( display, CurrentTime ); + if (!clipping_cursor) + XUngrabPointer( display, CurrentTime ); + + /* unclip it during drag, see Wine-Bug 53831 */ + if (x11drv_thread_data()->clip_hwnd) + { + was_clipped = TRUE; + ungrab_clipping_window(); + } XSendEvent(display, root_window, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
/* try to detect the end of the size/move by polling for the mouse button to be released */ @@ -1713,6 +1723,7 @@ void move_resize_window( HWND hwnd, int dir ) if (!(xstate & (Button1Mask << (button - 1)))) break; NtUserMsgWaitForMultipleObjectsEx( 0, NULL, 100, QS_ALLINPUT, 0 ); } + if (was_clipped) grab_clipping_window( &clip_rect );
TRACE( "hwnd %p/%lx done\n", hwnd, win ); send_message( hwnd, WM_EXITSIZEMOVE, 0, 0 ); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 70a29d24fb1..a0620d90d85 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1567,6 +1567,7 @@ static void create_whole_window( struct x11drv_win_data *data ) WCHAR text[1024]; COLORREF key; BYTE alpha; + BOOL was_clipped = FALSE; DWORD layered_flags; HRGN win_rgn; POINT pos; @@ -1595,10 +1596,21 @@ static void create_whole_window( struct x11drv_win_data *data ) if (!(cy = data->whole_rect.bottom - data->whole_rect.top)) cy = 1; else if (cy > 65535) cy = 65535;
+ /* unclip it while we create the Window, see Wine-Bug 53831 */ + if (x11drv_thread_data()->clip_hwnd) + { + was_clipped = TRUE; + ungrab_clipping_window(); + } pos = virtual_screen_to_root( data->whole_rect.left, data->whole_rect.top ); data->whole_window = XCreateWindow( data->display, root_window, pos.x, pos.y, cx, cy, 0, data->vis.depth, InputOutput, data->vis.visual, mask, &attr ); + if (was_clipped) + { + clipping_cursor = TRUE; + retry_grab_clipping_window(); + } if (!data->whole_window) goto done;
set_initial_wm_hints( data->display, data->whole_window ); @@ -2402,6 +2414,8 @@ void X11DRV_SetCapture( HWND hwnd, UINT flags ) if (!(data = get_win_data( NtUserGetAncestor( hwnd, GA_ROOT )))) return; if (data->whole_window) { + if (data->managed && thread_data->clip_hwnd) + ungrab_clipping_window(); XFlush( gdi_display ); XGrabPointer( data->display, data->whole_window, False, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, @@ -2412,12 +2426,15 @@ void X11DRV_SetCapture( HWND hwnd, UINT flags ) } else /* release capture */ { - if (!(data = get_win_data( thread_data->grab_hwnd ))) return; + HWND grab_hwnd = thread_data->grab_hwnd; + + if (!(data = get_win_data( grab_hwnd ))) return; XFlush( gdi_display ); XUngrabPointer( data->display, CurrentTime ); XFlush( data->display ); thread_data->grab_hwnd = NULL; release_win_data( data ); + clip_fullscreen_window( grab_hwnd, FALSE ); } }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=125365
Your paranoid android.
=== debian11 (build log) ===
Task: Could not create the win32 wineprefix: Failed to disable the crash dialogs: Task: WineTest did not produce the win32 report
I guess I need to investigate these failures. A bit weird why it crashes with some NULL-offset'd pointer, I assume. Testbot says some of them are pre-existing (WoW results): https://testbot.winehq.org/JobDetails.pl?Key=125408
Meanwhile a patch without the winex11.drv changes seems to not introduce them at all: https://testbot.winehq.org/JobDetails.pl?Key=125413
Not sure if just (bad) luck yet�
Yeah, it was my fault. Apparently `x11drv_thread_data()` can be NULL when creating window, so it's not fixed.