From 7d152991c7e21eb054b2bb020353c66b0d297e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 18 May 2015 14:51:40 +0200 Subject: [PATCH] [wayland] ShellClient can reference an internal QWindow If the ShellClient got created for a Qt internal window, we try to find the QWindow and if we get one, we use the geometry directly as it got set by KWin in the first place. Also a windowId() is added to ShellClient which can be used by the effect system to find an EffectWindow. If it's an internal QWindow we just use that window id. For other clients we still need some smart solution. --- effects.cpp | 7 +++++++ shell_client.cpp | 38 +++++++++++++++++++++++++++++++++++++- shell_client.h | 8 ++++++++ wayland_server.cpp | 16 ++++++++++++++++ wayland_server.h | 4 ++++ 5 files changed, 72 insertions(+), 1 deletion(-) diff --git a/effects.cpp b/effects.cpp index 0e62b63a92..6b73b087d4 100644 --- a/effects.cpp +++ b/effects.cpp @@ -1032,6 +1032,13 @@ EffectWindow* EffectsHandlerImpl::findWindow(WId id) const return w->effectWindow(); if (Unmanaged* w = Workspace::self()->findUnmanaged(id)) return w->effectWindow(); +#if HAVE_WAYLAND + if (waylandServer()) { + if (ShellClient *w = waylandServer()->findClient(id)) { + return w->effectWindow(); + } + } +#endif return NULL; } diff --git a/shell_client.cpp b/shell_client.cpp index 0b86f09612..13f0f8c2a1 100644 --- a/shell_client.cpp +++ b/shell_client.cpp @@ -22,10 +22,13 @@ along with this program. If not, see . #include "wayland_server.h" #include "virtualdesktops.h" +#include #include #include #include +#include + using namespace KWayland::Server; namespace KWin @@ -36,6 +39,8 @@ ShellClient::ShellClient(ShellSurfaceInterface *surface) , m_shellSurface(surface) { setSurface(surface->surface()); + findInternalWindow(); + createWindowId(); setupCompositing(); if (surface->surface()->buffer()) { setReadyForPainting(); @@ -43,7 +48,11 @@ ShellClient::ShellClient(ShellSurfaceInterface *surface) } else { ready_for_painting = false; } - setGeometry(QRect(QPoint(0, 0), m_clientSize)); + if (m_internalWindow) { + setGeometry(m_internalWindow->geometry()); + } else { + setGeometry(QRect(QPoint(0, 0), m_clientSize)); + } setDesktop(VirtualDesktopManager::self()->current()); @@ -329,4 +338,31 @@ bool ShellClient::wantsInput() const return true; } +void ShellClient::createWindowId() +{ + if (m_internalWindow) { + m_windowId = m_internalWindow->winId(); + } + // TODO: create internal window ids +} + +void ShellClient::findInternalWindow() +{ + if (m_shellSurface->client() != waylandServer()->qtConnection()) { + return; + } + const QWindowList windows = kwinApp()->topLevelWindows(); + for (QWindow *w: windows) { + QScopedPointer s(KWayland::Client::Surface::fromWindow(w)); + if (!s) { + continue; + } + if (s->id() != surface()->id()) { + continue; + } + m_internalWindow = w; + return; + } +} + } diff --git a/shell_client.h b/shell_client.h index bd93ea24c4..8ccb6c0481 100644 --- a/shell_client.h +++ b/shell_client.h @@ -87,6 +87,10 @@ public: bool userCanSetNoBorder() const override; bool wantsInput() const override; + quint32 windowId() const { + return m_windowId; + } + protected: void addDamage(const QRegion &damage) override; bool belongsToSameApplication(const AbstractClient *other, bool active_hack) const override; @@ -94,11 +98,15 @@ protected: private: void setGeometry(const QRect &rect); void destroyClient(); + void createWindowId(); + void findInternalWindow(); static void deleteClient(ShellClient *c); KWayland::Server::ShellSurfaceInterface *m_shellSurface; QSize m_clientSize; bool m_closing = false; + quint32 m_windowId = 0; + QWindow *m_internalWindow = nullptr; }; } diff --git a/wayland_server.cpp b/wayland_server.cpp index c0a625a52e..9ae4884403 100644 --- a/wayland_server.cpp +++ b/wayland_server.cpp @@ -261,4 +261,20 @@ void WaylandServer::dispatch() m_display->dispatchEvents(0); } +ShellClient *WaylandServer::findClient(quint32 id) const +{ + if (id == 0) { + return nullptr; + } + auto it = std::find_if(m_clients.constBegin(), m_clients.constEnd(), + [id] (ShellClient *c) { + return c->windowId() == id; + } + ); + if (it == m_clients.constEnd()) { + return nullptr; + } + return *it; +} + } diff --git a/wayland_server.h b/wayland_server.h index 11c204f6b6..18266d34ef 100644 --- a/wayland_server.h +++ b/wayland_server.h @@ -75,6 +75,7 @@ public: return m_clients; } void removeClient(ShellClient *c); + ShellClient *findClient(quint32 id) const; AbstractBackend *backend() const { return m_backend; @@ -97,6 +98,9 @@ public: KWayland::Server::ClientConnection *xWaylandConnection() const { return m_xwaylandConnection; } + KWayland::Server::ClientConnection *qtConnection() const { + return m_qtConnection; + } KWayland::Server::ClientConnection *internalConnection() const { return m_internalConnection.server; }