feat(xworkspaces): add urgent desktop detection

This commit is contained in:
NBonaparte 2017-02-19 23:25:19 -08:00 committed by Michael Carlberg
parent bd8e748399
commit 44f12c6065
8 changed files with 55 additions and 2 deletions

View File

@ -66,6 +66,7 @@ namespace modules {
void rebuild_clientlist();
void rebuild_desktops();
void rebuild_desktop_states();
void set_desktop_urgent(xcb_window_t window);
bool input(string&& cmd);

View File

@ -8,7 +8,7 @@ struct cached_atom {
xcb_atom_t* atom;
};
extern cached_atom ATOMS[35];
extern cached_atom ATOMS[36];
extern xcb_atom_t _NET_SUPPORTED;
extern xcb_atom_t _NET_CURRENT_DESKTOP;
@ -45,3 +45,4 @@ extern xcb_atom_t _XSETROOT_ID;
extern xcb_atom_t ESETROOT_PMAP_ID;
extern xcb_atom_t _COMPTON_SHADOW;
extern xcb_atom_t _NET_WM_WINDOW_OPACITY;
extern xcb_atom_t WM_HINTS;

View File

@ -27,6 +27,7 @@ namespace ewmh_util {
xcb_window_t get_active_window(int screen = 0);
void change_current_desktop(unsigned int desktop);
unsigned int get_desktop_from_window(xcb_window_t window);
void set_wm_window_type(xcb_window_t win, vector<xcb_atom_t> types);

View File

@ -12,6 +12,7 @@ namespace icccm_util {
void set_wm_name(xcb_connection_t* c, xcb_window_t w, const char* wmname, size_t l, const char* wmclass, size_t l2);
void set_wm_protocols(xcb_connection_t* c, xcb_window_t w, vector<xcb_atom_t> flags);
bool get_wm_urgency(xcb_connection_t* c, xcb_window_t w);
}
POLYBAR_NS_END

View File

@ -104,6 +104,10 @@ namespace modules {
} else if (evt->atom == m_ewmh->_NET_CURRENT_DESKTOP) {
m_current_desktop = ewmh_util::get_current_desktop();
rebuild_desktop_states();
} else if (evt->atom == WM_HINTS) {
if (icccm_util::get_wm_urgency(m_connection, evt->window)) {
set_desktop_urgent(evt->window);
}
} else {
return;
}
@ -133,6 +137,8 @@ namespace modules {
std::set_difference(
clients.begin(), clients.end(), m_clientlist.begin(), m_clientlist.end(), back_inserter(diff));
for (auto&& win : diff) {
// listen for wm_hint (urgency) changes
m_connection.ensure_event_mask(win, XCB_EVENT_MASK_PROPERTY_CHANGE);
// track window
m_clientlist.emplace_back(win);
}
@ -215,6 +221,31 @@ namespace modules {
}
}
/**
* Find window and set corresponding desktop to urgent
*/
void xworkspaces_module::set_desktop_urgent(xcb_window_t window) {
auto desk = ewmh_util::get_desktop_from_window(window);
if(desk == m_current_desktop)
// ignore if current desktop is urgent
return;
for (auto&& v : m_viewports) {
for (auto&& d : v->desktops) {
if (d->index == desk && d->state != desktop_state::URGENT) {
d->state = desktop_state::URGENT;
d->label = m_labels.at(d->state)->clone();
d->label->reset_tokens();
d->label->replace_token("%index%", to_string(d->index - d->offset + 1));
d->label->replace_token("%name%", m_desktop_names[d->index]);
d->label->replace_token("%icon%", m_icons->get(m_desktop_names[d->index], DEFAULT_ICON)->get());
return;
}
}
}
}
/**
* Fetch and parse data
*/

View File

@ -38,9 +38,10 @@ xcb_atom_t _XSETROOT_ID;
xcb_atom_t ESETROOT_PMAP_ID;
xcb_atom_t _COMPTON_SHADOW;
xcb_atom_t _NET_WM_WINDOW_OPACITY;
xcb_atom_t WM_HINTS;
// clang-format off
cached_atom ATOMS[35] = {
cached_atom ATOMS[36] = {
{"_NET_SUPPORTED", sizeof("_NET_SUPPORTED") - 1, &_NET_SUPPORTED},
{"_NET_CURRENT_DESKTOP", sizeof("_NET_CURRENT_DESKTOP") - 1, &_NET_CURRENT_DESKTOP},
{"_NET_ACTIVE_WINDOW", sizeof("_NET_ACTIVE_WINDOW") - 1, &_NET_ACTIVE_WINDOW},
@ -76,5 +77,6 @@ cached_atom ATOMS[35] = {
{"ESETROOT_PMAP_ID", sizeof("ESETROOT_PMAP_ID") - 1, &ESETROOT_PMAP_ID},
{"_COMPTON_SHADOW", sizeof("_COMPTON_SHADOW") - 1, &_COMPTON_SHADOW},
{"_NET_WM_WINDOW_OPACITY", sizeof("_NET_WM_WINDOW_OPACITY") - 1, &_NET_WM_WINDOW_OPACITY},
{"WM_HINTS", sizeof("WM_HINTS") - 1, &WM_HINTS},
};
// clang-format on

View File

@ -112,6 +112,13 @@ namespace ewmh_util {
xcb_flush(conn->connection);
}
unsigned int get_desktop_from_window(xcb_window_t window) {
auto conn = initialize().get();
unsigned int desktop = XCB_NONE;
xcb_ewmh_get_wm_desktop_reply(conn, xcb_ewmh_get_wm_desktop(conn, window), &desktop, nullptr);
return desktop;
}
void set_wm_window_type(xcb_window_t win, vector<xcb_atom_t> types) {
auto conn = initialize().get();
xcb_ewmh_set_wm_window_type(conn, win, types.size(), types.data());

View File

@ -29,6 +29,15 @@ namespace icccm_util {
void set_wm_protocols(xcb_connection_t* c, xcb_window_t w, vector<xcb_atom_t> flags) {
xcb_icccm_set_wm_protocols(c, w, WM_PROTOCOLS, flags.size(), flags.data());
}
bool get_wm_urgency(xcb_connection_t* c, xcb_window_t w) {
xcb_icccm_wm_hints_t hints;
if (xcb_icccm_get_wm_hints_reply(c, xcb_icccm_get_wm_hints(c, w), &hints, NULL)) {
if(xcb_icccm_wm_hints_get_urgency(&hints) == XCB_ICCCM_WM_HINT_X_URGENCY)
return true;
}
return false;
}
}
POLYBAR_NS_END