Bug 384805 - cursor jumps upon edge activation
Summary: cursor jumps upon edge activation
Status: RESOLVED NOT A BUG
Alias: None
Product: kwin
Classification: Plasma
Component: core (other bugs)
Version First Reported In: 5.10.5
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: KWin default assignee
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-09-17 21:54 UTC by Michael Zanetti
Modified: 2017-10-04 19:16 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:
mgraesslin: Wayland-
mgraesslin: X11+


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Zanetti 2017-09-17 21:54:40 UTC
So I'm using libinput as touchpad driver on a new MacBook Pro and because the touchpad is so huge with high resolution, the cursor moves really slow and systemsetting's mouse module doesn't support changing the cursor speed for libinput. So I'm using this to double the mouse cursor speed:

xinput set-prop 12 142 2.000000, 0.000000, 0.000000, 0.000000, 2.000000, 0.000000, 0.000000, 0.000000, 1.000000

That works fine, except for this bug: when revealing an autohiding panel with the mouse, the cursor jumps for half a screen width/height along the edge (depending whether the panel is on the side or bottom).

As example, revealing an autohiding panel on the left screen edge by hitting the center of the left edge, as soon as the panel appears, the cursor jumps to the lower left corner of the screen.
Comment 1 Martin Flöser 2017-09-18 04:20:08 UTC
I don't see a reason why KWin should be responsible for that. It does a push back, but only one pixel to the right.
Comment 2 Michael Zanetti 2017-09-18 07:25:40 UTC
Hi Martin, I'm not 100% sure either if it's really kwin... Maybe it's the panel? 

But perhaps it's something in that 1 pixel push back that break it? like, if it does setCursorPosition(x, y) trying to correct one of them by 1 (depending on the edge) but there's some issue in the calculation of the new x/y values? I'm just guessing here... For all I know is that it only happens on edges where that have an autohide panel and if libinput's properties are set to translate the cursor matrix.
Comment 3 Martin Flöser 2017-09-18 14:56:31 UTC
The relevant code in KWin is:
void Edge::pushCursorBack(const QPoint &cursorPos)
{
    if (m_pushBackBlocked)
        return;
    int x = cursorPos.x();
    int y = cursorPos.y();
    const QSize &distance = edges()->cursorPushBackDistance();
    if (isLeft()) {
        x += distance.width();
    }
    if (isRight()) {
        x -= distance.width();
    }
    if (isTop()) {
        y += distance.height();
    }
    if (isBottom()) {
        y -= distance.height();
    }
    Cursor::setPos(x, y);
}

This has worked for years and I'm quite certain it is not broken ;-)

What I could imagine is that cursor warping does not work in general due to the xinput property you set. We just use xcb_warp_pointer on the rootWindow. You could try using a dummy implementation to check whether warping works.
Comment 4 Michael Zanetti 2017-09-19 09:55:35 UTC
Hey, so, I've edited screenedge.cpp and commented out the pushback of the cursor, and indeed the issue is gone (obviously at the cost that the one pixel pushback doesn't work any more either).

I also tried to add debug prints for the cursor position when it hits the edge and those seem to be correct. Which leads me to believe that the issue must be somewhere on the path of of Cursor::setPos(). Not saying it's necessarily in kwin itself, but at least it seems to happen when writing the position, and not when reading it.

I tried to follow the path but I got lost. All the connections to Cursor::posChanged don't seem to actually set the cursor (except in the software cursor case which doesn't seem to be case here, at least I couldn't see the m_softwareCursor path in platform.cpp being triggered) and the drm/x11standalone backends don't actually seem to trigger any cursor position updates, but rather only use that information for the edge glow and such.

Hope this helps, not sure where to go from here atm.
Br,
Michael
Comment 5 Martin Flöser 2017-09-19 15:25:34 UTC
Cursor::setPos is finally implemented in the X11Cursor::doSetPos (file plugins/platforms/x11/standalone/x11cursor.cpp line60)

void X11Cursor::doSetPos()
{
    const QPoint &pos = currentPos();
    xcb_warp_pointer(connection(), XCB_WINDOW_NONE, rootWindow(), 0, 0, 0, 0, pos.x(), pos.y());
    // call default implementation to emit signal
    Cursor::doSetPos();
}

As written in the last comment my guess is that xcb_warp_pointer just creates an incorrect warp in your case.
Comment 6 Martin Flöser 2017-10-04 19:16:01 UTC
Assuming it's a problem in xinput and not in KWin.