mirror of
https://github.com/rad4day/Waybar.git
synced 2023-12-21 10:22:59 +01:00
feat: args && class id
This commit is contained in:
parent
66ad2864c2
commit
b554094c7e
@ -15,7 +15,7 @@ class Client {
|
||||
Client(int argc, char *argv[]);
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
Glib::RefPtr<Gtk::Application> gtk_app;
|
||||
Gtk::Main gtk_main;
|
||||
std::string css_file;
|
||||
std::string config_file;
|
||||
Glib::RefPtr<Gdk::Display> gdk_display;
|
||||
@ -27,8 +27,8 @@ class Client {
|
||||
std::vector<std::unique_ptr<Bar>> bars;
|
||||
|
||||
private:
|
||||
void setupConfigs(const std::string& config, const std::string& style);
|
||||
void bindInterfaces();
|
||||
auto setupCss();
|
||||
const std::string getValidPath(std::vector<std::string> paths);
|
||||
|
||||
static void handleGlobal(void *data, struct wl_registry *registry,
|
||||
|
@ -23,7 +23,7 @@ namespace fs = std::filesystem;
|
||||
|
||||
class Battery : public ALabel {
|
||||
public:
|
||||
Battery(const Json::Value&);
|
||||
Battery(const std::string&, const Json::Value&);
|
||||
~Battery();
|
||||
auto update() -> void;
|
||||
private:
|
||||
|
@ -9,7 +9,7 @@ namespace waybar::modules {
|
||||
|
||||
class Clock : public ALabel {
|
||||
public:
|
||||
Clock(const Json::Value&);
|
||||
Clock(const std::string&, const Json::Value&);
|
||||
auto update() -> void;
|
||||
private:
|
||||
waybar::util::SleeperThread thread_;
|
||||
|
@ -13,7 +13,7 @@ namespace waybar::modules {
|
||||
|
||||
class Cpu : public ALabel {
|
||||
public:
|
||||
Cpu(const Json::Value&);
|
||||
Cpu(const std::string&, const Json::Value&);
|
||||
auto update() -> void;
|
||||
private:
|
||||
static inline const std::string data_dir_ = "/proc/stat";
|
||||
|
@ -11,7 +11,7 @@ namespace waybar::modules {
|
||||
|
||||
class Custom : public ALabel {
|
||||
public:
|
||||
Custom(const std::string, const Json::Value&);
|
||||
Custom(const std::string&, const Json::Value&);
|
||||
~Custom();
|
||||
auto update() -> void;
|
||||
private:
|
||||
|
@ -9,7 +9,7 @@ namespace waybar::modules {
|
||||
|
||||
class Memory : public ALabel {
|
||||
public:
|
||||
Memory(const Json::Value&);
|
||||
Memory(const std::string&, const Json::Value&);
|
||||
auto update() -> void;
|
||||
private:
|
||||
static inline const std::string data_dir_ = "/proc/meminfo";
|
||||
|
@ -15,7 +15,7 @@ namespace waybar::modules {
|
||||
|
||||
class Network : public ALabel {
|
||||
public:
|
||||
Network(const Json::Value&);
|
||||
Network(const std::string&, const Json::Value&);
|
||||
~Network();
|
||||
auto update() -> void;
|
||||
private:
|
||||
|
@ -10,7 +10,7 @@ namespace waybar::modules {
|
||||
|
||||
class Pulseaudio : public ALabel {
|
||||
public:
|
||||
Pulseaudio(const Json::Value&);
|
||||
Pulseaudio(const std::string&, const Json::Value&);
|
||||
~Pulseaudio();
|
||||
auto update() -> void;
|
||||
private:
|
||||
|
@ -12,7 +12,7 @@ namespace waybar::modules::SNI {
|
||||
|
||||
class Tray : public IModule {
|
||||
public:
|
||||
Tray(const Json::Value&);
|
||||
Tray(const std::string&, const Json::Value&);
|
||||
auto update() -> void;
|
||||
operator Gtk::Widget &();
|
||||
private:
|
||||
|
@ -12,7 +12,7 @@ namespace waybar::modules::sway {
|
||||
|
||||
class Mode : public ALabel {
|
||||
public:
|
||||
Mode(const waybar::Bar&, const Json::Value&);
|
||||
Mode(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||
auto update() -> void;
|
||||
private:
|
||||
void worker();
|
||||
|
@ -13,7 +13,7 @@ namespace waybar::modules::sway {
|
||||
|
||||
class Window : public ALabel {
|
||||
public:
|
||||
Window(const waybar::Bar&, const Json::Value&);
|
||||
Window(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||
auto update() -> void;
|
||||
private:
|
||||
void worker();
|
||||
|
@ -12,7 +12,7 @@ namespace waybar::modules::sway {
|
||||
|
||||
class Workspaces : public IModule {
|
||||
public:
|
||||
Workspaces(const waybar::Bar&, const Json::Value&);
|
||||
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||
auto update() -> void;
|
||||
operator Gtk::Widget &();
|
||||
private:
|
||||
|
@ -63,14 +63,14 @@ struct SleeperThread {
|
||||
{
|
||||
do_run_ = false;
|
||||
condvar_.notify_all();
|
||||
if (thread_.joinable()) {
|
||||
thread_.detach();
|
||||
}
|
||||
}
|
||||
|
||||
~SleeperThread()
|
||||
{
|
||||
stop();
|
||||
if (thread_.joinable()) {
|
||||
thread_.detach();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
1264
include/util/clara.hpp
Normal file
1264
include/util/clara.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,7 @@ project(
|
||||
],
|
||||
)
|
||||
|
||||
cpp_args = []
|
||||
cpp_args = ['-DVERSION="@0@"'.format(meson.project_version())]
|
||||
cpp_link_args = []
|
||||
|
||||
if false # libc++
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include "client.hpp"
|
||||
#include "util/clara.hpp"
|
||||
#include <iostream>
|
||||
|
||||
waybar::Client::Client(int argc, char* argv[])
|
||||
: gtk_app(Gtk::Application::create(argc, argv, "fr.arouillard.waybar")),
|
||||
: gtk_main(argc, argv),
|
||||
gdk_display(Gdk::Display::get_default())
|
||||
{
|
||||
if (!gdk_display) {
|
||||
@ -12,25 +13,6 @@ waybar::Client::Client(int argc, char* argv[])
|
||||
throw std::runtime_error("Bar need to run under Wayland");
|
||||
}
|
||||
wl_display = gdk_wayland_display_get_wl_display(gdk_display->gobj());
|
||||
|
||||
config_file = getValidPath({
|
||||
"$XDG_CONFIG_HOME/waybar/config",
|
||||
"$HOME/.config/waybar/config",
|
||||
"$HOME/waybar/config",
|
||||
"/etc/xdg/waybar/config",
|
||||
"./resources/config",
|
||||
});
|
||||
css_file = getValidPath({
|
||||
"$XDG_CONFIG_HOME/waybar/style.css",
|
||||
"$HOME/.config/waybar/style.css",
|
||||
"$HOME/waybar/style.css",
|
||||
"/etc/xdg/waybar/style.css",
|
||||
"./resources/style.css",
|
||||
});
|
||||
if (css_file.empty() || config_file.empty()) {
|
||||
throw std::runtime_error("Missing required resources files");
|
||||
}
|
||||
std::cout << "Resources files: " + config_file + ", " + css_file << std::endl;
|
||||
}
|
||||
|
||||
const std::string waybar::Client::getValidPath(std::vector<std::string> paths)
|
||||
@ -88,6 +70,28 @@ void waybar::Client::handleGlobalRemove(void* data,
|
||||
}
|
||||
}
|
||||
|
||||
void waybar::Client::setupConfigs(const std::string& config, const std::string& style)
|
||||
{
|
||||
config_file = config.empty() ? getValidPath({
|
||||
"$XDG_CONFIG_HOME/waybar/config",
|
||||
"$HOME/.config/waybar/config",
|
||||
"$HOME/waybar/config",
|
||||
"/etc/xdg/waybar/config",
|
||||
"./resources/config",
|
||||
}) : config;
|
||||
css_file = style.empty() ? getValidPath({
|
||||
"$XDG_CONFIG_HOME/waybar/style.css",
|
||||
"$HOME/.config/waybar/style.css",
|
||||
"$HOME/waybar/style.css",
|
||||
"/etc/xdg/waybar/style.css",
|
||||
"./resources/style.css",
|
||||
}) : style;
|
||||
if (css_file.empty() || config_file.empty()) {
|
||||
throw std::runtime_error("Missing required resources files");
|
||||
}
|
||||
std::cout << "Resources files: " + config_file + ", " + css_file << std::endl;
|
||||
}
|
||||
|
||||
void waybar::Client::bindInterfaces()
|
||||
{
|
||||
registry = wl_display_get_registry(wl_display);
|
||||
@ -103,11 +107,32 @@ void waybar::Client::bindInterfaces()
|
||||
wl_display_roundtrip(wl_display);
|
||||
}
|
||||
|
||||
int waybar::Client::main(int /*argc*/, char* /*argv*/[])
|
||||
int waybar::Client::main(int argc, char* argv[])
|
||||
{
|
||||
bool show_help = false;
|
||||
bool show_version = false;
|
||||
std::string config;
|
||||
std::string style;
|
||||
auto cli = clara::detail::Help(show_help)
|
||||
| clara::detail::Opt(show_version)["-v"]["--version"]("Show version")
|
||||
| clara::detail::Opt(config, "config")["-c"]["--config"]("Config path")
|
||||
| clara::detail::Opt(style, "style")["-s"]["--style"]("Style path");
|
||||
auto res = cli.parse(clara::detail::Args(argc, argv));
|
||||
if (!res) {
|
||||
std::cerr << "Error in command line: " << res.errorMessage() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if (show_help) {
|
||||
std::cout << cli << std::endl;
|
||||
return 0;
|
||||
}
|
||||
if (show_version) {
|
||||
std::cout << "Waybar v" << VERSION << std::endl;
|
||||
return 0;
|
||||
}
|
||||
setupConfigs(config, style);
|
||||
bindInterfaces();
|
||||
gtk_app->hold();
|
||||
gtk_app->run();
|
||||
gtk_main.run();
|
||||
bars.clear();
|
||||
zxdg_output_manager_v1_destroy(xdg_output_manager);
|
||||
zwlr_layer_shell_v1_destroy(layer_shell);
|
||||
|
@ -7,43 +7,45 @@ waybar::Factory::Factory(const Bar& bar, const Json::Value& config)
|
||||
waybar::IModule* waybar::Factory::makeModule(const std::string &name) const
|
||||
{
|
||||
try {
|
||||
auto ref = name.substr(0, name.find("#"));
|
||||
auto hash_pos = name.find("#");
|
||||
auto ref = name.substr(0, hash_pos);
|
||||
auto id = hash_pos != std::string::npos ? name.substr(hash_pos + 1) : "";
|
||||
if (ref == "battery") {
|
||||
return new waybar::modules::Battery(config_[name]);
|
||||
return new waybar::modules::Battery(id, config_[name]);
|
||||
}
|
||||
#ifdef HAVE_SWAY
|
||||
if (ref == "sway/mode") {
|
||||
return new waybar::modules::sway::Mode(bar_, config_[name]);
|
||||
return new waybar::modules::sway::Mode(id, bar_, config_[name]);
|
||||
}
|
||||
if (ref == "sway/workspaces") {
|
||||
return new waybar::modules::sway::Workspaces(bar_, config_[name]);
|
||||
return new waybar::modules::sway::Workspaces(id, bar_, config_[name]);
|
||||
}
|
||||
if (ref == "sway/window") {
|
||||
return new waybar::modules::sway::Window(bar_, config_[name]);
|
||||
return new waybar::modules::sway::Window(id, bar_, config_[name]);
|
||||
}
|
||||
#endif
|
||||
if (ref == "memory") {
|
||||
return new waybar::modules::Memory(config_[name]);
|
||||
return new waybar::modules::Memory(id, config_[name]);
|
||||
}
|
||||
if (ref == "cpu") {
|
||||
return new waybar::modules::Cpu(config_[name]);
|
||||
return new waybar::modules::Cpu(id, config_[name]);
|
||||
}
|
||||
if (ref == "clock") {
|
||||
return new waybar::modules::Clock(config_[name]);
|
||||
return new waybar::modules::Clock(id, config_[name]);
|
||||
}
|
||||
#ifdef HAVE_DBUSMENU
|
||||
if (ref == "tray") {
|
||||
return new waybar::modules::SNI::Tray(config_[name]);
|
||||
return new waybar::modules::SNI::Tray(id, config_[name]);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_LIBNL
|
||||
if (ref == "network") {
|
||||
return new waybar::modules::Network(config_[name]);
|
||||
return new waybar::modules::Network(id, config_[name]);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_LIBPULSE
|
||||
if (ref == "pulseaudio") {
|
||||
return new waybar::modules::Pulseaudio(config_[name]);
|
||||
return new waybar::modules::Pulseaudio(id, config_[name]);
|
||||
}
|
||||
#endif
|
||||
if (ref.compare(0, 7, "custom/") == 0 && ref.size() > 7) {
|
||||
|
@ -1,8 +1,12 @@
|
||||
#include "modules/battery.hpp"
|
||||
|
||||
waybar::modules::Battery::Battery(const Json::Value& config)
|
||||
waybar::modules::Battery::Battery(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "{capacity}%", 60)
|
||||
{
|
||||
label_.set_name("battery");
|
||||
if (!id.empty()) {
|
||||
label_.get_style_context()->add_class(id);
|
||||
}
|
||||
try {
|
||||
if (config_["bat"].isString()) {
|
||||
auto dir = data_dir_ / config_["bat"].asString();
|
||||
@ -131,10 +135,8 @@ auto waybar::modules::Battery::update() -> void
|
||||
}
|
||||
if (format.empty()) {
|
||||
event_box_.hide();
|
||||
label_.set_name("");
|
||||
} else {
|
||||
event_box_.show();
|
||||
label_.set_name("battery");
|
||||
label_.set_markup(fmt::format(format, fmt::arg("capacity", capacity),
|
||||
fmt::arg("icon", getIcon(capacity))));
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
#include "modules/clock.hpp"
|
||||
|
||||
waybar::modules::Clock::Clock(const Json::Value& config)
|
||||
waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "{:%H:%M}", 60)
|
||||
{
|
||||
label_.set_name("clock");
|
||||
if (!id.empty()) {
|
||||
label_.get_style_context()->add_class(id);
|
||||
}
|
||||
thread_ = [this] {
|
||||
auto now = waybar::chrono::clock::now();
|
||||
dp.emit();
|
||||
|
@ -1,9 +1,12 @@
|
||||
#include "modules/cpu.hpp"
|
||||
|
||||
waybar::modules::Cpu::Cpu(const Json::Value& config)
|
||||
waybar::modules::Cpu::Cpu(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "{usage}%", 10)
|
||||
{
|
||||
label_.set_name("cpu");
|
||||
if (!id.empty()) {
|
||||
label_.get_style_context()->add_class(id);
|
||||
}
|
||||
thread_ = [this] {
|
||||
dp.emit();
|
||||
thread_.sleep_for(interval_);
|
||||
|
@ -1,18 +1,18 @@
|
||||
#include "modules/custom.hpp"
|
||||
|
||||
waybar::modules::Custom::Custom(const std::string name,
|
||||
waybar::modules::Custom::Custom(const std::string& name,
|
||||
const Json::Value& config)
|
||||
: ALabel(config, "{}"), name_(name), fp_(nullptr)
|
||||
{
|
||||
label_.set_name("custom-" + name_);
|
||||
if (config_["exec"].isString()) {
|
||||
if (interval_.count() > 0) {
|
||||
delayWorker();
|
||||
} else {
|
||||
continuousWorker();
|
||||
}
|
||||
} else {
|
||||
update();
|
||||
}
|
||||
dp.emit();
|
||||
}
|
||||
|
||||
waybar::modules::Custom::~Custom()
|
||||
@ -31,8 +31,7 @@ void waybar::modules::Custom::delayWorker()
|
||||
auto res = waybar::util::command::exec(config_["exec-if"].asString());
|
||||
if (res.exit_code != 0) {
|
||||
can_update = false;
|
||||
label_.hide();
|
||||
label_.set_name("");
|
||||
event_box_.hide();
|
||||
}
|
||||
}
|
||||
if (can_update) {
|
||||
@ -80,11 +79,8 @@ auto waybar::modules::Custom::update() -> void
|
||||
{
|
||||
// Hide label if output is empty
|
||||
if (config_["exec"].isString() && (output_.out.empty() || output_.exit_code != 0)) {
|
||||
label_.hide();
|
||||
label_.set_name("");
|
||||
event_box_.hide();
|
||||
} else {
|
||||
label_.set_name("custom-" + name_);
|
||||
|
||||
if (config_["return-type"].asString() == "json") {
|
||||
parseOutputJson();
|
||||
} else {
|
||||
@ -109,7 +105,7 @@ auto waybar::modules::Custom::update() -> void
|
||||
prevclass_ = "";
|
||||
}
|
||||
|
||||
label_.show();
|
||||
event_box_.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
#include "modules/memory.hpp"
|
||||
|
||||
waybar::modules::Memory::Memory(const Json::Value& config)
|
||||
waybar::modules::Memory::Memory(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "{}%", 30)
|
||||
{
|
||||
label_.set_name("memory");
|
||||
if (!id.empty()) {
|
||||
label_.get_style_context()->add_class(id);
|
||||
}
|
||||
thread_ = [this] {
|
||||
dp.emit();
|
||||
thread_.sleep_for(interval_);
|
||||
@ -17,11 +21,9 @@ auto waybar::modules::Memory::update() -> void
|
||||
label_.set_markup(fmt::format(format_, used_ram_percentage));
|
||||
auto used_ram_gigabytes = (memtotal_ - memfree_) / std::pow(1024, 2);
|
||||
label_.set_tooltip_text(fmt::format("{:.{}f}Gb used", used_ram_gigabytes, 1));
|
||||
label_.set_name("memory");
|
||||
label_.show();
|
||||
event_box_.show();
|
||||
} else {
|
||||
label_.set_name("");
|
||||
label_.hide();
|
||||
event_box_.hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
#include "modules/network.hpp"
|
||||
|
||||
waybar::modules::Network::Network(const Json::Value& config)
|
||||
waybar::modules::Network::Network(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "{ifname}", 60), family_(AF_INET),
|
||||
cidr_(-1), signal_strength_dbm_(0), signal_strength_(0)
|
||||
{
|
||||
label_.set_name("network");
|
||||
if (!id.empty()) {
|
||||
label_.get_style_context()->add_class(id);
|
||||
}
|
||||
sock_fd_ = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (sock_fd_ < 0) {
|
||||
throw std::runtime_error("Can't open network socket");
|
||||
@ -29,10 +33,9 @@ waybar::modules::Network::Network(const Json::Value& config)
|
||||
}
|
||||
}
|
||||
initNL80211();
|
||||
label_.set_name("network");
|
||||
// Trigger first values
|
||||
getInfo();
|
||||
update();
|
||||
dp.emit();
|
||||
worker();
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "modules/pulseaudio.hpp"
|
||||
|
||||
waybar::modules::Pulseaudio::Pulseaudio(const Json::Value &config)
|
||||
waybar::modules::Pulseaudio::Pulseaudio(const std::string& id, const Json::Value &config)
|
||||
: ALabel(config, "{volume}%"),
|
||||
mainloop_(nullptr),
|
||||
mainloop_api_(nullptr),
|
||||
@ -10,6 +10,9 @@ waybar::modules::Pulseaudio::Pulseaudio(const Json::Value &config)
|
||||
muted_(false),
|
||||
scrolling_(false) {
|
||||
label_.set_name("pulseaudio");
|
||||
if (!id.empty()) {
|
||||
label_.get_style_context()->add_class(id);
|
||||
}
|
||||
mainloop_ = pa_threaded_mainloop_new();
|
||||
if (mainloop_ == nullptr) {
|
||||
throw std::runtime_error("pa_mainloop_new() failed.");
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
waybar::modules::SNI::Tray::Tray(const Json::Value &config)
|
||||
waybar::modules::SNI::Tray::Tray(const std::string& id, const Json::Value &config)
|
||||
: config_(config), watcher_(), host_(nb_hosts_, config,
|
||||
std::bind(&Tray::onAdd, this, std::placeholders::_1),
|
||||
std::bind(&Tray::onRemove, this, std::placeholders::_1))
|
||||
|
@ -1,12 +1,17 @@
|
||||
#include "modules/sway/mode.hpp"
|
||||
|
||||
waybar::modules::sway::Mode::Mode(const Bar& bar, const Json::Value& config)
|
||||
waybar::modules::sway::Mode::Mode(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||
: ALabel(config, "{}"), bar_(bar)
|
||||
{
|
||||
label_.set_name("mode");
|
||||
if (!id.empty()) {
|
||||
label_.get_style_context()->add_class(id);
|
||||
}
|
||||
ipc_.connect();
|
||||
ipc_.subscribe("[ \"mode\" ]");
|
||||
// Launch worker
|
||||
worker();
|
||||
dp.emit();
|
||||
}
|
||||
|
||||
void waybar::modules::sway::Mode::worker()
|
||||
@ -32,12 +37,10 @@ void waybar::modules::sway::Mode::worker()
|
||||
auto waybar::modules::sway::Mode::update() -> void
|
||||
{
|
||||
if (mode_.empty()) {
|
||||
label_.set_name("");
|
||||
label_.hide();
|
||||
event_box_.hide();
|
||||
} else {
|
||||
label_.set_name("mode");
|
||||
label_.set_markup(fmt::format(format_, mode_));
|
||||
label_.set_tooltip_text(mode_);
|
||||
label_.show();
|
||||
event_box_.show();
|
||||
}
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
#include "modules/sway/window.hpp"
|
||||
|
||||
waybar::modules::sway::Window::Window(const Bar &bar, const Json::Value& config)
|
||||
waybar::modules::sway::Window::Window(const std::string& id, const Bar &bar, const Json::Value& config)
|
||||
: ALabel(config, "{}"), bar_(bar), windowId_(-1)
|
||||
{
|
||||
label_.set_name("window");
|
||||
if (!id.empty()) {
|
||||
label_.get_style_context()->add_class(id);
|
||||
}
|
||||
if (label_.get_max_width_chars() == -1) {
|
||||
label_.set_hexpand(true);
|
||||
label_.set_ellipsize(Pango::EllipsizeMode::ELLIPSIZE_END);
|
||||
|
@ -1,10 +1,13 @@
|
||||
#include "modules/sway/workspaces.hpp"
|
||||
|
||||
waybar::modules::sway::Workspaces::Workspaces(const Bar& bar,
|
||||
waybar::modules::sway::Workspaces::Workspaces(const std::string& id, const Bar& bar,
|
||||
const Json::Value& config)
|
||||
: bar_(bar), config_(config), scrolling_(false)
|
||||
{
|
||||
box_.set_name("workspaces");
|
||||
if (!id.empty()) {
|
||||
box_.get_style_context()->add_class(id);
|
||||
}
|
||||
ipc_.connect();
|
||||
ipc_.subscribe("[ \"workspace\" ]");
|
||||
// Launch worker
|
||||
|
Loading…
Reference in New Issue
Block a user