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):
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);
}

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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() {

View file

@ -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;

View file

@ -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();
}

View file

@ -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

View file

@ -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) {

View file

@ -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::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) {
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();
}
} else if (subj == &m_theme.reconfigSig()) {
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) {

View file

@ -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();