Changed title signal in Focusable to new signal system

This commit is contained in:
Henrik Kinnunen 2010-03-26 18:15:45 +01:00
parent 9ad388c5bf
commit dd8fcc8b7b
13 changed files with 156 additions and 75 deletions

View file

@ -37,10 +37,13 @@ public:
ClientMenuItem(Focusable &client, ClientMenu &menu): ClientMenuItem(Focusable &client, ClientMenu &menu):
FbTk::MenuItem(client.title().c_str(), menu), FbTk::MenuItem(client.title().c_str(), menu),
m_client(client) { m_client(client) {
client.titleSig().attach(&menu); m_signals.join(client.titleSig(),
client.dieSig().attach(&menu); FbTk::MemFunSelectArg1(menu, &ClientMenu::titleChanged));
} client.dieSig().attach(&menu);
~ClientMenuItem() { m_client.titleSig().detach(menu()); } }
~ClientMenuItem() {
}
void click(int button, int time, unsigned int mods) { void click(int button, int time, unsigned int mods) {
FluxboxWindow *fbwin = m_client.fbwindow(); FluxboxWindow *fbwin = m_client.fbwindow();
@ -75,6 +78,7 @@ public:
private: private:
Focusable &m_client; Focusable &m_client;
FbTk::SignalTracker m_signals;
}; };
} // end anonymous namespace } // end anonymous namespace
@ -118,30 +122,46 @@ void ClientMenu::refreshMenu() {
updateMenu(); 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) { void ClientMenu::update(FbTk::Subject *subj) {
if (subj && typeid(*subj) == typeid(Focusable::FocusSubject)) { if (subj && typeid(*subj) == typeid(Focusable::FocusSubject)) {
Focusable::FocusSubject *fsubj = static_cast<Focusable::FocusSubject *>(subj); Focusable::FocusSubject *fsubj = static_cast<Focusable::FocusSubject *>(subj);
Focusable &win = fsubj->win(); Focusable &win = fsubj->win();
// find the corresponding menuitem // find correct menu item
ClientMenuItem *cl_item = 0; ClientMenuItem* cl_item = getMenuItem(*this, win);
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;
}
}
// update accordingly // update accordingly
if (cl_item && fsubj == &win.dieSig()) if (cl_item && fsubj == &win.dieSig()) {
remove(cl_item->getIndex()); 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 } else
FbTk::Menu::update(subj); FbTk::Menu::update(subj);
} }

View file

@ -28,6 +28,8 @@
class BScreen; class BScreen;
class FluxboxWindow; class FluxboxWindow;
class Focusable;
/** /**
* A menu holding a set of client menus. * A menu holding a set of client menus.
* @see WorkspaceMenu * @see WorkspaceMenu
@ -47,6 +49,10 @@ public:
/// refresh the entire menu /// refresh the entire menu
void refreshMenu(); void refreshMenu();
/// Called when window title changed.
void titleChanged(Focusable& win);
private: private:
void updateClientList(BScreen& screen) { void updateClientList(BScreen& screen) {

View file

@ -164,7 +164,7 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) {
if (width >= nr_icon_data) { if (width >= nr_icon_data) {
fbdbg << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON width (" fbdbg << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON width ("
<< width << ") for " << winclient.title() << "\n"; << width << ") for " << winclient.title() << "\n";
break; break;
} }
@ -172,7 +172,7 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) {
if (height >= nr_icon_data) { if (height >= nr_icon_data) {
fbdbg << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON height (" fbdbg << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON height ("
<< height << ") for " << winclient.title() << "\n"; << height << ") for " << winclient.title() << "\n";
break; break;
} }
@ -180,7 +180,7 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) {
// strange values stored in the NETWM_ICON // strange values stored in the NETWM_ICON
if (i + width * height > nr_icon_data) { if (i + width * height > nr_icon_data) {
fbdbg << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON dimensions (" 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; break;
} }
@ -1293,7 +1293,7 @@ bool Ewmh::propertyNotify(WinClient &winclient, Atom the_property) {
if (!newtitle.empty()) if (!newtitle.empty())
winclient.setTitle(newtitle); winclient.setTitle(newtitle);
if (winclient.fbwindow()) if (winclient.fbwindow())
winclient.fbwindow()->titleSig().notify(); winclient.fbwindow()->titleSig().emit(newtitle, *winclient.fbwindow());
return true; return true;
} else if (the_property == m_net->wm_icon_name) { } else if (the_property == m_net->wm_icon_name) {
// we don't use icon title, since we don't show icons // we don't use icon title, since we don't show icons

View file

@ -42,9 +42,10 @@ public:
m_screen(scr), m_fbwin(fbwin), m_screen(scr), m_fbwin(fbwin),
m_instance_name("fluxbox"), m_class_name("fluxbox"), m_instance_name("fluxbox"), m_class_name("fluxbox"),
m_focused(false), m_attention_state(false), m_focused(false), m_attention_state(false),
m_titlesig(*this), m_diesig(*this), m_diesig(*this),
m_attentionsig(*this), m_attentionsig(*this),
m_focussig() { } m_focussig(),
m_titlesig() { }
virtual ~Focusable() { } virtual ~Focusable() { }
/** /**
@ -116,10 +117,11 @@ public:
@name signals @name signals
@{ @{
*/ */
// Used for both title and icon changes. typedef FbTk::Signal<void, const std::string&, Focusable&> TitleSignal;
FbTk::Subject &titleSig() { return m_titlesig; } /// Used for both title and icon changes.
// Used for both title and icon changes. TitleSignal &titleSig() { return m_titlesig; }
const FbTk::Subject &titleSig() const { 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; } FbTk::Signal<void, Focusable&> &focusSig() { return m_focussig; }
const FbTk::Signal<void, Focusable&> &focusSig() const { return m_focussig; } const FbTk::Signal<void, Focusable&> &focusSig() const { return m_focussig; }
FbTk::Subject &dieSig() { return m_diesig; } FbTk::Subject &dieSig() { return m_diesig; }
@ -143,10 +145,11 @@ protected:
FbTk::PixmapWithMask m_icon; //< icon pixmap with mask FbTk::PixmapWithMask m_icon; //< icon pixmap with mask
// state and hint signals // state and hint signals
FocusSubject m_titlesig, m_diesig, m_attentionsig; FocusSubject m_diesig, m_attentionsig;
private: private:
FbTk::Signal<void, Focusable&> m_focussig; FbTk::Signal<void, Focusable&> m_focussig;
TitleSignal m_titlesig;
}; };
#endif // FOCUSABLE_HH #endif // FOCUSABLE_HH

View file

@ -113,10 +113,9 @@ void FocusableList::update(FbTk::Subject *subj) {
if (typeid(*subj) == typeid(Focusable::FocusSubject)) { if (typeid(*subj) == typeid(Focusable::FocusSubject)) {
Focusable::FocusSubject *fsubj = Focusable::FocusSubject *fsubj =
static_cast<Focusable::FocusSubject *>(subj); static_cast<Focusable::FocusSubject *>(subj);
if (fsubj == &fsubj->win().dieSig()) if (fsubj == &fsubj->win().dieSig()) {
remove(fsubj->win()); remove(fsubj->win());
else if (fsubj == &fsubj->win().titleSig()) }
checkUpdate(fsubj->win());
} }
if (typeid(*subj) == typeid(FluxboxWindow::WinSubject)) { if (typeid(*subj) == typeid(FluxboxWindow::WinSubject)) {
FluxboxWindow::WinSubject *fsubj = FluxboxWindow::WinSubject *fsubj =
@ -244,17 +243,27 @@ void FocusableList::remove(Focusable &win) {
bool contained = contains(win); bool contained = contains(win);
detachSignals(win); detachSignals(win);
if (!contained) if (!contained) {
return; return;
}
m_list.remove(&win); m_list.remove(&win);
m_removesig.notify(&win); m_removesig.notify(&win);
} }
void FocusableList::updateTitle(Focusable& win) {
checkUpdate(win);
}
void FocusableList::attachSignals(Focusable &win) { void FocusableList::attachSignals(Focusable &win) {
win.dieSig().attach(this); win.dieSig().attach(this);
if (m_parent) { if (m_parent) {
// attach various signals for matching // 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(); FluxboxWindow *fbwin = win.fbwindow();
if (!fbwin) if (!fbwin)
return; return;
@ -268,8 +277,14 @@ void FocusableList::attachSignals(Focusable &win) {
void FocusableList::detachSignals(Focusable &win) { void FocusableList::detachSignals(Focusable &win) {
win.dieSig().detach(this); win.dieSig().detach(this);
if (m_parent) { 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 // detach various signals for matching
win.titleSig().detach(this);
FluxboxWindow *fbwin = win.fbwindow(); FluxboxWindow *fbwin = win.fbwindow();
if (!fbwin) if (!fbwin)
return; return;

View file

@ -116,12 +116,18 @@ private:
void attachChild(FocusableList &child) const; void attachChild(FocusableList &child) const;
void workspaceChanged(BScreen &screen); void workspaceChanged(BScreen &screen);
void focusedWindowChanged(BScreen &screen, FluxboxWindow *win, WinClient *client); 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; std::auto_ptr<ClientPattern> m_pat;
const FocusableList *m_parent; const FocusableList *m_parent;
BScreen &m_screen; BScreen &m_screen;
std::list<Focusable *> m_list; std::list<Focusable *> m_list;
mutable FocusableListSubject m_ordersig, m_addsig, m_removesig, m_resetsig; 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 #endif // FOCUSABLELIST_HH

View file

@ -59,15 +59,18 @@ IconButton::IconButton(const FbTk::FbWindow &parent,
m_theme(win, focused_theme, unfocused_theme), m_theme(win, focused_theme, unfocused_theme),
m_pm(win.screen().imageControl()) { 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(), m_signals.join(m_win.focusSig(),
MemFunIgnoreArgs(*this, &IconButton::reconfigAndClear)); MemFunIgnoreArgs(*this, &IconButton::reconfigAndClear));
m_win.attentionSig().attach(this); m_win.attentionSig().attach(this);
FbTk::EventManager::instance()->add(*this, m_icon_window); FbTk::EventManager::instance()->add(*this, m_icon_window);
reconfigTheme(); reconfigTheme();
update(0); refreshEverything(false);
} }
IconButton::~IconButton() { IconButton::~IconButton() {
@ -102,7 +105,7 @@ void IconButton::moveResize(int x, int y,
if (m_icon_window.width() != FbTk::Button::width() || if (m_icon_window.width() != FbTk::Button::width() ||
m_icon_window.height() != FbTk::Button::height()) { m_icon_window.height() != FbTk::Button::height()) {
reconfigTheme(); 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() || if (m_icon_window.width() != FbTk::Button::width() ||
m_icon_window.height() != FbTk::Button::height()) { m_icon_window.height() != FbTk::Button::height()) {
reconfigTheme(); 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) { void IconButton::setPixmap(bool use) {
if (m_use_pixmap != use) { if (m_use_pixmap != use) {
m_use_pixmap = use; m_use_pixmap = use;
update(0); refreshEverything(false);
} }
} }
@ -175,16 +178,7 @@ void IconButton::reconfigAndClear() {
clear(); clear();
} }
void IconButton::update(FbTk::Subject *subj) { void IconButton::refreshEverything(bool setup) {
// 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
Display *display = FbTk::App::instance()->display(); Display *display = FbTk::App::instance()->display();
int screen = m_win.screen().screenNumber(); int screen = m_win.screen().screenNumber();
@ -242,17 +236,36 @@ void IconButton::update(FbTk::Subject *subj) {
#endif // SHAPE #endif // SHAPE
if (subj != 0) { if (setup) {
setupWindow(); setupWindow();
} else { } else {
m_icon_window.clear(); 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, // if the title was changed AND the mouse is over *this,
// update the tooltip // update the tooltip
if (subj == &m_win.titleSig() && m_has_tooltip)
showTooltip();
refreshEverything(subj != 0);
} }
void IconButton::setupWindow() { void IconButton::setupWindow() {

View file

@ -73,6 +73,12 @@ private:
void setupWindow(); void setupWindow();
void showTooltip(); 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; Focusable &m_win;
FbTk::FbWindow m_icon_window; FbTk::FbWindow m_icon_window;
FbTk::FbPixmap m_icon_pixmap; FbTk::FbPixmap m_icon_pixmap;

View file

@ -278,8 +278,7 @@ void WinButton::clear() {
FbTk::Button::clear(); FbTk::Button::clear();
drawType(); drawType();
} }
void WinButton::updateAll() {
void WinButton::update(FbTk::Subject *subj) {
// update the menu icon // update the menu icon
if (m_type == MENUICON && !m_listen_to.empty()) { if (m_type == MENUICON && !m_listen_to.empty()) {
@ -316,3 +315,7 @@ void WinButton::update(FbTk::Subject *subj) {
clear(); clear();
} }
void WinButton::update(FbTk::Subject *subj) {
updateAll();
}

View file

@ -25,6 +25,7 @@
#include "FbTk/Button.hh" #include "FbTk/Button.hh"
#include "FbTk/Observer.hh" #include "FbTk/Observer.hh"
#include "FbTk/FbPixmap.hh" #include "FbTk/FbPixmap.hh"
#include "FbTk/Signal.hh"
class FluxboxWindow; class FluxboxWindow;
class WinButtonTheme; class WinButtonTheme;
@ -35,7 +36,7 @@ template <class T> class ThemeProxy;
} }
/// draws and handles basic window button graphic /// 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: public:
/// draw type for the button /// draw type for the button
enum Type {MAXIMIZE, MINIMIZE, SHADE, STICK, CLOSE, MENUICON}; enum Type {MAXIMIZE, MINIMIZE, SHADE, STICK, CLOSE, MENUICON};
@ -57,6 +58,7 @@ public:
/// override for redrawing /// override for redrawing
void clear(); void clear();
void update(FbTk::Subject *subj); void update(FbTk::Subject *subj);
void updateAll();
private: private:
void drawType(); void drawType();
Type m_type; ///< the button type Type m_type; ///< the button type

View file

@ -341,13 +341,13 @@ void WinClient::updateTitle() {
return; return;
m_title = string(Xutil::getWMName(window()), 0, 512); m_title = string(Xutil::getWMName(window()), 0, 512);
titleSig().notify(); titleSig().emit(m_title, *this);
} }
void WinClient::setTitle(const FbTk::FbString &title) { void WinClient::setTitle(const FbTk::FbString &title) {
m_title = title; m_title = title;
m_title_override = true; m_title_override = true;
titleSig().notify(); titleSig().emit(m_title, *this);
} }
void WinClient::setIcon(const FbTk::PixmapWithMask& pm) { 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.pixmap().copy(pm.pixmap());
m_icon.mask().copy(pm.mask()); m_icon.mask().copy(pm.mask());
m_icon_override = true; m_icon_override = true;
titleSig().notify(); titleSig().emit(m_title, *this);
} }
void WinClient::setFluxboxWindow(FluxboxWindow *win) { void WinClient::setFluxboxWindow(FluxboxWindow *win) {

View file

@ -988,7 +988,7 @@ bool FluxboxWindow::setCurrentClient(WinClient &client, bool setinput) {
button<<endl; button<<endl;
if (old != &client) { if (old != &client) {
titleSig().notify(); titleSig().emit(title(), *this);
frame().setFocusTitle(title()); frame().setFocusTitle(title());
frame().setShapingClient(&client, false); frame().setShapingClient(&client, false);
} }
@ -2103,7 +2103,7 @@ void FluxboxWindow::propertyNotifyEvent(WinClient &client, Atom atom) {
case XA_WM_HINTS: case XA_WM_HINTS:
client.updateWMHints(); client.updateWMHints();
titleSig().notify(); titleSig().emit(title(), *this);
// nothing uses this yet // nothing uses this yet
// hintSig().notify(); // notify listeners // hintSig().notify(); // notify listeners
break; break;
@ -2707,18 +2707,19 @@ void FluxboxWindow::leaveNotifyEvent(XCrossingEvent &ev) {
//installColormap(false); //installColormap(false);
} }
void FluxboxWindow::setTitle(const std::string& title, Focusable &client) {
// only update focus title for current client
if (&client != m_client) {
return;
}
frame().setFocusTitle(title);
// relay title to others that display the focus title
titleSig().emit(title, *this);
}
void FluxboxWindow::update(FbTk::Subject *subj) { void FluxboxWindow::update(FbTk::Subject *subj) {
if (subj && typeid(*subj) == typeid(Focusable::FocusSubject)) { if (subj == &m_theme.reconfigSig()) {
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();
}
} else if (subj == &m_theme.reconfigSig()) {
frame().applyDecorations(); frame().applyDecorations();
sendConfigureNotify(); sendConfigureNotify();
} else if (m_initialized && subj == &m_frame.frameExtentSig()) { } else if (m_initialized && subj == &m_frame.frameExtentSig()) {
@ -3637,7 +3638,9 @@ void FluxboxWindow::updateButtons() {
dir[i], dir[i],
frame().titlebar(), frame().titlebar(),
0, 0, 10, 10); 0, 0, 10, 10);
titleSig().attach(winbtn); winbtn->join(titleSig(),
FbTk::MemFunIgnoreArgs(*winbtn, &WinButton::updateAll));
winbtn->setOnClick(show_menu_cmd); winbtn->setOnClick(show_menu_cmd);
break; 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, btn->window()); // we take care of button events for this
evm.add(*this, client.window()); evm.add(*this, client.window());
client.setFluxboxWindow(this); client.setFluxboxWindow(this);
client.titleSig().attach(this); join(client.titleSig(),
FbTk::MemFun(*this, &FluxboxWindow::setTitle));
} }
FluxboxWindow::ReferenceCorner FluxboxWindow::getCorner(string str) { FluxboxWindow::ReferenceCorner FluxboxWindow::getCorner(string str) {

View file

@ -474,6 +474,9 @@ public:
bool oplock; ///< Used to help stop transient loops occurring by locking a window during certain operations bool oplock; ///< Used to help stop transient loops occurring by locking a window during certain operations
private: private:
/// signal callback for title changes by clients
void setTitle(const std::string &title, Focusable &client);
void setupWindow(); void setupWindow();
void updateButtons(); void updateButtons();