diff --git a/include/factory.hpp b/include/factory.hpp index db6fd87..a34e361 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -9,7 +9,7 @@ #endif #ifdef HAVE_WLR #include "modules/wlr/taskbar.hpp" -#include "modules/wlr/workspaces.hpp" +#include "modules/wlr/workspace_manager.hpp" #endif #ifdef HAVE_RIVER #include "modules/river/tags.hpp" diff --git a/include/modules/wlr/workspace_manager.hpp b/include/modules/wlr/workspace_manager.hpp new file mode 100644 index 0000000..3c8fe99 --- /dev/null +++ b/include/modules/wlr/workspace_manager.hpp @@ -0,0 +1,109 @@ +#pragma once + +#include +#include + +#include +#include + +#include "AModule.hpp" +#include "bar.hpp" +#include "wlr-workspace-unstable-v1-client-protocol.h" + +namespace waybar::modules::wlr { + +class WorkspaceManager; +class WorkspaceGroup; + +class Workspace { + public: + Workspace(const waybar::Bar &bar, const Json::Value &config, WorkspaceGroup &workspace_group, + zwlr_workspace_handle_v1 *workspace); + ~Workspace(); + auto update() -> void; + + auto id() const -> uint32_t { return id_; } + auto handle_name(const std::string &name) -> void { name_ = name; } + auto handle_coordinates(const std::vector &coordinates) -> void { + coordinates_ = coordinates; + } + auto handle_state(const std::vector &state) -> void; + auto handle_remove() -> void; + + enum class State { ACTIVE = 1 << 0 }; + + private: + static uint32_t workspace_global_id; + const Bar & bar_; + const Json::Value &config_; + WorkspaceGroup & workspace_group_; + + // wlr stuff + zwlr_workspace_handle_v1 *workspace_handle_; + uint32_t state_ = 0; + + uint32_t id_; + std::string name_; + std::vector coordinates_; + + const Gtk::Box box_; + const Gtk::Image icon_; +}; + +class WorkspaceGroup { + public: + WorkspaceGroup(const waybar::Bar &bar, const Json::Value &config, WorkspaceManager &manager, + zwlr_workspace_group_handle_v1 *workspace_group_handle); + ~WorkspaceGroup(); + auto update() -> void; + + auto id() const -> uint32_t { return id_; } + auto remove_workspace(uint32_t id_) -> void; + + // wlr stuff + auto handle_workspace_create(zwlr_workspace_handle_v1 *workspace_handle) -> void; + + auto handle_remove() -> void; + auto handle_output_enter(wl_output *output) -> void; + auto handle_output_leave() -> void; + + private: + static uint32_t group_global_id; + const waybar::Bar &bar_; + const Json::Value &config_; + WorkspaceManager & workspace_manager_; + + // wlr stuff + zwlr_workspace_group_handle_v1 *workspace_group_handle_; + wl_output * output_ = nullptr; + + uint32_t id_; + std::vector> workspaces_; +}; + +class WorkspaceManager : public AModule { + public: + WorkspaceManager(const std::string &id, const waybar::Bar &bar, const Json::Value &config); + ~WorkspaceManager() override; + auto update() -> void override; + + auto remove_workspace_group(uint32_t id_) -> void; + + // wlr stuff + auto register_manager(wl_registry *registry, uint32_t name, uint32_t version) -> void; + auto handle_workspace_group_create(zwlr_workspace_group_handle_v1 *workspace_group_handle) + -> void; + + auto handle_done() -> void; + auto handle_finished() -> void; + + private: + const waybar::Bar & bar_; + Gtk::Box box_; + std::vector> groups_; + + // wlr stuff + zwlr_workspace_manager_v1 *workspace_manager_ = nullptr; +}; + +} // namespace waybar::modules::wlr diff --git a/include/modules/wlr/workspace_manager_binding.hpp b/include/modules/wlr/workspace_manager_binding.hpp new file mode 100644 index 0000000..1cef652 --- /dev/null +++ b/include/modules/wlr/workspace_manager_binding.hpp @@ -0,0 +1,8 @@ +#include "wlr-workspace-unstable-v1-client-protocol.h" + +namespace waybar::modules::wlr { + void add_registry_listener(void *data); + void add_workspace_listener(zwlr_workspace_handle_v1 *workspace_handle, void *data); + void add_workspace_group_listener(zwlr_workspace_group_handle_v1 *workspace_group_handle, void *data); + zwlr_workspace_manager_v1* workspace_manager_bind(wl_registry *registry, uint32_t name, uint32_t version, void *data); +} \ No newline at end of file diff --git a/include/modules/wlr/workspaces.hpp b/include/modules/wlr/workspaces.hpp deleted file mode 100644 index 351ddc4..0000000 --- a/include/modules/wlr/workspaces.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -#include "AModule.hpp" -#include "bar.hpp" -#include "wlr-workspace-unstable-v1-client-protocol.h" - -namespace waybar::modules::wlr { - -class WorkspaceManager; -class WorkspaceGroup; - -class Workspace { - public: - Workspace(const waybar::Bar &bar, const Json::Value &config, WorkspaceGroup &workspace_group, - zwlr_workspace_handle_v1 &workspace); - ~Workspace() = default; - auto update() -> void; - - enum class State { ACTIVE = 1 << 1 }; - - private: - const Bar & bar_; - const Gtk::Box box_; - const Gtk::Image icon_; - const Json::Value & config_; - const WorkspaceGroup &workspace_group_; - - // wlr stuff - zwlr_workspace_handle_v1 &workspace_handle_; - uint32_t state_; -}; - -class WorkspaceGroup { - public: - WorkspaceGroup(const waybar::Bar &bar, const Json::Value &config, WorkspaceManager &manager, - zwlr_workspace_group_handle_v1 &workspace_group_handle); - auto update() -> void; - - // wlr stuff - auto handle_workspace_create(zwlr_workspace_handle_v1 &workspace_handle) -> void; - auto handle_remove() -> void; - auto handle_output_enter(wl_output &output) -> void; - auto handle_output_leave(wl_output &output) -> void; - - private: - const waybar::Bar & bar_; - const Json::Value & config_; - const WorkspaceManager & workspace_manager_; - std::vector> workspaces_; - - // wlr stuff - zwlr_workspace_group_handle_v1 &workspace_group_handle_; -}; - -class WorkspaceManager : public AModule { - public: - WorkspaceManager(const std::string &id, const waybar::Bar &bar, const Json::Value &config); - auto update() -> void override; - - // wlr stuff - auto register_manager(wl_registry *registry, uint32_t name, uint32_t version) -> void; - auto handle_workspace_group_create(zwlr_workspace_group_handle_v1 *workspace_group_handle) - -> void; - auto handle_done() -> void; - auto handle_finished() -> void; - - private: - const waybar::Bar & bar_; - Gtk::Box box_; - std::vector> groups_; - - // wlr stuff - zwlr_workspace_manager_v1 *workspace_manager_ = nullptr; -}; - -} // namespace waybar::modules::wlr diff --git a/meson.build b/meson.build index d0ba1e8..638a766 100644 --- a/meson.build +++ b/meson.build @@ -166,7 +166,8 @@ src_files += [ if true add_project_arguments('-DHAVE_WLR', language: 'cpp') src_files += 'src/modules/wlr/taskbar.cpp' - src_files += 'src/modules/wlr/workspaces.cpp' + src_files += 'src/modules/wlr/workspace_manager.cpp' + src_files += 'src/modules/wlr/workspace_manager_binding.cpp' endif if true diff --git a/src/modules/wlr/workspace_manager.cpp b/src/modules/wlr/workspace_manager.cpp new file mode 100644 index 0000000..04a3188 --- /dev/null +++ b/src/modules/wlr/workspace_manager.cpp @@ -0,0 +1,182 @@ +#include "modules/wlr/workspace_manager.hpp" + +#include +#include + +#include + +#include "modules/wlr/workspace_manager_binding.hpp" + +namespace waybar::modules::wlr { + +uint32_t Workspace::workspace_global_id = 0; +uint32_t WorkspaceGroup::group_global_id = 0; + +WorkspaceManager::WorkspaceManager(const std::string &id, const waybar::Bar &bar, + const Json::Value &config) + : waybar::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_); + + add_registry_listener(this); + if (!workspace_manager_) { + return; + } +} + +auto WorkspaceManager::register_manager(wl_registry *registry, uint32_t name, uint32_t version) + -> void { + if (workspace_manager_) { + spdlog::warn("Register workspace manager again although already registered!"); + return; + } + if (version != 1) { + spdlog::warn("Using different workspace manager protocol version: {}", version); + } + workspace_manager_ = workspace_manager_bind(registry, name, version, this); +} + +auto WorkspaceManager::handle_workspace_group_create( + zwlr_workspace_group_handle_v1 *workspace_group_handle) -> void { + groups_.push_back(std::make_unique(bar_, config_, *this, workspace_group_handle)); + spdlog::debug("Workspace group {} created", groups_.back()->id()); +} + +auto WorkspaceManager::handle_finished() -> void { + zwlr_workspace_manager_v1_destroy(workspace_manager_); + workspace_manager_ = nullptr; +} + +auto WorkspaceManager::handle_done() -> void { +} + +auto WorkspaceManager::update() -> void { + for (auto &group : groups_) { + group->update(); + } + AModule::update(); +} + +WorkspaceManager::~WorkspaceManager() { + if (!workspace_manager_) { + return; + } + + zwlr_workspace_manager_v1_destroy(workspace_manager_); + workspace_manager_ = nullptr; +} +auto WorkspaceManager::remove_workspace_group(uint32_t id) -> void { + auto it = std::find_if(groups_.begin(), + groups_.end(), + [id](const std::unique_ptr &g) { return g->id() == id; }); + + if (it == groups_.end()) { + spdlog::warn("Can't find group with id {}", id); + return; + } + + groups_.erase(it); +} + +WorkspaceGroup::WorkspaceGroup(const Bar &bar, const Json::Value &config, WorkspaceManager &manager, + zwlr_workspace_group_handle_v1 *workspace_group_handle) + : bar_(bar), + config_(config), + workspace_manager_(manager), + workspace_group_handle_(workspace_group_handle), + id_(++group_global_id) { + add_workspace_group_listener(workspace_group_handle, this); +} + +WorkspaceGroup::~WorkspaceGroup()->void { + if (!workspace_group_handle_) { + return; + } + + zwlr_workspace_group_handle_v1_destroy(workspace_group_handle_); + workspace_group_handle_ = nullptr; +} + +auto WorkspaceGroup::handle_workspace_create(zwlr_workspace_handle_v1 *workspace) -> void { + workspaces_.push_back(std::make_unique(bar_, config_, *this, workspace)); + spdlog::debug("Workspace {} created", workspaces_.back()->id()); +} + +auto WorkspaceGroup::handle_remove() -> void { + zwlr_workspace_group_handle_v1_destroy(workspace_group_handle_); + workspace_group_handle_ = nullptr; + workspace_manager_.remove_workspace_group(id_); +} + +auto WorkspaceGroup::handle_output_enter(wl_output *output) -> void { + spdlog::debug("Output {} assigned to {} group", (void *)output, id_); + output_ = output; +} + +auto WorkspaceGroup::handle_output_leave() -> void { + spdlog::debug("Output {} remove from {} group", (void *)output_, id_); + output_ = nullptr; +} + +auto WorkspaceGroup::update() -> void { + for (auto &workspace : workspaces_) { + workspace->update(); + } +} + +auto WorkspaceGroup::remove_workspace(uint32_t id) -> void { + auto it = std::find_if(workspaces_.begin(), + workspaces_.end(), + [id](const std::unique_ptr &w) { return w->id() == id; }); + + if (it == workspaces_.end()) { + spdlog::warn("Can't find group with id {}", id); + return; + } + + workspaces_.erase(it); +} + +Workspace::Workspace(const Bar &bar, const Json::Value &config, WorkspaceGroup &workspace_group, + zwlr_workspace_handle_v1 *workspace) + : bar_(bar), + config_(config), + workspace_group_(workspace_group), + workspace_handle_(workspace), + id_(++workspace_global_id) { + add_workspace_listener(workspace, this); +} + +Workspace::~Workspace() { + if (!workspace_handle_) { + return; + } + + zwlr_workspace_handle_v1_destroy(workspace_handle_); + workspace_handle_ = nullptr; +} + +auto Workspace::update() -> void {} + +auto Workspace::handle_state(const std::vector &state) -> void { + state_ = 0; + for (auto state_entry : state) { + switch (state_entry) { + case ZWLR_WORKSPACE_HANDLE_V1_STATE_ACTIVE: + state_ |= (uint32_t)State::ACTIVE; + break; + } + } +} + +auto Workspace::handle_remove() -> void { + zwlr_workspace_handle_v1_destroy(workspace_handle_); + workspace_handle_ = nullptr; + workspace_group_.remove_workspace(id_); +} +} // namespace waybar::modules::wlr \ No newline at end of file diff --git a/src/modules/wlr/workspace_manager_binding.cpp b/src/modules/wlr/workspace_manager_binding.cpp new file mode 100644 index 0000000..f6db711 --- /dev/null +++ b/src/modules/wlr/workspace_manager_binding.cpp @@ -0,0 +1,134 @@ +#include "modules/wlr/workspace_manager_binding.hpp" + +#include + +#include "client.hpp" +#include "modules/wlr/workspace_manager.hpp" + +namespace waybar::modules::wlr { + +static void handle_global(void *data, wl_registry *registry, uint32_t name, const char *interface, + uint32_t version) { + if (std::strcmp(interface, zwlr_workspace_manager_v1_interface.name) == 0) { + static_cast(data)->register_manager(registry, name, version); + } +} + +static void handle_global_remove(void *data, wl_registry *registry, uint32_t name) { + /* Nothing to do here */ +} + +static const wl_registry_listener registry_listener_impl = {.global = handle_global, + .global_remove = handle_global_remove}; + +void add_registry_listener(void *data) { + wl_display * display = Client::inst()->wl_display; + wl_registry *registry = wl_display_get_registry(display); + + wl_registry_add_listener(registry, ®istry_listener_impl, data); + wl_display_roundtrip(display); + wl_display_roundtrip(display); +} + +static void workspace_manager_handle_workspace_group( + void *data, zwlr_workspace_manager_v1 *_, zwlr_workspace_group_handle_v1 *workspace_group) { + static_cast(data)->handle_workspace_group_create(workspace_group); +} + +static void workspace_manager_handle_done(void *data, zwlr_workspace_manager_v1 *_) { + static_cast(data)->handle_done(); +} + +static void workspace_manager_handle_finished(void *data, zwlr_workspace_manager_v1 *_) { + static_cast(data)->handle_finished(); +} + +static const zwlr_workspace_manager_v1_listener workspace_manager_impl = { + .workspace_group = workspace_manager_handle_workspace_group, + .done = workspace_manager_handle_done, + .finished = workspace_manager_handle_finished, +}; + +zwlr_workspace_manager_v1 *workspace_manager_bind(wl_registry *registry, uint32_t name, + uint32_t version, void *data) { + auto *workspace_manager = static_cast( + wl_registry_bind(registry, name, &zwlr_workspace_manager_v1_interface, version)); + + if (workspace_manager) + zwlr_workspace_manager_v1_add_listener(workspace_manager, &workspace_manager_impl, data); + else + spdlog::error("Failed to register manager"); + + return workspace_manager; +} + +static void workspace_group_handle_output_enter(void *data, zwlr_workspace_group_handle_v1 *_, + wl_output *output) { + static_cast(data)->handle_output_enter(output); +} + +static void workspace_group_handle_output_leave(void *data, zwlr_workspace_group_handle_v1 *_, + wl_output *output) { + static_cast(data)->handle_output_leave(); +} + +static void workspace_group_handle_workspace(void *data, zwlr_workspace_group_handle_v1 *_, + zwlr_workspace_handle_v1 *workspace) { + static_cast(data)->handle_workspace_create(workspace); +} + +static void workspace_group_handle_remove(void *data, zwlr_workspace_group_handle_v1 *_) { + static_cast(data)->handle_remove(); +} + +static const zwlr_workspace_group_handle_v1_listener workspace_group_impl = { + .output_enter = workspace_group_handle_output_enter, + .output_leave = workspace_group_handle_output_leave, + .workspace = workspace_group_handle_workspace, + .remove = workspace_group_handle_remove}; + +void add_workspace_group_listener(zwlr_workspace_group_handle_v1 *workspace_group_handle, + void * data) { + zwlr_workspace_group_handle_v1_add_listener(workspace_group_handle, &workspace_group_impl, data); +} + +void workspace_handle_name(void *data, struct zwlr_workspace_handle_v1 *_, const char *name) { + static_cast(data)->handle_name(name); +} + +void workspace_handle_coordinates(void *data, struct zwlr_workspace_handle_v1 *_, + struct wl_array *coordinates) { + std::vector coords_vec; + auto coords = static_cast(coordinates->data); + for (size_t i = 0; i < coordinates->size; ++i) { + coords_vec.push_back(coords[i]); + } + + static_cast(data)->handle_coordinates(coords_vec); +} + +void workspace_handle_state(void *data, struct zwlr_workspace_handle_v1 *_, + struct wl_array *state) { + std::vector state_vec; + auto coords = static_cast(state->data); + for (size_t i = 0; i < state->size; ++i) { + state_vec.push_back(coords[i]); + } + + static_cast(data)->handle_state(state_vec); +} + +void workspace_handle_remove(void *data, struct zwlr_workspace_handle_v1 *_) { + static_cast(data)->handle_remove(); +} + +static const zwlr_workspace_handle_v1_listener workspace_impl = { + .name = workspace_handle_name, + .coordinates = workspace_handle_coordinates, + .state = workspace_handle_state, + .remove = workspace_handle_remove}; + +void add_workspace_listener(zwlr_workspace_handle_v1 *workspace_handle, void *data) { + zwlr_workspace_handle_v1_add_listener(workspace_handle, &workspace_impl, data); +} +} // namespace waybar::modules::wlr diff --git a/src/modules/wlr/workspaces.cpp b/src/modules/wlr/workspaces.cpp deleted file mode 100644 index 0d9ae0b..0000000 --- a/src/modules/wlr/workspaces.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "modules/wlr/workspaces.hpp" - -#include -#include - -#include - -namespace waybar::modules::wlr { - -static void handle_global(void *data, wl_registry *registry, uint32_t name, - const char *interface, uint32_t version) { - if (std::strcmp(interface, zwlr_workspace_manager_v1_interface.name) == 0) { - static_cast(data)->register_manager(registry, name, version); - } -} - -static void handle_global_remove(void *data, wl_registry *registry, uint32_t name) { - /* Nothing to do here */ -} - -static const wl_registry_listener registry_listener_impl = {.global = handle_global, - .global_remove = handle_global_remove}; - -WorkspaceManager::WorkspaceManager(const std::string &id, const waybar::Bar &bar, - const Json::Value &config) - : waybar::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_); - - // wlr stuff - wl_display * display = Client::inst()->wl_display; - wl_registry *registry = wl_display_get_registry(display); - - wl_registry_add_listener(registry, ®istry_listener_impl, this); - wl_display_roundtrip(display); - - if (!workspace_manager_) { - return; - } -} - -static void workspace_manager_handle_workspace_group( - void *data, zwlr_workspace_manager_v1 *_, - zwlr_workspace_group_handle_v1 *workspace_group) { - static_cast(data)->handle_workspace_group_create(workspace_group); -} - -static void workspace_manager_handle_done(void *data, zwlr_workspace_manager_v1 *_) { - static_cast(data)->handle_done(); -} - -static void workspace_manager_handle_finished(void *data, zwlr_workspace_manager_v1 *_) { - static_cast(data)->handle_finished(); -} - -static const zwlr_workspace_manager_v1_listener workspace_manager_impl = { - .workspace_group = workspace_manager_handle_workspace_group, - .done = workspace_manager_handle_done, - .finished = workspace_manager_handle_finished, -}; - -auto WorkspaceManager::register_manager(wl_registry *registry, uint32_t name, uint32_t version) - -> void { - if (workspace_manager_) { - spdlog::warn("Register workspace manager again although already registered!"); - return; - } - if (version != 1) { - spdlog::warn("Using different workspace manager protocol version: {}", version); - } - - workspace_manager_ = static_cast( - wl_registry_bind(registry, name, &zwlr_workspace_manager_v1_interface, version)); - - if (workspace_manager_) - zwlr_workspace_manager_v1_add_listener(workspace_manager_, &workspace_manager_impl, this); - else - spdlog::debug("Failed to register manager"); -} -auto WorkspaceManager::handle_workspace_group_create( - zwlr_workspace_group_handle_v1 *workspace_group_handle) -> void { - groups_.push_back(std::make_unique(bar_, config_, *this, *workspace_group_handle)); -} - -auto WorkspaceManager::handle_finished() -> void { - zwlr_workspace_manager_v1_destroy(workspace_manager_); - workspace_manager_ = nullptr; -} -auto WorkspaceManager::handle_done() -> void {} -auto WorkspaceManager::update() -> void { - for (auto &group : groups_) { - group->update(); - } - AModule::update(); -} - -static void workspace_group_handle_output_enter(void *data, - zwlr_workspace_group_handle_v1 *_, - wl_output *output) { - static_cast(data)->handle_output_enter(*output); -} - -static void workspace_group_handle_output_leave(void *data, - zwlr_workspace_group_handle_v1 *_, - wl_output *output) { - static_cast(data)->handle_output_leave(*output); -} - -static void workspace_group_handle_workspace(void *data, - zwlr_workspace_group_handle_v1 *_, - zwlr_workspace_handle_v1 *workspace) { - static_cast(data)->handle_workspace_create(*workspace); -} - -static void workspace_group_handle_remove(void *data, - zwlr_workspace_group_handle_v1 *_) { - static_cast(data)->handle_remove(); -} - -static const zwlr_workspace_group_handle_v1_listener workspace_group_impl = { - .output_enter = workspace_group_handle_output_enter, - .output_leave = workspace_group_handle_output_leave, - .workspace = workspace_group_handle_workspace, - .remove = workspace_group_handle_remove -}; - -WorkspaceGroup::WorkspaceGroup(const Bar & bar, const Json::Value &config, WorkspaceManager &manager, - zwlr_workspace_group_handle_v1 &workspace_group_handle) - : bar_(bar), config_(config), workspace_manager_(manager), workspace_group_handle_(workspace_group_handle) -{ - zwlr_workspace_group_handle_v1_add_listener(&workspace_group_handle, &workspace_group_impl, this); -} -auto WorkspaceGroup::handle_workspace_create(zwlr_workspace_handle_v1 &workspace) -> void { - workspaces_.push_back(std::make_unique(bar_, config_, *this, workspace)); -} -auto WorkspaceGroup::handle_remove() -> void {} -auto WorkspaceGroup::handle_output_enter(wl_output &output) -> void {} -auto WorkspaceGroup::handle_output_leave(wl_output &output) -> void {} -auto WorkspaceGroup::update() -> void { - -} -Workspace::Workspace(const Bar &bar, const Json::Value &config, - WorkspaceGroup &workspace_group, zwlr_workspace_handle_v1 &workspace) - : bar_(bar), config_(config), workspace_group_(workspace_group), workspace_handle_(workspace) -{ -} -} // namespace waybar::modules::wlr \ No newline at end of file