diff --git a/abstract_client.cpp b/abstract_client.cpp index 8b0655686b..5cd40d985a 100644 --- a/abstract_client.cpp +++ b/abstract_client.cpp @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "abstract_client.h" +#include "focuschain.h" #ifdef KWIN_BUILD_TABBOX #include "tabbox.h" #endif @@ -239,4 +240,44 @@ void AbstractClient::demandAttention(bool set) emit demandsAttentionChanged(); } +void AbstractClient::setDesktop(int desktop) +{ + const int numberOfDesktops = VirtualDesktopManager::self()->count(); + if (desktop != NET::OnAllDesktops) // Do range check + desktop = qMax(1, qMin(numberOfDesktops, desktop)); + desktop = qMin(numberOfDesktops, rules()->checkDesktop(desktop)); + if (m_desktop == desktop) + return; + + int was_desk = m_desktop; + const bool wasOnCurrentDesktop = isOnCurrentDesktop(); + m_desktop = desktop; + + doSetDesktop(desktop, was_desk); + + FocusChain::self()->update(this, FocusChain::MakeFirst); + updateWindowRules(Rules::Desktop); + + emit desktopChanged(); + if (wasOnCurrentDesktop != isOnCurrentDesktop()) + emit desktopPresenceChanged(this, was_desk); +} + +void AbstractClient::doSetDesktop(int desktop, int was_desk) +{ + Q_UNUSED(desktop) + Q_UNUSED(was_desk) +} + +void AbstractClient::setOnAllDesktops(bool b) +{ + if ((b && isOnAllDesktops()) || + (!b && !isOnAllDesktops())) + return; + if (b) + setDesktop(NET::OnAllDesktops); + else + setDesktop(VirtualDesktopManager::self()->current()); +} + } diff --git a/abstract_client.h b/abstract_client.h index 2f70061364..f92550f37e 100644 --- a/abstract_client.h +++ b/abstract_client.h @@ -47,6 +47,14 @@ class AbstractClient : public Toplevel * @see Workspace::activateClient **/ Q_PROPERTY(bool active READ isActive NOTIFY activeChanged) + /** + * The desktop this Client is on. If the Client is on all desktops the property has value -1. + **/ + Q_PROPERTY(int desktop READ desktop WRITE setDesktop NOTIFY desktopChanged) + /** + * Whether the Client is on all desktops. That is desktop is -1. + **/ + Q_PROPERTY(bool onAllDesktops READ isOnAllDesktops WRITE setOnAllDesktops NOTIFY desktopChanged) /** * Whether the Client should be excluded from window switching effects. **/ @@ -154,8 +162,11 @@ public: virtual const QKeySequence &shortcut() const = 0; virtual void setShortcut(const QString &cut) = 0; virtual bool performMouseCommand(Options::MouseCommand, const QPoint &globalPos) = 0; - virtual void setOnAllDesktops(bool set) = 0; - virtual void setDesktop(int) = 0; + void setOnAllDesktops(bool set); + void setDesktop(int); + int desktop() const override { + return m_desktop; + } virtual void minimize(bool avoid_animation = false) = 0; virtual void unminimize(bool avoid_animation = false)= 0; virtual void setFullScreen(bool set, bool user = true) = 0; @@ -248,6 +259,7 @@ Q_SIGNALS: **/ void demandsAttentionChanged(); void desktopPresenceChanged(KWin::AbstractClient*, int); // to be forwarded by Workspace + void desktopChanged(); protected: AbstractClient(); @@ -278,6 +290,15 @@ protected: * Default implementation does nothing. **/ virtual void doSetKeepBelow(); + /** + * Called from ::setDeskop once the desktop value got updated, but before the changed signal + * is emitted. + * + * Default implementation does nothing. + * @param desktop The new desktop the Client is on + * @param was_desk The desktop the Client was on before + **/ + virtual void doSetDesktop(int desktop, int was_desk); // TODO: remove boolean trap virtual bool belongsToSameApplication(const AbstractClient *other, bool active_hack) const = 0; @@ -291,6 +312,7 @@ private: bool m_keepBelow = false; bool m_demandsAttention = false; QTimer *m_autoRaiseTimer = nullptr; + int m_desktop = 0; // 0 means not on any desktop yet }; } diff --git a/client.cpp b/client.cpp index ffbe0b95c6..8e8a4268bb 100644 --- a/client.cpp +++ b/client.cpp @@ -147,7 +147,6 @@ Client::Client() // Set the initial mapping state mapping_state = Withdrawn; quick_tile_mode = QuickTileNone; - desk = 0; // No desktop yet mode = PositionCenter; buttonDown = false; @@ -262,7 +261,6 @@ void Client::releaseWindow(bool on_shutdown) workspace()->removeClient(this); // Only when the window is being unmapped, not when closing down KWin (NETWM sections 5.5,5.7) info->setDesktop(0); - desk = 0; info->setState(0, info->state()); // Reset all state flags } else untab(); @@ -1304,18 +1302,8 @@ void Client::setModal(bool m) // _NET_WM_STATE_MODAL should possibly rather be _NET_WM_WINDOW_TYPE_MODAL_DIALOG } -void Client::setDesktop(int desktop) +void Client::doSetDesktop(int desktop, int was_desk) { - const int numberOfDesktops = VirtualDesktopManager::self()->count(); - if (desktop != NET::OnAllDesktops) // Do range check - desktop = qMax(1, qMin(numberOfDesktops, desktop)); - desktop = qMin(numberOfDesktops, rules()->checkDesktop(desktop)); - if (desk == desktop) - return; - - int was_desk = desk; - const bool wasOnCurrentDesktop = isOnCurrentDesktop(); - desk = desktop; info->setDesktop(desktop); if ((was_desk == NET::OnAllDesktops) != (desktop == NET::OnAllDesktops)) { // onAllDesktops changed @@ -1335,17 +1323,11 @@ void Client::setDesktop(int desktop) foreach (Client * c2, mainClients()) c2->setDesktop(desktop); } - - FocusChain::self()->update(this, FocusChain::MakeFirst); updateVisibility(); - updateWindowRules(Rules::Desktop); // Update states of all other windows in this group if (tabGroup()) tabGroup()->updateStates(this, TabGroup::Desktop); - emit desktopChanged(); - if (wasOnCurrentDesktop != isOnCurrentDesktop()) - emit desktopPresenceChanged(this, was_desk); } /** @@ -1450,7 +1432,7 @@ int Client::desktop() const if (needsSessionInteract) { return NET::OnAllDesktops; } - return desk; + return AbstractClient::desktop(); } /** @@ -1466,21 +1448,6 @@ QStringList Client::activities() const return activityList; } -void Client::setOnAllDesktops(bool b) -{ - if ((b && isOnAllDesktops()) || - (!b && !isOnAllDesktops())) - return; - if (b) - setDesktop(NET::OnAllDesktops); - else - setDesktop(VirtualDesktopManager::self()->current()); - - // Update states of all other windows in this group - if (tabGroup()) - tabGroup()->updateStates(this, TabGroup::Desktop); -} - /** * if @p on is true, sets on all activities. * if it's false, sets it to only be on the current activity diff --git a/client.h b/client.h index fc637ed77c..6abc1738d0 100644 --- a/client.h +++ b/client.h @@ -81,14 +81,6 @@ class Client * To read only the caption as provided by WM_NAME, use the getter with an additional @c false value. **/ Q_PROPERTY(QString caption READ caption NOTIFY captionChanged) - /** - * The desktop this Client is on. If the Client is on all desktops the property has value -1. - **/ - Q_PROPERTY(int desktop READ desktop WRITE setDesktop NOTIFY desktopChanged) - /** - * Whether the Client is on all desktops. That is desktop is -1. - **/ - Q_PROPERTY(bool onAllDesktops READ isOnAllDesktops WRITE setOnAllDesktops NOTIFY desktopChanged) /** * Whether this Client is fullScreen. A Client might either be fullScreen due to the _NET_WM property * or through a legacy support hack. The fullScreen state can only be changed if the Client does not @@ -298,8 +290,6 @@ public: QSize adjustedSize() const; virtual int desktop() const; - void setDesktop(int) override; - void setOnAllDesktops(bool set) override; void sendToScreen(int screen) override; @@ -615,6 +605,7 @@ protected: void doSetActive() override; void doSetKeepAbove() override; void doSetKeepBelow() override; + void doSetDesktop(int desktop, int was_desk) override; private Q_SLOTS: void delayedSetShortcut(); @@ -635,7 +626,6 @@ Q_SIGNALS: void clientStepUserMovedResized(KWin::Client *, const QRect&); void clientFinishUserMovedResized(KWin::Client*); void captionChanged(); - void desktopChanged(); void fullScreenChanged(); void transientChanged(); void modalChanged(); @@ -775,7 +765,6 @@ private: KDecoration2::Decoration *m_decoration; QPointer m_decoratedClient; QElapsedTimer m_decorationDoubleClickTimer; - int desk; QStringList activityList; int m_activityUpdatesBlocked; bool m_blockedActivityUpdatesRequireTransients; diff --git a/manage.cpp b/manage.cpp index 75af4e519b..295aafc8df 100644 --- a/manage.cpp +++ b/manage.cpp @@ -177,6 +177,7 @@ bool Client::manage(xcb_window_t w, bool isMapped) readActivities(activitiesCookie); // Initial desktop placement + int desk = 0; if (session) { desk = session->desktop; if (session->onAllDesktops) @@ -236,6 +237,7 @@ bool Client::manage(xcb_window_t w, bool isMapped) desk = rules()->checkDesktop(desk, !isMapped); if (desk != NET::OnAllDesktops) // Do range check desk = qBound(1, desk, static_cast(VirtualDesktopManager::self()->count())); + setDesktop(desk); info->setDesktop(desk); workspace()->updateOnAllDesktopsOfTransients(this); // SELI TODO //onAllDesktopsChange(); // Decoration doesn't exist here yet