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

View file

@ -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<int> *timeout_res = dynamic_cast<Resource<int>* >(res.findResource(res_name));
if (timeout_res == 0) {
// no resource, create one and add it to managed resources
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
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<Command> cmd(new ToggleFrameFocusCmd(win));
RefCount<Command> 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<FluxboxWindow::WinSubject*>(subj);
delete m_attentions[&winsubj->win()];
m_attentions.erase(&winsubj->win());
WinClient::WinClientSubj *winsubj =
static_cast<WinClient::WinClientSubj *>(subj);
delete m_attentions[&winsubj->winClient()];
m_attentions.erase(&winsubj->winClient());
}

View file

@ -27,7 +27,7 @@
#include <map>
class FluxboxWindow;
class WinClient;
namespace FbTk {
class Timer;
@ -41,11 +41,11 @@ class AttentionNoticeHandler: public FbTk::Observer {
public:
~AttentionNoticeHandler();
typedef std::map<FluxboxWindow*, FbTk::Timer*> 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<WinClient*, FbTk::Timer*> 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:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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