From e3342467fcdb7fc6c38610dacbd2e272d565900b Mon Sep 17 00:00:00 2001 From: asas1asas200 Date: Mon, 29 Aug 2022 04:55:48 +0800 Subject: [PATCH 1/3] feat(sway/scratchpad): add basic counter --- include/factory.hpp | 1 + include/modules/sway/scratchpad.hpp | 34 +++++++++++++++++++ meson.build | 3 +- src/factory.cpp | 3 ++ src/modules/sway/scratchpad.cpp | 52 +++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 include/modules/sway/scratchpad.hpp create mode 100644 src/modules/sway/scratchpad.cpp diff --git a/include/factory.hpp b/include/factory.hpp index 47ef530b..0bd4a909 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -9,6 +9,7 @@ #ifdef HAVE_SWAY #include "modules/sway/language.hpp" #include "modules/sway/mode.hpp" +#include "modules/sway/scratchpad.hpp" #include "modules/sway/window.hpp" #include "modules/sway/workspaces.hpp" #endif diff --git a/include/modules/sway/scratchpad.hpp b/include/modules/sway/scratchpad.hpp new file mode 100644 index 00000000..9464a6ed --- /dev/null +++ b/include/modules/sway/scratchpad.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include +#include + +#include "ALabel.hpp" +#include "bar.hpp" +#include "client.hpp" +#include "modules/sway/ipc/client.hpp" +#include "util/json.hpp" + +namespace waybar::modules::sway { +// class Scratchpad : public AModule, public sigc::trackable { +class Scratchpad : public ALabel { + public: + Scratchpad(const std::string&, const waybar::Bar&, const Json::Value&); + ~Scratchpad() = default; + auto update() -> void; + + private: + auto getTree() -> void; + auto onCmd(const struct Ipc::ipc_response&) -> void; + auto onEvent(const struct Ipc::ipc_response&) -> void; + // bool handleScroll(GdkEventScroll*); + Gtk::Box box_; + const Bar& bar_; + std::mutex mutex_; + int count_; + Ipc ipc_; + util::JsonParser parser_; +}; +} // namespace waybar::modules::sway \ No newline at end of file diff --git a/meson.build b/meson.build index 3c320068..d1442ec5 100644 --- a/meson.build +++ b/meson.build @@ -184,7 +184,8 @@ src_files += [ 'src/modules/sway/mode.cpp', 'src/modules/sway/language.cpp', 'src/modules/sway/window.cpp', - 'src/modules/sway/workspaces.cpp' + 'src/modules/sway/workspaces.cpp', + 'src/modules/sway/scratchpad.cpp' ] if true diff --git a/src/factory.cpp b/src/factory.cpp index 6df69d5c..4a72d403 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -35,6 +35,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { if (ref == "sway/language") { return new waybar::modules::sway::Language(id, config_[name]); } + if (ref == "sway/scratchpad") { + return new waybar::modules::sway::Scratchpad(id, bar_, config_[name]); + } #endif #ifdef HAVE_WLR if (ref == "wlr/taskbar") { diff --git a/src/modules/sway/scratchpad.cpp b/src/modules/sway/scratchpad.cpp new file mode 100644 index 00000000..a7fd7baf --- /dev/null +++ b/src/modules/sway/scratchpad.cpp @@ -0,0 +1,52 @@ +#include "modules/sway/scratchpad.hpp" + +#include + +#include + +namespace waybar::modules::sway { +Scratchpad::Scratchpad(const std::string& id, const waybar::Bar& bar, const Json::Value& config) + : ALabel(config, "scratchpad", id, "{count}"), + box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0), + bar_(bar), + count_(0) { + ipc_.subscribe(R"(["window"])"); + ipc_.signal_event.connect(sigc::mem_fun(*this, &Scratchpad::onEvent)); + ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Scratchpad::onCmd)); + + getTree(); + + ipc_.setWorker([this] { + try { + ipc_.handleEvent(); + } catch (const std::exception& e) { + spdlog::error("Scratchpad: {}", e.what()); + } + }); +} +auto Scratchpad::update() -> void { + label_.set_markup(fmt::format(format_, fmt::arg("count", count_))); + AModule::update(); +} + +auto Scratchpad::getTree() -> void { + try { + ipc_.sendCmd(IPC_GET_TREE); + } catch (const std::exception& e) { + spdlog::error("Scratchpad: {}", e.what()); + } +} + +auto Scratchpad::onCmd(const struct Ipc::ipc_response& res) -> void { + try { + std::lock_guard lock(mutex_); + auto tree = parser_.parse(res.payload); + count_ = tree["nodes"][0]["nodes"][0]["floating_nodes"].size(); + dp.emit(); + } catch (const std::exception& e) { + spdlog::error("Scratchpad: {}", e.what()); + } +} + +auto Scratchpad::onEvent(const struct Ipc::ipc_response& res) -> void { getTree(); } +} // namespace waybar::modules::sway \ No newline at end of file From d2ff116c928c0e6927a88035decef3117a56d938 Mon Sep 17 00:00:00 2001 From: asas1asas200 Date: Wed, 31 Aug 2022 01:54:19 +0800 Subject: [PATCH 2/3] feat(sway/scratchpad): add some configs Add some configs for displaying. Remove draft codes. --- include/modules/sway/scratchpad.hpp | 13 ++++----- resources/config | 9 ++++++- resources/style.css | 9 +++++++ src/factory.cpp | 2 +- src/modules/sway/scratchpad.cpp | 42 ++++++++++++++++++++++++----- 5 files changed, 61 insertions(+), 14 deletions(-) diff --git a/include/modules/sway/scratchpad.hpp b/include/modules/sway/scratchpad.hpp index 9464a6ed..e68e7726 100644 --- a/include/modules/sway/scratchpad.hpp +++ b/include/modules/sway/scratchpad.hpp @@ -12,10 +12,9 @@ #include "util/json.hpp" namespace waybar::modules::sway { -// class Scratchpad : public AModule, public sigc::trackable { class Scratchpad : public ALabel { public: - Scratchpad(const std::string&, const waybar::Bar&, const Json::Value&); + Scratchpad(const std::string&, const Json::Value&); ~Scratchpad() = default; auto update() -> void; @@ -23,11 +22,13 @@ class Scratchpad : public ALabel { auto getTree() -> void; auto onCmd(const struct Ipc::ipc_response&) -> void; auto onEvent(const struct Ipc::ipc_response&) -> void; - // bool handleScroll(GdkEventScroll*); - Gtk::Box box_; - const Bar& bar_; - std::mutex mutex_; + + std::string tooltip_format_; + bool show_empty_; + bool tooltip_enabled_; + std::string tooltip_text_; int count_; + std::mutex mutex_; Ipc ipc_; util::JsonParser parser_; }; diff --git a/resources/config b/resources/config index 6a753acf..ad76e937 100644 --- a/resources/config +++ b/resources/config @@ -5,7 +5,7 @@ // "width": 1280, // Waybar width "spacing": 4, // Gaps between modules (4px) // Choose the order of the modules - "modules-left": ["sway/workspaces", "sway/mode", "custom/media"], + "modules-left": ["sway/workspaces", "sway/mode", "sway/scratchpad", "custom/media"], "modules-center": ["sway/window"], "modules-right": ["mpd", "idle_inhibitor", "pulseaudio", "network", "cpu", "memory", "temperature", "backlight", "keyboard-state", "sway/language", "battery", "battery#bat2", "clock", "tray"], // Modules configuration @@ -36,6 +36,13 @@ "sway/mode": { "format": "{}" }, + "sway/scratchpad": { + "format": "{icon} {count}", + "show-empty": false, + "format-icons": ["", ""], + "tooltip": true, + "tooltip-format": "{app}: {title}" + }, "mpd": { "format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {volume}% ", "format-disconnected": "Disconnected ", diff --git a/resources/style.css b/resources/style.css index 563ee0dd..d22cd252 100644 --- a/resources/style.css +++ b/resources/style.css @@ -78,6 +78,7 @@ window#waybar.chromium { #tray, #mode, #idle_inhibitor, +#scratchpad, #mpd { padding: 0 10px; color: #ffffff; @@ -252,3 +253,11 @@ label:focus { #keyboard-state > label.locked { background: rgba(0, 0, 0, 0.2); } + +#scratchpad { + background: rgba(0, 0, 0, 0.2); +} + +#scratchpad.empty { + background-color: transparent; +} diff --git a/src/factory.cpp b/src/factory.cpp index 4a72d403..f29b0f58 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -36,7 +36,7 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { return new waybar::modules::sway::Language(id, config_[name]); } if (ref == "sway/scratchpad") { - return new waybar::modules::sway::Scratchpad(id, bar_, config_[name]); + return new waybar::modules::sway::Scratchpad(id, config_[name]); } #endif #ifdef HAVE_WLR diff --git a/src/modules/sway/scratchpad.cpp b/src/modules/sway/scratchpad.cpp index a7fd7baf..59e30530 100644 --- a/src/modules/sway/scratchpad.cpp +++ b/src/modules/sway/scratchpad.cpp @@ -5,10 +5,14 @@ #include namespace waybar::modules::sway { -Scratchpad::Scratchpad(const std::string& id, const waybar::Bar& bar, const Json::Value& config) - : ALabel(config, "scratchpad", id, "{count}"), - box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0), - bar_(bar), +Scratchpad::Scratchpad(const std::string& id, const Json::Value& config) + : ALabel(config, "scratchpad", id, + config["format"].isString() ? config["format"].asString() : "{icon} {count}"), + tooltip_format_(config_["tooltip-format"].isString() ? config_["tooltip-format"].asString() + : "{app}: {title}"), + show_empty_(config_["show-empty"].isBool() ? config_["show-empty"].asBool() : false), + tooltip_enabled_(config_["tooltip"].isBool() ? config_["tooltip"].asBool() : true), + tooltip_text_(""), count_(0) { ipc_.subscribe(R"(["window"])"); ipc_.signal_event.connect(sigc::mem_fun(*this, &Scratchpad::onEvent)); @@ -25,8 +29,23 @@ Scratchpad::Scratchpad(const std::string& id, const waybar::Bar& bar, const Json }); } auto Scratchpad::update() -> void { - label_.set_markup(fmt::format(format_, fmt::arg("count", count_))); - AModule::update(); + if (count_ || show_empty_) { + event_box_.show(); + label_.set_markup( + fmt::format(format_, fmt::arg("icon", getIcon(count_, "", config_["format-icons"].size())), + fmt::arg("count", count_))); + if (tooltip_enabled_) { + label_.set_tooltip_markup(tooltip_text_); + } + } else { + event_box_.hide(); + } + if (count_) { + label_.get_style_context()->remove_class("empty"); + } else { + label_.get_style_context()->add_class("empty"); + } + ALabel::update(); } auto Scratchpad::getTree() -> void { @@ -42,6 +61,17 @@ auto Scratchpad::onCmd(const struct Ipc::ipc_response& res) -> void { std::lock_guard lock(mutex_); auto tree = parser_.parse(res.payload); count_ = tree["nodes"][0]["nodes"][0]["floating_nodes"].size(); + if (tooltip_enabled_) { + tooltip_text_.clear(); + for (const auto& window : tree["nodes"][0]["nodes"][0]["floating_nodes"]) { + tooltip_text_.append(fmt::format(tooltip_format_ + '\n', + fmt::arg("app", window["app_id"].asString()), + fmt::arg("title", window["name"].asString()))); + } + if (!tooltip_text_.empty()) { + tooltip_text_.pop_back(); + } + } dp.emit(); } catch (const std::exception& e) { spdlog::error("Scratchpad: {}", e.what()); From bc201fd0eb72000daf90b385a25f02e2d89231f1 Mon Sep 17 00:00:00 2001 From: asas1asas200 Date: Wed, 31 Aug 2022 02:27:30 +0800 Subject: [PATCH 3/3] doc(sway/scratchpad): add man page --- man/waybar-sway-scratchpad.5.scd | 64 ++++++++++++++++++++++++++++++++ man/waybar.5.scd.in | 1 + meson.build | 1 + 3 files changed, 66 insertions(+) create mode 100644 man/waybar-sway-scratchpad.5.scd diff --git a/man/waybar-sway-scratchpad.5.scd b/man/waybar-sway-scratchpad.5.scd new file mode 100644 index 00000000..11fc32c0 --- /dev/null +++ b/man/waybar-sway-scratchpad.5.scd @@ -0,0 +1,64 @@ +waybar-sway-scratchpad(5) + +# NAME + +waybar - sway scratchpad module + +# DESCRIPTION + +The *scratchpad* module displays the scratchpad status in Sway + +# CONFIGURATION + +Addressed by *sway/scratchpad* + +*format*: ++ + typeof: string ++ + default: {icon} {count} ++ + The format, how information should be displayed. + +*show-empty*: ++ + typeof: bool ++ + default: false ++ + Option to show module when scratchpad is empty. + +*format-icons*: ++ + typeof: array/object ++ + Based on the current scratchpad window counts, the corresponding icon gets selected. + +*tooltip*: ++ + typeof: bool ++ + default: true ++ + Option to disable tooltip on hover. + +*tooltip-format*: ++ + typeof: string ++ + default: {app}: {title} ++ + The format, how information in the tooltip should be displayed. + +# FORMAT REPLACEMENTS + +*{icon}*: Icon, as defined in *format-icons*. + +*{count}*: Number of windows in the scratchpad. + +*{app}*: Name of the application in the scratchpad. + +*{title}*: Title of the application in the scratchpad. + +# EXAMPLES + +``` +"sway/scratchpad": { + "format": "{icon} {count}", + "show-empty": false, + "format-icons": ["", ""], + "tooltip": true, + "tooltip-format": "{app}: {title}" +} +``` + +# STYLE + +- *#scratchpad* +- *#scratchpad.empty* diff --git a/man/waybar.5.scd.in b/man/waybar.5.scd.in index fafc2b36..54340f21 100644 --- a/man/waybar.5.scd.in +++ b/man/waybar.5.scd.in @@ -273,6 +273,7 @@ A module group is defined by specifying a module named "group/some-group-name". - *waybar-river-window(5)* - *waybar-states(5)* - *waybar-sway-mode(5)* +- *waybar-sway-scratchpad(5)* - *waybar-sway-window(5)* - *waybar-sway-workspaces(5)* - *waybar-wlr-taskbar(5)* diff --git a/meson.build b/meson.build index d1442ec5..9fdabb2c 100644 --- a/meson.build +++ b/meson.build @@ -365,6 +365,7 @@ if scdoc.found() 'waybar-river-window.5.scd', 'waybar-sway-language.5.scd', 'waybar-sway-mode.5.scd', + 'waybar-sway-scratchpad.5.scd', 'waybar-sway-window.5.scd', 'waybar-sway-workspaces.5.scd', 'waybar-temperature.5.scd',