aboutsummaryrefslogtreecommitdiff
path: root/src/SystemTray.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/SystemTray.cc')
-rw-r--r--src/SystemTray.cc93
1 files changed, 71 insertions, 22 deletions
diff --git a/src/SystemTray.cc b/src/SystemTray.cc
index ab64f20..c4b9331 100644
--- a/src/SystemTray.cc
+++ b/src/SystemTray.cc
@@ -1,5 +1,5 @@
1// SystemTray.cc 1// SystemTray.cc
2// Copyright (c) 2003-2004 Henrik Kinnunen (fluxgen at users.sourceforge.net) 2// Copyright (c) 2003-2005 Henrik Kinnunen (fluxgen at users.sourceforge.net)
3// 3//
4// Permission is hereby granted, free of charge, to any person obtaining a 4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"), 5// copy of this software and associated documentation files (the "Software"),
@@ -24,6 +24,7 @@
24#include "SystemTray.hh" 24#include "SystemTray.hh"
25 25
26#include "FbTk/EventManager.hh" 26#include "FbTk/EventManager.hh"
27#include "FbTk/ImageControl.hh"
27 28
28#include "AtomHandler.hh" 29#include "AtomHandler.hh"
29#include "fluxbox.hh" 30#include "fluxbox.hh"
@@ -49,7 +50,7 @@ public:
49 SystemTrayHandler(SystemTray &tray):m_tray(tray) { 50 SystemTrayHandler(SystemTray &tray):m_tray(tray) {
50 } 51 }
51 // client message is the only thing we care about 52 // client message is the only thing we care about
52 bool checkClientMessage(const XClientMessageEvent &ce, 53 bool checkClientMessage(const XClientMessageEvent &ce,
53 BScreen * screen, WinClient * const winclient) { 54 BScreen * screen, WinClient * const winclient) {
54 // must be on the same screen 55 // must be on the same screen
55 if ((screen && screen->screenNumber() != m_tray.window().screenNumber()) || 56 if ((screen && screen->screenNumber() != m_tray.window().screenNumber()) ||
@@ -60,11 +61,11 @@ public:
60 61
61 void initForScreen(BScreen &screen) { }; 62 void initForScreen(BScreen &screen) { };
62 void setupFrame(FluxboxWindow &win) { }; 63 void setupFrame(FluxboxWindow &win) { };
63 void setupClient(WinClient &winclient) { 64 void setupClient(WinClient &winclient) {
64 // must be on the same screen 65 // must be on the same screen
65 if (winclient.screenNumber() != m_tray.window().screenNumber()) 66 if (winclient.screenNumber() != m_tray.window().screenNumber())
66 return; 67 return;
67 68
68 // we dont want a managed window 69 // we dont want a managed window
69 if (winclient.fbwindow() != 0) 70 if (winclient.fbwindow() != 0)
70 return; 71 return;
@@ -100,15 +101,19 @@ private:
100 SystemTray &m_tray; 101 SystemTray &m_tray;
101}; 102};
102 103
103SystemTray::SystemTray(const FbTk::FbWindow &parent): 104SystemTray::SystemTray(const FbTk::FbWindow& parent, ButtonTheme& theme, BScreen& screen):
104 ToolbarItem(ToolbarItem::FIXED), 105 ToolbarItem(ToolbarItem::FIXED),
105 m_window(parent, 0, 0, 1, 1, ExposureMask | ButtonPressMask | ButtonReleaseMask | 106 m_window(parent, 0, 0, 1, 1, ExposureMask | ButtonPressMask | ButtonReleaseMask |
106 SubstructureNotifyMask | SubstructureRedirectMask) { 107 SubstructureNotifyMask | SubstructureRedirectMask),
108 m_theme(theme),
109 m_screen(screen),
110 m_pixmap(0) {
107 111
108 FbTk::EventManager::instance()->add(*this, m_window); 112 FbTk::EventManager::instance()->add(*this, m_window);
113 m_theme.reconfigSig().attach(this);
109 114
110 // just try to blend in... (better than defaulting to white) 115 Fluxbox* fluxbox = Fluxbox::instance();
111 m_window.setBackgroundPixmap(ParentRelative); 116 Display *disp = fluxbox->display();
112 117
113 // setup atom name to _NET_SYSTEM_TRAY_S<screen number> 118 // setup atom name to _NET_SYSTEM_TRAY_S<screen number>
114 char intbuff[16]; 119 char intbuff[16];
@@ -116,8 +121,6 @@ SystemTray::SystemTray(const FbTk::FbWindow &parent):
116 std::string atom_name("_NET_SYSTEM_TRAY_S"); 121 std::string atom_name("_NET_SYSTEM_TRAY_S");
117 atom_name += intbuff; // append number 122 atom_name += intbuff; // append number
118 123
119 Display *disp = FbTk::App::instance()->display();
120
121 // get selection owner and see if it's free 124 // get selection owner and see if it's free
122 Atom tray_atom = XInternAtom(disp, atom_name.c_str(), False); 125 Atom tray_atom = XInternAtom(disp, atom_name.c_str(), False);
123 Window owner = XGetSelectionOwner(disp, tray_atom); 126 Window owner = XGetSelectionOwner(disp, tray_atom);
@@ -134,11 +137,14 @@ SystemTray::SystemTray(const FbTk::FbWindow &parent):
134#endif // DEBUG 137#endif // DEBUG
135 // set owner 138 // set owner
136 XSetSelectionOwner(disp, tray_atom, m_window.window(), CurrentTime); 139 XSetSelectionOwner(disp, tray_atom, m_window.window(), CurrentTime);
140
137 m_handler.reset(new SystemTrayHandler(*this)); 141 m_handler.reset(new SystemTrayHandler(*this));
138 Fluxbox::instance()->addAtomHandler(m_handler.get(), atom_name); 142
139 Window root_window = RootWindow(disp, m_window.screenNumber()); 143 fluxbox->addAtomHandler(m_handler.get(), atom_name);
144
140 145
141 // send selection owner msg 146 // send selection owner msg
147 Window root_window = m_screen.rootWindow().window();
142 XEvent ce; 148 XEvent ce;
143 ce.xclient.type = ClientMessage; 149 ce.xclient.type = ClientMessage;
144 ce.xclient.message_type = XInternAtom(disp, "MANAGER", False); 150 ce.xclient.message_type = XInternAtom(disp, "MANAGER", False);
@@ -153,12 +159,17 @@ SystemTray::SystemTray(const FbTk::FbWindow &parent):
153 159
154 XSendEvent(disp, root_window, false, StructureNotifyMask, &ce); 160 XSendEvent(disp, root_window, false, StructureNotifyMask, &ce);
155 161
162 update(0);
156} 163}
157 164
158SystemTray::~SystemTray() { 165SystemTray::~SystemTray() {
159 // remove us, else fluxbox might delete the memory too 166 // remove us, else fluxbox might delete the memory too
160 Fluxbox::instance()->removeAtomHandler(m_handler.get()); 167 Fluxbox::instance()->removeAtomHandler(m_handler.get());
161 removeAllClients(); 168 removeAllClients();
169
170 if (m_pixmap)
171 m_screen.imageControl().removeImage(m_pixmap);
172
162 // ~FbWindow cleans EventManager 173 // ~FbWindow cleans EventManager
163} 174}
164 175
@@ -196,11 +207,13 @@ void SystemTray::hide() {
196} 207}
197 208
198void SystemTray::show() { 209void SystemTray::show() {
210
211 update(0);
199 m_window.show(); 212 m_window.show();
200} 213}
201 214
202unsigned int SystemTray::width() const { 215unsigned int SystemTray::width() const {
203 return m_clients.size()*height(); 216 return m_clients.size()* (height() - 2 * m_theme.border().width());
204} 217}
205 218
206unsigned int SystemTray::height() const { 219unsigned int SystemTray::height() const {
@@ -216,7 +229,7 @@ bool SystemTray::clientMessage(const XClientMessageEvent &event) {
216 // static const int SYSTEM_TRAY_BEGIN_MESSAGE = 1; 229 // static const int SYSTEM_TRAY_BEGIN_MESSAGE = 1;
217 // static const int SYSTEM_TRAY_CANCEL_MESSAGE = 2; 230 // static const int SYSTEM_TRAY_CANCEL_MESSAGE = 2;
218 231
219 if (event.message_type == 232 if (event.message_type ==
220 XInternAtom(FbTk::App::instance()->display(), "_NET_SYSTEM_TRAY_OPCODE", False)) { 233 XInternAtom(FbTk::App::instance()->display(), "_NET_SYSTEM_TRAY_OPCODE", False)) {
221 234
222 int type = event.data.l[1]; 235 int type = event.data.l[1];
@@ -264,8 +277,8 @@ void SystemTray::addClient(Window win) {
264 XWindowAttributes attr; 277 XWindowAttributes attr;
265 attr.screen = 0; 278 attr.screen = 0;
266 if (XGetWindowAttributes(FbTk::App::instance()->display(), 279 if (XGetWindowAttributes(FbTk::App::instance()->display(),
267 win, &attr) != 0 && 280 win, &attr) != 0 &&
268 attr.screen != 0 && 281 attr.screen != 0 &&
269 XScreenNumberOfScreen(attr.screen) != window().screenNumber()) { 282 XScreenNumberOfScreen(attr.screen) != window().screenNumber()) {
270 return; 283 return;
271 } 284 }
@@ -313,12 +326,13 @@ void SystemTray::removeClient(Window win) {
313 326
314void SystemTray::exposeEvent(XExposeEvent &event) { 327void SystemTray::exposeEvent(XExposeEvent &event) {
315 m_window.clear(); 328 m_window.clear();
329 update(0);
316} 330}
317 331
318void SystemTray::handleEvent(XEvent &event) { 332void SystemTray::handleEvent(XEvent &event) {
319 if (event.type == DestroyNotify) { 333 if (event.type == DestroyNotify) {
320 removeClient(event.xdestroywindow.window); 334 removeClient(event.xdestroywindow.window);
321 } else if (event.type == UnmapNotify && event.xany.send_event) { 335 } else if (event.type == UnmapNotify && event.xany.send_event) {
322 // we ignore server-generated events, which can occur 336 // we ignore server-generated events, which can occur
323 // on restart. The ICCCM says that a client must send 337 // on restart. The ICCCM says that a client must send
324 // a synthetic event for the withdrawn state 338 // a synthetic event for the withdrawn state
@@ -326,7 +340,7 @@ void SystemTray::handleEvent(XEvent &event) {
326 } else if (event.type == ConfigureNotify) { 340 } else if (event.type == ConfigureNotify) {
327 // we got configurenotify from an client 341 // we got configurenotify from an client
328 // check and see if we need to update it's size 342 // check and see if we need to update it's size
329 // and we must reposition and resize them to fit 343 // and we must reposition and resize them to fit
330 // our toolbar 344 // our toolbar
331 ClientList::iterator it = findClient(event.xconfigure.window); 345 ClientList::iterator it = findClient(event.xconfigure.window);
332 if (it != m_clients.end()) { 346 if (it != m_clients.end()) {
@@ -345,15 +359,19 @@ void SystemTray::handleEvent(XEvent &event) {
345} 359}
346 360
347void SystemTray::rearrangeClients() { 361void SystemTray::rearrangeClients() {
348 // move and resize clients 362 // move and resize clients
349 ClientList::iterator client_it = m_clients.begin(); 363 ClientList::iterator client_it = m_clients.begin();
350 ClientList::iterator client_it_end = m_clients.end(); 364 ClientList::iterator client_it_end = m_clients.end();
351 int next_x = 0; 365 int next_x = 0;
352 for (; client_it != client_it_end; ++client_it, next_x += height()) { 366 const unsigned int h = height();
353 (*client_it)->moveResize(next_x, 0, height(), height()); 367 const unsigned int b = m_theme.border().width();
368 for (; client_it != client_it_end;
369 ++client_it, next_x += h - 2 * b) {
370 (*client_it)->moveResize(next_x, b, h - b, h - b);
354 } 371 }
355 372
356 resize(next_x, height()); 373 resize(next_x, height());
374 update(0);
357} 375}
358 376
359void SystemTray::removeAllClients() { 377void SystemTray::removeAllClients() {
@@ -366,3 +384,34 @@ void SystemTray::removeAllClients() {
366 m_clients.pop_back(); 384 m_clients.pop_back();
367 } 385 }
368} 386}
387
388void SystemTray::update(FbTk::Subject* subject) {
389
390 if (!m_theme.texture().usePixmap()) {
391 m_window.setBackgroundColor(m_theme.texture().color());
392 }
393 else {
394 if(m_pixmap)
395 m_screen.imageControl().removeImage(m_pixmap);
396 m_pixmap = m_screen.imageControl().renderImage(width(), height(),
397 m_theme.texture());
398 m_window.setBackgroundPixmap(m_pixmap);
399 }
400
401 // "themereconfigure"
402 if (subject) {
403 ClientList::iterator client_it = m_clients.begin();
404 ClientList::iterator client_it_end = m_clients.end();
405 int next_x = 0;
406 const unsigned int h = height();
407 const unsigned int b = m_theme.border().width();
408 for (; client_it != client_it_end;
409 ++client_it, next_x += h - 2 * b) {
410
411 // maybe not the best solution (yet), force a refresh of the
412 // background of the client
413 (*client_it)->hide();
414 (*client_it)->show();
415 }
416 }
417}