[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kwin] /: Move TabGroup functionality from Client to AbstractClient
From:       Martin_Flöser <null () kde ! org>
Date:       2018-05-20 18:18:31
Message-ID: E1fKSud-0000hA-1I () code ! kde ! org
[Download RAW message or body]

Git commit 46d8b87646cd4f90533ab8642eb0dfeb0d93d33b by Martin Flöser.
Committed on 20/05/2018 at 17:50.
Pushed by graesslin into branch 'master'.

Move TabGroup functionality from Client to AbstractClient

Only setClientShown remains in Client. This might need a dedicated
implementation for ShellClient.

M  +72   -9    abstract_client.cpp
M  +44   -4    abstract_client.h
M  +11   -90   client.cpp
M  +0    -45   client.h
M  +1    -1    manage.cpp
M  +1    -0    tabgroup.h

https://commits.kde.org/kwin/46d8b87646cd4f90533ab8642eb0dfeb0d93d33b

diff --git a/abstract_client.cpp b/abstract_client.cpp
index bc3774d73..1e3a21e79 100644
--- a/abstract_client.cpp
+++ b/abstract_client.cpp
@@ -114,14 +114,10 @@ bool AbstractClient::isTransient() const
     return false;
 }
 
-TabGroup *AbstractClient::tabGroup() const
-{
-    return nullptr;
-}
-
 void AbstractClient::setTabGroup(TabGroup* group)
 {
-    Q_UNUSED(group)
+    tab_group = group;
+    emit tabGroupChanged();
 }
 
 void AbstractClient::setClientShown(bool shown)
@@ -131,16 +127,83 @@ void AbstractClient::setClientShown(bool shown)
 
 bool AbstractClient::untab(const QRect &toGeometry, bool clientRemoved)
 {
-    Q_UNUSED(toGeometry)
-    Q_UNUSED(clientRemoved)
+    TabGroup *group = tab_group;
+    if (group && group->remove(this)) { // remove sets the tabgroup to "0", \
therefore the pointer is cached +        if (group->isEmpty()) {
+            delete group;
+        }
+        if (clientRemoved)
+            return true; // there's been a broadcast signal that this client is now \
removed - don't touch it +        setClientShown(!(isMinimized() || isShade()));
+        bool keepSize = toGeometry.size() == size();
+        bool changedSize = false;
+        if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) {
+            changedSize = true;
+            setQuickTileMode(QuickTileFlag::None); // if we leave a quicktiled \
group, assume that the user wants to untile +        }
+        if (toGeometry.isValid()) {
+            if (maximizeMode() != MaximizeRestore) {
+                changedSize = true;
+                maximize(MaximizeRestore); // explicitly calling for a geometry -> \
unmaximize +            }
+            if (keepSize && changedSize) {
+                setGeometryRestore(geometry()); // checkWorkspacePosition() invokes \
it +                QPoint cpoint = Cursor::pos();
+                QPoint point = cpoint;
+                point.setX((point.x() - toGeometry.x()) * geometryRestore().width() \
/ toGeometry.width()); +                point.setY((point.y() - toGeometry.y()) * \
geometryRestore().height() / toGeometry.height()); +                auto \
geometry_restore = geometryRestore(); +                \
geometry_restore.moveTo(cpoint-point); +                \
setGeometryRestore(geometry_restore); +            } else {
+                setGeometryRestore(toGeometry); // checkWorkspacePosition() invokes \
it +            }
+            setGeometry(geometryRestore());
+            checkWorkspacePosition();
+        }
+        return true;
+    }
     return false;
 }
 
-bool AbstractClient::isCurrentTab() const
+bool AbstractClient::tabTo(AbstractClient *other, bool behind, bool activate)
 {
+    Q_ASSERT(other && other != this);
+
+    if (tab_group && tab_group == other->tabGroup()) { // special case: move inside \
group +        tab_group->move(this, other, behind);
+        return true;
+    }
+
+    GeometryUpdatesBlocker blocker(this);
+    const bool wasBlocking = signalsBlocked();
+    blockSignals(true); // prevent client emitting "retabbed to nowhere" cause it's \
about to be entabbed the next moment +    untab();
+    blockSignals(wasBlocking);
+
+    TabGroup *newGroup = other->tabGroup() ? other->tabGroup() : new \
TabGroup(other); +
+    if (!newGroup->add(this, other, behind, activate)) {
+        if (newGroup->count() < 2) { // adding "c" to "to" failed for whatever \
reason +            newGroup->remove(other);
+            delete newGroup;
+        }
+        return false;
+    }
     return true;
 }
 
+void AbstractClient::syncTabGroupFor(QString property, bool fromThisClient)
+{
+    if (tab_group)
+        tab_group->sync(property.toAscii().data(), fromThisClient ? this : \
tab_group->current()); +}
+
+bool AbstractClient::isCurrentTab() const
+{
+    return !tab_group || tab_group->current() == this;
+}
+
 xcb_timestamp_t AbstractClient::userTime() const
 {
     return XCB_TIME_CURRENT_TIME;
diff --git a/abstract_client.h b/abstract_client.h
index c7401a8f8..c5259b664 100644
--- a/abstract_client.h
+++ b/abstract_client.h
@@ -272,6 +272,10 @@ class KWIN_EXPORT AbstractClient : public Toplevel
      * considered unresponsive. This usually indicates that the application froze or \
                crashed.
      */
     Q_PROPERTY(bool unresponsive READ unresponsive NOTIFY unresponsiveChanged)
+    /**
+     * The "Window Tabs" Group this Client belongs to.
+     **/
+    Q_PROPERTY(KWin::TabGroup* tabGroup READ tabGroup NOTIFY tabGroupChanged \
SCRIPTABLE false)  
 public:
     virtual ~AbstractClient();
@@ -422,11 +426,34 @@ public:
         return m_minimized;
     }
     virtual void setFullScreen(bool set, bool user = true) = 0;
-    virtual TabGroup *tabGroup() const;
-    virtual void setTabGroup(TabGroup* group);
+    // Tabbing functions
+    Q_INVOKABLE inline bool tabBefore(AbstractClient *other, bool activate) { return \
tabTo(other, false, activate); } +    Q_INVOKABLE inline bool \
tabBehind(AbstractClient *other, bool activate) { return tabTo(other, true, \
activate); } +    /**
+     * Syncs the *dynamic* @param property @param fromThisClient or the @link \
currentTab() to +     * all members of the @link tabGroup() (if there is one)
+     *
+     * eg. if you call:
+     * client->setProperty("kwin_tiling_floats", true);
+     * client->syncTabGroupFor("kwin_tiling_floats", true)
+     * all clients in this tabGroup will have \
::property("kwin_tiling_floats").toBool() == true +     *
+     * WARNING: non dynamic properties are ignored - you're not supposed to \
alter/update such explicitly +     */
+    Q_INVOKABLE void syncTabGroupFor(QString property, bool fromThisClient = false);
+    TabGroup *tabGroup() const;
+    /**
+     * Set tab group - this is to be invoked by TabGroup::add/remove(client) and NO \
ONE ELSE +     */
+    void setTabGroup(TabGroup* group);
     virtual void setClientShown(bool shown);
-    Q_INVOKABLE virtual bool untab(const QRect &toGeometry = QRect(), bool \
                clientRemoved = false);
-    virtual bool isCurrentTab() const;
+    Q_INVOKABLE bool untab(const QRect &toGeometry = QRect(), bool clientRemoved = \
false); +    /*
+    *   When a click is done in the decoration and it calls the group
+    *   to change the visible client it starts to move-resize the new
+    *   client, this function stops it.
+    */
+    bool isCurrentTab() const;
     virtual QRect geometryRestore() const = 0;
     virtual MaximizeMode maximizeMode() const = 0;
     void maximize(MaximizeMode);
@@ -732,6 +759,11 @@ Q_SIGNALS:
     void hasApplicationMenuChanged(bool);
     void applicationMenuActiveChanged(bool);
     void unresponsiveChanged(bool);
+    /**
+     * Emitted whenever the Client's TabGroup changed. That is whenever the Client \
is moved to +     * another group, but not when a Client gets added or removed to the \
Client's ClientGroup. +     **/
+    void tabGroupChanged();
 
 protected:
     AbstractClient();
@@ -1031,6 +1063,8 @@ protected:
     void finishWindowRules();
     void discardTemporaryRules();
 
+    bool tabTo(AbstractClient *other, bool behind, bool activate);
+
 private:
     void handlePaletteChange();
     QSharedPointer<TabBox::TabBoxClientImpl> m_tabBoxClient;
@@ -1108,6 +1142,7 @@ private:
     QKeySequence _shortcut;
 
     WindowRules m_rules;
+    TabGroup* tab_group = nullptr;
 
     static bool s_haveResizeEffect;
 };
@@ -1175,6 +1210,11 @@ inline void \
AbstractClient::setPendingGeometryUpdate(PendingGeometry_t update)  \
m_pendingGeometryUpdate = update;  }
 
+inline TabGroup* AbstractClient::tabGroup() const
+{
+    return tab_group;
+}
+
 }
 
 Q_DECLARE_METATYPE(KWin::AbstractClient*)
diff --git a/client.cpp b/client.cpp
index 23fca9222..8dd910e3c 100644
--- a/client.cpp
+++ b/client.cpp
@@ -108,7 +108,6 @@ Client::Client()
     , shadeHoverTimer(NULL)
     , m_colormap(XCB_COLORMAP_NONE)
     , in_group(NULL)
-    , tab_group(NULL)
     , ping_timer(NULL)
     , m_killHelperPID(0)
     , m_pingTimestamp(XCB_TIME_CURRENT_TIME)
@@ -167,6 +166,17 @@ Client::Client()
         }
     });
 
+    connect(this, &Client::tabGroupChanged, this,
+        [this] {
+            auto group = tabGroup();
+            if (group) {
+                unsigned long data[] = {qHash(group)}; //->id();
+                m_client.changeProperty(atoms->kde_net_wm_tab_group, \
XCB_ATOM_CARDINAL, 32, 1, data); +            }
+            else
+                m_client.deleteProperty(atoms->kde_net_wm_tab_group);
+        });
+
     // SELI TODO: Initialize xsizehints??
 }
 
@@ -1506,95 +1516,6 @@ void Client::fetchIconicName()
     }
 }
 
-bool Client::tabTo(Client *other, bool behind, bool activate)
-{
-    Q_ASSERT(other && other != this);
-
-    if (tab_group && tab_group == other->tabGroup()) { // special case: move inside \
                group
-        tab_group->move(this, other, behind);
-        return true;
-    }
-
-    GeometryUpdatesBlocker blocker(this);
-    const bool wasBlocking = signalsBlocked();
-    blockSignals(true); // prevent client emitting "retabbed to nowhere" cause it's \
                about to be entabbed the next moment
-    untab();
-    blockSignals(wasBlocking);
-
-    TabGroup *newGroup = other->tabGroup() ? other->tabGroup() : new \
                TabGroup(other);
-
-    if (!newGroup->add(this, other, behind, activate)) {
-        if (newGroup->count() < 2) { // adding "c" to "to" failed for whatever \
                reason
-            newGroup->remove(other);
-            delete newGroup;
-        }
-        return false;
-    }
-    return true;
-}
-
-bool Client::untab(const QRect &toGeometry, bool clientRemoved)
-{
-    TabGroup *group = tab_group;
-    if (group && group->remove(this)) { // remove sets the tabgroup to "0", \
                therefore the pointer is cached
-        if (group->isEmpty()) {
-            delete group;
-        }
-        if (clientRemoved)
-            return true; // there's been a broadcast signal that this client is now \
                removed - don't touch it
-        setClientShown(!(isMinimized() || isShade()));
-        bool keepSize = toGeometry.size() == size();
-        bool changedSize = false;
-        if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) {
-            changedSize = true;
-            setQuickTileMode(QuickTileFlag::None); // if we leave a quicktiled \
                group, assume that the user wants to untile
-        }
-        if (toGeometry.isValid()) {
-            if (maximizeMode() != MaximizeRestore) {
-                changedSize = true;
-                maximize(MaximizeRestore); // explicitly calling for a geometry -> \
                unmaximize
-            }
-            if (keepSize && changedSize) {
-                geom_restore = geometry(); // checkWorkspacePosition() invokes it
-                QPoint cpoint = Cursor::pos();
-                QPoint point = cpoint;
-                point.setX((point.x() - toGeometry.x()) * geom_restore.width() / \
                toGeometry.width());
-                point.setY((point.y() - toGeometry.y()) * geom_restore.height() / \
                toGeometry.height());
-                geom_restore.moveTo(cpoint-point);
-            } else {
-                geom_restore = toGeometry; // checkWorkspacePosition() invokes it
-            }
-            setGeometry(geom_restore);
-            checkWorkspacePosition();
-        }
-        return true;
-    }
-    return false;
-}
-
-void Client::setTabGroup(TabGroup *group)
-{
-    tab_group = group;
-    if (group) {
-        unsigned long data[] = {qHash(group)}; //->id();
-        m_client.changeProperty(atoms->kde_net_wm_tab_group, XCB_ATOM_CARDINAL, 32, \
                1, data);
-    }
-    else
-        m_client.deleteProperty(atoms->kde_net_wm_tab_group);
-    emit tabGroupChanged();
-}
-
-bool Client::isCurrentTab() const
-{
-    return !tab_group || tab_group->current() == this;
-}
-
-void Client::syncTabGroupFor(QString property, bool fromThisClient)
-{
-    if (tab_group)
-        tab_group->sync(property.toAscii().data(), fromThisClient ? this : \
                tab_group->current());
-}
-
 void Client::setClientShown(bool shown)
 {
     if (deleting)
diff --git a/client.h b/client.h
index 288c4b18d..755b4fd3b 100644
--- a/client.h
+++ b/client.h
@@ -70,10 +70,6 @@ class KWIN_EXPORT Client
      * Because of that no changed signal is provided.
      */
     Q_PROPERTY(QSize basicUnit READ basicUnit)
-    /**
-     * The "Window Tabs" Group this Client belongs to.
-     **/
-    Q_PROPERTY(KWin::TabGroup* tabGroup READ tabGroup NOTIFY tabGroupChanged \
SCRIPTABLE false)  /**
      * A client can block compositing. That is while the Client is alive and the \
                state is set,
      * Compositing is suspended and is resumed when there are no Clients blocking \
compositing any @@ -250,27 +246,6 @@ public:
     StrutRects strutRects() const;
     bool hasStrut() const override;
 
-    // Tabbing functions
-    TabGroup* tabGroup() const override; // Returns a pointer to client_group
-    Q_INVOKABLE inline bool tabBefore(Client *other, bool activate) { return \
                tabTo(other, false, activate); }
-    Q_INVOKABLE inline bool tabBehind(Client *other, bool activate) { return \
                tabTo(other, true, activate); }
-    /**
-     * Syncs the *dynamic* @param property @param fromThisClient or the @link \
                currentTab() to
-     * all members of the @link tabGroup() (if there is one)
-     *
-     * eg. if you call:
-     * client->setProperty("kwin_tiling_floats", true);
-     * client->syncTabGroupFor("kwin_tiling_floats", true)
-     * all clients in this tabGroup will have \
                ::property("kwin_tiling_floats").toBool() == true
-     *
-     * WARNING: non dynamic properties are ignored - you're not supposed to \
                alter/update such explicitly
-     */
-    Q_INVOKABLE void syncTabGroupFor(QString property, bool fromThisClient = false);
-    Q_INVOKABLE bool untab(const QRect &toGeometry = QRect(), bool clientRemoved = \
                false) override;
-    /**
-     * Set tab group - this is to be invoked by TabGroup::add/remove(client) and NO \
                ONE ELSE
-     */
-    void setTabGroup(TabGroup* group) override;
     /*
     *   If shown is true the client is mapped and raised, if false
     *   the client is unmapped and hidden, this function is called
@@ -278,12 +253,6 @@ public:
     *   client.
     */
     void setClientShown(bool shown) override;
-    /*
-    *   When a click is done in the decoration and it calls the group
-    *   to change the visible client it starts to move-resize the new
-    *   client, this function stops it.
-    */
-    bool isCurrentTab() const override;
 
     /**
      * Whether or not the window has a strut that expands through the invisible area \
of @@ -407,12 +376,6 @@ Q_SIGNALS:
     void clientManaging(KWin::Client*);
     void clientFullScreenSet(KWin::Client*, bool, bool);
 
-    /**
-     * Emitted whenever the Client's TabGroup changed. That is whenever the Client \
                is moved to
-     * another group, but not when a Client gets added or removed to the Client's \
                ClientGroup.
-     **/
-    void tabGroupChanged();
-
     /**
      * Emitted whenever the Client want to show it menu
      */
@@ -497,8 +460,6 @@ private:
 
     void updateInputWindow();
 
-    bool tabTo(Client *other, bool behind, bool activate);
-
     Xcb::Property fetchShowOnScreenEdge() const;
     void readShowOnScreenEdge(Xcb::Property &property);
     /**
@@ -562,7 +523,6 @@ private:
     xcb_colormap_t m_colormap;
     QString cap_normal, cap_iconic, cap_suffix;
     Group* in_group;
-    TabGroup* tab_group;
     QTimer* ping_timer;
     qint64 m_killHelperPID;
     xcb_timestamp_t m_pingTimestamp;
@@ -634,11 +594,6 @@ inline Group* Client::group()
     return in_group;
 }
 
-inline TabGroup* Client::tabGroup() const
-{
-    return tab_group;
-}
-
 inline bool Client::isShown(bool shaded_is_shown) const
 {
     return !isMinimized() && (!isShade() || shaded_is_shown) && !hidden &&
diff --git a/manage.cpp b/manage.cpp
index efa607e45..68b28df9c 100644
--- a/manage.cpp
+++ b/manage.cpp
@@ -370,7 +370,7 @@ bool Client::manage(xcb_window_t w, bool isMapped)
                 }
             }
         }
-        if (!(tab_group || isMapped || session)) {
+        if (!(tabGroup() || isMapped || session)) {
             // Attempt to automatically group similar windows
             Client* similar = findAutogroupCandidate();
             if (similar && !similar->noBorder()) {
diff --git a/tabgroup.h b/tabgroup.h
index 544910f8c..f4f6b4439 100644
--- a/tabgroup.h
+++ b/tabgroup.h
@@ -150,6 +150,7 @@ Q_SIGNALS:
     void maxSizeChanged();
 
 private:
+    friend class AbstractClient;
     friend class Client;
 //     friend bool Client::tabTo(Client*, bool, bool);
     bool add(KWin::AbstractClient *c, AbstractClient *other, bool behind, bool \
activateC);


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic