https://bugs.kde.org/show_bug.cgi?id=421295

            Bug ID: 421295
           Summary: Krita zooms to the max and rotates wildly when using
                    touch gestures with a Wacom Intuos Pro M on Linux
           Product: krita
           Version: git master
          Platform: Compiled Sources
                OS: Linux
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: tablet support
          Assignee: krita-bugs-n...@kde.org
          Reporter: sunda...@ierne.eu.org
  Target Milestone: ---

Created attachment 128340
  --> https://bugs.kde.org/attachment.cgi?id=128340&action=edit
PyQt5 program to demonstrate the TouchPoint coordinate bug.

SUMMARY

Context: this issue happens with a Wacom Intuos Pro M tablet on (at least)
Ubuntu Linux 19.10 and 20.04, using (at least) Krita 4.2.9 and Krita from git
at head.

The zoom/rotate touch features randomly misbehaves, and zooms to the max (8000%
or so) while rotating to a random angle. This happens mostly at the beginning
of gestures, when both fingers come into contact with the tablet, and to a
lesser extent at the end of the gesture, when at least one of the fingers
leaves the tablet.

This happens both in the flatpak package (4.2.9.0 from flathub) and git at
head. As to drivers, package xserver-xorg-input-wacom is at version
1:0.39.0-0ubuntu1 and package libwacom2 is at version 1.3-2ubuntu1.

Qt is at version 5.12.8+dfsg-0ubuntu1 for the version of Krita compiled from
git master. KDE is at version runtime/org.kde.Platform/x86_64/5.14 (I don't
know which Qt version is in there but I'm assuming 5.14 too) for the flatpak
install of Krita.



STEPS TO REPRODUCE

1. Plug in a Wacom Intuos Pro M (or presumably any touch-enabled Wacom tablet
of that range?)

2. Configure the tablet to report touches instead of converting them to
gestures itself (for instance with "xsetwacom --set "Wacom Intuos Pro M (WL)
Finger touch" Gesture off" in a terminal). Tablet is also in absolute mode.

3. Start Krita from git master on Linux.

4. Start a new image. Perhaps draw a few scribbles for a better visualization
of the problem.

5. Try to zoom/rotate by a few percents with a two finger gesture.



OBSERVED RESULT

The picture zooms to the maximum and rotates to a random angle.


EXPECTED RESULT

The picture zooms/rotates by a few percents.


SOFTWARE/OS VERSIONS

Linux/KDE Plasma: Ubuntu 19.10 and 20.04 using Cinnamon or i3 as the DE.
KDE Plasma Version: N/A.
KDE Frameworks Version: 5.12 and 5.14.
Qt Version: 5.12 (and probably 5.14).



ADDITIONAL INFORMATION

The bug here seems to be that Qt feeds spurious TouchEvent positions to Krita
at the beginning and end of touches and Krita fails to filter them out.

Weirdly this happens with TouchPoint.pos() and .screenPos(), but
.normalizedPos() works as expected, except at the very end of the gesture when
one of the TouchPoints is in state RELEASED, where that TouchPoint's
coordinates are off by some distance no matter what type of coordinates is
used.

In order to demonstrate this I wrote a pure Qt5 demo (in Python, sorry). You
can find it attached to this bug, or here: https://pastebin.com/Zgi2UxEi

This demo shows the following noteworthy behaviors:

- When a two-finger touch event begins, one TouchPoint is in state PRESSED, and
both TouchPoints report the same coordinates even if the fingers are quite
apart on the tablet.

- Those initial coordinates are always integers, whereas they become floats
once the TouchPoints start moving around. This suggests that the coordinates
for TouchPoints in state PRESSED are the result of some internal Qt fudging,
rather than direct reports from the hardware or its driver.

- The fact that both TouchPoints initially have the same coordinates probably
explains the instantaneous maximum zoom.

- In following events, the TouchPoint that started off PRESSED remains at those
incorrect coordinates so long as it's in state STATIONARY. Once it starts being
reported as MOVED, it "jumps" to the correct coordinates.

- The TouchPoint that did not start off PRESSED does not demonstrate this jump;
its reported position seems to remain reliable.

- Therefore it looks like the issue is that the state of the non-PRESSED
TouchPoint is incorrectly copied to the PRESSED one somewhere during Qt's
processing of the event.

- TouchPoints in state RELEASED also frequently report coordinates some
distance off from their previous position. This feels like it's probably a
distinct bug, but can be addressed at the same time.

- Replacing the .pos() method with .normalizedPos() fixes those issues except
for the one pertaining to TouchPoints in state RELEASED.


Therefore:

The bug is not Krita's fault, but Krita probably shouldn't fully trust
TouchPoint coordinates.



CONCLUSIONS

- TouchPoint.pos() cannot be trusted for a TouchPoint that has been in state
PRESSED until that TouchPoint has reached state MOVED.
- No TouchPoint coordinates can be trusted for a TouchPoint that is in state
RELEASED.


SUGGESTED WORKAROUND

- For the RELEASED TouchPoint issue, stop handling the event as soon as one of
the TouchPoints reaches this state.
- For the PRESSED TouchPoint issue, there are two options.
  - Option 1: switch to .normalizedPos() instead of .pos(). This will require
some fudging with the reported values, as the zoom gesture also handles panning
and seems to expect coordinates that make sense for that purpose. This also
doesn't preserve the aspect ratio of the gesture on the device, as normalized
positions are floats in range [0, 1].
  - Option 2: ignore TouchPoints that have been in state PRESSED until they
reach state MOVED. This may take multiple events.

I will try to write a patch in that light.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to