Merge pull request #1292 from FlexW/feature/sway-app-icon
Show application icon when using sway window module
This commit is contained in:
		
						commit
						35d6da3965
					
				|  | @ -0,0 +1,25 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <gtkmm/box.h> | ||||
| #include <gtkmm/image.h> | ||||
| 
 | ||||
| #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
 | ||||
|  | @ -2,7 +2,8 @@ | |||
| 
 | ||||
| #include <fmt/format.h> | ||||
| #include <tuple> | ||||
| #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_; | ||||
|  |  | |||
|  | @ -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', | ||||
|  |  | |||
|  | @ -0,0 +1,28 @@ | |||
| #include "AIconLabel.hpp" | ||||
| 
 | ||||
| #include <gdkmm/pixbuf.h> | ||||
| 
 | ||||
| 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
 | ||||
|  | @ -1,11 +1,20 @@ | |||
| #include "modules/sway/window.hpp" | ||||
| 
 | ||||
| #include <gdkmm/pixbuf.h> | ||||
| #include <glibmm/fileutils.h> | ||||
| #include <glibmm/keyfile.h> | ||||
| #include <glibmm/miscutils.h> | ||||
| #include <gtkmm/enums.h> | ||||
| #include <spdlog/spdlog.h> | ||||
| 
 | ||||
| #include <filesystem> | ||||
| #include <regex> | ||||
| #include <string> | ||||
| 
 | ||||
| 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<std::string> 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<Glib::ustring> 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) { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue