Ensure PointerInputRedirection::processMotion finishes prior to warping
ClosedPublic

Authored by graesslin on Mar 26 2017, 2:02 PM.

Details

Summary

Consider the following situation: we have three InputEventFilter linked
in the sequence A - B - C.

The input filters are processing pointer motion events. The expected
behavior is that the new motion is processed in the sequence

A -> B -> C

So far this did not work correctly if the pointer gets warped during the
processing. If e.g. filter B warps the pointer we get a motion sequence:

A (1) -> B (1) -> A (2) -> B (2) -> C (2) -> C (1)

The filters following the one warping the pointer get first the newer
than the older position. This is obviously wrong. Unfortunately it is not
just a theoretical condition, but a condition happening when interacting
with the screenedges, which warp the pointer.

This change introduces a PositionUpdateBlocker in
PointerInputRedirection::processMotion to ensure that a processMotion
call finishes prior to the next update. If the PositionUpdateBlocker is
blocked the new position gets scheduled and processed once the
PositionUpdateBlocker gets destroyed.

With this we get the expected sequence for B warping pointer:

A (1) -> B (1) -> C (1) -> A (2) -> B (2) -> C (2)

This should hopefully improve the interaction with screen edges on
Wayland.

CCBUG: 374867

Test Plan

Added an auto test demonstrating the issue of incorrect
ordering caused by screenedges. Prior to the change the test is failing.

Diff Detail

Repository
R108 KWin
Branch
position-update-blocker
Lint
No Linters Available
Unit
No Unit Test Coverage
graesslin created this revision.Mar 26 2017, 2:02 PM
Restricted Application added a project: KWin. · View Herald TranscriptMar 26 2017, 2:02 PM
Restricted Application added subscribers: kwin, plasma-devel. · View Herald Transcript
anthonyfieroni added inline comments.
pointer_input.cpp
234–236

This can lead to strange side effect

  1. isPositionBlocked == true
  2. s_scheduledPositions.size() > 1
  3. isPositionBlocked == false
  4. s_scheduledPositions.size() - 1 but still not 0

In next block/unblock will be triggered pertty old motion event, no? Maybe it's better to steal all blocked events except last one.

graesslin added inline comments.Mar 26 2017, 7:36 PM
pointer_input.cpp
234–236

No it is fine. You need to look at the big picture. This will invoke the first queued element for processMotion. Which in turn creates a new blocker and when going out of processMotion the next item will be processed. It is a recursive dequeueing of all elements. If another motion gets scheduled it just gets put to the end of the queue.

anthonyfieroni added inline comments.Mar 27 2017, 3:51 AM
pointer_input.cpp
234–236

Ah, great :)

bshah accepted this revision.Mar 27 2017, 3:55 AM
This revision is now accepted and ready to land.Mar 27 2017, 3:55 AM
This revision was automatically updated to reflect the committed changes.