Synergy-core: Non-identity Coordinate Transformation Matrix confuses pointer warping on X11

Created on 20 Apr 2016  Â·  20Comments  Â·  Source: symless/synergy-core

Under X11, devices have a "Coordinate Transformation Matrix" property that is often used by applications to restrict devices with absolute input (e.g. a touchscreen or Wacom tablet) to a single monitor. Coordinates reported by the device are multiplied by the transformation matrix as a final step before the X server actually moves the cursor in response to device movement.

It appears that Synergy's pointer warping code does not work as expected when this property is set. Specifically, it appears that when using my Wacom tablet "puck" in relative mode with a transformation matrix of "0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0" (as set by the GNOME Control Center after mapping the tablet to one of my displays) a series of events like the following will be produced:

# Move puck to the left on the server
[2016-04-20T08:45:44] DEBUG2: event: MotionNotify 26,426
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
[2016-04-20T08:45:44] DEBUG2: event: MotionNotify 19,428
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
[2016-04-20T08:45:44] DEBUG2: event: MotionNotify 12,431
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
[2016-04-20T08:45:45] DEBUG2: event: MotionNotify 6,434
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
[2016-04-20T08:45:45] DEBUG2: event: MotionNotify 0,436
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
[2016-04-20T08:45:45] DEBUG2: find neighbor on left of "linux-server"
        /build/synergy/src/synergy-1.7.6-stable/src/lib/server/Server.cpp,612
[2016-04-20T08:45:45] DEBUG2: "linux-client" is on left of "linux-server" at 0.363750
        /build/synergy/src/synergy-1.7.6-stable/src/lib/server/Server.cpp,635
[2016-04-20T08:45:45] DEBUG1: try to leave "linux-server" on left
        /build/synergy/src/synergy-1.7.6-stable/src/lib/server/Server.cpp,809
...
# Warps cursor to center of monitor and enters client from right
[2016-04-20T08:45:45] DEBUG2: warped to 960,600
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1947
[2016-04-20T08:45:45] DEBUG1: send enter to "linux-client", 1599,327 1 2000
        /build/synergy/src/synergy-1.7.6-stable/src/lib/server/ClientProxy1_0.cpp,260
...
# Motion events and warps occur as I continue moving puck left
[2016-04-20T08:45:45] DEBUG2: event: MotionNotify 433,608
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
[2016-04-20T08:45:45] DEBUG2: warped to 960,600
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1947
[2016-04-20T08:45:45] DEBUG2: event: MotionNotify 474,600
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
[2016-04-20T08:45:45] DEBUG2: warped to 960,600
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1947
[2016-04-20T08:45:45] DEBUG2: event: MotionNotify 960,600
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
[2016-04-20T08:45:45] DEBUG2: event: MotionNotify 470,601
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
[2016-04-20T08:45:45] DEBUG2: warped to 960,600
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1947
[2016-04-20T08:45:45] DEBUG2: event: MotionNotify 960,600
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
[2016-04-20T08:45:45] DEBUG2: event: MotionNotify 465,602
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
[2016-04-20T08:45:45] DEBUG2: warped to 960,600
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1947
[2016-04-20T08:45:45] DEBUG2: event: MotionNotify 960,600
        /build/synergy/src/synergy-1.7.6-stable/src/lib/platform/XWindowsScreen.cpp,1592
...
# Server sends events off to the client
[2016-04-20T08:45:45] DEBUG2: onMouseMoveSecondary -527,+8
        /build/synergy/src/synergy-1.7.6-stable/src/lib/server/Server.cpp,1873
[2016-04-20T08:45:45] DEBUG2: onMouseMoveSecondary +41,-8
        /build/synergy/src/synergy-1.7.6-stable/src/lib/server/Server.cpp,1873
[2016-04-20T08:45:45] DEBUG2: onMouseMoveSecondary +486,+0
        /build/synergy/src/synergy-1.7.6-stable/src/lib/server/Server.cpp,1873
[2016-04-20T08:45:45] DEBUG2: onMouseMoveSecondary -490,+1
        /build/synergy/src/synergy-1.7.6-stable/src/lib/server/Server.cpp,1873
[2016-04-20T08:45:45] DEBUG2: onMouseMoveSecondary +490,-1
        /build/synergy/src/synergy-1.7.6-stable/src/lib/server/Server.cpp,1873
[2016-04-20T08:45:45] DEBUG2: onMouseMoveSecondary -495,+2
        /build/synergy/src/synergy-1.7.6-stable/src/lib/server/Server.cpp,1873
[2016-04-20T08:45:45] DEBUG2: onMouseMoveSecondary +495,-2
        /build/synergy/src/synergy-1.7.6-stable/src/lib/server/Server.cpp,1873

It appears that the X server passes the warped coordinate (960,600) through the transformation matrix, causing it to "think" the pointer is actually at (480,600). When a relative motion occurs, the next event is reported based on that assumption, but the Synergy server still believes it to be at (960,600). The result is that massive deltas are sent to the Synergy client, and often (though it cannot be seen in the trace above) ends up causing the pointer to become pinned to the left-hand side of the client.

I'm not sure if Synergy should be taking the transformation matrix into account when warping the pointer, or if the X server should /not/ be taking it into account, but either way setting the matrix back to identity "1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0" prevents the bug from being triggered.

bug

All 20 comments

I experienced this bug as well, but for different reasons. In order to fix pointer speed issues with my Trackpoint, I set the matrix up to scale up the input as recommended in this Stack Exchange post:

xinput --set-prop 'TPPS/2 IBM TrackPoint' 143 5.00000, 0.000000, 0.000000, 0.000000, 5.00000, 0.000000, 0.000000, 0.000000, 1.000000

When using the trackpoint with the non-identity matrix, the cursor becomes invisible/moves to a weird location when the pointer is on a client which is to the right of the primary display. Using the computer's touchpad without the matrix works fine on the same client.

Stumbled on this myself after I have to change:

#xinput set-prop "Razer Razer DeathAdder" "Device Accel Constant Deceleration" 10
xinput set-prop "Razer Razer DeathAdder" "Coordinate Transformation Matrix" 1, 0, 0, 0, 1, 0, 0, 0, 10

Device Accel Constant Deceleration no longer exists on my new version of xorg.
I spent a few hours trying to hack it around. The hack which worked for me:

warp.patch.txt

diff --git a/src/lib/platform/XWindowsScreen.cpp b/src/lib/platform/XWindowsScreen.cpp
index eab8be0..93696b6 100644
--- a/src/lib/platform/XWindowsScreen.cpp
+++ b/src/lib/platform/XWindowsScreen.cpp
@@ -33,6 +33,7 @@
 #include "base/String.h"
 #include "base/IEventQueue.h"
 #include "base/TMethodEventJob.h"
+#include <X11/extensions/XInput2.h>

 #include <cstring>
 #include <cstdlib>
@@ -1940,6 +1941,11 @@ XWindowsScreen::warpCursorNoFlush(SInt32 x, SInt32 y)

        // warp mouse
        XWarpPointer(m_display, None, m_root, 0, 0, 0, 0, x, y);
+       int device_id;
+       XISetClientPointer(m_display, None, 2 /* Virtual core pointer id from 'xinput' tool*/);
+        if (XIGetClientPointer(m_display, None, &device_id) != False) {
+          XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, 0, 0);
+        }

        // send an event that we can recognize after the mouse warp
        XSendEvent(m_display, m_window, False, 0, &eventAfter);

Well, my previous patch has one big problem - sometimes cursor randomly jumps, which is really bad for gaming. Here is another one which works very reliably for me.

warp.patch3.txt

I tried your patch and it breaks functionality when using a linux host and a windows client. My mouse no longer enters the new screen, it just stays on the server.

It works again if I don#t remove the HAVE_XI2 block, but the mouse is jumpy / jittering then.

warp_patch4.txt
Sorry, I haven't updated the bug. I also got the jumpy behaviour, so I have to rework my patch (attached, warp_patch4.txt) which works in games flawlessly for me for a few months. It has some unrelated changes in a few other places to fix the compilation of my pretty dated version of synergy (synergy-1.6.3).

Looking at the code now I find it quite messy and it feels like there is a small bug there in a discard loop. So, I just made a slightly tweaked version and I'm testing it now:
warp_patch5.txt

I'm also using custom options to switch between screens using keyboard instead of mouse. So I didn't try if it actually works with edge switching. Here is the options from my config file:

section: options
    relativeMouseMoves = true
    keystroke(KP_Add) = switchToScreen(vm)
    keystroke(KP_Subtract) = switchToScreen(pc)

I tried your warp patch No. 5 now. It works for me in a short test. Though no screen-edge-switching.
I mainly use that method so I guess I'll dig into why that doesn't work.

Why does your patch remove

#ifdef HAVE_XI2
    if (m_xi2detected) {
        // Process RawMotion
        XGenericEventCookie *cookie = (XGenericEventCookie*)&xevent->xcookie;
            if (XGetEventData(m_display, cookie) &&
                cookie->type == GenericEvent &&
                cookie->extension == xi_opcode) {
            if (cookie->evtype == XI_RawMotion) {
                // Get current pointer's position
                Window root, child;
                XMotionEvent xmotion;
                xmotion.type = MotionNotify;
                xmotion.send_event = False; // Raw motion
                xmotion.display = m_display;
                xmotion.window = m_window;
                /* xmotion's time, state and is_hint are not used */
                unsigned int msk;
                    xmotion.same_screen = XQueryPointer(
                        m_display, m_root, &xmotion.root, &xmotion.subwindow,
                        &xmotion.x_root,
                        &xmotion.y_root,
                        &xmotion.x,
                        &xmotion.y,
                        &msk);
                    xevent->xmotion = xmotion;
                    onMouseMove(xevent);
                    XFreeEventData(m_display, cookie);
                    return;
                //LOG((CLOG_DEBUG2 "would do thing."));

            }
                XFreeEventData(m_display, cookie);
        }
    }
#endif

Without it, I don't see log outputs like

[2018-11-13T20:59:54] DEBUG2: event: MotionNotify 571,771
    /home/marenz/projects/synergy-core/src/lib/platform/XWindowsScreen.cpp,1595
[2018-11-13T20:59:54] DEBUG2: event: MotionNotify 571,771
    /home/marenz/projects/synergy-core/src/lib/platform/XWindowsScreen.cpp,1595
[2018-11-13T20:59:54] DEBUG2: event: MotionNotify 571,772

while moving the mouse on the primary screen. I suppose that is important to detect when it is getting near the edge.

Your patch seems to make it that we don't track the mouse at all any more as long as we're focused on the servers' screen.

Putting it back in as-is is also not working though as the mouse is alternating between two positions then (on the client screen)

So, if I add that code back and add the additional condition

    if (xmotion.send_event && m_waitForWarp) {

then the edge-detection works again. However, the mouse jumps back to the primary screen if I move it too fast.
Also when I am at the client screen edges (the non-switch-edges), it jumps 10 pixels or so back to the position it was a few milliseconds before.

Well, some progress at least.

It looks like this code I removed is some kind of hack. Query pointer will
add extra race condition and latency. Not sure you need it. You can try to
find the switching logic and check why it doesn't trigger.

On Wed, Nov 14, 2018, 07:29 Mathias L. Baumann notifications@github.com
wrote:

So, if I add that code back and add the additional condition

if (xmotion.send_event && m_waitForWarp) {

then the edge-detection works again. However, the mouse jumps back to the
primary screen if I move it too fast.
Also when I am at the client screen edges (the non-switch-edges), it jumps
10 pixels or so back to the position it was a few milliseconds before.

Well, some progress at least.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/symless/synergy-core/issues/5287#issuecomment-438425101,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AG8PHa86TS5XY4XVBhveT796GeWSITQXks5uuyu9gaJpZM4IL7t1
.

Well, it seems while on the primary screen, I don't get any xevent->type == MotionNotify but only xevent->type == GenericEvent

And the switching logic is somewhere in onMouseMove which isn't called for GenericEvent if we don't have that extra code block

This is my hack-fix currently. It only works for a matrix of 0.5 0 0 0 .5 0 0 0 1

diff --git a/src/lib/platform/XWindowsScreen.cpp b/src/lib/platform/XWindowsScreen.cpp
index 6a0d72bf..4ac9a936 100644
--- a/src/lib/platform/XWindowsScreen.cpp
+++ b/src/lib/platform/XWindowsScreen.cpp
@@ -1269,7 +1269,11 @@ XWindowsScreen::handleSystemEvent(const Event& event, void*)
                         &xmotion.x,
                         &xmotion.y,
                         &msk);
+                    if (m_isOnScreen)
+                    {
                     onMouseMove(xmotion);
+                    }
                     XFreeEventData(m_display, cookie);
                     return;
             }
@@ -1932,7 +1937,7 @@ XWindowsScreen::warpCursorNoFlush(SInt32 x, SInt32 y)
     XSendEvent(m_display, m_window, False, 0, &eventBefore);

     // warp mouse
-       XWarpPointer(m_display, None, m_root, 0, 0, 0, 0, x, y);
+    XWarpPointer(m_display, None, m_root, 0, 0, 0, 0, x*2, y*2);

What's happening here:

Instead of warping to the screen center, I warp to the center multiplied by two. I do that because my matrix is 0.5 which means due to the xserver bug it first warps to the original specified coordinates but upon movement it starts from the position that results in the matrix multiplication which is in my case half. so my * 2 basically makes it the screen center again.

The other part of the code makes the XI code conditional on running only when on the primary screen. I do that because otherwise the XQueryMouse call results in the coordinates where the moues i shortly on the multiplied coordinates and thus resulting in a huge jump.

However, this solution sometimes has lags if you move the mouse too fast, I have not identified why that is yet.

Having the same issue both on Ubuntu 16.04 and Ubuntu 18.04 fresh images.
At Ubuntu 18.04 when cursor position is being wrapped and then unwrapped again by some application (for example - Minecraft game) cursor jumps to some random position on the screen.
At Ubuntu 16.04 occurs both previously described behavior while also when dragging files on the desktop or in the file manager (nautilus) cursor randomly jumps to some position near bottom-right corner of the screen.

I am using custom CTM (xinput --set-prop <my_mouse_id> Coordinate Transformation Matrix 1 0 0 0 1 0 0 0 0.7), my mouse is Logitech G502, also tested with some Razor mouse my roommate has, the same bug occurs.

This bug is fixed simply by setting transformation matrix values to default ones, but that does not satisfies me because I am using it to increase my mouse sensitivity. Spent days already trying out different fixes, checking different solutions, nothing works.

I have to say though that this behaviour started appearing first about 6 month ago, so my best guess is that some driver \ kernel part got updated which causes this issue. I am going to be trying to install older versions of Ubuntu in the near future and trying out dragging items & minecraft without connecting to the internet so I wouldn't get any updated software or drivers installed (planning on taking 1 year old .iso image of Ubuntu).

If anyone could help me out with this problem though you can either contact me via email (in profile) or post here.

That's the problem in xorg which causes this effects as was mentioned here.

On Mon, Nov 19, 2018, 12:12 Anatoly notifications@github.com wrote:

Having the same issue both on Ubuntu 16.04 and Ubuntu 18.04 fresh images.
At Ubuntu 18.04 when cursor position is being wrapped and then unwrapped
again by some application (for example - Minecraft game) cursor jumps to
some random position on the screen.
At Ubuntu 16.04 occurs both previously described behavior while also when
dragging files on the desktop or in the file manager (nautilus) cursor
randomly jumps to some position near bottom-right corner of the screen.

I am using custom CTM (xinput --set-prop Coordinate
Transformation Matrix 1 0 0 0 1 0 0 0 0.7), my mouse is Logitech G502,
also tested with some Razor mouse my roommate has, the same bug occurs.

This bug is fixed simply by setting transformation matrix values to
default ones, but that does not satisfies me because I am using it to
increase my mouse sensitivity. Spent days already trying out different
fixes, checking different solutions, nothing works.

I have to say though that this behaviour started appearing first about 6
month ago, so my best guess is that some driver \ kernel part got updated
which causes this issue. I am going to be trying to install older versions
of Ubuntu in the near future and trying out dragging items & minecraft
without connecting to the internet so I wouldn't get any updated software
or drivers installed (planning on taking 1 year old .iso image of Ubuntu).

If anyone could help me out with this problem though you can either
contact me via email (in profile) or post here.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/symless/synergy-core/issues/5287#issuecomment-439744086,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AG8PHcuojARUfbdA9mc0wBmUjC9FKU5Bks5uwgWYgaJpZM4IL7t1
.

Any ideas on how to fix that? I am not an expert in linux, but is it possible top install another version of xorg so it would be ok?

I can confirm the issue for xorg-server 1.20.3 from Ubuntu sources. This causes the track point on a HP Elitebook 850 G5 to be unusable with scaled coordinates when running KDE. See xorg bug no. 600

Same here. Using synergy 1.10.3 or ArchLinux:

> uname -a  
Linux Aiur 5.4.11-arch1-1 #1 SMP PREEMPT Sun, 12 Jan 2020 12:15:27 +0000 x86_64 GNU/Linux

If we don't want to wait for the xorg bug to be fixed, a work-around needs to be implemented here.. maybe we can read the current transformation matrix and apply a modified position to jump to..

Or we just fix the bug in Xorg directly.. it doesn't sound like a too hard problem to solve with a bit of time..

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nbeazy picture nbeazy  Â·  4Comments

jasonosei picture jasonosei  Â·  3Comments

LeTink picture LeTink  Â·  4Comments

straris picture straris  Â·  5Comments

xmstspider picture xmstspider  Â·  4Comments