win32u: Move fullscreen window cursor clipping from winex11.

This commit is contained in:
Rémi Bernon 2023-06-08 08:51:47 +02:00 committed by Alexandre Julliard
parent b1d273bba3
commit af902c188e
11 changed files with 103 additions and 121 deletions

View file

@ -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:
if (hwnd) 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;

View file

@ -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)

View file

@ -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)

View file

@ -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
}

View file

@ -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 */

View file

@ -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.@)
*/

View file

@ -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;
}

View file

@ -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))
{

View file

@ -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
*/

View file

@ -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;

View file

@ -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;