mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-10-31 07:52:42 +01:00 
			
		
		
		
	Merge branch 'Alexays:master' into sort-workspaces-by-number
This commit is contained in:
		
							
								
								
									
										57
									
								
								ext4fuse.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								ext4fuse.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| class MacFuseRequirement < Requirement | ||||
|   fatal true | ||||
|  | ||||
|   satisfy(build_env: false) { self.class.binary_mac_fuse_installed? } | ||||
|  | ||||
|   def self.binary_mac_fuse_installed? | ||||
|     File.exist?("/usr/local/include/fuse/fuse.h") && | ||||
|       !File.symlink?("/usr/local/include/fuse") | ||||
|   end | ||||
|  | ||||
|   env do | ||||
|     ENV.append_path "PKG_CONFIG_PATH", HOMEBREW_LIBRARY/"Homebrew/os/mac/pkgconfig/fuse" | ||||
|     ENV.append_path "PKG_CONFIG_PATH", "/usr/local/lib/pkgconfig" | ||||
|  | ||||
|     unless HOMEBREW_PREFIX.to_s == "/usr/local" | ||||
|       ENV.append_path "HOMEBREW_LIBRARY_PATHS", "/usr/local/lib" | ||||
|       ENV.append_path "HOMEBREW_INCLUDE_PATHS", "/usr/local/include/fuse" | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def message | ||||
|     "macFUSE is required. Please run `brew install --cask macfuse` first." | ||||
|   end | ||||
| end | ||||
|  | ||||
| class Ext4fuse < Formula | ||||
|   desc "Read-only implementation of ext4 for FUSE" | ||||
|   homepage "https://github.com/gerard/ext4fuse" | ||||
|   url "https://github.com/gerard/ext4fuse/archive/v0.1.3.tar.gz" | ||||
|   sha256 "550f1e152c4de7d4ea517ee1c708f57bfebb0856281c508511419db45aa3ca9f" | ||||
|   license "GPL-2.0" | ||||
|   head "https://github.com/gerard/ext4fuse.git" | ||||
|  | ||||
|   bottle do | ||||
|     sha256 cellar: :any, catalina:    "446dde5e84b058966ead0cde5e38e9411f465732527f6decfa1c0dcdbd4abbef" | ||||
|     sha256 cellar: :any, mojave:      "88c4918bf5218f99295e539fe4499152edb3b60b6659e44ddd68b22359f512ae" | ||||
|     sha256 cellar: :any, high_sierra: "fc69c8993afd0ffc16a73c9c036ca8f83c77ac2a19b3237f76f9ccee8b30bbc9" | ||||
|     sha256 cellar: :any, sierra:      "fe8bbe7cd5362f00ff06ef750926bf349d60563c20b0ecf212778631c8912ba2" | ||||
|     sha256 cellar: :any, el_capitan:  "291047c821b7b205d85be853fb005510c6ab01bd4c2a2193c192299b6f049d35" | ||||
|     sha256 cellar: :any, yosemite:    "b11f564b7e7c08af0b0a3e9854973d39809bf2d8a56014f4882772b2f7307ac1" | ||||
|   end | ||||
|  | ||||
|   depends_on "pkg-config" => :build | ||||
|  | ||||
|   on_macos do | ||||
|     depends_on MacFuseRequirement => :build | ||||
|   end | ||||
|  | ||||
|   on_linux do | ||||
|     depends_on "libfuse" | ||||
|   end | ||||
|  | ||||
|   def install | ||||
|     system "make" | ||||
|     bin.install "ext4fuse" | ||||
|   end | ||||
| end | ||||
							
								
								
									
										34
									
								
								include/AButton.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								include/AButton.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <glibmm/markup.h> | ||||
| #include <gtkmm/button.h> | ||||
| #include <gtkmm/label.h> | ||||
| #include <json/json.h> | ||||
|  | ||||
| #include "AModule.hpp" | ||||
|  | ||||
| namespace waybar { | ||||
|  | ||||
| class AButton : public AModule { | ||||
|  public: | ||||
|   AButton(const Json::Value &, const std::string &, const std::string &, const std::string &format, | ||||
|           uint16_t interval = 0, bool ellipsize = false, bool enable_click = false, | ||||
|           bool enable_scroll = false); | ||||
|   virtual ~AButton() = default; | ||||
|   virtual auto update() -> void; | ||||
|   virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0); | ||||
|   virtual std::string getIcon(uint16_t, const std::vector<std::string> &alts, uint16_t max = 0); | ||||
|  | ||||
|  protected: | ||||
|   Gtk::Button button_ = Gtk::Button(name_); | ||||
|   Gtk::Label *label_ = (Gtk::Label *)button_.get_child(); | ||||
|   std::string format_; | ||||
|   const std::chrono::seconds interval_; | ||||
|   bool alt_ = false; | ||||
|   std::string default_format_; | ||||
|  | ||||
|   virtual bool handleToggle(GdkEventButton *const &e); | ||||
|   virtual std::string getState(uint8_t value, bool lesser = false); | ||||
| }; | ||||
|  | ||||
| }  // namespace waybar | ||||
| @@ -23,8 +23,8 @@ | ||||
| #endif | ||||
| #ifdef HAVE_HYPRLAND | ||||
| #include "modules/hyprland/backend.hpp" | ||||
| #include "modules/hyprland/window.hpp" | ||||
| #include "modules/hyprland/language.hpp" | ||||
| #include "modules/hyprland/window.hpp" | ||||
| #endif | ||||
| #if defined(__linux__) && !defined(NO_FILESYSTEM) | ||||
| #include "modules/battery.hpp" | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| #include <string_view> | ||||
| #include <vector> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "util/json.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
|  | ||||
| @@ -14,7 +14,7 @@ struct udev_device; | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Backlight : public ALabel { | ||||
| class Backlight : public AButton { | ||||
|   class BacklightDev { | ||||
|    public: | ||||
|     BacklightDev() = default; | ||||
|   | ||||
| @@ -13,7 +13,7 @@ | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
| @@ -24,7 +24,7 @@ namespace fs = std::experimental::filesystem; | ||||
| namespace fs = std::filesystem; | ||||
| #endif | ||||
|  | ||||
| class Battery : public ALabel { | ||||
| class Battery : public AButton { | ||||
|  public: | ||||
|   Battery(const std::string&, const Json::Value&); | ||||
|   ~Battery(); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #ifdef WANT_RFKILL | ||||
| #include "util/rfkill.hpp" | ||||
| #endif | ||||
| @@ -12,7 +12,7 @@ | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Bluetooth : public ALabel { | ||||
| class Bluetooth : public AButton { | ||||
|   struct ControllerInfo { | ||||
|     std::string path; | ||||
|     std::string address; | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| #include <date/tz.h> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
|  | ||||
| namespace waybar { | ||||
| @@ -14,7 +14,7 @@ namespace modules { | ||||
| const std::string kCalendarPlaceholder = "calendar"; | ||||
| const std::string KTimezonedTimeListPlaceholder = "timezoned_time_list"; | ||||
|  | ||||
| class Clock : public ALabel { | ||||
| class Clock : public AButton { | ||||
|  public: | ||||
|   Clock(const std::string&, const Json::Value&); | ||||
|   ~Clock() = default; | ||||
|   | ||||
| @@ -9,12 +9,12 @@ | ||||
| #include <utility> | ||||
| #include <vector> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Cpu : public ALabel { | ||||
| class Cpu : public AButton { | ||||
|  public: | ||||
|   Cpu(const std::string&, const Json::Value&); | ||||
|   ~Cpu() = default; | ||||
|   | ||||
| @@ -5,14 +5,14 @@ | ||||
| #include <csignal> | ||||
| #include <string> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "util/command.hpp" | ||||
| #include "util/json.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Custom : public ALabel { | ||||
| class Custom : public AButton { | ||||
|  public: | ||||
|   Custom(const std::string&, const std::string&, const Json::Value&); | ||||
|   ~Custom(); | ||||
|   | ||||
| @@ -5,13 +5,13 @@ | ||||
|  | ||||
| #include <fstream> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "util/format.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Disk : public ALabel { | ||||
| class Disk : public AButton { | ||||
|  public: | ||||
|   Disk(const std::string&, const Json::Value&); | ||||
|   ~Disk() = default; | ||||
|   | ||||
| @@ -1,30 +1,28 @@ | ||||
| #pragma once | ||||
| #include <string> | ||||
| #include <memory> | ||||
| #include <mutex> | ||||
| #include <deque> | ||||
| #include <functional> | ||||
| #include <memory> | ||||
| #include <mutex> | ||||
| #include <string> | ||||
| #include <thread> | ||||
|  | ||||
| namespace waybar::modules::hyprland { | ||||
| class IPC { | ||||
| public: | ||||
|  public: | ||||
|   IPC() { startIPC(); } | ||||
|  | ||||
|   void registerForIPC(const std::string&, std::function<void(const std::string&)>); | ||||
|  | ||||
|   std::string getSocket1Reply(const std::string& rq); | ||||
|  | ||||
| private: | ||||
|  private: | ||||
|   void startIPC(); | ||||
|   void parseIPC(const std::string&); | ||||
|  | ||||
|  void startIPC(); | ||||
|  void parseIPC(const std::string&); | ||||
|  | ||||
|  std::mutex callbackMutex; | ||||
|  std::deque<std::pair<std::string, std::function<void(const std::string&)>>> callbacks; | ||||
|   std::mutex callbackMutex; | ||||
|   std::deque<std::pair<std::string, std::function<void(const std::string&)>>> callbacks; | ||||
| }; | ||||
|  | ||||
| inline std::unique_ptr<IPC> gIPC; | ||||
| inline bool modulesReady = false; | ||||
| }; | ||||
|  | ||||
| };  // namespace waybar::modules::hyprland | ||||
|   | ||||
| @@ -1,20 +1,20 @@ | ||||
| #include <fmt/format.h> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "bar.hpp" | ||||
| #include "modules/hyprland/backend.hpp" | ||||
| #include "util/json.hpp" | ||||
|  | ||||
| namespace waybar::modules::hyprland { | ||||
|  | ||||
| class Language : public waybar::ALabel { | ||||
| public: | ||||
| class Language : public waybar::AButton { | ||||
|  public: | ||||
|   Language(const std::string&, const waybar::Bar&, const Json::Value&); | ||||
|   ~Language() = default; | ||||
|  | ||||
|   auto update() -> void; | ||||
|  | ||||
| private: | ||||
|  private: | ||||
|   void onEvent(const std::string&); | ||||
|  | ||||
|   void initLanguage(); | ||||
| @@ -26,4 +26,4 @@ private: | ||||
|   std::string layoutName_; | ||||
| }; | ||||
|  | ||||
| } | ||||
| }  // namespace waybar::modules::hyprland | ||||
|   | ||||
| @@ -10,19 +10,22 @@ | ||||
| namespace waybar::modules::hyprland { | ||||
|  | ||||
| class Window : public waybar::ALabel { | ||||
| public: | ||||
|  public: | ||||
|   Window(const std::string&, const waybar::Bar&, const Json::Value&); | ||||
|   ~Window() = default; | ||||
|  | ||||
|   auto update() -> void; | ||||
|  | ||||
| private: | ||||
|  private: | ||||
|   uint getActiveWorkspaceID(std::string); | ||||
|   std::string getLastWindowTitle(uint); | ||||
|   void onEvent(const std::string&); | ||||
|  | ||||
|   bool separate_outputs; | ||||
|   std::mutex mutex_; | ||||
|   const Bar& bar_; | ||||
|   util::JsonParser parser_; | ||||
|   std::string lastView; | ||||
| }; | ||||
|  | ||||
| } | ||||
| }  // namespace waybar::modules::hyprland | ||||
| @@ -2,13 +2,13 @@ | ||||
|  | ||||
| #include <fmt/format.h> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "bar.hpp" | ||||
| #include "client.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class IdleInhibitor : public ALabel { | ||||
| class IdleInhibitor : public AButton { | ||||
|   sigc::connection timeout_; | ||||
|  | ||||
|  public: | ||||
| @@ -20,6 +20,7 @@ class IdleInhibitor : public ALabel { | ||||
|  | ||||
|  private: | ||||
|   bool handleToggle(GdkEventButton* const& e); | ||||
|   void toggleStatus(); | ||||
|  | ||||
|   const Bar& bar_; | ||||
|   struct zwp_idle_inhibitor_v1* idle_inhibitor_; | ||||
|   | ||||
| @@ -4,12 +4,12 @@ | ||||
|  | ||||
| #include <memory> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "bar.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Inhibitor : public ALabel { | ||||
| class Inhibitor : public AButton { | ||||
|  public: | ||||
|   Inhibitor(const std::string&, const waybar::Bar&, const Json::Value&); | ||||
|   ~Inhibitor() override; | ||||
|   | ||||
| @@ -1,9 +1,11 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <fmt/format.h> | ||||
| #include <fstream> | ||||
| #include <jack/jack.h> | ||||
| #include <jack/thread.h> | ||||
|  | ||||
| #include <fstream> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
|  | ||||
| @@ -11,26 +13,26 @@ namespace waybar::modules { | ||||
|  | ||||
| class JACK : public ALabel { | ||||
|  public: | ||||
|   JACK(const std::string&, const Json::Value&); | ||||
|   JACK(const std::string &, const Json::Value &); | ||||
|   ~JACK() = default; | ||||
|   auto update() -> void; | ||||
|  | ||||
|   int                 bufSize(jack_nframes_t size); | ||||
|   int                 sampleRate(jack_nframes_t rate); | ||||
|   int                 xrun(); | ||||
|   void                shutdown(); | ||||
|   int bufSize(jack_nframes_t size); | ||||
|   int sampleRate(jack_nframes_t rate); | ||||
|   int xrun(); | ||||
|   void shutdown(); | ||||
|  | ||||
|  private: | ||||
|   std::string         JACKState(); | ||||
|   std::string JACKState(); | ||||
|  | ||||
|   jack_client_t*      client_; | ||||
|   jack_nframes_t      bufsize_; | ||||
|   jack_nframes_t      samplerate_; | ||||
|   unsigned int        xruns_; | ||||
|   float               load_; | ||||
|   bool                running_; | ||||
|   std::mutex          mutex_; | ||||
|   std::string         state_; | ||||
|   jack_client_t *client_; | ||||
|   jack_nframes_t bufsize_; | ||||
|   jack_nframes_t samplerate_; | ||||
|   unsigned int xruns_; | ||||
|   float load_; | ||||
|   bool running_; | ||||
|   std::mutex mutex_; | ||||
|   std::string state_; | ||||
|   util::SleeperThread thread_; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -5,12 +5,12 @@ | ||||
| #include <fstream> | ||||
| #include <unordered_map> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Memory : public ALabel { | ||||
| class Memory : public AButton { | ||||
|  public: | ||||
|   Memory(const std::string&, const Json::Value&); | ||||
|   ~Memory() = default; | ||||
|   | ||||
| @@ -7,12 +7,12 @@ | ||||
| #include <condition_variable> | ||||
| #include <thread> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "modules/mpd/state.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class MPD : public ALabel { | ||||
| class MPD : public AButton { | ||||
|   friend class detail::Context; | ||||
|  | ||||
|   // State machine | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
| #include <condition_variable> | ||||
| #include <thread> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
| class MPD; | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
|  | ||||
| #include <optional> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
| #ifdef WANT_RFKILL | ||||
| #include "util/rfkill.hpp" | ||||
| @@ -18,7 +18,7 @@ | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Network : public ALabel { | ||||
| class Network : public AButton { | ||||
|  public: | ||||
|   Network(const std::string&, const Json::Value&); | ||||
|   ~Network(); | ||||
|   | ||||
| @@ -7,11 +7,11 @@ | ||||
| #include <algorithm> | ||||
| #include <array> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Pulseaudio : public ALabel { | ||||
| class Pulseaudio : public AButton { | ||||
|  public: | ||||
|   Pulseaudio(const std::string&, const Json::Value&); | ||||
|   ~Pulseaudio(); | ||||
|   | ||||
| @@ -2,12 +2,12 @@ | ||||
|  | ||||
| #include <fmt/chrono.h> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Clock : public ALabel { | ||||
| class Clock : public AButton { | ||||
|  public: | ||||
|   Clock(const std::string&, const Json::Value&); | ||||
|   ~Clock() = default; | ||||
|   | ||||
| @@ -4,12 +4,12 @@ | ||||
|  | ||||
| #include <vector> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Sndio : public ALabel { | ||||
| class Sndio : public AButton { | ||||
|  public: | ||||
|   Sndio(const std::string &, const Json::Value &); | ||||
|   ~Sndio(); | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
| #include <map> | ||||
| #include <string> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "bar.hpp" | ||||
| #include "client.hpp" | ||||
| #include "modules/sway/ipc/client.hpp" | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| namespace waybar::modules::sway { | ||||
|  | ||||
| class Language : public ALabel, public sigc::trackable { | ||||
| class Language : public AButton, public sigc::trackable { | ||||
|  public: | ||||
|   Language(const std::string& id, const Json::Value& config); | ||||
|   ~Language() = default; | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| #include <fmt/format.h> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "bar.hpp" | ||||
| #include "client.hpp" | ||||
| #include "modules/sway/ipc/client.hpp" | ||||
| @@ -10,7 +10,7 @@ | ||||
|  | ||||
| namespace waybar::modules::sway { | ||||
|  | ||||
| class Mode : public ALabel, public sigc::trackable { | ||||
| class Mode : public AButton, public sigc::trackable { | ||||
|  public: | ||||
|   Mode(const std::string&, const Json::Value&); | ||||
|   ~Mode() = default; | ||||
|   | ||||
| @@ -4,12 +4,12 @@ | ||||
|  | ||||
| #include <fstream> | ||||
|  | ||||
| #include "ALabel.hpp" | ||||
| #include "AButton.hpp" | ||||
| #include "util/sleeper_thread.hpp" | ||||
|  | ||||
| namespace waybar::modules { | ||||
|  | ||||
| class Temperature : public ALabel { | ||||
| class Temperature : public AButton { | ||||
|  public: | ||||
|   Temperature(const std::string&, const Json::Value&); | ||||
|   ~Temperature() = default; | ||||
|   | ||||
| @@ -56,9 +56,10 @@ struct formatter<pow_format> { | ||||
|       fraction /= base; | ||||
|     } | ||||
|  | ||||
|     auto max_width = 4            // coeff in {:.3g} format | ||||
|                      + 1          // prefix from units array | ||||
|                      + s.binary_  // for the 'i' in GiB. | ||||
|     auto number_width = 5              // coeff in {:.1f} format | ||||
|                         + s.binary_;   // potential 4th digit before the decimal point | ||||
|     auto max_width = number_width + 1  // prefix from units array | ||||
|                      + s.binary_       // for the 'i' in GiB. | ||||
|                      + s.unit_.length(); | ||||
|  | ||||
|     const char* format; | ||||
| @@ -69,15 +70,16 @@ struct formatter<pow_format> { | ||||
|       case '<': | ||||
|         return format_to(ctx.out(), "{:<{}}", fmt::format("{}", s), max_width); | ||||
|       case '=': | ||||
|         format = "{coefficient:<4.3g}{padding}{prefix}{unit}"; | ||||
|         format = "{coefficient:<{number_width}.1f}{padding}{prefix}{unit}"; | ||||
|         break; | ||||
|       case 0: | ||||
|       default: | ||||
|         format = "{coefficient:.3g}{prefix}{unit}"; | ||||
|         format = "{coefficient:.1f}{prefix}{unit}"; | ||||
|         break; | ||||
|     } | ||||
|     return format_to( | ||||
|         ctx.out(), format, fmt::arg("coefficient", fraction), | ||||
|         fmt::arg("number_width", number_width), | ||||
|         fmt::arg("prefix", std::string() + units[pow] + ((s.binary_ && pow) ? "i" : "")), | ||||
|         fmt::arg("unit", s.unit_), | ||||
|         fmt::arg("padding", pow         ? "" | ||||
|   | ||||
							
								
								
									
										6
									
								
								include/util/sanitize_str.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								include/util/sanitize_str.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| #pragma once | ||||
| #include <string> | ||||
|  | ||||
| namespace waybar::util { | ||||
| std::string sanitize_string(std::string str); | ||||
| }  // namespace waybar::util | ||||
| @@ -63,6 +63,11 @@ screensaving, also known as "presentation mode". | ||||
| 	typeof: double ++ | ||||
| 	Threshold to be used when scrolling. | ||||
|  | ||||
| *start-activated*: ++ | ||||
|   typeof: bool ++ | ||||
|   default: *false* ++ | ||||
|   Whether the inhibit should be activated when starting waybar. | ||||
|  | ||||
| *timeout*: ++ | ||||
| 	typeof: double ++ | ||||
| 	The number of minutes the inhibit should last. | ||||
|   | ||||
| @@ -101,6 +101,10 @@ Additionally you can control the volume by scrolling *up* or *down* while the cu | ||||
| 	default: 100 ++ | ||||
| 	The maximum volume that can be set, in percentage. | ||||
|  | ||||
| *ignored-sinks*: ++ | ||||
| 	typeof: array ++ | ||||
| 	Sinks in this list will not be shown as the active sink by Waybar. Entries should be the sink's description field. | ||||
|  | ||||
| # FORMAT REPLACEMENTS | ||||
|  | ||||
| *{desc}*: Pulseaudio port's description, for bluetooth it'll be the device name. | ||||
|   | ||||
| @@ -143,6 +143,7 @@ endif | ||||
| src_files = files( | ||||
|     'src/factory.cpp', | ||||
|     'src/AModule.cpp', | ||||
|     'src/AButton.cpp', | ||||
|     'src/ALabel.cpp', | ||||
|     'src/AIconLabel.cpp', | ||||
|     'src/modules/custom.cpp', | ||||
| @@ -154,7 +155,8 @@ src_files = files( | ||||
|     'src/client.cpp', | ||||
|     'src/config.cpp', | ||||
|     'src/group.cpp', | ||||
|     'src/util/ustring_clen.cpp' | ||||
|     'src/util/ustring_clen.cpp', | ||||
|     'src/util/sanitize_str.cpp' | ||||
| ) | ||||
|  | ||||
| if is_linux | ||||
|   | ||||
| @@ -34,6 +34,12 @@ window#waybar.chromium { | ||||
|     border: none; | ||||
| } | ||||
|  | ||||
| /* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ | ||||
| button:hover { | ||||
|     background: inherit; | ||||
|     box-shadow: inset 0 -3px #ffffff; | ||||
| } | ||||
|  | ||||
| #workspaces button { | ||||
|     padding: 0 5px; | ||||
|     background-color: transparent; | ||||
| @@ -45,10 +51,8 @@ window#waybar.chromium { | ||||
|     border-radius: 0; | ||||
| } | ||||
|  | ||||
| /* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ | ||||
| #workspaces button:hover { | ||||
|     background: rgba(0, 0, 0, 0.2); | ||||
|     box-shadow: inset 0 -3px #ffffff; | ||||
| } | ||||
|  | ||||
| #workspaces button.focused { | ||||
|   | ||||
							
								
								
									
										154
									
								
								src/AButton.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								src/AButton.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,154 @@ | ||||
| #include "AButton.hpp" | ||||
|  | ||||
| #include <fmt/format.h> | ||||
|  | ||||
| #include <util/command.hpp> | ||||
|  | ||||
| namespace waybar { | ||||
|  | ||||
| AButton::AButton(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) | ||||
|     : AModule(config, name, id, config["format-alt"].isString() || enable_click, enable_scroll), | ||||
|       format_(config_["format"].isString() ? config_["format"].asString() : format), | ||||
|       interval_(config_["interval"] == "once" | ||||
|                     ? std::chrono::seconds(100000000) | ||||
|                     : std::chrono::seconds( | ||||
|                           config_["interval"].isUInt() ? config_["interval"].asUInt() : interval)), | ||||
|       default_format_(format_) { | ||||
|   button_.set_name(name); | ||||
|   button_.set_relief(Gtk::RELIEF_NONE); | ||||
|   if (!id.empty()) { | ||||
|     button_.get_style_context()->add_class(id); | ||||
|   } | ||||
|   event_box_.add(button_); | ||||
|   if (config_["max-length"].isUInt()) { | ||||
|     label_->set_max_width_chars(config_["max-length"].asInt()); | ||||
|     label_->set_ellipsize(Pango::EllipsizeMode::ELLIPSIZE_END); | ||||
|     label_->set_single_line_mode(true); | ||||
|   } else if (ellipsize && label_->get_max_width_chars() == -1) { | ||||
|     label_->set_ellipsize(Pango::EllipsizeMode::ELLIPSIZE_END); | ||||
|     label_->set_single_line_mode(true); | ||||
|   } | ||||
|  | ||||
|   if (config_["min-length"].isUInt()) { | ||||
|     label_->set_width_chars(config_["min-length"].asUInt()); | ||||
|   } | ||||
|  | ||||
|   uint rotate = 0; | ||||
|  | ||||
|   if (config_["rotate"].isUInt()) { | ||||
|     rotate = config["rotate"].asUInt(); | ||||
|     label_->set_angle(rotate); | ||||
|   } | ||||
|  | ||||
|   if (config_["align"].isDouble()) { | ||||
|     auto align = config_["align"].asFloat(); | ||||
|     if (rotate == 90 || rotate == 270) { | ||||
|       label_->set_yalign(align); | ||||
|     } else { | ||||
|       label_->set_xalign(align); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   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() || config_["format-alt"].isString() || enable_click)) { | ||||
|     button_.set_sensitive(false); | ||||
|   } else { | ||||
|     button_.signal_pressed().connect([this] { | ||||
|       GdkEventButton* e = (GdkEventButton*)gdk_event_new(GDK_BUTTON_PRESS); | ||||
|       e->button = 1; | ||||
|       handleToggle(e); | ||||
|     }); | ||||
|   } | ||||
| } | ||||
|  | ||||
| auto AButton::update() -> void { AModule::update(); } | ||||
|  | ||||
| std::string AButton::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())) { | ||||
|       format_icons = format_icons[alt]; | ||||
|     } else { | ||||
|       format_icons = format_icons["default"]; | ||||
|     } | ||||
|   } | ||||
|   if (format_icons.isArray()) { | ||||
|     auto size = format_icons.size(); | ||||
|     auto idx = std::clamp(percentage / ((max == 0 ? 100 : max) / size), 0U, size - 1); | ||||
|     format_icons = format_icons[idx]; | ||||
|   } | ||||
|   if (format_icons.isString()) { | ||||
|     return format_icons.asString(); | ||||
|   } | ||||
|   return ""; | ||||
| } | ||||
|  | ||||
| std::string AButton::getIcon(uint16_t percentage, const std::vector<std::string>& alts, | ||||
|                              uint16_t max) { | ||||
|   auto format_icons = config_["format-icons"]; | ||||
|   if (format_icons.isObject()) { | ||||
|     std::string _alt = "default"; | ||||
|     for (const auto& alt : alts) { | ||||
|       if (!alt.empty() && (format_icons[alt].isString() || format_icons[alt].isArray())) { | ||||
|         _alt = alt; | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     format_icons = format_icons[_alt]; | ||||
|   } | ||||
|   if (format_icons.isArray()) { | ||||
|     auto size = format_icons.size(); | ||||
|     auto idx = std::clamp(percentage / ((max == 0 ? 100 : max) / size), 0U, size - 1); | ||||
|     format_icons = format_icons[idx]; | ||||
|   } | ||||
|   if (format_icons.isString()) { | ||||
|     return format_icons.asString(); | ||||
|   } | ||||
|   return ""; | ||||
| } | ||||
|  | ||||
| bool waybar::AButton::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 AButton::getState(uint8_t value, bool lesser) { | ||||
|   if (!config_["states"].isObject()) { | ||||
|     return ""; | ||||
|   } | ||||
|   // Get current state | ||||
|   std::vector<std::pair<std::string, uint8_t>> states; | ||||
|   if (config_["states"].isObject()) { | ||||
|     for (auto it = config_["states"].begin(); it != config_["states"].end(); ++it) { | ||||
|       if (it->isUInt() && it.key().isString()) { | ||||
|         states.emplace_back(it.key().asString(), it->asUInt()); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   // Sort states | ||||
|   std::sort(states.begin(), states.end(), [&lesser](auto& a, auto& b) { | ||||
|     return lesser ? a.second < b.second : a.second > b.second; | ||||
|   }); | ||||
|   std::string valid_state; | ||||
|   for (auto const& state : states) { | ||||
|     if ((lesser ? value <= state.second : value >= state.second) && valid_state.empty()) { | ||||
|       button_.get_style_context()->add_class(state.first); | ||||
|       valid_state = state.first; | ||||
|     } else { | ||||
|       button_.get_style_context()->remove_class(state.first); | ||||
|     } | ||||
|   } | ||||
|   return valid_state; | ||||
| } | ||||
|  | ||||
| }  // namespace waybar | ||||
| @@ -87,7 +87,7 @@ int waybar::modules::Backlight::BacklightDev::get_max() const { return max_; } | ||||
| void waybar::modules::Backlight::BacklightDev::set_max(int max) { max_ = max; } | ||||
|  | ||||
| waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value &config) | ||||
|     : ALabel(config, "backlight", id, "{percent}%", 2), | ||||
|     : AButton(config, "backlight", id, "{percent}%", 2), | ||||
|       preferred_device_(config["device"].isString() ? config["device"].asString() : "") { | ||||
|   // Get initial state | ||||
|   { | ||||
| @@ -174,19 +174,19 @@ auto waybar::modules::Backlight::update() -> void { | ||||
|  | ||||
|     const uint8_t percent = | ||||
|         best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max()); | ||||
|     label_.set_markup(fmt::format(format_, fmt::arg("percent", std::to_string(percent)), | ||||
|                                   fmt::arg("icon", getIcon(percent)))); | ||||
|     label_->set_markup(fmt::format(format_, fmt::arg("percent", std::to_string(percent)), | ||||
|                                    fmt::arg("icon", getIcon(percent)))); | ||||
|     getState(percent); | ||||
|   } else { | ||||
|     if (!previous_best_.has_value()) { | ||||
|       return; | ||||
|     } | ||||
|     label_.set_markup(""); | ||||
|     label_->set_markup(""); | ||||
|   } | ||||
|   previous_best_ = best == nullptr ? std::nullopt : std::optional{*best}; | ||||
|   previous_format_ = format_; | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| template <class ForwardIt> | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| #include <spdlog/spdlog.h> | ||||
|  | ||||
| waybar::modules::Battery::Battery(const std::string& id, const Json::Value& config) | ||||
|     : ALabel(config, "battery", id, "{capacity}%", 60) { | ||||
|     : AButton(config, "battery", id, "{capacity}%", 60) { | ||||
|   battery_watch_fd_ = inotify_init1(IN_CLOEXEC); | ||||
|   if (battery_watch_fd_ == -1) { | ||||
|     throw std::runtime_error("Unable to listen batteries."); | ||||
| @@ -108,7 +108,7 @@ void waybar::modules::Battery::refreshBatteries() { | ||||
|       } | ||||
|       auto adap_defined = config_["adapter"].isString(); | ||||
|       if (((adap_defined && dir_name == config_["adapter"].asString()) || !adap_defined) && | ||||
|           fs::exists(node.path() / "online")) { | ||||
|           (fs::exists(node.path() / "online") || fs::exists(node.path() / "status"))) { | ||||
|         adapter_ = node.path(); | ||||
|       } | ||||
|     } | ||||
| @@ -156,124 +156,305 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g | ||||
|   std::lock_guard<std::mutex> guard(battery_list_mutex_); | ||||
|  | ||||
|   try { | ||||
|     uint32_t total_power = 0;   // μW | ||||
|     uint32_t total_power = 0;  // μW | ||||
|     bool total_power_exists = false; | ||||
|     uint32_t total_energy = 0;  // μWh | ||||
|     bool total_energy_exists = false; | ||||
|     uint32_t total_energy_full = 0; | ||||
|     bool total_energy_full_exists = false; | ||||
|     uint32_t total_energy_full_design = 0; | ||||
|     uint32_t total_capacity{0}; | ||||
|     bool total_energy_full_design_exists = false; | ||||
|     uint32_t total_capacity = 0; | ||||
|     bool total_capacity_exists = false; | ||||
|  | ||||
|     std::string status = "Unknown"; | ||||
|     for (auto const& item : batteries_) { | ||||
|       auto bat = item.first; | ||||
|       uint32_t power_now; | ||||
|       uint32_t energy_full; | ||||
|       uint32_t energy_now; | ||||
|       uint32_t energy_full_design; | ||||
|       uint32_t capacity{0}; | ||||
|       std::string _status; | ||||
|       std::getline(std::ifstream(bat / "status"), _status); | ||||
|  | ||||
|       // Some battery will report current and charge in μA/μAh. | ||||
|       // Scale these by the voltage to get μW/μWh. | ||||
|       if (fs::exists(bat / "current_now") || fs::exists(bat / "current_avg")) { | ||||
|         uint32_t voltage_now; | ||||
|         uint32_t current_now; | ||||
|         uint32_t charge_now; | ||||
|         uint32_t charge_full; | ||||
|         uint32_t charge_full_design; | ||||
|         // Some batteries have only *_avg, not *_now | ||||
|         if (fs::exists(bat / "voltage_now")) | ||||
|           std::ifstream(bat / "voltage_now") >> voltage_now; | ||||
|         else | ||||
|           std::ifstream(bat / "voltage_avg") >> voltage_now; | ||||
|         if (fs::exists(bat / "current_now")) | ||||
|           std::ifstream(bat / "current_now") >> current_now; | ||||
|         else | ||||
|           std::ifstream(bat / "current_avg") >> current_now; | ||||
|         std::ifstream(bat / "charge_full") >> charge_full; | ||||
|         std::ifstream(bat / "charge_full_design") >> charge_full_design; | ||||
|         if (fs::exists(bat / "charge_now")) | ||||
|           std::ifstream(bat / "charge_now") >> charge_now; | ||||
|         else { | ||||
|           // charge_now is missing on some systems, estimate using capacity. | ||||
|           uint32_t capacity; | ||||
|           std::ifstream(bat / "capacity") >> capacity; | ||||
|           charge_now = (capacity * charge_full) / 100; | ||||
|         } | ||||
|         power_now = ((uint64_t)current_now * (uint64_t)voltage_now) / 1000000; | ||||
|         energy_now = ((uint64_t)charge_now * (uint64_t)voltage_now) / 1000000; | ||||
|         energy_full = ((uint64_t)charge_full * (uint64_t)voltage_now) / 1000000; | ||||
|         energy_full_design = ((uint64_t)charge_full_design * (uint64_t)voltage_now) / 1000000; | ||||
|       }  // Gamepads such as PS Dualshock provide the only capacity | ||||
|       else if (fs::exists(bat / "energy_now") && fs::exists(bat / "energy_full")) { | ||||
|         std::ifstream(bat / "power_now") >> power_now; | ||||
|         std::ifstream(bat / "energy_now") >> energy_now; | ||||
|         std::ifstream(bat / "energy_full") >> energy_full; | ||||
|         std::ifstream(bat / "energy_full_design") >> energy_full_design; | ||||
|       } else { | ||||
|  | ||||
|       uint32_t capacity = 0; | ||||
|       bool capacity_exists = false; | ||||
|       if (fs::exists(bat / "capacity")) { | ||||
|         capacity_exists = true; | ||||
|         std::ifstream(bat / "capacity") >> capacity; | ||||
|         power_now = 0; | ||||
|         energy_now = 0; | ||||
|         energy_full = 0; | ||||
|         energy_full_design = 0; | ||||
|       } | ||||
|  | ||||
|       uint32_t current_now = 0; | ||||
|       bool current_now_exists = false; | ||||
|       if (fs::exists(bat / "current_now")) { | ||||
|         current_now_exists = true; | ||||
|         std::ifstream(bat / "current_now") >> current_now; | ||||
|       } else if (fs::exists(bat / "current_avg")) { | ||||
|         current_now_exists = true; | ||||
|         std::ifstream(bat / "current_avg") >> current_now; | ||||
|       } | ||||
|  | ||||
|       uint32_t voltage_now = 0; | ||||
|       bool voltage_now_exists = false; | ||||
|       if (fs::exists(bat / "voltage_now")) { | ||||
|         voltage_now_exists = true; | ||||
|         std::ifstream(bat / "voltage_now") >> voltage_now; | ||||
|       } else if (fs::exists(bat / "voltage_avg")) { | ||||
|         voltage_now_exists = true; | ||||
|         std::ifstream(bat / "voltage_avg") >> voltage_now; | ||||
|       } | ||||
|  | ||||
|       uint32_t charge_full = 0; | ||||
|       bool charge_full_exists = false; | ||||
|       if (fs::exists(bat / "charge_full")) { | ||||
|         charge_full_exists = true; | ||||
|         std::ifstream(bat / "charge_full") >> charge_full; | ||||
|       } | ||||
|  | ||||
|       uint32_t charge_full_design = 0; | ||||
|       bool charge_full_design_exists = false; | ||||
|       if (fs::exists(bat / "charge_full_design")) { | ||||
|         charge_full_design_exists = true; | ||||
|         std::ifstream(bat / "charge_full_design") >> charge_full_design; | ||||
|       } | ||||
|  | ||||
|       uint32_t charge_now = 0; | ||||
|       bool charge_now_exists = false; | ||||
|       if (fs::exists(bat / "charge_now")) { | ||||
|         charge_now_exists = true; | ||||
|         std::ifstream(bat / "charge_now") >> charge_now; | ||||
|       } | ||||
|  | ||||
|       uint32_t power_now = 0; | ||||
|       bool power_now_exists = false; | ||||
|       if (fs::exists(bat / "power_now")) { | ||||
|         power_now_exists = true; | ||||
|         std::ifstream(bat / "power_now") >> power_now; | ||||
|       } | ||||
|  | ||||
|       uint32_t energy_now = 0; | ||||
|       bool energy_now_exists = false; | ||||
|       if (fs::exists(bat / "energy_now")) { | ||||
|         energy_now_exists = true; | ||||
|         std::ifstream(bat / "energy_now") >> energy_now; | ||||
|       } | ||||
|  | ||||
|       uint32_t energy_full = 0; | ||||
|       bool energy_full_exists = false; | ||||
|       if (fs::exists(bat / "energy_full")) { | ||||
|         energy_full_exists = true; | ||||
|         std::ifstream(bat / "energy_full") >> energy_full; | ||||
|       } | ||||
|  | ||||
|       uint32_t energy_full_design = 0; | ||||
|       bool energy_full_design_exists = false; | ||||
|       if (fs::exists(bat / "energy_full_design")) { | ||||
|         energy_full_design_exists = true; | ||||
|         std::ifstream(bat / "energy_full_design") >> energy_full_design; | ||||
|       } | ||||
|  | ||||
|       if (!voltage_now_exists) { | ||||
|         if (power_now_exists && current_now_exists && current_now != 0) { | ||||
|           voltage_now_exists = true; | ||||
|           voltage_now = 1000000 * (uint64_t)power_now / (uint64_t)current_now; | ||||
|         } else if (energy_full_design_exists && charge_full_design_exists && | ||||
|                    charge_full_design != 0) { | ||||
|           voltage_now_exists = true; | ||||
|           voltage_now = 1000000 * (uint64_t)energy_full_design / (uint64_t)charge_full_design; | ||||
|         } else if (energy_now_exists) { | ||||
|           if (charge_now_exists && charge_now != 0) { | ||||
|             voltage_now_exists = true; | ||||
|             voltage_now = 1000000 * (uint64_t)energy_now / (uint64_t)charge_now; | ||||
|           } else if (capacity_exists && charge_full_exists) { | ||||
|             charge_now_exists = true; | ||||
|             charge_now = (uint64_t)charge_full * (uint64_t)capacity / 100; | ||||
|             if (charge_full != 0 && capacity != 0) { | ||||
|               voltage_now_exists = true; | ||||
|               voltage_now = | ||||
|                   1000000 * (uint64_t)energy_now * 100 / (uint64_t)charge_full / (uint64_t)capacity; | ||||
|             } | ||||
|           } | ||||
|         } else if (energy_full_exists) { | ||||
|           if (charge_full_exists && charge_full != 0) { | ||||
|             voltage_now_exists = true; | ||||
|             voltage_now = 1000000 * (uint64_t)energy_full / (uint64_t)charge_full; | ||||
|           } else if (charge_now_exists && capacity_exists) { | ||||
|             if (capacity != 0) { | ||||
|               charge_full_exists = true; | ||||
|               charge_full = 100 * (uint64_t)charge_now / (uint64_t)capacity; | ||||
|             } | ||||
|             if (charge_now != 0) { | ||||
|               voltage_now_exists = true; | ||||
|               voltage_now = | ||||
|                   10000 * (uint64_t)energy_full * (uint64_t)capacity / (uint64_t)charge_now; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (!capacity_exists) { | ||||
|         if (charge_now_exists && charge_full_exists && charge_full != 0) { | ||||
|           capacity_exists = true; | ||||
|           capacity = 100 * (uint64_t)charge_now / (uint64_t)charge_full; | ||||
|         } else if (energy_now_exists && energy_full_exists && energy_full != 0) { | ||||
|           capacity_exists = true; | ||||
|           capacity = 100 * (uint64_t)energy_now / (uint64_t)energy_full; | ||||
|         } else if (charge_now_exists && energy_full_exists && voltage_now_exists) { | ||||
|           if (!charge_full_exists && voltage_now != 0) { | ||||
|             charge_full_exists = true; | ||||
|             charge_full = 1000000 * (uint64_t)energy_full / (uint64_t)voltage_now; | ||||
|           } | ||||
|           if (energy_full != 0) { | ||||
|             capacity_exists = true; | ||||
|             capacity = (uint64_t)charge_now * (uint64_t)voltage_now / 10000 / (uint64_t)energy_full; | ||||
|           } | ||||
|         } else if (charge_full_exists && energy_now_exists && voltage_now_exists) { | ||||
|           if (!charge_now_exists && voltage_now != 0) { | ||||
|             charge_now_exists = true; | ||||
|             charge_now = 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now; | ||||
|           } | ||||
|           if (voltage_now != 0 && charge_full != 0) { | ||||
|             capacity_exists = true; | ||||
|             capacity = 100 * 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now / | ||||
|                        (uint64_t)charge_full; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (!energy_now_exists && voltage_now_exists) { | ||||
|         if (charge_now_exists) { | ||||
|           energy_now_exists = true; | ||||
|           energy_now = (uint64_t)charge_now * (uint64_t)voltage_now / 1000000; | ||||
|         } else if (capacity_exists && charge_full_exists) { | ||||
|           charge_now_exists = true; | ||||
|           charge_now = (uint64_t)capacity * (uint64_t)charge_full / 100; | ||||
|           energy_now_exists = true; | ||||
|           energy_now = | ||||
|               (uint64_t)voltage_now * (uint64_t)capacity * (uint64_t)charge_full / 1000000 / 100; | ||||
|         } else if (capacity_exists && energy_full) { | ||||
|           if (voltage_now != 0) { | ||||
|             charge_full_exists = true; | ||||
|             charge_full = 1000000 * (uint64_t)energy_full / (uint64_t)voltage_now; | ||||
|             charge_now_exists = true; | ||||
|             charge_now = (uint64_t)capacity * 10000 * (uint64_t)energy_full / (uint64_t)voltage_now; | ||||
|           } | ||||
|           energy_now_exists = true; | ||||
|           energy_now = (uint64_t)capacity * (uint64_t)energy_full / 100; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (!energy_full_exists && voltage_now_exists) { | ||||
|         if (charge_full_exists) { | ||||
|           energy_full_exists = true; | ||||
|           energy_full = (uint64_t)charge_full * (uint64_t)voltage_now / 1000000; | ||||
|         } else if (charge_now_exists && capacity_exists && capacity != 0) { | ||||
|           charge_full_exists = true; | ||||
|           charge_full = 100 * (uint64_t)charge_now / (uint64_t)capacity; | ||||
|           energy_full_exists = true; | ||||
|           energy_full = (uint64_t)charge_now * (uint64_t)voltage_now / (uint64_t)capacity / 10000; | ||||
|         } else if (capacity_exists && energy_now) { | ||||
|           if (voltage_now != 0) { | ||||
|             charge_now_exists = true; | ||||
|             charge_now = 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now; | ||||
|           } | ||||
|           if (capacity != 0) { | ||||
|             energy_full_exists = true; | ||||
|             energy_full = 100 * (uint64_t)energy_now / (uint64_t)capacity; | ||||
|             if (voltage_now != 0) { | ||||
|               charge_full_exists = true; | ||||
|               charge_full = | ||||
|                   100 * 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now / (uint64_t)capacity; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (!power_now_exists && voltage_now_exists && current_now_exists) { | ||||
|         power_now_exists = true; | ||||
|         power_now = (uint64_t)voltage_now * (uint64_t)current_now / 1000000; | ||||
|       } | ||||
|  | ||||
|       if (!energy_full_design_exists && voltage_now_exists && charge_full_design_exists) { | ||||
|         energy_full_design_exists = true; | ||||
|         energy_full_design = (uint64_t)voltage_now * (uint64_t)charge_full_design / 1000000; | ||||
|       } | ||||
|  | ||||
|       // Show the "smallest" status among all batteries | ||||
|       if (status_gt(status, _status)) { | ||||
|         status = _status; | ||||
|       if (status_gt(status, _status)) status = _status; | ||||
|  | ||||
|       if (power_now_exists) { | ||||
|         total_power_exists = true; | ||||
|         total_power += power_now; | ||||
|       } | ||||
|       if (energy_now_exists) { | ||||
|         total_energy_exists = true; | ||||
|         total_energy += energy_now; | ||||
|       } | ||||
|       if (energy_full_exists) { | ||||
|         total_energy_full_exists = true; | ||||
|         total_energy_full += energy_full; | ||||
|       } | ||||
|       if (energy_full_design_exists) { | ||||
|         total_energy_full_design_exists = true; | ||||
|         total_energy_full_design += energy_full_design; | ||||
|       } | ||||
|       if (capacity_exists) { | ||||
|         total_capacity_exists = true; | ||||
|         total_capacity += capacity; | ||||
|       } | ||||
|       total_power += power_now; | ||||
|       total_energy += energy_now; | ||||
|       total_energy_full += energy_full; | ||||
|       total_energy_full_design += energy_full_design; | ||||
|       total_capacity += capacity; | ||||
|     } | ||||
|  | ||||
|     if (!adapter_.empty() && status == "Discharging") { | ||||
|       bool online; | ||||
|       std::string current_status; | ||||
|       std::ifstream(adapter_ / "online") >> online; | ||||
|       if (online) { | ||||
|         status = "Plugged"; | ||||
|       std::getline(std::ifstream(adapter_ / "status"), current_status); | ||||
|       if (online && current_status != "Discharging") status = "Plugged"; | ||||
|     } | ||||
|  | ||||
|     float time_remaining{0.0f}; | ||||
|     if (status == "Discharging" && total_power_exists && total_energy_exists) { | ||||
|       if (total_power != 0) time_remaining = (float)total_energy / total_power; | ||||
|     } else if (status == "Charging" && total_energy_exists && total_energy_full_exists && | ||||
|                total_power_exists) { | ||||
|       if (total_power != 0) | ||||
|         time_remaining = -(float)(total_energy_full - total_energy) / total_power; | ||||
|       // If we've turned positive it means the battery is past 100% and so just report that as no | ||||
|       // time remaining | ||||
|       if (time_remaining > 0.0f) time_remaining = 0.0f; | ||||
|     } | ||||
|  | ||||
|     float calculated_capacity{0.0f}; | ||||
|     if (total_capacity_exists) { | ||||
|       if (total_capacity > 0.0f) | ||||
|         calculated_capacity = (float)total_capacity; | ||||
|       else if (total_energy_full_exists && total_energy_exists) { | ||||
|         if (total_energy_full > 0.0f) | ||||
|           calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full); | ||||
|       } | ||||
|     } | ||||
|     float time_remaining = 0; | ||||
|     if (status == "Discharging" && total_power != 0) { | ||||
|       time_remaining = (float)total_energy / total_power; | ||||
|     } else if (status == "Charging" && total_power != 0) { | ||||
|       time_remaining = -(float)(total_energy_full - total_energy) / total_power; | ||||
|       if (time_remaining > 0.0f) { | ||||
|         // If we've turned positive it means the battery is past 100% and so | ||||
|         // just report that as no time remaining | ||||
|         time_remaining = 0.0f; | ||||
|       } | ||||
|     } | ||||
|     float capacity{0.0f}; | ||||
|     if (total_energy_full > 0.0f) { | ||||
|       capacity = ((float)total_energy * 100.0f / (float)total_energy_full); | ||||
|     } else { | ||||
|       capacity = (float)total_capacity; | ||||
|     } | ||||
|  | ||||
|     // Handle design-capacity | ||||
|     if (config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) { | ||||
|       capacity = ((float)total_energy * 100.0f / (float)total_energy_full_design); | ||||
|     if ((config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) && | ||||
|         total_energy_exists && total_energy_full_design_exists) { | ||||
|       if (total_energy_full_design > 0.0f) | ||||
|         calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full_design); | ||||
|     } | ||||
|  | ||||
|     // Handle full-at | ||||
|     if (config_["full-at"].isUInt()) { | ||||
|       auto full_at = config_["full-at"].asUInt(); | ||||
|       if (full_at < 100) { | ||||
|         capacity = 100.f * capacity / full_at; | ||||
|       } | ||||
|     } | ||||
|     if (capacity > 100.f) { | ||||
|       // This can happen when the battery is calibrating and goes above 100% | ||||
|       // Handle it gracefully by clamping at 100% | ||||
|       capacity = 100.f; | ||||
|     } | ||||
|     uint8_t cap = round(capacity); | ||||
|     if (cap == 100 && status == "Charging") { | ||||
|       // If we've reached 100% just mark as full as some batteries can stay | ||||
|       // stuck reporting they're still charging but not yet done | ||||
|       status = "Full"; | ||||
|       if (full_at < 100) calculated_capacity = 100.f * calculated_capacity / full_at; | ||||
|     } | ||||
|  | ||||
|     // Handle it gracefully by clamping at 100% | ||||
|     // This can happen when the battery is calibrating and goes above 100% | ||||
|     if (calculated_capacity > 100.f) calculated_capacity = 100.f; | ||||
|  | ||||
|     uint8_t cap = round(calculated_capacity); | ||||
|     // If we've reached 100% just mark as full as some batteries can stay stuck reporting they're | ||||
|     // still charging but not yet done | ||||
|     if (cap == 100 && status == "Charging") status = "Full"; | ||||
|  | ||||
|     return {cap, time_remaining, status, total_power / 1e6}; | ||||
|   } catch (const std::exception& e) { | ||||
|     spdlog::error("Battery: {}", e.what()); | ||||
| @@ -284,11 +465,13 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g | ||||
| const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) const { | ||||
|   if (!adapter_.empty()) { | ||||
|     bool online; | ||||
|     std::string status; | ||||
|     std::ifstream(adapter_ / "online") >> online; | ||||
|     std::getline(std::ifstream(adapter_ / "status"), status); | ||||
|     if (capacity == 100) { | ||||
|       return "Full"; | ||||
|     } | ||||
|     if (online) { | ||||
|     if (online && status != "Discharging") { | ||||
|       return "Plugged"; | ||||
|     } | ||||
|     return "Discharging"; | ||||
| @@ -309,7 +492,8 @@ const std::string waybar::modules::Battery::formatTimeRemaining(float hoursRemai | ||||
|     format = config_["format-time"].asString(); | ||||
|   } | ||||
|   std::string zero_pad_minutes = fmt::format("{:02d}", minutes); | ||||
|   return fmt::format(format, fmt::arg("H", full_hours), fmt::arg("M", minutes), fmt::arg("m", zero_pad_minutes)); | ||||
|   return fmt::format(format, fmt::arg("H", full_hours), fmt::arg("M", minutes), | ||||
|                      fmt::arg("m", zero_pad_minutes)); | ||||
| } | ||||
|  | ||||
| auto waybar::modules::Battery::update() -> void { | ||||
| @@ -346,14 +530,14 @@ auto waybar::modules::Battery::update() -> void { | ||||
|     } else if (config_["tooltip-format"].isString()) { | ||||
|       tooltip_format = config_["tooltip-format"].asString(); | ||||
|     } | ||||
|     label_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("timeTo", tooltip_text_default), | ||||
|                                         fmt::arg("capacity", capacity), | ||||
|                                         fmt::arg("time", time_remaining_formatted))); | ||||
|     button_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("timeTo", tooltip_text_default), | ||||
|                                          fmt::arg("capacity", capacity), | ||||
|                                          fmt::arg("time", time_remaining_formatted))); | ||||
|   } | ||||
|   if (!old_status_.empty()) { | ||||
|     label_.get_style_context()->remove_class(old_status_); | ||||
|     button_.get_style_context()->remove_class(old_status_); | ||||
|   } | ||||
|   label_.get_style_context()->add_class(status); | ||||
|   button_.get_style_context()->add_class(status); | ||||
|   old_status_ = status; | ||||
|   if (!state.empty() && config_["format-" + status + "-" + state].isString()) { | ||||
|     format = config_["format-" + status + "-" + state].asString(); | ||||
| @@ -367,10 +551,10 @@ auto waybar::modules::Battery::update() -> void { | ||||
|   } else { | ||||
|     event_box_.show(); | ||||
|     auto icons = std::vector<std::string>{status + "-" + state, status, state}; | ||||
|     label_.set_markup(fmt::format(format, fmt::arg("capacity", capacity), fmt::arg("power", power), | ||||
|                                   fmt::arg("icon", getIcon(capacity, icons)), | ||||
|                                   fmt::arg("time", time_remaining_formatted))); | ||||
|     label_->set_markup(fmt::format(format, fmt::arg("capacity", capacity), fmt::arg("power", power), | ||||
|                                    fmt::arg("icon", getIcon(capacity, icons)), | ||||
|                                    fmt::arg("time", time_remaining_formatted))); | ||||
|   } | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|   | ||||
| @@ -80,7 +80,7 @@ auto getUcharProperty(GDBusProxy* proxy, const char* property_name) -> unsigned | ||||
| }  // namespace | ||||
|  | ||||
| waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& config) | ||||
|     : ALabel(config, "bluetooth", id, " {status}", 10), | ||||
|     : AButton(config, "bluetooth", id, " {status}", 10), | ||||
| #ifdef WANT_RFKILL | ||||
|       rfkill_{RFKILL_TYPE_BLUETOOTH}, | ||||
| #endif | ||||
| @@ -189,10 +189,10 @@ auto waybar::modules::Bluetooth::update() -> void { | ||||
|   format_.empty() ? event_box_.hide() : event_box_.show(); | ||||
|  | ||||
|   auto update_style_context = [this](const std::string& style_class, bool in_next_state) { | ||||
|     if (in_next_state && !label_.get_style_context()->has_class(style_class)) { | ||||
|       label_.get_style_context()->add_class(style_class); | ||||
|     } else if (!in_next_state && label_.get_style_context()->has_class(style_class)) { | ||||
|       label_.get_style_context()->remove_class(style_class); | ||||
|     if (in_next_state && !button_.get_style_context()->has_class(style_class)) { | ||||
|       button_.get_style_context()->add_class(style_class); | ||||
|     } else if (!in_next_state && button_.get_style_context()->has_class(style_class)) { | ||||
|       button_.get_style_context()->remove_class(style_class); | ||||
|     } | ||||
|   }; | ||||
|   update_style_context("discoverable", cur_controller_.discoverable); | ||||
| @@ -204,7 +204,7 @@ auto waybar::modules::Bluetooth::update() -> void { | ||||
|   update_style_context(state, true); | ||||
|   state_ = state; | ||||
|  | ||||
|   label_.set_markup(fmt::format( | ||||
|   label_->set_markup(fmt::format( | ||||
|       format_, fmt::arg("status", state_), fmt::arg("num_connections", connected_devices_.size()), | ||||
|       fmt::arg("controller_address", cur_controller_.address), | ||||
|       fmt::arg("controller_address_type", cur_controller_.address_type), | ||||
| @@ -245,7 +245,7 @@ auto waybar::modules::Bluetooth::update() -> void { | ||||
|         device_enumerate_.erase(0, 1); | ||||
|       } | ||||
|     } | ||||
|     label_.set_tooltip_text(fmt::format( | ||||
|     button_.set_tooltip_text(fmt::format( | ||||
|         tooltip_format, fmt::arg("status", state_), | ||||
|         fmt::arg("num_connections", connected_devices_.size()), | ||||
|         fmt::arg("controller_address", cur_controller_.address), | ||||
| @@ -259,7 +259,7 @@ auto waybar::modules::Bluetooth::update() -> void { | ||||
|   } | ||||
|  | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| // NOTE: only for when the org.bluez.Battery1 interface is added/removed after/before a device is | ||||
|   | ||||
| @@ -18,7 +18,7 @@ | ||||
| using waybar::waybar_time; | ||||
|  | ||||
| waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) | ||||
|     : ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true), | ||||
|     : AButton(config, "clock", id, "{:%H:%M}", 60, false, false, true), | ||||
|       current_time_zone_idx_(0), | ||||
|       is_calendar_in_tooltip_(false), | ||||
|       is_timezoned_list_in_tooltip_(false) { | ||||
| @@ -107,7 +107,7 @@ auto waybar::modules::Clock::update() -> void { | ||||
|   } else { | ||||
|     text = fmt::format(format_, wtime); | ||||
|   } | ||||
|   label_.set_markup(text); | ||||
|   label_->set_markup(text); | ||||
|  | ||||
|   if (tooltipEnabled()) { | ||||
|     if (config_["tooltip-format"].isString()) { | ||||
| @@ -119,12 +119,12 @@ auto waybar::modules::Clock::update() -> void { | ||||
|       text = | ||||
|           fmt::format(tooltip_format, wtime, fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines), | ||||
|                       fmt::arg(KTimezonedTimeListPlaceholder.c_str(), timezoned_time_lines)); | ||||
|       label_.set_tooltip_markup(text); | ||||
|       button_.set_tooltip_markup(text); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| bool waybar::modules::Clock::handleScroll(GdkEventScroll* e) { | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
| #endif | ||||
|  | ||||
| waybar::modules::Cpu::Cpu(const std::string& id, const Json::Value& config) | ||||
|     : ALabel(config, "cpu", id, "{usage}%", 10) { | ||||
|     : AButton(config, "cpu", id, "{usage}%", 10) { | ||||
|   thread_ = [this] { | ||||
|     dp.emit(); | ||||
|     thread_.sleep_for(interval_); | ||||
| @@ -23,7 +23,7 @@ auto waybar::modules::Cpu::update() -> void { | ||||
|   auto [cpu_usage, tooltip] = getCpuUsage(); | ||||
|   auto [max_frequency, min_frequency, avg_frequency] = getCpuFrequency(); | ||||
|   if (tooltipEnabled()) { | ||||
|     label_.set_tooltip_text(tooltip); | ||||
|     button_.set_tooltip_text(tooltip); | ||||
|   } | ||||
|   auto format = format_; | ||||
|   auto total_usage = cpu_usage.empty() ? 0 : cpu_usage[0]; | ||||
| @@ -52,11 +52,11 @@ auto waybar::modules::Cpu::update() -> void { | ||||
|       auto icon_format = fmt::format("icon{}", core_i); | ||||
|       store.push_back(fmt::arg(icon_format.c_str(), getIcon(cpu_usage[i], icons))); | ||||
|     } | ||||
|     label_.set_markup(fmt::vformat(format, store)); | ||||
|     label_->set_markup(fmt::vformat(format, store)); | ||||
|   } | ||||
|  | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| double waybar::modules::Cpu::getCpuLoad() { | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
|  | ||||
| waybar::modules::Custom::Custom(const std::string& name, const std::string& id, | ||||
|                                 const Json::Value& config) | ||||
|     : ALabel(config, "custom-" + name, id, "{}"), | ||||
|     : AButton(config, "custom-" + name, id, "{}"), | ||||
|       name_(name), | ||||
|       id_(id), | ||||
|       percentage_(0), | ||||
| @@ -103,13 +103,13 @@ void waybar::modules::Custom::handleEvent() { | ||||
| } | ||||
|  | ||||
| bool waybar::modules::Custom::handleScroll(GdkEventScroll* e) { | ||||
|   auto ret = ALabel::handleScroll(e); | ||||
|   auto ret = AButton::handleScroll(e); | ||||
|   handleEvent(); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| bool waybar::modules::Custom::handleToggle(GdkEventButton* const& e) { | ||||
|   auto ret = ALabel::handleToggle(e); | ||||
|   auto ret = AButton::handleToggle(e); | ||||
|   handleEvent(); | ||||
|   return ret; | ||||
| } | ||||
| @@ -125,37 +125,39 @@ auto waybar::modules::Custom::update() -> void { | ||||
|     } else { | ||||
|       parseOutputRaw(); | ||||
|     } | ||||
|     auto str = fmt::format(format_, text_, fmt::arg("alt", alt_), | ||||
|     auto str = fmt::format(format_, Glib::Markup::escape_text(text_).raw(), fmt::arg("alt", alt_), | ||||
|                            fmt::arg("icon", getIcon(percentage_, alt_)), | ||||
|                            fmt::arg("percentage", percentage_)); | ||||
|     if (str.empty()) { | ||||
|       event_box_.hide(); | ||||
|     } else { | ||||
|       label_.set_markup(str); | ||||
|       label_->set_markup(str); | ||||
|       if (tooltipEnabled()) { | ||||
|         if (text_ == tooltip_) { | ||||
|           if (label_.get_tooltip_markup() != str) { | ||||
|             label_.set_tooltip_markup(str); | ||||
|           if (button_.get_tooltip_markup() != str) { | ||||
|             button_.set_tooltip_markup(str); | ||||
|           } | ||||
|         } else { | ||||
|           if (label_.get_tooltip_markup() != tooltip_) { | ||||
|             label_.set_tooltip_markup(tooltip_); | ||||
|           if (button_.get_tooltip_markup() != tooltip_) { | ||||
|             button_.set_tooltip_markup(tooltip_); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       auto classes = label_.get_style_context()->list_classes(); | ||||
|       auto classes = button_.get_style_context()->list_classes(); | ||||
|       for (auto const& c : classes) { | ||||
|         if (c == id_) continue; | ||||
|         label_.get_style_context()->remove_class(c); | ||||
|         button_.get_style_context()->remove_class(c); | ||||
|       } | ||||
|       for (auto const& c : class_) { | ||||
|         label_.get_style_context()->add_class(c); | ||||
|         button_.get_style_context()->add_class(c); | ||||
|       } | ||||
|       button_.get_style_context()->add_class("flat"); | ||||
|       button_.get_style_context()->add_class("text-button"); | ||||
|       event_box_.show(); | ||||
|     } | ||||
|   } | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| void waybar::modules::Custom::parseOutputRaw() { | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| using namespace waybar::util; | ||||
|  | ||||
| waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config) | ||||
|     : ALabel(config, "disk", id, "{}%", 30), path_("/") { | ||||
|     : AButton(config, "disk", id, "{}%", 30), path_("/") { | ||||
|   thread_ = [this] { | ||||
|     dp.emit(); | ||||
|     thread_.sleep_for(interval_); | ||||
| @@ -58,7 +58,7 @@ auto waybar::modules::Disk::update() -> void { | ||||
|     event_box_.hide(); | ||||
|   } else { | ||||
|     event_box_.show(); | ||||
|     label_.set_markup( | ||||
|     label_->set_markup( | ||||
|         fmt::format(format, stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free), | ||||
|                     fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), | ||||
|                     fmt::arg("used", used), fmt::arg("percentage_used", percentage_used), | ||||
| @@ -70,12 +70,12 @@ auto waybar::modules::Disk::update() -> void { | ||||
|     if (config_["tooltip-format"].isString()) { | ||||
|       tooltip_format = config_["tooltip-format"].asString(); | ||||
|     } | ||||
|     label_.set_tooltip_text( | ||||
|     button_.set_tooltip_text( | ||||
|         fmt::format(tooltip_format, stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free), | ||||
|                     fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), | ||||
|                     fmt::arg("used", used), fmt::arg("percentage_used", percentage_used), | ||||
|                     fmt::arg("total", total), fmt::arg("path", path_))); | ||||
|   } | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|   | ||||
| @@ -4,12 +4,14 @@ | ||||
| #include <xkbcommon/xkbcommon.h> | ||||
| #include <xkbcommon/xkbregistry.h> | ||||
|  | ||||
| #include <util/sanitize_str.hpp> | ||||
|  | ||||
| #include "modules/hyprland/backend.hpp" | ||||
|  | ||||
| namespace waybar::modules::hyprland { | ||||
|  | ||||
| Language::Language(const std::string& id, const Bar& bar, const Json::Value& config) | ||||
|     : ALabel(config, "language", id, "{}", 0, true), bar_(bar) { | ||||
|     : AButton(config, "language", id, "{}", 0, true), bar_(bar) { | ||||
|   modulesReady = true; | ||||
|  | ||||
|   if (!gIPC.get()) { | ||||
| @@ -19,8 +21,8 @@ Language::Language(const std::string& id, const Bar& bar, const Json::Value& con | ||||
|   // get the active layout when open | ||||
|   initLanguage(); | ||||
|  | ||||
|   label_.hide(); | ||||
|   ALabel::update(); | ||||
|   button_.hide(); | ||||
|   AButton::update(); | ||||
|  | ||||
|   // register for hyprland ipc | ||||
|   gIPC->registerForIPC("activelayout", [&](const std::string& ev) { this->onEvent(ev); }); | ||||
| @@ -30,13 +32,13 @@ auto Language::update() -> void { | ||||
|   std::lock_guard<std::mutex> lg(mutex_); | ||||
|  | ||||
|   if (!format_.empty()) { | ||||
|     label_.show(); | ||||
|     label_.set_markup(layoutName_); | ||||
|     button_.show(); | ||||
|     label_->set_markup(layoutName_); | ||||
|   } else { | ||||
|     label_.hide(); | ||||
|     button_.hide(); | ||||
|   } | ||||
|  | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| void Language::onEvent(const std::string& ev) { | ||||
| @@ -48,16 +50,6 @@ void Language::onEvent(const std::string& ev) { | ||||
|   if (config_.isMember("keyboard-name") && keebName != config_["keyboard-name"].asString()) | ||||
|     return;  // ignore | ||||
|  | ||||
|   auto replaceAll = [](std::string str, const std::string& from, | ||||
|                        const std::string& to) -> std::string { | ||||
|     size_t start_pos = 0; | ||||
|     while ((start_pos = str.find(from, start_pos)) != std::string::npos) { | ||||
|       str.replace(start_pos, from.length(), to); | ||||
|       start_pos += to.length(); | ||||
|     } | ||||
|     return str; | ||||
|   }; | ||||
|  | ||||
|   const auto BRIEFNAME = getShortFrom(layoutName); | ||||
|  | ||||
|   if (config_.isMember("format-" + BRIEFNAME)) { | ||||
| @@ -67,7 +59,7 @@ void Language::onEvent(const std::string& ev) { | ||||
|     layoutName = fmt::format(format_, layoutName); | ||||
|   } | ||||
|  | ||||
|   layoutName = replaceAll(layoutName, "&", "&"); | ||||
|   layoutName = waybar::util::sanitize_string(layoutName); | ||||
|  | ||||
|   if (layoutName == layoutName_) return; | ||||
|  | ||||
| @@ -128,4 +120,4 @@ std::string Language::getShortFrom(const std::string& fullName) { | ||||
|   return ""; | ||||
| } | ||||
|  | ||||
| }  // namespace waybar::modules::hyprland | ||||
| }  // namespace waybar::modules::hyprland | ||||
|   | ||||
| @@ -2,13 +2,18 @@ | ||||
|  | ||||
| #include <spdlog/spdlog.h> | ||||
|  | ||||
| #include <util/sanitize_str.hpp> | ||||
|  | ||||
| #include "modules/hyprland/backend.hpp" | ||||
| #include "util/command.hpp" | ||||
| #include "util/json.hpp" | ||||
|  | ||||
| namespace waybar::modules::hyprland { | ||||
|  | ||||
| Window::Window(const std::string& id, const Bar& bar, const Json::Value& config) | ||||
|     : ALabel(config, "window", id, "{}", 0, true), bar_(bar) { | ||||
|   modulesReady = true; | ||||
|   separate_outputs = config["separate-outputs"].as<bool>(); | ||||
|  | ||||
|   if (!gIPC.get()) { | ||||
|     gIPC = std::make_unique<IPC>(); | ||||
| @@ -35,21 +40,41 @@ auto Window::update() -> void { | ||||
|   ALabel::update(); | ||||
| } | ||||
|  | ||||
| uint Window::getActiveWorkspaceID(std::string monitorName) { | ||||
|   auto cmd = waybar::util::command::exec("hyprctl monitors -j"); | ||||
|   assert(cmd.exit_code == 0); | ||||
|   Json::Value json = parser_.parse(cmd.out); | ||||
|   assert(json.isArray()); | ||||
|   auto monitor = std::find_if(json.begin(), json.end(), [&](Json::Value monitor){ | ||||
|     return monitor["name"] == monitorName; | ||||
|   }); | ||||
|   assert(monitor != std::end(json)); | ||||
|   return (*monitor)["activeWorkspace"]["id"].as<uint>(); | ||||
| } | ||||
|  | ||||
| std::string Window::getLastWindowTitle(uint workspaceID) { | ||||
|   auto cmd = waybar::util::command::exec("hyprctl workspaces -j"); | ||||
|   assert(cmd.exit_code == 0); | ||||
|   Json::Value json = parser_.parse(cmd.out); | ||||
|   assert(json.isArray()); | ||||
|   auto workspace = std::find_if(json.begin(), json.end(), [&](Json::Value workspace){ | ||||
|     return workspace["id"].as<uint>() == workspaceID; | ||||
|   }); | ||||
|   assert(workspace != std::end(json)); | ||||
|   return (*workspace)["lastwindowtitle"].as<std::string>(); | ||||
| } | ||||
|  | ||||
| void Window::onEvent(const std::string& ev) { | ||||
|   std::lock_guard<std::mutex> lg(mutex_); | ||||
|   auto windowName = ev.substr(ev.find_first_of(',') + 1).substr(0, 256); | ||||
|  | ||||
|   auto replaceAll = [](std::string str, const std::string& from, | ||||
|                        const std::string& to) -> std::string { | ||||
|     size_t start_pos = 0; | ||||
|     while ((start_pos = str.find(from, start_pos)) != std::string::npos) { | ||||
|       str.replace(start_pos, from.length(), to); | ||||
|       start_pos += to.length(); | ||||
|     } | ||||
|     return str; | ||||
|   }; | ||||
|   std::string windowName; | ||||
|   if (separate_outputs) { | ||||
|     windowName = getLastWindowTitle(getActiveWorkspaceID(this->bar_.output->name)); | ||||
|   } else { | ||||
|     windowName = ev.substr(ev.find_first_of(',') + 1).substr(0, 256); | ||||
|   } | ||||
|  | ||||
|   windowName = replaceAll(windowName, "&", "&"); | ||||
|   windowName = waybar::util::sanitize_string(windowName); | ||||
|  | ||||
|   if (windowName == lastView) return; | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ bool waybar::modules::IdleInhibitor::status = false; | ||||
|  | ||||
| waybar::modules::IdleInhibitor::IdleInhibitor(const std::string& id, const Bar& bar, | ||||
|                                               const Json::Value& config) | ||||
|     : ALabel(config, "idle_inhibitor", id, "{status}"), | ||||
|     : AButton(config, "idle_inhibitor", id, "{status}", 0, false, true), | ||||
|       bar_(bar), | ||||
|       idle_inhibitor_(nullptr), | ||||
|       pid_(-1) { | ||||
| @@ -16,6 +16,11 @@ waybar::modules::IdleInhibitor::IdleInhibitor(const std::string& id, const Bar& | ||||
|     throw std::runtime_error("idle-inhibit not available"); | ||||
|   } | ||||
|  | ||||
|   if (waybar::modules::IdleInhibitor::modules.empty() && config_["start-activated"].isBool() && | ||||
|       config_["start-activated"].asBool() != status) { | ||||
|     toggleStatus(); | ||||
|   } | ||||
|  | ||||
|   event_box_.add_events(Gdk::BUTTON_PRESS_MASK); | ||||
|   event_box_.signal_button_press_event().connect( | ||||
|       sigc::mem_fun(*this, &IdleInhibitor::handleToggle)); | ||||
| @@ -44,13 +49,13 @@ waybar::modules::IdleInhibitor::~IdleInhibitor() { | ||||
| auto waybar::modules::IdleInhibitor::update() -> void { | ||||
|   // Check status | ||||
|   if (status) { | ||||
|     label_.get_style_context()->remove_class("deactivated"); | ||||
|     button_.get_style_context()->remove_class("deactivated"); | ||||
|     if (idle_inhibitor_ == nullptr) { | ||||
|       idle_inhibitor_ = zwp_idle_inhibit_manager_v1_create_inhibitor( | ||||
|           waybar::Client::inst()->idle_inhibit_manager, bar_.surface); | ||||
|     } | ||||
|   } else { | ||||
|     label_.get_style_context()->remove_class("activated"); | ||||
|     button_.get_style_context()->remove_class("activated"); | ||||
|     if (idle_inhibitor_ != nullptr) { | ||||
|       zwp_idle_inhibitor_v1_destroy(idle_inhibitor_); | ||||
|       idle_inhibitor_ = nullptr; | ||||
| @@ -58,11 +63,11 @@ auto waybar::modules::IdleInhibitor::update() -> void { | ||||
|   } | ||||
|  | ||||
|   std::string status_text = status ? "activated" : "deactivated"; | ||||
|   label_.set_markup(fmt::format(format_, fmt::arg("status", status_text), | ||||
|                                 fmt::arg("icon", getIcon(0, status_text)))); | ||||
|   label_.get_style_context()->add_class(status_text); | ||||
|   label_->set_markup(fmt::format(format_, fmt::arg("status", status_text), | ||||
|                                  fmt::arg("icon", getIcon(0, status_text)))); | ||||
|   button_.get_style_context()->add_class(status_text); | ||||
|   if (tooltipEnabled()) { | ||||
|     label_.set_tooltip_markup( | ||||
|     button_.set_tooltip_markup( | ||||
|         status ? fmt::format(config_["tooltip-format-activated"].isString() | ||||
|                                  ? config_["tooltip-format-activated"].asString() | ||||
|                                  : "{status}", | ||||
| @@ -75,37 +80,41 @@ auto waybar::modules::IdleInhibitor::update() -> void { | ||||
|                              fmt::arg("icon", getIcon(0, status_text)))); | ||||
|   } | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| void waybar::modules::IdleInhibitor::toggleStatus() { | ||||
|   status = !status; | ||||
|  | ||||
|   if (timeout_.connected()) { | ||||
|     /* cancel any already active timeout handler */ | ||||
|     timeout_.disconnect(); | ||||
|   } | ||||
|  | ||||
|   if (status && config_["timeout"].isNumeric()) { | ||||
|     auto timeoutMins = config_["timeout"].asDouble(); | ||||
|     int timeoutSecs = timeoutMins * 60; | ||||
|  | ||||
|     timeout_ = Glib::signal_timeout().connect_seconds( | ||||
|         []() { | ||||
|           /* intentionally not tied to a module instance lifetime | ||||
|            * as the output with `this` can be disconnected | ||||
|            */ | ||||
|           spdlog::info("deactivating idle_inhibitor by timeout"); | ||||
|           status = false; | ||||
|           for (auto const& module : waybar::modules::IdleInhibitor::modules) { | ||||
|             module->update(); | ||||
|           } | ||||
|           /* disconnect */ | ||||
|           return false; | ||||
|         }, | ||||
|         timeoutSecs); | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool waybar::modules::IdleInhibitor::handleToggle(GdkEventButton* const& e) { | ||||
|   if (e->button == 1) { | ||||
|     status = !status; | ||||
|  | ||||
|     if (timeout_.connected()) { | ||||
|       /* cancel any already active timeout handler */ | ||||
|       timeout_.disconnect(); | ||||
|     } | ||||
|  | ||||
|     if (status && config_["timeout"].isNumeric()) { | ||||
|       auto timeoutMins = config_["timeout"].asDouble(); | ||||
|       int timeoutSecs = timeoutMins * 60; | ||||
|  | ||||
|       timeout_ = Glib::signal_timeout().connect_seconds( | ||||
|           []() { | ||||
|             /* intentionally not tied to a module instance lifetime | ||||
|              * as the output with `this` can be disconnected | ||||
|              */ | ||||
|             spdlog::info("deactivating idle_inhibitor by timeout"); | ||||
|             status = false; | ||||
|             for (auto const& module : waybar::modules::IdleInhibitor::modules) { | ||||
|               module->update(); | ||||
|             } | ||||
|             /* disconnect */ | ||||
|             return false; | ||||
|           }, | ||||
|           timeoutSecs); | ||||
|     } | ||||
|     toggleStatus(); | ||||
|  | ||||
|     // Make all other idle inhibitor modules update | ||||
|     for (auto const& module : waybar::modules::IdleInhibitor::modules) { | ||||
| @@ -115,6 +124,6 @@ bool waybar::modules::IdleInhibitor::handleToggle(GdkEventButton* const& e) { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ALabel::handleToggle(e); | ||||
|   AButton::handleToggle(e); | ||||
|   return true; | ||||
| } | ||||
|   | ||||
| @@ -98,7 +98,7 @@ auto getInhibitors(const Json::Value& config) -> std::string { | ||||
| namespace waybar::modules { | ||||
|  | ||||
| Inhibitor::Inhibitor(const std::string& id, const Bar& bar, const Json::Value& config) | ||||
|     : ALabel(config, "inhibitor", id, "{status}", true), | ||||
|     : AButton(config, "inhibitor", id, "{status}", true), | ||||
|       dbus_(::dbus()), | ||||
|       inhibitors_(::getInhibitors(config)) { | ||||
|   event_box_.add_events(Gdk::BUTTON_PRESS_MASK); | ||||
| @@ -117,16 +117,16 @@ auto Inhibitor::activated() -> bool { return handle_ != -1; } | ||||
| auto Inhibitor::update() -> void { | ||||
|   std::string status_text = activated() ? "activated" : "deactivated"; | ||||
|  | ||||
|   label_.get_style_context()->remove_class(activated() ? "deactivated" : "activated"); | ||||
|   label_.set_markup(fmt::format(format_, fmt::arg("status", status_text), | ||||
|                                 fmt::arg("icon", getIcon(0, status_text)))); | ||||
|   label_.get_style_context()->add_class(status_text); | ||||
|   button_.get_style_context()->remove_class(activated() ? "deactivated" : "activated"); | ||||
|   label_->set_markup(fmt::format(format_, fmt::arg("status", status_text), | ||||
|                                  fmt::arg("icon", getIcon(0, status_text)))); | ||||
|   button_.get_style_context()->add_class(status_text); | ||||
|  | ||||
|   if (tooltipEnabled()) { | ||||
|     label_.set_tooltip_text(status_text); | ||||
|     button_.set_tooltip_text(status_text); | ||||
|   } | ||||
|  | ||||
|   return ALabel::update(); | ||||
|   return AButton::update(); | ||||
| } | ||||
|  | ||||
| auto Inhibitor::handleToggle(GdkEventButton* const& e) -> bool { | ||||
| @@ -142,7 +142,7 @@ auto Inhibitor::handleToggle(GdkEventButton* const& e) -> bool { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return ALabel::handleToggle(e); | ||||
|   return AButton::handleToggle(e); | ||||
| } | ||||
|  | ||||
| }  // namespace waybar::modules | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| #include "modules/memory.hpp" | ||||
|  | ||||
| waybar::modules::Memory::Memory(const std::string& id, const Json::Value& config) | ||||
|     : ALabel(config, "memory", id, "{}%", 30) { | ||||
|     : AButton(config, "memory", id, "{}%", 30) { | ||||
|   thread_ = [this] { | ||||
|     dp.emit(); | ||||
|     thread_.sleep_for(interval_); | ||||
| @@ -54,7 +54,7 @@ auto waybar::modules::Memory::update() -> void { | ||||
|     } else { | ||||
|       event_box_.show(); | ||||
|       auto icons = std::vector<std::string>{state}; | ||||
|       label_.set_markup(fmt::format( | ||||
|       label_->set_markup(fmt::format( | ||||
|           format, used_ram_percentage, fmt::arg("icon", getIcon(used_ram_percentage, icons)), | ||||
|           fmt::arg("total", total_ram_gigabytes), fmt::arg("swapTotal", total_swap_gigabytes), | ||||
|           fmt::arg("percentage", used_ram_percentage), | ||||
| @@ -66,7 +66,7 @@ auto waybar::modules::Memory::update() -> void { | ||||
|     if (tooltipEnabled()) { | ||||
|       if (config_["tooltip-format"].isString()) { | ||||
|         auto tooltip_format = config_["tooltip-format"].asString(); | ||||
|         label_.set_tooltip_text(fmt::format( | ||||
|         button_.set_tooltip_text(fmt::format( | ||||
|             tooltip_format, used_ram_percentage, fmt::arg("total", total_ram_gigabytes), | ||||
|             fmt::arg("swapTotal", total_swap_gigabytes), | ||||
|             fmt::arg("percentage", used_ram_percentage), | ||||
| @@ -74,12 +74,12 @@ auto waybar::modules::Memory::update() -> void { | ||||
|             fmt::arg("swapUsed", used_swap_gigabytes), fmt::arg("avail", available_ram_gigabytes), | ||||
|             fmt::arg("swapAvail", available_swap_gigabytes))); | ||||
|       } else { | ||||
|         label_.set_tooltip_text(fmt::format("{:.{}f}GiB used", used_ram_gigabytes, 1)); | ||||
|         button_.set_tooltip_text(fmt::format("{:.{}f}GiB used", used_ram_gigabytes, 1)); | ||||
|       } | ||||
|     } | ||||
|   } else { | ||||
|     event_box_.hide(); | ||||
|   } | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|   | ||||
| @@ -4,6 +4,9 @@ | ||||
| #include <glibmm/ustring.h> | ||||
| #include <spdlog/spdlog.h> | ||||
|  | ||||
| #include <util/sanitize_str.hpp> | ||||
| using namespace waybar::util; | ||||
|  | ||||
| #include "modules/mpd/state.hpp" | ||||
| #if defined(MPD_NOINLINE) | ||||
| namespace waybar::modules { | ||||
| @@ -12,7 +15,7 @@ namespace waybar::modules { | ||||
| #endif | ||||
|  | ||||
| waybar::modules::MPD::MPD(const std::string& id, const Json::Value& config) | ||||
|     : ALabel(config, "mpd", id, "{album} - {artist} - {title}", 5), | ||||
|     : AButton(config, "mpd", id, "{album} - {artist} - {title}", 5, false, true), | ||||
|       module_name_(id.empty() ? "mpd" : "mpd#" + id), | ||||
|       server_(nullptr), | ||||
|       port_(config_["port"].isUInt() ? config["port"].asUInt() : 0), | ||||
| @@ -44,7 +47,7 @@ auto waybar::modules::MPD::update() -> void { | ||||
|   context_.update(); | ||||
|  | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| void waybar::modules::MPD::queryMPD() { | ||||
| @@ -85,15 +88,15 @@ std::string waybar::modules::MPD::getFilename() const { | ||||
|  | ||||
| void waybar::modules::MPD::setLabel() { | ||||
|   if (connection_ == nullptr) { | ||||
|     label_.get_style_context()->add_class("disconnected"); | ||||
|     label_.get_style_context()->remove_class("stopped"); | ||||
|     label_.get_style_context()->remove_class("playing"); | ||||
|     label_.get_style_context()->remove_class("paused"); | ||||
|     button_.get_style_context()->add_class("disconnected"); | ||||
|     button_.get_style_context()->remove_class("stopped"); | ||||
|     button_.get_style_context()->remove_class("playing"); | ||||
|     button_.get_style_context()->remove_class("paused"); | ||||
|  | ||||
|     auto format = config_["format-disconnected"].isString() | ||||
|                       ? config_["format-disconnected"].asString() | ||||
|                       : "disconnected"; | ||||
|     label_.set_markup(format); | ||||
|     label_->set_markup(format); | ||||
|  | ||||
|     if (tooltipEnabled()) { | ||||
|       std::string tooltip_format; | ||||
| @@ -101,11 +104,11 @@ void waybar::modules::MPD::setLabel() { | ||||
|                            ? config_["tooltip-format-disconnected"].asString() | ||||
|                            : "MPD (disconnected)"; | ||||
|       // Nothing to format | ||||
|       label_.set_tooltip_text(tooltip_format); | ||||
|       button_.set_tooltip_text(tooltip_format); | ||||
|     } | ||||
|     return; | ||||
|   } else { | ||||
|     label_.get_style_context()->remove_class("disconnected"); | ||||
|     button_.get_style_context()->remove_class("disconnected"); | ||||
|   } | ||||
|  | ||||
|   auto format = format_; | ||||
| @@ -118,29 +121,29 @@ void waybar::modules::MPD::setLabel() { | ||||
|   if (stopped()) { | ||||
|     format = | ||||
|         config_["format-stopped"].isString() ? config_["format-stopped"].asString() : "stopped"; | ||||
|     label_.get_style_context()->add_class("stopped"); | ||||
|     label_.get_style_context()->remove_class("playing"); | ||||
|     label_.get_style_context()->remove_class("paused"); | ||||
|     button_.get_style_context()->add_class("stopped"); | ||||
|     button_.get_style_context()->remove_class("playing"); | ||||
|     button_.get_style_context()->remove_class("paused"); | ||||
|   } else { | ||||
|     label_.get_style_context()->remove_class("stopped"); | ||||
|     button_.get_style_context()->remove_class("stopped"); | ||||
|     if (playing()) { | ||||
|       label_.get_style_context()->add_class("playing"); | ||||
|       label_.get_style_context()->remove_class("paused"); | ||||
|       button_.get_style_context()->add_class("playing"); | ||||
|       button_.get_style_context()->remove_class("paused"); | ||||
|     } else if (paused()) { | ||||
|       format = config_["format-paused"].isString() ? config_["format-paused"].asString() | ||||
|                                                    : config_["format"].asString(); | ||||
|       label_.get_style_context()->add_class("paused"); | ||||
|       label_.get_style_context()->remove_class("playing"); | ||||
|       button_.get_style_context()->add_class("paused"); | ||||
|       button_.get_style_context()->remove_class("playing"); | ||||
|     } | ||||
|  | ||||
|     stateIcon = getStateIcon(); | ||||
|  | ||||
|     artist = getTag(MPD_TAG_ARTIST); | ||||
|     album_artist = getTag(MPD_TAG_ALBUM_ARTIST); | ||||
|     album = getTag(MPD_TAG_ALBUM); | ||||
|     title = getTag(MPD_TAG_TITLE); | ||||
|     date = getTag(MPD_TAG_DATE); | ||||
|     filename = getFilename(); | ||||
|     artist = sanitize_string(getTag(MPD_TAG_ARTIST)); | ||||
|     album_artist = sanitize_string(getTag(MPD_TAG_ALBUM_ARTIST)); | ||||
|     album = sanitize_string(getTag(MPD_TAG_ALBUM)); | ||||
|     title = sanitize_string(getTag(MPD_TAG_TITLE)); | ||||
|     date = sanitize_string(getTag(MPD_TAG_DATE)); | ||||
|     filename = sanitize_string(getFilename()); | ||||
|     song_pos = mpd_status_get_song_pos(status_.get()) + 1; | ||||
|     volume = mpd_status_get_volume(status_.get()); | ||||
|     if (volume < 0) { | ||||
| @@ -166,7 +169,7 @@ void waybar::modules::MPD::setLabel() { | ||||
|   if (config_["title-len"].isInt()) title = title.substr(0, config_["title-len"].asInt()); | ||||
|  | ||||
|   try { | ||||
|     label_.set_markup(fmt::format( | ||||
|     label_->set_markup(fmt::format( | ||||
|         format, fmt::arg("artist", Glib::Markup::escape_text(artist).raw()), | ||||
|         fmt::arg("albumArtist", Glib::Markup::escape_text(album_artist).raw()), | ||||
|         fmt::arg("album", Glib::Markup::escape_text(album).raw()), | ||||
| @@ -195,7 +198,7 @@ void waybar::modules::MPD::setLabel() { | ||||
|                       fmt::arg("queueLength", queue_length), fmt::arg("stateIcon", stateIcon), | ||||
|                       fmt::arg("consumeIcon", consumeIcon), fmt::arg("randomIcon", randomIcon), | ||||
|                       fmt::arg("repeatIcon", repeatIcon), fmt::arg("singleIcon", singleIcon)); | ||||
|       label_.set_tooltip_text(tooltip_text); | ||||
|       button_.set_tooltip_text(tooltip_text); | ||||
|     } catch (fmt::format_error const& e) { | ||||
|       spdlog::warn("mpd: format error (tooltip): {}", e.what()); | ||||
|     } | ||||
|   | ||||
| @@ -78,7 +78,7 @@ waybar::modules::Network::readBandwidthUsage() { | ||||
| } | ||||
|  | ||||
| waybar::modules::Network::Network(const std::string &id, const Json::Value &config) | ||||
|     : ALabel(config, "network", id, DEFAULT_FORMAT, 60), | ||||
|     : AButton(config, "network", id, DEFAULT_FORMAT, 60), | ||||
|       ifid_(-1), | ||||
|       family_(config["family"] == "ipv6" ? AF_INET6 : AF_INET), | ||||
|       efd_(-1), | ||||
| @@ -95,11 +95,11 @@ waybar::modules::Network::Network(const std::string &id, const Json::Value &conf | ||||
| #endif | ||||
|       frequency_(0.0) { | ||||
|  | ||||
|   // Start with some "text" in the module's label_, update() will then | ||||
|   // Start with some "text" in the module's label_-> update() will then | ||||
|   // update it. Since the text should be different, update() will be able | ||||
|   // to show or hide the event_box_. This is to work around the case where | ||||
|   // the module start with no text, but the the event_box_ is shown. | ||||
|   label_.set_markup("<s></s>"); | ||||
|   label_->set_markup("<s></s>"); | ||||
|  | ||||
|   auto bandwidth = readBandwidthUsage(); | ||||
|   if (bandwidth.has_value()) { | ||||
| @@ -309,8 +309,8 @@ auto waybar::modules::Network::update() -> void { | ||||
|  | ||||
|   if (!alt_) { | ||||
|     auto state = getNetworkState(); | ||||
|     if (!state_.empty() && label_.get_style_context()->has_class(state_)) { | ||||
|       label_.get_style_context()->remove_class(state_); | ||||
|     if (!state_.empty() && button_.get_style_context()->has_class(state_)) { | ||||
|       button_.get_style_context()->remove_class(state_); | ||||
|     } | ||||
|     if (config_["format-" + state].isString()) { | ||||
|       default_format_ = config_["format-" + state].asString(); | ||||
| @@ -322,8 +322,8 @@ auto waybar::modules::Network::update() -> void { | ||||
|     if (config_["tooltip-format-" + state].isString()) { | ||||
|       tooltip_format = config_["tooltip-format-" + state].asString(); | ||||
|     } | ||||
|     if (!label_.get_style_context()->has_class(state)) { | ||||
|       label_.get_style_context()->add_class(state); | ||||
|     if (!button_.get_style_context()->has_class(state)) { | ||||
|       button_.get_style_context()->add_class(state); | ||||
|     } | ||||
|     format_ = default_format_; | ||||
|     state_ = state; | ||||
| @@ -349,8 +349,8 @@ auto waybar::modules::Network::update() -> void { | ||||
|       fmt::arg("bandwidthUpBytes", pow_format(bandwidth_up / interval_.count(), "B/s")), | ||||
|       fmt::arg("bandwidthTotalBytes", | ||||
|                pow_format((bandwidth_up + bandwidth_down) / interval_.count(), "B/s"))); | ||||
|   if (text.compare(label_.get_label()) != 0) { | ||||
|     label_.set_markup(text); | ||||
|   if (text.compare(label_->get_label()) != 0) { | ||||
|     label_->set_markup(text); | ||||
|     if (text.empty()) { | ||||
|       event_box_.hide(); | ||||
|     } else { | ||||
| @@ -382,16 +382,16 @@ auto waybar::modules::Network::update() -> void { | ||||
|           fmt::arg("bandwidthUpBytes", pow_format(bandwidth_up / interval_.count(), "B/s")), | ||||
|           fmt::arg("bandwidthTotalBytes", | ||||
|                    pow_format((bandwidth_up + bandwidth_down) / interval_.count(), "B/s"))); | ||||
|       if (label_.get_tooltip_text() != tooltip_text) { | ||||
|         label_.set_tooltip_markup(tooltip_text); | ||||
|       if (button_.get_tooltip_text() != tooltip_text) { | ||||
|         button_.set_tooltip_markup(tooltip_text); | ||||
|       } | ||||
|     } else if (label_.get_tooltip_text() != text) { | ||||
|       label_.set_tooltip_markup(text); | ||||
|     } else if (button_.get_tooltip_text() != text) { | ||||
|       button_.set_tooltip_markup(text); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| bool waybar::modules::Network::checkInterface(std::string name) { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| #include "modules/pulseaudio.hpp" | ||||
|  | ||||
| waybar::modules::Pulseaudio::Pulseaudio(const std::string &id, const Json::Value &config) | ||||
|     : ALabel(config, "pulseaudio", id, "{volume}%"), | ||||
|     : AButton(config, "pulseaudio", id, "{volume}%"), | ||||
|       mainloop_(nullptr), | ||||
|       mainloop_api_(nullptr), | ||||
|       context_(nullptr), | ||||
| @@ -91,19 +91,31 @@ bool waybar::modules::Pulseaudio::handleScroll(GdkEventScroll *e) { | ||||
|   pa_volume_t change = volume_tick; | ||||
|   pa_cvolume pa_volume = pa_volume_; | ||||
|   int max_volume = 100; | ||||
|   double step = 1; | ||||
|   // isDouble returns true for integers as well, just in case | ||||
|   if (config_["scroll-step"].isDouble()) { | ||||
|     change = round(config_["scroll-step"].asDouble() * volume_tick); | ||||
|     step = config_["scroll-step"].asDouble(); | ||||
|   } | ||||
|   if (config_["max-volume"].isInt()) { | ||||
|     max_volume = std::min(0, config_["max-volume"].asInt()); | ||||
|     max_volume = std::min(config_["max-volume"].asInt(), static_cast<int>(PA_VOLUME_UI_MAX)); | ||||
|   } | ||||
|  | ||||
|   if (dir == SCROLL_DIR::UP) { | ||||
|     if (volume_ + 1 <= max_volume) { | ||||
|     if (volume_ < max_volume) { | ||||
|       if (volume_ + step > max_volume) { | ||||
|         change = round((max_volume - volume_) * volume_tick); | ||||
|       } else { | ||||
|         change = round(step * volume_tick); | ||||
|       } | ||||
|       pa_cvolume_inc(&pa_volume, change); | ||||
|     } | ||||
|   } else if (dir == SCROLL_DIR::DOWN) { | ||||
|     if (volume_ - 1 >= 0) { | ||||
|     if (volume_ > 0) { | ||||
|       if (volume_ - step < 0) { | ||||
|         change = round(volume_ * volume_tick); | ||||
|       } else { | ||||
|         change = round(step * volume_tick); | ||||
|       } | ||||
|       pa_cvolume_dec(&pa_volume, change); | ||||
|     } | ||||
|   } | ||||
| @@ -170,6 +182,15 @@ void waybar::modules::Pulseaudio::sinkInfoCb(pa_context * /*context*/, const pa_ | ||||
|   if (i == nullptr) return; | ||||
|  | ||||
|   auto pa = static_cast<waybar::modules::Pulseaudio *>(data); | ||||
|  | ||||
|   if (pa->config_["ignored-sinks"].isArray()) { | ||||
|     for (const auto &ignored_sink : pa->config_["ignored-sinks"]) { | ||||
|       if (ignored_sink.asString() == i->description) { | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (pa->current_sink_name_ == i->name) { | ||||
|     if (i->state != PA_SINK_RUNNING) { | ||||
|       pa->current_sink_running_ = false; | ||||
| @@ -240,9 +261,9 @@ auto waybar::modules::Pulseaudio::update() -> void { | ||||
|     if (monitor_.find("a2dp_sink") != std::string::npos ||  // PulseAudio | ||||
|         monitor_.find("a2dp-sink") != std::string::npos) {  // PipeWire | ||||
|       format_name = format_name + "-bluetooth"; | ||||
|       label_.get_style_context()->add_class("bluetooth"); | ||||
|       button_.get_style_context()->add_class("bluetooth"); | ||||
|     } else { | ||||
|       label_.get_style_context()->remove_class("bluetooth"); | ||||
|       button_.get_style_context()->remove_class("bluetooth"); | ||||
|     } | ||||
|     if (muted_) { | ||||
|       // Check muted bluetooth format exist, otherwise fallback to default muted format | ||||
| @@ -250,29 +271,29 @@ auto waybar::modules::Pulseaudio::update() -> void { | ||||
|         format_name = "format"; | ||||
|       } | ||||
|       format_name = format_name + "-muted"; | ||||
|       label_.get_style_context()->add_class("muted"); | ||||
|       label_.get_style_context()->add_class("sink-muted"); | ||||
|       button_.get_style_context()->add_class("muted"); | ||||
|       button_.get_style_context()->add_class("sink-muted"); | ||||
|     } else { | ||||
|       label_.get_style_context()->remove_class("muted"); | ||||
|       label_.get_style_context()->remove_class("sink-muted"); | ||||
|       button_.get_style_context()->remove_class("muted"); | ||||
|       button_.get_style_context()->remove_class("sink-muted"); | ||||
|     } | ||||
|     format = config_[format_name].isString() ? config_[format_name].asString() : format; | ||||
|   } | ||||
|   // TODO: find a better way to split source/sink | ||||
|   std::string format_source = "{volume}%"; | ||||
|   if (source_muted_) { | ||||
|     label_.get_style_context()->add_class("source-muted"); | ||||
|     button_.get_style_context()->add_class("source-muted"); | ||||
|     if (config_["format-source-muted"].isString()) { | ||||
|       format_source = config_["format-source-muted"].asString(); | ||||
|     } | ||||
|   } else { | ||||
|     label_.get_style_context()->remove_class("source-muted"); | ||||
|     button_.get_style_context()->remove_class("source-muted"); | ||||
|     if (config_["format-source-muted"].isString()) { | ||||
|       format_source = config_["format-source"].asString(); | ||||
|     } | ||||
|   } | ||||
|   format_source = fmt::format(format_source, fmt::arg("volume", source_volume_)); | ||||
|   label_.set_markup(fmt::format( | ||||
|   label_->set_markup(fmt::format( | ||||
|       format, fmt::arg("desc", desc_), fmt::arg("volume", volume_), | ||||
|       fmt::arg("format_source", format_source), fmt::arg("source_volume", source_volume_), | ||||
|       fmt::arg("source_desc", source_desc_), fmt::arg("icon", getIcon(volume_, getPulseIcon())))); | ||||
| @@ -283,16 +304,16 @@ auto waybar::modules::Pulseaudio::update() -> void { | ||||
|       tooltip_format = config_["tooltip-format"].asString(); | ||||
|     } | ||||
|     if (!tooltip_format.empty()) { | ||||
|       label_.set_tooltip_text(fmt::format( | ||||
|       button_.set_tooltip_text(fmt::format( | ||||
|           tooltip_format, fmt::arg("desc", desc_), fmt::arg("volume", volume_), | ||||
|           fmt::arg("format_source", format_source), fmt::arg("source_volume", source_volume_), | ||||
|           fmt::arg("source_desc", source_desc_), | ||||
|           fmt::arg("icon", getIcon(volume_, getPulseIcon())))); | ||||
|     } else { | ||||
|       label_.set_tooltip_text(desc_); | ||||
|       button_.set_tooltip_text(desc_); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| #include <time.h> | ||||
|  | ||||
| waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) | ||||
|     : ALabel(config, "clock", id, "{:%H:%M}", 60) { | ||||
|     : AButton(config, "clock", id, "{:%H:%M}", 60) { | ||||
|   thread_ = [this] { | ||||
|     dp.emit(); | ||||
|     auto now = std::chrono::system_clock::now(); | ||||
| @@ -19,17 +19,17 @@ auto waybar::modules::Clock::update() -> void { | ||||
|   auto now = std::chrono::system_clock::now(); | ||||
|   auto localtime = fmt::localtime(std::chrono::system_clock::to_time_t(now)); | ||||
|   auto text = fmt::format(format_, localtime); | ||||
|   label_.set_markup(text); | ||||
|   label_->set_markup(text); | ||||
|  | ||||
|   if (tooltipEnabled()) { | ||||
|     if (config_["tooltip-format"].isString()) { | ||||
|       auto tooltip_format = config_["tooltip-format"].asString(); | ||||
|       auto tooltip_text = fmt::format(tooltip_format, localtime); | ||||
|       label_.set_tooltip_text(tooltip_text); | ||||
|       button_.set_tooltip_text(tooltip_text); | ||||
|     } else { | ||||
|       label_.set_tooltip_text(text); | ||||
|       button_.set_tooltip_text(text); | ||||
|     } | ||||
|   } | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|   | ||||
| @@ -41,7 +41,7 @@ auto Sndio::connect_to_sndio() -> void { | ||||
| } | ||||
|  | ||||
| Sndio::Sndio(const std::string &id, const Json::Value &config) | ||||
|     : ALabel(config, "sndio", id, "{volume}%", 1), | ||||
|     : AButton(config, "sndio", id, "{volume}%", 1, false, true), | ||||
|       hdl_(nullptr), | ||||
|       pfds_(0), | ||||
|       addr_(0), | ||||
| @@ -105,14 +105,14 @@ auto Sndio::update() -> void { | ||||
|   unsigned int vol = 100. * static_cast<double>(volume_) / static_cast<double>(maxval_); | ||||
|  | ||||
|   if (volume_ == 0) { | ||||
|     label_.get_style_context()->add_class("muted"); | ||||
|     button_.get_style_context()->add_class("muted"); | ||||
|   } else { | ||||
|     label_.get_style_context()->remove_class("muted"); | ||||
|     button_.get_style_context()->remove_class("muted"); | ||||
|   } | ||||
|  | ||||
|   label_.set_markup(fmt::format(format, fmt::arg("volume", vol), fmt::arg("raw_value", volume_))); | ||||
|   label_->set_markup(fmt::format(format, fmt::arg("volume", vol), fmt::arg("raw_value", volume_))); | ||||
|  | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| auto Sndio::set_desc(struct sioctl_desc *d, unsigned int val) -> void { | ||||
|   | ||||
| @@ -18,7 +18,7 @@ const std::string Language::XKB_LAYOUT_NAMES_KEY = "xkb_layout_names"; | ||||
| const std::string Language::XKB_ACTIVE_LAYOUT_NAME_KEY = "xkb_active_layout_name"; | ||||
|  | ||||
| Language::Language(const std::string& id, const Json::Value& config) | ||||
|     : ALabel(config, "language", id, "{}", 0, true) { | ||||
|     : AButton(config, "language", id, "{}", 0, true) { | ||||
|   is_variant_displayed = format_.find("{variant}") != std::string::npos; | ||||
|   if (format_.find("{}") != std::string::npos || format_.find("{short}") != std::string::npos) { | ||||
|     displayed_short_flag |= static_cast<std::byte>(DispayedShortFlag::ShortName); | ||||
| @@ -99,7 +99,7 @@ auto Language::update() -> void { | ||||
|       format_, fmt::arg("short", layout_.short_name), | ||||
|       fmt::arg("shortDescription", layout_.short_description), fmt::arg("long", layout_.full_name), | ||||
|       fmt::arg("variant", layout_.variant), fmt::arg("flag", layout_.country_flag()))); | ||||
|   label_.set_markup(display_layout); | ||||
|   label_->set_markup(display_layout); | ||||
|   if (tooltipEnabled()) { | ||||
|     if (tooltip_format_ != "") { | ||||
|       auto tooltip_display_layout = trim( | ||||
| @@ -107,22 +107,22 @@ auto Language::update() -> void { | ||||
|                       fmt::arg("shortDescription", layout_.short_description), | ||||
|                       fmt::arg("long", layout_.full_name), fmt::arg("variant", layout_.variant), | ||||
|                       fmt::arg("flag", layout_.country_flag()))); | ||||
|       label_.set_tooltip_markup(tooltip_display_layout); | ||||
|       button_.set_tooltip_markup(tooltip_display_layout); | ||||
|     } else { | ||||
|       label_.set_tooltip_markup(display_layout); | ||||
|       button_.set_tooltip_markup(display_layout); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   event_box_.show(); | ||||
|  | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| auto Language::set_current_layout(std::string current_layout) -> void { | ||||
|   label_.get_style_context()->remove_class(layout_.short_name); | ||||
|   button_.get_style_context()->remove_class(layout_.short_name); | ||||
|   layout_ = layouts_map_[current_layout]; | ||||
|   label_.get_style_context()->add_class(layout_.short_name); | ||||
|   button_.get_style_context()->add_class(layout_.short_name); | ||||
| } | ||||
|  | ||||
| auto Language::init_layouts_map(const std::vector<std::string>& used_layouts) -> void { | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| namespace waybar::modules::sway { | ||||
|  | ||||
| Mode::Mode(const std::string& id, const Json::Value& config) | ||||
|     : ALabel(config, "mode", id, "{}", 0, true) { | ||||
|     : AButton(config, "mode", id, "{}", 0, true) { | ||||
|   ipc_.subscribe(R"(["mode"])"); | ||||
|   ipc_.signal_event.connect(sigc::mem_fun(*this, &Mode::onEvent)); | ||||
|   // Launch worker | ||||
| @@ -42,14 +42,14 @@ auto Mode::update() -> void { | ||||
|   if (mode_.empty()) { | ||||
|     event_box_.hide(); | ||||
|   } else { | ||||
|     label_.set_markup(fmt::format(format_, mode_)); | ||||
|     label_->set_markup(fmt::format(format_, mode_)); | ||||
|     if (tooltipEnabled()) { | ||||
|       label_.set_tooltip_text(mode_); | ||||
|       button_.set_tooltip_text(mode_); | ||||
|     } | ||||
|     event_box_.show(); | ||||
|   } | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| }  // namespace waybar::modules::sway | ||||
|   | ||||
| @@ -3,15 +3,11 @@ | ||||
| #include <filesystem> | ||||
|  | ||||
| #if defined(__FreeBSD__) | ||||
| // clang-format off | ||||
| #include <sys/types.h> | ||||
| #include <sys/sysctl.h> | ||||
| // clang-format on | ||||
| #endif | ||||
|  | ||||
| waybar::modules::Temperature::Temperature(const std::string& id, const Json::Value& config) | ||||
|     : ALabel(config, "temperature", id, "{temperatureC}°C", 10) { | ||||
|  | ||||
|     : AButton(config, "temperature", id, "{temperatureC}°C", 10) { | ||||
| #if defined(__FreeBSD__) | ||||
| // try to read sysctl? | ||||
| #else | ||||
| @@ -46,9 +42,9 @@ auto waybar::modules::Temperature::update() -> void { | ||||
|   auto format = format_; | ||||
|   if (critical) { | ||||
|     format = config_["format-critical"].isString() ? config_["format-critical"].asString() : format; | ||||
|     label_.get_style_context()->add_class("critical"); | ||||
|     button_.get_style_context()->add_class("critical"); | ||||
|   } else { | ||||
|     label_.get_style_context()->remove_class("critical"); | ||||
|     button_.get_style_context()->remove_class("critical"); | ||||
|   } | ||||
|  | ||||
|   if (format.empty()) { | ||||
| @@ -59,21 +55,21 @@ auto waybar::modules::Temperature::update() -> void { | ||||
|   } | ||||
|  | ||||
|   auto max_temp = config_["critical-threshold"].isInt() ? config_["critical-threshold"].asInt() : 0; | ||||
|   label_.set_markup(fmt::format(format, fmt::arg("temperatureC", temperature_c), | ||||
|                                 fmt::arg("temperatureF", temperature_f), | ||||
|                                 fmt::arg("temperatureK", temperature_k), | ||||
|                                 fmt::arg("icon", getIcon(temperature_c, "", max_temp)))); | ||||
|   label_->set_markup(fmt::format(format, fmt::arg("temperatureC", temperature_c), | ||||
|                                  fmt::arg("temperatureF", temperature_f), | ||||
|                                  fmt::arg("temperatureK", temperature_k), | ||||
|                                  fmt::arg("icon", getIcon(temperature_c, "", max_temp)))); | ||||
|   if (tooltipEnabled()) { | ||||
|     std::string tooltip_format = "{temperatureC}°C"; | ||||
|     if (config_["tooltip-format"].isString()) { | ||||
|       tooltip_format = config_["tooltip-format"].asString(); | ||||
|     } | ||||
|     label_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("temperatureC", temperature_c), | ||||
|                                         fmt::arg("temperatureF", temperature_f), | ||||
|                                         fmt::arg("temperatureK", temperature_k))); | ||||
|     button_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("temperatureC", temperature_c), | ||||
|                                          fmt::arg("temperatureF", temperature_f), | ||||
|                                          fmt::arg("temperatureK", temperature_k))); | ||||
|   } | ||||
|   // Call parent update | ||||
|   ALabel::update(); | ||||
|   AButton::update(); | ||||
| } | ||||
|  | ||||
| float waybar::modules::Temperature::getTemperature() { | ||||
| @@ -81,13 +77,17 @@ float waybar::modules::Temperature::getTemperature() { | ||||
|   int temp; | ||||
|   size_t size = sizeof temp; | ||||
|  | ||||
|   auto zone = config_["thermal-zone"].isInt() ? config_["thermal-zone"].asInt() : 0; | ||||
|   auto sysctl_thermal = fmt::format("hw.acpi.thermal.tz{}.temperature", zone); | ||||
|  | ||||
|   if (sysctlbyname("hw.acpi.thermal.tz0.temperature", &temp, &size, NULL, 0) != 0) { | ||||
|     throw std::runtime_error("sysctl hw.acpi.thermal.tz0.temperature or dev.cpu.0.temperature failed"); | ||||
|     throw std::runtime_error( | ||||
|         "sysctl hw.acpi.thermal.tz0.temperature or dev.cpu.0.temperature failed"); | ||||
|   } | ||||
|   auto temperature_c = ((float)temp-2732)/10;   | ||||
|   auto temperature_c = ((float)temp - 2732) / 10; | ||||
|   return temperature_c; | ||||
|  | ||||
| #else // Linux | ||||
| #else  // Linux | ||||
|   std::ifstream temp(file_path_); | ||||
|   if (!temp.is_open()) { | ||||
|     throw std::runtime_error("Can't open " + file_path_); | ||||
|   | ||||
							
								
								
									
										24
									
								
								src/util/sanitize_str.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/util/sanitize_str.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| #include <array> | ||||
| #include <string> | ||||
| #include <util/sanitize_str.hpp> | ||||
| #include <utility> | ||||
|  | ||||
| namespace waybar::util { | ||||
| // replaces ``<>&"'`` with their encoded counterparts | ||||
| std::string sanitize_string(std::string str) { | ||||
|   // note: it's important that '&' is replaced first; therefor we *can't* use std::map | ||||
|   const std::pair<char, std::string> replacement_table[] = { | ||||
|       {'&', "&"}, {'<', "<"}, {'>', ">"}, {'"', """}, {'\'', "'"}}; | ||||
|   size_t startpoint; | ||||
|   for (size_t i = 0; i < (sizeof(replacement_table) / sizeof(replacement_table[0])); ++i) { | ||||
|     startpoint = 0; | ||||
|     std::pair pair = replacement_table[i]; | ||||
|     while ((startpoint = str.find(pair.first, startpoint)) != std::string::npos) { | ||||
|       str.replace(startpoint, 1, pair.second); | ||||
|       startpoint += pair.second.length(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return str; | ||||
| } | ||||
| }  // namespace waybar::util | ||||
		Reference in New Issue
	
	Block a user
	 herlev
					herlev