From 932ccb2ac375fd5779f588daca492b296fe70e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Sun, 20 Jan 2019 14:04:13 +0100 Subject: [PATCH] Switch ThumbnailItem to internal uuid instead of WId Summary: So far the ThumbnailItem in TabBox mode used the window id for finding the window it should render a thumbnail on. In the Wayland world this is not unique. The window id could be either an X11 window or a wayland window. We don't guarantee that there are no conflicting ids. With the internal id we have a way to properly identify the windows, so this element should use them. To support this the property changed the type to QUuid and the clientmodel also provides the QUuid. As in TabBox the way to get the window is through the model this should be compatible for all themes. It's tested and verified with the Breeze switcher. For declarative KWin scripts the ThumbnailItem also provides the AbstractClient as a property, so there should not be any script which uses wid. If it does, this could break, but well the script should use the intended API. Test Plan: ctest passes, manual testing of Breeze alt-tab switcher Reviewers: #kwin Differential Revision: https://phabricator.kde.org/D18405 --- autotests/mock_effectshandler.h | 3 +++ autotests/tabbox/mock_tabboxclient.h | 5 +++++ effects.cpp | 12 +++++++++++- effects.h | 1 + libkwineffects/kwineffects.h | 7 +++++++ tabbox/clientmodel.cpp | 3 ++- tabbox/tabbox.cpp | 5 +++++ tabbox/tabbox.h | 1 + tabbox/tabboxhandler.h | 1 + thumbnailitem.cpp | 18 +++++++----------- thumbnailitem.h | 11 ++++++----- 11 files changed, 49 insertions(+), 18 deletions(-) diff --git a/autotests/mock_effectshandler.h b/autotests/mock_effectshandler.h index 3587ce86e0..d3fcab03b9 100644 --- a/autotests/mock_effectshandler.h +++ b/autotests/mock_effectshandler.h @@ -137,6 +137,9 @@ public: KWin::EffectWindow *findWindow(QWindow *w) const override { return nullptr; } + KWin::EffectWindow *findWindow(const QUuid &id) const override { + return nullptr; + } void *getProxy(QString) override { return nullptr; } diff --git a/autotests/tabbox/mock_tabboxclient.h b/autotests/tabbox/mock_tabboxclient.h index 32b42d7209..f8ce00cd44 100644 --- a/autotests/tabbox/mock_tabboxclient.h +++ b/autotests/tabbox/mock_tabboxclient.h @@ -23,6 +23,7 @@ along with this program. If not, see . #include "../../tabbox/tabboxhandler.h" #include +#include namespace KWin { @@ -65,6 +66,10 @@ public: return QIcon(); } + QUuid internalId() const override { + return QUuid{}; + } + private: QString m_caption; WId m_wId; diff --git a/effects.cpp b/effects.cpp index 3177bbd5f7..08d7f1588d 100644 --- a/effects.cpp +++ b/effects.cpp @@ -1099,6 +1099,16 @@ EffectWindow *EffectsHandlerImpl::findWindow(QWindow *w) const return nullptr; } +EffectWindow *EffectsHandlerImpl::findWindow(const QUuid &id) const +{ + if (const auto client = workspace()->findAbstractClient([&id] (const AbstractClient *c) { return c->internalId() == id; })) { + return client->effectWindow(); + } + if (const auto unmanaged = workspace()->findUnmanaged([&id] (const Unmanaged *c) { return c->internalId() == id; })) { + return unmanaged->effectWindow(); + } + return nullptr; +} EffectWindowList EffectsHandlerImpl::stackingOrder() const { @@ -2023,7 +2033,7 @@ void EffectWindowImpl::registerThumbnail(AbstractThumbnailItem *item) if (WindowThumbnailItem *thumb = qobject_cast(item)) { insertThumbnail(thumb); connect(thumb, SIGNAL(destroyed(QObject*)), SLOT(thumbnailDestroyed(QObject*))); - connect(thumb, SIGNAL(wIdChanged(qulonglong)), SLOT(thumbnailTargetChanged())); + connect(thumb, &WindowThumbnailItem::wIdChanged, this, &EffectWindowImpl::thumbnailTargetChanged); } else if (DesktopThumbnailItem *desktopThumb = qobject_cast(item)) { m_desktopThumbnails.append(desktopThumb); connect(desktopThumb, SIGNAL(destroyed(QObject*)), SLOT(desktopThumbnailDestroyed(QObject*))); diff --git a/effects.h b/effects.h index 92faaa1bef..39c220f943 100644 --- a/effects.h +++ b/effects.h @@ -135,6 +135,7 @@ public: EffectWindow* findWindow(WId id) const override; EffectWindow* findWindow(KWayland::Server::SurfaceInterface *surf) const override; EffectWindow *findWindow(QWindow *w) const override; + EffectWindow *findWindow(const QUuid &id) const override; EffectWindowList stackingOrder() const override; void setElevatedWindow(KWin::EffectWindow* w, bool set) override; diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h index 1ca8da379c..934d5bd439 100644 --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -1088,6 +1088,13 @@ public: * @since 5.16 **/ Q_SCRIPTABLE virtual KWin::EffectWindow *findWindow(QWindow *w) const = 0; + /** + * Finds the EffectWindow for the Toplevel with KWin internal @p id. + * If there is no such window @c null is returned. + * + * @since 5.16 + **/ + Q_SCRIPTABLE virtual KWin::EffectWindow *findWindow(const QUuid &id) const = 0; virtual EffectWindowList stackingOrder() const = 0; // window will be temporarily painted as if being at the top of the stack Q_SCRIPTABLE virtual void setElevatedWindow(KWin::EffectWindow* w, bool set) = 0; diff --git a/tabbox/clientmodel.cpp b/tabbox/clientmodel.cpp index 79bb6a6f77..7a7625095e 100644 --- a/tabbox/clientmodel.cpp +++ b/tabbox/clientmodel.cpp @@ -25,6 +25,7 @@ along with this program. If not, see . #include "tabboxhandler.h" // Qt #include +#include // TODO: remove with Qt 5, only for HTML escaping the caption #include #include @@ -84,7 +85,7 @@ QVariant ClientModel::data(const QModelIndex& index, int role) const return tabBox->desktopName(client.data()); } case WIdRole: - return qulonglong(client->window()); + return client->internalId(); case MinimizedRole: return client->isMinimized(); case CloseableRole: diff --git a/tabbox/tabbox.cpp b/tabbox/tabbox.cpp index 473e501302..e540ec0609 100644 --- a/tabbox/tabbox.cpp +++ b/tabbox/tabbox.cpp @@ -441,6 +441,11 @@ bool TabBoxClientImpl::isFirstInTabBox() const return m_client->isFirstInTabBox(); } +QUuid TabBoxClientImpl::internalId() const +{ + return m_client->internalId(); +} + /********************************************************* * TabBox *********************************************************/ diff --git a/tabbox/tabbox.h b/tabbox/tabbox.h index 8aef8ffa0e..b062b96595 100644 --- a/tabbox/tabbox.h +++ b/tabbox/tabbox.h @@ -103,6 +103,7 @@ public: virtual bool isCloseable() const; virtual void close(); virtual bool isFirstInTabBox() const; + QUuid internalId() const override; AbstractClient* client() const { return m_client; diff --git a/tabbox/tabboxhandler.h b/tabbox/tabboxhandler.h index b7d158d835..094a8e6210 100644 --- a/tabbox/tabboxhandler.h +++ b/tabbox/tabboxhandler.h @@ -395,6 +395,7 @@ public: virtual bool isCloseable() const = 0; virtual void close() = 0; virtual bool isFirstInTabBox() const = 0; + virtual QUuid internalId() const = 0; }; /** diff --git a/thumbnailitem.cpp b/thumbnailitem.cpp index a0f3f47e8a..566232990d 100644 --- a/thumbnailitem.cpp +++ b/thumbnailitem.cpp @@ -77,7 +77,7 @@ void AbstractThumbnailItem::findParentEffectWindow() qCDebug(KWIN_CORE) << "No QQuickWindow assigned yet"; return; } - if (auto *w = static_cast(effects->findWindow(qw->winId()))) { + if (auto *w = static_cast(effects->findWindow(qw))) { m_parent = QWeakPointer(w); } } @@ -132,18 +132,14 @@ WindowThumbnailItem::~WindowThumbnailItem() { } -void WindowThumbnailItem::setWId(qulonglong wId) +void WindowThumbnailItem::setWId(const QUuid &wId) { if (m_wId == wId) { return; } m_wId = wId; if (m_wId != 0) { - AbstractClient *c = Workspace::self()->findClient(Predicate::WindowMatch, m_wId); - if (!c && waylandServer()) { - c = waylandServer()->findClient(m_wId); - } - setClient(c); + setClient(workspace()->findAbstractClient([this] (const AbstractClient *c) { return c->internalId() == m_wId; })); } else if (m_client) { m_client = NULL; emit clientChanged(); @@ -158,9 +154,9 @@ void WindowThumbnailItem::setClient(AbstractClient *client) } m_client = client; if (m_client) { - setWId(m_client->windowId()); + setWId(m_client->internalId()); } else { - setWId(0); + setWId({}); } emit clientChanged(); } @@ -170,7 +166,7 @@ void WindowThumbnailItem::paint(QPainter *painter) if (effects) { return; } - Client *client = Workspace::self()->findClient(Predicate::WindowMatch, m_wId); + auto client = workspace()->findAbstractClient([this] (const AbstractClient *c) { return c->internalId() == m_wId; }); if (!client) { return; } @@ -182,7 +178,7 @@ void WindowThumbnailItem::paint(QPainter *painter) void WindowThumbnailItem::repaint(KWin::EffectWindow *w) { - if (static_cast(w)->window()->windowId() == m_wId) { + if (static_cast(w)->window()->internalId() == m_wId) { update(); } } diff --git a/thumbnailitem.h b/thumbnailitem.h index d57939bac4..b40ad94cac 100644 --- a/thumbnailitem.h +++ b/thumbnailitem.h @@ -22,6 +22,7 @@ along with this program. If not, see . #define KWIN_THUMBNAILITEM_H #include +#include #include #include @@ -76,26 +77,26 @@ private: class WindowThumbnailItem : public AbstractThumbnailItem { Q_OBJECT - Q_PROPERTY(qulonglong wId READ wId WRITE setWId NOTIFY wIdChanged SCRIPTABLE true) + Q_PROPERTY(QUuid wId READ wId WRITE setWId NOTIFY wIdChanged SCRIPTABLE true) Q_PROPERTY(KWin::AbstractClient *client READ client WRITE setClient NOTIFY clientChanged) public: explicit WindowThumbnailItem(QQuickItem *parent = 0); virtual ~WindowThumbnailItem(); - qulonglong wId() const { + QUuid wId() const { return m_wId; } - void setWId(qulonglong wId); + void setWId(const QUuid &wId); AbstractClient *client() const; void setClient(AbstractClient *client); virtual void paint(QPainter *painter); Q_SIGNALS: - void wIdChanged(qulonglong wid); + void wIdChanged(const QUuid &wid); void clientChanged(); protected Q_SLOTS: virtual void repaint(KWin::EffectWindow* w); private: - qulonglong m_wId; + QUuid m_wId; AbstractClient *m_client; };