[tabbox] Intercept QWheelEvents on QQuickWindow for scrolling
Summary: The TabBox performs the scrolling of the items by itself in order to support wheel events even if the mouse is not on the TabBox. For that KWin grabs pointer events on X11 (on Wayland an input filter is used) and forwards them to the TabBox. Qt uses Xinput2 for scrolling on the QQuickWindow. Due to that KWin does not get any xcb core button press/release events when scrolling inside the QQuickWindow and thus scrolling doesn't work. There are three possible approaches to fix this: 1. Implement scrolling support in each of the QML switchers 2. Add an xinput2 filter to TabBox 3. Intercept the QWheelEvents on the QQuickWindow The first approach has the disadvantage that all themes need adjustment and that there might be behaviorial difference whether one scrolls on the TabBox window or outside the window. The second approach would be most in line with the other filters, but is difficult due to the nature of xinput2 (no xcb bindings, etc). Thus the third approach might be the best solution. Wheel events are only delivered to the QQuickWindow if the native events were not already intercepted, thus we know it won't have side effects for the case that Wayland is used or xinput2 is not supported. The implementation installs an event filter on the QQuickWindow which gets created when showing the TabBox and inside the filter waits till there is an angleDelta of +/-120 and scrolls by one per every 120 angle delta as described in the QWheelEvent documentation. BUG: 369661 FIXED-IN: 5.8.2 Test Plan: Scrolled with touchpad and mouse wheel. Reviewers: #kwin, #plasma, broulik Subscribers: plasma-devel, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D2953
This commit is contained in:
parent
78a2732a9a
commit
e9d20b80e9
2 changed files with 34 additions and 0 deletions
|
@ -92,6 +92,7 @@ public:
|
|||
*/
|
||||
bool isShown;
|
||||
TabBoxClient *lastRaisedClient, *lastRaisedClientSucc;
|
||||
int wheelAngleDelta = 0;
|
||||
|
||||
private:
|
||||
QObject *createSwitcherItem(bool desktopMode);
|
||||
|
@ -336,6 +337,10 @@ void TabBoxHandlerPrivate::show()
|
|||
// everything is prepared, so let's make the whole thing visible
|
||||
item->setVisible(true);
|
||||
}
|
||||
if (QWindow *w = window()) {
|
||||
wheelAngleDelta = 0;
|
||||
w->installEventFilter(q);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -607,6 +612,33 @@ QModelIndex TabBoxHandler::first() const
|
|||
return model->index(0, 0);
|
||||
}
|
||||
|
||||
bool TabBoxHandler::eventFilter(QObject *watched, QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::Wheel && watched == d->window()) {
|
||||
QWheelEvent *event = static_cast<QWheelEvent*>(e);
|
||||
// On x11 the delta for vertical scrolling might also be on X for whatever reason
|
||||
const int delta = qAbs(event->angleDelta().x()) > qAbs(event->angleDelta().y()) ? event->angleDelta().x() : event->angleDelta().y();
|
||||
d->wheelAngleDelta += delta;
|
||||
while (d->wheelAngleDelta <= -120) {
|
||||
d->wheelAngleDelta += 120;
|
||||
const QModelIndex index = nextPrev(true);
|
||||
if (index.isValid()) {
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
while (d->wheelAngleDelta >= 120) {
|
||||
d->wheelAngleDelta -= 120;
|
||||
const QModelIndex index = nextPrev(false);
|
||||
if (index.isValid()) {
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// pass on
|
||||
return QObject::eventFilter(watched, e);
|
||||
}
|
||||
|
||||
TabBoxHandler* tabBox = nullptr;
|
||||
|
||||
TabBoxClient::TabBoxClient()
|
||||
|
|
|
@ -334,6 +334,8 @@ public:
|
|||
*/
|
||||
QModelIndex first() const;
|
||||
|
||||
bool eventFilter(QObject *watcher, QEvent *event) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* This signal is fired when the TabBoxConfig changes
|
||||
|
|
Loading…
Reference in a new issue