diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | src/Ewmh.cc | 2 | ||||
-rw-r--r-- | src/FbTk/FbWindow.cc | 8 | ||||
-rw-r--r-- | src/FbTk/FbWindow.hh | 3 | ||||
-rw-r--r-- | src/SystemTray.cc | 47 | ||||
-rw-r--r-- | src/SystemTray.hh | 8 | ||||
-rw-r--r-- | src/fluxbox.cc | 2 |
7 files changed, 60 insertions, 14 deletions
@@ -1,5 +1,9 @@ | |||
1 | (Format: Year/Month/Day) | 1 | (Format: Year/Month/Day) |
2 | Changes for 1.0.0: | 2 | Changes for 1.0.0: |
3 | *07/08/05: | ||
4 | * Fix System Tray restart issues (Simon) | ||
5 | (including gaim/pidgin crash-on-restart) | ||
6 | src/SystemTray.hh/cc src/FbTk/FbWindow.hh/cc | ||
3 | *07/07/31: | 7 | *07/07/31: |
4 | * Change _NET_WM_WINDOW_TYPE_MENU to use TINY decoration type (Mark) | 8 | * Change _NET_WM_WINDOW_TYPE_MENU to use TINY decoration type (Mark) |
5 | Ewmh.cc | 9 | Ewmh.cc |
diff --git a/src/Ewmh.cc b/src/Ewmh.cc index fef4428..4bc7e1c 100644 --- a/src/Ewmh.cc +++ b/src/Ewmh.cc | |||
@@ -141,7 +141,7 @@ void Ewmh::initForScreen(BScreen &screen) { | |||
141 | m_net_wm_state_fullscreen, | 141 | m_net_wm_state_fullscreen, |
142 | m_net_wm_state_hidden, | 142 | m_net_wm_state_hidden, |
143 | m_net_wm_state_skip_taskbar, | 143 | m_net_wm_state_skip_taskbar, |
144 | m_net_wm_state_modal, | 144 | // m_net_wm_state_modal, |
145 | m_net_wm_state_below, | 145 | m_net_wm_state_below, |
146 | m_net_wm_state_above, | 146 | m_net_wm_state_above, |
147 | m_net_wm_state_demands_attention, | 147 | m_net_wm_state_demands_attention, |
diff --git a/src/FbTk/FbWindow.cc b/src/FbTk/FbWindow.cc index 2c2bb24..f8141cf 100644 --- a/src/FbTk/FbWindow.cc +++ b/src/FbTk/FbWindow.cc | |||
@@ -556,6 +556,14 @@ void FbWindow::deleteProperty(Atom property) { | |||
556 | XDeleteProperty(display(), m_window, property); | 556 | XDeleteProperty(display(), m_window, property); |
557 | } | 557 | } |
558 | 558 | ||
559 | void FbWindow::addToSaveSet() { | ||
560 | XAddToSaveSet(display(), m_window); | ||
561 | } | ||
562 | |||
563 | void FbWindow::removeFromSaveSet() { | ||
564 | XRemoveFromSaveSet(display(), m_window); | ||
565 | } | ||
566 | |||
559 | int FbWindow::screenNumber() const { | 567 | int FbWindow::screenNumber() const { |
560 | return m_screen_num; | 568 | return m_screen_num; |
561 | } | 569 | } |
diff --git a/src/FbTk/FbWindow.hh b/src/FbTk/FbWindow.hh index a1b93cc..091fb48 100644 --- a/src/FbTk/FbWindow.hh +++ b/src/FbTk/FbWindow.hh | |||
@@ -165,6 +165,9 @@ public: | |||
165 | 165 | ||
166 | std::string textProperty(Atom property) const; | 166 | std::string textProperty(Atom property) const; |
167 | 167 | ||
168 | void addToSaveSet(); | ||
169 | void removeFromSaveSet(); | ||
170 | |||
168 | /// @return parent FbWindow | 171 | /// @return parent FbWindow |
169 | const FbWindow *parent() const { return m_parent; } | 172 | const FbWindow *parent() const { return m_parent; } |
170 | /// @return real X window | 173 | /// @return real X window |
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 | } |
diff --git a/src/SystemTray.hh b/src/SystemTray.hh index 392ca11..557d1e4 100644 --- a/src/SystemTray.hh +++ b/src/SystemTray.hh | |||
@@ -60,7 +60,7 @@ public: | |||
60 | void handleEvent(XEvent &event); | 60 | void handleEvent(XEvent &event); |
61 | 61 | ||
62 | void addClient(Window win); | 62 | void addClient(Window win); |
63 | void removeClient(Window win); | 63 | void removeClient(Window win, bool destroyed); |
64 | 64 | ||
65 | unsigned int width() const; | 65 | unsigned int width() const; |
66 | unsigned int height() const; | 66 | unsigned int height() const; |
@@ -83,7 +83,7 @@ private: | |||
83 | 83 | ||
84 | void rearrangeClients(); | 84 | void rearrangeClients(); |
85 | void removeAllClients(); | 85 | void removeAllClients(); |
86 | void hideClient(TrayWindow *traywin); | 86 | void hideClient(TrayWindow *traywin, bool destroyed = false); |
87 | void showClient(TrayWindow *traywin); | 87 | void showClient(TrayWindow *traywin); |
88 | 88 | ||
89 | FbTk::FbWindow m_window; | 89 | FbTk::FbWindow m_window; |
@@ -95,6 +95,10 @@ private: | |||
95 | 95 | ||
96 | ClientList m_clients; | 96 | ClientList m_clients; |
97 | size_t m_num_visible_clients; | 97 | size_t m_num_visible_clients; |
98 | |||
99 | // gaim/pidgin seems to barf if the selection is not an independent window. | ||
100 | // I suspect it's an interacton with parent relationship and gdk window caching. | ||
101 | FbTk::FbWindow m_selection_owner; | ||
98 | }; | 102 | }; |
99 | 103 | ||
100 | #endif // SYSTEMTRAY_HH | 104 | #endif // SYSTEMTRAY_HH |
diff --git a/src/fluxbox.cc b/src/fluxbox.cc index d739944..8b9e39a 100644 --- a/src/fluxbox.cc +++ b/src/fluxbox.cc | |||
@@ -255,6 +255,7 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile | |||
255 | SignalHandler &sigh = SignalHandler::instance(); | 255 | SignalHandler &sigh = SignalHandler::instance(); |
256 | sigh.registerHandler(SIGSEGV, this); | 256 | sigh.registerHandler(SIGSEGV, this); |
257 | sigh.registerHandler(SIGFPE, this); | 257 | sigh.registerHandler(SIGFPE, this); |
258 | sigh.registerHandler(SIGPIPE, this); // e.g. output sent to grep | ||
258 | sigh.registerHandler(SIGTERM, this); | 259 | sigh.registerHandler(SIGTERM, this); |
259 | sigh.registerHandler(SIGINT, this); | 260 | sigh.registerHandler(SIGINT, this); |
260 | sigh.registerHandler(SIGCHLD, this); | 261 | sigh.registerHandler(SIGCHLD, this); |
@@ -1091,6 +1092,7 @@ void Fluxbox::handleSignal(int signum) { | |||
1091 | break; | 1092 | break; |
1092 | case SIGFPE: | 1093 | case SIGFPE: |
1093 | case SIGINT: | 1094 | case SIGINT: |
1095 | case SIGPIPE: | ||
1094 | case SIGTERM: | 1096 | case SIGTERM: |
1095 | shutdown(); | 1097 | shutdown(); |
1096 | break; | 1098 | break; |