From 84b1fa30f0312ac6f26a91a43693dc41e5c16b7b Mon Sep 17 00:00:00 2001 From: cutealien Date: Thu, 19 Aug 2021 17:25:08 +0000 Subject: [PATCH] Add a workaround for XWarpPointer bug mentioned reported by vikaig (#450) Problem is that the mouse jumps when users have set a coordinate transformation matrix for their mouse on X11. XWarpPointer first sets the correct coordinates, but X11 then moves the mouse wrongly to the scaled position on the next mouse event. On X-Org bugtracker it's this bug: https://gitlab.freedesktop.org/xorg/xserver/-/issues/600 The fix needs compiling with _IRR_LINUX_X11_XINPUT2_ enabled (so far disabled by default) Note: We only use XINPUT2 so far for touch-input... I hope this patch won't conflict with that. Also I mix now IInput2 and X11 functions as getting the mouse-position still uses X11. But seems to work in my tests. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6230 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 3 ++ source/Irrlicht/CIrrDeviceLinux.cpp | 7 +++ source/Irrlicht/CIrrDeviceLinux.h | 66 +++++++++++++++++++++++------ 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/changes.txt b/changes.txt index 501769de..9c27ea15 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,8 @@ -------------------------- Changes in 1.9 (not yet released) +- Add a workaround for XWarpPointer bug that causes mouse to jump when users have set a Coordinate Transformation Matrix for their mouse on X11. + This was mentioned in bug #450 by vikaig. + The fix needs compiling with _IRR_LINUX_X11_XINPUT2_ enabled (so far disabled by default) - Add IGeometryCreator::createTorusMesh to create donuts. - Don't try loading broken image files twice with same loader anymore. - Make CImageLoaderJPG thread safe. Thanks @ Edoardo Lolletti for report and patch (patch #324) diff --git a/source/Irrlicht/CIrrDeviceLinux.cpp b/source/Irrlicht/CIrrDeviceLinux.cpp index 630078aa..b0914f4c 100644 --- a/source/Irrlicht/CIrrDeviceLinux.cpp +++ b/source/Irrlicht/CIrrDeviceLinux.cpp @@ -2154,6 +2154,9 @@ CIrrDeviceLinux::CCursorControl::CCursorControl(CIrrDeviceLinux* dev, bool null) : Device(dev) #ifdef _IRR_COMPILE_WITH_X11_ , PlatformBehavior(gui::ECPB_NONE), LastQuery(0) +#ifdef _IRR_LINUX_X11_XINPUT2_ + , DeviceId(0) +#endif #endif , IsVisible(true), Null(null), UseReferenceRect(false) , ActiveIcon(gui::ECI_NORMAL), ActiveIconStartTime(0) @@ -2161,6 +2164,10 @@ CIrrDeviceLinux::CCursorControl::CCursorControl(CIrrDeviceLinux* dev, bool null) #ifdef _IRR_COMPILE_WITH_X11_ if (!Null) { +#ifdef _IRR_LINUX_X11_XINPUT2_ + XIGetClientPointer(Device->XDisplay, Device->XWindow, &DeviceId); +#endif + XGCValues values; unsigned long valuemask = 0; diff --git a/source/Irrlicht/CIrrDeviceLinux.h b/source/Irrlicht/CIrrDeviceLinux.h index 64e95c13..ee71ca1c 100644 --- a/source/Irrlicht/CIrrDeviceLinux.h +++ b/source/Irrlicht/CIrrDeviceLinux.h @@ -37,6 +37,10 @@ #endif #include +#ifdef _IRR_LINUX_X11_XINPUT2_ +#include +#endif + #else #define KeySym s32 #endif @@ -224,22 +228,54 @@ namespace irr { if (UseReferenceRect) { - XWarpPointer(Device->XDisplay, - None, - Device->XWindow, 0, 0, - Device->Width, - Device->Height, - ReferenceRect.UpperLeftCorner.X + x, - ReferenceRect.UpperLeftCorner.Y + y); - +// NOTE: XIWarpPointer works when X11 has set a coordinate transformation matrix for the mouse unlike XWarpPointer +// which runs into a bug mentioned here: https://gitlab.freedesktop.org/xorg/xserver/-/issues/600 +// So also workaround for Irrlicht bug #450 +#ifdef _IRR_LINUX_X11_XINPUT2_ + if ( DeviceId != 0) + { + XIWarpPointer(Device->XDisplay, + DeviceId, + None, + Device->XWindow, 0, 0, + Device->Width, + Device->Height, + ReferenceRect.UpperLeftCorner.X + x, + ReferenceRect.UpperLeftCorner.Y + y); + } + else +#endif + { + XWarpPointer(Device->XDisplay, + None, + Device->XWindow, 0, 0, + Device->Width, + Device->Height, + ReferenceRect.UpperLeftCorner.X + x, + ReferenceRect.UpperLeftCorner.Y + y); + } } else { - XWarpPointer(Device->XDisplay, - None, - Device->XWindow, 0, 0, - Device->Width, - Device->Height, x, y); +#ifdef _IRR_LINUX_X11_XINPUT2_ + if ( DeviceId != 0) + { + XIWarpPointer(Device->XDisplay, + DeviceId, + None, + Device->XWindow, 0, 0, + Device->Width, + Device->Height, x, y); + } + else +#endif + { + XWarpPointer(Device->XDisplay, + None, + Device->XWindow, 0, 0, + Device->Width, + Device->Height, x, y); + } } XFlush(Device->XDisplay); } @@ -353,6 +389,10 @@ namespace irr u32 LastQuery; Cursor InvisCursor; +#ifdef _IRR_LINUX_X11_XINPUT2_ + int DeviceId; +#endif + struct CursorFrameX11 { CursorFrameX11() : IconHW(0) {}