From 44f12c6065ff9066b1304cf83dfb6eedee8fd119 Mon Sep 17 00:00:00 2001 From: NBonaparte <98007b33@opayq.com> Date: Sun, 19 Feb 2017 23:25:19 -0800 Subject: [PATCH 1/4] feat(xworkspaces): add urgent desktop detection --- include/modules/xworkspaces.hpp | 1 + include/x11/atoms.hpp | 3 ++- include/x11/ewmh.hpp | 1 + include/x11/icccm.hpp | 1 + src/modules/xworkspaces.cpp | 31 +++++++++++++++++++++++++++++++ src/x11/atoms.cpp | 4 +++- src/x11/ewmh.cpp | 7 +++++++ src/x11/icccm.cpp | 9 +++++++++ 8 files changed, 55 insertions(+), 2 deletions(-) diff --git a/include/modules/xworkspaces.hpp b/include/modules/xworkspaces.hpp index e1f52426..2d5447db 100644 --- a/include/modules/xworkspaces.hpp +++ b/include/modules/xworkspaces.hpp @@ -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); diff --git a/include/x11/atoms.hpp b/include/x11/atoms.hpp index 169dd12a..94aa806e 100644 --- a/include/x11/atoms.hpp +++ b/include/x11/atoms.hpp @@ -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; diff --git a/include/x11/ewmh.hpp b/include/x11/ewmh.hpp index 8591da9c..bced1347 100644 --- a/include/x11/ewmh.hpp +++ b/include/x11/ewmh.hpp @@ -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 types); diff --git a/include/x11/icccm.hpp b/include/x11/icccm.hpp index 4f85eb83..d27bbb93 100644 --- a/include/x11/icccm.hpp +++ b/include/x11/icccm.hpp @@ -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 flags); + bool get_wm_urgency(xcb_connection_t* c, xcb_window_t w); } POLYBAR_NS_END diff --git a/src/modules/xworkspaces.cpp b/src/modules/xworkspaces.cpp index dfaf4141..7401eb5b 100644 --- a/src/modules/xworkspaces.cpp +++ b/src/modules/xworkspaces.cpp @@ -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 */ diff --git a/src/x11/atoms.cpp b/src/x11/atoms.cpp index 5fd98560..3145783f 100644 --- a/src/x11/atoms.cpp +++ b/src/x11/atoms.cpp @@ -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 diff --git a/src/x11/ewmh.cpp b/src/x11/ewmh.cpp index 0d0f7972..1c4fb2f6 100644 --- a/src/x11/ewmh.cpp +++ b/src/x11/ewmh.cpp @@ -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 types) { auto conn = initialize().get(); xcb_ewmh_set_wm_window_type(conn, win, types.size(), types.data()); diff --git a/src/x11/icccm.cpp b/src/x11/icccm.cpp index 2bb12f47..a6e292ee 100644 --- a/src/x11/icccm.cpp +++ b/src/x11/icccm.cpp @@ -29,6 +29,15 @@ namespace icccm_util { void set_wm_protocols(xcb_connection_t* c, xcb_window_t w, vector 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 From 98610461de287550e3537c419dc3624bf7b472b6 Mon Sep 17 00:00:00 2001 From: Eivind Uggedal Date: Tue, 21 Feb 2017 08:15:13 +0100 Subject: [PATCH 2/4] fix(build): POSIX compliant command usage Shells like dash do not support printing paths of more than one argument with the builtin `command -vp`. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 70472178..eb005358 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # Polybar development tasks # BUILDDIR ?= build -GENERATOR ?= $(shell command -vp ninja make | xargs basename | sed "s/ninja/Ninja/;s/make/Unix Makefiles/") +GENERATOR ?= $(shell for c in ninja make; do command -vp $$c; done | xargs basename | sed "s/ninja/Ninja/;s/make/Unix Makefiles/") all: configure build link From 47bc4597421ca655c870e9ed2c66c3893fceb94c Mon Sep 17 00:00:00 2001 From: Adam Ransom Date: Tue, 21 Feb 2017 22:23:16 +0900 Subject: [PATCH 3/4] fix(bspwm): Update when focusing urgent desktops When focusing a desktop with the urgent flag, two events are received from `bspc` simultaneously, separated by a newline character. This was not handled correctly and the second event was discarded causing the urgent style to be removed, but the focused style would remain on the previously focused desktop. This fixes the problem by handling any number of events that arrive at the same time (separated by newlines). --- include/modules/bspwm.hpp | 2 ++ src/modules/bspwm.cpp | 14 +++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/modules/bspwm.hpp b/include/modules/bspwm.hpp index 5e9a07be..b1b02a7a 100644 --- a/include/modules/bspwm.hpp +++ b/include/modules/bspwm.hpp @@ -51,6 +51,8 @@ namespace modules { bool input(string&& cmd); private: + bool handle_status(string& data); + static constexpr auto DEFAULT_ICON = "ws-icon-default"; static constexpr auto DEFAULT_LABEL = "%icon% %name%"; static constexpr auto DEFAULT_MONITOR_LABEL = "%name%"; diff --git a/src/modules/bspwm.cpp b/src/modules/bspwm.cpp index cd036ad9..0ae8e725 100644 --- a/src/modules/bspwm.cpp +++ b/src/modules/bspwm.cpp @@ -157,12 +157,18 @@ namespace modules { } string data{m_subscriber->receive(BUFSIZ)}; + bool result = false; - size_t pos; - if ((pos = data.find('\n')) != string::npos) { - data.erase(pos); + for (auto&& status_line : string_util::split(data, '\n')) { + // Need to return true if ANY of the handle_status calls + // return true + result = this->handle_status(status_line) || result; } + return result; + } + + bool bspwm_module::handle_status(string& data) { if (data.empty()) { return false; } @@ -180,6 +186,8 @@ namespace modules { m_hash = hash; + size_t pos; + // Extract the string for the defined monitor if (m_pinworkspaces) { const auto needle_active = ":M" + m_bar.monitor->name + ":"; From 90fa9c823063f22628c868c168aabb9fe6d40cd6 Mon Sep 17 00:00:00 2001 From: Alex Feldman-Crough Date: Wed, 22 Feb 2017 21:36:33 -0800 Subject: [PATCH 4/4] Mention NixOS with the other operating systems --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index aa5c7227..2e8ebe27 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ If you are using **Arch Linux**, you can install the AUR package [polybar-git](h If you are using **Void Linux**, there's a [xbps template available](https://github.com/jaagr/void-packages/blob/polybar/srcpkgs/polybar/template) that you could use to build the project. A [pull-request has been submitted](https://github.com/voidlinux/void-packages/pull/5192) but it is still not merged into the official repositories so I wouldn't hold my breath. +If you are using **NixOS**, **Polybar** is available in the unstable channel and can be installed with the command `nix-env -iA nixos.polybar`. + ### Dependencies