diff --git a/abstract_client.cpp b/abstract_client.cpp
index 972377da40..f058c786c0 100644
--- a/abstract_client.cpp
+++ b/abstract_client.cpp
@@ -25,6 +25,11 @@ along with this program. If not, see .
#endif
#include "workspace.h"
+#if HAVE_WAYLAND
+#include "wayland_server.h"
+#include
+#endif
+
namespace KWin
{
@@ -509,4 +514,122 @@ bool AbstractClient::hasStrut() const
return false;
}
+void AbstractClient::setupWindowManagementInterface()
+{
+#if HAVE_WAYLAND
+ if (m_windowManagementInterface) {
+ // already setup
+ return;
+ }
+ if (!waylandServer() || !surface()) {
+ return;
+ }
+ if (!waylandServer()->windowManagement()) {
+ return;
+ }
+ using namespace KWayland::Server;
+ auto w = waylandServer()->windowManagement()->createWindow(this);
+ w->setTitle(caption());
+ w->setVirtualDesktop(isOnAllDesktops() ? 0 : desktop() - 1);
+ w->setActive(isActive());
+ w->setFullscreen(isFullScreen());
+ w->setKeepAbove(keepAbove());
+ w->setKeepBelow(keepBelow());
+ w->setMaximized(maximizeMode() == KWin::MaximizeFull);
+ w->setMinimized(isMinimized());
+ w->setOnAllDesktops(isOnAllDesktops());
+ w->setDemandsAttention(isDemandingAttention());
+ w->setCloseable(isCloseable());
+ w->setMaximizeable(isMaximizable());
+ w->setMinimizeable(isMinimizable());
+ w->setFullscreenable(isFullScreenable());
+ w->setThemedIconName(icon().name().isEmpty() ? QStringLiteral("xorg") : icon().name());
+ connect(this, &AbstractClient::captionChanged, w, [w, this] { w->setTitle(caption()); });
+ connect(this, &AbstractClient::desktopChanged, w,
+ [w, this] {
+ if (isOnAllDesktops()) {
+ w->setOnAllDesktops(true);
+ return;
+ }
+ w->setVirtualDesktop(desktop() - 1);
+ w->setOnAllDesktops(false);
+ }
+ );
+ connect(this, &AbstractClient::activeChanged, w, [w, this] { w->setActive(isActive()); });
+ connect(this, &AbstractClient::fullScreenChanged, w, [w, this] { w->setFullscreen(isFullScreen()); });
+ connect(this, &AbstractClient::keepAboveChanged, w, &PlasmaWindowInterface::setKeepAbove);
+ connect(this, &AbstractClient::keepBelowChanged, w, &PlasmaWindowInterface::setKeepBelow);
+ connect(this, &AbstractClient::minimizedChanged, w, [w, this] { w->setMinimized(isMinimized()); });
+ connect(this, static_cast(&AbstractClient::clientMaximizedStateChanged), w,
+ [w] (KWin::AbstractClient *c, MaximizeMode mode) {
+ Q_UNUSED(c);
+ w->setMaximized(mode == KWin::MaximizeFull);
+ }
+ );
+ connect(this, &AbstractClient::demandsAttentionChanged, w, [w, this] { w->setDemandsAttention(isDemandingAttention()); });
+ connect(this, &AbstractClient::iconChanged, w,
+ [w, this] {
+ const QIcon i = icon();
+ w->setThemedIconName(i.name().isEmpty() ? QStringLiteral("xorg") : i.name());
+ }
+ );
+ connect(w, &PlasmaWindowInterface::closeRequested, this, [this] { closeWindow(); });
+ connect(w, &PlasmaWindowInterface::virtualDesktopRequested, this,
+ [this] (quint32 desktop) {
+ workspace()->sendClientToDesktop(this, desktop + 1, true);
+ }
+ );
+ connect(w, &PlasmaWindowInterface::fullscreenRequested, this,
+ [this] (bool set) {
+ setFullScreen(set, false);
+ }
+ );
+ connect(w, &PlasmaWindowInterface::minimizedRequested, this,
+ [this] (bool set) {
+ if (set) {
+ minimize();
+ } else {
+ unminimize();
+ }
+ }
+ );
+ connect(w, &PlasmaWindowInterface::maximizedRequested, this,
+ [this] (bool set) {
+ maximize(set ? MaximizeFull : MaximizeRestore);
+ }
+ );
+ connect(w, &PlasmaWindowInterface::keepAboveRequested, this,
+ [this] (bool set) {
+ setKeepAbove(set);
+ }
+ );
+ connect(w, &PlasmaWindowInterface::keepBelowRequested, this,
+ [this] (bool set) {
+ setKeepBelow(set);
+ }
+ );
+ connect(w, &PlasmaWindowInterface::demandsAttentionRequested, this,
+ [this] (bool set) {
+ demandAttention(set);
+ }
+ );
+ connect(w, &PlasmaWindowInterface::activeRequested, this,
+ [this] (bool set) {
+ if (set) {
+ workspace()->activateClient(this, true);
+ }
+ }
+ );
+ m_windowManagementInterface = w;
+#endif
+}
+
+void AbstractClient::destroyWindowManagementInterface()
+{
+#if HAVE_WAYLAND
+ delete m_windowManagementInterface;
+ m_windowManagementInterface = nullptr;
+#endif
+}
+
}
diff --git a/abstract_client.h b/abstract_client.h
index 8b2a2e7777..2e1a3b1e0e 100644
--- a/abstract_client.h
+++ b/abstract_client.h
@@ -26,6 +26,14 @@ along with this program. If not, see .
#include
+namespace KWayland
+{
+namespace Server
+{
+class PlasmaWindowInterface;
+}
+}
+
namespace KWin
{
@@ -430,6 +438,9 @@ protected:
virtual void doSetSkipTaskbar();
virtual void doSetSkipPager();
+ void setupWindowManagementInterface();
+ void destroyWindowManagementInterface();
+
void updateColorScheme(QString path);
private:
@@ -456,6 +467,8 @@ private:
std::shared_ptr m_palette;
static QHash> s_palettes;
static std::shared_ptr s_defaultPalette;
+
+ KWayland::Server::PlasmaWindowInterface *m_windowManagementInterface = nullptr;
};
inline void AbstractClient::move(const QPoint& p, ForceGeometry_t force)
diff --git a/client.cpp b/client.cpp
index 98bc6f9751..acbe49249d 100644
--- a/client.cpp
+++ b/client.cpp
@@ -223,6 +223,7 @@ void Client::releaseWindow(bool on_shutdown)
{
assert(!deleting);
deleting = true;
+ destroyWindowManagementInterface();
Deleted* del = NULL;
if (!on_shutdown) {
del = Deleted::create(this);
@@ -293,6 +294,7 @@ void Client::destroyClient()
{
assert(!deleting);
deleting = true;
+ destroyWindowManagementInterface();
Deleted* del = Deleted::create(this);
if (moveResizeMode)
emit clientFinishUserMovedResized(this);
@@ -1824,6 +1826,7 @@ void Client::sendSyncRequest()
if (!ready_for_painting) {
// failed on initial pre-show request
setReadyForPainting();
+ setupWindowManagementInterface();
return;
}
// failed during resize
@@ -2231,8 +2234,10 @@ void Client::setDecoratedClient(QPointer< Decoration::DecoratedClientImpl > clie
void Client::addDamage(const QRegion &damage)
{
if (!ready_for_painting) { // avoid "setReadyForPainting()" function calling overhead
- if (syncRequest.counter == XCB_NONE) // cannot detect complete redraw, consider done now
+ if (syncRequest.counter == XCB_NONE) { // cannot detect complete redraw, consider done now
setReadyForPainting();
+ setupWindowManagementInterface();
+ }
}
Toplevel::addDamage(damage);
}
diff --git a/composite.cpp b/composite.cpp
index 8371390613..a586ffdd0c 100644
--- a/composite.cpp
+++ b/composite.cpp
@@ -1024,8 +1024,10 @@ void Client::damageNotifyEvent()
}
if (!ready_for_painting) { // avoid "setReadyForPainting()" function calling overhead
- if (syncRequest.counter == XCB_NONE) // cannot detect complete redraw, consider done now
+ if (syncRequest.counter == XCB_NONE) { // cannot detect complete redraw, consider done now
setReadyForPainting();
+ setupWindowManagementInterface();
+ }
}
Toplevel::damageNotifyEvent();
diff --git a/events.cpp b/events.cpp
index cdbcf65d60..1add8e0494 100644
--- a/events.cpp
+++ b/events.cpp
@@ -1547,6 +1547,7 @@ void Client::syncEvent(xcb_sync_alarm_notify_event_t* e)
{
if (e->alarm == syncRequest.alarm && e->counter_value.hi == syncRequest.value.hi && e->counter_value.lo == syncRequest.value.lo) {
setReadyForPainting();
+ setupWindowManagementInterface();
syncRequest.isPending = false;
if (syncRequest.failsafeTimeout)
syncRequest.failsafeTimeout->stop();
diff --git a/shell_client.cpp b/shell_client.cpp
index 2ff3eaa660..9608f3b9c5 100644
--- a/shell_client.cpp
+++ b/shell_client.cpp
@@ -52,6 +52,7 @@ ShellClient::ShellClient(ShellSurfaceInterface *surface)
setupCompositing();
if (surface->surface()->buffer()) {
setReadyForPainting();
+ setupWindowManagementInterface();
m_unmapped = false;
m_clientSize = surface->surface()->buffer()->size();
} else {
@@ -211,12 +212,21 @@ void ShellClient::addDamage(const QRegion &damage)
}
setGeometry(QRect(position, m_clientSize));
}
- m_unmapped = false;
+ markAsUnmapped();
setDepth(m_shellSurface->surface()->buffer()->hasAlphaChannel() ? 32 : 24);
- setReadyForPainting();
Toplevel::addDamage(damage);
}
+void ShellClient::markAsUnmapped()
+{
+ if (!m_unmapped) {
+ return;
+ }
+ m_unmapped = false;
+ setReadyForPainting();
+ setupWindowManagementInterface();
+}
+
void ShellClient::setGeometry(const QRect &rect)
{
if (geom == rect) {
@@ -591,6 +601,7 @@ void ShellClient::unmap()
{
m_unmapped = true;
ready_for_painting = false;
+ destroyWindowManagementInterface();
addWorkspaceRepaint(visibleRect());
workspace()->clientHidden(this);
emit windowHidden(this);
diff --git a/shell_client.h b/shell_client.h
index 3ef084bb59..bf91c43728 100644
--- a/shell_client.h
+++ b/shell_client.h
@@ -127,6 +127,7 @@ private:
void findInternalWindow();
void updateInternalWindowGeometry();
void updateIcon();
+ void markAsUnmapped();
static void deleteClient(ShellClient *c);
KWayland::Server::ShellSurfaceInterface *m_shellSurface;
diff --git a/wayland_server.cpp b/wayland_server.cpp
index 770950a9cc..9f414a725c 100644
--- a/wayland_server.cpp
+++ b/wayland_server.cpp
@@ -87,9 +87,6 @@ void WaylandServer::init(const QByteArray &socketName)
};
if (Toplevel *t = ws->findToplevel(check)) {
t->setSurface(surface);
- if (Client *c = dynamic_cast(t)) {
- announceClientToWindowManagement(c);
- }
}
}
);
@@ -201,111 +198,9 @@ void WaylandServer::initWorkspace()
);
}
);
- connect(workspace(), &Workspace::clientAdded, this, &WaylandServer::announceClientToWindowManagement);
- connect(this, &WaylandServer::shellClientAdded, this, &WaylandServer::announceClientToWindowManagement);
}
}
-void WaylandServer::announceClientToWindowManagement(AbstractClient *c)
-{
- if (!c->surface()) {
- return;
- }
- using namespace KWayland::Server;
- auto w = m_windowManagement->createWindow(c);
- w->setTitle(c->caption());
- w->setVirtualDesktop(c->isOnAllDesktops() ? 0 : c->desktop() - 1);
- w->setActive(c->isActive());
- w->setFullscreen(c->isFullScreen());
- w->setKeepAbove(c->keepAbove());
- w->setKeepBelow(c->keepBelow());
- w->setMaximized(c->maximizeMode() == KWin::MaximizeFull);
- w->setMinimized(c->isMinimized());
- w->setOnAllDesktops(c->isOnAllDesktops());
- w->setDemandsAttention(c->isDemandingAttention());
- w->setCloseable(c->isCloseable());
- w->setMaximizeable(c->isMaximizable());
- w->setMinimizeable(c->isMinimizable());
- w->setFullscreenable(c->isFullScreenable());
- w->setThemedIconName(c->icon().name().isEmpty() ? QStringLiteral("xorg") : c->icon().name());
- connect(c, &AbstractClient::captionChanged, w, [w, c] { w->setTitle(c->caption()); });
- connect(c, &AbstractClient::desktopChanged, w,
- [w, c] {
- if (c->isOnAllDesktops()) {
- w->setOnAllDesktops(true);
- return;
- }
- w->setVirtualDesktop(c->desktop() - 1);
- w->setOnAllDesktops(false);
- }
- );
- connect(c, &AbstractClient::activeChanged, w, [w, c] { w->setActive(c->isActive()); });
- connect(c, &AbstractClient::fullScreenChanged, w, [w, c] { w->setFullscreen(c->isFullScreen()); });
- connect(c, &AbstractClient::keepAboveChanged, w, &PlasmaWindowInterface::setKeepAbove);
- connect(c, &AbstractClient::keepBelowChanged, w, &PlasmaWindowInterface::setKeepBelow);
- connect(c, &AbstractClient::minimizedChanged, w, [w, c] { w->setMinimized(c->isMinimized()); });
- connect(c, static_cast(&AbstractClient::clientMaximizedStateChanged), w,
- [w] (KWin::AbstractClient *c, MaximizeMode mode) {
- Q_UNUSED(c);
- w->setMaximized(mode == KWin::MaximizeFull);
- }
- );
- connect(c, &AbstractClient::demandsAttentionChanged, w, [w, c] { w->setDemandsAttention(c->isDemandingAttention()); });
- connect(c, &AbstractClient::iconChanged, w,
- [w, c] {
- const QIcon icon = c->icon();
- w->setThemedIconName(icon.name().isEmpty() ? QStringLiteral("xorg") : icon.name());
- }
- );
- connect(w, &PlasmaWindowInterface::closeRequested, c, [c] { c->closeWindow(); });
- connect(w, &PlasmaWindowInterface::virtualDesktopRequested, c,
- [c] (quint32 desktop) {
- workspace()->sendClientToDesktop(c, desktop + 1, true);
- }
- );
- connect(w, &PlasmaWindowInterface::fullscreenRequested, c,
- [c] (bool set) {
- c->setFullScreen(set, false);
- }
- );
- connect(w, &PlasmaWindowInterface::minimizedRequested, c,
- [c] (bool set) {
- if (set) {
- c->minimize();
- } else {
- c->unminimize();
- }
- }
- );
- connect(w, &PlasmaWindowInterface::maximizedRequested, c,
- [c] (bool set) {
- c->maximize(set ? MaximizeFull : MaximizeRestore);
- }
- );
- connect(w, &PlasmaWindowInterface::keepAboveRequested, c,
- [c] (bool set) {
- c->setKeepAbove(set);
- }
- );
- connect(w, &PlasmaWindowInterface::keepBelowRequested, c,
- [c] (bool set) {
- c->setKeepBelow(set);
- }
- );
- connect(w, &PlasmaWindowInterface::demandsAttentionRequested, c,
- [c] (bool set) {
- c->demandAttention(set);
- }
- );
- connect(w, &PlasmaWindowInterface::activeRequested, c,
- [c] (bool set) {
- if (set) {
- workspace()->activateClient(c, true);
- }
- }
- );
-}
-
void WaylandServer::initOutputs()
{
if (m_backend && m_backend->handlesOutputs()) {
diff --git a/wayland_server.h b/wayland_server.h
index 69d00d25fc..1081ff2e93 100644
--- a/wayland_server.h
+++ b/wayland_server.h
@@ -76,6 +76,9 @@ public:
KWayland::Server::ShellInterface *shell() {
return m_shell;
}
+ KWayland::Server::PlasmaWindowManagementInterface *windowManagement() {
+ return m_windowManagement;
+ }
QList clients() const {
return m_clients;
}
@@ -138,7 +141,6 @@ Q_SIGNALS:
private:
void fakeDummyQtWindowInput();
quint16 createClientId(KWayland::Server::ClientConnection *c);
- void announceClientToWindowManagement(AbstractClient *c);
KWayland::Server::Display *m_display = nullptr;
KWayland::Server::CompositorInterface *m_compositor = nullptr;
KWayland::Server::SeatInterface *m_seat = nullptr;