diff options
author | mathias <mathias> | 2005-01-14 09:58:16 (GMT) |
---|---|---|
committer | mathias <mathias> | 2005-01-14 09:58:16 (GMT) |
commit | 69e86c6c25841309daf2c5a6d29e21bd2c11297e (patch) | |
tree | f15147a69ecc0a08d92e5a633d12b49b2fcfc3d6 /src/SystemTray.cc | |
parent | a07d61e63dfc129660cc9bab344c9e040a7f991f (diff) | |
download | fluxbox-69e86c6c25841309daf2c5a6d29e21bd2c11297e.zip fluxbox-69e86c6c25841309daf2c5a6d29e21bd2c11297e.tar.bz2 |
systemtray-tool has now a propper background. its styleable via the
toolbar.systray.* ressource, same way as the clock.
Diffstat (limited to 'src/SystemTray.cc')
-rw-r--r-- | src/SystemTray.cc | 93 |
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 | ||
103 | SystemTray::SystemTray(const FbTk::FbWindow &parent): | 104 | SystemTray::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 | ||
158 | SystemTray::~SystemTray() { | 165 | SystemTray::~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 | ||
198 | void SystemTray::show() { | 209 | void SystemTray::show() { |
210 | |||
211 | update(0); | ||
199 | m_window.show(); | 212 | m_window.show(); |
200 | } | 213 | } |
201 | 214 | ||
202 | unsigned int SystemTray::width() const { | 215 | unsigned 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 | ||
206 | unsigned int SystemTray::height() const { | 219 | unsigned 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 | ||
314 | void SystemTray::exposeEvent(XExposeEvent &event) { | 327 | void SystemTray::exposeEvent(XExposeEvent &event) { |
315 | m_window.clear(); | 328 | m_window.clear(); |
329 | update(0); | ||
316 | } | 330 | } |
317 | 331 | ||
318 | void SystemTray::handleEvent(XEvent &event) { | 332 | void 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 | ||
347 | void SystemTray::rearrangeClients() { | 361 | void 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 | ||
359 | void SystemTray::removeAllClients() { | 377 | void SystemTray::removeAllClients() { |
@@ -366,3 +384,34 @@ void SystemTray::removeAllClients() { | |||
366 | m_clients.pop_back(); | 384 | m_clients.pop_back(); |
367 | } | 385 | } |
368 | } | 386 | } |
387 | |||
388 | void 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 | } | ||