From f644c28180d238b7efe3dc2ff4f2ea3559c4081c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Thu, 1 Dec 2011 13:15:11 +0100 Subject: [PATCH] Support for sticky items in TabBox list This is needed for Plasma Active's home screen which should always be the first element in the list. --- atoms.cpp | 3 +++ atoms.h | 1 + client.cpp | 19 +++++++++++++++++++ client.h | 8 ++++++++ events.cpp | 2 ++ manage.cpp | 1 + tabbox/clientmodel.cpp | 11 +++++++++++ tabbox/tabbox.cpp | 5 +++++ tabbox/tabbox.h | 1 + tabbox/tabboxhandler.h | 1 + 10 files changed, 52 insertions(+) diff --git a/atoms.cpp b/atoms.cpp index 1fd237d18b..c2d7f04490 100644 --- a/atoms.cpp +++ b/atoms.cpp @@ -126,6 +126,9 @@ Atoms::Atoms() atoms[n] = &kde_net_wm_tab_group; names[n++] = (char*) "_KDE_NET_WM_TAB_GROUP"; + atoms[n] = &kde_first_in_window_list; + names[n++] = (char*) "_KDE_FIRST_IN_WINDOWLIST"; + assert(n <= max); XInternAtoms(display(), names, n, false, atoms_return); diff --git a/atoms.h b/atoms.h index 1f9085a265..c45b0b05a2 100644 --- a/atoms.h +++ b/atoms.h @@ -64,6 +64,7 @@ public: Atom kde_net_wm_shadow; Atom kde_net_wm_opaque_region; Atom kde_net_wm_tab_group; + Atom kde_first_in_window_list; }; diff --git a/client.cpp b/client.cpp index 52d181a1cc..3c249d7347 100644 --- a/client.cpp +++ b/client.cpp @@ -127,6 +127,7 @@ Client::Client(Workspace* ws) , demandAttentionKNotifyTimer(NULL) , m_responsibleForDecoPixmap(false) , paintRedirector(0) + , m_firstInTabBox(false) , electricMaximizing(false) , activitiesDefined(false) , needsSessionInteract(false) @@ -2393,6 +2394,24 @@ QRect Client::decorationRect() const } } +void Client::updateFirstInTabBox() +{ + // TODO: move into KWindowInfo + Atom type; + int format, status; + unsigned long nitems = 0; + unsigned long extra = 0; + unsigned char *data = 0; + status = XGetWindowProperty(display(), window(), atoms->kde_first_in_window_list, 0, 1, false, atoms->kde_first_in_window_list, &type, &format, &nitems, &extra, &data); + if (status == Success && format == 32 && nitems == 1) { + setFirstInTabBox(true); + } else { + setFirstInTabBox(false); + } + if (data) + XFree(data); +} + } // namespace #include "client.moc" diff --git a/client.h b/client.h index 26c7c74be8..40b4bcd173 100644 --- a/client.h +++ b/client.h @@ -426,6 +426,13 @@ public: TabBox::TabBoxClientImpl* tabBoxClient() const { return m_tabBoxClient; } + bool isFirstInTabBox() const { + return m_firstInTabBox; + } + void setFirstInTabBox(bool enable) { + m_firstInTabBox = enable; + } + void updateFirstInTabBox(); //sets whether the client should be treated as a SessionInteract window void setSessionInteract(bool needed); @@ -718,6 +725,7 @@ private: bool m_responsibleForDecoPixmap; PaintRedirector* paintRedirector; TabBox::TabBoxClientImpl* m_tabBoxClient; + bool m_firstInTabBox; bool electricMaximizing; QuickTileMode electricMode; diff --git a/events.cpp b/events.cpp index fd1147d22a..289e3f7864 100644 --- a/events.cpp +++ b/events.cpp @@ -857,6 +857,8 @@ void Client::propertyNotifyEvent(XPropertyEvent* e) checkActivities(); else if (e->atom == atoms->kde_net_wm_block_compositing) updateCompositeBlocking(true); + else if (e->atom == atoms->kde_first_in_window_list) + updateFirstInTabBox(); break; } } diff --git a/manage.cpp b/manage.cpp index 1877a3d96b..59c7674cbe 100644 --- a/manage.cpp +++ b/manage.cpp @@ -142,6 +142,7 @@ bool Client::manage(Window w, bool isMapped) original_skip_taskbar = skip_taskbar = (info->state() & NET::SkipTaskbar) != 0; skip_pager = (info->state() & NET::SkipPager) != 0; + updateFirstInTabBox(); setupCompositing(); diff --git a/tabbox/clientmodel.cpp b/tabbox/clientmodel.cpp index 92c748dbb5..4ca7fef80a 100644 --- a/tabbox/clientmodel.cpp +++ b/tabbox/clientmodel.cpp @@ -175,6 +175,7 @@ void ClientModel::createClientList(int desktop, bool partialReset) start = m_clientList.first(); m_clientList.clear(); + QList stickyClients; switch(tabBox->config().clientSwitchingMode()) { case TabBoxConfig::FocusChainSwitching: { @@ -190,6 +191,9 @@ void ClientModel::createClientList(int desktop, bool partialReset) m_clientList.prepend(add); } else m_clientList += add; + if (add->isFirstInTabBox()) { + stickyClients << add; + } } c = tabBox->nextClientFocusChain(c); @@ -214,6 +218,9 @@ void ClientModel::createClientList(int desktop, bool partialReset) m_clientList.prepend(add); } else m_clientList += add; + if (add->isFirstInTabBox()) { + stickyClients << add; + } } if (index >= stacking.size() - 1) { c = NULL; @@ -227,6 +234,10 @@ void ClientModel::createClientList(int desktop, bool partialReset) break; } } + foreach (TabBoxClient *c, stickyClients) { + m_clientList.removeAll(c); + m_clientList.prepend(c); + } if (tabBox->config().isShowDesktop()) { TabBoxClient* desktopClient = tabBox->desktopClient(); if (desktopClient) diff --git a/tabbox/tabbox.cpp b/tabbox/tabbox.cpp index a84081015a..6f458578c0 100644 --- a/tabbox/tabbox.cpp +++ b/tabbox/tabbox.cpp @@ -297,6 +297,11 @@ void TabBoxClientImpl::close() m_client->closeWindow(); } +bool TabBoxClientImpl::isFirstInTabBox() const +{ + return m_client->isFirstInTabBox(); +} + /********************************************************* * TabBox *********************************************************/ diff --git a/tabbox/tabbox.h b/tabbox/tabbox.h index a0d5a8bce5..716cf7e0cb 100644 --- a/tabbox/tabbox.h +++ b/tabbox/tabbox.h @@ -83,6 +83,7 @@ public: virtual int height() const; virtual bool isCloseable() const; virtual void close(); + virtual bool isFirstInTabBox() const; Client* client() const { return m_client; diff --git a/tabbox/tabboxhandler.h b/tabbox/tabboxhandler.h index ec15cd5d07..00cc3e7590 100644 --- a/tabbox/tabboxhandler.h +++ b/tabbox/tabboxhandler.h @@ -401,6 +401,7 @@ public: virtual int height() const = 0; virtual bool isCloseable() const = 0; virtual void close() = 0; + virtual bool isFirstInTabBox() const = 0; }; /**