Make Urgency Hint flash the correct WinClient's tab.

This commit is contained in:
markt 2006-06-24 18:19:49 +00:00
parent 0b730c76b1
commit a23ad67197
11 changed files with 79 additions and 35 deletions

View file

@ -1,6 +1,9 @@
(Format: Year/Month/Day) (Format: Year/Month/Day)
Changes for 1.0rc2: Changes for 1.0rc2:
*06/06/24: *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) * Fix some more X-errors (Simon)
- window was resized, triggering background re-render, but - window was resized, triggering background re-render, but
background is invalid sometimes (during reconfiguring) background is invalid sometimes (during reconfiguring)

View file

@ -23,7 +23,7 @@
#include "AttentionNoticeHandler.hh" #include "AttentionNoticeHandler.hh"
#include "Window.hh" #include "WinClient.hh"
#include "Screen.hh" #include "Screen.hh"
#include "STLUtil.hh" #include "STLUtil.hh"
@ -34,14 +34,16 @@
namespace { namespace {
class ToggleFrameFocusCmd: public FbTk::Command { class ToggleFrameFocusCmd: public FbTk::Command {
public: public:
ToggleFrameFocusCmd(FluxboxWindow &win): ToggleFrameFocusCmd(WinClient &client):
m_win(win) {} m_client(client) {}
void execute() { void execute() {
m_win.frame().setFocus( ! m_win.frame().focused() ); m_state ^= true;
m_win.attentionSig().notify(); m_client.fbwindow()->setLabelButtonFocus(m_client, m_state);
m_client.fbwindow()->setAttentionState(m_state);
} }
private: private:
FluxboxWindow& m_win; WinClient& m_client;
bool m_state;
}; };
} // end anonymous namespace } // end anonymous namespace
@ -51,27 +53,27 @@ AttentionNoticeHandler::~AttentionNoticeHandler() {
STLUtil::destroyAndClearSecond(m_attentions); STLUtil::destroyAndClearSecond(m_attentions);
} }
void AttentionNoticeHandler::addAttention(FluxboxWindow &win) { void AttentionNoticeHandler::addAttention(WinClient &client) {
// no need to add already focused window // no need to add already active client
if (win.isFocused()) if (client.fbwindow()->isFocused() && &client.fbwindow()->winClient() == &client)
return; return;
// Already have a notice for it? // 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()) { if (it != m_attentions.end()) {
return; return;
} }
using namespace FbTk; using namespace FbTk;
ResourceManager &res = win.screen().resourceManager(); ResourceManager &res = client.screen().resourceManager();
std::string res_name = win.screen().name() + ".demandsAttentionTimeout"; std::string res_name = client.screen().name() + ".demandsAttentionTimeout";
std::string res_alt_name = win.screen().name() + ".DemandsAttentionTimeout"; std::string res_alt_name = client.screen().name() + ".DemandsAttentionTimeout";
Resource<int> *timeout_res = dynamic_cast<Resource<int>* >(res.findResource(res_name)); Resource<int> *timeout_res = dynamic_cast<Resource<int>* >(res.findResource(res_name));
if (timeout_res == 0) { if (timeout_res == 0) {
// no resource, create one and add it to managed resources // no resource, create one and add it to managed resources
timeout_res = new FbTk::Resource<int>(res, 500, res_name, res_alt_name); timeout_res = new FbTk::Resource<int>(res, 500, res_name, res_alt_name);
win.screen().addManagedResource(timeout_res); client.screen().addManagedResource(timeout_res);
} }
// disable if timeout is zero // disable if timeout is zero
if (**timeout_res == 0) if (**timeout_res == 0)
@ -82,25 +84,25 @@ void AttentionNoticeHandler::addAttention(FluxboxWindow &win) {
timeval timeout; timeval timeout;
timeout.tv_sec = 0; timeout.tv_sec = 0;
timeout.tv_usec = **timeout_res * 1000; timeout.tv_usec = **timeout_res * 1000;
RefCount<Command> cmd(new ToggleFrameFocusCmd(win)); RefCount<Command> cmd(new ToggleFrameFocusCmd(client));
timer->setCommand(cmd); timer->setCommand(cmd);
timer->setTimeout(timeout); timer->setTimeout(timeout);
timer->fireOnce(false); // will repeat until window has focus timer->fireOnce(false); // will repeat until window has focus
timer->start(); timer->start();
m_attentions[&win] = timer; m_attentions[&client] = timer;
// attach signals that will make notice go away // attach signals that will make notice go away
win.dieSig().attach(this); client.dieSig().attach(this);
win.focusSig().attach(this); client.focusSig().attach(this);
} }
void AttentionNoticeHandler::update(FbTk::Subject *subj) { void AttentionNoticeHandler::update(FbTk::Subject *subj) {
// all signals results in destruction of the notice // all signals results in destruction of the notice
FluxboxWindow::WinSubject *winsubj = WinClient::WinClientSubj *winsubj =
static_cast<FluxboxWindow::WinSubject*>(subj); static_cast<WinClient::WinClientSubj *>(subj);
delete m_attentions[&winsubj->win()]; delete m_attentions[&winsubj->winClient()];
m_attentions.erase(&winsubj->win()); m_attentions.erase(&winsubj->winClient());
} }

View file

@ -27,7 +27,7 @@
#include <map> #include <map>
class FluxboxWindow; class WinClient;
namespace FbTk { namespace FbTk {
class Timer; class Timer;
@ -41,11 +41,11 @@ class AttentionNoticeHandler: public FbTk::Observer {
public: public:
~AttentionNoticeHandler(); ~AttentionNoticeHandler();
typedef std::map<FluxboxWindow*, FbTk::Timer*> NoticeMap; typedef std::map<WinClient*, FbTk::Timer*> NoticeMap;
/// Adds a window that requires attention, /// Adds a client that requires attention,
/// will fail if the window is already focused /// will fail if the client is already active
void addAttention(FluxboxWindow &win); void addAttention(WinClient &client);
/// removes the window from the attention map /// removes the client from the attention map
void update(FbTk::Subject *subj); void update(FbTk::Subject *subj);
private: private:

View file

@ -1084,10 +1084,10 @@ void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) {
win.moveToLayer(Layer::NORMAL); win.moveToLayer(Layer::NORMAL);
} else if (state == m_net_wm_state_demands_attention) { } else if (state == m_net_wm_state_demands_attention) {
if (value) { // if add attention if (value) { // if add attention
Fluxbox::instance()->attentionHandler().addAttention(win); Fluxbox::instance()->attentionHandler().addAttention(win.winClient());
} else { // erase it } else { // erase it
Fluxbox::instance()->attentionHandler(). Fluxbox::instance()->attentionHandler().
update(&win.attentionSig()); update(&win.winClient().focusSig());
} }
} }

View file

@ -650,6 +650,18 @@ void FbWinFrame::setLabelButtonFocus(FbTk::TextButton &btn) {
applyActiveLabel(*m_current_label); 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) { void FbWinFrame::setClientWindow(FbTk::FbWindow &win) {
win.setBorderWidth(0); win.setBorderWidth(0);

View file

@ -150,6 +150,8 @@ public:
void moveLabelButtonRightOf(FbTk::TextButton &btn, const FbTk::TextButton &dest); void moveLabelButtonRightOf(FbTk::TextButton &btn, const FbTk::TextButton &dest);
/// which button is to be rendered focused /// which button is to be rendered focused
void setLabelButtonFocus(FbTk::TextButton &btn); void setLabelButtonFocus(FbTk::TextButton &btn);
/// specify focus state of button
void setLabelButtonFocus(FbTk::TextButton &btn, bool value);
/// attach a client window for client area /// attach a client window for client area
void setClientWindow(FbTk::FbWindow &win); void setClientWindow(FbTk::FbWindow &win);
/// remove attached client window /// remove attached client window

View file

@ -601,7 +601,7 @@ void IconbarTool::update(FbTk::Subject *subj) {
IconButton *button = findButton(winsubj->win()); IconButton *button = findButton(winsubj->win());
if (button) { if (button) {
renderButton(*button, true, renderButton(*button, true,
winsubj->win().frame().focused() ? 1 : 0); winsubj->win().getAttentionState());
} }
return; return;
} else { } else {

View file

@ -74,7 +74,8 @@ WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):FbTk::Fb
m_blackbox_hint(0), m_blackbox_hint(0),
m_mwm_hint(0), m_mwm_hint(0),
m_focus_mode(F_PASSIVE), m_focus_mode(F_PASSIVE),
m_diesig(*this), m_screen(screen), m_diesig(*this), m_focussig(*this),
m_screen(screen),
m_strut(0) { m_strut(0) {
updateWMProtocols(); updateWMProtocols();
updateBlackboxHints(); updateBlackboxHints();
@ -516,10 +517,10 @@ void WinClient::updateWMHints() {
if (m_win && m_win->isInitialized()) { if (m_win && m_win->isInitialized()) {
if (wmhint->flags & XUrgencyHint) { if (wmhint->flags & XUrgencyHint) {
Fluxbox::instance()->attentionHandler().addAttention(*m_win); Fluxbox::instance()->attentionHandler().addAttention(*this);
} else { } else {
Fluxbox::instance()->attentionHandler(). Fluxbox::instance()->attentionHandler().
update(&(m_win->attentionSig())); update(&m_focussig);
} }
} }

View file

@ -117,6 +117,8 @@ public:
const BScreen &screen() const { return m_screen; } const BScreen &screen() const { return m_screen; }
/// notifies when this client dies /// notifies when this client dies
FbTk::Subject &dieSig() { return m_diesig; } 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 WinClient *transientFor() { return transient_for; }
inline const WinClient *transientFor() const { return transient_for; } inline const WinClient *transientFor() const { return transient_for; }
@ -211,6 +213,7 @@ private:
int m_focus_mode; int m_focus_mode;
WinClientSubj m_diesig; WinClientSubj m_diesig;
WinClientSubj m_focussig;
BScreen &m_screen; BScreen &m_screen;
Strut *m_strut; Strut *m_strut;

View file

@ -1065,6 +1065,7 @@ bool FluxboxWindow::setCurrentClient(WinClient &client, bool setinput) {
m_client = &client; m_client = &client;
m_client->raise(); m_client->raise();
m_client->focusSig().notify();
titleSig().notify(); titleSig().notify();
#ifdef DEBUG #ifdef DEBUG
@ -1081,6 +1082,19 @@ bool FluxboxWindow::setCurrentClient(WinClient &client, bool setinput) {
return false; 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 { bool FluxboxWindow::isGroupable() const {
if (isResizable() && isMaximizable() && !winClient().isTransient()) if (isResizable() && isMaximizable() && !winClient().isTransient())
return true; return true;
@ -2095,8 +2109,11 @@ void FluxboxWindow::setFocusFlag(bool focus) {
} }
// did focus change? notify listeners // did focus change? notify listeners
if (was_focused != focus) if (was_focused != focus) {
m_focussig.notify(); m_focussig.notify();
if (m_client)
m_client->focusSig().notify();
}
} }

View file

@ -178,6 +178,9 @@ public:
bool removeClient(WinClient &client); bool removeClient(WinClient &client);
/// set new current client and raise it /// set new current client and raise it
bool setCurrentClient(WinClient &client, bool setinput = true); 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); WinClient *findClient(Window win);
void nextClient(); void nextClient();
void prevClient(); void prevClient();
@ -500,6 +503,7 @@ private:
WinClient *m_attaching_tab; WinClient *m_attaching_tab;
bool m_attention_state;
BScreen &m_screen; /// screen on which this window exist BScreen &m_screen; /// screen on which this window exist
FbTk::Timer m_timer; FbTk::Timer m_timer;
Display *display; /// display connection Display *display; /// display connection