Make Urgency Hint flash the correct WinClient's tab.
This commit is contained in:
parent
0b730c76b1
commit
a23ad67197
11 changed files with 79 additions and 35 deletions
|
@ -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)
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue