diff --git a/include/bar.hpp b/include/bar.hpp index 6f3dfcf97..030e1e35b 100644 --- a/include/bar.hpp +++ b/include/bar.hpp @@ -59,7 +59,13 @@ class Bar { ~Bar() = default; void setVisible(bool visible); + void setHiddenClass(bool value) const; + void setBottomLayerClass(bool value) const; + void moveToTopLayer() const; + void moveToBottomLayer() const; + void moveToConfiguredLayer() const; void toggle(); + void setExclusive(bool value); void handleSignal(int); struct waybar_output *output; diff --git a/include/factory.hpp b/include/factory.hpp index 4b9f32aa9..79a08f3f4 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -10,6 +10,7 @@ #include "modules/sway/mode.hpp" #include "modules/sway/window.hpp" #include "modules/sway/workspaces.hpp" +#include "modules/sway/hide.hpp" #include "modules/sway/language.hpp" #endif #ifdef HAVE_WLR diff --git a/include/modules/sway/hide.hpp b/include/modules/sway/hide.hpp new file mode 100644 index 000000000..90a054d88 --- /dev/null +++ b/include/modules/sway/hide.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include <fmt/format.h> +#include <tuple> +#include <mutex> +#include "ALabel.hpp" +#include "bar.hpp" +#include "client.hpp" +#include "modules/sway/ipc/client.hpp" +#include "util/json.hpp" +#include "util/sleeper_thread.hpp" + +namespace waybar::modules::sway { + +class Hide : public ALabel, public sigc::trackable { + public: + Hide(const std::string&, const waybar::Bar&, const Json::Value&); + ~Hide() = default; + auto update() -> void; + + private: + void onEvent(const struct Ipc::ipc_response&); + void worker(); + + std::string current_mode_; + bool visible_by_modifier_; + const Bar& bar_; + std::string window_; + int windowId_; + util::JsonParser parser_; + + util::SleeperThread thread_; + std::mutex mutex_; + Ipc ipc_; +}; + +} // namespace waybar::modules::sway diff --git a/meson.build b/meson.build index c09fbb617..f7d87059d 100644 --- a/meson.build +++ b/meson.build @@ -180,7 +180,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/hide.cpp', ] if true diff --git a/src/bar.cpp b/src/bar.cpp index a8b230e1e..08adde8a6 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -536,23 +536,6 @@ void waybar::Bar::onMap(GdkEventAny*) { surface = gdk_wayland_window_get_wl_surface(gdk_window); } -void waybar::Bar::setVisible(bool value) { - visible = value; - if (!visible) { - window.get_style_context()->add_class("hidden"); - window.set_opacity(0); - surface_impl_->setLayer(bar_layer::BOTTOM); - } else { - window.get_style_context()->remove_class("hidden"); - window.set_opacity(1); - surface_impl_->setLayer(layer_); - } - surface_impl_->setExclusiveZone(exclusive && visible); - surface_impl_->commit(); -} - -void waybar::Bar::toggle() { setVisible(!visible); } - // Converting string to button code rn as to avoid doing it later void waybar::Bar::setupAltFormatKeyForModule(const std::string& module_name) { if (config.isMember(module_name)) { @@ -614,6 +597,62 @@ void waybar::Bar::handleSignal(int signal) { } } +void waybar::Bar::setVisible(bool value) { + visible = value; + if (!visible) { + window.get_style_context()->add_class("hidden"); + window.set_opacity(0); + surface_impl_->setLayer(bar_layer::BOTTOM); + } else { + window.get_style_context()->remove_class("hidden"); + window.set_opacity(1); + surface_impl_->setLayer(layer_); + } + surface_impl_->setExclusiveZone(exclusive && visible); + surface_impl_->commit(); +} + +void waybar::Bar::setHiddenClass(bool value) const { + if (value) { + window.get_style_context()->add_class("hidden"); + } else { + window.get_style_context()->remove_class("hidden"); + } +} + +void waybar::Bar::setBottomLayerClass(bool value) const { + if (value) { + window.get_style_context()->add_class("bottom-layer"); + } else { + window.get_style_context()->remove_class("bottom-layer"); + } +} + +void waybar::Bar::moveToTopLayer() const { + surface_impl_->setLayer(bar_layer::TOP); + surface_impl_->commit(); +} + +void waybar::Bar::moveToBottomLayer() const { + surface_impl_->setLayer(bar_layer::BOTTOM); + surface_impl_->commit(); +} + +void waybar::Bar::moveToConfiguredLayer() const { + surface_impl_->setLayer(layer_); + surface_impl_->commit(); +} + +void waybar::Bar::setExclusive(bool value) { + exclusive = value; + surface_impl_->setExclusiveZone(exclusive && visible); + surface_impl_->commit(); +} + +void waybar::Bar::toggle() { + return setVisible(!visible); +} + void waybar::Bar::getModules(const Factory& factory, const std::string& pos) { if (config[pos].isArray()) { for (const auto& name : config[pos]) { diff --git a/src/factory.cpp b/src/factory.cpp index 983635450..02b981813 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -22,6 +22,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { if (ref == "sway/window") { return new waybar::modules::sway::Window(id, bar_, config_[name]); } + if (ref == "sway/hide") { + return new waybar::modules::sway::Hide(id, bar_, config_[name]); + } if (ref == "sway/language") { return new waybar::modules::sway::Language(id, config_[name]); } diff --git a/src/modules/sway/hide.cpp b/src/modules/sway/hide.cpp new file mode 100644 index 000000000..c5984e2db --- /dev/null +++ b/src/modules/sway/hide.cpp @@ -0,0 +1,83 @@ +#include "modules/sway/hide.hpp" +#include <spdlog/spdlog.h> +#include "client.hpp" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" + +namespace waybar::modules::sway { + +Hide::Hide(const std::string& id, const Bar& bar, const Json::Value& config) + : ALabel(config, "hide", id, "{}", 0, true), bar_(bar), windowId_(-1) { + ipc_.subscribe(R"(["bar_state_update","barconfig_update"])"); + ipc_.signal_event.connect(sigc::mem_fun(*this, &Hide::onEvent)); + + // override mode to "hide" + auto &bar_local = const_cast<Bar &>(bar_); + bar_local.config["mode"] = "hide"; + bar_local.setExclusive(false); + + if (config_["hide-on-startup"].asBool()) { + spdlog::debug("sway/hide: Hiding on startup enabled!"); + bar_local.setHiddenClass(true); + bar_local.moveToConfiguredLayer(); + } else { + bar_local.moveToTopLayer(); + } + + ipc_.setWorker([this] { + try { + ipc_.handleEvent(); + } catch (const std::exception& e) { + spdlog::error("Hide: {}", e.what()); + } + }); +} + +void Hide::onEvent(const struct Ipc::ipc_response& res) { + std::lock_guard<std::mutex> lock(mutex_); + auto payload = parser_.parse(res.payload); + auto &bar = const_cast<Bar &>(bar_); + + if (payload.isMember("mode")) { + auto mode = payload["mode"].asString(); + if (mode == "hide") { + // Hide the bars when configuring the "hide" bar + spdlog::debug("sway/hide: hiding bar(s)"); + bar.setVisible(false); + bar.setExclusive(false); + } else if (mode == "dock") { // enables toggling the bar using killall -USR2 waybar + spdlog::debug("sway/hide: showing bar(s)"); + bar.setVisible(true); + bar.setExclusive(true); + } + return; + } + + if (payload.isMember("visible_by_modifier")) { + visible_by_modifier_ = payload["visible_by_modifier"].asBool(); + spdlog::debug("sway/hide: visible by modifier: {}", visible_by_modifier_); + + if (visible_by_modifier_) { + bar.setHiddenClass(false); + bar.setBottomLayerClass(false); + bar.moveToTopLayer(); + return; + } + + bool hide_to_bottom_layer_ = config_["hide-to-bottom-layer"].asBool(); + if (hide_to_bottom_layer_) { + spdlog::debug("sway/hide: Moving bar to bottom layer instead of hiding."); + bar.setBottomLayerClass(true); + bar.moveToBottomLayer(); + return; + } + + bar.setBottomLayerClass(false); + bar.setHiddenClass(true); + bar.moveToConfiguredLayer(); + } +} + +auto Hide::update() -> void { +} + +} // namespace waybar::modules::sway