From 06432e4eee6d2ceb5e7ee75ad6d46c1ab322452a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 14 Jul 2022 22:38:24 +0530 Subject: [PATCH] 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) --- manual/customize.rst | 2 +- src/calibre/gui2/__init__.py | 9 --------- src/calibre/gui2/gestures.py | 11 ++++++----- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/manual/customize.rst b/manual/customize.rst index 249db08ca8..b44c3cd02b 100644 --- a/manual/customize.rst +++ b/manual/customize.rst @@ -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 diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 2e3f3dfcbd..c6b651e4e5 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -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 diff --git a/src/calibre/gui2/gestures.py b/src/calibre/gui2/gestures.py index 0e6cac0915..8688dae217 100644 --- a/src/calibre/gui2/gestures.py +++ b/src/calibre/gui2/gestures.py @@ -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