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
This commit is contained in:
Martin Flöser 2019-01-20 14:04:13 +01:00
parent 02a0561016
commit 932ccb2ac3
11 changed files with 49 additions and 18 deletions

View file

@ -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;
}

View file

@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "../../tabbox/tabboxhandler.h"
#include <QIcon>
#include <QUuid>
namespace KWin
{
@ -65,6 +66,10 @@ public:
return QIcon();
}
QUuid internalId() const override {
return QUuid{};
}
private:
QString m_caption;
WId m_wId;

View file

@ -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<WindowThumbnailItem*>(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<DesktopThumbnailItem*>(item)) {
m_desktopThumbnails.append(desktopThumb);
connect(desktopThumb, SIGNAL(destroyed(QObject*)), SLOT(desktopThumbnailDestroyed(QObject*)));

View file

@ -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;

View file

@ -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;

View file

@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "tabboxhandler.h"
// Qt
#include <QIcon>
#include <QUuid>
// TODO: remove with Qt 5, only for HTML escaping the caption
#include <QTextDocument>
#include <QTextStream>
@ -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:

View file

@ -441,6 +441,11 @@ bool TabBoxClientImpl::isFirstInTabBox() const
return m_client->isFirstInTabBox();
}
QUuid TabBoxClientImpl::internalId() const
{
return m_client->internalId();
}
/*********************************************************
* TabBox
*********************************************************/

View file

@ -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;

View file

@ -395,6 +395,7 @@ public:
virtual bool isCloseable() const = 0;
virtual void close() = 0;
virtual bool isFirstInTabBox() const = 0;
virtual QUuid internalId() const = 0;
};
/**

View file

@ -77,7 +77,7 @@ void AbstractThumbnailItem::findParentEffectWindow()
qCDebug(KWIN_CORE) << "No QQuickWindow assigned yet";
return;
}
if (auto *w = static_cast<EffectWindowImpl*>(effects->findWindow(qw->winId()))) {
if (auto *w = static_cast<EffectWindowImpl*>(effects->findWindow(qw))) {
m_parent = QWeakPointer<EffectWindowImpl>(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<KWin::EffectWindowImpl*>(w)->window()->windowId() == m_wId) {
if (static_cast<KWin::EffectWindowImpl*>(w)->window()->internalId() == m_wId) {
update();
}
}

View file

@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KWIN_THUMBNAILITEM_H
#include <QPointer>
#include <QUuid>
#include <QWeakPointer>
#include <QQuickPaintedItem>
@ -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;
};