From 66d127879461aed2e6c6312d52219502a6354f71 Mon Sep 17 00:00:00 2001 From: Marco Martin Date: Fri, 24 Jun 2022 15:56:08 +0000 Subject: [PATCH] Internal tracking for quick effect item focus focus used to be always forced to the root item of the view in the "active screen" (which behavior is configurable between mouse poosition and screen of active window) now set focus to that particular view only if nothing is focused, also when the user explicitly sets focus to an item in another view remove focus to the old one so the item properly focused would be there BUG:455807 BUG:455783 CCBUG:455633 --- src/libkwineffects/kwinoffscreenquickview.cpp | 5 +++ src/libkwineffects/kwinoffscreenquickview.h | 2 + src/libkwineffects/kwinquickeffect.cpp | 39 +++++++++++++++++-- src/libkwineffects/kwinquickeffect.h | 5 +++ 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/libkwineffects/kwinoffscreenquickview.cpp b/src/libkwineffects/kwinoffscreenquickview.cpp index 6b90eabc68..14baa08085 100644 --- a/src/libkwineffects/kwinoffscreenquickview.cpp +++ b/src/libkwineffects/kwinoffscreenquickview.cpp @@ -435,6 +435,11 @@ QQuickItem *OffscreenQuickView::contentItem() const return d->m_view->contentItem(); } +QQuickWindow *OffscreenQuickView::window() const +{ + return d->m_view; +} + void OffscreenQuickView::setVisible(bool visible) { if (d->m_visible == visible) { diff --git a/src/libkwineffects/kwinoffscreenquickview.h b/src/libkwineffects/kwinoffscreenquickview.h index 40fa70bcfe..8429de0c49 100644 --- a/src/libkwineffects/kwinoffscreenquickview.h +++ b/src/libkwineffects/kwinoffscreenquickview.h @@ -27,6 +27,7 @@ class QKeyEvent; class QQmlContext; class QQuickItem; +class QQuickWindow; namespace KWin { @@ -109,6 +110,7 @@ public: /** The invisble root item of the window*/ QQuickItem *contentItem() const; + QQuickWindow *window() const; /** * @brief Marks the window as visible/invisible diff --git a/src/libkwineffects/kwinquickeffect.cpp b/src/libkwineffects/kwinquickeffect.cpp index c577fb57b6..a67edb3446 100644 --- a/src/libkwineffects/kwinquickeffect.cpp +++ b/src/libkwineffects/kwinquickeffect.cpp @@ -10,6 +10,7 @@ #include #include +#include #include namespace KWin @@ -220,6 +221,19 @@ QuickSceneView *QuickSceneEffect::viewAt(const QPoint &pos) const return nullptr; } +void QuickSceneEffect::activateView(QuickSceneView *view) +{ + for (auto *otherView : d->views) { + if (otherView == view && !view->window()->activeFocusItem()) { + QFocusEvent focusEvent(QEvent::FocusIn, Qt::ActiveWindowFocusReason); + qApp->sendEvent(view->window(), &focusEvent); + } else if (otherView->window()->activeFocusItem()) { + QFocusEvent focusEvent(QEvent::FocusOut, Qt::ActiveWindowFocusReason); + qApp->sendEvent(otherView->window(), &focusEvent); + } + } +} + void QuickSceneEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) { Q_UNUSED(mask) @@ -288,6 +302,10 @@ void QuickSceneEffect::addScreen(EffectScreen *screen) properties["width"] = view->geometry().width(); properties["height"] = view->geometry().height(); view->setRootItem(qobject_cast(d->qmlComponent->createWithInitialProperties(properties))); + // we need the focus always set to the view of activescreen at first, and changed only upon user interaction + if (view->contentItem()) { + view->contentItem()->setFocus(false); + } view->setAutomaticRepaint(false); connect(view, &QuickSceneView::repaintNeeded, this, [view]() { @@ -400,16 +418,28 @@ void QuickSceneEffect::windowInputMouseEvent(QEvent *event) } if (target) { + if (buttons) { + activateView(target); + } target->forwardMouseEvent(event); } } void QuickSceneEffect::grabbedKeyboardEvent(QKeyEvent *keyEvent) { - QuickSceneView *screenView = d->views.value(effects->activeScreen()); - if (screenView) { - screenView->contentItem()->setFocus(true); - screenView->forwardKeyEvent(keyEvent); + auto it = std::find_if(d->views.constBegin(), d->views.constEnd(), [](QuickSceneView *v) { + return v->window()->activeFocusItem(); + }); + + if (it == d->views.constEnd()) { + QuickSceneView *screenView = d->views.value(effects->activeScreen()); + if (screenView) { + activateView(screenView); + screenView->forwardKeyEvent(keyEvent); + } + } else { + (*it)->forwardKeyEvent(keyEvent); + return; } } @@ -417,6 +447,7 @@ bool QuickSceneEffect::touchDown(qint32 id, const QPointF &pos, quint32 time) { for (QuickSceneView *screenView : qAsConst(d->views)) { if (screenView->geometry().contains(pos.toPoint())) { + activateView(screenView); return screenView->forwardTouchDown(id, pos, time); } } diff --git a/src/libkwineffects/kwinquickeffect.h b/src/libkwineffects/kwinquickeffect.h index ae98dca611..60b3ad2ffc 100644 --- a/src/libkwineffects/kwinquickeffect.h +++ b/src/libkwineffects/kwinquickeffect.h @@ -92,6 +92,11 @@ public: */ QuickSceneView *viewAt(const QPoint &pos) const; + /** + * Sets the given @a view as active. It will get a focusin event and all the other views will be set as inactive + */ + void activateView(QuickSceneView *view); + /** * Returns the source URL. */