From 02bd2e060dd65e592119c527001a6ab19735d3f5 Mon Sep 17 00:00:00 2001 From: Mihir Lad Date: Wed, 22 Jul 2020 18:35:26 -0400 Subject: [PATCH] dwm: Add label-floating This label is visible when the currently focused client is in floating mode and detached from the layout. It uses the focused_state_change_event as well as the focused_client_change_event to check if the focused client is floating and updates m_is_floating accordingly which will enable/disbale the floating label in the final output. update_floating_label is called when the floating state of the client is not known. The function queries dwm for the properties of the focused client and sets m_is_floating accordingly. This fixes issue #2. --- config.cmake | 2 +- include/modules/dwm.hpp | 31 +++++++++++++++++++++++++++- src/modules/dwm.cpp | 45 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/config.cmake b/config.cmake index 0846b4c5..d2e494e6 100644 --- a/config.cmake +++ b/config.cmake @@ -168,7 +168,7 @@ label-urgent-padding = 2 [module/dwm] type = internal/dwm -format = +format = enable-tags-click = false enable-layout-click = false diff --git a/include/modules/dwm.hpp b/include/modules/dwm.hpp index ad9f0622..ac44bb4b 100644 --- a/include/modules/dwm.hpp +++ b/include/modules/dwm.hpp @@ -56,7 +56,7 @@ namespace modules { auto input(string&& cmd) -> bool override; private: - static constexpr const char* DEFAULT_FORMAT_TAGS{" "}; + static constexpr const char* DEFAULT_FORMAT_TAGS{" "}; static constexpr const char* DEFAULT_STATE_LABEL{"%name%"}; /** @@ -75,6 +75,11 @@ namespace modules { */ static constexpr const char* TAG_LABEL_LAYOUT{""}; + /** + * The floating label is shown when the selected window is floating + */ + static constexpr const char* TAG_LABEL_FLOATING{""}; + /** * The title layout is replaced by the currently focused window title */ @@ -140,6 +145,14 @@ namespace modules { */ void on_focused_title_change(const dwmipc::FocusedTitleChangeEvent& ev); + /** + * Called by has_event when the state of the currently focused window + * changes. This updates the floating label. + * + * @param ev Event data + */ + void on_focused_state_change(const dwmipc::FocusedStateChangeEvent& ev); + /** * Get a list of monitors from dwm, store them in m_monitors, and update the * pointers to the active monitor and bar monitor. @@ -159,6 +172,12 @@ namespace modules { */ void update_title_label(); + /** + * Query dwm to determine if the currently focused client and update + * m_is_floating + */ + void update_floating_label(); + /** * Translate the tag's tag states to a state_t enum value * @@ -246,6 +265,11 @@ namespace modules { */ bool m_layout_reverse{false}; + /** + * If true, show floating label + */ + bool m_is_floating{false}; + /** * If the layout symbol is clicked on, it will set the layout represented by * this symbol. The default is monocle mode [M]. @@ -288,6 +312,11 @@ namespace modules { */ label_t m_layout_label; + /** + * Shown when currently focused window is floating + */ + label_t m_floating_label; + /** * Inserted between tags */ diff --git a/src/modules/dwm.cpp b/src/modules/dwm.cpp index c9e49c51..e567e2d0 100644 --- a/src/modules/dwm.cpp +++ b/src/modules/dwm.cpp @@ -28,7 +28,7 @@ namespace modules { m_ipc = factory_util::unique(socket_path); // Load configuration - m_formatter->add(DEFAULT_FORMAT, DEFAULT_FORMAT_TAGS, {TAG_LABEL_TAGS, TAG_LABEL_LAYOUT, TAG_LABEL_TITLE}); + m_formatter->add(DEFAULT_FORMAT, DEFAULT_FORMAT_TAGS, {TAG_LABEL_TAGS, TAG_LABEL_LAYOUT, TAG_LABEL_FLOATING, TAG_LABEL_TITLE}); // Populate m_state_labels map with labels and their states if (m_formatter->has(TAG_LABEL_TAGS)) { @@ -50,6 +50,10 @@ namespace modules { m_layout_label = load_optional_label(m_conf, name(), "label-layout", "%layout%"); } + if (m_formatter->has(TAG_LABEL_FLOATING)) { + m_floating_label = load_optional_label(m_conf, name(), "label-floating", ""); + } + if (m_formatter->has(TAG_LABEL_TITLE)) { m_title_label = load_optional_label(m_conf, name(), "label-title", "%title%"); } @@ -74,6 +78,10 @@ namespace modules { m_tags.emplace_back(t.tag_name, t.bit_mask, state, move(label)); } + if (m_floating_label) { + update_floating_label(); + } + if (m_layout_label) { auto layouts = m_ipc->get_layouts(); m_layouts = m_ipc->get_layouts(); @@ -106,6 +114,14 @@ namespace modules { m_ipc->subscribe(dwmipc::Event::FOCUSED_TITLE_CHANGE); } + if (m_floating_label) { + update_floating_label(); + m_ipc->on_focused_state_change = [this](const dwmipc::FocusedStateChangeEvent& ev) { + this->on_focused_state_change(ev); + }; + m_ipc->subscribe(dwmipc::Event::FOCUSED_STATE_CHANGE); + } + // This event is for keeping track of the currently focused monitor m_ipc->on_monitor_focus_change = [this](const dwmipc::MonitorFocusChangeEvent& ev) { this->on_monitor_focus_change(ev); @@ -154,6 +170,11 @@ namespace modules { auto dwm_module::build(builder* builder, const string& tag) const -> bool { if (tag == TAG_LABEL_TITLE) { builder->node(m_title_label); + } else if (tag == TAG_LABEL_FLOATING) { + if (!m_is_floating) { + return true; + } + builder->node(m_floating_label); } else if (tag == TAG_LABEL_LAYOUT) { if (m_layout_click) { // Toggle between secondary and default layout @@ -353,6 +374,21 @@ namespace modules { m_title_label->replace_token("%title%", new_title); } + void dwm_module::update_floating_label() { + if (m_focused_client_id != 0) { + try { + m_is_floating = m_ipc->get_client(m_focused_client_id)->states.is_floating; + } catch (const dwmipc::SocketClosedError& err) { + m_log.err("%s: Disconnected from socket: %s", name(), err.what()); + reconnect_dwm(); + } catch (const dwmipc::IPCError& err) { + throw module_error(err.what()); + } + } else { + m_is_floating = false; + } + } + auto dwm_module::reconnect_dwm() -> bool { try { if (!m_ipc->is_main_socket_connected()) { @@ -401,10 +437,17 @@ namespace modules { } } + void dwm_module::on_focused_state_change(const dwmipc::FocusedStateChangeEvent& ev) { + if (ev.monitor_num == m_bar_mon->num && ev.client_window_id == m_focused_client_id) { + m_is_floating = ev.new_state.is_floating; + } + } + void dwm_module::on_client_focus_change(const dwmipc::ClientFocusChangeEvent& ev) { if (ev.monitor_num == m_bar_mon->num) { m_focused_client_id = ev.new_win_id; update_title_label(); + update_floating_label(); } }