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)
|
(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)
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue