From b27336033143158acbde1d2f36977dd25c10ab96 Mon Sep 17 00:00:00 2001 From: simonb Date: Sat, 4 Aug 2007 17:14:13 +0000 Subject: Fix system tray restart issues --- ChangeLog | 4 ++++ src/Ewmh.cc | 2 +- src/FbTk/FbWindow.cc | 8 ++++++++ src/FbTk/FbWindow.hh | 3 +++ src/SystemTray.cc | 47 ++++++++++++++++++++++++++++++++++++----------- src/SystemTray.hh | 8 ++++++-- src/fluxbox.cc | 2 ++ 7 files changed, 60 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 47d61f6..8879dec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ (Format: Year/Month/Day) Changes for 1.0.0: +*07/08/05: + * Fix System Tray restart issues (Simon) + (including gaim/pidgin crash-on-restart) + src/SystemTray.hh/cc src/FbTk/FbWindow.hh/cc *07/07/31: * Change _NET_WM_WINDOW_TYPE_MENU to use TINY decoration type (Mark) 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) { m_net_wm_state_fullscreen, m_net_wm_state_hidden, m_net_wm_state_skip_taskbar, - m_net_wm_state_modal, +// m_net_wm_state_modal, m_net_wm_state_below, m_net_wm_state_above, 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) { XDeleteProperty(display(), m_window, property); } +void FbWindow::addToSaveSet() { + XAddToSaveSet(display(), m_window); +} + +void FbWindow::removeFromSaveSet() { + XRemoveFromSaveSet(display(), m_window); +} + int FbWindow::screenNumber() const { return m_screen_num; } 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: std::string textProperty(Atom property) const; + void addToSaveSet(); + void removeFromSaveSet(); + /// @return parent FbWindow const FbWindow *parent() const { return m_parent; } /// @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: TrayWindow(Window win):FbTk::FbWindow(win), m_visible(false) { setEventMask(PropertyChangeMask); } + bool isVisible() { return m_visible; } void show() { if (!m_visible) { @@ -65,6 +66,7 @@ public: FbTk::FbWindow::hide(); } } + private: bool m_visible; }; @@ -132,9 +134,11 @@ SystemTray::SystemTray(const FbTk::FbWindow& parent, ButtonTheme& theme, BScreen SubstructureNotifyMask | SubstructureRedirectMask), m_theme(theme), m_screen(screen), - m_pixmap(0), m_num_visible_clients(0) { - + m_pixmap(0), m_num_visible_clients(0), + m_selection_owner(m_window, 0, 0, 1, 1, SubstructureNotifyMask, false, false, CopyFromParent, InputOnly) { + FbTk::EventManager::instance()->add(*this, m_window); + FbTk::EventManager::instance()->add(*this, m_selection_owner); m_theme.reconfigSig().attach(this); screen.bgChangeSig().attach(this); @@ -162,7 +166,7 @@ SystemTray::SystemTray(const FbTk::FbWindow& parent, ButtonTheme& theme, BScreen cerr<<__FILE__<<"(SystemTray(const FbTk::FbWindow)): SETTING OWNER!"<removeAtomHandler(m_handler.get()); + Fluxbox* fluxbox = Fluxbox::instance(); + fluxbox->removeAtomHandler(m_handler.get()); + Display *disp = fluxbox->display(); + // setup atom name to _NET_SYSTEM_TRAY_S + char intbuff[16]; + sprintf(intbuff, "%d", m_window.screenNumber()); + string atom_name("_NET_SYSTEM_TRAY_S"); + atom_name += intbuff; // append number + + // get selection owner and see if it's free + Atom tray_atom = XInternAtom(disp, atom_name.c_str(), False); + + // Properly give up selection. + XSetSelectionOwner(disp, tray_atom, None, CurrentTime); removeAllClients(); if (m_pixmap) @@ -323,10 +340,11 @@ void SystemTray::addClient(Window win) { FbTk::EventManager::instance()->add(*this, win); XChangeSaveSet(FbTk::App::instance()->display(), win, SetModeInsert); traywin->reparent(m_window, 0, 0); + traywin->addToSaveSet(); showClient(traywin); } -void SystemTray::removeClient(Window win) { +void SystemTray::removeClient(Window win, bool destroyed) { ClientList::iterator tray_it = findClient(win); if (tray_it == m_clients.end()) return; @@ -336,7 +354,11 @@ void SystemTray::removeClient(Window win) { #endif // DEBUG TrayWindow *traywin = *tray_it; m_clients.erase(tray_it); - hideClient(traywin); + if (!destroyed) { + traywin->setEventMask(NoEventMask); + traywin->removeFromSaveSet(); + } + hideClient(traywin, destroyed); delete traywin; } @@ -346,9 +368,9 @@ void SystemTray::exposeEvent(XExposeEvent &event) { void SystemTray::handleEvent(XEvent &event) { if (event.type == DestroyNotify) { - removeClient(event.xdestroywindow.window); + removeClient(event.xdestroywindow.window, true); } else if (event.type == ReparentNotify && event.xreparent.parent != m_window.window()) { - removeClient(event.xreparent.window); + removeClient(event.xreparent.window, false); } else if (event.type == UnmapNotify && event.xany.send_event) { // we ignore server-generated events, which can occur // on restart. The ICCCM says that a client must send @@ -443,20 +465,23 @@ void SystemTray::rearrangeClients() { void SystemTray::removeAllClients() { BScreen *screen = Fluxbox::instance()->findScreen(window().screenNumber()); while (!m_clients.empty()) { + m_clients.back()->setEventMask(NoEventMask); + m_clients.back()->hide(); if (screen) m_clients.back()->reparent(screen->rootWindow(), 0, 0); - m_clients.back()->hide(); + m_clients.back()->removeFromSaveSet(); delete m_clients.back(); m_clients.pop_back(); } m_num_visible_clients = 0; } -void SystemTray::hideClient(TrayWindow *traywin) { +void SystemTray::hideClient(TrayWindow *traywin, bool destroyed) { if (!traywin || !traywin->isVisible()) return; - traywin->hide(); + if (!destroyed) + traywin->hide(); m_num_visible_clients--; rearrangeClients(); } 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: void handleEvent(XEvent &event); void addClient(Window win); - void removeClient(Window win); + void removeClient(Window win, bool destroyed); unsigned int width() const; unsigned int height() const; @@ -83,7 +83,7 @@ private: void rearrangeClients(); void removeAllClients(); - void hideClient(TrayWindow *traywin); + void hideClient(TrayWindow *traywin, bool destroyed = false); void showClient(TrayWindow *traywin); FbTk::FbWindow m_window; @@ -95,6 +95,10 @@ private: ClientList m_clients; size_t m_num_visible_clients; + + // gaim/pidgin seems to barf if the selection is not an independent window. + // I suspect it's an interacton with parent relationship and gdk window caching. + FbTk::FbWindow m_selection_owner; }; #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 SignalHandler &sigh = SignalHandler::instance(); sigh.registerHandler(SIGSEGV, this); sigh.registerHandler(SIGFPE, this); + sigh.registerHandler(SIGPIPE, this); // e.g. output sent to grep sigh.registerHandler(SIGTERM, this); sigh.registerHandler(SIGINT, this); sigh.registerHandler(SIGCHLD, this); @@ -1091,6 +1092,7 @@ void Fluxbox::handleSignal(int signum) { break; case SIGFPE: case SIGINT: + case SIGPIPE: case SIGTERM: shutdown(); break; -- cgit v0.11.2