CoordinateTransformationMatrix causes mouse to jump to near upper-left corner sometimes
Summary
If a non-default Coordinate Transformation Matrix is specified for a mouse, then a number of circumstances cause the mouse to unexpectedly jump near the top-left corner of the screen upon the next mouse input event:
- When i3wm teleports the mouse, either to another monitor when following window focus or when resizing windows
- When the mouse cursor is unhidden/undisabled in LWJGL, such as in Minecraft (e.g. pause menu or inventory screen)
- Probably other scenarios
Steps to reproduce
Using i3wm (resizing windows):
- Set a non-default CoordinateTransformationMatrix for the mouse device; e.g.
1 0 0 0 1 0 0 0 2
- Open two windows tiled side-by-side (Mod+Enter opens a terminal by default, where "Mod" is either Super or Alt)
- Hold the Mod key (Super or Alt) while right-click-dragging between the two to resize them
- i3wm teleports the mouse to be directly between the two windows, as expected
- Note that when the mouse released or is first moved while dragging, the cursor immediately jumps to a location near the upper-left corner of the screen
Using i3wm (multi-monitor):
- Set a non-default CoordinateTransformationMatrix for the mouse device; e.g.
1 0 0 0 1 0 0 0 2
- Ensure that
mouse_warping output
is present in the i3wm configuration (this is the default behavior) - Use the keyboard to shift window focus between monitors; the mouse should follow
- Move the mouse slightly
- Note that when the mouse is first moved, the cursor immediately jumps to a location near the upper-left corner of the screen
Using Minecraft:
- Set a non-default CoordinateTransformationMatrix for the mouse device; e.g.
1 0 0 0 1 0 0 0 2
- Open Minecraft >=1.13 (tested using snapshot 19w04b; untested in Minecraft <1.13 before LWJGL3)
- Enter a world
- Open the pause menu or inventory screen
- Move the mouse slightly
- Note that when the mouse is first moved, the cursor immediately jumps to a location near the upper-left corner of the screen
Using a custom-made LWJGL demo:
- Set a non-default CoordinateTransformationMatrix for the mouse device; e.g.
1 0 0 0 1 0 0 0 2
- Ensure that Maven is installed along with some version of the JDK
- Clone, compile, and run
https://github.com/HactarCE/lwjgl3-demos
:
git clone https://github.com/HactarCE/lwjgl3-demos \
&& cd lwjgl3-demos \
&& mvn package \
&& java -jar target/lwjgl3-demos.jar \
- Press
z
to "disable" the cursor, then pressx
orc
to undisable it - Move the mouse slightly
- Note that when the mouse is first moved, the cursor immediately jumps to a location near the upper-left corner of the screen
Further information
I originally submitted this bug here on Libinput's issue tracker, but was deferred here as this was deemed to most likely be a bug with Xorg.
Another user has posted about this issue on the Unix & Linux Stack Exchange, describing similar behavior:
What happens, is that when I hit any key that gives me back my cursor, as soon as I move my mouse, the cursor jumps to the top left quadrant of my screen. The exact position is proportional to the scaling number I use, so .25 moves the cursor closer to the corner than .45. Moreover, if I use a value greater than 1, the cursor moves to a different quadrant of my monitor. And, of course, values of 1 leave the cursor in the center of the screen as expected. This just happens on the first mouse input, and the mouse behaves normally after that.
This is exactly what I am seeing as well. Note that the issue only seems to occur in the demo when the pointer is "disabled" with z
(hidden + captured) and then undisabled with x
or c
; pressing x
to "hide" the cursor and c
to unhide it does not cause the problem.
Hardware information:
» xinput
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ Logitech Gaming Mouse G600 id=8 [slave pointer (2)]
⎜ ↳ ckb1: Corsair K70 RGB Gaming Keyboard vKB id=10 [slave pointer (2)]
⎜ ↳ ckb1: Corsair K70 RGB Gaming Keyboard vM id=12 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Power Button id=7 [slave keyboard (3)]
↳ Logitech Gaming Mouse G600 Keyboard id=9 [slave keyboard (3)]
↳ ckb1: Corsair K70 RGB Gaming Keyboard vKB id=11 [slave keyboard (3)]
↳ ckb1: Corsair K70 RGB Gaming Keyboard vM id=13 [slave keyboard (3)]
» xinput list-props 8
Device 'Logitech Gaming Mouse G600':
Device Enabled (153): 1
Coordinate Transformation Matrix (155): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 2.500000
libinput Natural Scrolling Enabled (290): 0
libinput Natural Scrolling Enabled Default (291): 0
libinput Scroll Methods Available (292): 0, 0, 1
libinput Scroll Method Enabled (293): 0, 0, 0
libinput Scroll Method Enabled Default (294): 0, 0, 0
libinput Button Scrolling Button (295): 2
libinput Button Scrolling Button Default (296): 2
libinput Middle Emulation Enabled (297): 0
libinput Middle Emulation Enabled Default (298): 0
libinput Accel Speed (299): 0.800000
libinput Accel Speed Default (300): 0.000000
libinput Accel Profiles Available (301): 1, 1
libinput Accel Profile Enabled (302): 1, 0
libinput Accel Profile Enabled Default (303): 1, 0
libinput Left Handed Enabled (304): 0
libinput Left Handed Enabled Default (305): 0
libinput Send Events Modes Available (275): 1, 0
libinput Send Events Mode Enabled (276): 0, 0
libinput Send Events Mode Enabled Default (277): 0, 0
Device Node (278): "/dev/input/event3"
Device Product ID (279): 1133, 49738
libinput Drag Lock Buttons (306): <no items>
libinput Horizontal Scroll Enabled (307): 1
Other log output:
-
libinput record
output (using Minecraft): libinput-mouse-capture-and-release-record.txt -
libinput debug-events --verbose
output (using LWJGL demo): libinput-mouse-capture-and-release-debug-events.txt
I have added some comments beginning with ####
to the above files to identify where I "disabled"/undisabled the cursor.