Fix a regression that broke handling of mouse clicks on some Linux Wayland systems with a touchpad

Basically, in Qt 6 Wayland, Qt reports the device for mouse events
as finger when they come from a touchpad instead of a mouse. This caused
them to be swallowed by the gesture recognizer as being synthesized
mouse events.

Fixes #1981629 [Viewer TOC and search results  are not clickable](https://bugs.launchpad.net/calibre/+bug/1981629)
This commit is contained in:
Kovid Goyal 2022-07-14 22:38:24 +05:30
parent ee63c31685
commit 06432e4eee
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 7 additions and 15 deletions

View File

@ -49,7 +49,7 @@ Environment variables
the system theme -- beware of crashes and hangs.
* ``CALIBRE_SHOW_DEPRECATION_WARNINGS`` - causes calibre to print deprecation warnings to stdout. Useful for calibre developers.
* ``CALIBRE_NO_DEFAULT_PROGRAMS`` - prevent calibre from automatically registering the filetypes it is capable of handling with Windows.
* ``QT_QPA_PLATFORM`` - On Linux set this to ``wayland`` to force calibre to use Wayland. Note however that Qt + Wayland is extremely buggy.
* ``QT_QPA_PLATFORM`` - On Linux set this to ``wayland`` to force calibre to use Wayland and ``xcb`` to force use of X11.
* ``SYSFS_PATH`` - Use if sysfs is mounted somewhere other than /sys
* ``http_proxy``, ``https_proxy`` - used on Linux to specify an HTTP(S) proxy

View File

@ -1076,15 +1076,6 @@ class Application(QApplication):
args.extend(['-platform', 'windows:darkmode=2'])
else:
args.extend(['-platform', 'windows:darkmode=1'])
if not iswindows and not ismacos and not os.environ.get('QT_QPA_PLATFORM'):
# Various issues in Wayland make it unuseable so prevent Qt from
# using Wayland unless the user asks for it explicitly.
# In KDE right clicking on the book list causes left clicks on it
# to stop working till kwin is restarted. On GNOME there are no
# native window decorations. There have been reports of left clicks
# not working in GNOME though I cannot reproduce. So force use of
# XWayland.
args.extend(['-platform', 'xcb'])
self.headless = headless
from calibre_extensions import progress_indicator

View File

@ -5,14 +5,13 @@
import os
from functools import lru_cache
from qt.core import (
QApplication, QEvent, QInputDevice, QMouseEvent, QObject, QPointF,
QPointingDevice, QScroller, Qt, pyqtSignal
QApplication, QEvent, QInputDevice, QMouseEvent, QObject, QPointF, QScroller, Qt,
pyqtSignal
)
from calibre.utils.monotonic import monotonic
from polyglot.builtins import itervalues
HOLD_THRESHOLD = 1.0 # seconds
TAP_THRESHOLD = 50 # manhattan pixels
@ -160,6 +159,7 @@ class GestureManager(QObject):
if touch_supported():
view.viewport().setAttribute(Qt.WidgetAttribute.WA_AcceptTouchEvents)
self.state = State()
self.last_touch_event_device_id = None
self.state.tapped.connect(
self.handle_tap,
type=Qt.ConnectionType.QueuedConnection) # has to be queued otherwise QApplication.keyboardModifiers() does not work
@ -177,8 +177,8 @@ class GestureManager(QObject):
return
etype = ev.type()
if etype in (QEvent.Type.MouseButtonPress, QEvent.Type.MouseMove, QEvent.Type.MouseButtonRelease, QEvent.Type.MouseButtonDblClick):
if ev.pointingDevice().pointerType() is QPointingDevice.PointerType.Finger:
# swallow fake mouse events generated from touch events
if self.last_touch_event_device_id is not None and self.last_touch_event_device_id == ev.pointingDevice().uniqueId():
# swallow fake mouse events generated by the same device as the last touch event
ev.ignore()
return False
self.scroller.stop()
@ -189,6 +189,7 @@ class GestureManager(QObject):
boundary = self.evmap.get(etype)
if boundary is None or ev.deviceType() != QInputDevice.DeviceType.TouchScreen:
return
self.last_touch_event_device_id = ev.pointingDevice().uniqueId()
self.state.update(ev, boundary=boundary)
ev.accept()
return True