From 18844f59259b766a9d4cdd5117e218f1b99b3994 Mon Sep 17 00:00:00 2001 From: Vlad Zagorodniy Date: Tue, 9 Jul 2019 14:58:57 +0300 Subject: [PATCH] [wayland] Apply window rules only to xdg-shell clients Summary: There are rules that have to be applied only once, e.g. every Remember and Apply Initially rule, as well rules that need to configure the client, e.g. size, etc. In the best scenario the compositor would evaluate such rules when the client is about to be mapped. This change limits window rules only to xdg-shell clients because right now only this protocol lets compositors to intervene in the client initialization process. Also, it makes things a bit easier for us on the compositor side. xdg-shell protocol satisfies most of ours requirements to implement window rules, but not all of them. If the client is about to be mapped for the second time and its size is forced by a rule, then compositor may need to configure it. Currently, xdg-shell protocol doesn't have any mechanism that a client could use to notify the compositor about its intent to map. Reviewers: #kwin, davidedmundson Reviewed By: #kwin, davidedmundson Subscribers: fmonteiro, davidedmundson, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D19411 --- abstract_client.cpp | 5 ++++ abstract_client.h | 7 ++++++ internal_client.cpp | 5 ++++ internal_client.h | 1 + shell_client.cpp | 60 +++++++++++++++++++++++++++------------------ shell_client.h | 3 +++ useractions.cpp | 4 +-- 7 files changed, 59 insertions(+), 26 deletions(-) diff --git a/abstract_client.cpp b/abstract_client.cpp index 12e030cd32..f98dffdb82 100644 --- a/abstract_client.cpp +++ b/abstract_client.cpp @@ -2087,4 +2087,9 @@ bool AbstractClient::isInternal() const return false; } +bool AbstractClient::supportsWindowRules() const +{ + return true; +} + } diff --git a/abstract_client.h b/abstract_client.h index 40a633097b..8afdc3d48f 100644 --- a/abstract_client.h +++ b/abstract_client.h @@ -866,6 +866,13 @@ public: **/ virtual bool isInternal() const; + /** + * Returns whether window rules can be applied to this client. + * + * Default implementation returns @c true. + **/ + virtual bool supportsWindowRules() const; + public Q_SLOTS: virtual void closeWindow() = 0; diff --git a/internal_client.cpp b/internal_client.cpp index 2b3ea8b57d..7c7b6d7745 100644 --- a/internal_client.cpp +++ b/internal_client.cpp @@ -328,4 +328,9 @@ QWindow *InternalClient::internalWindow() const return m_internalWindow; } +bool InternalClient::supportsWindowRules() const +{ + return false; +} + } diff --git a/internal_client.h b/internal_client.h index e5c04f2375..d424ec9728 100644 --- a/internal_client.h +++ b/internal_client.h @@ -60,6 +60,7 @@ public: using AbstractClient::resizeWithChecks; void resizeWithChecks(int w, int h, ForceGeometry_t force = NormalGeometrySet) override; QWindow *internalWindow() const override; + bool supportsWindowRules() const override; protected: bool acceptsFocus() const override; diff --git a/shell_client.cpp b/shell_client.cpp index 68da207649..788a58aa87 100644 --- a/shell_client.cpp +++ b/shell_client.cpp @@ -76,6 +76,7 @@ ShellClient::ShellClient(ShellSurfaceInterface *surface) { setSurface(surface->surface()); init(); + m_isInitialized = true; } ShellClient::ShellClient(XdgShellSurfaceInterface *surface) @@ -140,10 +141,11 @@ void ShellClient::initSurface(T *shellSurface) resourceName = info.fileName().toUtf8(); } setResourceClass(resourceName, shellSurface->windowClass()); + setDesktopFileName(shellSurface->windowClass()); connect(shellSurface, &T::windowClassChanged, this, [this, resourceName] (const QByteArray &windowClass) { setResourceClass(resourceName, windowClass); - if (!m_internal) { + if (m_isInitialized && supportsWindowRules()) { setupWindowRules(true); applyWindowRules(); } @@ -201,11 +203,6 @@ void ShellClient::initSurface(T *shellSurface) connect(this, &ShellClient::geometryChanged, this, &ShellClient::updateClientOutputs); connect(screens(), &Screens::changed, this, &ShellClient::updateClientOutputs); - - if (!m_internal) { - setupWindowRules(false); - } - setDesktopFileName(rules()->checkDesktopFile(shellSurface->windowClass(), true).toUtf8()); } void ShellClient::init() @@ -335,17 +332,7 @@ void ShellClient::init() } // set initial desktop - setDesktop(rules()->checkDesktop(m_internal ? int(NET::OnAllDesktops) : VirtualDesktopManager::self()->current(), true)); - // TODO: merge in checks from Client::manage? - if (rules()->checkMinimize(false, true)) { - minimize(true); // No animation - } - setSkipTaskbar(rules()->checkSkipTaskbar(m_plasmaShellSurface ? m_plasmaShellSurface->skipTaskbar() : false, true)); - setSkipPager(rules()->checkSkipPager(false, true)); - setSkipSwitcher(rules()->checkSkipSwitcher(false, true)); - setKeepAbove(rules()->checkKeepAbove(false, true)); - setKeepBelow(rules()->checkKeepBelow(false, true)); - setShortcut(rules()->checkShortcut(QString(), true)); + setDesktop(m_internal ? int(NET::OnAllDesktops) : VirtualDesktopManager::self()->current()); // setup shadow integration getShadow(); @@ -359,13 +346,6 @@ void ShellClient::init() setTransient(); AbstractClient::updateColorScheme(QString()); - - if (!m_internal) { - discardTemporaryRules(); - applyWindowRules(); // Just in case - RuleBook::self()->discardUsed(this, false); // Remove ApplyNow rules - updateWindowRules(Rules::All); // Was blocked while !isManaged() - } } void ShellClient::finishInit() { @@ -373,6 +353,28 @@ void ShellClient::finishInit() { disconnect(s, &SurfaceInterface::committed, this, &ShellClient::finishInit); updateWindowMargins(); + + if (supportsWindowRules()) { + setupWindowRules(false); + + setDesktop(rules()->checkDesktop(desktop(), true)); + setDesktopFileName(rules()->checkDesktopFile(desktopFileName(), true).toUtf8()); + if (rules()->checkMinimize(isMinimized(), true)) { + minimize(true); // No animation. + } + setSkipTaskbar(rules()->checkSkipTaskbar(skipTaskbar(), true)); + setSkipPager(rules()->checkSkipPager(skipPager(), true)); + setSkipSwitcher(rules()->checkSkipSwitcher(skipSwitcher(), true)); + setKeepAbove(rules()->checkKeepAbove(keepAbove(), true)); + setKeepBelow(rules()->checkKeepBelow(keepBelow(), true)); + setShortcut(rules()->checkShortcut(shortcut().toString(), true)); + updateColorScheme(); + + discardTemporaryRules(); + RuleBook::self()->discardUsed(this, false); // Remove Apply Now rules. + updateWindowRules(Rules::All); + } + if (!isInitialPositionSet()) { QRect area = workspace()->clientArea(PlacementArea, Screens::self()->current(), desktop()); placeIn(area); @@ -382,6 +384,8 @@ void ShellClient::finishInit() { if (m_requestGeometryBlockCounter == 0) { requestGeometry(m_blockedRequestGeometry); } + + m_isInitialized = true; } void ShellClient::destroyClient() @@ -1945,4 +1949,12 @@ QWindow *ShellClient::internalWindow() const return nullptr; } +bool ShellClient::supportsWindowRules() const +{ + if (m_plasmaShellSurface) { + return false; + } + return m_xdgShellSurface; +} + } diff --git a/shell_client.h b/shell_client.h index 3abf3dea04..289551550b 100644 --- a/shell_client.h +++ b/shell_client.h @@ -163,6 +163,8 @@ public: return true; } + bool supportsWindowRules() const override; + protected: void addDamage(const QRegion &damage) override; bool belongsToSameApplication(const AbstractClient *other, SameApplicationChecks checks) const override; @@ -297,6 +299,7 @@ private: QMargins m_windowMargins; bool m_compositingSetup = false; + bool m_isInitialized = false; }; } diff --git a/useractions.cpp b/useractions.cpp index 1455f75b9a..47c6379851 100644 --- a/useractions.cpp +++ b/useractions.cpp @@ -471,8 +471,8 @@ void UserActionsMenu::menuAboutToShow() action->setText(i18n("&Extensions")); } - m_rulesOperation->setEnabled(true); - m_applicationRulesOperation->setEnabled(true); + m_rulesOperation->setEnabled(m_client.data()->supportsWindowRules()); + m_applicationRulesOperation->setEnabled(m_client.data()->supportsWindowRules()); showHideActivityMenu(); }