Commit 2545162f authored by Martin Flöser's avatar Martin Flöser

Support highlighting windows through EffectsHandlerImpl

Summary:
So far TabBox used highlight windows by passing window ids around through
an X property. This doesn't work on Wayland where we don't have window
ids for our TabBox and the Wayland windows.

This change introduces a new Effect::Feature for HighlightWindows which
the HighlightWindowsEffect provides. The EffectsHandlerImpl has a new
method to highlightWindows which it delegates to that effect if it is
loaded by invoking a new performFeature method.

The TabBoxHandler now passes the highlighting to the effects system
instead of updating the x11 property. Thus this works on Wayland and
at the same time improves the X11 side by no longer having to go through
the property protocol.

Test Plan: Verified that Alt+Tab highlights the windows on Wayland correctly.

Reviewers: #kwin, #plasma_on_wayland

Subscribers: plasma-devel, kwin

Tags: #plasma_on_wayland, #kwin

Differential Revision: https://phabricator.kde.org/D2630
parent 405702b1
......@@ -93,6 +93,11 @@ public:
}
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<TabBox::TabBoxClient> createMockWindow(const QString &caption, WId id);
void closeWindow(TabBox::TabBoxClient *client);
......
......@@ -107,6 +107,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
, m_effectLoader(new EffectLoader(this))
, m_trackingCursorChanges(0)
{
qRegisterMetaType<QVector<KWin::EffectWindow*>>();
connect(m_effectLoader, &AbstractEffectLoader::effectLoaded, this,
[this](Effect *effect, const QString &name) {
effect_order.insert(effect->requestedEffectChainPosition(), EffectPair(name, effect));
......@@ -1549,6 +1550,15 @@ bool EffectsHandlerImpl::animationsSupported() const
return m_scene->animationsSupported();
}
void EffectsHandlerImpl::highlightWindows(const QVector<EffectWindow *> &windows)
{
Effect *e = provides(Effect::HighlightWindows);
if (!e) {
return;
}
e->perform(Effect::HighlightWindows, QVariantList{QVariant::fromValue(windows)});
}
//****************************************
// EffectWindowImpl
//****************************************
......
......@@ -236,6 +236,8 @@ public:
bool touchMotion(quint32 id, const QPointF &pos, quint32 time);
bool touchUp(quint32 id, quint32 time);
void highlightWindows(const QVector<EffectWindow *> &windows);
public Q_SLOTS:
void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to);
void slotTabAdded(EffectWindow* from, EffectWindow* to);
......
......@@ -258,9 +258,47 @@ void HighlightWindowEffect::finishHighlighting()
m_windowOpacity.constBegin().key()->addRepaintFull();
}
void HighlightWindowEffect::highlightWindows(const QVector<KWin::EffectWindow *> &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::perform(Feature feature, const QVariantList &arguments)
{
if (feature != HighlightWindows) {
return false;
}
if (arguments.size() != 1) {
return false;
}
highlightWindows(arguments.first().value<QVector<EffectWindow*>>());
return true;
}
} // namespace
......@@ -42,6 +42,9 @@ public:
return 70;
}
bool provides(Feature feature) override;
bool perform(Feature feature, const QVariantList &arguments) override;
public Q_SLOTS:
void slotWindowAdded(KWin::EffectWindow* w);
void slotWindowClosed(KWin::EffectWindow *w);
......@@ -52,6 +55,8 @@ private:
void prepareHighlighting();
void finishHighlighting();
void highlightWindows(const QVector<KWin::EffectWindow *> &windows);
bool m_finishing;
float m_fadeDuration;
......
......@@ -695,6 +695,13 @@ bool Effect::touchUp(quint32 id, quint32 time)
return false;
}
bool Effect::perform(Feature feature, const QVariantList &arguments)
{
Q_UNUSED(feature)
Q_UNUSED(arguments)
return false;
}
//****************************************
// EffectFactory
//****************************************
......
......@@ -353,7 +353,7 @@ public:
};
enum Feature {
Nothing = 0, Resize, GeometryTip, Outline, ScreenInversion, Blur, Contrast
Nothing = 0, Resize, GeometryTip, Outline, ScreenInversion, Blur, Contrast, HighlightWindows
};
/**
......@@ -482,6 +482,19 @@ public:
*/
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 perform(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
......
......@@ -343,6 +343,21 @@ void TabBoxHandlerImpl::activateAndClose()
m_tabBox->accept();
}
void TabBoxHandlerImpl::highlightWindows(TabBoxClient *window, QWindow *controller)
{
if (!effects) {
return;
}
QVector<EffectWindow*> windows;
if (window) {
windows << static_cast<TabBoxClientImpl*>(window)->client()->effectWindow();
}
if (auto t = Workspace::self()->findToplevel(controller)) {
windows << t->effectWindow();
}
static_cast<EffectsHandlerImpl*>(effects)->highlightWindows(windows);
}
/*********************************************************
* TabBoxClientImpl
*********************************************************/
......
......@@ -74,6 +74,7 @@ public:
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;
......
......@@ -92,7 +92,6 @@ public:
*/
bool isShown;
TabBoxClient *lastRaisedClient, *lastRaisedClientSucc;
Xcb::Atom m_highlightWindowsAtom;
private:
QObject *createSwitcherItem(bool desktopMode);
......@@ -102,7 +101,6 @@ TabBoxHandlerPrivate::TabBoxHandlerPrivate(TabBoxHandler *q)
: m_qmlContext()
, m_qmlComponent()
, m_mainItem(nullptr)
, m_highlightWindowsAtom(QByteArrayLiteral("_KDE_WINDOW_HIGHLIGHT"))
{
this->q = q;
isShown = false;
......@@ -199,19 +197,11 @@ void TabBoxHandlerPrivate::updateHighlightWindows()
}
}
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 @@ void TabBoxHandlerPrivate::endHighlightWindows(bool abort)
lastRaisedClient = nullptr;
lastRaisedClientSucc = nullptr;
// highlight windows
xcb_delete_property(connection(), config.isShowTabBox() && w ? w->winId() : rootWindow(), m_highlightWindowsAtom);
q->highlightWindows();
}
#ifndef KWIN_UNIT_TEST
......
......@@ -187,6 +187,8 @@ public:
*/
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
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment