In Wayland, a client (in this case XWayland) should set the cursor surface when it receives pointer focus. Not doing this will leave the curser at whatever it was previously.
When running on XWayland, the X server will not be the entity that controls what actual pointer cursor is displayed, and it wont be notified about the pointer cursor changes done by the Wayland compositor. This causes X11 clients running via XWayland to end up with incorrect pointer cursors because the X server believes that, if the cursor was previously set to the cursor C, if we receive Wayland pointer focus over window W which also has the pointer cursor C, we do not need to update it. This will cause us to end up with the wrong cursor if cursor C was not the same one that was already set by the Wayland compositor. This patch introduces new API to mi/ to make it possible for a XWayland to trigger resetting of the pointer cursor sprite the next time dix asks it to display one. XWayland will now call this function upon receiving pointer focus, making sure that subsequent calls will trigger resetting of the pointer cursor sprite. Signed-off-by: Jonas Ådahl <[email protected]> --- Hi, This is the second version. In this patch I avoid poking at dix/ because it not needed thanks to PATCH 1/2 in this series. I still don't wrap the DisplayCursor vfunc, because the problem is still that only on enter do I want to force-trigger updating the cursor on wl_pointer.enter, and I can't cause mipointer.c to do that without new API and state, and there is setting a state in xwayland letting a wrapped DisplayCursor do that when one can do it up front before calling CheckMotion(). As mentioned, a different approach would be to work-around the issue in xwayland, but I consider such a solution more hacky than this. Please let me know what you think. Jonas hw/xwayland/xwayland-input.c | 6 +++++- mi/mipointer.c | 12 +++++++++++- mi/mipointer.h | 3 +++ mi/mipointrst.h | 1 + 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 010d28c..0c466c1 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -32,6 +32,7 @@ #include <xkbsrv.h> #include <xserver-properties.h> #include <inpututils.h> +#include <mipointer.h> static void xwl_pointer_control(DeviceIntPtr device, PtrCtrl *ctrl) @@ -210,6 +211,7 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer, { struct xwl_seat *xwl_seat = data; DeviceIntPtr dev = xwl_seat->pointer; + DeviceIntPtr master; int i; int sx = wl_fixed_to_int(sx_w); int sy = wl_fixed_to_int(sy_w); @@ -230,8 +232,10 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer, xwl_seat->focus_window = wl_surface_get_user_data(surface); + master = GetMaster(dev, POINTER_OR_FLOAT); (*pScreen->SetCursorPosition) (dev, pScreen, sx, sy, TRUE); - CheckMotion(NULL, GetMaster(dev, POINTER_OR_FLOAT)); + miPointerInvalidateCursor(master); + CheckMotion(NULL, master); /* Ideally, X clients shouldn't see these button releases. When * the pointer leaves a window with buttons down, it means that diff --git a/mi/mipointer.c b/mi/mipointer.c index ada1ab5..1afba24 100644 --- a/mi/mipointer.c +++ b/mi/mipointer.c @@ -389,6 +389,14 @@ miPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) UpdateSpriteForScreen(pDev, pScreen); } +void +miPointerInvalidateCursor(DeviceIntPtr pDev) +{ + miPointerPtr pPointer = MIPOINTER(pDev); + + pPointer->cursorInvalidated = TRUE; +} + /** * Syncronize the sprite with the cursor. * @@ -448,7 +456,8 @@ miPointerUpdateSprite(DeviceIntPtr pDev) /* * if the cursor has changed, display the new one */ - else if (pPointer->pCursor != pPointer->pSpriteCursor) { + else if (pPointer->pCursor != pPointer->pSpriteCursor || + pPointer->cursorInvalidated) { pCursor = pPointer->pCursor; if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)) @@ -465,6 +474,7 @@ miPointerUpdateSprite(DeviceIntPtr pDev) if (pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); } + pPointer->cursorInvalidated = FALSE; } /** diff --git a/mi/mipointer.h b/mi/mipointer.h index bdeed12..ef5e082 100644 --- a/mi/mipointer.h +++ b/mi/mipointer.h @@ -91,6 +91,9 @@ extern _X_EXPORT void miPointerWarpCursor(DeviceIntPtr /*pDev */ , int /*y */ ); +extern _X_EXPORT void miPointerInvalidateCursor(DeviceIntPtr /*pDev */ + ); + extern _X_EXPORT ScreenPtr miPointerGetScreen(DeviceIntPtr pDev); extern _X_EXPORT void diff --git a/mi/mipointrst.h b/mi/mipointrst.h index 104e45c..38a9f6f 100644 --- a/mi/mipointrst.h +++ b/mi/mipointrst.h @@ -44,6 +44,7 @@ typedef struct { int x, y; /* hot spot location */ int devx, devy; /* sprite position */ Bool generateEvent; /* generate an event during warping? */ + Bool cursorInvalidated; /* update cursor even if it didn't change */ } miPointerRec, *miPointerPtr; typedef struct { -- 2.4.3 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
