diff --git a/shell_client.h b/shell_client.h --- a/shell_client.h +++ b/shell_client.h @@ -61,6 +61,9 @@ KWayland::Server::ShellSurfaceInterface *shellSurface() const { return m_shellSurface; } + KWayland::Server::XdgShellSurfaceInterface *xdgShellSurface() const { + return m_xdgShellSurface; + } void blockActivityUpdates(bool b = true) override; QString caption(bool full = true) const override; diff --git a/shell_client.cpp b/shell_client.cpp --- a/shell_client.cpp +++ b/shell_client.cpp @@ -253,6 +253,12 @@ getShadow(); connect(s, &SurfaceInterface::shadowChanged, this, &Toplevel::getShadow); + connect(waylandServer(), &WaylandServer::foreignTransientChanged, this, [this](KWayland::Server::SurfaceInterface *child, KWayland::Server::SurfaceInterface *parent) { + Q_UNUSED(parent) + if (child == surface()) { + setTransient(); + } + }); setTransient(); // check whether we have a ServerSideDecoration if (ServerSideDecorationInterface *deco = ServerSideDecorationInterface::get(s)) { @@ -1320,6 +1326,9 @@ if (m_xdgShellPopup) { s = m_xdgShellPopup->transientFor().data(); } + if (!s) { + s = waylandServer()->findForeignTransientForSurface(surface()); + } auto t = waylandServer()->findClient(s); if (t != transientFor()) { // remove from main client diff --git a/wayland_server.h b/wayland_server.h --- a/wayland_server.h +++ b/wayland_server.h @@ -56,6 +56,7 @@ class OutputManagementInterface; class OutputConfigurationInterface; class XdgShellInterface; +class XdgForeignInterface; } } @@ -113,6 +114,11 @@ ShellClient *findClient(QWindow *w) const; /** + * return a transient parent of a surface imported with the foreign protocol, if any + */ + KWayland::Server::SurfaceInterface *findForeignTransientForSurface(KWayland::Server::SurfaceInterface *surface); + + /** * @returns file descriptor for Xwayland to connect to. **/ int createXWaylandConnection(); @@ -189,6 +195,7 @@ void shellClientRemoved(KWin::ShellClient*); void terminatingInternalClientConnection(); void initialized(); + void foreignTransientChanged(KWayland::Server::SurfaceInterface *child, KWayland::Server::SurfaceInterface *parent); private: void setupX11ClipboardSync(); @@ -229,6 +236,7 @@ KWayland::Server::ClientConnection *client = nullptr; QPointer ddi; } m_xclipbaordSync; + KWayland::Server::XdgForeignInterface *m_XdgForeign = nullptr; QList m_clients; QList m_internalClients; QHash m_clientIds; diff --git a/wayland_server.cpp b/wayland_server.cpp --- a/wayland_server.cpp +++ b/wayland_server.cpp @@ -52,6 +52,7 @@ #include #include #include +#include // Qt #include @@ -158,6 +159,20 @@ } else { connect(client, &ShellClient::windowShown, this, &WaylandServer::shellClientShown); } + //client->installXdgForeignInterface(m_XdgForeign); + connect(m_XdgForeign, &KWayland::Server::XdgForeignInterface::transientChanged, client, [this, client](KWayland::Server::SurfaceInterface *child, KWayland::Server::SurfaceInterface *parent) { + ShellClient *childClient = findClient(child); + //we are the parent, child is changed, manage all in this branch + if (findClient(parent) == client) { + if (childClient && client && client->surface() == parent) { + childClient->setModal(true); + } + //we are the child, just manage parent lost in this case + } else if (childClient == client && !parent) { + childClient->setModal(false); + } + emit foreignTransientChanged(child, parent); + }); } bool WaylandServer::init(const QByteArray &socketName, InitalizationFlags flags) @@ -301,9 +316,17 @@ m_display->createSubCompositor(m_display)->create(); + m_XdgForeign = m_display->createXdgForeignUnstableInterface(m_display); + m_XdgForeign->create(); + return true; } +SurfaceInterface *WaylandServer::findForeignTransientForSurface(SurfaceInterface *surface) +{ + return m_XdgForeign->transientFor(surface); +} + void WaylandServer::shellClientShown(Toplevel *t) { ShellClient *c = dynamic_cast(t);