diff options
Diffstat (limited to 'src/SystemTray.cc')
-rw-r--r-- | src/SystemTray.cc | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/src/SystemTray.cc b/src/SystemTray.cc index fdccda0..00d9b11 100644 --- a/src/SystemTray.cc +++ b/src/SystemTray.cc | |||
@@ -52,6 +52,7 @@ public: | |||
52 | TrayWindow(Window win):FbTk::FbWindow(win), m_visible(false) { | 52 | TrayWindow(Window win):FbTk::FbWindow(win), m_visible(false) { |
53 | setEventMask(PropertyChangeMask); | 53 | setEventMask(PropertyChangeMask); |
54 | } | 54 | } |
55 | |||
55 | bool isVisible() { return m_visible; } | 56 | bool isVisible() { return m_visible; } |
56 | void show() { | 57 | void show() { |
57 | if (!m_visible) { | 58 | if (!m_visible) { |
@@ -65,6 +66,7 @@ public: | |||
65 | FbTk::FbWindow::hide(); | 66 | FbTk::FbWindow::hide(); |
66 | } | 67 | } |
67 | } | 68 | } |
69 | |||
68 | private: | 70 | private: |
69 | bool m_visible; | 71 | bool m_visible; |
70 | }; | 72 | }; |
@@ -132,9 +134,11 @@ SystemTray::SystemTray(const FbTk::FbWindow& parent, ButtonTheme& theme, BScreen | |||
132 | SubstructureNotifyMask | SubstructureRedirectMask), | 134 | SubstructureNotifyMask | SubstructureRedirectMask), |
133 | m_theme(theme), | 135 | m_theme(theme), |
134 | m_screen(screen), | 136 | m_screen(screen), |
135 | m_pixmap(0), m_num_visible_clients(0) { | 137 | m_pixmap(0), m_num_visible_clients(0), |
136 | 138 | m_selection_owner(m_window, 0, 0, 1, 1, SubstructureNotifyMask, false, false, CopyFromParent, InputOnly) { | |
139 | |||
137 | FbTk::EventManager::instance()->add(*this, m_window); | 140 | FbTk::EventManager::instance()->add(*this, m_window); |
141 | FbTk::EventManager::instance()->add(*this, m_selection_owner); | ||
138 | m_theme.reconfigSig().attach(this); | 142 | m_theme.reconfigSig().attach(this); |
139 | screen.bgChangeSig().attach(this); | 143 | screen.bgChangeSig().attach(this); |
140 | 144 | ||
@@ -162,7 +166,7 @@ SystemTray::SystemTray(const FbTk::FbWindow& parent, ButtonTheme& theme, BScreen | |||
162 | cerr<<__FILE__<<"(SystemTray(const FbTk::FbWindow)): SETTING OWNER!"<<endl; | 166 | cerr<<__FILE__<<"(SystemTray(const FbTk::FbWindow)): SETTING OWNER!"<<endl; |
163 | #endif // DEBUG | 167 | #endif // DEBUG |
164 | // set owner | 168 | // set owner |
165 | XSetSelectionOwner(disp, tray_atom, m_window.window(), CurrentTime); | 169 | XSetSelectionOwner(disp, tray_atom, m_selection_owner.window(), CurrentTime); |
166 | 170 | ||
167 | m_handler.reset(new SystemTrayHandler(*this)); | 171 | m_handler.reset(new SystemTrayHandler(*this)); |
168 | 172 | ||
@@ -190,7 +194,20 @@ SystemTray::SystemTray(const FbTk::FbWindow& parent, ButtonTheme& theme, BScreen | |||
190 | 194 | ||
191 | SystemTray::~SystemTray() { | 195 | SystemTray::~SystemTray() { |
192 | // remove us, else fluxbox might delete the memory too | 196 | // remove us, else fluxbox might delete the memory too |
193 | Fluxbox::instance()->removeAtomHandler(m_handler.get()); | 197 | Fluxbox* fluxbox = Fluxbox::instance(); |
198 | fluxbox->removeAtomHandler(m_handler.get()); | ||
199 | Display *disp = fluxbox->display(); | ||
200 | // setup atom name to _NET_SYSTEM_TRAY_S<screen number> | ||
201 | char intbuff[16]; | ||
202 | sprintf(intbuff, "%d", m_window.screenNumber()); | ||
203 | string atom_name("_NET_SYSTEM_TRAY_S"); | ||
204 | atom_name += intbuff; // append number | ||
205 | |||
206 | // get selection owner and see if it's free | ||
207 | Atom tray_atom = XInternAtom(disp, atom_name.c_str(), False); | ||
208 | |||
209 | // Properly give up selection. | ||
210 | XSetSelectionOwner(disp, tray_atom, None, CurrentTime); | ||
194 | removeAllClients(); | 211 | removeAllClients(); |
195 | 212 | ||
196 | if (m_pixmap) | 213 | if (m_pixmap) |
@@ -323,10 +340,11 @@ void SystemTray::addClient(Window win) { | |||
323 | FbTk::EventManager::instance()->add(*this, win); | 340 | FbTk::EventManager::instance()->add(*this, win); |
324 | XChangeSaveSet(FbTk::App::instance()->display(), win, SetModeInsert); | 341 | XChangeSaveSet(FbTk::App::instance()->display(), win, SetModeInsert); |
325 | traywin->reparent(m_window, 0, 0); | 342 | traywin->reparent(m_window, 0, 0); |
343 | traywin->addToSaveSet(); | ||
326 | showClient(traywin); | 344 | showClient(traywin); |
327 | } | 345 | } |
328 | 346 | ||
329 | void SystemTray::removeClient(Window win) { | 347 | void SystemTray::removeClient(Window win, bool destroyed) { |
330 | ClientList::iterator tray_it = findClient(win); | 348 | ClientList::iterator tray_it = findClient(win); |
331 | if (tray_it == m_clients.end()) | 349 | if (tray_it == m_clients.end()) |
332 | return; | 350 | return; |
@@ -336,7 +354,11 @@ void SystemTray::removeClient(Window win) { | |||
336 | #endif // DEBUG | 354 | #endif // DEBUG |
337 | TrayWindow *traywin = *tray_it; | 355 | TrayWindow *traywin = *tray_it; |
338 | m_clients.erase(tray_it); | 356 | m_clients.erase(tray_it); |
339 | hideClient(traywin); | 357 | if (!destroyed) { |
358 | traywin->setEventMask(NoEventMask); | ||
359 | traywin->removeFromSaveSet(); | ||
360 | } | ||
361 | hideClient(traywin, destroyed); | ||
340 | delete traywin; | 362 | delete traywin; |
341 | } | 363 | } |
342 | 364 | ||
@@ -346,9 +368,9 @@ void SystemTray::exposeEvent(XExposeEvent &event) { | |||
346 | 368 | ||
347 | void SystemTray::handleEvent(XEvent &event) { | 369 | void SystemTray::handleEvent(XEvent &event) { |
348 | if (event.type == DestroyNotify) { | 370 | if (event.type == DestroyNotify) { |
349 | removeClient(event.xdestroywindow.window); | 371 | removeClient(event.xdestroywindow.window, true); |
350 | } else if (event.type == ReparentNotify && event.xreparent.parent != m_window.window()) { | 372 | } else if (event.type == ReparentNotify && event.xreparent.parent != m_window.window()) { |
351 | removeClient(event.xreparent.window); | 373 | removeClient(event.xreparent.window, false); |
352 | } else if (event.type == UnmapNotify && event.xany.send_event) { | 374 | } else if (event.type == UnmapNotify && event.xany.send_event) { |
353 | // we ignore server-generated events, which can occur | 375 | // we ignore server-generated events, which can occur |
354 | // on restart. The ICCCM says that a client must send | 376 | // on restart. The ICCCM says that a client must send |
@@ -443,20 +465,23 @@ void SystemTray::rearrangeClients() { | |||
443 | void SystemTray::removeAllClients() { | 465 | void SystemTray::removeAllClients() { |
444 | BScreen *screen = Fluxbox::instance()->findScreen(window().screenNumber()); | 466 | BScreen *screen = Fluxbox::instance()->findScreen(window().screenNumber()); |
445 | while (!m_clients.empty()) { | 467 | while (!m_clients.empty()) { |
468 | m_clients.back()->setEventMask(NoEventMask); | ||
469 | m_clients.back()->hide(); | ||
446 | if (screen) | 470 | if (screen) |
447 | m_clients.back()->reparent(screen->rootWindow(), 0, 0); | 471 | m_clients.back()->reparent(screen->rootWindow(), 0, 0); |
448 | m_clients.back()->hide(); | 472 | m_clients.back()->removeFromSaveSet(); |
449 | delete m_clients.back(); | 473 | delete m_clients.back(); |
450 | m_clients.pop_back(); | 474 | m_clients.pop_back(); |
451 | } | 475 | } |
452 | m_num_visible_clients = 0; | 476 | m_num_visible_clients = 0; |
453 | } | 477 | } |
454 | 478 | ||
455 | void SystemTray::hideClient(TrayWindow *traywin) { | 479 | void SystemTray::hideClient(TrayWindow *traywin, bool destroyed) { |
456 | if (!traywin || !traywin->isVisible()) | 480 | if (!traywin || !traywin->isVisible()) |
457 | return; | 481 | return; |
458 | 482 | ||
459 | traywin->hide(); | 483 | if (!destroyed) |
484 | traywin->hide(); | ||
460 | m_num_visible_clients--; | 485 | m_num_visible_clients--; |
461 | rearrangeClients(); | 486 | rearrangeClients(); |
462 | } | 487 | } |