aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregor Bollerhey <gbsoftware@arcor.de>2013-12-14 07:43:26 (GMT)
committerJan Sucan <jan@jansucan.com>2020-04-05 07:47:18 (GMT)
commit7e762f0a972b7714f76a94e537dd65d0067f67b2 (patch)
tree86968d8a594d15513efffc42cc559a62797f4e7e
parent53fa0d6aaca3eb8a1fe8011e0e3d53cb85e1a772 (diff)
downloadfluxbox-7e762f0a972b7714f76a94e537dd65d0067f67b2.zip
fluxbox-7e762f0a972b7714f76a94e537dd65d0067f67b2.tar.bz2
Make systray icon pinning available.
The user options screenname.systray.pinLeft and screenname.systray.pinRight in .fluxbox/init are read as comma sperated list of window classnames. While preserving the order of the lists, systray icons are sorted so that pinLeft'ed classnames appear left and vice versa.
-rw-r--r--src/SystemTray.cc89
-rw-r--r--src/SystemTray.hh7
2 files changed, 91 insertions, 5 deletions
diff --git a/src/SystemTray.cc b/src/SystemTray.cc
index 4fa9da3..4b2cf56 100644
--- a/src/SystemTray.cc
+++ b/src/SystemTray.cc
@@ -37,6 +37,11 @@
37#include <X11/Xatom.h> 37#include <X11/Xatom.h>
38 38
39#include <string> 39#include <string>
40#include <sstream>
41#include <vector>
42#include <memory>
43#include <algorithm>
44#include <functional>
40 45
41 46
42using std::string; 47using std::string;
@@ -161,7 +166,6 @@ public:
161 winclient.setEventMask(StructureNotifyMask | 166 winclient.setEventMask(StructureNotifyMask |
162 SubstructureNotifyMask | EnterWindowMask); 167 SubstructureNotifyMask | EnterWindowMask);
163 m_tray.addClient(winclient.window(), false); 168 m_tray.addClient(winclient.window(), false);
164
165 }; 169 };
166 170
167 void updateWorkarea(BScreen &) { } 171 void updateWorkarea(BScreen &) { }
@@ -192,7 +196,13 @@ SystemTray::SystemTray(const FbTk::FbWindow& parent,
192 m_theme(theme), 196 m_theme(theme),
193 m_screen(screen), 197 m_screen(screen),
194 m_pixmap(0), m_num_visible_clients(0), 198 m_pixmap(0), m_num_visible_clients(0),
195 m_selection_owner(m_window, 0, 0, 1, 1, SubstructureNotifyMask, false, false, CopyFromParent, InputOnly) { 199 m_selection_owner(m_window, 0, 0, 1, 1, SubstructureNotifyMask, false, false, CopyFromParent, InputOnly),
200 m_rc_systray_pinleft(screen.resourceManager(),
201 "", screen.name() + ".systray.pinLeft",
202 screen.altName() + ".Systray.PinLeft"),
203 m_rc_systray_pinright(screen.resourceManager(),
204 "", screen.name() + ".systray.pinRight",
205 screen.altName() + ".Systray.PinRight") {
196 206
197 FbTk::EventManager::instance()->add(*this, m_window); 207 FbTk::EventManager::instance()->add(*this, m_window);
198 FbTk::EventManager::instance()->add(*this, m_selection_owner); 208 FbTk::EventManager::instance()->add(*this, m_selection_owner);
@@ -456,6 +466,9 @@ void SystemTray::handleEvent(XEvent &event) {
456 // check and see if we need to update it's size 466 // check and see if we need to update it's size
457 // and we must reposition and resize them to fit 467 // and we must reposition and resize them to fit
458 // our toolbar 468 // our toolbar
469
470 sortClients();
471
459 ClientList::iterator it = findClient(event.xconfigure.window); 472 ClientList::iterator it = findClient(event.xconfigure.window);
460 if (it != m_clients.end()) { 473 if (it != m_clients.end()) {
461 if (static_cast<unsigned int>(event.xconfigure.width) != (*it)->width() || 474 if (static_cast<unsigned int>(event.xconfigure.width) != (*it)->width() ||
@@ -473,7 +486,6 @@ void SystemTray::handleEvent(XEvent &event) {
473 resizeSig().emit(); 486 resizeSig().emit();
474 } 487 }
475 } 488 }
476
477 } else if (event.type == PropertyNotify) { 489 } else if (event.type == PropertyNotify) {
478 ClientList::iterator it = findClient(event.xproperty.window); 490 ClientList::iterator it = findClient(event.xproperty.window);
479 if (it != m_clients.end()) { 491 if (it != m_clients.end()) {
@@ -484,8 +496,7 @@ void SystemTray::handleEvent(XEvent &event) {
484 hideClient(*it); 496 hideClient(*it);
485 } 497 }
486 } 498 }
487 } 499 }
488
489} 500}
490 501
491void SystemTray::rearrangeClients() { 502void SystemTray::rearrangeClients() {
@@ -556,6 +567,74 @@ void SystemTray::showClient(TrayWindow *traywin) {
556 rearrangeClients(); 567 rearrangeClients();
557} 568}
558 569
570static std::string trim(const std::string& str)
571{
572 const std::string whitespace(" \t");
573 const auto strBegin = str.find_first_not_of(whitespace);
574 if (strBegin == std::string::npos)
575 return ""; // no content
576
577 const auto strEnd = str.find_last_not_of(whitespace);
578 const auto strRange = strEnd - strBegin + 1;
579
580 return str.substr(strBegin, strRange);
581}
582
583static void parse_order(const std::string s, std::vector<std::string> &out) {
584 std::stringstream ss(s);
585 std::string item;
586
587 while (std::getline(ss, item, ','))
588 out.push_back(trim(item));
589}
590
591static int client_to_ordinal(const std::vector<std::string> left,
592 const std::vector<std::string> right,
593 TrayWindow *i) {
594
595 std::unique_ptr<XClassHint> xclasshint (XAllocClassHint());
596 if(XGetClassHint(Fluxbox::instance()->display(),
597 i->window(), xclasshint.get()) != BadWindow)
598 {
599 std::string classname(xclasshint.get()->res_class);
600
601 auto ix = std::find(left.begin(), left.end(), classname);
602 if (ix != left.end())
603 return -(left.end()-ix); // the more left, the negative (<0)
604 else {
605 ix = std::find(right.begin(), right.end(), classname);
606 if (ix != right.end())
607 // the more right, the positive (>0)
608 return ix-right.begin()+1;
609 }
610 }
611
612 // in neither list or invalid window (=0)
613 return 0;
614}
615
616static bool client_comperator(const std::vector<std::string> left,
617 const std::vector<std::string> right,
618 TrayWindow *item1, TrayWindow *item2) {
619 const int a = client_to_ordinal(left, right, item1);
620 const int b = client_to_ordinal(left, right, item2);
621 return a<b;
622}
623
624
625void SystemTray::sortClients() {
626 std::vector<std::string> pinleft, pinright;
627
628 parse_order(m_rc_systray_pinleft, pinleft);
629 parse_order(m_rc_systray_pinright, pinright);
630
631 m_clients.sort(std::bind(client_comperator,
632 pinleft, pinright,
633 std::placeholders::_1, std::placeholders::_2));
634
635 rearrangeClients();
636}
637
559void SystemTray::update() { 638void SystemTray::update() {
560 639
561 if (!m_theme->texture().usePixmap()) { 640 if (!m_theme->texture().usePixmap()) {
diff --git a/src/SystemTray.hh b/src/SystemTray.hh
index 16e703e..b9fd75a 100644
--- a/src/SystemTray.hh
+++ b/src/SystemTray.hh
@@ -26,12 +26,14 @@
26#include "FbTk/FbWindow.hh" 26#include "FbTk/FbWindow.hh"
27#include "FbTk/EventHandler.hh" 27#include "FbTk/EventHandler.hh"
28#include "FbTk/Signal.hh" 28#include "FbTk/Signal.hh"
29#include "FbTk/Resource.hh"
29 30
30#include "ToolTheme.hh" 31#include "ToolTheme.hh"
31#include "ToolbarItem.hh" 32#include "ToolbarItem.hh"
32 33
33#include <list> 34#include <list>
34#include <memory> 35#include <memory>
36#include <string>
35 37
36class BScreen; 38class BScreen;
37class ButtonTheme; 39class ButtonTheme;
@@ -91,6 +93,7 @@ public:
91 93
92private: 94private:
93 void update(); 95 void update();
96 void sortClients();
94 97
95 class TrayWindow; 98 class TrayWindow;
96 typedef std::list<TrayWindow*> ClientList; 99 typedef std::list<TrayWindow*> ClientList;
@@ -114,6 +117,10 @@ private:
114 // gaim/pidgin seems to barf if the selection is not an independent window. 117 // gaim/pidgin seems to barf if the selection is not an independent window.
115 // I suspect it's an interacton with parent relationship and gdk window caching. 118 // I suspect it's an interacton with parent relationship and gdk window caching.
116 FbTk::FbWindow m_selection_owner; 119 FbTk::FbWindow m_selection_owner;
120
121 // resources
122 FbTk::Resource<std::string> m_rc_systray_pinleft;
123 FbTk::Resource<std::string> m_rc_systray_pinright;
117}; 124};
118 125
119#endif // SYSTEMTRAY_HH 126#endif // SYSTEMTRAY_HH