aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/SystemTray.cc131
-rw-r--r--src/SystemTray.hh1
2 files changed, 64 insertions, 68 deletions
diff --git a/src/SystemTray.cc b/src/SystemTray.cc
index af534f6..2d1b316 100644
--- a/src/SystemTray.cc
+++ b/src/SystemTray.cc
@@ -41,7 +41,6 @@
41#include <vector> 41#include <vector>
42#include <memory> 42#include <memory>
43#include <algorithm> 43#include <algorithm>
44#include <functional>
45 44
46 45
47using std::string; 46using std::string;
@@ -84,6 +83,31 @@ void getScreenCoordinates(Window win, int x, int y, int &screen_x, int &screen_y
84 83
85static SystemTray *s_theoneandonly = 0; 84static SystemTray *s_theoneandonly = 0;
86 85
86static std::string trim(const std::string& str)
87{
88 // removes trailing and leading whitespace from a string
89
90 const std::string whitespace(" \t");
91 const auto strBegin = str.find_first_not_of(whitespace);
92 if (strBegin == std::string::npos)
93 return ""; // no content
94
95 const auto strEnd = str.find_last_not_of(whitespace);
96 const auto strRange = strEnd - strBegin + 1;
97
98 return str.substr(strBegin, strRange);
99}
100
101static void parse_order(const std::string s, std::vector<std::string> &out) {
102 // splits a comma seperated list and performs trimming
103
104 std::stringstream ss(s);
105 std::string item;
106
107 while (std::getline(ss, item, ','))
108 out.push_back(trim(item));
109}
110
87/// helper class for tray windows, so we dont call XDestroyWindow 111/// helper class for tray windows, so we dont call XDestroyWindow
88class SystemTray::TrayWindow : public FbTk::FbWindow { 112class SystemTray::TrayWindow : public FbTk::FbWindow {
89public: 113public:
@@ -91,6 +115,8 @@ public:
91 setEventMask(PropertyChangeMask); 115 setEventMask(PropertyChangeMask);
92 } 116 }
93 117
118 void pinByClassname(const std::vector<std::string> left, const std::vector<std::string> right);
119
94 bool isVisible() { return m_visible; } 120 bool isVisible() { return m_visible; }
95 bool isXEmbedded() { return m_xembedded; } 121 bool isXEmbedded() { return m_xembedded; }
96 void show() { 122 void show() {
@@ -133,6 +159,34 @@ private:
133 bool m_xembedded; // using xembed protocol? (i.e. unmap when done) 159 bool m_xembedded; // using xembed protocol? (i.e. unmap when done)
134}; 160};
135 161
162void TrayWindow::pinByClassname(const std::vector<std::string> left,
163 const std::vector<std::string> right) {
164 // based on the parsed order list and a given window returns an
165 // ordinal used to sort the tray icons.
166
167 auto deleter = [](XClassHint *x){if(x) XFree(x);};
168
169 std::unique_ptr<XClassHint, decltype(deleter)>
170 xclasshint(XAllocClassHint(), deleter);
171
172 if(XGetClassHint(Fluxbox::instance()->display(),
173 this->window(), xclasshint.get()))
174 {
175 std::string classname(xclasshint.get()->res_class);
176
177 auto ix = std::find(left.begin(), left.end(), classname);
178 if (ix != left.end())
179 m_order = -(left.end()-ix); // the more left, the negative (<0)
180 else {
181 ix = std::find(right.begin(), right.end(), classname);
182 if (ix != right.end())
183 // the more right, the positive (>0)
184 m_order = ix-right.begin()+1;
185 }
186 }
187 // in neither list or invalid window (=0)
188}
189
136/// handles clientmessage event and notifies systemtray 190/// handles clientmessage event and notifies systemtray
137class SystemTrayHandler: public AtomHandler { 191class SystemTrayHandler: public AtomHandler {
138public: 192public:
@@ -205,6 +259,9 @@ SystemTray::SystemTray(const FbTk::FbWindow& parent,
205 "", screen.name() + ".systray.pinRight", 259 "", screen.name() + ".systray.pinRight",
206 screen.altName() + ".Systray.PinRight") { 260 screen.altName() + ".Systray.PinRight") {
207 261
262 parse_order(m_rc_systray_pinleft, m_pinleft);
263 parse_order(m_rc_systray_pinright, m_pinright);
264
208 FbTk::EventManager::instance()->add(*this, m_window); 265 FbTk::EventManager::instance()->add(*this, m_window);
209 FbTk::EventManager::instance()->add(*this, m_selection_owner); 266 FbTk::EventManager::instance()->add(*this, m_selection_owner);
210 // setup signals 267 // setup signals
@@ -427,6 +484,9 @@ void SystemTray::addClient(Window win, bool using_xembed) {
427 484
428 if (traywin->getMappedDefault()) 485 if (traywin->getMappedDefault())
429 showClient(traywin); 486 showClient(traywin);
487
488 traywin->pinByClassname(m_pinleft, m_pinright);
489 sortClients();
430} 490}
431 491
432void SystemTray::removeClient(Window win, bool destroyed) { 492void SystemTray::removeClient(Window win, bool destroyed) {
@@ -444,6 +504,8 @@ void SystemTray::removeClient(Window win, bool destroyed) {
444 } 504 }
445 hideClient(traywin, destroyed); 505 hideClient(traywin, destroyed);
446 delete traywin; 506 delete traywin;
507
508 sortClients();
447} 509}
448 510
449void SystemTray::exposeEvent(XExposeEvent &event) { 511void SystemTray::exposeEvent(XExposeEvent &event) {
@@ -468,8 +530,6 @@ void SystemTray::handleEvent(XEvent &event) {
468 // and we must reposition and resize them to fit 530 // and we must reposition and resize them to fit
469 // our toolbar 531 // our toolbar
470 532
471 sortClients();
472
473 ClientList::iterator it = findClient(event.xconfigure.window); 533 ClientList::iterator it = findClient(event.xconfigure.window);
474 if (it != m_clients.end()) { 534 if (it != m_clients.end()) {
475 if (static_cast<unsigned int>(event.xconfigure.width) != (*it)->width() || 535 if (static_cast<unsigned int>(event.xconfigure.width) != (*it)->width() ||
@@ -568,73 +628,8 @@ void SystemTray::showClient(TrayWindow *traywin) {
568 rearrangeClients(); 628 rearrangeClients();
569} 629}
570 630
571static std::string trim(const std::string& str)
572{
573 // removes trailing and leading whitespace from a string
574
575 const std::string whitespace(" \t");
576 const auto strBegin = str.find_first_not_of(whitespace);
577 if (strBegin == std::string::npos)
578 return ""; // no content
579
580 const auto strEnd = str.find_last_not_of(whitespace);
581 const auto strRange = strEnd - strBegin + 1;
582
583 return str.substr(strBegin, strRange);
584}
585
586static void parse_order(const std::string s, std::vector<std::string> &out) {
587 // splits a comma seperated list and performs trimming
588
589 std::stringstream ss(s);
590 std::string item;
591
592 while (std::getline(ss, item, ','))
593 out.push_back(trim(item));
594}
595
596static int client_to_ordinal(const std::vector<std::string> left,
597 const std::vector<std::string> right,
598 TrayWindow *i) {
599 // based on the parsed order list and a given window returns an
600 // ordinal used to sort the tray icons.
601
602 auto deleter = [](XClassHint *x){if(x) XFree(x);};
603
604 std::unique_ptr<XClassHint, decltype(deleter)>
605 xclasshint(XAllocClassHint(), deleter);
606
607 if(XGetClassHint(Fluxbox::instance()->display(),
608 i->window(), xclasshint.get()))
609 {
610 std::string classname(xclasshint.get()->res_class);
611
612 auto ix = std::find(left.begin(), left.end(), classname);
613 if (ix != left.end())
614 return -(left.end()-ix); // the more left, the negative (<0)
615 else {
616 ix = std::find(right.begin(), right.end(), classname);
617 if (ix != right.end())
618 // the more right, the positive (>0)
619 return ix-right.begin()+1;
620 }
621 }
622
623 // in neither list or invalid window (=0)
624 return 0;
625}
626
627void SystemTray::sortClients() { 631void SystemTray::sortClients() {
628 std::vector<std::string> pinleft, pinright;
629
630 parse_order(m_rc_systray_pinleft, pinleft);
631 parse_order(m_rc_systray_pinright, pinright);
632
633 for(TrayWindow *i: m_clients)
634 i->m_order = client_to_ordinal(pinleft, pinright, i);
635
636 m_clients.sort([](TrayWindow *a, TrayWindow *b){return a->m_order < b->m_order;}); 632 m_clients.sort([](TrayWindow *a, TrayWindow *b){return a->m_order < b->m_order;});
637
638 rearrangeClients(); 633 rearrangeClients();
639} 634}
640 635
diff --git a/src/SystemTray.hh b/src/SystemTray.hh
index b9fd75a..c1485f6 100644
--- a/src/SystemTray.hh
+++ b/src/SystemTray.hh
@@ -121,6 +121,7 @@ private:
121 // resources 121 // resources
122 FbTk::Resource<std::string> m_rc_systray_pinleft; 122 FbTk::Resource<std::string> m_rc_systray_pinleft;
123 FbTk::Resource<std::string> m_rc_systray_pinright; 123 FbTk::Resource<std::string> m_rc_systray_pinright;
124 std::vector<std::string> m_pinleft, m_pinright;
124}; 125};
125 126
126#endif // SYSTEMTRAY_HH 127#endif // SYSTEMTRAY_HH