diff --git a/autotests/tabbox/mock_tabboxhandler.h b/autotests/tabbox/mock_tabboxhandler.h --- a/autotests/tabbox/mock_tabboxhandler.h +++ b/autotests/tabbox/mock_tabboxhandler.h @@ -93,6 +93,11 @@ } virtual void grabbedKeyEvent(QKeyEvent *event) const; + void highlightWindows(TabBox::TabBoxClient *window = nullptr, QWindow *controller = nullptr) override { + Q_UNUSED(window) + Q_UNUSED(controller) + } + // mock methods QWeakPointer createMockWindow(const QString &caption, WId id); void closeWindow(TabBox::TabBoxClient *client); diff --git a/effects.h b/effects.h --- a/effects.h +++ b/effects.h @@ -236,6 +236,8 @@ bool touchMotion(quint32 id, const QPointF &pos, quint32 time); bool touchUp(quint32 id, quint32 time); + void highlightWindows(const QVector &windows); + public Q_SLOTS: void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to); void slotTabAdded(EffectWindow* from, EffectWindow* to); diff --git a/effects.cpp b/effects.cpp --- a/effects.cpp +++ b/effects.cpp @@ -107,6 +107,7 @@ , m_effectLoader(new EffectLoader(this)) , m_trackingCursorChanges(0) { + qRegisterMetaType>(); connect(m_effectLoader, &AbstractEffectLoader::effectLoaded, this, [this](Effect *effect, const QString &name) { effect_order.insert(effect->requestedEffectChainPosition(), EffectPair(name, effect)); @@ -1549,6 +1550,15 @@ return m_scene->animationsSupported(); } +void EffectsHandlerImpl::highlightWindows(const QVector &windows) +{ + Effect *e = provides(Effect::HighlightWindows); + if (!e) { + return; + } + e->performFeature(Effect::HighlightWindows, QVariantList{QVariant::fromValue(windows)}); +} + //**************************************** // EffectWindowImpl //**************************************** diff --git a/effects/highlightwindow/highlightwindow.h b/effects/highlightwindow/highlightwindow.h --- a/effects/highlightwindow/highlightwindow.h +++ b/effects/highlightwindow/highlightwindow.h @@ -42,6 +42,9 @@ return 70; } + bool provides(Feature feature) override; + bool performFeature(Feature feature, const QVariantList &arguments) override; + public Q_SLOTS: void slotWindowAdded(KWin::EffectWindow* w); void slotWindowClosed(KWin::EffectWindow *w); @@ -52,6 +55,8 @@ void prepareHighlighting(); void finishHighlighting(); + void highlightWindows(const QVector &windows); + bool m_finishing; float m_fadeDuration; diff --git a/effects/highlightwindow/highlightwindow.cpp b/effects/highlightwindow/highlightwindow.cpp --- a/effects/highlightwindow/highlightwindow.cpp +++ b/effects/highlightwindow/highlightwindow.cpp @@ -258,9 +258,47 @@ m_windowOpacity.constBegin().key()->addRepaintFull(); } +void HighlightWindowEffect::highlightWindows(const QVector &windows) +{ + if (windows.isEmpty()) { + finishHighlighting(); + return; + } + + m_monitorWindow = nullptr; + m_highlightedWindows.clear(); + m_highlightedIds.clear(); + for (auto w : windows) { + m_highlightedWindows << w; + } + prepareHighlighting(); +} + bool HighlightWindowEffect::isActive() const { return !(m_windowOpacity.isEmpty() || effects->isScreenLocked()); } +bool HighlightWindowEffect::provides(Feature feature) +{ + switch (feature) { + case HighlightWindows: + return true; + default: + return false; + } +} + +bool HighlightWindowEffect::performFeature(Feature feature, const QVariantList &arguments) +{ + if (feature != HighlightWindows) { + return false; + } + if (arguments.size() != 1) { + return false; + } + highlightWindows(arguments.first().value>()); + return true; +} + } // namespace diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -353,7 +353,7 @@ }; enum Feature { - Nothing = 0, Resize, GeometryTip, Outline, ScreenInversion, Blur, Contrast + Nothing = 0, Resize, GeometryTip, Outline, ScreenInversion, Blur, Contrast, HighlightWindows }; /** @@ -483,6 +483,19 @@ virtual bool provides(Feature); /** + * Performs the @p feature with the @p arguments. + * + * This allows to have specific protocols between KWin core and an Effect. + * + * The method is supposed to return @c true if it performed the features, + * @c false otherwise. + * + * The default implementation returns @c false. + * @since 5.8 + **/ + virtual bool performFeature(Feature feature, const QVariantList &arguments); + + /** * Can be called to draw multiple copies (e.g. thumbnails) of a window. * You can change window's opacity/brightness/etc here, but you can't * do any transformations. diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -695,6 +695,13 @@ return false; } +bool Effect::performFeature(Feature feature, const QVariantList &arguments) +{ + Q_UNUSED(feature) + Q_UNUSED(arguments) + return false; +} + //**************************************** // EffectFactory //**************************************** diff --git a/tabbox/tabbox.h b/tabbox/tabbox.h --- a/tabbox/tabbox.h +++ b/tabbox/tabbox.h @@ -74,6 +74,7 @@ virtual QWeakPointer< TabBoxClient > clientToAddToList(KWin::TabBox::TabBoxClient* client, int desktop) const; virtual QWeakPointer< TabBoxClient > desktopClient() const; virtual void activateAndClose(); + void highlightWindows(TabBoxClient *window = nullptr, QWindow *controller = nullptr) override; private: bool checkDesktop(TabBoxClient* client, int desktop) const; diff --git a/tabbox/tabbox.cpp b/tabbox/tabbox.cpp --- a/tabbox/tabbox.cpp +++ b/tabbox/tabbox.cpp @@ -343,6 +343,21 @@ m_tabBox->accept(); } +void TabBoxHandlerImpl::highlightWindows(TabBoxClient *window, QWindow *controller) +{ + if (!effects) { + return; + } + QVector windows; + if (window) { + windows << static_cast(window)->client()->effectWindow(); + } + if (auto t = Workspace::self()->findToplevel(controller)) { + windows << t->effectWindow(); + } + static_cast(effects)->highlightWindows(windows); +} + /********************************************************* * TabBoxClientImpl *********************************************************/ diff --git a/tabbox/tabboxhandler.h b/tabbox/tabboxhandler.h --- a/tabbox/tabboxhandler.h +++ b/tabbox/tabboxhandler.h @@ -187,6 +187,8 @@ */ virtual void shadeClient(TabBoxClient *c, bool b) const = 0; + virtual void highlightWindows(TabBoxClient *window = nullptr, QWindow *controller = nullptr) = 0; + /** * @return The current stacking order of TabBoxClients */ diff --git a/tabbox/tabboxhandler.cpp b/tabbox/tabboxhandler.cpp --- a/tabbox/tabboxhandler.cpp +++ b/tabbox/tabboxhandler.cpp @@ -92,7 +92,6 @@ */ bool isShown; TabBoxClient *lastRaisedClient, *lastRaisedClientSucc; - Xcb::Atom m_highlightWindowsAtom; private: QObject *createSwitcherItem(bool desktopMode); @@ -102,7 +101,6 @@ : m_qmlContext() , m_qmlComponent() , m_mainItem(nullptr) - , m_highlightWindowsAtom(QByteArrayLiteral("_KDE_WINDOW_HIGHLIGHT")) { this->q = q; isShown = false; @@ -199,19 +197,11 @@ } } - xcb_window_t wId; - QVector< xcb_window_t > data; if (config.isShowTabBox() && w) { - wId = w->winId(); - data.resize(2); - data[ 1 ] = wId; + q->highlightWindows(currentClient, w); } else { - wId = rootWindow(); - data.resize(1); + q->highlightWindows(currentClient); } - data[ 0 ] = currentClient ? currentClient->window() : 0L; - xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, wId, m_highlightWindowsAtom, - m_highlightWindowsAtom, 32, data.size(), data.constData()); } void TabBoxHandlerPrivate::endHighlightWindows(bool abort) @@ -232,7 +222,7 @@ lastRaisedClient = nullptr; lastRaisedClientSucc = nullptr; // highlight windows - xcb_delete_property(connection(), config.isShowTabBox() && w ? w->winId() : rootWindow(), m_highlightWindowsAtom); + q->highlightWindows(); } #ifndef KWIN_UNIT_TEST