diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -493,6 +493,7 @@ libinput/libinput_logging.cpp udev.cpp touch_hide_cursor_spy.cpp + internal_client.cpp xwl/xwayland_interface.cpp ) diff --git a/autotests/integration/internal_window.cpp b/autotests/integration/internal_window.cpp --- a/autotests/integration/internal_window.cpp +++ b/autotests/integration/internal_window.cpp @@ -21,6 +21,7 @@ #include "platform.h" #include "cursor.h" #include "effects.h" +#include "internal_client.h" #include "shell_client.h" #include "screens.h" #include "wayland_server.h" @@ -227,6 +228,7 @@ QVERIFY(!workspace()->activeClient()); ShellClient *c = clientAddedSpy.first().first().value(); QVERIFY(c->isInternal()); + QVERIFY(qobject_cast(c)); QCOMPARE(c->icon().name(), QStringLiteral("wayland")); QVERIFY(!c->isDecorated()); QCOMPARE(workspace()->findToplevel(&win), c); diff --git a/internal_client.h b/internal_client.h new file mode 100644 --- /dev/null +++ b/internal_client.h @@ -0,0 +1,81 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2019 Martin Flöser + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#pragma once + +#include "shell_client.h" + + +namespace KWin +{ + +class KWIN_EXPORT InternalClient : public ShellClient +{ + Q_OBJECT +public: + InternalClient(KWayland::Server::ShellSurfaceInterface *surface); + // needed for template void WaylandServer::createSurface(T *surface) + InternalClient(KWayland::Server::XdgShellSurfaceInterface *surface); + // needed for template void WaylandServer::createSurface(T *surface) + InternalClient(KWayland::Server::XdgShellPopupInterface *surface); + ~InternalClient() override; + + bool eventFilter(QObject *watched, QEvent *event) override; + + NET::WindowType windowType(bool direct = false, int supported_types = 0) const override; + void killWindow() override; + bool isPopupWindow() const override; + void setInternalFramebufferObject(const QSharedPointer &fbo) override; + void closeWindow() override; + bool isCloseable() const override; + bool isMaximizable() const override; + bool isMinimizable() const override; + bool isMovable() const override; + bool isMovableAcrossScreens() const override; + bool isResizable() const override; + bool noBorder() const override; + bool userCanSetNoBorder() const override; + bool wantsInput() const override; + bool isInternal() const override; + bool isLockScreen() const override; + bool isInputMethod() const override; + quint32 windowId() const override; + using AbstractClient::resizeWithChecks; + void resizeWithChecks(int w, int h, ForceGeometry_t force = NormalGeometrySet) override; + QWindow *internalWindow() const override; + +protected: + bool acceptsFocus() const override; + void doMove(int x, int y) override; + void doResizeSync() override; + bool requestGeometry(const QRect &rect) override; + void doSetGeometry(const QRect &rect) override; + +private: + void findInternalWindow(); + void updateInternalWindowGeometry(); + void syncGeometryToInternalWindow(); + + NET::WindowType m_windowType = NET::Normal; + quint32 m_windowId = 0; + QWindow *m_internalWindow = nullptr; + Qt::WindowFlags m_internalWindowFlags = Qt::WindowFlags(); +}; + +} diff --git a/internal_client.cpp b/internal_client.cpp new file mode 100644 --- /dev/null +++ b/internal_client.cpp @@ -0,0 +1,321 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2019 Martin Flöser + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "internal_client.h" +#include "workspace.h" + +#include +#include + +#include + +Q_DECLARE_METATYPE(NET::WindowType) + +static const QByteArray s_skipClosePropertyName = QByteArrayLiteral("KWIN_SKIP_CLOSE_ANIMATION"); + +namespace KWin +{ + +InternalClient::InternalClient(KWayland::Server::ShellSurfaceInterface *surface) + : ShellClient(surface) +{ + findInternalWindow(); + updateInternalWindowGeometry(); + updateDecoration(true); +} + +InternalClient::InternalClient(KWayland::Server::XdgShellSurfaceInterface *surface) + : ShellClient(surface) +{ +} + +InternalClient::InternalClient(KWayland::Server::XdgShellPopupInterface *surface) + : ShellClient(surface) +{ +} + +InternalClient::~InternalClient() = default; + +void InternalClient::findInternalWindow() +{ + const QWindowList windows = kwinApp()->topLevelWindows(); + for (QWindow *w: windows) { + auto s = KWayland::Client::Surface::fromWindow(w); + if (!s) { + continue; + } + if (s->id() != surface()->id()) { + continue; + } + m_internalWindow = w; + m_windowId = m_internalWindow->winId(); + m_internalWindowFlags = m_internalWindow->flags(); + connect(m_internalWindow, &QWindow::xChanged, this, &InternalClient::updateInternalWindowGeometry); + connect(m_internalWindow, &QWindow::yChanged, this, &InternalClient::updateInternalWindowGeometry); + connect(m_internalWindow, &QWindow::destroyed, this, [this] { m_internalWindow = nullptr; }); + connect(m_internalWindow, &QWindow::opacityChanged, this, &InternalClient::setOpacity); + + const QVariant windowType = m_internalWindow->property("kwin_windowType"); + if (!windowType.isNull()) { + m_windowType = windowType.value(); + } + setOpacity(m_internalWindow->opacity()); + + // skip close animation support + setSkipCloseAnimation(m_internalWindow->property(s_skipClosePropertyName).toBool()); + m_internalWindow->installEventFilter(this); + return; + } +} + +bool InternalClient::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == m_internalWindow && event->type() == QEvent::DynamicPropertyChange) { + QDynamicPropertyChangeEvent *pe = static_cast(event); + if (pe->propertyName() == s_skipClosePropertyName) { + setSkipCloseAnimation(m_internalWindow->property(s_skipClosePropertyName).toBool()); + } + if (pe->propertyName() == "kwin_windowType") { + m_windowType = m_internalWindow->property("kwin_windowType").value(); + workspace()->updateClientArea(); + } + } + return false; +} + +NET::WindowType InternalClient::windowType(bool direct, int supported_types) const +{ + Q_UNUSED(direct) + Q_UNUSED(supported_types) + return m_windowType; +} + +void InternalClient::killWindow() +{ + // we don't kill our internal windows +} + +bool InternalClient::isPopupWindow() const +{ + if (Toplevel::isPopupWindow()) { + return true; + } + return m_internalWindowFlags.testFlag(Qt::Popup); +} + +void InternalClient::setInternalFramebufferObject(const QSharedPointer &fbo) +{ + if (fbo.isNull()) { + unmap(); + return; + } + + setClientSize(fbo->size() / surface()->scale()); + markAsMapped(); + doSetGeometry(QRect(geom.topLeft(), clientSize())); + Toplevel::setInternalFramebufferObject(fbo); + Toplevel::addDamage(QRegion(0, 0, width(), height())); +} + +void InternalClient::closeWindow() +{ + if (m_internalWindow) { + m_internalWindow->hide(); + } +} + +bool InternalClient::isCloseable() const +{ + return true; +} + +bool InternalClient::isMaximizable() const +{ + return false; +} + +bool InternalClient::isMinimizable() const +{ + return false; +} + +bool InternalClient::isMovable() const +{ + return true; +} + +bool InternalClient::isMovableAcrossScreens() const +{ + return true; +} + +bool InternalClient::isResizable() const +{ + return true; +} + +bool InternalClient::noBorder() const +{ + return m_internalWindowFlags.testFlag(Qt::FramelessWindowHint) || m_internalWindowFlags.testFlag(Qt::Popup); +} + +bool InternalClient::userCanSetNoBorder() const +{ + return !m_internalWindowFlags.testFlag(Qt::FramelessWindowHint) || m_internalWindowFlags.testFlag(Qt::Popup); +} + +bool InternalClient::wantsInput() const +{ + return false; +} + +bool InternalClient::acceptsFocus() const +{ + return false; +} + +bool InternalClient::isInternal() const +{ + return true; +} + +bool InternalClient::isLockScreen() const +{ + if (m_internalWindow) { + return m_internalWindow->property("org_kde_ksld_emergency").toBool(); + } + return false; +} + +bool InternalClient::isInputMethod() const +{ + if (m_internalWindow) { + return m_internalWindow->property("__kwin_input_method").toBool(); + } + return false; +} + +quint32 InternalClient::windowId() const +{ + return m_windowId; +} + +void InternalClient::updateInternalWindowGeometry() +{ + if (!m_internalWindow) { + return; + } + doSetGeometry(QRect(m_internalWindow->geometry().topLeft() - QPoint(borderLeft(), borderTop()), + m_internalWindow->geometry().size() + QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); +} + +bool InternalClient::requestGeometry(const QRect &rect) +{ + if (!ShellClient::requestGeometry(rect)) { + return false; + } + if (m_internalWindow) { + m_internalWindow->setGeometry(QRect(rect.topLeft() + QPoint(borderLeft(), borderTop()), rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); + } + return true; +} + +void InternalClient::doSetGeometry(const QRect &rect) +{ + if (geom == rect && pendingGeometryUpdate() == PendingGeometryNone) { + return; + } + if (!isUnmapped()) { + addWorkspaceRepaint(visibleRect()); + } + geom = rect; + + if (isUnmapped() && geometryRestore().isEmpty() && !geom.isEmpty()) { + // use first valid geometry as restore geometry + setGeometryRestore(geom); + } + + if (!isUnmapped()) { + addWorkspaceRepaint(visibleRect()); + } + syncGeometryToInternalWindow(); + if (hasStrut()) { + workspace()->updateClientArea(); + } + const auto old = geometryBeforeUpdateBlocking(); + updateGeometryBeforeUpdateBlocking(); + emit geometryShapeChanged(this, old); + + if (isResize()) { + performMoveResize(); + } +} + +void InternalClient::doMove(int x, int y) +{ + Q_UNUSED(x) + Q_UNUSED(y) + syncGeometryToInternalWindow(); +} + +void InternalClient::syncGeometryToInternalWindow() +{ + if (!m_internalWindow) { + return; + } + const QRect windowRect = QRect(geom.topLeft() + QPoint(borderLeft(), borderTop()), + geom.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom())); + if (m_internalWindow->geometry() != windowRect) { + // delay to end of cycle to prevent freeze, see BUG 384441 + QTimer::singleShot(0, m_internalWindow, std::bind(static_cast(&QWindow::setGeometry), m_internalWindow, windowRect)); + } +} + +void InternalClient::resizeWithChecks(int w, int h, ForceGeometry_t force) +{ + Q_UNUSED(force) + if (!m_internalWindow) { + return; + } + QRect area = workspace()->clientArea(WorkArea, this); + // don't allow growing larger than workarea + if (w > area.width()) { + w = area.width(); + } + if (h > area.height()) { + h = area.height(); + } + m_internalWindow->setGeometry(QRect(pos() + QPoint(borderLeft(), borderTop()), QSize(w, h) - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); +} + +void InternalClient::doResizeSync() +{ + if (!m_internalWindow) { + return; + } + const auto rect = moveResizeGeometry(); + m_internalWindow->setGeometry(QRect(rect.topLeft() + QPoint(borderLeft(), borderTop()), rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); +} + +QWindow *InternalClient::internalWindow() const +{ + return m_internalWindow; +} + +} diff --git a/shell_client.h b/shell_client.h --- a/shell_client.h +++ b/shell_client.h @@ -57,8 +57,6 @@ ShellClient(KWayland::Server::XdgShellPopupInterface *surface); virtual ~ShellClient(); - bool eventFilter(QObject *watched, QEvent *event) override; - QStringList activities() const override; QPoint clientContentPos() const override; QSize clientSize() const override; @@ -112,8 +110,6 @@ void setGeometry(int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet) override; bool hasStrut() const override; - void setInternalFramebufferObject(const QSharedPointer &fbo) override; - quint32 windowId() const override { return m_windowId; } @@ -126,12 +122,10 @@ **/ pid_t pid() const override; - bool isInternal() const; + virtual bool isInternal() const; bool isLockScreen() const override; bool isInputMethod() const override; - QWindow *internalWindow() const { - return m_internalWindow; - } + virtual QWindow *internalWindow() const; void installPlasmaShellSurface(KWayland::Server::PlasmaShellSurfaceInterface *surface); void installServerSideDecoration(KWayland::Server::ServerSideDecorationInterface *decoration); @@ -182,27 +176,32 @@ bool isWaitingForMoveResizeSync() const override; bool acceptsFocus() const override; void doMinimize() override; - void doMove(int x, int y) override; void updateCaption() override; + virtual bool requestGeometry(const QRect &rect); + virtual void doSetGeometry(const QRect &rect); + void unmap(); + void markAsMapped(); + + void setClientSize(const QSize &size) { + m_clientSize = size; + } + + bool isUnmapped() const { + return m_unmapped; + } + private Q_SLOTS: void clientFullScreenChanged(bool fullScreen); private: void init(); template void initSurface(T *shellSurface); - void requestGeometry(const QRect &rect); - void doSetGeometry(const QRect &rect); void createDecoration(const QRect &oldgeom); void destroyClient(); - void unmap(); void createWindowId(); - void findInternalWindow(); - void updateInternalWindowGeometry(); - void syncGeometryToInternalWindow(); void updateIcon(); - void markAsMapped(); void setTransient(); bool shouldExposeToWindowManagement(); void updateClientOutputs(); @@ -243,8 +242,6 @@ QRect m_geomFsRestore; //size and position of the window before it was set to fullscreen bool m_closing = false; quint32 m_windowId = 0; - QWindow *m_internalWindow = nullptr; - Qt::WindowFlags m_internalWindowFlags = Qt::WindowFlags(); bool m_unmapped = true; QRect m_geomMaximizeRestore; // size and position of the window before it was set to maximize NET::WindowType m_windowType = NET::Normal; diff --git a/shell_client.cpp b/shell_client.cpp --- a/shell_client.cpp +++ b/shell_client.cpp @@ -209,7 +209,6 @@ void ShellClient::init() { connect(this, &ShellClient::desktopFileNameChanged, this, &ShellClient::updateIcon); - findInternalWindow(); createWindowId(); setupCompositing(); updateIcon(); @@ -225,10 +224,7 @@ } else { ready_for_painting = false; } - if (m_internalWindow) { - updateInternalWindowGeometry(); - updateDecoration(true); - } else { + if (!m_internal) { doSetGeometry(QRect(QPoint(0, 0), m_clientSize)); } if (waylandServer()->inputMethodConnection() == s->client()) { @@ -501,20 +497,6 @@ Toplevel::addDamage(damage); } -void ShellClient::setInternalFramebufferObject(const QSharedPointer &fbo) -{ - if (fbo.isNull()) { - unmap(); - return; - } - - m_clientSize = fbo->size() / surface()->scale(); - markAsMapped(); - doSetGeometry(QRect(geom.topLeft(), m_clientSize)); - Toplevel::setInternalFramebufferObject(fbo); - Toplevel::addDamage(QRegion(0, 0, width(), height())); -} - void ShellClient::markAsMapped() { if (!m_unmapped) { @@ -635,7 +617,6 @@ if (!m_unmapped) { addWorkspaceRepaint(visibleRect()); } - syncGeometryToInternalWindow(); if (hasStrut()) { workspace()->updateClientArea(); } @@ -648,26 +629,6 @@ } } -void ShellClient::doMove(int x, int y) -{ - Q_UNUSED(x) - Q_UNUSED(y) - syncGeometryToInternalWindow(); -} - -void ShellClient::syncGeometryToInternalWindow() -{ - if (!m_internalWindow) { - return; - } - const QRect windowRect = QRect(geom.topLeft() + QPoint(borderLeft(), borderTop()), - geom.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom())); - if (m_internalWindow->geometry() != windowRect) { - // delay to end of cycle to prevent freeze, see BUG 384441 - QTimer::singleShot(0, m_internalWindow, std::bind(static_cast(&QWindow::setGeometry), m_internalWindow, windowRect)); - } -} - QByteArray ShellClient::windowRole() const { return QByteArray(); @@ -714,8 +675,6 @@ m_xdgShellSurface->close(); const qint32 pingSerial = static_cast(m_xdgShellSurface->global())->ping(m_xdgShellSurface); m_pingSerials.insert(pingSerial, PingReason::CloseWindow); - } else if (m_internalWindow) { - m_internalWindow->hide(); } } @@ -733,9 +692,6 @@ if (m_xdgShellSurface) { return true; } - if (m_internal) { - return true; - } return false; } @@ -746,17 +702,11 @@ bool ShellClient::isMaximizable() const { - if (m_internal) { - return false; - } return true; } bool ShellClient::isMinimizable() const { - if (m_internal) { - return false; - } return (!m_plasmaShellSurface || m_plasmaShellSurface->role() == PlasmaShellSurfaceInterface::Role::Normal); } @@ -924,9 +874,6 @@ bool ShellClient::noBorder() const { - if (isInternal()) { - return m_internalWindowFlags.testFlag(Qt::FramelessWindowHint) || m_internalWindowFlags.testFlag(Qt::Popup); - } if (m_serverDecoration) { if (m_serverDecoration->mode() == ServerSideDecorationManagerInterface::Mode::Server) { return m_userNoBorder || isFullScreen(); @@ -1062,9 +1009,6 @@ if (m_xdgDecoration && m_xdgDecoration->requestedMode() != XdgDecorationInterface::Mode::ClientSide) { return !isFullScreen() && !isShade() && !tabGroup(); } - if (m_internal) { - return !m_internalWindowFlags.testFlag(Qt::FramelessWindowHint) || m_internalWindowFlags.testFlag(Qt::Popup); - } return false; } @@ -1075,9 +1019,6 @@ bool ShellClient::acceptsFocus() const { - if (isInternal()) { - return false; - } if (waylandServer()->inputMethodConnection() == surface()->client()) { return false; } @@ -1111,87 +1052,36 @@ void ShellClient::createWindowId() { - if (m_internalWindow) { - m_windowId = m_internalWindow->winId(); - } else { + if (!m_internal) { m_windowId = waylandServer()->createWindowId(surface()); } } -void ShellClient::findInternalWindow() -{ - if (surface()->client() != waylandServer()->internalConnection()) { - return; - } - const QWindowList windows = kwinApp()->topLevelWindows(); - for (QWindow *w: windows) { - auto s = KWayland::Client::Surface::fromWindow(w); - if (!s) { - continue; - } - if (s->id() != surface()->id()) { - continue; - } - m_internalWindow = w; - m_internalWindowFlags = m_internalWindow->flags(); - connect(m_internalWindow, &QWindow::xChanged, this, &ShellClient::updateInternalWindowGeometry); - connect(m_internalWindow, &QWindow::yChanged, this, &ShellClient::updateInternalWindowGeometry); - connect(m_internalWindow, &QWindow::destroyed, this, [this] { m_internalWindow = nullptr; }); - connect(m_internalWindow, &QWindow::opacityChanged, this, &ShellClient::setOpacity); - - const QVariant windowType = m_internalWindow->property("kwin_windowType"); - if (!windowType.isNull()) { - m_windowType = windowType.value(); - } - setOpacity(m_internalWindow->opacity()); - - // skip close animation support - setSkipCloseAnimation(m_internalWindow->property(s_skipClosePropertyName).toBool()); - m_internalWindow->installEventFilter(this); - return; - } -} - -void ShellClient::updateInternalWindowGeometry() -{ - if (!m_internalWindow) { - return; - } - doSetGeometry(QRect(m_internalWindow->geometry().topLeft() - QPoint(borderLeft(), borderTop()), - m_internalWindow->geometry().size() + QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); -} - pid_t ShellClient::pid() const { return surface()->client()->processId(); } bool ShellClient::isInternal() const { - return m_internal; + return false; } bool ShellClient::isLockScreen() const { - if (m_internalWindow) { - return m_internalWindow->property("org_kde_ksld_emergency").toBool(); - } return surface()->client() == waylandServer()->screenLockerClientConnection(); } bool ShellClient::isInputMethod() const { - if (m_internal && m_internalWindow) { - return m_internalWindow->property("__kwin_input_method").toBool(); - } return surface()->client() == waylandServer()->inputMethodConnection(); } -void ShellClient::requestGeometry(const QRect &rect) +bool ShellClient::requestGeometry(const QRect &rect) { if (m_requestGeometryBlockCounter != 0) { m_blockedRequestGeometry = rect; - return; + return false; } PendingConfigureRequest configureRequest; configureRequest.positionAfterResize = rect.topLeft(); @@ -1218,9 +1108,7 @@ m_pendingConfigureRequests.append(configureRequest); m_blockedRequestGeometry = QRect(); - if (m_internal) { - m_internalWindow->setGeometry(QRect(rect.topLeft() + QPoint(borderLeft(), borderTop()), rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); - } + return true; } void ShellClient::updatePendingGeometry() @@ -1270,9 +1158,6 @@ if (m_xdgShellSurface) { m_xdgShellSurface->configure(xdgSurfaceStates(), QSize(w, h)); } - if (m_internal) { - m_internalWindow->setGeometry(QRect(pos() + QPoint(borderLeft(), borderTop()), QSize(w, h) - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); - } } void ShellClient::unmap() @@ -1292,11 +1177,7 @@ m_plasmaShellSurface = surface; auto updatePosition = [this, surface] { QRect rect = QRect(surface->position(), m_clientSize + QSize(borderLeft() + borderRight(), borderTop() + borderBottom())); - // Shell surfaces of internal windows are sometimes desync to current value. - // Make sure to not set window geometry of internal windows to invalid values (bug 386304) - if (!m_internal || rect.isValid()) { - doSetGeometry(rect); - } + doSetGeometry(rect); }; auto updateRole = [this, surface] { NET::WindowType type = NET::Unknown; @@ -1478,22 +1359,6 @@ updatePalette(palette->palette()); } - -bool ShellClient::eventFilter(QObject *watched, QEvent *event) -{ - if (watched == m_internalWindow && event->type() == QEvent::DynamicPropertyChange) { - QDynamicPropertyChangeEvent *pe = static_cast(event); - if (pe->propertyName() == s_skipClosePropertyName) { - setSkipCloseAnimation(m_internalWindow->property(s_skipClosePropertyName).toBool()); - } - if (pe->propertyName() == "kwin_windowType") { - m_windowType = m_internalWindow->property("kwin_windowType").value(); - workspace()->updateClientArea(); - } - } - return false; -} - void ShellClient::updateColorScheme() { if (m_paletteInterface) { @@ -1826,7 +1691,7 @@ bool ShellClient::shouldExposeToWindowManagement() { - if (isInternal()) { + if (m_internal) { return false; } if (isLockScreen()) { @@ -1916,9 +1781,6 @@ void ShellClient::killWindow() { - if (isInternal()) { - return; - } if (!surface()) { return; } @@ -1965,9 +1827,6 @@ if (Toplevel::isPopupWindow()) { return true; } - if (isInternal()) { - return m_internalWindowFlags.testFlag(Qt::Popup); - } if (m_shellSurface != nullptr) { return m_shellSurface->isPopup(); } @@ -1977,4 +1836,9 @@ return false; } +QWindow *ShellClient::internalWindow() const +{ + return nullptr; +} + } diff --git a/wayland_server.cpp b/wayland_server.cpp --- a/wayland_server.cpp +++ b/wayland_server.cpp @@ -22,6 +22,7 @@ #include "platform.h" #include "composite.h" #include "idle_inhibition.h" +#include "internal_client.h" #include "screens.h" #include "shell_client.h" #include "workspace.h" @@ -155,7 +156,13 @@ if (surface->client() == m_screenLockerClientConnection) { ScreenLocker::KSldApp::self()->lockScreenShown(); } - auto client = new ShellClient(surface); + ShellClient *client; + if (surface->client() == waylandServer()->internalConnection()) { + client = new InternalClient(surface); + } else { + client = new ShellClient(surface); + } + client = new ShellClient(surface); if (ServerSideDecorationInterface *deco = ServerSideDecorationInterface::get(surface->surface())) { client->installServerSideDecoration(deco); }