aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-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