From bcadf64031ee0520212aa8f092f5ac14122cd924 Mon Sep 17 00:00:00 2001 From: Felix Weilbach Date: Sun, 17 Oct 2021 20:08:16 +0200 Subject: [PATCH] Show application icon when using sway window module Signed-off-by: Felix Weilbach --- include/AIconLabel.hpp | 25 ++++++++++++++ include/modules/sway/window.hpp | 6 ++-- meson.build | 1 + src/AIconLabel.cpp | 28 +++++++++++++++ src/modules/sway/window.cpp | 61 +++++++++++++++++++++++++++++++-- 5 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 include/AIconLabel.hpp create mode 100644 src/AIconLabel.cpp diff --git a/include/AIconLabel.hpp b/include/AIconLabel.hpp new file mode 100644 index 0000000..3eac7dd --- /dev/null +++ b/include/AIconLabel.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include "ALabel.hpp" + +namespace waybar { + +class AIconLabel : public ALabel { + public: + AIconLabel(const Json::Value &config, const std::string &name, const std::string &id, + const std::string &format, uint16_t interval = 0, bool ellipsize = false, + bool enable_click = false, bool enable_scroll = false); + virtual ~AIconLabel() = default; + virtual auto update() -> void; + + protected: + Gtk::Image image_; + Gtk::Box box_; + + bool iconEnabled() const; +}; + +} // namespace waybar diff --git a/include/modules/sway/window.hpp b/include/modules/sway/window.hpp index 0f7ae31..0ab129e67 100644 --- a/include/modules/sway/window.hpp +++ b/include/modules/sway/window.hpp @@ -2,7 +2,8 @@ #include #include -#include "ALabel.hpp" + +#include "AIconLabel.hpp" #include "bar.hpp" #include "client.hpp" #include "modules/sway/ipc/client.hpp" @@ -10,7 +11,7 @@ namespace waybar::modules::sway { -class Window : public ALabel, public sigc::trackable { +class Window : public AIconLabel, public sigc::trackable { public: Window(const std::string&, const waybar::Bar&, const Json::Value&); ~Window() = default; @@ -23,6 +24,7 @@ class Window : public ALabel, public sigc::trackable { std::string& output); void getTree(); std::string rewriteTitle(const std::string& title); + void updateAppIcon(); const Bar& bar_; std::string window_; diff --git a/meson.build b/meson.build index 2c644cc..ba5a69d 100644 --- a/meson.build +++ b/meson.build @@ -142,6 +142,7 @@ src_files = files( 'src/factory.cpp', 'src/AModule.cpp', 'src/ALabel.cpp', + 'src/AIconLabel.cpp', 'src/modules/custom.cpp', 'src/modules/disk.cpp', 'src/modules/idle_inhibitor.cpp', diff --git a/src/AIconLabel.cpp b/src/AIconLabel.cpp new file mode 100644 index 0000000..5bc36e4 --- /dev/null +++ b/src/AIconLabel.cpp @@ -0,0 +1,28 @@ +#include "AIconLabel.hpp" + +#include + +namespace waybar { + +AIconLabel::AIconLabel(const Json::Value &config, const std::string &name, const std::string &id, + const std::string &format, uint16_t interval, bool ellipsize, + bool enable_click, bool enable_scroll) + : ALabel(config, name, id, format, interval, ellipsize, enable_click, enable_scroll) { + event_box_.remove(); + box_.set_orientation(Gtk::Orientation::ORIENTATION_HORIZONTAL); + box_.set_spacing(8); + box_.add(image_); + box_.add(label_); + event_box_.add(box_); +} + +auto AIconLabel::update() -> void { + image_.set_visible(image_.get_visible() && iconEnabled()); + ALabel::update(); +} + +bool AIconLabel::iconEnabled() const { + return config_["icon"].isBool() ? config_["icon"].asBool() : true; +} + +} // namespace waybar diff --git a/src/modules/sway/window.cpp b/src/modules/sway/window.cpp index fc81b2c..00418a1 100644 --- a/src/modules/sway/window.cpp +++ b/src/modules/sway/window.cpp @@ -1,11 +1,20 @@ #include "modules/sway/window.hpp" + +#include +#include +#include +#include +#include #include + +#include #include +#include namespace waybar::modules::sway { Window::Window(const std::string& id, const Bar& bar, const Json::Value& config) - : ALabel(config, "window", id, "{}", 0, true), bar_(bar), windowId_(-1) { + : AIconLabel(config, "window", id, "{}", 0, true), bar_(bar), windowId_(-1) { ipc_.subscribe(R"(["window","workspace"])"); ipc_.signal_event.connect(sigc::mem_fun(*this, &Window::onEvent)); ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Window::onCmd)); @@ -29,12 +38,60 @@ void Window::onCmd(const struct Ipc::ipc_response& res) { auto payload = parser_.parse(res.payload); auto output = payload["output"].isString() ? payload["output"].asString() : ""; std::tie(app_nb_, windowId_, window_, app_id_) = getFocusedNode(payload["nodes"], output); + updateAppIcon(); dp.emit(); } catch (const std::exception& e) { spdlog::error("Window: {}", e.what()); } } +std::optional getDesktopFilePath(const std::string& app_id) { + const auto data_dirs = Glib::get_system_data_dirs(); + for (const auto& data_dir : data_dirs) { + const auto desktop_file_path = data_dir + "applications/" + app_id + ".desktop"; + if (std::filesystem::exists(desktop_file_path)) { + return desktop_file_path; + } + } + return {}; +} + +std::optional getIconName(const std::string& app_id) { + const auto desktop_file_path = getDesktopFilePath(app_id); + if (!desktop_file_path.has_value()) { + return {}; + } + try { + Glib::KeyFile desktop_file; + desktop_file.load_from_file(desktop_file_path.value()); + const auto icon_name = desktop_file.get_string("Desktop Entry", "Icon"); + if (icon_name.empty()) { + return {}; + } + return icon_name; + } catch (Glib::FileError& error) { + spdlog::warn( + "Error while loading desktop file {}: {}", desktop_file_path.value(), error.what().c_str()); + } catch (Glib::KeyFileError& error) { + spdlog::warn( + "Error while loading desktop file {}: {}", desktop_file_path.value(), error.what().c_str()); + } + return {}; +} + +void Window::updateAppIcon() { + if (!iconEnabled()) { + return; + } + const auto icon_name = getIconName(app_id_); + if (icon_name.has_value()) { + image_.set_from_icon_name(icon_name.value(), Gtk::ICON_SIZE_LARGE_TOOLBAR); + image_.set_visible(true); + return; + } + image_.set_visible(false); +} + auto Window::update() -> void { if (!old_app_id_.empty()) { bar_.window.get_style_context()->remove_class(old_app_id_); @@ -63,7 +120,7 @@ auto Window::update() -> void { label_.set_tooltip_text(window_); } // Call parent update - ALabel::update(); + AIconLabel::update(); } int leafNodesInWorkspace(const Json::Value& node) {