[wayland] Improve creation of KWayland::Server::PlasmaWindowInterface
The creation of PlasmaWindowInterface is moved from WaylandServer into AbstractClient. This allows the sub classes to better control when to create/destroy the Client. For creation it's bound to becoming visible - that is Windows which are only created but never shown are not announced at all. For Client it's destroyed with the normal tear-down of a Client, for ShellClient it's destroyed on unmapped (which also means a new one will be created again in case of another mapping of the surface). As a side effect, this works around the problem that ShellClients do not yet get destroyed for QtWayland's menus (needs further investigation).
This commit is contained in:
parent
f6458fa1e8
commit
72635101f0
9 changed files with 163 additions and 110 deletions
|
@ -25,6 +25,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#endif
|
||||
#include "workspace.h"
|
||||
|
||||
#if HAVE_WAYLAND
|
||||
#include "wayland_server.h"
|
||||
#include <KWayland/Server/plasmawindowmanagement_interface.h>
|
||||
#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<void (AbstractClient::*)(AbstractClient*,MaximizeMode)>(&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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include <memory>
|
||||
|
||||
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<Decoration::DecorationPalette> m_palette;
|
||||
static QHash<QString, std::weak_ptr<Decoration::DecorationPalette>> s_palettes;
|
||||
static std::shared_ptr<Decoration::DecorationPalette> s_defaultPalette;
|
||||
|
||||
KWayland::Server::PlasmaWindowInterface *m_windowManagementInterface = nullptr;
|
||||
};
|
||||
|
||||
inline void AbstractClient::move(const QPoint& p, ForceGeometry_t force)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -127,6 +127,7 @@ private:
|
|||
void findInternalWindow();
|
||||
void updateInternalWindowGeometry();
|
||||
void updateIcon();
|
||||
void markAsUnmapped();
|
||||
static void deleteClient(ShellClient *c);
|
||||
|
||||
KWayland::Server::ShellSurfaceInterface *m_shellSurface;
|
||||
|
|
|
@ -87,9 +87,6 @@ void WaylandServer::init(const QByteArray &socketName)
|
|||
};
|
||||
if (Toplevel *t = ws->findToplevel(check)) {
|
||||
t->setSurface(surface);
|
||||
if (Client *c = dynamic_cast<Client*>(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<void (AbstractClient::*)(AbstractClient*,MaximizeMode)>(&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()) {
|
||||
|
|
|
@ -76,6 +76,9 @@ public:
|
|||
KWayland::Server::ShellInterface *shell() {
|
||||
return m_shell;
|
||||
}
|
||||
KWayland::Server::PlasmaWindowManagementInterface *windowManagement() {
|
||||
return m_windowManagement;
|
||||
}
|
||||
QList<ShellClient*> 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;
|
||||
|
|
Loading…
Reference in a new issue