From a23ad6719725a0290d01ac4bba0ce1905b2069d7 Mon Sep 17 00:00:00 2001 From: markt Date: Sat, 24 Jun 2006 18:19:49 +0000 Subject: Make Urgency Hint flash the correct WinClient's tab. --- ChangeLog | 3 +++ src/AttentionNoticeHandler.cc | 46 ++++++++++++++++++++++--------------------- src/AttentionNoticeHandler.hh | 12 +++++------ src/Ewmh.cc | 4 ++-- src/FbWinFrame.cc | 12 +++++++++++ src/FbWinFrame.hh | 2 ++ src/IconbarTool.cc | 2 +- src/WinClient.cc | 7 ++++--- src/WinClient.hh | 3 +++ src/Window.cc | 19 +++++++++++++++++- src/Window.hh | 4 ++++ 11 files changed, 79 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index 452c86d..74f46ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ (Format: Year/Month/Day) Changes for 1.0rc2: *06/06/24: + * Make Urgency Hint flash the correct tab in a group (Mark) + Ewmh.cc Window.cc/hh WinClient.cc/hh FbWinFrame.cc/hh IconbarTool.cc + AttentionNoticeHandler.cc/hh * Fix some more X-errors (Simon) - window was resized, triggering background re-render, but background is invalid sometimes (during reconfiguring) diff --git a/src/AttentionNoticeHandler.cc b/src/AttentionNoticeHandler.cc index 7cc2760..e2881af 100644 --- a/src/AttentionNoticeHandler.cc +++ b/src/AttentionNoticeHandler.cc @@ -23,7 +23,7 @@ #include "AttentionNoticeHandler.hh" -#include "Window.hh" +#include "WinClient.hh" #include "Screen.hh" #include "STLUtil.hh" @@ -34,14 +34,16 @@ namespace { class ToggleFrameFocusCmd: public FbTk::Command { public: - ToggleFrameFocusCmd(FluxboxWindow &win): - m_win(win) {} + ToggleFrameFocusCmd(WinClient &client): + m_client(client) {} void execute() { - m_win.frame().setFocus( ! m_win.frame().focused() ); - m_win.attentionSig().notify(); + m_state ^= true; + m_client.fbwindow()->setLabelButtonFocus(m_client, m_state); + m_client.fbwindow()->setAttentionState(m_state); } private: - FluxboxWindow& m_win; + WinClient& m_client; + bool m_state; }; } // end anonymous namespace @@ -51,27 +53,27 @@ AttentionNoticeHandler::~AttentionNoticeHandler() { STLUtil::destroyAndClearSecond(m_attentions); } -void AttentionNoticeHandler::addAttention(FluxboxWindow &win) { - // no need to add already focused window - if (win.isFocused()) +void AttentionNoticeHandler::addAttention(WinClient &client) { + // no need to add already active client + if (client.fbwindow()->isFocused() && &client.fbwindow()->winClient() == &client) return; // Already have a notice for it? - NoticeMap::iterator it = m_attentions.find(&win); + NoticeMap::iterator it = m_attentions.find(&client); if (it != m_attentions.end()) { return; } using namespace FbTk; - ResourceManager &res = win.screen().resourceManager(); - std::string res_name = win.screen().name() + ".demandsAttentionTimeout"; - std::string res_alt_name = win.screen().name() + ".DemandsAttentionTimeout"; + ResourceManager &res = client.screen().resourceManager(); + std::string res_name = client.screen().name() + ".demandsAttentionTimeout"; + std::string res_alt_name = client.screen().name() + ".DemandsAttentionTimeout"; Resource *timeout_res = dynamic_cast* >(res.findResource(res_name)); if (timeout_res == 0) { // no resource, create one and add it to managed resources timeout_res = new FbTk::Resource(res, 500, res_name, res_alt_name); - win.screen().addManagedResource(timeout_res); + client.screen().addManagedResource(timeout_res); } // disable if timeout is zero if (**timeout_res == 0) @@ -82,25 +84,25 @@ void AttentionNoticeHandler::addAttention(FluxboxWindow &win) { timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = **timeout_res * 1000; - RefCount cmd(new ToggleFrameFocusCmd(win)); + RefCount cmd(new ToggleFrameFocusCmd(client)); timer->setCommand(cmd); timer->setTimeout(timeout); timer->fireOnce(false); // will repeat until window has focus timer->start(); - m_attentions[&win] = timer; + m_attentions[&client] = timer; // attach signals that will make notice go away - win.dieSig().attach(this); - win.focusSig().attach(this); + client.dieSig().attach(this); + client.focusSig().attach(this); } void AttentionNoticeHandler::update(FbTk::Subject *subj) { // all signals results in destruction of the notice - FluxboxWindow::WinSubject *winsubj = - static_cast(subj); - delete m_attentions[&winsubj->win()]; - m_attentions.erase(&winsubj->win()); + WinClient::WinClientSubj *winsubj = + static_cast(subj); + delete m_attentions[&winsubj->winClient()]; + m_attentions.erase(&winsubj->winClient()); } diff --git a/src/AttentionNoticeHandler.hh b/src/AttentionNoticeHandler.hh index aa2f9f2..836a023 100644 --- a/src/AttentionNoticeHandler.hh +++ b/src/AttentionNoticeHandler.hh @@ -27,7 +27,7 @@ #include -class FluxboxWindow; +class WinClient; namespace FbTk { class Timer; @@ -41,11 +41,11 @@ class AttentionNoticeHandler: public FbTk::Observer { public: ~AttentionNoticeHandler(); - typedef std::map NoticeMap; - /// Adds a window that requires attention, - /// will fail if the window is already focused - void addAttention(FluxboxWindow &win); - /// removes the window from the attention map + typedef std::map NoticeMap; + /// Adds a client that requires attention, + /// will fail if the client is already active + void addAttention(WinClient &client); + /// removes the client from the attention map void update(FbTk::Subject *subj); private: diff --git a/src/Ewmh.cc b/src/Ewmh.cc index d74092a..15caab0 100644 --- a/src/Ewmh.cc +++ b/src/Ewmh.cc @@ -1084,10 +1084,10 @@ void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) { win.moveToLayer(Layer::NORMAL); } else if (state == m_net_wm_state_demands_attention) { if (value) { // if add attention - Fluxbox::instance()->attentionHandler().addAttention(win); + Fluxbox::instance()->attentionHandler().addAttention(win.winClient()); } else { // erase it Fluxbox::instance()->attentionHandler(). - update(&win.attentionSig()); + update(&win.winClient().focusSig()); } } diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc index 9df9012..9e7eedf 100644 --- a/src/FbWinFrame.cc +++ b/src/FbWinFrame.cc @@ -650,6 +650,18 @@ void FbWinFrame::setLabelButtonFocus(FbTk::TextButton &btn) { applyActiveLabel(*m_current_label); } +void FbWinFrame::setLabelButtonFocus(FbTk::TextButton &btn, bool value) { + if (btn.parent() != &m_tab_container) + return; + + if (value) + applyFocusLabel(btn); + else + applyUnfocusLabel(btn); + + btn.clear(); +} + void FbWinFrame::setClientWindow(FbTk::FbWindow &win) { win.setBorderWidth(0); diff --git a/src/FbWinFrame.hh b/src/FbWinFrame.hh index e8003d3..6858579 100644 --- a/src/FbWinFrame.hh +++ b/src/FbWinFrame.hh @@ -150,6 +150,8 @@ public: void moveLabelButtonRightOf(FbTk::TextButton &btn, const FbTk::TextButton &dest); /// which button is to be rendered focused void setLabelButtonFocus(FbTk::TextButton &btn); + /// specify focus state of button + void setLabelButtonFocus(FbTk::TextButton &btn, bool value); /// attach a client window for client area void setClientWindow(FbTk::FbWindow &win); /// remove attached client window diff --git a/src/IconbarTool.cc b/src/IconbarTool.cc index 4dc6d24..73817f1 100644 --- a/src/IconbarTool.cc +++ b/src/IconbarTool.cc @@ -601,7 +601,7 @@ void IconbarTool::update(FbTk::Subject *subj) { IconButton *button = findButton(winsubj->win()); if (button) { renderButton(*button, true, - winsubj->win().frame().focused() ? 1 : 0); + winsubj->win().getAttentionState()); } return; } else { diff --git a/src/WinClient.cc b/src/WinClient.cc index acb8250..1ede4d8 100644 --- a/src/WinClient.cc +++ b/src/WinClient.cc @@ -74,7 +74,8 @@ WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):FbTk::Fb m_blackbox_hint(0), m_mwm_hint(0), m_focus_mode(F_PASSIVE), - m_diesig(*this), m_screen(screen), + m_diesig(*this), m_focussig(*this), + m_screen(screen), m_strut(0) { updateWMProtocols(); updateBlackboxHints(); @@ -516,10 +517,10 @@ void WinClient::updateWMHints() { if (m_win && m_win->isInitialized()) { if (wmhint->flags & XUrgencyHint) { - Fluxbox::instance()->attentionHandler().addAttention(*m_win); + Fluxbox::instance()->attentionHandler().addAttention(*this); } else { Fluxbox::instance()->attentionHandler(). - update(&(m_win->attentionSig())); + update(&m_focussig); } } diff --git a/src/WinClient.hh b/src/WinClient.hh index 870de6a..3a9d792 100644 --- a/src/WinClient.hh +++ b/src/WinClient.hh @@ -117,6 +117,8 @@ public: const BScreen &screen() const { return m_screen; } /// notifies when this client dies FbTk::Subject &dieSig() { return m_diesig; } + /// notifies when this client becomes focused + FbTk::Subject &focusSig() { return m_focussig; } inline WinClient *transientFor() { return transient_for; } inline const WinClient *transientFor() const { return transient_for; } @@ -211,6 +213,7 @@ private: int m_focus_mode; WinClientSubj m_diesig; + WinClientSubj m_focussig; BScreen &m_screen; Strut *m_strut; diff --git a/src/Window.cc b/src/Window.cc index 1ad789d..145dc8e 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -1065,6 +1065,7 @@ bool FluxboxWindow::setCurrentClient(WinClient &client, bool setinput) { m_client = &client; m_client->raise(); + m_client->focusSig().notify(); titleSig().notify(); #ifdef DEBUG @@ -1081,6 +1082,19 @@ bool FluxboxWindow::setCurrentClient(WinClient &client, bool setinput) { return false; } +void FluxboxWindow::setLabelButtonFocus(WinClient &client, bool value) { + // make sure it's in our list + if (client.fbwindow() != this) + return; + + frame().setLabelButtonFocus(*m_labelbuttons[&client], value); +} + +void FluxboxWindow::setAttentionState(bool value) { + m_attention_state = value; + m_attentionsig.notify(); +} + bool FluxboxWindow::isGroupable() const { if (isResizable() && isMaximizable() && !winClient().isTransient()) return true; @@ -2095,8 +2109,11 @@ void FluxboxWindow::setFocusFlag(bool focus) { } // did focus change? notify listeners - if (was_focused != focus) + if (was_focused != focus) { m_focussig.notify(); + if (m_client) + m_client->focusSig().notify(); + } } diff --git a/src/Window.hh b/src/Window.hh index 27e8138..2b4ef92 100644 --- a/src/Window.hh +++ b/src/Window.hh @@ -178,6 +178,9 @@ public: bool removeClient(WinClient &client); /// set new current client and raise it bool setCurrentClient(WinClient &client, bool setinput = true); + void setLabelButtonFocus(WinClient &client, bool value = true); + void setAttentionState(bool value); + bool getAttentionState() { return m_attention_state; } WinClient *findClient(Window win); void nextClient(); void prevClient(); @@ -500,6 +503,7 @@ private: WinClient *m_attaching_tab; + bool m_attention_state; BScreen &m_screen; /// screen on which this window exist FbTk::Timer m_timer; Display *display; /// display connection -- cgit v0.11.2