From dd8fcc8b7b4c2bccf90edf9b0acfa52e21f5d1ce Mon Sep 17 00:00:00 2001 From: Henrik Kinnunen <fluxgen@fluxbox.org> Date: Fri, 26 Mar 2010 18:15:45 +0100 Subject: Changed title signal in Focusable to new signal system --- src/ClientMenu.cc | 58 +++++++++++++++++++++++++++++++++++----------------- src/ClientMenu.hh | 6 ++++++ src/Ewmh.cc | 8 ++++---- src/Focusable.hh | 17 ++++++++------- src/FocusableList.cc | 27 ++++++++++++++++++------ src/FocusableList.hh | 6 ++++++ src/IconButton.cc | 49 ++++++++++++++++++++++++++++---------------- src/IconButton.hh | 6 ++++++ src/WinButton.cc | 7 +++++-- src/WinButton.hh | 4 +++- src/WinClient.cc | 6 +++--- src/Window.cc | 34 ++++++++++++++++-------------- src/Window.hh | 3 +++ 13 files changed, 156 insertions(+), 75 deletions(-) diff --git a/src/ClientMenu.cc b/src/ClientMenu.cc index 71f322c..02df7e4 100644 --- a/src/ClientMenu.cc +++ b/src/ClientMenu.cc @@ -37,10 +37,13 @@ public: ClientMenuItem(Focusable &client, ClientMenu &menu): FbTk::MenuItem(client.title().c_str(), menu), m_client(client) { - client.titleSig().attach(&menu); - client.dieSig().attach(&menu); - } - ~ClientMenuItem() { m_client.titleSig().detach(menu()); } + m_signals.join(client.titleSig(), + FbTk::MemFunSelectArg1(menu, &ClientMenu::titleChanged)); + client.dieSig().attach(&menu); + } + + ~ClientMenuItem() { + } void click(int button, int time, unsigned int mods) { FluxboxWindow *fbwin = m_client.fbwindow(); @@ -75,6 +78,7 @@ public: private: Focusable &m_client; + FbTk::SignalTracker m_signals; }; } // end anonymous namespace @@ -118,30 +122,46 @@ void ClientMenu::refreshMenu() { updateMenu(); } +namespace { + +ClientMenuItem* getMenuItem(ClientMenu& menu, Focusable& win) { + // find the corresponding menuitem + ClientMenuItem *cl_item = 0; + for (size_t i = 0; i < menu.numberOfItems(); i++) { + FbTk::MenuItem *item = menu.find(i); + if (item && typeid(*item) == typeid(ClientMenuItem)) { + cl_item = static_cast<ClientMenuItem *>(item); + if (cl_item->client() == &win) + break; + } + } + + return cl_item; + +} + +} // anonymous + +void ClientMenu::titleChanged(Focusable& win) { + // find correct menu item + ClientMenuItem* cl_item = getMenuItem(*this, win); + if (cl_item) + FbTk::Menu::update(0); +} + void ClientMenu::update(FbTk::Subject *subj) { if (subj && typeid(*subj) == typeid(Focusable::FocusSubject)) { Focusable::FocusSubject *fsubj = static_cast<Focusable::FocusSubject *>(subj); Focusable &win = fsubj->win(); - // find the corresponding menuitem - ClientMenuItem *cl_item = 0; - for (size_t i = 0; i < numberOfItems(); i++) { - FbTk::MenuItem *item = find(i); - if (item && typeid(*item) == typeid(ClientMenuItem)) { - cl_item = static_cast<ClientMenuItem *>(item); - if (cl_item->client() == &win) - break; - } - } + // find correct menu item + ClientMenuItem* cl_item = getMenuItem(*this, win); // update accordingly - if (cl_item && fsubj == &win.dieSig()) + if (cl_item && fsubj == &win.dieSig()) { remove(cl_item->getIndex()); - else if (cl_item && fsubj == &win.titleSig()) - // this could change the size of the menu, so do a full update - FbTk::Menu::update(subj); - + } } else FbTk::Menu::update(subj); } diff --git a/src/ClientMenu.hh b/src/ClientMenu.hh index f0b6ce4..4b5cedb 100644 --- a/src/ClientMenu.hh +++ b/src/ClientMenu.hh @@ -28,6 +28,8 @@ class BScreen; class FluxboxWindow; +class Focusable; + /** * A menu holding a set of client menus. * @see WorkspaceMenu @@ -47,6 +49,10 @@ public: /// refresh the entire menu void refreshMenu(); + + /// Called when window title changed. + void titleChanged(Focusable& win); + private: void updateClientList(BScreen& screen) { diff --git a/src/Ewmh.cc b/src/Ewmh.cc index 3b4ea51..eadea4b 100644 --- a/src/Ewmh.cc +++ b/src/Ewmh.cc @@ -164,7 +164,7 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) { if (width >= nr_icon_data) { fbdbg << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON width (" - << width << ") for " << winclient.title() << "\n"; + << width << ") for " << winclient.title() << "\n"; break; } @@ -172,7 +172,7 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) { if (height >= nr_icon_data) { fbdbg << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON height (" - << height << ") for " << winclient.title() << "\n"; + << height << ") for " << winclient.title() << "\n"; break; } @@ -180,7 +180,7 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) { // strange values stored in the NETWM_ICON if (i + width * height > nr_icon_data) { fbdbg << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON dimensions (" - << width << "x" << height << ")for " << winclient.title() << "\n"; + << width << "x" << height << ")for " << winclient.title() << "\n"; break; } @@ -1293,7 +1293,7 @@ bool Ewmh::propertyNotify(WinClient &winclient, Atom the_property) { if (!newtitle.empty()) winclient.setTitle(newtitle); if (winclient.fbwindow()) - winclient.fbwindow()->titleSig().notify(); + winclient.fbwindow()->titleSig().emit(newtitle, *winclient.fbwindow()); return true; } else if (the_property == m_net->wm_icon_name) { // we don't use icon title, since we don't show icons diff --git a/src/Focusable.hh b/src/Focusable.hh index 6108ed9..8434a97 100644 --- a/src/Focusable.hh +++ b/src/Focusable.hh @@ -42,9 +42,10 @@ public: m_screen(scr), m_fbwin(fbwin), m_instance_name("fluxbox"), m_class_name("fluxbox"), m_focused(false), m_attention_state(false), - m_titlesig(*this), m_diesig(*this), + m_diesig(*this), m_attentionsig(*this), - m_focussig() { } + m_focussig(), + m_titlesig() { } virtual ~Focusable() { } /** @@ -116,10 +117,11 @@ public: @name signals @{ */ - // Used for both title and icon changes. - FbTk::Subject &titleSig() { return m_titlesig; } - // Used for both title and icon changes. - const FbTk::Subject &titleSig() const { return m_titlesig; } + typedef FbTk::Signal<void, const std::string&, Focusable&> TitleSignal; + /// Used for both title and icon changes. + TitleSignal &titleSig() { return m_titlesig; } + /// Used for both title and icon changes. + const TitleSignal &titleSig() const { return m_titlesig; } FbTk::Signal<void, Focusable&> &focusSig() { return m_focussig; } const FbTk::Signal<void, Focusable&> &focusSig() const { return m_focussig; } FbTk::Subject &dieSig() { return m_diesig; } @@ -143,10 +145,11 @@ protected: FbTk::PixmapWithMask m_icon; //< icon pixmap with mask // state and hint signals - FocusSubject m_titlesig, m_diesig, m_attentionsig; + FocusSubject m_diesig, m_attentionsig; private: FbTk::Signal<void, Focusable&> m_focussig; + TitleSignal m_titlesig; }; #endif // FOCUSABLE_HH diff --git a/src/FocusableList.cc b/src/FocusableList.cc index b2b0320..77e0a76 100644 --- a/src/FocusableList.cc +++ b/src/FocusableList.cc @@ -113,10 +113,9 @@ void FocusableList::update(FbTk::Subject *subj) { if (typeid(*subj) == typeid(Focusable::FocusSubject)) { Focusable::FocusSubject *fsubj = static_cast<Focusable::FocusSubject *>(subj); - if (fsubj == &fsubj->win().dieSig()) + if (fsubj == &fsubj->win().dieSig()) { remove(fsubj->win()); - else if (fsubj == &fsubj->win().titleSig()) - checkUpdate(fsubj->win()); + } } if (typeid(*subj) == typeid(FluxboxWindow::WinSubject)) { FluxboxWindow::WinSubject *fsubj = @@ -244,17 +243,27 @@ void FocusableList::remove(Focusable &win) { bool contained = contains(win); detachSignals(win); - if (!contained) + if (!contained) { return; + } m_list.remove(&win); m_removesig.notify(&win); } +void FocusableList::updateTitle(Focusable& win) { + checkUpdate(win); +} + void FocusableList::attachSignals(Focusable &win) { win.dieSig().attach(this); if (m_parent) { // attach various signals for matching - win.titleSig().attach(this); + if (m_signal_map.find(&win) == m_signal_map.end()) { + m_signal_map[&win] = join(win.titleSig(), + MemFunSelectArg1(*this, + &FocusableList::updateTitle)); + } + FluxboxWindow *fbwin = win.fbwindow(); if (!fbwin) return; @@ -268,8 +277,14 @@ void FocusableList::attachSignals(Focusable &win) { void FocusableList::detachSignals(Focusable &win) { win.dieSig().detach(this); 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 - win.titleSig().detach(this); FluxboxWindow *fbwin = win.fbwindow(); if (!fbwin) return; diff --git a/src/FocusableList.hh b/src/FocusableList.hh index 58ef9b6..1382da6 100644 --- a/src/FocusableList.hh +++ b/src/FocusableList.hh @@ -116,12 +116,18 @@ private: void attachChild(FocusableList &child) const; void workspaceChanged(BScreen &screen); void focusedWindowChanged(BScreen &screen, FluxboxWindow *win, WinClient *client); + /// Title has changed for a window + /// @param win The window that title changed for. + void updateTitle(Focusable& win); + std::auto_ptr<ClientPattern> m_pat; const FocusableList *m_parent; BScreen &m_screen; std::list<Focusable *> m_list; mutable FocusableListSubject m_ordersig, m_addsig, m_removesig, m_resetsig; + typedef std::map<Focusable*, FbTk::SignalTracker::TrackID> SignalMap; + SignalMap m_signal_map; }; #endif // FOCUSABLELIST_HH diff --git a/src/IconButton.cc b/src/IconButton.cc index ce89651..320918c 100644 --- a/src/IconButton.cc +++ b/src/IconButton.cc @@ -59,15 +59,18 @@ IconButton::IconButton(const FbTk::FbWindow &parent, m_theme(win, focused_theme, unfocused_theme), m_pm(win.screen().imageControl()) { - m_win.titleSig().attach(this); + m_signals.join(m_win.titleSig(), + MemFunIgnoreArgs(*this, &IconButton::clientTitleChanged)); + m_signals.join(m_win.focusSig(), MemFunIgnoreArgs(*this, &IconButton::reconfigAndClear)); + m_win.attentionSig().attach(this); FbTk::EventManager::instance()->add(*this, m_icon_window); reconfigTheme(); - update(0); + refreshEverything(false); } IconButton::~IconButton() { @@ -102,7 +105,7 @@ void IconButton::moveResize(int x, int y, if (m_icon_window.width() != FbTk::Button::width() || m_icon_window.height() != FbTk::Button::height()) { reconfigTheme(); - update(0); // update icon window + refreshEverything(false); // update icon window } } @@ -111,7 +114,7 @@ void IconButton::resize(unsigned int width, unsigned int height) { if (m_icon_window.width() != FbTk::Button::width() || m_icon_window.height() != FbTk::Button::height()) { reconfigTheme(); - update(0); // update icon window + refreshEverything(false); // update icon window } } @@ -140,7 +143,7 @@ void IconButton::clearArea(int x, int y, void IconButton::setPixmap(bool use) { if (m_use_pixmap != use) { m_use_pixmap = use; - update(0); + refreshEverything(false); } } @@ -175,16 +178,7 @@ void IconButton::reconfigAndClear() { clear(); } -void IconButton::update(FbTk::Subject *subj) { - // if the window's focus state changed, we need to update the background - if (subj == &m_win.attentionSig()) { - reconfigAndClear(); - return; - } - - // we got signal that either title or - // icon pixmap was updated, - // so we refresh everything +void IconButton::refreshEverything(bool setup) { Display *display = FbTk::App::instance()->display(); int screen = m_win.screen().screenNumber(); @@ -242,17 +236,36 @@ void IconButton::update(FbTk::Subject *subj) { #endif // SHAPE - if (subj != 0) { + if (setup) { setupWindow(); } else { m_icon_window.clear(); } + +} + +void IconButton::clientTitleChanged() { + refreshEverything(true); + + if (m_has_tooltip) + showTooltip(); +} + +void IconButton::update(FbTk::Subject *subj) { + // if the window's focus state changed, we need to update the background + if (subj == &m_win.attentionSig()) { + reconfigAndClear(); + return; + } + + // we got signal that either title or + // icon pixmap was updated, + // so we refresh everything // if the title was changed AND the mouse is over *this, // update the tooltip - if (subj == &m_win.titleSig() && m_has_tooltip) - showTooltip(); + refreshEverything(subj != 0); } void IconButton::setupWindow() { diff --git a/src/IconButton.hh b/src/IconButton.hh index 5a6af0d..d1eb17e 100644 --- a/src/IconButton.hh +++ b/src/IconButton.hh @@ -73,6 +73,12 @@ private: void setupWindow(); void showTooltip(); + /// Refresh all pixmaps and windows + /// @param setup Wether to setup window again. + void refreshEverything(bool setup); + /// Called when client title changed. + void clientTitleChanged(); + Focusable &m_win; FbTk::FbWindow m_icon_window; FbTk::FbPixmap m_icon_pixmap; diff --git a/src/WinButton.cc b/src/WinButton.cc index d64034e..9ecbb9c 100644 --- a/src/WinButton.cc +++ b/src/WinButton.cc @@ -278,8 +278,7 @@ void WinButton::clear() { FbTk::Button::clear(); drawType(); } - -void WinButton::update(FbTk::Subject *subj) { +void WinButton::updateAll() { // update the menu icon if (m_type == MENUICON && !m_listen_to.empty()) { @@ -316,3 +315,7 @@ void WinButton::update(FbTk::Subject *subj) { clear(); } + +void WinButton::update(FbTk::Subject *subj) { + updateAll(); +} diff --git a/src/WinButton.hh b/src/WinButton.hh index 7f40f1a..a116a15 100644 --- a/src/WinButton.hh +++ b/src/WinButton.hh @@ -25,6 +25,7 @@ #include "FbTk/Button.hh" #include "FbTk/Observer.hh" #include "FbTk/FbPixmap.hh" +#include "FbTk/Signal.hh" class FluxboxWindow; class WinButtonTheme; @@ -35,7 +36,7 @@ template <class T> class ThemeProxy; } /// draws and handles basic window button graphic -class WinButton:public FbTk::Button, public FbTk::Observer { +class WinButton:public FbTk::Button, public FbTk::Observer, public FbTk::SignalTracker { public: /// draw type for the button enum Type {MAXIMIZE, MINIMIZE, SHADE, STICK, CLOSE, MENUICON}; @@ -57,6 +58,7 @@ public: /// override for redrawing void clear(); void update(FbTk::Subject *subj); + void updateAll(); private: void drawType(); Type m_type; ///< the button type diff --git a/src/WinClient.cc b/src/WinClient.cc index 6ec15f3..7a10c12 100644 --- a/src/WinClient.cc +++ b/src/WinClient.cc @@ -341,13 +341,13 @@ void WinClient::updateTitle() { return; m_title = string(Xutil::getWMName(window()), 0, 512); - titleSig().notify(); + titleSig().emit(m_title, *this); } void WinClient::setTitle(const FbTk::FbString &title) { m_title = title; m_title_override = true; - titleSig().notify(); + titleSig().emit(m_title, *this); } void WinClient::setIcon(const FbTk::PixmapWithMask& pm) { @@ -355,7 +355,7 @@ void WinClient::setIcon(const FbTk::PixmapWithMask& pm) { m_icon.pixmap().copy(pm.pixmap()); m_icon.mask().copy(pm.mask()); m_icon_override = true; - titleSig().notify(); + titleSig().emit(m_title, *this); } void WinClient::setFluxboxWindow(FluxboxWindow *win) { diff --git a/src/Window.cc b/src/Window.cc index 34b5d0c..586dc7b 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -988,7 +988,7 @@ bool FluxboxWindow::setCurrentClient(WinClient &client, bool setinput) { button<<endl; if (old != &client) { - titleSig().notify(); + titleSig().emit(title(), *this); frame().setFocusTitle(title()); frame().setShapingClient(&client, false); } @@ -2103,7 +2103,7 @@ void FluxboxWindow::propertyNotifyEvent(WinClient &client, Atom atom) { case XA_WM_HINTS: client.updateWMHints(); - titleSig().notify(); + titleSig().emit(title(), *this); // nothing uses this yet // hintSig().notify(); // notify listeners break; @@ -2707,18 +2707,19 @@ void FluxboxWindow::leaveNotifyEvent(XCrossingEvent &ev) { //installColormap(false); } -void FluxboxWindow::update(FbTk::Subject *subj) { - if (subj && typeid(*subj) == typeid(Focusable::FocusSubject)) { - Focusable::FocusSubject &fsubj = - static_cast<Focusable::FocusSubject &>(*subj); - Focusable &win = fsubj.win(); - - if (&fsubj == &win.titleSig() && &win == m_client) { - frame().setFocusTitle(win.title()); - titleSig().notify(); - } +void FluxboxWindow::setTitle(const std::string& title, Focusable &client) { + // only update focus title for current client + if (&client != m_client) { + return; + } - } else if (subj == &m_theme.reconfigSig()) { + frame().setFocusTitle(title); + // relay title to others that display the focus title + titleSig().emit(title, *this); +} + +void FluxboxWindow::update(FbTk::Subject *subj) { + if (subj == &m_theme.reconfigSig()) { frame().applyDecorations(); sendConfigureNotify(); } else if (m_initialized && subj == &m_frame.frameExtentSig()) { @@ -3637,7 +3638,9 @@ void FluxboxWindow::updateButtons() { dir[i], frame().titlebar(), 0, 0, 10, 10); - titleSig().attach(winbtn); + winbtn->join(titleSig(), + FbTk::MemFunIgnoreArgs(*winbtn, &WinButton::updateAll)); + winbtn->setOnClick(show_menu_cmd); break; } @@ -3709,7 +3712,8 @@ void FluxboxWindow::associateClient(WinClient &client) { evm.add(*this, btn->window()); // we take care of button events for this evm.add(*this, client.window()); client.setFluxboxWindow(this); - client.titleSig().attach(this); + join(client.titleSig(), + FbTk::MemFun(*this, &FluxboxWindow::setTitle)); } FluxboxWindow::ReferenceCorner FluxboxWindow::getCorner(string str) { diff --git a/src/Window.hh b/src/Window.hh index 9cefd55..a097ac6 100644 --- a/src/Window.hh +++ b/src/Window.hh @@ -474,6 +474,9 @@ public: bool oplock; ///< Used to help stop transient loops occurring by locking a window during certain operations private: + /// signal callback for title changes by clients + void setTitle(const std::string &title, Focusable &client); + void setupWindow(); void updateButtons(); -- cgit v0.11.2