diff options
author | Gregor Bollerhey <gbsoftware@arcor.de> | 2014-01-08 19:38:00 (GMT) |
---|---|---|
committer | Jan Sucan <jan@jansucan.com> | 2020-04-05 07:50:20 (GMT) |
commit | b23aba180ffe8f6af2a2955641b73f764f740f62 (patch) | |
tree | 2624a6074dae27cb9b2173612815b0169c6fcefb /src | |
parent | bb0790d7945d4ed728b374409aa227dce07b0090 (diff) | |
download | fluxbox-b23aba180ffe8f6af2a2955641b73f764f740f62.zip fluxbox-b23aba180ffe8f6af2a2955641b73f764f740f62.tar.bz2 |
Icon order now is property of the SystemTray.
This way it is only parsed once in the constructor. Updating the
TrayWindow order is now a method which is called once when the icon is
created.
sortClients/rearrange is now only called on adding and removing icons.
Diffstat (limited to 'src')
-rw-r--r-- | src/SystemTray.cc | 131 | ||||
-rw-r--r-- | src/SystemTray.hh | 1 |
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 | ||
47 | using std::string; | 46 | using std::string; |
@@ -84,6 +83,31 @@ void getScreenCoordinates(Window win, int x, int y, int &screen_x, int &screen_y | |||
84 | 83 | ||
85 | static SystemTray *s_theoneandonly = 0; | 84 | static SystemTray *s_theoneandonly = 0; |
86 | 85 | ||
86 | static 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 | |||
101 | static 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 |
88 | class SystemTray::TrayWindow : public FbTk::FbWindow { | 112 | class SystemTray::TrayWindow : public FbTk::FbWindow { |
89 | public: | 113 | public: |
@@ -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 | ||
162 | void 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 |
137 | class SystemTrayHandler: public AtomHandler { | 191 | class SystemTrayHandler: public AtomHandler { |
138 | public: | 192 | public: |
@@ -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 | ||
432 | void SystemTray::removeClient(Window win, bool destroyed) { | 492 | void 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 | ||
449 | void SystemTray::exposeEvent(XExposeEvent &event) { | 511 | void 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 | ||
571 | static 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 | |||
586 | static 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 | |||
596 | static 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 | |||
627 | void SystemTray::sortClients() { | 631 | void 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 |