I wasn't completely sure what to do with the registry key. Keeping "Wine/X11 Driver" is a bit odd, but it also makes sure we stay backward compatible. Changing it would require more changes elsewhere and maybe it could be done later, if / when more options are moved.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/mouse.c | 49 ++++++--------------------------------- dlls/winex11.drv/window.c | 2 -- dlls/winex11.drv/x11drv.h | 2 -- 3 files changed, 7 insertions(+), 46 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 4d94a97f3c8..3820e98ed18 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -442,7 +442,6 @@ static BOOL grab_clipping_window( const RECT *clip ) if (!data->clip_hwnd) sync_window_cursor( clip_window ); InterlockedExchangePointer( (void **)&cursor_window, msg_hwnd ); data->clip_hwnd = msg_hwnd; - send_notify_message( NtUserGetDesktopWindow(), WM_X11DRV_CLIP_CURSOR_NOTIFY, 0, (LPARAM)msg_hwnd ); return TRUE; #else WARN( "XInput2 was not available at compile time\n" ); @@ -457,16 +456,19 @@ static BOOL grab_clipping_window( const RECT *clip ) */ static void ungrab_clipping_window(void) { - Display *display = thread_init_display(); + struct x11drv_thread_data *data = x11drv_init_thread_data(); Window clip_window = init_clip_window();
if (!clip_window) return;
TRACE( "no longer clipping\n" ); - XUnmapWindow( display, clip_window ); - if (clipping_cursor) XUngrabPointer( display, CurrentTime ); + XUnmapWindow( data->display, clip_window ); + if (clipping_cursor) XUngrabPointer( data->display, CurrentTime ); clipping_cursor = FALSE; - send_notify_message( NtUserGetDesktopWindow(), WM_X11DRV_CLIP_CURSOR_NOTIFY, 0, 0 ); + NtUserDestroyWindow( data->clip_hwnd ); + data->clip_hwnd = 0; + data->clip_reset = NtGetTickCount(); + disable_xinput2(); }
/*********************************************************************** @@ -483,43 +485,6 @@ void retry_grab_clipping_window(void) NtUserClipCursor( &last_clip_rect ); }
-/*********************************************************************** - * clip_cursor_notify - * - * Notification function called upon receiving a WM_X11DRV_CLIP_CURSOR_NOTIFY. - */ -LRESULT clip_cursor_notify( HWND hwnd, HWND prev_clip_hwnd, HWND new_clip_hwnd ) -{ - struct x11drv_thread_data *data = x11drv_init_thread_data(); - - 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 || new_clip_hwnd) TRACE( "clip hwnd changed from %p to %p\n", prev, new_clip_hwnd ); - if (prev) send_notify_message( prev, WM_X11DRV_CLIP_CURSOR_NOTIFY, (WPARAM)prev, 0 ); - } - else if (hwnd == data->clip_hwnd) /* this is a notification that clipping has been reset */ - { - TRACE( "clip hwnd reset from %p\n", hwnd ); - data->clip_hwnd = 0; - data->clip_reset = NtGetTickCount(); - disable_xinput2(); - NtUserDestroyWindow( hwnd ); - } - else if (prev_clip_hwnd) - { - /* This is a notification send by the desktop window to an old - * dangling clip window. - */ - TRACE( "destroying old clip hwnd %p\n", prev_clip_hwnd ); - NtUserDestroyWindow( prev_clip_hwnd ); - } - return 0; -} - /*********************************************************************** * clip_fullscreen_window * diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 2e290295860..3705d337101 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -3085,8 +3085,6 @@ LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) } return 0; } - case WM_X11DRV_CLIP_CURSOR_NOTIFY: - return clip_cursor_notify( hwnd, (HWND)wp, (HWND)lp ); case WM_X11DRV_CLIP_CURSOR_REQUEST: return clip_cursor_request( hwnd, (BOOL)wp, (BOOL)lp ); case WM_X11DRV_DELETE_TAB: diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index aea62c90b7c..e366cab4977 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -589,7 +589,6 @@ enum x11drv_window_messages WM_X11DRV_SET_WIN_REGION, WM_X11DRV_DESKTOP_RESIZED, WM_X11DRV_SET_CURSOR, - WM_X11DRV_CLIP_CURSOR_NOTIFY, WM_X11DRV_CLIP_CURSOR_REQUEST, WM_X11DRV_DELETE_TAB, WM_X11DRV_ADD_TAB @@ -684,7 +683,6 @@ extern XContext cursor_context DECLSPEC_HIDDEN; extern void X11DRV_SetFocus( HWND hwnd ) DECLSPEC_HIDDEN; extern void set_window_cursor( Window window, HCURSOR handle ) DECLSPEC_HIDDEN; extern void sync_window_cursor( Window window ) DECLSPEC_HIDDEN; -extern LRESULT clip_cursor_notify( HWND hwnd, HWND prev_clip_hwnd, HWND new_clip_hwnd ) DECLSPEC_HIDDEN; extern LRESULT clip_cursor_request( HWND hwnd, BOOL fullscreen, BOOL reset ) DECLSPEC_HIDDEN; extern void retry_grab_clipping_window(void) DECLSPEC_HIDDEN; extern BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) DECLSPEC_HIDDEN;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/input.c | 7 +++- dlls/win32u/sysparams.c | 75 +++++++++++++++++++++++++++++++++- dlls/win32u/win32u_private.h | 1 + dlls/winex11.drv/mouse.c | 2 +- dlls/winex11.drv/x11drv.h | 1 - dlls/winex11.drv/x11drv_main.c | 4 -- 6 files changed, 80 insertions(+), 10 deletions(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index c26660319df..cea18b89920 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -406,7 +406,7 @@ static const KBDTABLES kbdus_tables =
LONG global_key_state_counter = 0; - +BOOL grab_pointer = TRUE;
static void kbd_tables_init_vsc2vk( const KBDTABLES *tables, BYTE vsc2vk[0x300] ) { @@ -2503,7 +2503,10 @@ BOOL process_wine_clipcursor( BOOL empty, BOOL reset )
TRACE( "empty %u, reset %u\n", empty, reset );
- if (empty || reset) return user_driver->pClipCursor( NULL, reset ); + if (reset) return user_driver->pClipCursor( NULL, TRUE ); + + if (!grab_pointer) return TRUE; + if (empty) return user_driver->pClipCursor( NULL, reset );
get_clip_cursor( &rect ); return user_driver->pClipCursor( &rect, FALSE ); diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 99042c85923..1ffb040ae75 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -4099,13 +4099,47 @@ static union sysparam_all_entry * const default_entries[] = (union sysparam_all_entry *)&entry_AUDIODESC_ON, };
-void sysparams_init(void) +/*********************************************************************** + * get_config_key + * + * Get a config key from either the app-specific or the default config + */ +static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name, + WCHAR *buffer, DWORD size ) { + WCHAR nameW[128]; + char buf[2048]; + KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf; + + asciiz_to_unicode( nameW, name ); + + if (appkey && query_reg_value( appkey, nameW, info, sizeof(buf) )) + { + size = min( info->DataLength, size - sizeof(WCHAR) ); + memcpy( buffer, info->Data, size ); + buffer[size / sizeof(WCHAR)] = 0; + return 0; + } + + if (defkey && query_reg_value( defkey, nameW, info, sizeof(buf) )) + { + size = min( info->DataLength, size - sizeof(WCHAR) ); + memcpy( buffer, info->Data, size ); + buffer[size / sizeof(WCHAR)] = 0; + return 0; + } + + return ERROR_FILE_NOT_FOUND; +}
+void sysparams_init(void) +{ + WCHAR buffer[MAX_PATH+16], *p, *appname; DWORD i, dispos, dpi_scaling; WCHAR layout[KL_NAMELENGTH]; pthread_mutexattr_t attr; - HKEY hkey; + HKEY hkey, appkey = 0; + DWORD len;
static const WCHAR software_wineW[] = {'S','o','f','t','w','a','r','e','\','W','i','n','e'}; static const WCHAR temporary_system_parametersW[] = @@ -4114,6 +4148,7 @@ void sysparams_init(void) static const WCHAR oneW[] = {'1',0}; static const WCHAR kl_preloadW[] = {'K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','\','P','r','e','l','o','a','d'}; + static const WCHAR x11driverW[] = {'\','X','1','1',' ','D','r','i','v','e','r',0};
pthread_mutexattr_init( &attr ); pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); @@ -4173,6 +4208,42 @@ void sysparams_init(void) for (i = 0; i < ARRAY_SIZE( default_entries ); i++) default_entries[i]->hdr.init( default_entries[i] ); } + + /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */ + hkey = reg_open_hkcu_key( "Software\Wine\X11 Driver" ); + + /* open the app-specific key */ + + appname = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer; + if ((p = wcsrchr( appname, '/' ))) appname = p + 1; + if ((p = wcsrchr( appname, '\' ))) appname = p + 1; + len = lstrlenW( appname ); + + if (len && len < MAX_PATH) + { + HKEY tmpkey; + int i; + + for (i = 0; appname[i]; i++) buffer[i] = RtlDowncaseUnicodeChar( appname[i] ); + buffer[i] = 0; + appname = buffer; + memcpy( appname + i, x11driverW, sizeof(x11driverW) ); + + /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */ + if ((tmpkey = reg_open_hkcu_key( "Software\Wine\AppDefaults" ))) + { + appkey = reg_open_key( tmpkey, appname, lstrlenW( appname ) * sizeof(WCHAR) ); + NtClose( tmpkey ); + } + } + +#define IS_OPTION_TRUE(ch) \ + ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1') + + if (!get_config_key( hkey, appkey, "GrabPointer", buffer, sizeof(buffer) )) + grab_pointer = IS_OPTION_TRUE( buffer[0] ); + +#undef IS_OPTION_TRUE }
static BOOL update_desktop_wallpaper(void) diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 45e58093ba4..3cb5eef6fb1 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -86,6 +86,7 @@ extern BOOL register_imm_window( HWND hwnd ) DECLSPEC_HIDDEN; extern void unregister_imm_window( HWND hwnd ) DECLSPEC_HIDDEN;
/* input.c */ +extern BOOL grab_pointer DECLSPEC_HIDDEN; extern BOOL destroy_caret(void) DECLSPEC_HIDDEN; extern LONG global_key_state_counter DECLSPEC_HIDDEN; extern HWND get_active_window(void) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 3820e98ed18..fd03f03f0dd 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -1526,7 +1526,7 @@ BOOL X11DRV_ClipCursor( const RECT *clip, BOOL reset ) { TRACE( "clip %p, reset %u\n", clip, reset );
- if (!reset && grab_pointer) + if (!reset) { RECT virtual_rect = NtUserGetVirtualScreenRect();
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index e366cab4977..7cbf40079d2 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -443,7 +443,6 @@ extern BOOL use_take_focus DECLSPEC_HIDDEN; extern BOOL use_primary_selection DECLSPEC_HIDDEN; extern BOOL use_system_cursors DECLSPEC_HIDDEN; extern BOOL show_systray DECLSPEC_HIDDEN; -extern BOOL grab_pointer DECLSPEC_HIDDEN; extern BOOL grab_fullscreen DECLSPEC_HIDDEN; extern BOOL usexcomposite DECLSPEC_HIDDEN; extern BOOL managed_mode DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 929be92ff7a..c4d537d6ada 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -74,7 +74,6 @@ BOOL use_take_focus = TRUE; BOOL use_primary_selection = FALSE; BOOL use_system_cursors = TRUE; BOOL show_systray = TRUE; -BOOL grab_pointer = TRUE; BOOL grab_fullscreen = FALSE; BOOL managed_mode = TRUE; BOOL decorated_mode = TRUE; @@ -498,9 +497,6 @@ static void setup_options(void) if (!get_config_key( hkey, appkey, "ShowSystray", buffer, sizeof(buffer) )) show_systray = IS_OPTION_TRUE( buffer[0] );
- if (!get_config_key( hkey, appkey, "GrabPointer", buffer, sizeof(buffer) )) - grab_pointer = IS_OPTION_TRUE( buffer[0] ); - if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) )) grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/input.c | 7 ++++++- dlls/win32u/ntuser_private.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index cea18b89920..2b951576c57 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2499,11 +2499,16 @@ BOOL get_clip_cursor( RECT *rect )
BOOL process_wine_clipcursor( BOOL empty, BOOL reset ) { + struct user_thread_info *thread_info = get_user_thread_info(); RECT rect;
TRACE( "empty %u, reset %u\n", empty, reset );
- if (reset) return user_driver->pClipCursor( NULL, TRUE ); + if (reset) + { + thread_info->clipping_reset = NtGetTickCount(); + return user_driver->pClipCursor( NULL, TRUE ); + }
if (!grab_pointer) return TRUE; if (empty) return user_driver->pClipCursor( NULL, reset ); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 0e7d84e3faa..88e644d2522 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -130,6 +130,7 @@ struct user_thread_info UINT kbd_layout_id; /* Current keyboard layout ID */ struct rawinput_thread_data *rawinput; /* RawInput thread local data / buffer */ UINT spy_indent; /* Current spy indent */ + DWORD clipping_reset; /* time when clipping was last reset */ };
C_ASSERT( sizeof(struct user_thread_info) <= sizeof(((TEB *)0)->Win32ClientInfo) );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/input.c | 9 ++++++++- dlls/win32u/ntuser_private.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 2b951576c57..0dc166986f3 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -404,6 +404,7 @@ static const KBDTABLES kbdus_tables = .fLocaleFlags = MAKELONG(0, KBD_VERSION), };
+static LONG clipping_cursor; /* clipping thread counter */
LONG global_key_state_counter = 0; BOOL grab_pointer = TRUE; @@ -2504,6 +2505,9 @@ BOOL process_wine_clipcursor( BOOL empty, BOOL reset )
TRACE( "empty %u, reset %u\n", empty, reset );
+ if (thread_info->clipping_cursor) InterlockedDecrement( &clipping_cursor ); + thread_info->clipping_cursor = FALSE; + if (reset) { thread_info->clipping_reset = NtGetTickCount(); @@ -2514,7 +2518,10 @@ BOOL process_wine_clipcursor( BOOL empty, BOOL reset ) if (empty) return user_driver->pClipCursor( NULL, reset );
get_clip_cursor( &rect ); - return user_driver->pClipCursor( &rect, FALSE ); + if (!user_driver->pClipCursor( &rect, FALSE )) return FALSE; + InterlockedIncrement( &clipping_cursor ); + thread_info->clipping_cursor = TRUE; + return TRUE; }
/*********************************************************************** diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 88e644d2522..b39e38db5d6 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -130,6 +130,7 @@ struct user_thread_info UINT kbd_layout_id; /* Current keyboard layout ID */ struct rawinput_thread_data *rawinput; /* RawInput thread local data / buffer */ UINT spy_indent; /* Current spy indent */ + BOOL clipping_cursor; /* thread is currently clipping */ DWORD clipping_reset; /* time when clipping was last reset */ };
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 2 +- dlls/winex11.drv/mouse.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index edb7a1bf983..0e059a94f30 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -782,7 +782,7 @@ static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev )
if (use_take_focus) { - if (hwnd == NtUserGetForegroundWindow()) clip_fullscreen_window( hwnd, FALSE ); + clip_fullscreen_window( hwnd, FALSE ); return TRUE; }
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index fd03f03f0dd..00e537cecde 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -500,6 +500,8 @@ BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) BOOL fullscreen;
if (hwnd == NtUserGetDesktopWindow()) return FALSE; + if (hwnd != NtUserGetForegroundWindow()) return FALSE; + style = NtUserGetWindowLongW( hwnd, GWL_STYLE ); if (!(style & WS_VISIBLE)) return FALSE; if ((style & (WS_POPUP | WS_CHILD)) == WS_CHILD) return FALSE; @@ -628,12 +630,8 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU last_cursor_change = input->u.mi.time; }
- if (hwnd != NtUserGetDesktopWindow()) - { - hwnd = NtUserGetAncestor( hwnd, GA_ROOT ); - if ((input->u.mi.dwFlags & (MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_RIGHTDOWN)) && hwnd == NtUserGetForegroundWindow()) - clip_fullscreen_window( hwnd, FALSE ); - } + if (input->u.mi.dwFlags & (MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_RIGHTDOWN)) + clip_fullscreen_window( hwnd, FALSE );
/* update the wine server Z-order */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/input.c | 70 +++++++++++++++++++++++++--- dlls/win32u/message.c | 8 +++- dlls/win32u/ntgdi_private.h | 9 ---- dlls/win32u/sysparams.c | 4 ++ dlls/win32u/win32u_private.h | 16 ++++++- dlls/win32u/winstation.c | 13 ++++++ dlls/winex11.drv/desktop.c | 3 -- dlls/winex11.drv/event.c | 6 +-- dlls/winex11.drv/mouse.c | 89 +----------------------------------- dlls/winex11.drv/window.c | 2 - dlls/winex11.drv/x11drv.h | 4 -- 11 files changed, 103 insertions(+), 121 deletions(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 0dc166986f3..b115dcc03b2 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -408,6 +408,7 @@ static LONG clipping_cursor; /* clipping thread counter */
LONG global_key_state_counter = 0; BOOL grab_pointer = TRUE; +BOOL grab_fullscreen = FALSE;
static void kbd_tables_init_vsc2vk( const KBDTABLES *tables, BYTE vsc2vk[0x300] ) { @@ -1845,7 +1846,7 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus ) if (previous == hwnd) { if (prev) *prev = hwnd; - return TRUE; + goto done; }
/* call CBT hook chain */ @@ -1869,7 +1870,7 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus ) SERVER_END_REQ; if (!ret) return FALSE; if (prev) *prev = previous; - if (previous == hwnd) return TRUE; + if (previous == hwnd) goto done;
if (hwnd) { @@ -1934,6 +1935,8 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus ) } }
+done: + clip_fullscreen_window( hwnd, FALSE ); return TRUE; }
@@ -2458,6 +2461,49 @@ BOOL WINAPI NtUserIsMouseInPointerEnabled(void) return FALSE; }
+/*********************************************************************** + * clip_fullscreen_window + * + * Turn on clipping if the active window is fullscreen. + */ +BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) +{ + struct user_thread_info *thread_info = get_user_thread_info(); + MONITORINFO monitor_info = {.cbSize = sizeof(MONITORINFO)}; + RECT rect, virtual_rect = NtUserGetVirtualScreenRect(); + HMONITOR monitor; + DWORD style; + + if (hwnd == NtUserGetDesktopWindow()) return FALSE; + if (hwnd != NtUserGetForegroundWindow()) return FALSE; + + style = NtUserGetWindowLongW( hwnd, GWL_STYLE ); + if (!(style & WS_VISIBLE)) return FALSE; + if ((style & (WS_POPUP | WS_CHILD)) == WS_CHILD) return FALSE; + /* maximized windows don't count as full screen */ + if ((style & WS_MAXIMIZE) && (style & WS_CAPTION) == WS_CAPTION) return FALSE; + + if (!NtUserGetWindowRect( hwnd, &rect )) return FALSE; + if (!NtUserIsWindowRectFullScreen( &rect )) return FALSE; + if (NtGetTickCount() - thread_info->clipping_reset < 1000) return FALSE; + if (!reset && clipping_cursor && thread_info->clipping_cursor) return FALSE; /* already clipping */ + + if (!(monitor = NtUserMonitorFromWindow( hwnd, MONITOR_DEFAULTTONEAREST ))) return FALSE; + if (!NtUserGetMonitorInfo( monitor, &monitor_info )) return FALSE; + if (!grab_fullscreen) + { + RECT virtual_rect = NtUserGetVirtualScreenRect(); + if (!EqualRect( &monitor_info.rcMonitor, &virtual_rect )) return FALSE; + if (is_virtual_desktop()) return FALSE; + } + + /* shrink the clipping rect to make sure it is not ignored for being fullscreen */ + if (EqualRect( &monitor_info.rcMonitor, &virtual_rect )) InflateRect( &monitor_info.rcMonitor, -1, -1 ); + + TRACE( "win %p clipping fullscreen\n", hwnd ); + return NtUserClipCursor( &monitor_info.rcMonitor ); +} + /********************************************************************** * NtUserGetPointerInfoList (win32u.@) */ @@ -2498,14 +2544,15 @@ BOOL get_clip_cursor( RECT *rect ) return ret; }
-BOOL process_wine_clipcursor( BOOL empty, BOOL reset ) +BOOL process_wine_clipcursor( HWND hwnd, BOOL empty, BOOL reset ) { struct user_thread_info *thread_info = get_user_thread_info(); - RECT rect; + RECT rect, virtual_rect = NtUserGetVirtualScreenRect(); + BOOL was_clipping;
- TRACE( "empty %u, reset %u\n", empty, reset ); + TRACE( "hwnd %p, empty %u, reset %u\n", hwnd, empty, reset );
- if (thread_info->clipping_cursor) InterlockedDecrement( &clipping_cursor ); + if ((was_clipping = thread_info->clipping_cursor)) InterlockedDecrement( &clipping_cursor ); thread_info->clipping_cursor = FALSE;
if (reset) @@ -2515,9 +2562,18 @@ BOOL process_wine_clipcursor( BOOL empty, BOOL reset ) }
if (!grab_pointer) return TRUE; - if (empty) return user_driver->pClipCursor( NULL, reset );
+ /* we are clipping if the clip rectangle is smaller than the screen */ get_clip_cursor( &rect ); + intersect_rect( &rect, &rect, &virtual_rect ); + if (EqualRect( &rect, &virtual_rect )) empty = TRUE; + if (empty) + { + /* if currently clipping, check if we should switch to fullscreen clipping */ + if (was_clipping && clip_fullscreen_window( hwnd, TRUE )) return TRUE; + return user_driver->pClipCursor( NULL, FALSE ); + } + if (!user_driver->pClipCursor( &rect, FALSE )) return FALSE; InterlockedIncrement( &clipping_cursor ); thread_info->clipping_cursor = TRUE; diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 7238dd1bd46..e10350fcd3b 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -1272,7 +1272,8 @@ static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPAR return call_current_hook( h_extra->handle, HC_ACTION, wparam, h_extra->lparam ); } case WM_WINE_CLIPCURSOR: - return process_wine_clipcursor( wparam, lparam ); + if (wparam && lparam) return clip_fullscreen_window( hwnd, FALSE ); + return process_wine_clipcursor( hwnd, wparam, lparam ); case WM_WINE_UPDATEWINDOWSTATE: update_window_state( hwnd ); return 0; @@ -1767,7 +1768,7 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar else if (is_mouse_message( msg->message )) ret = process_mouse_message( msg, hw_id, msg_data->info, hwnd_filter, first, last, remove ); else if (msg->message == WM_WINE_CLIPCURSOR) - process_wine_clipcursor( msg->wParam, msg->lParam ); + process_wine_clipcursor( msg->hwnd, msg->wParam, msg->lParam ); else ERR( "unknown message type %x\n", msg->message ); SetThreadDpiAwarenessContext( context ); @@ -2594,6 +2595,9 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r info.timeout = 0; info.params = NULL;
+ if (input->type == INPUT_MOUSE && (input->mi.dwFlags & (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_RIGHTDOWN))) + clip_fullscreen_window( hwnd, FALSE ); + if (input->type == INPUT_HARDWARE && rawinput->header.dwType == RIM_TYPEHID) { if (input->hi.uMsg == WM_INPUT_DEVICE_CHANGE) diff --git a/dlls/win32u/ntgdi_private.h b/dlls/win32u/ntgdi_private.h index 87b7d943295..ad4c709b865 100644 --- a/dlls/win32u/ntgdi_private.h +++ b/dlls/win32u/ntgdi_private.h @@ -531,15 +531,6 @@ static inline DC *get_physdev_dc( PHYSDEV dev ) return get_nulldrv_dc( dev ); }
-static inline BOOL intersect_rect( RECT *dst, const RECT *src1, const RECT *src2 ) -{ - dst->left = max( src1->left, src2->left ); - dst->top = max( src1->top, src2->top ); - dst->right = min( src1->right, src2->right ); - dst->bottom = min( src1->bottom, src2->bottom ); - return !IsRectEmpty( dst ); -} - static inline void order_rect( RECT *rect ) { if (rect->left > rect->right) diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 1ffb040ae75..2424777970d 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2704,6 +2704,8 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod send_message_timeout( HWND_BROADCAST, WM_DISPLAYCHANGE, current_mode.dmBitsPerPel, MAKELPARAM( current_mode.dmPelsWidth, current_mode.dmPelsHeight ), SMTO_ABORTIFHUNG, 2000, FALSE ); + /* post clip_fullscreen_window request to the foreground window */ + NtUserPostMessage( NtUserGetForegroundWindow(), WM_WINE_CLIPCURSOR, TRUE, TRUE ); }
return ret; @@ -4242,6 +4244,8 @@ void sysparams_init(void)
if (!get_config_key( hkey, appkey, "GrabPointer", buffer, sizeof(buffer) )) grab_pointer = IS_OPTION_TRUE( buffer[0] ); + if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) )) + grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
#undef IS_OPTION_TRUE } diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 3cb5eef6fb1..44baf546182 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -87,6 +87,7 @@ extern void unregister_imm_window( HWND hwnd ) DECLSPEC_HIDDEN;
/* input.c */ extern BOOL grab_pointer DECLSPEC_HIDDEN; +extern BOOL grab_fullscreen DECLSPEC_HIDDEN; extern BOOL destroy_caret(void) DECLSPEC_HIDDEN; extern LONG global_key_state_counter DECLSPEC_HIDDEN; extern HWND get_active_window(void) DECLSPEC_HIDDEN; @@ -102,7 +103,8 @@ extern BOOL set_foreground_window( HWND hwnd, BOOL mouse ) DECLSPEC_HIDDEN; extern void toggle_caret( HWND hwnd ) DECLSPEC_HIDDEN; extern void update_mouse_tracking_info( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL get_clip_cursor( RECT *rect ) DECLSPEC_HIDDEN; -extern BOOL process_wine_clipcursor( BOOL empty, BOOL reset ) DECLSPEC_HIDDEN; +extern BOOL process_wine_clipcursor( HWND hwnd, BOOL empty, BOOL reset ) DECLSPEC_HIDDEN; +extern BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) DECLSPEC_HIDDEN;
/* menu.c */ extern HMENU create_menu( BOOL is_popup ) DECLSPEC_HIDDEN; @@ -183,6 +185,9 @@ extern void user_lock(void) DECLSPEC_HIDDEN; extern void user_unlock(void) DECLSPEC_HIDDEN; extern void user_check_not_lock(void) DECLSPEC_HIDDEN;
+/* winstation.c */ +extern BOOL is_virtual_desktop(void) DECLSPEC_HIDDEN; + /* window.c */ struct tagWND; extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN; @@ -347,4 +352,13 @@ static inline const char *debugstr_color( COLORREF color ) return wine_dbg_sprintf( "RGB(%02x,%02x,%02x)", GetRValue(color), GetGValue(color), GetBValue(color) ); }
+static inline BOOL intersect_rect( RECT *dst, const RECT *src1, const RECT *src2 ) +{ + dst->left = max( src1->left, src2->left ); + dst->top = max( src1->top, src2->top ); + dst->right = min( src1->right, src2->right ); + dst->bottom = min( src1->bottom, src2->bottom ); + return !IsRectEmpty( dst ); +} + #endif /* __WINE_WIN32U_PRIVATE */ diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index 466b2e6262c..049ed111954 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -40,6 +40,19 @@ WINE_DECLARE_DEBUG_CHANNEL(win);
#define DESKTOP_ALL_ACCESS 0x01ff
+BOOL is_virtual_desktop(void) +{ + HANDLE desktop = NtUserGetThreadDesktop( GetCurrentThreadId() ); + USEROBJECTFLAGS flags = {0}; + NTSTATUS status; + DWORD len; + + status = NtUserGetObjectInformation( desktop, UOI_FLAGS, &flags, sizeof(flags), &len ); + if (status) return FALSE; + + return !!(flags.dwFlags & DF_WINE_CREATE_DESKTOP); +} + /*********************************************************************** * NtUserCreateWindowStation (win32u.@) */ diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index b58dc050bd3..8a5682c1acb 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -451,8 +451,5 @@ void X11DRV_resize_desktop(void) send_message_timeout( HWND_BROADCAST, WM_X11DRV_DESKTOP_RESIZED, old_virtual_rect.left, old_virtual_rect.top, SMTO_ABORTIFHUNG, 2000, FALSE );
- /* forward clip_fullscreen_window request to the foreground window */ - send_notify_message( NtUserGetForegroundWindow(), WM_X11DRV_CLIP_CURSOR_REQUEST, TRUE, TRUE ); - old_virtual_rect = virtual_rect; } diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 0e059a94f30..55709a0bc5f 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -780,11 +780,7 @@ static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev )
xim_set_focus( hwnd, TRUE );
- if (use_take_focus) - { - clip_fullscreen_window( hwnd, FALSE ); - return TRUE; - } + if (use_take_focus) return TRUE;
if (!can_activate_window(hwnd)) { diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 00e537cecde..33256e5880c 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -467,7 +467,6 @@ static void ungrab_clipping_window(void) clipping_cursor = FALSE; NtUserDestroyWindow( data->clip_hwnd ); data->clip_hwnd = 0; - data->clip_reset = NtGetTickCount(); disable_xinput2(); }
@@ -485,50 +484,6 @@ void retry_grab_clipping_window(void) NtUserClipCursor( &last_clip_rect ); }
-/*********************************************************************** - * clip_fullscreen_window - * - * Turn on clipping if the active window is fullscreen. - */ -BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) -{ - struct x11drv_win_data *data; - struct x11drv_thread_data *thread_data; - MONITORINFO monitor_info; - HMONITOR monitor; - DWORD style; - BOOL fullscreen; - - if (hwnd == NtUserGetDesktopWindow()) return FALSE; - if (hwnd != NtUserGetForegroundWindow()) return FALSE; - - style = NtUserGetWindowLongW( hwnd, GWL_STYLE ); - if (!(style & WS_VISIBLE)) return FALSE; - if ((style & (WS_POPUP | WS_CHILD)) == WS_CHILD) return FALSE; - /* maximized windows don't count as full screen */ - if ((style & WS_MAXIMIZE) && (style & WS_CAPTION) == WS_CAPTION) return FALSE; - if (!(data = get_win_data( hwnd ))) return FALSE; - fullscreen = NtUserIsWindowRectFullScreen( &data->whole_rect ); - release_win_data( data ); - if (!fullscreen) return FALSE; - if (!(thread_data = x11drv_thread_data())) return FALSE; - if (NtGetTickCount() - thread_data->clip_reset < 1000) return FALSE; - if (!reset && clipping_cursor && thread_data->clip_hwnd) return FALSE; /* already clipping */ - - monitor = NtUserMonitorFromWindow( hwnd, MONITOR_DEFAULTTONEAREST ); - if (!monitor) return FALSE; - monitor_info.cbSize = sizeof(monitor_info); - if (!NtUserGetMonitorInfo( monitor, &monitor_info )) return FALSE; - if (!grab_fullscreen) - { - RECT virtual_rect = NtUserGetVirtualScreenRect(); - if (!EqualRect( &monitor_info.rcMonitor, &virtual_rect )) return FALSE; - if (is_virtual_desktop()) return FALSE; - } - TRACE( "win %p clipping fullscreen\n", hwnd ); - return grab_clipping_window( &monitor_info.rcMonitor ); -} -
/*********************************************************************** * is_old_motion_event @@ -630,9 +585,6 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU last_cursor_change = input->u.mi.time; }
- if (input->u.mi.dwFlags & (MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_RIGHTDOWN)) - clip_fullscreen_window( hwnd, FALSE ); - /* update the wine server Z-order */
if (hwnd != x11drv_thread_data()->grab_hwnd && @@ -1522,50 +1474,11 @@ BOOL X11DRV_GetCursorPos(LPPOINT pos) */ BOOL X11DRV_ClipCursor( const RECT *clip, BOOL reset ) { - TRACE( "clip %p, reset %u\n", clip, reset ); - - if (!reset) - { - RECT virtual_rect = NtUserGetVirtualScreenRect(); - - if (!clip) clip = &virtual_rect; - - /* we are clipping if the clip rectangle is smaller than the screen */ - if (clip->left > virtual_rect.left || clip->right < virtual_rect.right || - clip->top > virtual_rect.top || clip->bottom < virtual_rect.bottom) - { - if (grab_clipping_window( clip )) return TRUE; - } - else /* if currently clipping, check if we should switch to fullscreen clipping */ - { - struct x11drv_thread_data *data = x11drv_thread_data(); - if (data && data->clip_hwnd) - { - if (EqualRect( clip, &clip_rect )) return TRUE; - if (clip_fullscreen_window( NtUserGetForegroundWindow(), TRUE )) return TRUE; - } - } - } + if (!reset && clip && grab_clipping_window( clip )) return TRUE; ungrab_clipping_window(); return TRUE; }
-/*********************************************************************** - * clip_cursor_request - * - * Function called upon receiving a WM_X11DRV_CLIP_CURSOR_REQUEST. - */ -LRESULT clip_cursor_request( HWND hwnd, BOOL fullscreen, BOOL reset ) -{ - if (hwnd == NtUserGetDesktopWindow()) - WARN( "ignoring clip cursor request on desktop window.\n" ); - else if (hwnd != NtUserGetForegroundWindow()) - WARN( "ignoring clip cursor request on non-foreground window.\n" ); - else if (fullscreen) - clip_fullscreen_window( hwnd, reset ); - return 0; -} - /*********************************************************************** * move_resize_window */ diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 3705d337101..e139b06d634 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -3085,8 +3085,6 @@ LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) } return 0; } - case WM_X11DRV_CLIP_CURSOR_REQUEST: - return clip_cursor_request( hwnd, (BOOL)wp, (BOOL)lp ); case WM_X11DRV_DELETE_TAB: taskbar_delete_tab( hwnd ); return 0; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 7cbf40079d2..1055bcc7117 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -389,7 +389,6 @@ struct x11drv_thread_data unsigned long warp_serial; /* serial number of last pointer warp request */ Window clip_window; /* window used for cursor clipping */ HWND clip_hwnd; /* message window stored in desktop while clipping is active */ - DWORD clip_reset; /* time when clipping was last reset */ #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */ void *xi2_devices; /* list of XInput2 devices (valid when state is enabled) */ @@ -588,7 +587,6 @@ enum x11drv_window_messages WM_X11DRV_SET_WIN_REGION, WM_X11DRV_DESKTOP_RESIZED, WM_X11DRV_SET_CURSOR, - WM_X11DRV_CLIP_CURSOR_REQUEST, WM_X11DRV_DELETE_TAB, WM_X11DRV_ADD_TAB }; @@ -682,9 +680,7 @@ extern XContext cursor_context DECLSPEC_HIDDEN; extern void X11DRV_SetFocus( HWND hwnd ) DECLSPEC_HIDDEN; extern void set_window_cursor( Window window, HCURSOR handle ) DECLSPEC_HIDDEN; extern void sync_window_cursor( Window window ) DECLSPEC_HIDDEN; -extern LRESULT clip_cursor_request( HWND hwnd, BOOL fullscreen, BOOL reset ) DECLSPEC_HIDDEN; extern void retry_grab_clipping_window(void) DECLSPEC_HIDDEN; -extern BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) DECLSPEC_HIDDEN; extern void move_resize_window( HWND hwnd, int dir ) DECLSPEC_HIDDEN; extern void X11DRV_InitKeyboard( Display *display ) DECLSPEC_HIDDEN; extern BOOL X11DRV_ProcessEvents( DWORD mask ) DECLSPEC_HIDDEN;
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 tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=133580
Your paranoid android.
=== debian11 (32 bit report) ===
user32: win.c:3764: Test failed: got error 1400