Merge pull request #1667 from asas1asas200/zeng-feat-sway_scratchpad

This commit is contained in:
Alex 2022-10-18 09:00:31 +02:00 committed by GitHub
commit 7746328daa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 206 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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*

View File

@ -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)*

View File

@ -187,7 +187,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
@ -374,6 +375,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',

View File

@ -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": "<span style=\"italic\">{}</span>"
},
"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 ",

View File

@ -82,6 +82,7 @@ button:hover {
#tray,
#mode,
#idle_inhibitor,
#scratchpad,
#mpd {
padding: 0 10px;
color: #ffffff;
@ -256,3 +257,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;
}

View File

@ -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, config_[name]);
}
#endif
#ifdef HAVE_WLR
if (ref == "wlr/taskbar") {

View File

@ -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