diff --git a/include/ALabel.hpp b/include/ALabel.hpp index 5e664d66..9e1a08d6 100644 --- a/include/ALabel.hpp +++ b/include/ALabel.hpp @@ -1,42 +1,30 @@ #pragma once #include -#include #include #include -#include "IModule.hpp" +#include "AModule.hpp" namespace waybar { -class ALabel : public IModule { +class ALabel : public AModule { public: ALabel(const Json::Value &, const std::string &, const std::string &, const std::string &format, uint16_t interval = 0); - virtual ~ALabel(); + virtual ~ALabel() = default; virtual auto update() -> void; virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0); - virtual operator Gtk::Widget &(); protected: - bool tooltipEnabled(); - - Gtk::EventBox event_box_; Gtk::Label label_; - const Json::Value & config_; std::string format_; std::string click_param; - std::mutex mutex_; const std::chrono::seconds interval_; bool alt_ = false; std::string default_format_; - virtual bool handleToggle(GdkEventButton *const &ev); - virtual bool handleScroll(GdkEventScroll *); + virtual bool handleToggle(GdkEventButton *const &e); virtual std::string getState(uint8_t value, bool lesser = false); - - private: - std::vector pid_; - gdouble distance_scrolled_; }; } // namespace waybar diff --git a/include/AModule.hpp b/include/AModule.hpp new file mode 100644 index 00000000..841b8d6e --- /dev/null +++ b/include/AModule.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include +#include "IModule.hpp" + +namespace waybar { + +class AModule : public IModule { + public: + AModule(const Json::Value &, const std::string &, const std::string &, + bool enable_click = false, bool enable_scroll = false); + virtual ~AModule(); + virtual auto update() -> void; + virtual operator Gtk::Widget &(); + + Glib::Dispatcher dp; + + protected: + enum SCROLL_DIR { NONE, UP, DOWN, LEFT, RIGHT }; + + SCROLL_DIR getScrollDir(GdkEventScroll *e); + bool tooltipEnabled(); + + const Json::Value &config_; + Gtk::EventBox event_box_; + std::string click_param_; + + virtual bool handleToggle(GdkEventButton *const &ev); + virtual bool handleScroll(GdkEventScroll *); + + private: + std::vector pid_; + gdouble distance_scrolled_y_; + gdouble distance_scrolled_x_; +}; + +} // namespace waybar diff --git a/include/IModule.hpp b/include/IModule.hpp index a9b2f17d..69d55d8c 100644 --- a/include/IModule.hpp +++ b/include/IModule.hpp @@ -1,7 +1,5 @@ #pragma once -#include -#include #include namespace waybar { @@ -11,7 +9,6 @@ class IModule { virtual ~IModule() = default; virtual auto update() -> void = 0; virtual operator Gtk::Widget &() = 0; - Glib::Dispatcher dp; // Hmmm Maybe I should create an abstract class ? }; } // namespace waybar diff --git a/include/bar.hpp b/include/bar.hpp index 97ca03e5..7ab6aebe 100644 --- a/include/bar.hpp +++ b/include/bar.hpp @@ -4,8 +4,9 @@ #include #include #include +#include #include -#include "IModule.hpp" +#include "AModule.hpp" #include "idle-inhibit-unstable-v1-client-protocol.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h" @@ -73,9 +74,9 @@ class Bar { Gtk::Box center_; Gtk::Box right_; Gtk::Box box_; - std::vector> modules_left_; - std::vector> modules_center_; - std::vector> modules_right_; + std::vector> modules_left_; + std::vector> modules_center_; + std::vector> modules_right_; }; } // namespace waybar diff --git a/include/factory.hpp b/include/factory.hpp index 65d7e3ce..4f5d63e3 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -37,7 +37,7 @@ namespace waybar { class Factory { public: Factory(const Bar& bar, const Json::Value& config); - IModule* makeModule(const std::string& name) const; + AModule* makeModule(const std::string& name) const; private: const Bar& bar_; diff --git a/include/modules/pulseaudio.hpp b/include/modules/pulseaudio.hpp index 9f92374a..d575f627 100644 --- a/include/modules/pulseaudio.hpp +++ b/include/modules/pulseaudio.hpp @@ -21,14 +21,13 @@ class Pulseaudio : public ALabel { static void sourceInfoCb(pa_context*, const pa_source_info* i, int, void* data); static void serverInfoCb(pa_context*, const pa_server_info*, void*); static void volumeModifyCb(pa_context*, int, void*); - bool handleVolume(GdkEventScroll* e); + bool handleScroll(GdkEventScroll* e); const std::string getPortIcon() const; pa_threaded_mainloop* mainloop_; pa_mainloop_api* mainloop_api_; pa_context* context_; - bool scrolling_; // SINK uint32_t sink_idx_{0}; uint16_t volume_; diff --git a/include/modules/sni/tray.hpp b/include/modules/sni/tray.hpp index dd092c97..e0aced1f 100644 --- a/include/modules/sni/tray.hpp +++ b/include/modules/sni/tray.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include "IModule.hpp" +#include "AModule.hpp" #include "bar.hpp" #include "modules/sni/host.hpp" #include "modules/sni/watcher.hpp" @@ -9,19 +9,17 @@ namespace waybar::modules::SNI { -class Tray : public IModule { +class Tray : public AModule { public: Tray(const std::string&, const Bar&, const Json::Value&); ~Tray() = default; auto update() -> void; - operator Gtk::Widget&(); private: void onAdd(std::unique_ptr& item); void onRemove(std::unique_ptr& item); static inline std::size_t nb_hosts_ = 0; - const Json::Value& config_; Gtk::Box box_; SNI::Watcher watcher_; SNI::Host host_; diff --git a/include/modules/sway/mode.hpp b/include/modules/sway/mode.hpp index 62509a28..f0cf74c1 100644 --- a/include/modules/sway/mode.hpp +++ b/include/modules/sway/mode.hpp @@ -22,6 +22,7 @@ class Mode : public ALabel, public sigc::trackable { std::string mode_; util::JsonParser parser_; + std::mutex mutex_; util::SleeperThread thread_; Ipc ipc_; diff --git a/include/modules/sway/window.hpp b/include/modules/sway/window.hpp index c7a3ab2d..5bb129d7 100644 --- a/include/modules/sway/window.hpp +++ b/include/modules/sway/window.hpp @@ -26,13 +26,13 @@ class Window : public ALabel, public sigc::trackable { void getTree(); const Bar& bar_; - std::mutex mutex_; std::string window_; int windowId_; std::string app_id_; std::string old_app_id_; std::size_t app_nb_; util::JsonParser parser_; + std::mutex mutex_; util::SleeperThread thread_; Ipc ipc_; diff --git a/include/modules/sway/workspaces.hpp b/include/modules/sway/workspaces.hpp index 33789df4..498acc95 100644 --- a/include/modules/sway/workspaces.hpp +++ b/include/modules/sway/workspaces.hpp @@ -3,7 +3,7 @@ #include #include #include -#include "IModule.hpp" +#include "AModule.hpp" #include "bar.hpp" #include "client.hpp" #include "modules/sway/ipc/client.hpp" @@ -12,12 +12,11 @@ namespace waybar::modules::sway { -class Workspaces : public IModule, public sigc::trackable { +class Workspaces : public AModule, public sigc::trackable { public: Workspaces(const std::string&, const waybar::Bar&, const Json::Value&); ~Workspaces() = default; auto update() -> void; - operator Gtk::Widget&(); private: void onCmd(const struct Ipc::ipc_response&); @@ -33,15 +32,12 @@ class Workspaces : public IModule, public sigc::trackable { bool handleScroll(GdkEventScroll*); const Bar& bar_; - const Json::Value& config_; std::vector workspaces_; std::vector workspaces_order_; - std::mutex mutex_; Gtk::Box box_; util::JsonParser parser_; - bool scrolling_; std::unordered_map buttons_; - gdouble distance_scrolled_; + std::mutex mutex_; util::SleeperThread thread_; Ipc ipc_; diff --git a/meson.build b/meson.build index 3e1c2248..38ab6aae 100644 --- a/meson.build +++ b/meson.build @@ -65,6 +65,7 @@ libmpdclient = dependency('libmpdclient', required: get_option('mpd')) src_files = files( 'src/factory.cpp', + 'src/AModule.cpp', 'src/ALabel.cpp', 'src/modules/memory.cpp', 'src/modules/battery.cpp', diff --git a/resources/style.css b/resources/style.css index fe03bcaf..ad657363 100644 --- a/resources/style.css +++ b/resources/style.css @@ -58,9 +58,20 @@ window#waybar.chromium { border-bottom: 3px solid #ffffff; } -#clock, #battery, #cpu, #memory, #temperature, #backlight, #network, #pulseaudio, #custom-media, #tray, #mode, #idle_inhibitor { +#clock, +#battery, +#cpu, +#memory, +#temperature, +#backlight, +#network, +#pulseaudio, +#custom-media, +#tray, +#mode, +#idle_inhibitor { padding: 0 10px; - margin: 0 5px; + margin: 0 4px; color: #ffffff; } diff --git a/src/ALabel.cpp b/src/ALabel.cpp index 792e7955..cc7ab829 100644 --- a/src/ALabel.cpp +++ b/src/ALabel.cpp @@ -2,9 +2,11 @@ #include #include -waybar::ALabel::ALabel(const Json::Value& config, const std::string& name, const std::string& id, - const std::string& format, uint16_t interval) - : config_(config), +namespace waybar { + +ALabel::ALabel(const Json::Value& config, const std::string& name, const std::string& id, + const std::string& format, uint16_t interval) + : AModule(config, name, id, config["format-alt"].isString()), format_(config_["format"].isString() ? config_["format"].asString() : format), interval_(config_["interval"] == "once" ? std::chrono::seconds(100000000) @@ -24,108 +26,13 @@ waybar::ALabel::ALabel(const Json::Value& config, const std::string& name, const if (config_["rotate"].isUInt()) { label_.set_angle(config["rotate"].asUInt()); } - - if (config_["format-alt"].isString()) { - event_box_.add_events(Gdk::BUTTON_PRESS_MASK); - event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &ALabel::handleToggle)); - } - - // configure events' user commands - if (config_["on-click"].isString() || config_["on-click-middle"].isString() || - config_["on-click-backward"].isString() || config_["on-click-forward"].isString() || - config_["on-click-right"].isString()) { - event_box_.add_events(Gdk::BUTTON_PRESS_MASK); - event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &ALabel::handleToggle)); - } - if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) { - event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); - event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &ALabel::handleScroll)); - } } -waybar::ALabel::~ALabel() { - for (const auto& pid : pid_) { - if (pid != -1) { - kill(-pid, 9); - } - } -} - -auto waybar::ALabel::update() -> void { +auto ALabel::update() -> void { // Nothing here } -bool waybar::ALabel::handleToggle(GdkEventButton* const& e) { - std::string format; - if (config_["on-click"].isString() && e->button == 1) { - format = config_["on-click"].asString(); - } else if (config_["on-click-middle"].isString() && e->button == 2) { - format = config_["on-click-middle"].asString(); - } else if (config_["on-click-right"].isString() && e->button == 3) { - format = config_["on-click-right"].asString(); - } else if (config_["on-click-forward"].isString() && e->button == 8) { - format = config_["on-click-backward"].asString(); - } else if (config_["on-click-backward"].isString() && e->button == 9) { - format = config_["on-click-forward"].asString(); - } - if (!format.empty()) { - pid_.push_back(util::command::forkExec(fmt::format(format, fmt::arg("arg", click_param)))); - } - if (config_["format-alt-click"].isUInt() && e->button == config_["format-alt-click"].asUInt()) { - alt_ = !alt_; - if (alt_ && config_["format-alt"].isString()) { - format_ = config_["format-alt"].asString(); - } else { - format_ = default_format_; - } - } - - dp.emit(); - return true; -} - -bool waybar::ALabel::handleScroll(GdkEventScroll* e) { - // Avoid concurrent scroll event - std::lock_guard lock(mutex_); - bool direction_up = false; - - if (e->direction == GDK_SCROLL_UP) { - direction_up = true; - } - if (e->direction == GDK_SCROLL_DOWN) { - direction_up = false; - } - if (e->direction == GDK_SCROLL_SMOOTH) { - gdouble delta_x, delta_y; - gdk_event_get_scroll_deltas(reinterpret_cast(e), &delta_x, &delta_y); - distance_scrolled_ += delta_y; - gdouble threshold = 0; - if (config_["smooth-scrolling-threshold"].isNumeric()) { - threshold = config_["smooth-scrolling-threshold"].asDouble(); - } - - if (distance_scrolled_ < -threshold) { - direction_up = true; - } else if (distance_scrolled_ > threshold) { - direction_up = false; - } - if(abs(distance_scrolled_) > threshold) { - distance_scrolled_ = 0; - } else { - // Don't execute the action if we haven't met the threshold! - return false; - } - } - if (direction_up && config_["on-scroll-up"].isString()) { - pid_.push_back(util::command::forkExec(config_["on-scroll-up"].asString())); - } else if (config_["on-scroll-down"].isString()) { - pid_.push_back(util::command::forkExec(config_["on-scroll-down"].asString())); - } - dp.emit(); - return true; -} - -std::string waybar::ALabel::getIcon(uint16_t percentage, const std::string& alt, uint16_t max) { +std::string ALabel::getIcon(uint16_t percentage, const std::string& alt, uint16_t max) { auto format_icons = config_["format-icons"]; if (format_icons.isObject()) { if (!alt.empty() && (format_icons[alt].isString() || format_icons[alt].isArray())) { @@ -145,7 +52,19 @@ std::string waybar::ALabel::getIcon(uint16_t percentage, const std::string& alt, return ""; } -std::string waybar::ALabel::getState(uint8_t value, bool lesser) { +bool waybar::ALabel::handleToggle(GdkEventButton* const& e) { + if (config_["format-alt-click"].isUInt() && e->button == config_["format-alt-click"].asUInt()) { + alt_ = !alt_; + if (alt_ && config_["format-alt"].isString()) { + format_ = config_["format-alt"].asString(); + } else { + format_ = default_format_; + } + } + return AModule::handleToggle(e); +} + +std::string ALabel::getState(uint8_t value, bool lesser) { if (!config_["states"].isObject()) { return ""; } @@ -174,8 +93,4 @@ std::string waybar::ALabel::getState(uint8_t value, bool lesser) { return valid_state; } -bool waybar::ALabel::tooltipEnabled() { - return config_["tooltip"].isBool() ? config_["tooltip"].asBool() : true; -} - -waybar::ALabel::operator Gtk::Widget&() { return event_box_; } +} // namespace waybar diff --git a/src/AModule.cpp b/src/AModule.cpp new file mode 100644 index 00000000..38e97850 --- /dev/null +++ b/src/AModule.cpp @@ -0,0 +1,119 @@ +#include "AModule.hpp" +#include +#include + +namespace waybar { + +AModule::AModule(const Json::Value& config, const std::string& name, const std::string& id, + bool enable_click, bool enable_scroll) + : config_(std::move(config)) { + // configure events' user commands + if (config_["on-click"].isString() || config_["on-click-middle"].isString() || + config_["on-click-backward"].isString() || config_["on-click-forward"].isString() || + config_["on-click-right"].isString() || enable_click) { + event_box_.add_events(Gdk::BUTTON_PRESS_MASK); + event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &AModule::handleToggle)); + } + if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString() || enable_scroll) { + event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); + event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &AModule::handleScroll)); + } +} + +AModule::~AModule() { + for (const auto& pid : pid_) { + if (pid != -1) { + kill(-pid, 9); + } + } +} + +auto AModule::update() -> void { + // Nothing here +} + +bool AModule::handleToggle(GdkEventButton* const& e) { + std::string format; + if (config_["on-click"].isString() && e->button == 1) { + format = config_["on-click"].asString(); + } else if (config_["on-click-middle"].isString() && e->button == 2) { + format = config_["on-click-middle"].asString(); + } else if (config_["on-click-right"].isString() && e->button == 3) { + format = config_["on-click-right"].asString(); + } else if (config_["on-click-forward"].isString() && e->button == 8) { + format = config_["on-click-backward"].asString(); + } else if (config_["on-click-backward"].isString() && e->button == 9) { + format = config_["on-click-forward"].asString(); + } + if (!format.empty()) { + pid_.push_back(util::command::forkExec(fmt::format(format, fmt::arg("arg", click_param_)))); + } + dp.emit(); + return true; +} + +AModule::SCROLL_DIR AModule::getScrollDir(GdkEventScroll* e) { + switch (e -> direction) { + case GDK_SCROLL_UP: return SCROLL_DIR::UP; + case GDK_SCROLL_DOWN: return SCROLL_DIR::DOWN; + case GDK_SCROLL_LEFT: return SCROLL_DIR::LEFT; + case GDK_SCROLL_RIGHT: return SCROLL_DIR::RIGHT; + case GDK_SCROLL_SMOOTH: { + SCROLL_DIR dir{SCROLL_DIR::NONE}; + + distance_scrolled_y_ += e->delta_y; + distance_scrolled_x_ += e->delta_x; + + gdouble threshold = 0; + if (config_["smooth-scrolling-threshold"].isNumeric()) { + threshold = config_["smooth-scrolling-threshold"].asDouble(); + } + + if (distance_scrolled_y_ < -threshold) { + dir = SCROLL_DIR::UP; + } else if (distance_scrolled_y_ > threshold) { + dir = SCROLL_DIR::DOWN; + } else if (distance_scrolled_x_ > threshold) { + dir = SCROLL_DIR::RIGHT; + } else if (distance_scrolled_x_ < -threshold) { + dir = SCROLL_DIR::LEFT; + } + + switch (dir) { + case SCROLL_DIR::UP: + case SCROLL_DIR::DOWN: + distance_scrolled_y_ = 0; + break; + case SCROLL_DIR::LEFT: + case SCROLL_DIR::RIGHT: + distance_scrolled_x_ = 0; + break; + case SCROLL_DIR::NONE: + break; + } + + return dir; + } + // Silence -Wreturn-type: + default: return SCROLL_DIR::NONE; + } +} + +bool AModule::handleScroll(GdkEventScroll* e) { + auto dir = getScrollDir(e); + if (dir == SCROLL_DIR::UP && config_["on-scroll-up"].isString()) { + pid_.push_back(util::command::forkExec(config_["on-scroll-up"].asString())); + } else if (dir == SCROLL_DIR::DOWN && config_["on-scroll-down"].isString()) { + pid_.push_back(util::command::forkExec(config_["on-scroll-down"].asString())); + } + dp.emit(); + return true; +} + +bool AModule::tooltipEnabled() { + return config_["tooltip"].isBool() ? config_["tooltip"].asBool() : true; +} + +AModule::operator Gtk::Widget&() { return event_box_; } + +} // namespace waybar diff --git a/src/bar.cpp b/src/bar.cpp index c2d6155e..4d02148b 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -287,14 +287,11 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos) { modules_right_.emplace_back(module); } module->dp.connect([module, &name] { - // Fix https://github.com/Alexays/Waybar/issues/320, proper way? - Glib::signal_idle().connect_once([module, &name] { - try { - module->update(); - } catch (const std::exception& e) { - spdlog::error("{}: {}", name.asString(), e.what()); - } - }); + try { + module->update(); + } catch (const std::exception& e) { + spdlog::error("{}: {}", name.asString(), e.what()); + } }); } catch (const std::exception& e) { spdlog::warn("module {}: {}", name.asString(), e.what()); diff --git a/src/factory.cpp b/src/factory.cpp index 9fd7671e..396b4bcc 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -2,7 +2,7 @@ waybar::Factory::Factory(const Bar& bar, const Json::Value& config) : bar_(bar), config_(config) {} -waybar::IModule* waybar::Factory::makeModule(const std::string& name) const { +waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { try { auto hash_pos = name.find('#'); auto ref = name.substr(0, hash_pos); diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index 4ed0d625..19fb0c57 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -5,7 +5,6 @@ waybar::modules::Pulseaudio::Pulseaudio(const std::string &id, const Json::Value mainloop_(nullptr), mainloop_api_(nullptr), context_(nullptr), - scrolling_(false), sink_idx_(0), volume_(0), muted_(false), @@ -32,13 +31,6 @@ waybar::modules::Pulseaudio::Pulseaudio(const std::string &id, const Json::Value throw std::runtime_error("pa_mainloop_run() failed."); } pa_threaded_mainloop_unlock(mainloop_); - - // define the pulse scroll events only when no user provided - // events are configured - if (!config["on-scroll-up"].isString() && !config["on-scroll-down"].isString()) { - event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); - event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &Pulseaudio::handleVolume)); - } } waybar::modules::Pulseaudio::~Pulseaudio() { @@ -74,50 +66,33 @@ void waybar::modules::Pulseaudio::contextStateCb(pa_context *c, void *data) { } } -bool waybar::modules::Pulseaudio::handleVolume(GdkEventScroll *e) { - // Avoid concurrent scroll event - if (scrolling_) { - return false; +bool waybar::modules::Pulseaudio::handleScroll(GdkEventScroll *e) { + // change the pulse volume only when no user provided + // events are configured + if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) { + return AModule::handleScroll(e); } - bool direction_up = false; - double volume_tick = (double)PA_VOLUME_NORM / 100; + auto dir = AModule::getScrollDir(e); + if (dir == SCROLL_DIR::NONE) { + return true; + } + double volume_tick = static_cast(PA_VOLUME_NORM) / 100; pa_volume_t change = volume_tick; pa_cvolume pa_volume = pa_volume_; - scrolling_ = true; - if (e->direction == GDK_SCROLL_UP) { - direction_up = true; - } - if (e->direction == GDK_SCROLL_DOWN) { - direction_up = false; - } - - if (e->direction == GDK_SCROLL_SMOOTH) { - gdouble delta_x, delta_y; - gdk_event_get_scroll_deltas(reinterpret_cast(e), &delta_x, &delta_y); - if (delta_y < 0) { - direction_up = true; - } else if (delta_y > 0) { - direction_up = false; - } - } - // isDouble returns true for integers as well, just in case if (config_["scroll-step"].isDouble()) { change = round(config_["scroll-step"].asDouble() * volume_tick); } - - if (direction_up) { + if (dir == SCROLL_DIR::UP) { if (volume_ + 1 < 100) { pa_cvolume_inc(&pa_volume, change); } - } else { + } else if (dir == SCROLL_DIR::DOWN) { if (volume_ - 1 >= 0) { pa_cvolume_dec(&pa_volume, change); } } - pa_context_set_sink_volume_by_index(context_, sink_idx_, &pa_volume, volumeModifyCb, this); - return true; } @@ -249,7 +224,4 @@ auto waybar::modules::Pulseaudio::update() -> void { if (tooltipEnabled()) { label_.set_tooltip_text(desc_); } - if (scrolling_) { - scrolling_ = false; - } } diff --git a/src/modules/sni/tray.cpp b/src/modules/sni/tray.cpp index 84d28803..50d03842 100644 --- a/src/modules/sni/tray.cpp +++ b/src/modules/sni/tray.cpp @@ -4,15 +4,16 @@ namespace waybar::modules::SNI { Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config) - : config_(config), + : AModule(config, "tray", id), box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0), watcher_(nb_hosts_), host_(nb_hosts_, config, std::bind(&Tray::onAdd, this, std::placeholders::_1), std::bind(&Tray::onRemove, this, std::placeholders::_1)) { - box_.set_name("tray"); spdlog::warn( "For a functionnal tray you must have libappindicator-* installed and export " "XDG_CURRENT_DESKTOP=Unity"); + box_.set_name("tray"); + event_box_.add(box_); if (!id.empty()) { box_.get_style_context()->add_class(id); } @@ -41,6 +42,4 @@ auto Tray::update() -> void { } } -Tray::operator Gtk::Widget&() { return box_; } - } // namespace waybar::modules::SNI diff --git a/src/modules/sway/ipc/client.cpp b/src/modules/sway/ipc/client.cpp index 28eb25fc..eae6c76e 100644 --- a/src/modules/sway/ipc/client.cpp +++ b/src/modules/sway/ipc/client.cpp @@ -142,4 +142,4 @@ void Ipc::handleEvent() { signal_event.emit(res); } -} // namespace waybar::modules::sway \ No newline at end of file +} // namespace waybar::modules::sway diff --git a/src/modules/sway/mode.cpp b/src/modules/sway/mode.cpp index f419a6cf..1f1cd889 100644 --- a/src/modules/sway/mode.cpp +++ b/src/modules/sway/mode.cpp @@ -13,6 +13,7 @@ Mode::Mode(const std::string& id, const Json::Value& config) : ALabel(config, "m void Mode::onEvent(const struct Ipc::ipc_response& res) { try { + std::lock_guard lock(mutex_); auto payload = parser_.parse(res.payload); if (payload["change"] != "default") { mode_ = Glib::Markup::escape_text(payload["change"].asString()); diff --git a/src/modules/sway/window.cpp b/src/modules/sway/window.cpp index 25262b00..1d6bfacc 100644 --- a/src/modules/sway/window.cpp +++ b/src/modules/sway/window.cpp @@ -22,7 +22,7 @@ void Window::onEvent(const struct Ipc::ipc_response& res) { getTree(); } void Window::onCmd(const struct Ipc::ipc_response& res) { try { std::lock_guard lock(mutex_); - auto payload = parser_.parse(res.payload); + auto payload = parser_.parse(res.payload); auto output = payload["ouput"].isString() ? payload["output"].asString() : ""; std::tie(app_nb_, windowId_, window_, app_id_) = getFocusedNode(payload["nodes"], output); dp.emit(); diff --git a/src/modules/sway/workspaces.cpp b/src/modules/sway/workspaces.cpp index afca4785..3a3f0abe 100644 --- a/src/modules/sway/workspaces.cpp +++ b/src/modules/sway/workspaces.cpp @@ -4,14 +4,14 @@ namespace waybar::modules::sway { Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config) - : bar_(bar), - config_(config), - box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0), - scrolling_(false) { + : AModule(config, "workspaces", id, false, !config["disable-scroll"].asBool()), + bar_(bar), + box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0) { box_.set_name("workspaces"); if (!id.empty()) { box_.get_style_context()->add_class(id); } + event_box_.add(box_); ipc_.subscribe(R"(["workspace"])"); ipc_.signal_event.connect(sigc::mem_fun(*this, &Workspaces::onEvent)); ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Workspaces::onCmd)); @@ -36,9 +36,9 @@ void Workspaces::onEvent(const struct Ipc::ipc_response &res) { void Workspaces::onCmd(const struct Ipc::ipc_response &res) { if (res.type == IPC_GET_WORKSPACES) { try { - auto payload = parser_.parse(res.payload); - if (payload.isArray()) { + { std::lock_guard lock(mutex_); + auto payload = parser_.parse(res.payload); workspaces_.clear(); std::copy_if(payload.begin(), payload.end(), @@ -91,16 +91,11 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) { return lhs["name"].asString() < rhs["name"].asString(); }); } - - dp.emit(); } + dp.emit(); } catch (const std::exception &e) { spdlog::error("Workspaces: {}", e.what()); } - } else { - if (scrolling_) { - scrolling_ = false; - } } } @@ -181,8 +176,8 @@ auto Workspaces::update() -> void { } Gtk::Button &Workspaces::addButton(const Json::Value &node) { - auto pair = buttons_.emplace(node["name"].asString(), node["name"].asString()); - auto &button = pair.first->second; + auto pair = buttons_.emplace(node["name"].asString(), node["name"].asString()); + auto &&button = pair.first->second; box_.pack_start(button, false, false, 0); button.set_relief(Gtk::RELIEF_NONE); button.signal_clicked().connect([this, node] { @@ -201,10 +196,6 @@ Gtk::Button &Workspaces::addButton(const Json::Value &node) { spdlog::error("Workspaces: {}", e.what()); } }); - if (!config_["disable-scroll"].asBool()) { - button.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); - button.signal_scroll_event().connect(sigc::mem_fun(*this, &Workspaces::handleScroll)); - } return button; } @@ -223,64 +214,27 @@ std::string Workspaces::getIcon(const std::string &name, const Json::Value &node } bool Workspaces::handleScroll(GdkEventScroll *e) { - // Avoid concurrent scroll event - if (scrolling_) { - return false; + auto dir = AModule::getScrollDir(e); + if (dir == SCROLL_DIR::NONE) { + return true; + } + std::lock_guard lock(mutex_); + auto it = std::find_if(workspaces_.begin(), workspaces_.end(), [](const auto &workspace) { + return workspace["focused"].asBool(); + }); + if (it == workspaces_.end()) { + return true; } std::string name; - scrolling_ = true; - { - std::lock_guard lock(mutex_); - auto it = std::find_if(workspaces_.begin(), workspaces_.end(), [](const auto &workspace) { - return workspace["focused"].asBool(); - }); - if (it == workspaces_.end()) { - scrolling_ = false; - return false; - } - switch (e->direction) { - case GDK_SCROLL_DOWN: - case GDK_SCROLL_RIGHT: { - name = getCycleWorkspace(it, false); - break; - } - case GDK_SCROLL_UP: - case GDK_SCROLL_LEFT: { - name = getCycleWorkspace(it, true); - break; - } - case GDK_SCROLL_SMOOTH: { - gdouble delta_x, delta_y; - gdk_event_get_scroll_deltas(reinterpret_cast(e), &delta_x, &delta_y); - - if (abs(delta_x) > abs(delta_y)) { - distance_scrolled_ += delta_x; - } else { - distance_scrolled_ += delta_y; - } - gdouble threshold = 0; - if (config_["smooth-scrolling-threshold"].isNumeric()) { - threshold = config_["smooth-scrolling-threshold"].asDouble(); - } - - if (distance_scrolled_ < -threshold) { - name = getCycleWorkspace(it, true); - } else if (distance_scrolled_ > threshold) { - name = getCycleWorkspace(it, false); - } - if(abs(distance_scrolled_) > threshold) { - distance_scrolled_ = 0; - } - break; - } - default: { - break; - } - } - if (name.empty() || name == (*it)["name"].asString()) { - scrolling_ = false; - return false; - } + if (dir == SCROLL_DIR::DOWN || dir == SCROLL_DIR::RIGHT) { + name = getCycleWorkspace(it, false); + } else if (dir == SCROLL_DIR::UP || dir == SCROLL_DIR::LEFT) { + name = getCycleWorkspace(it, true); + } else { + return true; + } + if (name == (*it)["name"].asString()) { + return true; } try { ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", name)); @@ -329,6 +283,4 @@ void Workspaces::onButtonReady(const Json::Value &node, Gtk::Button &button) { } } -Workspaces::operator Gtk::Widget &() { return box_; } - } // namespace waybar::modules::sway