diff --git a/src/AttentionNoticeHandler.cc b/src/AttentionNoticeHandler.cc index 88dd72a6..90523197 100644 --- a/src/AttentionNoticeHandler.cc +++ b/src/AttentionNoticeHandler.cc @@ -88,9 +88,8 @@ void AttentionNoticeHandler::addAttention(Focusable &client) { m_attentions[&client] = timer; // attach signals that will make notice go away - client.dieSig().attach(this); - - client.focusSig().connect(MemFun(*this, &AttentionNoticeHandler::windowFocusChanged)); + join(client.dieSig(), MemFun(*this, &AttentionNoticeHandler::removeWindow)); + join(client.focusSig(), MemFun(*this, &AttentionNoticeHandler::windowFocusChanged)); // update _NET_WM_STATE atom if (client.fbwindow()) @@ -104,16 +103,6 @@ void AttentionNoticeHandler::removeWindow(Focusable& win) { updateWindow(win, true); } -void AttentionNoticeHandler::update(FbTk::Subject* subj) { - // we need to be able to get the window - if (!subj || typeid(*subj) != typeid(Focusable::FocusSubject)) - return; - Focusable::FocusSubject *winsubj = - static_cast(subj); - - removeWindow(winsubj->win()); -} - void AttentionNoticeHandler::updateWindow(Focusable& win, bool died) { // all signals results in destruction of the notice diff --git a/src/AttentionNoticeHandler.hh b/src/AttentionNoticeHandler.hh index 27d3b43e..ed319b45 100644 --- a/src/AttentionNoticeHandler.hh +++ b/src/AttentionNoticeHandler.hh @@ -22,10 +22,10 @@ #ifndef ATTENTIONNOTICEHANDLER_HH #define ATTENTIONNOTICEHANDLER_HH -#include "FbTk/Observer.hh" - #include +#include "FbTk/Signal.hh" + class Focusable; namespace FbTk { @@ -36,7 +36,7 @@ class Timer; * Makes the title and iconbutton flash when the window * demands attention. */ -class AttentionNoticeHandler: public FbTk::Observer { +class AttentionNoticeHandler: private FbTk::SignalTracker { public: ~AttentionNoticeHandler(); @@ -44,8 +44,6 @@ public: /// Adds a client that requires attention, /// will fail if the client is already active void addAttention(Focusable &client); - /// removes the client from the attention map - void update(FbTk::Subject *subj); bool isDemandingAttention(const Focusable &client); diff --git a/src/ClientMenu.cc b/src/ClientMenu.cc index 4a3dacd4..96527ece 100644 --- a/src/ClientMenu.cc +++ b/src/ClientMenu.cc @@ -40,10 +40,7 @@ public: m_client(client) { m_signals.join(client.titleSig(), FbTk::MemFunSelectArg1(menu, &ClientMenu::titleChanged)); - client.dieSig().attach(&menu); - } - - ~ClientMenuItem() { + m_signals.join(client.dieSig(), FbTk::MemFun(menu, &ClientMenu::clientDied)); } void click(int button, int time, unsigned int mods) { @@ -156,16 +153,11 @@ void ClientMenu::titleChanged(Focusable& win) { themeReconfigured(); } -void ClientMenu::update(FbTk::Subject *subj) { - if (Focusable::FocusSubject *fsubj = dynamic_cast(subj)) { - Focusable &win = fsubj->win(); +void ClientMenu::clientDied(Focusable &win) { + // find correct menu item + ClientMenuItem* cl_item = getMenuItem(*this, win); - // find correct menu item - ClientMenuItem* cl_item = getMenuItem(*this, win); - - // update accordingly - if (cl_item && fsubj == &win.dieSig()) { - remove(cl_item->getIndex()); - } - } + // update accordingly + if (cl_item) + remove(cl_item->getIndex()); } diff --git a/src/ClientMenu.hh b/src/ClientMenu.hh index 61fd1987..b40e1226 100644 --- a/src/ClientMenu.hh +++ b/src/ClientMenu.hh @@ -25,7 +25,6 @@ #include "FbMenu.hh" #include "FbTk/Signal.hh" -#include "FbTk/Observer.hh" class BScreen; class FluxboxWindow; @@ -35,7 +34,7 @@ class Focusable; * A menu holding a set of client menus. * @see WorkspaceMenu */ -class ClientMenu: public FbMenu, public FbTk::Observer { +class ClientMenu: public FbMenu { public: typedef std::list Focusables; @@ -54,15 +53,15 @@ public: /// Called when window title changed. void titleChanged(Focusable& win); + /// Called when a client dies. Removes the corresponding menu item + void clientDied(Focusable& win); + private: void updateClientList(BScreen& screen) { refreshMenu(); } - /// called when receiving a subject signal - void update(FbTk::Subject *subj); - Focusables &m_list; ///< clients in the menu FbTk::SignalTracker m_slots; ///< track all the slots }; diff --git a/src/CurrentWindowCmd.cc b/src/CurrentWindowCmd.cc index 1122e1fc..8d27a3ab 100644 --- a/src/CurrentWindowCmd.cc +++ b/src/CurrentWindowCmd.cc @@ -635,18 +635,18 @@ void ChangeLayerCmd::real_execute() { } namespace { -class SetTitleDialog: public TextDialog, public FbTk::Observer { +class SetTitleDialog: public TextDialog, private FbTk::SignalTracker { public: SetTitleDialog(FluxboxWindow &win, const string &title): TextDialog(win.screen(), title), window(win) { - win.dieSig().attach(this); + join(win.dieSig(), FbTk::MemFunIgnoreArgs(*this, &SetTitleDialog::windowDied)); setText(win.title()); } - // only attached signal is window destruction - void update(FbTk::Subject *subj) { delete this; } - private: + // only attached signal is window destruction + void windowDied() { delete this; } + void exec(const std::string &text) { window.winClient().setTitle(text); } diff --git a/src/Focusable.hh b/src/Focusable.hh index 72a1dccb..cf2169af 100644 --- a/src/Focusable.hh +++ b/src/Focusable.hh @@ -41,9 +41,9 @@ public: m_screen(scr), m_fbwin(fbwin), m_instance_name("fluxbox"), m_class_name("fluxbox"), m_focused(false), m_attention_state(false), - m_diesig(*this), m_attentionsig(*this), m_focussig(), + m_diesig(), m_titlesig() { } virtual ~Focusable() { } @@ -125,9 +125,7 @@ public: /// Used for both title and icon changes. const TitleSignal &titleSig() const { return m_titlesig; } FbTk::Signal &focusSig() { return m_focussig; } - const FbTk::Signal &focusSig() const { return m_focussig; } - FbTk::Subject &dieSig() { return m_diesig; } - const FbTk::Subject &dieSig() const { return m_diesig; } + FbTk::Signal &dieSig() { return m_diesig; } FbTk::Subject &attentionSig() { return m_attentionsig; } const FbTk::Subject &attentionSig() const { return m_attentionsig; } /** @} */ // end group signals @@ -150,10 +148,11 @@ protected: FbTk::PixmapWithMask m_icon; //< icon pixmap with mask // state and hint signals - FocusSubject m_diesig, m_attentionsig; + FocusSubject m_attentionsig; private: FbTk::Signal m_focussig; + FbTk::Signal m_diesig; TitleSignal m_titlesig; }; diff --git a/src/FocusableList.cc b/src/FocusableList.cc index 748e940f..a130ec0e 100644 --- a/src/FocusableList.cc +++ b/src/FocusableList.cc @@ -111,13 +111,6 @@ void FocusableList::update(FbTk::Subject *subj) { if (subj == 0 || m_screen.isShuttingdown()) return; - if (typeid(*subj) == typeid(Focusable::FocusSubject)) { - Focusable::FocusSubject *fsubj = - static_cast(subj); - if (fsubj == &fsubj->win().dieSig()) { - remove(fsubj->win()); - } - } if (typeid(*subj) == typeid(FluxboxWindow::WinSubject)) { FluxboxWindow::WinSubject *fsubj = static_cast(subj); @@ -254,15 +247,17 @@ void FocusableList::remove(Focusable &win) { void FocusableList::updateTitle(Focusable& win) { checkUpdate(win); } +#include "Debug.hh" void FocusableList::attachSignals(Focusable &win) { - win.dieSig().attach(this); if (m_parent) { // attach various signals for matching - if (m_signal_map.find(&win) == m_signal_map.end()) { - m_signal_map[&win] = join(win.titleSig(), - MemFunSelectArg1(*this, - &FocusableList::updateTitle)); + FbTk::RefCount &tracker = m_signal_map[&win]; + if (! tracker) { + // we have not attached to this window yet + tracker = new SignalTracker; + tracker->join(win.titleSig(), MemFunSelectArg1(*this, &FocusableList::updateTitle)); + tracker->join(win.dieSig(), MemFun(*this, &FocusableList::remove)); } FluxboxWindow *fbwin = win.fbwindow(); @@ -276,15 +271,8 @@ void FocusableList::attachSignals(Focusable &win) { } void FocusableList::detachSignals(Focusable &win) { - win.dieSig().detach(this); + m_signal_map.erase(&win); if (m_parent) { - // disconnect client - SignalMap::iterator sigIt = m_signal_map.find(&win); - if (sigIt != m_signal_map.end()) { - leave(sigIt->second); - m_signal_map.erase(sigIt); - } - // detach various signals for matching FluxboxWindow *fbwin = win.fbwindow(); if (!fbwin) diff --git a/src/FocusableList.hh b/src/FocusableList.hh index 1382da68..6e46db90 100644 --- a/src/FocusableList.hh +++ b/src/FocusableList.hh @@ -24,6 +24,7 @@ #include "FbTk/NotCopyable.hh" #include "FbTk/Observer.hh" +#include "FbTk/RefCount.hh" #include "FbTk/Subject.hh" #include "FbTk/Signal.hh" @@ -126,7 +127,7 @@ private: std::list m_list; mutable FocusableListSubject m_ordersig, m_addsig, m_removesig, m_resetsig; - typedef std::map SignalMap; + typedef std::map > SignalMap; SignalMap m_signal_map; }; diff --git a/src/WinClient.cc b/src/WinClient.cc index 4ef37ae8..b73f27cb 100644 --- a/src/WinClient.cc +++ b/src/WinClient.cc @@ -155,7 +155,7 @@ WinClient::~WinClient() { fbwindow()->removeClient(*this); // this takes care of any focus issues - m_diesig.notify(); + dieSig().emit(*this); // This fixes issue 1 (see WinClient.hh): // If transients die before the transient_for is created diff --git a/src/Window.cc b/src/Window.cc index 756c3584..ca631780 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -350,7 +350,7 @@ FluxboxWindow::~FluxboxWindow() { m_timer.stop(); // notify die - m_diesig.notify(); + dieSig().emit(*this); if (m_client != 0 && !m_screen.isShuttingdown()) delete m_client; // this also removes client from our list diff --git a/src/fluxbox.cc b/src/fluxbox.cc index 99b9ea92..0263de7c 100644 --- a/src/fluxbox.cc +++ b/src/fluxbox.cc @@ -943,7 +943,6 @@ void Fluxbox::handleSignal(int signum) { void Fluxbox::update(FbTk::Subject *changedsub) { //TODO: fix signaling, this does not look good FluxboxWindow *fbwin = 0; - WinClient *client = 0; if (typeid(*changedsub) == typeid(FluxboxWindow::WinSubject)) { FluxboxWindow::WinSubject *winsub = dynamic_cast(changedsub); @@ -951,8 +950,6 @@ void Fluxbox::update(FbTk::Subject *changedsub) { } else if (typeid(*changedsub) == typeid(Focusable::FocusSubject)) { Focusable::FocusSubject *winsub = dynamic_cast(changedsub); fbwin = winsub->win().fbwindow(); - if (typeid(winsub->win()) == typeid(WinClient)) - client = dynamic_cast(&winsub->win()); } if (fbwin && &fbwin->stateSig() == changedsub) { // state signal @@ -981,55 +978,63 @@ void Fluxbox::update(FbTk::Subject *changedsub) { } else if (fbwin && &fbwin->layerSig() == changedsub) { // layer signal STLUtil::forAllIf(m_atomhandler, mem_fun(&AtomHandler::update), CallMemFunWithRefArg(&AtomHandler::updateLayer, *fbwin)); - } else if (fbwin && &fbwin->dieSig() == changedsub) { // window death signal - STLUtil::forAllIf(m_atomhandler, mem_fun(&AtomHandler::update), - CallMemFunWithRefArg(&AtomHandler::updateFrameClose, *fbwin)); - - // make sure each workspace get this - BScreen &scr = fbwin->screen(); - scr.removeWindow(fbwin); - if (FocusControl::focusedFbWindow() == fbwin) - FocusControl::setFocusedFbWindow(0); } else if (fbwin && &fbwin->workspaceSig() == changedsub) { // workspace signal STLUtil::forAllIf(m_atomhandler, mem_fun(&AtomHandler::update), CallMemFunWithRefArg(&AtomHandler::updateWorkspace, *fbwin)); - } else if (client && &client->dieSig() == changedsub) { // client death - STLUtil::forAllIf(m_atomhandler, mem_fun(&AtomHandler::update), - CallMemFunWithRefArg(&AtomHandler::updateClientClose, *client)); - - BScreen &screen = client->screen(); - - // At this point, we trust that this client is no longer in the - // client list of its frame (but it still has reference to the frame) - // We also assume that any remaining active one is the last focused one - - // This is where we revert focus on window close - // NOWHERE ELSE!!! - if (FocusControl::focusedWindow() == client) { - FocusControl::unfocusWindow(*client); - // make sure nothing else uses this window before focus reverts - FocusControl::setFocusedWindow(0); - } else if (FocusControl::expectingFocus() == client) { - FocusControl::setExpectingFocus(0); - revertFocus(); - } - - screen.removeClient(*client); } } +void Fluxbox::windowDied(Focusable &focusable) { + FluxboxWindow *fbwin = focusable.fbwindow(); + + STLUtil::forAllIf(m_atomhandler, mem_fun(&AtomHandler::update), + CallMemFunWithRefArg(&AtomHandler::updateFrameClose, *focusable.fbwindow())); + + // make sure each workspace get this + BScreen &scr = focusable.screen(); + scr.removeWindow(fbwin); + if (FocusControl::focusedFbWindow() == fbwin) + FocusControl::setFocusedFbWindow(0); +} + +void Fluxbox::clientDied(Focusable &focusable) { + WinClient &client = dynamic_cast(focusable); + + STLUtil::forAllIf(m_atomhandler, mem_fun(&AtomHandler::update), + CallMemFunWithRefArg(&AtomHandler::updateClientClose, client)); + + BScreen &screen = client.screen(); + + // At this point, we trust that this client is no longer in the + // client list of its frame (but it still has reference to the frame) + // We also assume that any remaining active one is the last focused one + + // This is where we revert focus on window close + // NOWHERE ELSE!!! + if (FocusControl::focusedWindow() == &client) { + FocusControl::unfocusWindow(client); + // make sure nothing else uses this window before focus reverts + FocusControl::setFocusedWindow(0); + } else if (FocusControl::expectingFocus() == &client) { + FocusControl::setExpectingFocus(0); + revertFocus(); + } + + screen.removeClient(client); +} + void Fluxbox::attachSignals(FluxboxWindow &win) { win.hintSig().attach(this); win.stateSig().attach(this); win.workspaceSig().attach(this); win.layerSig().attach(this); - win.dieSig().attach(this); + join(win.dieSig(), FbTk::MemFun(*this, &Fluxbox::windowDied)); STLUtil::forAll(m_atomhandler, CallMemFunWithRefArg(&AtomHandler::setupFrame, win)); } void Fluxbox::attachSignals(WinClient &winclient) { - winclient.dieSig().attach(this); + join(winclient.dieSig(), FbTk::MemFun(*this, &Fluxbox::clientDied)); STLUtil::forAll(m_atomhandler, CallMemFunWithRefArg(&AtomHandler::setupClient, winclient)); } diff --git a/src/fluxbox.hh b/src/fluxbox.hh index 36b39efb..082297f0 100644 --- a/src/fluxbox.hh +++ b/src/fluxbox.hh @@ -217,6 +217,10 @@ private: /// Called when the workspace area changed. void workspaceAreaChanged(BScreen &screen); + /// Called when a window (FluxboxWindow) dies + void windowDied(Focusable &focusable); + /// Called when a client (WinClient) dies + void clientDied(Focusable &focusable); std::auto_ptr m_fbatoms;