XWayland only allows warping the cursor if it is not visible. Fixes a regression from the periodic cursor sync removal.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/clipboard.c | 26 ++------------ dlls/winex11.drv/x11drv.h | 2 ++ dlls/winex11.drv/x11drv_main.c | 63 ++++++++++++++++++++++++++++++++++ dlls/winex11.drv/xfixes.h | 36 +++++++++++++++++++ 4 files changed, 103 insertions(+), 24 deletions(-) create mode 100644 dlls/winex11.drv/xfixes.h
diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c index 04b34660331..d2dcb03f8c2 100644 --- a/dlls/winex11.drv/clipboard.c +++ b/dlls/winex11.drv/clipboard.c @@ -83,6 +83,7 @@ #include "ntstatus.h" #define WIN32_NO_STATUS #include "x11drv.h" +#include "xfixes.h"
#ifdef HAVE_X11_EXTENSIONS_XFIXES_H #include <X11/extensions/Xfixes.h> @@ -199,7 +200,6 @@ static UINT rendered_formats; static ULONG last_clipboard_update; static struct clipboard_format **current_x11_formats; static unsigned int nb_current_x11_formats; -static BOOL use_xfixes;
Display *clipboard_display = NULL;
@@ -2170,28 +2170,6 @@ static BOOL selection_notify_event( HWND hwnd, XEvent *event ) static void xfixes_init(void) { #ifdef SONAME_LIBXFIXES - typeof(XFixesSelectSelectionInput) *pXFixesSelectSelectionInput; - typeof(XFixesQueryExtension) *pXFixesQueryExtension; - typeof(XFixesQueryVersion) *pXFixesQueryVersion; - - int event_base, error_base; - int major = 3, minor = 0; - void *handle; - - handle = dlopen(SONAME_LIBXFIXES, RTLD_NOW); - if (!handle) return; - - pXFixesQueryExtension = dlsym(handle, "XFixesQueryExtension"); - if (!pXFixesQueryExtension) return; - pXFixesQueryVersion = dlsym(handle, "XFixesQueryVersion"); - if (!pXFixesQueryVersion) return; - pXFixesSelectSelectionInput = dlsym(handle, "XFixesSelectSelectionInput"); - if (!pXFixesSelectSelectionInput) return; - - if (!pXFixesQueryExtension(clipboard_display, &event_base, &error_base)) - return; - pXFixesQueryVersion(clipboard_display, &major, &minor); - use_xfixes = (major >= 1); if (!use_xfixes) return;
pXFixesSelectSelectionInput(clipboard_display, import_window, x11drv_atom(CLIPBOARD), @@ -2205,7 +2183,7 @@ static void xfixes_init(void) XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask); } - X11DRV_register_event_handler(event_base + XFixesSelectionNotify, + X11DRV_register_event_handler(xfixes_event_base + XFixesSelectionNotify, selection_notify_event, "XFixesSelectionNotify"); TRACE("xfixes succesully initialized\n"); #else diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 8e383ae4c48..20261d6f914 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -448,12 +448,14 @@ extern BOOL use_primary_selection; extern BOOL use_system_cursors; extern BOOL grab_fullscreen; extern BOOL usexcomposite; +extern BOOL use_xfixes; extern BOOL managed_mode; extern BOOL private_color_map; extern int primary_monitor; extern int copy_default_colors; extern int alloc_system_colors; extern int xrender_error_base; +extern int xfixes_event_base; extern char *process_name; extern Display *clipboard_display;
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index e58d3afca63..4a7885ca0e0 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -47,6 +47,7 @@ #include "x11drv.h" #include "winreg.h" #include "xcomposite.h" +#include "xfixes.h" #include "wine/server.h" #include "wine/debug.h" #include "wine/list.h" @@ -68,6 +69,7 @@ Window root_window; BOOL usexvidmode = TRUE; BOOL usexrandr = TRUE; BOOL usexcomposite = TRUE; +BOOL use_xfixes = FALSE; BOOL use_take_focus = TRUE; BOOL use_primary_selection = FALSE; BOOL use_system_cursors = TRUE; @@ -81,6 +83,7 @@ BOOL shape_layered_windows = TRUE; int copy_default_colors = 128; int alloc_system_colors = 256; int xrender_error_base = 0; +int xfixes_event_base = 0; char *process_name = NULL;
static x11drv_error_callback err_callback; /* current callback for error */ @@ -559,6 +562,63 @@ sym_not_found: } #endif /* defined(SONAME_LIBXCOMPOSITE) */
+#ifdef SONAME_LIBXFIXES + +#define MAKE_FUNCPTR(f) typeof(f) * p##f; +MAKE_FUNCPTR(XFixesQueryExtension) +MAKE_FUNCPTR(XFixesQueryVersion) +MAKE_FUNCPTR(XFixesCreateRegion) +MAKE_FUNCPTR(XFixesCreateRegionFromGC) +MAKE_FUNCPTR(XFixesSelectSelectionInput) +#undef MAKE_FUNCPTR + +static void x11drv_load_xfixes(void) +{ + int event, error, major = 3, minor = 0; + void *xfixes; + + if (!(xfixes = dlopen(SONAME_LIBXFIXES, RTLD_NOW))) + { + WARN("Xfixes library %s not found, disabled.\n", SONAME_LIBXFIXES); + return; + } + +#define LOAD_FUNCPTR(f) \ + if (!(p##f = dlsym(xfixes, #f))) \ + { \ + WARN("Xfixes function %s not found, disabled\n", #f); \ + dlclose(xfixes); \ + return; \ + } + LOAD_FUNCPTR(XFixesQueryExtension) + LOAD_FUNCPTR(XFixesQueryVersion) + LOAD_FUNCPTR(XFixesCreateRegion) + LOAD_FUNCPTR(XFixesCreateRegionFromGC) + LOAD_FUNCPTR(XFixesSelectSelectionInput) +#undef LOAD_FUNCPTR + + if (!pXFixesQueryExtension(gdi_display, &event, &error)) + { + WARN("Xfixes extension not found, disabled.\n"); + dlclose(xfixes); + return; + } + + if (!pXFixesQueryVersion(gdi_display, &major, &minor) || + major < 2) + { + WARN("Xfixes version 2.0 not found, disabled.\n"); + dlclose(xfixes); + return; + } + + TRACE("Xfixes, error %d, event %d, version %d.%d found\n", + error, event, major, minor); + use_xfixes = TRUE; + xfixes_event_base = event; +} +#endif /* SONAME_LIBXFIXES */ + static void init_visuals( Display *display, int screen ) { int count; @@ -661,6 +721,9 @@ static NTSTATUS x11drv_init( void *arg ) X11DRV_XF86VM_Init(); /* initialize XRandR */ X11DRV_XRandR_Init(); +#ifdef SONAME_LIBXFIXES + x11drv_load_xfixes(); +#endif #ifdef SONAME_LIBXCOMPOSITE X11DRV_XComposite_Init(); #endif diff --git a/dlls/winex11.drv/xfixes.h b/dlls/winex11.drv/xfixes.h new file mode 100644 index 00000000000..f3beea5efed --- /dev/null +++ b/dlls/winex11.drv/xfixes.h @@ -0,0 +1,36 @@ +/* + * Wine X11DRV Xfixes interface + * + * Copyright 2021 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#ifndef __WINE_XFIXES_H +#define __WINE_XFIXES_H + +#ifndef __WINE_CONFIG_H +# error You must include config.h to use this header +#endif + +#ifdef SONAME_LIBXFIXES +#include <X11/extensions/Xfixes.h> +#define MAKE_FUNCPTR(f) extern typeof(f) * p##f; +MAKE_FUNCPTR(XFixesQueryExtension) +MAKE_FUNCPTR(XFixesQueryVersion) +MAKE_FUNCPTR(XFixesSelectSelectionInput) +#undef MAKE_FUNCPTR +#endif /* defined(SONAME_LIBXFIXES) */ + +#endif /* __WINE_XFIXES_H */
From: Rémi Bernon rbernon@codeweavers.com
XWayland only allows warping the cursor if it is not visible. Fixes a regression from the periodic cursor sync removal. --- dlls/winex11.drv/mouse.c | 3 +++ dlls/winex11.drv/x11drv_main.c | 4 ++++ dlls/winex11.drv/xfixes.h | 2 ++ 3 files changed, 9 insertions(+)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 9d25b71c992..a98a8ac4add 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -51,6 +51,7 @@ MAKE_FUNCPTR(XcursorLibraryLoadCursor); #define OEMRESOURCE
#include "x11drv.h" +#include "xfixes.h" #include "winreg.h" #include "wine/server.h" #include "wine/debug.h" @@ -1400,8 +1401,10 @@ BOOL X11DRV_SetCursorPos( INT x, INT y ) return FALSE; }
+ if (use_xfixes) pXFixesHideCursor( data->display, root_window ); XWarpPointer( data->display, root_window, root_window, 0, 0, 0, 0, pos.x, pos.y ); data->warp_serial = NextRequest( data->display ); + if (use_xfixes) pXFixesShowCursor( data->display, root_window );
if (!clipping_cursor) XUngrabPointer( data->display, CurrentTime ); diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 4a7885ca0e0..f3106b8832f 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -565,11 +565,13 @@ sym_not_found: #ifdef SONAME_LIBXFIXES
#define MAKE_FUNCPTR(f) typeof(f) * p##f; +MAKE_FUNCPTR(XFixesHideCursor) MAKE_FUNCPTR(XFixesQueryExtension) MAKE_FUNCPTR(XFixesQueryVersion) MAKE_FUNCPTR(XFixesCreateRegion) MAKE_FUNCPTR(XFixesCreateRegionFromGC) MAKE_FUNCPTR(XFixesSelectSelectionInput) +MAKE_FUNCPTR(XFixesShowCursor) #undef MAKE_FUNCPTR
static void x11drv_load_xfixes(void) @@ -590,11 +592,13 @@ static void x11drv_load_xfixes(void) dlclose(xfixes); \ return; \ } + LOAD_FUNCPTR(XFixesHideCursor) LOAD_FUNCPTR(XFixesQueryExtension) LOAD_FUNCPTR(XFixesQueryVersion) LOAD_FUNCPTR(XFixesCreateRegion) LOAD_FUNCPTR(XFixesCreateRegionFromGC) LOAD_FUNCPTR(XFixesSelectSelectionInput) + LOAD_FUNCPTR(XFixesShowCursor) #undef LOAD_FUNCPTR
if (!pXFixesQueryExtension(gdi_display, &event, &error)) diff --git a/dlls/winex11.drv/xfixes.h b/dlls/winex11.drv/xfixes.h index f3beea5efed..6cd4e48425b 100644 --- a/dlls/winex11.drv/xfixes.h +++ b/dlls/winex11.drv/xfixes.h @@ -27,9 +27,11 @@ #ifdef SONAME_LIBXFIXES #include <X11/extensions/Xfixes.h> #define MAKE_FUNCPTR(f) extern typeof(f) * p##f; +MAKE_FUNCPTR(XFixesHideCursor) MAKE_FUNCPTR(XFixesQueryExtension) MAKE_FUNCPTR(XFixesQueryVersion) MAKE_FUNCPTR(XFixesSelectSelectionInput) +MAKE_FUNCPTR(XFixesShowCursor) #undef MAKE_FUNCPTR #endif /* defined(SONAME_LIBXFIXES) */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/mouse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index a98a8ac4add..dd4f8378415 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -1601,7 +1601,7 @@ BOOL X11DRV_MotionNotify( HWND hwnd, XEvent *xev ) input.mi.time = EVENT_x11_time_to_win32_time( event->time ); input.mi.dwExtraInfo = 0;
- if (!hwnd && is_old_motion_event( event->serial )) + if (is_old_motion_event( event->serial )) { TRACE( "pos %d,%d old serial %lu, ignoring\n", event->x, event->y, event->serial ); return FALSE;
Does this pave the way for other XWayland workarounds? I'm already thinking of one for CDS function
Is this wrong for some reason? Fwiw XWayland implements pointer warping with Wayland pointer lock protocol, it'll only work within the window that is focused anyway so this shouldn't risk causing spurious pointer motion.
This sounds like something that should be fixed in XWayland.
This merge request was closed by Rémi Bernon.
Reopening because it doesn't seem like XWayland is interested in an easy fix and would rather wait for an hypothetical better Wayland protocol. See https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1839 which has been nacked right away.