On Thu Sep 29 09:17:32 2022 +0000, Zhiyi Zhang wrote:
This might break clipping. Note that in X11DRV_resize_desktop(), ungrab_clipping_window() is called. In ungrab_clipping_window(), XUngrabPointer() is called when clipping_cursor is FALSE. Also notice that in grab_clipping_window() clipping is rejected in the desktop process. So clipping_cursor in the desktop process will always be FALSE and clipping will not be released as before. You need to keep the clipping logic the same as the old one.
Hmm, I think that's the same logic as how it is currently done:
`X11DRV_resize_desktop` is already sending a message to the desktop window if it's not called from the desktop thread, so its actual logic is only executed from the desktop thread:
https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/winex11.drv/desktop.c...
```c if (NtUserGetWindowThread( hwnd, NULL ) != GetCurrentThreadId()) { send_message( hwnd, WM_X11DRV_RESIZE_DESKTOP, 0, 0 ); } else { /* ... */ ungrab_clipping_window(); } ```
From that thread, `ungrab_clipping_window` indeed skips the `XUngrabPointer`, but sends a `WM_X11DRV_CLIP_CURSOR_NOTIFY` message to the desktop window (so the thread itself):
https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/winex11.drv/mouse.c#L...
```c void ungrab_clipping_window(void) { /* ... */ if (clipping_cursor) XUngrabPointer( display, CurrentTime ); clipping_cursor = FALSE; send_notify_message( NtUserGetDesktopWindow(), WM_X11DRV_CLIP_CURSOR_NOTIFY, 0, 0 ); } ```
Which is later use to reset some desktop clip_hwnd variable, and forwarded to the previously clipping window:
https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/winex11.drv/mouse.c#L...
```c if (hwnd == NtUserGetDesktopWindow()) /* change the clip window stored in the desktop process */ { static HWND clip_hwnd; HWND prev = clip_hwnd; clip_hwnd = new_clip_hwnd; if (prev) send_notify_message( prev, WM_X11DRV_CLIP_CURSOR_NOTIFY, (WPARAM)prev, 0 ); } ```
This then translates, in the currently clipping thread, to the cursor being ungrabbed and the clipping window being destroyed:
https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/winex11.drv/mouse.c#L...
```c else if (hwnd == data->clip_hwnd) /* this is a notification that clipping has been reset */ { disable_xinput2(); NtUserDestroyWindow( hwnd ); } ```
**Then however**, I think you're right that the changes can break clipping, but I think it's because of https://gitlab.winehq.org/wine/wine/-/merge_requests/944/diffs?commit_id=1cf... instead:
Moving that part to `X11DRV_resize_desktop` makes it likely never match the condition, because the desktop is unlikely to be the foreground process. Instead I think it can simply send the `WM_X11DRV_CLIP_CURSOR_REQUEST` to the foreground window without even checking the thread id / pid.
```c /* forward clip_fullscreen_window request to the foreground window */ if ((foreground = NtUserGetForegroundWindow()) && (tid = NtUserGetWindowThread( foreground, &pid )) && pid == GetCurrentProcessId()) { if (tid == GetCurrentThreadId()) clip_fullscreen_window( foreground, TRUE ); else send_notify_message( foreground, WM_X11DRV_CLIP_CURSOR_REQUEST, TRUE, TRUE ); } ```
That should still asynchronously restore clipping from the foreground process if fullscreen clipping is enabled, and always after the reset logic described above.