Merge pull request #1667 from asas1asas200/zeng-feat-sway_scratchpad
This commit is contained in:
		
						commit
						7746328daa
					
				| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
#ifdef HAVE_SWAY
 | 
					#ifdef HAVE_SWAY
 | 
				
			||||||
#include "modules/sway/language.hpp"
 | 
					#include "modules/sway/language.hpp"
 | 
				
			||||||
#include "modules/sway/mode.hpp"
 | 
					#include "modules/sway/mode.hpp"
 | 
				
			||||||
 | 
					#include "modules/sway/scratchpad.hpp"
 | 
				
			||||||
#include "modules/sway/window.hpp"
 | 
					#include "modules/sway/window.hpp"
 | 
				
			||||||
#include "modules/sway/workspaces.hpp"
 | 
					#include "modules/sway/workspaces.hpp"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,35 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gtkmm/label.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <mutex>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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 ALabel {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  Scratchpad(const std::string&, 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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  std::string tooltip_format_;
 | 
				
			||||||
 | 
					  bool show_empty_;
 | 
				
			||||||
 | 
					  bool tooltip_enabled_;
 | 
				
			||||||
 | 
					  std::string tooltip_text_;
 | 
				
			||||||
 | 
					  int count_;
 | 
				
			||||||
 | 
					  std::mutex mutex_;
 | 
				
			||||||
 | 
					  Ipc ipc_;
 | 
				
			||||||
 | 
					  util::JsonParser parser_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					}  // namespace waybar::modules::sway
 | 
				
			||||||
| 
						 | 
					@ -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*
 | 
				
			||||||
| 
						 | 
					@ -273,6 +273,7 @@ A module group is defined by specifying a module named "group/some-group-name".
 | 
				
			||||||
- *waybar-river-window(5)*
 | 
					- *waybar-river-window(5)*
 | 
				
			||||||
- *waybar-states(5)*
 | 
					- *waybar-states(5)*
 | 
				
			||||||
- *waybar-sway-mode(5)*
 | 
					- *waybar-sway-mode(5)*
 | 
				
			||||||
 | 
					- *waybar-sway-scratchpad(5)*
 | 
				
			||||||
- *waybar-sway-window(5)*
 | 
					- *waybar-sway-window(5)*
 | 
				
			||||||
- *waybar-sway-workspaces(5)*
 | 
					- *waybar-sway-workspaces(5)*
 | 
				
			||||||
- *waybar-wlr-taskbar(5)*
 | 
					- *waybar-wlr-taskbar(5)*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -187,7 +187,8 @@ src_files += [
 | 
				
			||||||
    'src/modules/sway/mode.cpp',
 | 
					    'src/modules/sway/mode.cpp',
 | 
				
			||||||
    'src/modules/sway/language.cpp',
 | 
					    'src/modules/sway/language.cpp',
 | 
				
			||||||
    'src/modules/sway/window.cpp',
 | 
					    'src/modules/sway/window.cpp',
 | 
				
			||||||
    'src/modules/sway/workspaces.cpp'
 | 
					    'src/modules/sway/workspaces.cpp',
 | 
				
			||||||
 | 
					    'src/modules/sway/scratchpad.cpp'
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if true
 | 
					if true
 | 
				
			||||||
| 
						 | 
					@ -374,6 +375,7 @@ if scdoc.found()
 | 
				
			||||||
        'waybar-river-window.5.scd',
 | 
					        'waybar-river-window.5.scd',
 | 
				
			||||||
        'waybar-sway-language.5.scd',
 | 
					        'waybar-sway-language.5.scd',
 | 
				
			||||||
        'waybar-sway-mode.5.scd',
 | 
					        'waybar-sway-mode.5.scd',
 | 
				
			||||||
 | 
					        'waybar-sway-scratchpad.5.scd',
 | 
				
			||||||
        'waybar-sway-window.5.scd',
 | 
					        'waybar-sway-window.5.scd',
 | 
				
			||||||
        'waybar-sway-workspaces.5.scd',
 | 
					        'waybar-sway-workspaces.5.scd',
 | 
				
			||||||
        'waybar-temperature.5.scd',
 | 
					        'waybar-temperature.5.scd',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@
 | 
				
			||||||
    // "width": 1280, // Waybar width
 | 
					    // "width": 1280, // Waybar width
 | 
				
			||||||
    "spacing": 4, // Gaps between modules (4px)
 | 
					    "spacing": 4, // Gaps between modules (4px)
 | 
				
			||||||
    // Choose the order of the modules
 | 
					    // 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-center": ["sway/window"],
 | 
				
			||||||
    "modules-right": ["mpd", "idle_inhibitor", "pulseaudio", "network", "cpu", "memory", "temperature", "backlight", "keyboard-state", "sway/language", "battery", "battery#bat2", "clock", "tray"],
 | 
					    "modules-right": ["mpd", "idle_inhibitor", "pulseaudio", "network", "cpu", "memory", "temperature", "backlight", "keyboard-state", "sway/language", "battery", "battery#bat2", "clock", "tray"],
 | 
				
			||||||
    // Modules configuration
 | 
					    // Modules configuration
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,13 @@
 | 
				
			||||||
    "sway/mode": {
 | 
					    "sway/mode": {
 | 
				
			||||||
        "format": "<span style=\"italic\">{}</span>"
 | 
					        "format": "<span style=\"italic\">{}</span>"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "sway/scratchpad": {
 | 
				
			||||||
 | 
					        "format": "{icon} {count}",
 | 
				
			||||||
 | 
					        "show-empty": false,
 | 
				
			||||||
 | 
					        "format-icons": ["", ""],
 | 
				
			||||||
 | 
					        "tooltip": true,
 | 
				
			||||||
 | 
					        "tooltip-format": "{app}: {title}"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "mpd": {
 | 
					    "mpd": {
 | 
				
			||||||
        "format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {volume}% ",
 | 
					        "format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {volume}% ",
 | 
				
			||||||
        "format-disconnected": "Disconnected ",
 | 
					        "format-disconnected": "Disconnected ",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,6 +82,7 @@ button:hover {
 | 
				
			||||||
#tray,
 | 
					#tray,
 | 
				
			||||||
#mode,
 | 
					#mode,
 | 
				
			||||||
#idle_inhibitor,
 | 
					#idle_inhibitor,
 | 
				
			||||||
 | 
					#scratchpad,
 | 
				
			||||||
#mpd {
 | 
					#mpd {
 | 
				
			||||||
    padding: 0 10px;
 | 
					    padding: 0 10px;
 | 
				
			||||||
    color: #ffffff;
 | 
					    color: #ffffff;
 | 
				
			||||||
| 
						 | 
					@ -256,3 +257,11 @@ label:focus {
 | 
				
			||||||
#keyboard-state > label.locked {
 | 
					#keyboard-state > label.locked {
 | 
				
			||||||
    background: rgba(0, 0, 0, 0.2);
 | 
					    background: rgba(0, 0, 0, 0.2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#scratchpad {
 | 
				
			||||||
 | 
					    background: rgba(0, 0, 0, 0.2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#scratchpad.empty {
 | 
				
			||||||
 | 
						background-color: transparent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
 | 
				
			||||||
    if (ref == "sway/language") {
 | 
					    if (ref == "sway/language") {
 | 
				
			||||||
      return new waybar::modules::sway::Language(id, config_[name]);
 | 
					      return new waybar::modules::sway::Language(id, config_[name]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (ref == "sway/scratchpad") {
 | 
				
			||||||
 | 
					      return new waybar::modules::sway::Scratchpad(id, config_[name]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef HAVE_WLR
 | 
					#ifdef HAVE_WLR
 | 
				
			||||||
    if (ref == "wlr/taskbar") {
 | 
					    if (ref == "wlr/taskbar") {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,82 @@
 | 
				
			||||||
 | 
					#include "modules/sway/scratchpad.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <spdlog/spdlog.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace waybar::modules::sway {
 | 
				
			||||||
 | 
					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));
 | 
				
			||||||
 | 
					  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 {
 | 
				
			||||||
 | 
					  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 {
 | 
				
			||||||
 | 
					  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<std::mutex> 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());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto Scratchpad::onEvent(const struct Ipc::ipc_response& res) -> void { getTree(); }
 | 
				
			||||||
 | 
					}  // namespace waybar::modules::sway
 | 
				
			||||||
		Loading…
	
		Reference in New Issue