Merge branch 'master' into smooth-power

This commit is contained in:
Alexis Rouillard
2026-07-03 22:11:06 +02:00
committed by GitHub
206 changed files with 4685 additions and 2526 deletions
+4 -8
View File
@@ -10,13 +10,9 @@ jobs:
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v6
# TODO: bump to clang 19 release - uses: RafikFarhad/clang-format-github-action@v6
# - uses: DoozyX/clang-format-lint-action@v0.18.2
- uses: DoozyX/clang-format-lint-action@558090054b3f39e3d6af24f0cd73b319535da809
name: clang-format name: clang-format
with: with:
source: "." sources: "src/**/*.hpp,src/**/*.cpp"
extensions: "hpp,h,cpp,c" style: "file"
style: "file:.clang-format"
clangFormatVersion: 19
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
container: container:
image: alexays/waybar:debian image: alexays/waybar:debian
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v6
- name: configure - name: configure
run: | run: |
meson -Dcpp_std=c++20 build # necessary to generate compile_commands.json meson -Dcpp_std=c++20 build # necessary to generate compile_commands.json
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v3
+2 -2
View File
@@ -12,13 +12,13 @@ jobs:
# https://github.com/actions/runner/issues/385 - for FreeBSD runner support # https://github.com/actions/runner/issues/385 - for FreeBSD runner support
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v6
- name: Test in FreeBSD VM - name: Test in FreeBSD VM
uses: cross-platform-actions/action@v0.28.0 uses: cross-platform-actions/action@v0.28.0
timeout-minutes: 180 timeout-minutes: 180
env: env:
CPPFLAGS: '-isystem/usr/local/include' CPPFLAGS: '-isystem/usr/local/include'
LDFLAGS: '-L/usr/local/lib' LDFLAGS: '-L/usr/local/lib'
with: with:
operating_system: freebsd operating_system: freebsd
version: "14.2" version: "14.2"
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
image: alexays/waybar:${{ matrix.distro }} image: alexays/waybar:${{ matrix.distro }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v6
- name: configure - name: configure
run: meson setup -Dman-pages=enabled -Dcpp_std=${{matrix.cpp_std}} build run: meson setup -Dman-pages=enabled -Dcpp_std=${{matrix.cpp_std}} build
- name: build - name: build
+12 -9
View File
@@ -2,16 +2,19 @@ name: "Nix-Tests"
on: on:
pull_request: pull_request:
push: push:
concurrency:
group: ${{ github.workflow }}-nix-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs: jobs:
nix-flake-check: nix-flake-check:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- uses: cachix/install-nix-action@v27 - uses: cachix/install-nix-action@v31
with: with:
extra_nix_config: | extra_nix_config: |
experimental-features = nix-command flakes experimental-features = nix-command flakes
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- run: nix flake show - run: nix flake show
- run: nix flake check --print-build-logs - run: nix flake check --print-build-logs
- run: nix build --print-build-logs - run: nix build --print-build-logs
+5 -5
View File
@@ -4,19 +4,19 @@ on:
schedule: schedule:
- cron: '0 0 1 * *' # Run monthly - cron: '0 0 1 * *' # Run monthly
push: push:
paths: paths:
- 'flake.nix' - 'flake.nix'
jobs: jobs:
lockfile: lockfile:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name != 'schedule' || github.repository == 'Alexays/Waybar' if: github.event_name != 'schedule' || github.repository == 'Alexays/Waybar'
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v27 uses: cachix/install-nix-action@v31
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Update flake.lock - name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@v21 uses: DeterminateSystems/update-flake-lock@v28
+3
View File
@@ -7,6 +7,7 @@ vgcore.*
*.swp *.swp
packagecache packagecache
/subprojects/**/ /subprojects/**/
/subprojects/.wraplock
/build* /build*
/dist /dist
/meson.egg-info /meson.egg-info
@@ -50,3 +51,5 @@ result
result-* result-*
.ccls-cache .ccls-cache
_codeql_detected_source_root
heaptrack*
+5 -1
View File
@@ -119,7 +119,7 @@ sudo apt install \
On Arch, you can use this command: On Arch, you can use this command:
``` ```
pacman -S \ pacman -S --asdeps \
gtkmm3 \ gtkmm3 \
jsoncpp \ jsoncpp \
libsigc++ \ libsigc++ \
@@ -151,6 +151,10 @@ Contributions welcome!<br>
Have fun :)<br> Have fun :)<br>
The style guidelines are [Google's](https://google.github.io/styleguide/cppguide.html) The style guidelines are [Google's](https://google.github.io/styleguide/cppguide.html)
> [!CAUTION]
> Distributions of Waybar are only released on the [official GitHub page](https://github.com/Alexays/Waybar).<br/>
> Waybar does **not** have an official website. Do not trust any sites that claim to be official.
## License ## License
Waybar is licensed under the MIT license. [See LICENSE for more information](https://github.com/Alexays/Waybar/blob/master/LICENSE). Waybar is licensed under the MIT license. [See LICENSE for more information](https://github.com/Alexays/Waybar/blob/master/LICENSE).
+1
View File
@@ -0,0 +1 @@
.
Generated
+6 -6
View File
@@ -3,11 +3,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1761588595, "lastModified": 1767039857,
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -18,11 +18,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1764242076, "lastModified": 1769461804,
"narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=", "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "2fad6eac6077f03fe109c4d4eb171cf96791faa4", "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
"type": "github" "type": "github"
}, },
"original": { "original": {
+4 -4
View File
@@ -9,15 +9,15 @@ namespace waybar {
class AAppIconLabel : public AIconLabel { class AAppIconLabel : public AIconLabel {
public: public:
AAppIconLabel(const Json::Value &config, const std::string &name, const std::string &id, AAppIconLabel(const Json::Value& config, const std::string& name, const std::string& id,
const std::string &format, uint16_t interval = 0, bool ellipsize = false, const std::string& format, uint16_t interval = 0, bool ellipsize = false,
bool enable_click = false, bool enable_scroll = false); bool enable_click = false, bool enable_scroll = false);
virtual ~AAppIconLabel() = default; virtual ~AAppIconLabel() = default;
auto update() -> void override; auto update() -> void override;
protected: protected:
void updateAppIconName(const std::string &app_identifier, void updateAppIconName(const std::string& app_identifier,
const std::string &alternative_app_identifier); const std::string& alternative_app_identifier);
void updateAppIcon(); void updateAppIcon();
unsigned app_icon_size_{24}; unsigned app_icon_size_{24};
bool update_app_icon_{true}; bool update_app_icon_{true};
+2 -2
View File
@@ -9,8 +9,8 @@ namespace waybar {
class AIconLabel : public ALabel { class AIconLabel : public ALabel {
public: public:
AIconLabel(const Json::Value &config, const std::string &name, const std::string &id, AIconLabel(const Json::Value& config, const std::string& name, const std::string& id,
const std::string &format, uint16_t interval = 0, bool ellipsize = false, const std::string& format, uint16_t interval = 0, bool ellipsize = false,
bool enable_click = false, bool enable_scroll = false); bool enable_click = false, bool enable_scroll = false);
virtual ~AIconLabel() = default; virtual ~AIconLabel() = default;
auto update() -> void override; auto update() -> void override;
+15 -6
View File
@@ -4,19 +4,21 @@
#include <gtkmm/label.h> #include <gtkmm/label.h>
#include <json/json.h> #include <json/json.h>
#include <optional>
#include "AModule.hpp" #include "AModule.hpp"
namespace waybar { namespace waybar {
class ALabel : public AModule { class ALabel : public AModule {
public: public:
ALabel(const Json::Value &, const std::string &, const std::string &, const std::string &format, ALabel(const Json::Value&, const std::string&, const std::string&, const std::string& format,
uint16_t interval = 0, bool ellipsize = false, bool enable_click = false, uint16_t interval = 0, bool ellipsize = false, bool enable_click = false,
bool enable_scroll = false); bool enable_scroll = false);
virtual ~ALabel() = default; virtual ~ALabel() = default;
auto update() -> void override; auto update() -> void override;
virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0); 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); virtual std::string getIcon(uint16_t, const std::vector<std::string>& alts, uint16_t max = 0);
protected: protected:
Gtk::Label label_; Gtk::Label label_;
@@ -25,12 +27,19 @@ class ALabel : public AModule {
bool alt_ = false; bool alt_ = false;
std::string default_format_; std::string default_format_;
bool handleToggle(GdkEventButton *const &e) override; bool setLabelMarkup(const Glib::ustring& markup);
bool setTooltipMarkup(const Glib::ustring& markup);
bool handleToggle(GdkEventButton* const& e) override;
virtual std::string getState(uint8_t value, bool lesser = false); virtual std::string getState(uint8_t value, bool lesser = false);
std::map<std::string, GtkMenuItem *> submenus_; std::map<std::string, GtkMenuItem*> submenus_;
std::map<std::string, std::string> menuActionsMap_; std::map<std::string, std::string> menuActionsMap_;
static void handleGtkMenuEvent(GtkMenuItem *menuitem, gpointer data); static void handleGtkMenuEvent(GtkMenuItem* menuitem, gpointer data);
private:
std::optional<Glib::ustring> last_label_markup_;
std::optional<Glib::ustring> last_tooltip_markup_;
}; };
} // namespace waybar } // namespace waybar
+21 -14
View File
@@ -12,51 +12,58 @@ namespace waybar {
class AModule : public IModule { class AModule : public IModule {
public: public:
static constexpr const char *MODULE_CLASS = "module"; static constexpr const char* MODULE_CLASS = "module";
~AModule() override; ~AModule() override;
auto update() -> void override; auto update() -> void override;
virtual auto refresh(int shouldRefresh) -> void {}; virtual auto refresh(int shouldRefresh) -> void {};
operator Gtk::Widget &() override; operator Gtk::Widget&() override;
auto doAction(const std::string &name) -> void override; auto doAction(const std::string& name) -> void override;
/// Emitting on this dispatcher triggers a update() call /// Emitting on this dispatcher triggers a update() call
Glib::Dispatcher dp; Glib::Dispatcher dp;
bool expandEnabled() const; bool expandEnabled() const;
virtual void suspend() {};
virtual void resume() {};
bool shouldSuspend() const { return disable_on_sleep_; }
protected: protected:
// Don't need to make an object directly // Don't need to make an object directly
// Derived classes are able to use it // Derived classes are able to use it
AModule(const Json::Value &, const std::string &, const std::string &, bool enable_click = false, AModule(const Json::Value&, const std::string&, const std::string&, bool enable_click = false,
bool enable_scroll = false); bool enable_scroll = false);
enum SCROLL_DIR { NONE, UP, DOWN, LEFT, RIGHT }; enum SCROLL_DIR { NONE, UP, DOWN, LEFT, RIGHT };
SCROLL_DIR getScrollDir(GdkEventScroll *e); SCROLL_DIR getScrollDir(GdkEventScroll* e);
bool tooltipEnabled() const; bool tooltipEnabled() const;
std::vector<int> pid_children_; std::vector<int> pid_children_;
const std::string name_; const std::string name_;
const Json::Value &config_; const Json::Value& config_;
Gtk::EventBox event_box_; Gtk::EventBox event_box_;
virtual void setCursor(Gdk::CursorType const &c); virtual void setCursor(Gdk::CursorType const& c);
virtual bool handleToggle(GdkEventButton *const &ev); virtual bool handleToggle(GdkEventButton* const& ev);
virtual bool handleMouseEnter(GdkEventCrossing *const &ev); virtual bool handleMouseEnter(GdkEventCrossing* const& ev);
virtual bool handleMouseLeave(GdkEventCrossing *const &ev); virtual bool handleMouseLeave(GdkEventCrossing* const& ev);
virtual bool handleScroll(GdkEventScroll *); virtual bool handleScroll(GdkEventScroll*);
virtual bool handleRelease(GdkEventButton *const &ev); virtual bool handleRelease(GdkEventButton* const& ev);
GObject *menu_;
bool disable_on_sleep_{false};
GObject* menu_ = nullptr;
private: private:
bool handleUserEvent(GdkEventButton *const &ev); bool handleUserEvent(GdkEventButton* const& ev);
const bool isTooltip; const bool isTooltip;
const bool isExpand; const bool isExpand;
bool hasUserEvents_; bool hasUserEvents_;
gdouble distance_scrolled_y_; gdouble distance_scrolled_y_;
gdouble distance_scrolled_x_; gdouble distance_scrolled_x_;
sigc::connection cursor_timeout_conn_;
std::map<std::string, std::string> eventActionMap_; std::map<std::string, std::string> eventActionMap_;
static const inline std::map<std::pair<uint, GdkEventType>, std::string> eventMap_{ static const inline std::map<std::pair<uint, GdkEventType>, std::string> eventMap_{
{std::make_pair(1, GdkEventType::GDK_BUTTON_PRESS), "on-click"}, {std::make_pair(1, GdkEventType::GDK_BUTTON_PRESS), "on-click"},
+14 -11
View File
@@ -62,11 +62,11 @@ class Bar : public sigc::trackable {
static const std::string MODE_DEFAULT; static const std::string MODE_DEFAULT;
static const std::string MODE_INVISIBLE; static const std::string MODE_INVISIBLE;
Bar(struct waybar_output *w_output, const Json::Value &); Bar(struct waybar_output* w_output, const Json::Value&);
Bar(const Bar &) = delete; Bar(const Bar&) = delete;
~Bar(); ~Bar();
void setMode(const std::string &mode); void setMode(const std::string& mode);
void setVisible(bool value); void setVisible(bool value);
void toggle(); void toggle();
void show(); void show();
@@ -75,9 +75,11 @@ class Bar : public sigc::trackable {
util::KillSignalAction getOnSigusr1Action(); util::KillSignalAction getOnSigusr1Action();
util::KillSignalAction getOnSigusr2Action(); util::KillSignalAction getOnSigusr2Action();
struct waybar_output *output; void toggleSuspend(bool suspend);
struct waybar_output* output;
Json::Value config; Json::Value config;
struct wl_surface *surface; struct wl_surface* surface;
bool visible = true; bool visible = true;
Gtk::Window window; Gtk::Window window;
Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL; Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL;
@@ -91,15 +93,16 @@ class Bar : public sigc::trackable {
#endif #endif
private: private:
void onMap(GdkEventAny *); void onMap(GdkEventAny*);
auto setupWidgets() -> void; auto setupWidgets() -> void;
void getModules(const Factory &, const std::string &, waybar::Group *); void getModules(const Factory&, const std::string&, waybar::Group*);
void setupAltFormatKeyForModule(const std::string &module_name); void setupAltFormatKeyForModule(const std::string& module_name);
void setupAltFormatKeyForModuleList(const char *module_list_name); void setupAltFormatKeyForModuleList(const char* module_list_name);
void setMode(const bar_mode &); void setMode(const bar_mode&);
void setPassThrough(bool passthrough); void setPassThrough(bool passthrough);
void setPosition(Gtk::PositionType position); void setPosition(Gtk::PositionType position);
void onConfigure(GdkEventConfigure *ev); void forceLayerCommit();
void onConfigure(GdkEventConfigure* ev);
void configureGlobalOffset(int width, int height); void configureGlobalOffset(int width, int height);
void onOutputGeometryChanged(); void onOutputGeometryChanged();
+20 -17
View File
@@ -17,35 +17,36 @@ namespace waybar {
class Client { class Client {
public: public:
static Client *inst(); static Client* inst();
int main(int argc, char *argv[]); int main(int argc, char* argv[]);
void reset(); void reset();
Glib::RefPtr<Gtk::Application> gtk_app; Glib::RefPtr<Gtk::Application> gtk_app;
Glib::RefPtr<Gdk::Display> gdk_display; Glib::RefPtr<Gdk::Display> gdk_display;
struct wl_display *wl_display = nullptr; struct wl_display* wl_display = nullptr;
struct wl_registry *registry = nullptr; struct wl_registry* registry = nullptr;
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr; struct zxdg_output_manager_v1* xdg_output_manager = nullptr;
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager = nullptr; struct zwp_idle_inhibit_manager_v1* idle_inhibit_manager = nullptr;
std::vector<std::unique_ptr<Bar>> bars; std::vector<std::unique_ptr<Bar>> bars;
Config config; Config config;
std::string bar_id; std::string bar_id;
private: private:
Client() = default; Client() = default;
const std::string getStyle(const std::string &style, std::optional<Appearance> appearance); const std::string getStyle(const std::string& style, std::optional<Appearance> appearance);
void bindInterfaces(); void bindInterfaces();
void handleOutput(struct waybar_output &output); void handleOutput(struct waybar_output& output);
auto setupCss(const std::string &css_file) -> void; auto setupCss(const std::string& css_file) -> void;
struct waybar_output &getOutput(void *); struct waybar_output& getOutput(void*);
std::vector<Json::Value> getOutputConfigs(struct waybar_output &output); std::vector<Json::Value> getOutputConfigs(struct waybar_output& output);
static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name, static void handleGlobal(void* data, struct wl_registry* registry, uint32_t name,
const char *interface, uint32_t version); const char* interface, uint32_t version);
static void handleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name); static void handleGlobalRemove(void* data, struct wl_registry* registry, uint32_t name);
static void handleOutputDone(void *, struct zxdg_output_v1 *); static void handleOutputDone(void*, struct zxdg_output_v1*);
static void handleOutputName(void *, struct zxdg_output_v1 *, const char *); void createBarsBatch();
static void handleOutputDescription(void *, struct zxdg_output_v1 *, const char *); static void handleOutputName(void*, struct zxdg_output_v1*, const char*);
static void handleOutputDescription(void*, struct zxdg_output_v1*, const char*);
void handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor); void handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor);
void handleMonitorRemoved(Glib::RefPtr<Gdk::Monitor> monitor); void handleMonitorRemoved(Glib::RefPtr<Gdk::Monitor> monitor);
void handleDeferredMonitorRemoval(Glib::RefPtr<Gdk::Monitor> monitor); void handleDeferredMonitorRemoval(Glib::RefPtr<Gdk::Monitor> monitor);
@@ -58,6 +59,8 @@ class Client {
std::string m_cssFile; std::string m_cssFile;
sigc::connection monitor_added_connection_; sigc::connection monitor_added_connection_;
sigc::connection monitor_removed_connection_; sigc::connection monitor_removed_connection_;
std::list<waybar_output*> pending_outputs_;
bool bars_scheduled_ = false;
}; };
} // namespace waybar } // namespace waybar
+11 -11
View File
@@ -14,29 +14,29 @@ namespace waybar {
class Config { class Config {
public: public:
static const std::vector<std::string> CONFIG_DIRS; static const std::vector<std::string> CONFIG_DIRS;
static const char *CONFIG_PATH_ENV; static const char* CONFIG_PATH_ENV;
/* Try to find any of provided names in the supported set of config directories */ /* Try to find any of provided names in the supported set of config directories */
static std::optional<std::string> findConfigPath( static std::optional<std::string> findConfigPath(
const std::vector<std::string> &names, const std::vector<std::string> &dirs = CONFIG_DIRS); const std::vector<std::string>& names, const std::vector<std::string>& dirs = CONFIG_DIRS);
static std::vector<std::string> tryExpandPath(const std::string &base, static std::vector<std::string> tryExpandPath(const std::string& base,
const std::string &filename); const std::string& filename);
Config() = default; Config() = default;
void load(const std::string &config); void load(const std::string& config);
Json::Value &getConfig() { return config_; } Json::Value& getConfig() { return config_; }
std::vector<Json::Value> getOutputConfigs(const std::string &name, const std::string &identifier); std::vector<Json::Value> getOutputConfigs(const std::string& name, const std::string& identifier);
private: private:
void setupConfig(Json::Value &dst, const std::string &config_file, int depth); void setupConfig(Json::Value& dst, const std::string& config_file, int depth);
void resolveConfigIncludes(Json::Value &config, int depth); void resolveConfigIncludes(Json::Value& config, int depth);
void mergeConfig(Json::Value &a_config_, Json::Value &b_config_); void mergeConfig(Json::Value& a_config_, Json::Value& b_config_);
static std::vector<std::string> findIncludePath( static std::vector<std::string> findIncludePath(
const std::string &name, const std::vector<std::string> &dirs = CONFIG_DIRS); const std::string& name, const std::vector<std::string>& dirs = CONFIG_DIRS);
std::string config_file_; std::string config_file_;
+8 -7
View File
@@ -11,13 +11,13 @@ namespace waybar {
class Group : public AModule { class Group : public AModule {
public: public:
Group(const std::string &, const std::string &, const Json::Value &, bool); Group(const std::string&, const std::string&, const Json::Value&, bool);
~Group() override = default; ~Group() override = default;
auto update() -> void override; auto update() -> void override;
operator Gtk::Widget &() override; operator Gtk::Widget&() override;
virtual Gtk::Box &getBox(); virtual Gtk::Box& getBox();
void addWidget(Gtk::Widget &widget); void addWidget(Gtk::Widget& widget);
protected: protected:
Gtk::Box box; Gtk::Box box;
@@ -27,9 +27,10 @@ class Group : public AModule {
bool is_drawer = false; bool is_drawer = false;
bool click_to_reveal = false; bool click_to_reveal = false;
std::string add_class_to_drawer_children; std::string add_class_to_drawer_children;
bool handleMouseEnter(GdkEventCrossing *const &ev) override; bool handleMouseEnter(GdkEventCrossing* const& ev) override;
bool handleMouseLeave(GdkEventCrossing *const &ev) override; bool handleMouseLeave(GdkEventCrossing* const& ev) override;
bool handleToggle(GdkEventButton *const &ev) override; bool handleToggle(GdkEventButton* const& ev) override;
bool handleScroll(GdkEventScroll* e) override;
void show_group(); void show_group();
void hide_group(); void hide_group();
}; };
+2 -2
View File
@@ -17,11 +17,11 @@ namespace waybar::modules {
class Backlight : public ALabel { class Backlight : public ALabel {
public: public:
Backlight(const std::string &, const Json::Value &); Backlight(const std::string&, const Json::Value&);
virtual ~Backlight() = default; virtual ~Backlight() = default;
auto update() -> void override; auto update() -> void override;
bool handleScroll(GdkEventScroll *e) override; bool handleScroll(GdkEventScroll* e) override;
const std::string preferred_device_; const std::string preferred_device_;
+1 -1
View File
@@ -6,7 +6,7 @@
#if defined(__linux__) #if defined(__linux__)
#include <sys/inotify.h> #include <sys/inotify.h>
#endif #endif
#include <sys/poll.h> #include <poll.h>
#include <algorithm> #include <algorithm>
#include <chrono> #include <chrono>
+1
View File
@@ -35,6 +35,7 @@ class Custom : public ALabel {
std::string id_; std::string id_;
std::string alt_; std::string alt_;
std::string tooltip_; std::string tooltip_;
std::string last_tooltip_markup_;
const bool tooltip_format_enabled_; const bool tooltip_format_enabled_;
std::vector<std::string> class_; std::vector<std::string> class_;
int percentage_; int percentage_;
+1 -1
View File
@@ -22,7 +22,7 @@ class Disk : public ALabel {
std::string path_; std::string path_;
std::string unit_; std::string unit_;
float calc_specific_divisor(const std::string divisor); float calc_specific_divisor(const std::string& divisor);
}; };
} // namespace waybar::modules } // namespace waybar::modules
+6 -6
View File
@@ -12,23 +12,23 @@ namespace waybar::modules::dwl {
class Tags : public waybar::AModule { class Tags : public waybar::AModule {
public: public:
Tags(const std::string &, const waybar::Bar &, const Json::Value &); Tags(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Tags(); virtual ~Tags();
// Handlers for wayland events // Handlers for wayland events
void handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused); void handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused);
void handle_primary_clicked(uint32_t tag); void handle_primary_clicked(uint32_t tag);
bool handle_button_press(GdkEventButton *event_button, uint32_t tag); bool handle_button_press(GdkEventButton* event_button, uint32_t tag);
struct zdwl_ipc_manager_v2 *status_manager_; struct zdwl_ipc_manager_v2* status_manager_;
struct wl_seat *seat_; struct wl_seat* seat_;
private: private:
const waybar::Bar &bar_; const waybar::Bar& bar_;
Gtk::Box box_; Gtk::Box box_;
std::vector<Gtk::Button> buttons_; std::vector<Gtk::Button> buttons_;
struct zdwl_ipc_output_v2 *output_status_; struct zdwl_ipc_output_v2* output_status_;
}; };
} /* namespace waybar::modules::dwl */ } /* namespace waybar::modules::dwl */
+7 -7
View File
@@ -13,26 +13,26 @@ namespace waybar::modules::dwl {
class Window : public AAppIconLabel, public sigc::trackable { class Window : public AAppIconLabel, public sigc::trackable {
public: public:
Window(const std::string &, const waybar::Bar &, const Json::Value &); Window(const std::string&, const waybar::Bar&, const Json::Value&);
~Window(); ~Window();
void handle_layout(const uint32_t layout); void handle_layout(const uint32_t layout);
void handle_title(const char *title); void handle_title(const char* title);
void handle_appid(const char *ppid); void handle_appid(const char* ppid);
void handle_layout_symbol(const char *layout_symbol); void handle_layout_symbol(const char* layout_symbol);
void handle_frame(); void handle_frame();
struct zdwl_ipc_manager_v2 *status_manager_; struct zdwl_ipc_manager_v2* status_manager_;
private: private:
const Bar &bar_; const Bar& bar_;
std::string title_; std::string title_;
std::string appid_; std::string appid_;
std::string layout_symbol_; std::string layout_symbol_;
uint32_t layout_; uint32_t layout_;
struct zdwl_ipc_output_v2 *output_status_; struct zdwl_ipc_output_v2* output_status_;
}; };
} // namespace waybar::modules::dwl } // namespace waybar::modules::dwl
+31 -31
View File
@@ -20,16 +20,16 @@ class Workspace;
class WorkspaceManager final : public AModule { class WorkspaceManager final : public AModule {
public: public:
WorkspaceManager(const std::string &id, const waybar::Bar &bar, const Json::Value &config); WorkspaceManager(const std::string& id, const waybar::Bar& bar, const Json::Value& config);
~WorkspaceManager() override; ~WorkspaceManager() override;
void register_manager(wl_registry *registry, uint32_t name, uint32_t version); void register_manager(wl_registry* registry, uint32_t name, uint32_t version);
void remove_workspace_group(uint32_t id); void remove_workspace_group(uint32_t id);
void remove_workspace(uint32_t id); void remove_workspace(uint32_t id);
void set_needs_sorting() { needs_sorting_ = true; } void set_needs_sorting() { needs_sorting_ = true; }
// wl events // wl events
void handle_workspace_group(ext_workspace_group_handle_v1 *handle); void handle_workspace_group(ext_workspace_group_handle_v1* handle);
void handle_workspace(ext_workspace_handle_v1 *handle); void handle_workspace(ext_workspace_handle_v1* handle);
void handle_done(); void handle_done();
void handle_finished(); void handle_finished();
@@ -38,7 +38,7 @@ class WorkspaceManager final : public AModule {
private: private:
void update() override; void update() override;
bool has_button(const Gtk::Button *button); bool has_button(const Gtk::Button* button);
void sort_workspaces(); void sort_workspaces();
void clear_buttons(); void clear_buttons();
void update_buttons(); void update_buttons();
@@ -52,10 +52,10 @@ class WorkspaceManager final : public AModule {
bool sort_by_coordinates_ = false; bool sort_by_coordinates_ = false;
bool all_outputs_ = false; bool all_outputs_ = false;
const waybar::Bar &bar_; const waybar::Bar& bar_;
Gtk::Box box_; Gtk::Box box_;
ext_workspace_manager_v1 *ext_manager_ = nullptr; ext_workspace_manager_v1* ext_manager_ = nullptr;
std::vector<std::unique_ptr<WorkspaceGroup>> groups_; std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
std::vector<std::unique_ptr<Workspace>> workspaces_; std::vector<std::unique_ptr<Workspace>> workspaces_;
@@ -64,60 +64,60 @@ class WorkspaceManager final : public AModule {
class WorkspaceGroup { class WorkspaceGroup {
public: public:
WorkspaceGroup(WorkspaceManager &manager, ext_workspace_group_handle_v1 *handle, uint32_t id); WorkspaceGroup(WorkspaceManager& manager, ext_workspace_group_handle_v1* handle, uint32_t id);
~WorkspaceGroup(); ~WorkspaceGroup();
u_int32_t id() const { return id_; } u_int32_t id() const { return id_; }
bool has_output(const wl_output *output); bool has_output(const wl_output* output);
bool has_workspace(const ext_workspace_handle_v1 *workspace); bool has_workspace(const ext_workspace_handle_v1* workspace);
// wl events // wl events
void handle_capabilities(uint32_t capabilities); void handle_capabilities(uint32_t capabilities);
void handle_output_enter(wl_output *output); void handle_output_enter(wl_output* output);
void handle_output_leave(wl_output *output); void handle_output_leave(wl_output* output);
void handle_workspace_enter(ext_workspace_handle_v1 *handle); void handle_workspace_enter(ext_workspace_handle_v1* handle);
void handle_workspace_leave(ext_workspace_handle_v1 *handle); void handle_workspace_leave(ext_workspace_handle_v1* handle);
void handle_removed(); void handle_removed();
private: private:
WorkspaceManager &workspaces_manager_; WorkspaceManager& workspaces_manager_;
ext_workspace_group_handle_v1 *ext_handle_; ext_workspace_group_handle_v1* ext_handle_;
uint32_t id_; uint32_t id_;
std::vector<wl_output *> outputs_; std::vector<wl_output*> outputs_;
std::vector<ext_workspace_handle_v1 *> workspaces_; std::vector<ext_workspace_handle_v1*> workspaces_;
}; };
class Workspace { class Workspace {
public: public:
Workspace(const Json::Value &config, WorkspaceManager &manager, ext_workspace_handle_v1 *handle, Workspace(const Json::Value& config, WorkspaceManager& manager, ext_workspace_handle_v1* handle,
uint32_t id, const std::string &name); uint32_t id, const std::string& name);
~Workspace(); ~Workspace();
ext_workspace_handle_v1 *handle() const { return ext_handle_; } ext_workspace_handle_v1* handle() const { return ext_handle_; }
u_int32_t id() const { return id_; } u_int32_t id() const { return id_; }
std::string &workspace_id() { return workspace_id_; } std::string& workspace_id() { return workspace_id_; }
std::string &name() { return name_; } std::string& name() { return name_; }
std::vector<u_int32_t> &coordinates() { return coordinates_; } std::vector<u_int32_t>& coordinates() { return coordinates_; }
Gtk::Button &button() { return button_; } Gtk::Button& button() { return button_; }
void update(); void update();
// wl events // wl events
void handle_id(const std::string &id); void handle_id(const std::string& id);
void handle_name(const std::string &name); void handle_name(const std::string& name);
void handle_coordinates(const std::vector<uint32_t> &coordinates); void handle_coordinates(const std::vector<uint32_t>& coordinates);
void handle_state(uint32_t state); void handle_state(uint32_t state);
void handle_capabilities(uint32_t capabilities); void handle_capabilities(uint32_t capabilities);
void handle_removed(); void handle_removed();
// gdk events // gdk events
bool handle_clicked(const GdkEventButton *button) const; bool handle_clicked(const GdkEventButton* button) const;
private: private:
bool has_state(uint32_t state) const { return (state_ & state) == state; } bool has_state(uint32_t state) const { return (state_ & state) == state; }
std::string icon(); std::string icon();
WorkspaceManager &workspace_manager_; WorkspaceManager& workspace_manager_;
ext_workspace_handle_v1 *ext_handle_ = nullptr; ext_workspace_handle_v1* ext_handle_ = nullptr;
uint32_t id_; uint32_t id_;
uint32_t state_ = 0; uint32_t state_ = 0;
std::string workspace_id_; std::string workspace_id_;
@@ -1,10 +1,10 @@
#include "ext-workspace-v1-client-protocol.h" #include "ext-workspace-v1-client-protocol.h"
namespace waybar::modules::ext { namespace waybar::modules::ext {
void add_registry_listener(void *data); void add_registry_listener(void* data);
void add_workspace_listener(ext_workspace_handle_v1 *workspace_handle, void *data); void add_workspace_listener(ext_workspace_handle_v1* workspace_handle, void* data);
void add_workspace_group_listener(ext_workspace_group_handle_v1 *workspace_group_handle, void add_workspace_group_listener(ext_workspace_group_handle_v1* workspace_group_handle,
void *data); void* data);
ext_workspace_manager_v1 *workspace_manager_bind(wl_registry *registry, uint32_t name, ext_workspace_manager_v1* workspace_manager_bind(wl_registry* registry, uint32_t name,
uint32_t version, void *data); uint32_t version, void* data);
} // namespace waybar::modules::ext } // namespace waybar::modules::ext
+12 -12
View File
@@ -17,7 +17,7 @@ namespace waybar::modules {
class Gamemode : public AModule { class Gamemode : public AModule {
public: public:
Gamemode(const std::string &, const Json::Value &); Gamemode(const std::string&, const Json::Value&);
virtual ~Gamemode(); virtual ~Gamemode();
auto update() -> void override; auto update() -> void override;
@@ -26,20 +26,20 @@ class Gamemode : public AModule {
const std::string DEFAULT_FORMAT = "{glyph}"; const std::string DEFAULT_FORMAT = "{glyph}";
const std::string DEFAULT_FORMAT_ALT = "{glyph} {count}"; const std::string DEFAULT_FORMAT_ALT = "{glyph} {count}";
const std::string DEFAULT_TOOLTIP_FORMAT = "Games running: {count}"; const std::string DEFAULT_TOOLTIP_FORMAT = "Games running: {count}";
const std::string DEFAULT_GLYPH = ""; const std::string DEFAULT_GLYPH = "󰊴";
void appear(const Glib::RefPtr<Gio::DBus::Connection> &connection, const Glib::ustring &name, void appear(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& name,
const Glib::ustring &name_owner); const Glib::ustring& name_owner);
void disappear(const Glib::RefPtr<Gio::DBus::Connection> &connection, const Glib::ustring &name); void disappear(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& name);
void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection> &connection, void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection>& connection,
const Glib::ustring &sender_name, const Glib::ustring &object_path, const Glib::ustring& sender_name, const Glib::ustring& object_path,
const Glib::ustring &interface_name, const Glib::ustring &signal_name, const Glib::ustring& interface_name, const Glib::ustring& signal_name,
const Glib::VariantContainerBase &parameters); const Glib::VariantContainerBase& parameters);
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name, void notify_cb(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
const Glib::VariantContainerBase &arguments); const Glib::VariantContainerBase& arguments);
void getData(); void getData();
bool handleToggle(GdkEventButton *const &) override; bool handleToggle(GdkEventButton* const&) override;
// Config // Config
std::string format = DEFAULT_FORMAT; std::string format = DEFAULT_FORMAT;
+19 -3
View File
@@ -1,8 +1,10 @@
#pragma once #pragma once
#include <atomic>
#include <filesystem> #include <filesystem>
#include <list> #include <list>
#include <mutex> #include <mutex>
#include <optional>
#include <string> #include <string>
#include <thread> #include <thread>
#include <utility> #include <utility>
@@ -34,19 +36,33 @@ class IPC {
Json::Value getSocket1JsonReply(const std::string& rq); Json::Value getSocket1JsonReply(const std::string& rq);
static std::filesystem::path getSocketFolder(const char* instanceSig); static std::filesystem::path getSocketFolder(const char* instanceSig);
/// Dispatch a Hyprland command. Automatically uses the correct protocol
/// (legacy text or Lua-based) depending on the running Hyprland version.
static std::string dispatch(const std::string& dispatcher, const std::string& arg);
/// Build a Lua-format dispatch command string.
static std::string buildLuaDispatch(const std::string& dispatcher, const std::string& arg);
protected: protected:
static std::filesystem::path socketFolder_; static std::filesystem::path socketFolder_;
/// Detect whether the running Hyprland uses the Lua-based IPC protocol.
/// Returns true for Hyprland >= 0.54 (Lua config), false for older versions.
static bool isLuaProtocol();
static std::optional<bool> s_luaProtocolDetected_; // cached detection result
private: private:
void socketListener(); void socketListener();
void parseIPC(const std::string&); void parseIPC(const std::string&);
std::thread ipcThread_; std::thread ipcThread_;
std::mutex callbackMutex_; std::mutex callbackMutex_;
std::mutex socketMutex_;
util::JsonParser parser_; util::JsonParser parser_;
std::list<std::pair<std::string, EventHandler*>> callbacks_; std::list<std::pair<std::string, EventHandler*>> callbacks_;
int socketfd_; // the hyprland socket file descriptor int socketfd_ = -1; // the hyprland socket file descriptor
pid_t socketOwnerPid_; pid_t socketOwnerPid_ = -1;
bool running_ = true; // the ipcThread will stop running when this is false std::atomic<bool> running_ = true; // the ipcThread will stop running when this is false
}; };
}; // namespace waybar::modules::hyprland }; // namespace waybar::modules::hyprland
+1
View File
@@ -26,6 +26,7 @@ class Submap : public waybar::ALabel, public EventHandler {
const Bar& bar_; const Bar& bar_;
util::JsonParser parser_; util::JsonParser parser_;
std::string submap_; std::string submap_;
std::string prev_submap_;
bool always_on_ = false; bool always_on_ = false;
std::string default_submap_ = "Default"; std::string default_submap_ = "Default";
+11 -11
View File
@@ -20,8 +20,8 @@ class Window : public waybar::AAppIconLabel, public EventHandler {
private: private:
struct Workspace { struct Workspace {
int id; int id = 0;
int windows; int windows = 0;
std::string last_window; std::string last_window;
std::string last_window_title; std::string last_window_title;
@@ -29,14 +29,14 @@ class Window : public waybar::AAppIconLabel, public EventHandler {
}; };
struct WindowData { struct WindowData {
bool floating; bool floating = false;
int monitor = -1; int monitor = -1;
std::string class_name; std::string class_name;
std::string initial_class_name; std::string initial_class_name;
std::string title; std::string title;
std::string initial_title; std::string initial_title;
bool fullscreen; bool fullscreen = false;
bool grouped; bool grouped = false;
static auto parse(const Json::Value&) -> WindowData; static auto parse(const Json::Value&) -> WindowData;
}; };
@@ -47,7 +47,7 @@ class Window : public waybar::AAppIconLabel, public EventHandler {
void queryActiveWorkspace(); void queryActiveWorkspace();
void setClass(const std::string&, bool enable); void setClass(const std::string&, bool enable);
bool separateOutputs_; bool separateOutputs_ = false;
std::mutex mutex_; std::mutex mutex_;
const Bar& bar_; const Bar& bar_;
util::JsonParser parser_; util::JsonParser parser_;
@@ -55,11 +55,11 @@ class Window : public waybar::AAppIconLabel, public EventHandler {
Workspace workspace_; Workspace workspace_;
std::string soloClass_; std::string soloClass_;
std::string lastSoloClass_; std::string lastSoloClass_;
bool solo_; bool solo_ = false;
bool allFloating_; bool allFloating_ = false;
bool swallowing_; bool swallowing_ = false;
bool fullscreen_; bool fullscreen_ = false;
bool focused_; bool focused_ = false;
IPC& m_ipc; IPC& m_ipc;
}; };
@@ -40,10 +40,11 @@ struct WindowRepr {
class WindowCreationPayload { class WindowCreationPayload {
public: public:
WindowCreationPayload(std::string workspace_name, WindowAddress window_address, WindowCreationPayload(const std::string& workspace_name, WindowAddress window_address,
WindowRepr window_repr); WindowRepr window_repr);
WindowCreationPayload(std::string workspace_name, WindowAddress window_address, WindowCreationPayload(const std::string& workspace_name, WindowAddress window_address,
std::string window_class, std::string window_title, bool is_active); const std::string& window_class, const std::string& window_title,
bool is_active);
WindowCreationPayload(Json::Value const& client_data); WindowCreationPayload(Json::Value const& client_data);
int incrementTimeSpentUncreated(); int incrementTimeSpentUncreated();
+12
View File
@@ -30,6 +30,7 @@ class Workspace {
public: public:
explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager, explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager,
const Json::Value& clients_data = Json::Value::nullRef); const Json::Value& clients_data = Json::Value::nullRef);
~Workspace();
std::string& selectIcon(std::map<std::string, std::string>& icons_map); std::string& selectIcon(std::map<std::string, std::string>& icons_map);
Gtk::Button& button() { return m_button; }; Gtk::Button& button() { return m_button; };
@@ -45,6 +46,15 @@ class Workspace {
bool isUrgent() const { return m_isUrgent; }; bool isUrgent() const { return m_isUrgent; };
bool handleClicked(GdkEventButton* bt) const; bool handleClicked(GdkEventButton* bt) const;
bool handleEnter(GdkEventCrossing* event);
bool handleLeave(GdkEventCrossing* event);
void startHoverCheck();
void stopHoverCheck();
bool syncHoverClass();
bool pointerInsideButton();
void setActive(bool value = true) { m_isActive = value; }; void setActive(bool value = true) { m_isActive = value; };
void setPersistentRule(bool value = true) { m_isPersistentRule = value; }; void setPersistentRule(bool value = true) { m_isPersistentRule = value; };
void setPersistentConfig(bool value = true) { m_isPersistentConfig = value; }; void setPersistentConfig(bool value = true) { m_isPersistentConfig = value; };
@@ -80,6 +90,8 @@ class Workspace {
bool m_isUrgent = false; bool m_isUrgent = false;
bool m_isVisible = false; bool m_isVisible = false;
sigc::connection m_hoverCheckConnection;
std::vector<WindowRepr> m_windowMap; std::vector<WindowRepr> m_windowMap;
Gtk::Button m_button; Gtk::Button m_button;
+7 -1
View File
@@ -4,6 +4,7 @@
#include <gtkmm/enums.h> #include <gtkmm/enums.h>
#include <gtkmm/label.h> #include <gtkmm/label.h>
#include <json/value.h> #include <json/value.h>
#include <sigc++/connection.h>
#include <cstdint> #include <cstdint>
#include <map> #include <map>
@@ -43,6 +44,7 @@ class Workspaces : public AModule, public EventHandler {
auto moveToMonitor() const -> bool { return m_moveToMonitor; } auto moveToMonitor() const -> bool { return m_moveToMonitor; }
auto enableTaskbar() const -> bool { return m_enableTaskbar; } auto enableTaskbar() const -> bool { return m_enableTaskbar; }
auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; } auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; }
auto barScroll() const -> bool { return m_barScroll; }
auto getBarOutput() const -> std::string { return m_bar.output->name; } auto getBarOutput() const -> std::string { return m_bar.output->name; }
auto formatBefore() const -> std::string { return m_formatBefore; } auto formatBefore() const -> std::string { return m_formatBefore; }
@@ -58,7 +60,7 @@ class Workspaces : public AModule, public EventHandler {
enum class ActiveWindowPosition { NONE, FIRST, LAST }; enum class ActiveWindowPosition { NONE, FIRST, LAST };
auto activeWindowPosition() const -> ActiveWindowPosition { return m_activeWindowPosition; } auto activeWindowPosition() const -> ActiveWindowPosition { return m_activeWindowPosition; }
std::string getRewrite(std::string window_class, std::string window_title); std::string getRewrite(const std::string& window_class, const std::string& window_title);
std::string& getWindowSeparator() { return m_formatWindowSeparator; } std::string& getWindowSeparator() { return m_formatWindowSeparator; }
bool isWorkspaceIgnored(std::string const& workspace_name); bool isWorkspaceIgnored(std::string const& workspace_name);
@@ -122,6 +124,8 @@ class Workspaces : public AModule, public EventHandler {
static std::pair<std::string, std::string> splitDoublePayload(std::string const& payload); static std::pair<std::string, std::string> splitDoublePayload(std::string const& payload);
static std::tuple<std::string, std::string, std::string> splitTriplePayload( static std::tuple<std::string, std::string, std::string> splitTriplePayload(
std::string const& payload); std::string const& payload);
// scroll events
bool handleScroll(GdkEventScroll* e) override;
// Update methods // Update methods
void doUpdate(); void doUpdate();
@@ -145,6 +149,7 @@ class Workspaces : public AModule, public EventHandler {
bool m_specialVisibleOnly = false; bool m_specialVisibleOnly = false;
bool m_persistentOnly = false; bool m_persistentOnly = false;
bool m_moveToMonitor = false; bool m_moveToMonitor = false;
bool m_barScroll = false;
Json::Value m_persistentWorkspaceConfig; Json::Value m_persistentWorkspaceConfig;
// Map for windows stored in workspaces not present in the current bar. // Map for windows stored in workspaces not present in the current bar.
@@ -204,6 +209,7 @@ class Workspaces : public AModule, public EventHandler {
std::mutex m_mutex; std::mutex m_mutex;
const Bar& m_bar; const Bar& m_bar;
Gtk::Box m_box; Gtk::Box m_box;
sigc::connection m_scrollEventConnection_;
IPC& m_ipc; IPC& m_ipc;
}; };
+6 -6
View File
@@ -13,7 +13,7 @@ namespace waybar::modules {
class JACK : public ALabel { class JACK : public ALabel {
public: public:
JACK(const std::string &, const Json::Value &); JACK(const std::string&, const Json::Value&);
virtual ~JACK() = default; virtual ~JACK() = default;
auto update() -> void override; auto update() -> void override;
@@ -25,7 +25,7 @@ class JACK : public ALabel {
private: private:
std::string JACKState(); std::string JACKState();
jack_client_t *client_; jack_client_t* client_;
jack_nframes_t bufsize_; jack_nframes_t bufsize_;
jack_nframes_t samplerate_; jack_nframes_t samplerate_;
unsigned int xruns_; unsigned int xruns_;
@@ -38,7 +38,7 @@ class JACK : public ALabel {
} // namespace waybar::modules } // namespace waybar::modules
int bufSizeCallback(jack_nframes_t size, void *obj); int bufSizeCallback(jack_nframes_t size, void* obj);
int sampleRateCallback(jack_nframes_t rate, void *obj); int sampleRateCallback(jack_nframes_t rate, void* obj);
int xrunCallback(void *obj); int xrunCallback(void* obj);
void shutdownCallback(void *obj); void shutdownCallback(void* obj);
+2
View File
@@ -3,6 +3,7 @@
#include <fmt/chrono.h> #include <fmt/chrono.h>
#include <gtkmm/label.h> #include <gtkmm/label.h>
#include <mutex>
#include <set> #include <set>
#include <unordered_map> #include <unordered_map>
@@ -41,6 +42,7 @@ class KeyboardState : public AModule {
struct libinput* libinput_; struct libinput* libinput_;
std::unordered_map<std::string, struct libinput_device*> libinput_devices_; std::unordered_map<std::string, struct libinput_device*> libinput_devices_;
std::mutex devices_mutex_; // protects libinput_devices_
std::set<int> binding_keys; std::set<int> binding_keys;
util::SleeperThread libinput_thread_, hotplug_thread_; util::SleeperThread libinput_thread_, hotplug_thread_;
+2
View File
@@ -22,6 +22,8 @@ class Memory : public ALabel {
std::unordered_map<std::string, unsigned long> meminfo_; std::unordered_map<std::string, unsigned long> meminfo_;
util::SleeperThread thread_; util::SleeperThread thread_;
std::string unit_;
}; };
} // namespace waybar::modules } // namespace waybar::modules
+6 -2
View File
@@ -33,6 +33,7 @@ class MPD : public ALabel {
detail::unique_status status_; detail::unique_status status_;
mpd_state state_; mpd_state state_;
detail::unique_song song_; detail::unique_song song_;
std::string ellipsis_;
public: public:
MPD(const std::string&, const Json::Value&); MPD(const std::string&, const Json::Value&);
@@ -44,7 +45,11 @@ class MPD : public ALabel {
std::string getFilename() const; std::string getFilename() const;
void setLabel(); void setLabel();
std::string getStateIcon() const; std::string getStateIcon() const;
std::string getOptionIcon(std::string optionName, bool activated) const; std::string getOptionIcon(const std::string& optionName, bool activated) const;
std::string getArtistStr(bool truncated) const;
std::string getAlbumArtistStr(bool truncated) const;
std::string getAlbumStr(bool truncated) const;
std::string getTitleStr(bool truncated) const;
// GUI-side methods // GUI-side methods
bool handlePlayPause(GdkEventButton* const&); bool handlePlayPause(GdkEventButton* const&);
@@ -54,7 +59,6 @@ class MPD : public ALabel {
void tryConnect(); void tryConnect();
void checkErrors(mpd_connection* conn); void checkErrors(mpd_connection* conn);
void fetchState(); void fetchState();
void queryMPD();
inline bool stopped() const { return connection_ && state_ == MPD_STATE_STOP; } inline bool stopped() const { return connection_ && state_ == MPD_STATE_STOP; }
inline bool playing() const { return connection_ && state_ == MPD_STATE_PLAY; } inline bool playing() const { return connection_ && state_ == MPD_STATE_PLAY; }
-1
View File
@@ -197,7 +197,6 @@ class Context {
void tryConnect() const; void tryConnect() const;
void checkErrors(mpd_connection*) const; void checkErrors(mpd_connection*) const;
void do_update(); void do_update();
void queryMPD() const;
void fetchState() const; void fetchState() const;
constexpr mpd_state state() const; constexpr mpd_state state() const;
void emit() const; void emit() const;
+2 -2
View File
@@ -1,13 +1,14 @@
#pragma once #pragma once
namespace detail { namespace detail {
using namespace std::literals::chrono_literals;
inline bool Context::is_connected() const { return mpd_module_->connection_ != nullptr; } inline bool Context::is_connected() const { return mpd_module_->connection_ != nullptr; }
inline bool Context::is_playing() const { return mpd_module_->playing(); } inline bool Context::is_playing() const { return mpd_module_->playing(); }
inline bool Context::is_paused() const { return mpd_module_->paused(); } inline bool Context::is_paused() const { return mpd_module_->paused(); }
inline bool Context::is_stopped() const { return mpd_module_->stopped(); } inline bool Context::is_stopped() const { return mpd_module_->stopped(); }
constexpr inline std::size_t Context::interval() const { return mpd_module_->interval_.count(); } constexpr inline std::size_t Context::interval() const { return mpd_module_->interval_ / 1s; }
inline void Context::tryConnect() const { mpd_module_->tryConnect(); } inline void Context::tryConnect() const { mpd_module_->tryConnect(); }
inline unique_connection& Context::connection() { return mpd_module_->connection_; } inline unique_connection& Context::connection() { return mpd_module_->connection_; }
constexpr inline mpd_state Context::state() const { return mpd_module_->state_; } constexpr inline mpd_state Context::state() const { return mpd_module_->state_; }
@@ -15,7 +16,6 @@ constexpr inline mpd_state Context::state() const { return mpd_module_->state_;
inline void Context::do_update() { mpd_module_->setLabel(); } inline void Context::do_update() { mpd_module_->setLabel(); }
inline void Context::checkErrors(mpd_connection* conn) const { mpd_module_->checkErrors(conn); } inline void Context::checkErrors(mpd_connection* conn) const { mpd_module_->checkErrors(conn); }
inline void Context::queryMPD() const { mpd_module_->queryMPD(); }
inline void Context::fetchState() const { mpd_module_->fetchState(); } inline void Context::fetchState() const { mpd_module_->fetchState(); }
inline void Context::emit() const { mpd_module_->emit(); } inline void Context::emit() const { mpd_module_->emit(); }
+1
View File
@@ -78,6 +78,7 @@ class Mpris : public ALabel {
PlayerctlPlayerManager* manager; PlayerctlPlayerManager* manager;
PlayerctlPlayer* player; PlayerctlPlayer* player;
PlayerctlPlayer* last_active_player_ = nullptr;
std::string lastStatus; std::string lastStatus;
std::string lastPlayer; std::string lastPlayer;
+3
View File
@@ -70,6 +70,9 @@ class Network : public ALabel {
unsigned long long bandwidth_down_total_{0}; unsigned long long bandwidth_down_total_{0};
unsigned long long bandwidth_up_total_{0}; unsigned long long bandwidth_up_total_{0};
unsigned long long bandwidth_down_prev_{0};
unsigned long long bandwidth_up_prev_{0};
std::chrono::steady_clock::time_point bandwidth_last_sample_time_;
std::string state_; std::string state_;
std::string essid_; std::string essid_;
+1 -1
View File
@@ -17,7 +17,7 @@ class EventHandler {
class IPC { class IPC {
public: public:
IPC() { startIPC(); } IPC();
void registerForIPC(const std::string& ev, EventHandler* ev_handler); void registerForIPC(const std::string& ev, EventHandler* ev_handler);
void unregisterForIPC(EventHandler* handler); void unregisterForIPC(EventHandler* handler);
+4 -4
View File
@@ -10,13 +10,13 @@ namespace waybar::modules::niri {
class Language : public ALabel, public EventHandler { class Language : public ALabel, public EventHandler {
public: public:
Language(const std::string &, const Bar &, const Json::Value &); Language(const std::string&, const Bar&, const Json::Value&);
~Language() override; ~Language() override;
void update() override; void update() override;
private: private:
void updateFromIPC(); void updateFromIPC();
void onEvent(const Json::Value &ev) override; void onEvent(const Json::Value& ev) override;
void doUpdate(); void doUpdate();
struct Layout { struct Layout {
@@ -26,10 +26,10 @@ class Language : public ALabel, public EventHandler {
std::string short_description; std::string short_description;
}; };
static Layout getLayout(const std::string &fullName); static Layout getLayout(const std::string& fullName);
std::mutex mutex_; std::mutex mutex_;
const Bar &bar_; const Bar& bar_;
std::vector<Layout> layouts_; std::vector<Layout> layouts_;
unsigned current_idx_; unsigned current_idx_;
+4 -4
View File
@@ -11,16 +11,16 @@ namespace waybar::modules::niri {
class Window : public AAppIconLabel, public EventHandler { class Window : public AAppIconLabel, public EventHandler {
public: public:
Window(const std::string &, const Bar &, const Json::Value &); Window(const std::string&, const Bar&, const Json::Value&);
~Window() override; ~Window() override;
void update() override; void update() override;
private: private:
void onEvent(const Json::Value &ev) override; void onEvent(const Json::Value& ev) override;
void doUpdate(); void doUpdate();
void setClass(const std::string &className, bool enable); void setClass(const std::string& className, bool enable);
const Bar &bar_; const Bar& bar_;
std::string oldAppId_; std::string oldAppId_;
}; };
+5 -5
View File
@@ -11,17 +11,17 @@ namespace waybar::modules::niri {
class Workspaces : public AModule, public EventHandler { class Workspaces : public AModule, public EventHandler {
public: public:
Workspaces(const std::string &, const Bar &, const Json::Value &); Workspaces(const std::string&, const Bar&, const Json::Value&);
~Workspaces() override; ~Workspaces() override;
void update() override; void update() override;
private: private:
void onEvent(const Json::Value &ev) override; void onEvent(const Json::Value& ev) override;
void doUpdate(); void doUpdate();
Gtk::Button &addButton(const Json::Value &ws); Gtk::Button& addButton(const Json::Value& ws);
std::string getIcon(const std::string &value, const Json::Value &ws); std::string getIcon(const std::string& value, const Json::Value& ws);
const Bar &bar_; const Bar& bar_;
Gtk::Box box_; Gtk::Box box_;
// Map from niri workspace id to button. // Map from niri workspace id to button.
std::unordered_map<uint64_t, Gtk::Button> buttons_; std::unordered_map<uint64_t, Gtk::Button> buttons_;
+8 -8
View File
@@ -16,15 +16,15 @@ struct Profile {
class PowerProfilesDaemon : public ALabel { class PowerProfilesDaemon : public ALabel {
public: public:
PowerProfilesDaemon(const std::string &, const Json::Value &); PowerProfilesDaemon(const std::string&, const Json::Value&);
auto update() -> void override; auto update() -> void override;
void profileChangedCb(const Gio::DBus::Proxy::MapChangedProperties &, void profileChangedCb(const Gio::DBus::Proxy::MapChangedProperties&,
const std::vector<Glib::ustring> &); const std::vector<Glib::ustring>&);
void busConnectedCb(Glib::RefPtr<Gio::AsyncResult> &r); void busConnectedCb(Glib::RefPtr<Gio::AsyncResult>& r);
void getAllPropsCb(Glib::RefPtr<Gio::AsyncResult> &r); void getAllPropsCb(Glib::RefPtr<Gio::AsyncResult>& r);
void setPropCb(Glib::RefPtr<Gio::AsyncResult> &r); void setPropCb(Glib::RefPtr<Gio::AsyncResult>& r);
void populateInitState(); void populateInitState();
bool handleToggle(GdkEventButton *const &e) override; bool handleToggle(GdkEventButton* const& e) override;
private: private:
// True if we're connected to the dbug interface. False if we're // True if we're connected to the dbug interface. False if we're
@@ -32,7 +32,7 @@ class PowerProfilesDaemon : public ALabel {
bool connected_; bool connected_;
// Look for a profile name in the list of available profiles and // Look for a profile name in the list of available profiles and
// switch activeProfile_ to it. // switch activeProfile_ to it.
void switchToProfile(std::string const &); void switchToProfile(std::string const&);
// Used to toggle/display the profiles // Used to toggle/display the profiles
std::vector<Profile> availableProfiles_; std::vector<Profile> availableProfiles_;
// Points to the active profile in the profiles list // Points to the active profile in the profiles list
+5 -4
View File
@@ -13,21 +13,22 @@ namespace waybar::modules::privacy {
class Privacy : public AModule { class Privacy : public AModule {
public: public:
Privacy(const std::string &, const Json::Value &, Gtk::Orientation, const std::string &pos); Privacy(const std::string&, const Json::Value&, Gtk::Orientation, const std::string& pos);
auto update() -> void override; auto update() -> void override;
void onPrivacyNodesChanged(); void onPrivacyNodesChanged();
private: private:
std::list<PrivacyNodeInfo *> nodes_screenshare; // Screen is being shared std::list<PrivacyNodeInfo*> nodes_screenshare; // Screen is being shared
std::list<PrivacyNodeInfo *> nodes_audio_in; // Application is using the microphone std::list<PrivacyNodeInfo*> nodes_audio_in; // Application is using the microphone
std::list<PrivacyNodeInfo *> nodes_audio_out; // Application is outputting audio std::list<PrivacyNodeInfo*> nodes_audio_out; // Application is outputting audio
std::mutex mutex_; std::mutex mutex_;
sigc::connection visibility_conn; sigc::connection visibility_conn;
// Config // Config
Gtk::Box box_; Gtk::Box box_;
std::vector<PrivacyItem*> modules_;
uint iconSpacing = 4; uint iconSpacing = 4;
uint iconSize = 20; uint iconSize = 20;
uint transition_duration = 250; uint transition_duration = 250;
+4 -4
View File
@@ -16,16 +16,16 @@ namespace waybar::modules::privacy {
class PrivacyItem : public Gtk::Revealer { class PrivacyItem : public Gtk::Revealer {
public: public:
PrivacyItem(const Json::Value &config_, enum PrivacyNodeType privacy_type_, PrivacyItem(const Json::Value& config_, enum PrivacyNodeType privacy_type_,
std::list<PrivacyNodeInfo *> *nodes, Gtk::Orientation orientation, std::list<PrivacyNodeInfo*>* nodes, Gtk::Orientation orientation,
const std::string &pos, const uint icon_size, const uint transition_duration); const std::string& pos, const uint icon_size, const uint transition_duration);
enum PrivacyNodeType privacy_type; enum PrivacyNodeType privacy_type;
void set_in_use(bool in_use); void set_in_use(bool in_use);
private: private:
std::list<PrivacyNodeInfo *> *nodes; std::list<PrivacyNodeInfo*>* nodes;
sigc::connection signal_conn; sigc::connection signal_conn;
+10 -7
View File
@@ -6,11 +6,6 @@
#include "util/audio_backend.hpp" #include "util/audio_backend.hpp"
namespace waybar::modules { namespace waybar::modules {
enum class PulseaudioSliderTarget {
Sink,
Source,
};
class PulseaudioSlider : public ASlider { class PulseaudioSlider : public ASlider {
public: public:
PulseaudioSlider(const std::string&, const Json::Value&); PulseaudioSlider(const std::string&, const Json::Value&);
@@ -21,7 +16,15 @@ class PulseaudioSlider : public ASlider {
private: private:
std::shared_ptr<util::AudioBackend> backend = nullptr; std::shared_ptr<util::AudioBackend> backend = nullptr;
PulseaudioSliderTarget target = PulseaudioSliderTarget::Sink; util::PulseaudioTarget target = util::PulseaudioTarget::Sink;
bool zero_on_mute = true;
bool unmute_on_volume_change = true;
// zero_on_mute and unmute_on_volume_change default to true
// in order to maintain previous behaviour when using a
// config in which these values are undefined
bool previously_muted = false;
}; };
} // namespace waybar::modules } // namespace waybar::modules
+11 -11
View File
@@ -10,25 +10,25 @@ namespace waybar::modules::river {
class Layout : public waybar::ALabel { class Layout : public waybar::ALabel {
public: public:
Layout(const std::string &, const waybar::Bar &, const Json::Value &); Layout(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Layout(); virtual ~Layout();
// Handlers for wayland events // Handlers for wayland events
void handle_name(const char *name); void handle_name(const char* name);
void handle_clear(); void handle_clear();
void handle_focused_output(struct wl_output *output); void handle_focused_output(struct wl_output* output);
void handle_unfocused_output(struct wl_output *output); void handle_unfocused_output(struct wl_output* output);
struct zriver_status_manager_v1 *status_manager_; struct zriver_status_manager_v1* status_manager_;
struct wl_seat *seat_; struct wl_seat* seat_;
private: private:
const waybar::Bar &bar_; const waybar::Bar& bar_;
std::string name_; std::string name_;
struct wl_output *output_; // stores the output this module belongs to struct wl_output* output_; // stores the output this module belongs to
struct wl_output *focused_output_; // stores the currently focused output struct wl_output* focused_output_; // stores the currently focused output
struct zriver_output_status_v1 *output_status_; struct zriver_output_status_v1* output_status_;
struct zriver_seat_status_v1 *seat_status_; struct zriver_seat_status_v1* seat_status_;
}; };
} /* namespace waybar::modules::river */ } /* namespace waybar::modules::river */
+6 -6
View File
@@ -10,19 +10,19 @@ namespace waybar::modules::river {
class Mode : public waybar::ALabel { class Mode : public waybar::ALabel {
public: public:
Mode(const std::string &, const waybar::Bar &, const Json::Value &); Mode(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Mode(); virtual ~Mode();
// Handlers for wayland events // Handlers for wayland events
void handle_mode(const char *mode); void handle_mode(const char* mode);
struct zriver_status_manager_v1 *status_manager_; struct zriver_status_manager_v1* status_manager_;
struct wl_seat *seat_; struct wl_seat* seat_;
private: private:
const waybar::Bar &bar_; const waybar::Bar& bar_;
std::string mode_; std::string mode_;
struct zriver_seat_status_v1 *seat_status_; struct zriver_seat_status_v1* seat_status_;
}; };
} /* namespace waybar::modules::river */ } /* namespace waybar::modules::river */
+8 -8
View File
@@ -13,27 +13,27 @@ namespace waybar::modules::river {
class Tags : public waybar::AModule { class Tags : public waybar::AModule {
public: public:
Tags(const std::string &, const waybar::Bar &, const Json::Value &); Tags(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Tags(); virtual ~Tags();
// Handlers for wayland events // Handlers for wayland events
void handle_focused_tags(uint32_t tags); void handle_focused_tags(uint32_t tags);
void handle_view_tags(struct wl_array *tags); void handle_view_tags(struct wl_array* tags);
void handle_urgent_tags(uint32_t tags); void handle_urgent_tags(uint32_t tags);
void handle_show(); void handle_show();
void handle_primary_clicked(uint32_t tag); void handle_primary_clicked(uint32_t tag);
bool handle_button_press(GdkEventButton *event_button, uint32_t tag); bool handle_button_press(GdkEventButton* event_button, uint32_t tag);
struct zriver_status_manager_v1 *status_manager_; struct zriver_status_manager_v1* status_manager_;
struct zriver_control_v1 *control_; struct zriver_control_v1* control_;
struct wl_seat *seat_; struct wl_seat* seat_;
private: private:
const waybar::Bar &bar_; const waybar::Bar& bar_;
Gtk::Box box_; Gtk::Box box_;
std::vector<Gtk::Button> buttons_; std::vector<Gtk::Button> buttons_;
struct zriver_output_status_v1 *output_status_; struct zriver_output_status_v1* output_status_;
}; };
} /* namespace waybar::modules::river */ } /* namespace waybar::modules::river */
+10 -10
View File
@@ -12,22 +12,22 @@ namespace waybar::modules::river {
class Window : public waybar::ALabel { class Window : public waybar::ALabel {
public: public:
Window(const std::string &, const waybar::Bar &, const Json::Value &); Window(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Window(); virtual ~Window();
// Handlers for wayland events // Handlers for wayland events
void handle_focused_view(const char *title); void handle_focused_view(const char* title);
void handle_focused_output(struct wl_output *output); void handle_focused_output(struct wl_output* output);
void handle_unfocused_output(struct wl_output *output); void handle_unfocused_output(struct wl_output* output);
struct zriver_status_manager_v1 *status_manager_; struct zriver_status_manager_v1* status_manager_;
struct wl_seat *seat_; struct wl_seat* seat_;
private: private:
const waybar::Bar &bar_; const waybar::Bar& bar_;
struct wl_output *output_; // stores the output this module belongs to struct wl_output* output_; // stores the output this module belongs to
struct wl_output *focused_output_; // stores the currently focused output struct wl_output* focused_output_; // stores the currently focused output
struct zriver_seat_status_v1 *seat_status_; struct zriver_seat_status_v1* seat_status_;
}; };
} /* namespace waybar::modules::river */ } /* namespace waybar::modules::river */
+5 -5
View File
@@ -11,18 +11,18 @@ namespace waybar::modules {
class Sndio : public ALabel { class Sndio : public ALabel {
public: public:
Sndio(const std::string &, const Json::Value &); Sndio(const std::string&, const Json::Value&);
virtual ~Sndio(); virtual ~Sndio();
auto update() -> void override; auto update() -> void override;
auto set_desc(struct sioctl_desc *, unsigned int) -> void; auto set_desc(struct sioctl_desc*, unsigned int) -> void;
auto put_val(unsigned int, unsigned int) -> void; auto put_val(unsigned int, unsigned int) -> void;
bool handleScroll(GdkEventScroll *) override; bool handleScroll(GdkEventScroll*) override;
bool handleToggle(GdkEventButton *const &) override; bool handleToggle(GdkEventButton* const&) override;
private: private:
auto connect_to_sndio() -> void; auto connect_to_sndio() -> void;
util::SleeperThread thread_; util::SleeperThread thread_;
struct sioctl_hdl *hdl_; struct sioctl_hdl* hdl_;
std::vector<struct pollfd> pfds_; std::vector<struct pollfd> pfds_;
unsigned int addr_; unsigned int addr_;
unsigned int volume_, old_volume_, maxval_; unsigned int volume_, old_volume_, maxval_;
+9 -2
View File
@@ -16,7 +16,7 @@ class Host {
public: public:
Host(const std::size_t id, const Json::Value&, const Bar&, Host(const std::size_t id, const Json::Value&, const Bar&,
const std::function<void(std::unique_ptr<Item>&)>&, const std::function<void(std::unique_ptr<Item>&)>&,
const std::function<void(std::unique_ptr<Item>&)>&); const std::function<void(std::unique_ptr<Item>&)>&, const std::function<void()>&);
~Host(); ~Host();
private: private:
@@ -28,9 +28,13 @@ class Host {
static void registerHost(GObject*, GAsyncResult*, gpointer); static void registerHost(GObject*, GAsyncResult*, gpointer);
static void itemRegistered(SnWatcher*, const gchar*, gpointer); static void itemRegistered(SnWatcher*, const gchar*, gpointer);
static void itemUnregistered(SnWatcher*, const gchar*, gpointer); static void itemUnregistered(SnWatcher*, const gchar*, gpointer);
void itemReady(Item&);
void itemInvalidated(Item&);
void removeItem(std::vector<std::unique_ptr<Item>>::iterator);
void clearItems();
std::tuple<std::string, std::string> getBusNameAndObjectPath(const std::string); std::tuple<std::string, std::string> getBusNameAndObjectPath(const std::string);
void addRegisteredItem(std::string service); void addRegisteredItem(const std::string& service);
std::vector<std::unique_ptr<Item>> items_; std::vector<std::unique_ptr<Item>> items_;
const std::string bus_name_; const std::string bus_name_;
@@ -39,10 +43,13 @@ class Host {
std::size_t watcher_id_; std::size_t watcher_id_;
GCancellable* cancellable_ = nullptr; GCancellable* cancellable_ = nullptr;
SnWatcher* watcher_ = nullptr; SnWatcher* watcher_ = nullptr;
sigc::connection retry_connection_;
unsigned retry_count_ = 0;
const Json::Value& config_; const Json::Value& config_;
const Bar& bar_; const Bar& bar_;
const std::function<void(std::unique_ptr<Item>&)> on_add_; const std::function<void(std::unique_ptr<Item>&)> on_add_;
const std::function<void(std::unique_ptr<Item>&)> on_remove_; const std::function<void(std::unique_ptr<Item>&)> on_remove_;
const std::function<void()> on_update_;
}; };
} // namespace waybar::modules::SNI } // namespace waybar::modules::SNI
+22 -2
View File
@@ -11,6 +11,7 @@
#include <libdbusmenu-gtk/dbusmenu-gtk.h> #include <libdbusmenu-gtk/dbusmenu-gtk.h>
#include <sigc++/trackable.h> #include <sigc++/trackable.h>
#include <functional>
#include <set> #include <set>
#include <string_view> #include <string_view>
@@ -25,9 +26,13 @@ struct ToolTip {
class Item : public sigc::trackable { class Item : public sigc::trackable {
public: public:
Item(const std::string&, const std::string&, const Json::Value&, const Bar&); Item(const std::string&, const std::string&, const Json::Value&, const Bar&,
const std::function<void(Item&)>&, const std::function<void(Item&)>&,
const std::function<void()>&);
~Item(); ~Item();
bool isReady() const;
std::string bus_name; std::string bus_name;
std::string object_path; std::string object_path;
@@ -41,9 +46,12 @@ class Item : public sigc::trackable {
std::string title; std::string title;
std::string icon_name; std::string icon_name;
Glib::RefPtr<Gdk::Pixbuf> icon_pixmap; Glib::RefPtr<Gdk::Pixbuf> icon_pixmap;
bool has_custom_icon_ = false;
Glib::RefPtr<Gtk::IconTheme> icon_theme; Glib::RefPtr<Gtk::IconTheme> icon_theme;
std::string overlay_icon_name; std::string overlay_icon_name;
Glib::RefPtr<Gdk::Pixbuf> overlay_icon_pixmap;
std::string attention_icon_name; std::string attention_icon_name;
Glib::RefPtr<Gdk::Pixbuf> attention_icon_pixmap;
std::string attention_movie_name; std::string attention_movie_name;
std::string icon_theme_path; std::string icon_theme_path;
std::string menu; std::string menu;
@@ -62,6 +70,8 @@ class Item : public sigc::trackable {
void proxyReady(Glib::RefPtr<Gio::AsyncResult>& result); void proxyReady(Glib::RefPtr<Gio::AsyncResult>& result);
void setProperty(const Glib::ustring& name, Glib::VariantBase& value); void setProperty(const Glib::ustring& name, Glib::VariantBase& value);
void setStatus(const Glib::ustring& value); void setStatus(const Glib::ustring& value);
void setReady();
void invalidate();
void setCustomIcon(const std::string& id); void setCustomIcon(const std::string& id);
void getUpdatedProperties(); void getUpdatedProperties();
void processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& result); void processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& result);
@@ -69,8 +79,13 @@ class Item : public sigc::trackable {
const Glib::VariantContainerBase& arguments); const Glib::VariantContainerBase& arguments);
void updateImage(); void updateImage();
Glib::RefPtr<Gdk::Pixbuf> extractPixBuf(GVariant* variant); static Glib::RefPtr<Gdk::Pixbuf> extractPixBuf(GVariant* variant);
Glib::RefPtr<Gdk::Pixbuf> getIconPixbuf(); Glib::RefPtr<Gdk::Pixbuf> getIconPixbuf();
Glib::RefPtr<Gdk::Pixbuf> getAttentionIconPixbuf();
Glib::RefPtr<Gdk::Pixbuf> getOverlayIconPixbuf();
Glib::RefPtr<Gdk::Pixbuf> loadIconFromNameOrFile(const std::string& name, bool log_failure);
static Glib::RefPtr<Gdk::Pixbuf> overlayPixbufs(const Glib::RefPtr<Gdk::Pixbuf>&,
const Glib::RefPtr<Gdk::Pixbuf>&);
Glib::RefPtr<Gdk::Pixbuf> getIconByName(const std::string& name, int size); Glib::RefPtr<Gdk::Pixbuf> getIconByName(const std::string& name, int size);
double getScaledIconSize(); double getScaledIconSize();
static void onMenuDestroyed(Item* self, GObject* old_menu_pointer); static void onMenuDestroyed(Item* self, GObject* old_menu_pointer);
@@ -86,8 +101,13 @@ class Item : public sigc::trackable {
gdouble distance_scrolled_y_ = 0; gdouble distance_scrolled_y_ = 0;
// visibility of items with Status == Passive // visibility of items with Status == Passive
bool show_passive_ = false; bool show_passive_ = false;
bool ready_ = false;
Glib::ustring status_ = "active";
const Bar& bar_; const Bar& bar_;
const std::function<void(Item&)> on_ready_;
const std::function<void(Item&)> on_invalidate_;
const std::function<void()> on_updated_;
Glib::RefPtr<Gio::DBus::Proxy> proxy_; Glib::RefPtr<Gio::DBus::Proxy> proxy_;
Glib::RefPtr<Gio::Cancellable> cancellable_; Glib::RefPtr<Gio::Cancellable> cancellable_;
+1 -1
View File
@@ -19,9 +19,9 @@ class Tray : public AModule {
private: private:
void onAdd(std::unique_ptr<Item>& item); void onAdd(std::unique_ptr<Item>& item);
void onRemove(std::unique_ptr<Item>& item); void onRemove(std::unique_ptr<Item>& item);
void queueUpdate();
static inline std::size_t nb_hosts_ = 0; static inline std::size_t nb_hosts_ = 0;
bool show_passive_ = false;
Gtk::Box box_; Gtk::Box box_;
SNI::Watcher::singleton watcher_; SNI::Watcher::singleton watcher_;
SNI::Host host_; SNI::Host host_;
+14 -14
View File
@@ -30,27 +30,27 @@ class Watcher {
typedef struct { typedef struct {
GfWatchType type; GfWatchType type;
Watcher *watcher; Watcher* watcher;
gchar *service; gchar* service;
gchar *bus_name; gchar* bus_name;
gchar *object_path; gchar* object_path;
guint watch_id; guint watch_id;
} GfWatch; } GfWatch;
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection> &, Glib::ustring); void busAcquired(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
static gboolean handleRegisterHost(Watcher *, GDBusMethodInvocation *, const gchar *); static gboolean handleRegisterHost(Watcher*, GDBusMethodInvocation*, const gchar*);
static gboolean handleRegisterItem(Watcher *, GDBusMethodInvocation *, const gchar *); static gboolean handleRegisterItem(Watcher*, GDBusMethodInvocation*, const gchar*);
static GfWatch *gfWatchFind(GSList *list, const gchar *bus_name, const gchar *object_path); static GfWatch* gfWatchFind(GSList* list, const gchar* bus_name, const gchar* object_path);
static GfWatch *gfWatchNew(GfWatchType, const gchar *, const gchar *, const gchar *, Watcher *); static GfWatch* gfWatchNew(GfWatchType, const gchar*, const gchar*, const gchar*, Watcher*);
static void nameVanished(GDBusConnection *connection, const char *name, gpointer data); static void nameVanished(GDBusConnection* connection, const char* name, gpointer data);
static void gfWatchFree(gpointer data); static void gfWatchFree(gpointer data);
void updateRegisteredItems(SnWatcher *obj); void updateRegisteredItems(SnWatcher* obj);
uint32_t bus_name_id_; uint32_t bus_name_id_;
GSList *hosts_ = nullptr; GSList* hosts_ = nullptr;
GSList *items_ = nullptr; GSList* items_ = nullptr;
SnWatcher *watcher_ = nullptr; SnWatcher* watcher_ = nullptr;
}; };
} // namespace waybar::modules::SNI } // namespace waybar::modules::SNI
+1 -1
View File
@@ -37,7 +37,7 @@ class BarIpcClient {
void onModeUpdate(bool visible_by_modifier); void onModeUpdate(bool visible_by_modifier);
void onUrgencyUpdate(bool visible_by_urgency); void onUrgencyUpdate(bool visible_by_urgency);
void update(); void update();
bool isModuleEnabled(std::string name); bool isModuleEnabled(const std::string& name);
Bar& bar_; Bar& bar_;
util::JsonParser parser_; util::JsonParser parser_;
+11 -9
View File
@@ -12,6 +12,8 @@
#include <string> #include <string>
#include "ipc.hpp" #include "ipc.hpp"
#include "util/SafeSignal.hpp"
#include "util/scoped_fd.hpp"
#include "util/sleeper_thread.hpp" #include "util/sleeper_thread.hpp"
namespace waybar::modules::sway { namespace waybar::modules::sway {
@@ -27,25 +29,25 @@ class Ipc {
std::string payload; std::string payload;
}; };
sigc::signal<void, const struct ipc_response &> signal_event; ::waybar::SafeSignal<const struct ipc_response&> signal_event;
sigc::signal<void, const struct ipc_response &> signal_cmd; ::waybar::SafeSignal<const struct ipc_response&> signal_cmd;
void sendCmd(uint32_t type, const std::string &payload = ""); void sendCmd(uint32_t type, const std::string& payload = "");
void subscribe(const std::string &payload); void subscribe(const std::string& payload);
void handleEvent(); void handleEvent();
void setWorker(std::function<void()> &&func); void setWorker(std::function<void()>&& func);
protected: protected:
static inline const std::string ipc_magic_ = "i3-ipc"; static inline const std::string ipc_magic_ = "i3-ipc";
static inline const size_t ipc_header_size_ = ipc_magic_.size() + 8; static inline const size_t ipc_header_size_ = ipc_magic_.size() + 8;
const std::string getSocketPath() const; const std::string getSocketPath() const;
int open(const std::string &) const; int open(const std::string&) const;
struct ipc_response send(int fd, uint32_t type, const std::string &payload = ""); struct ipc_response send(int fd, uint32_t type, const std::string& payload = "");
struct ipc_response recv(int fd); struct ipc_response recv(int fd);
int fd_; util::ScopedFd fd_;
int fd_event_; util::ScopedFd fd_event_;
std::mutex mutex_; std::mutex mutex_;
util::SleeperThread thread_; util::SleeperThread thread_;
}; };
+1 -1
View File
@@ -47,7 +47,7 @@ class Language : public ALabel, public sigc::trackable {
void onEvent(const struct Ipc::ipc_response&); void onEvent(const struct Ipc::ipc_response&);
void onCmd(const struct Ipc::ipc_response&); void onCmd(const struct Ipc::ipc_response&);
auto set_current_layout(std::string current_layout) -> void; auto set_current_layout(const std::string& current_layout) -> void;
auto init_layouts_map(const std::vector<std::string>& used_layouts) -> void; auto init_layouts_map(const std::vector<std::string>& used_layouts) -> void;
const static std::string XKB_LAYOUT_NAMES_KEY; const static std::string XKB_LAYOUT_NAMES_KEY;
+3 -2
View File
@@ -24,10 +24,11 @@ class Workspaces : public AModule, public sigc::trackable {
private: private:
static constexpr std::string_view workspace_switch_cmd_ = "workspace {} \"{}\""; static constexpr std::string_view workspace_switch_cmd_ = "workspace {} \"{}\"";
static constexpr std::string_view workspace_switch_number_cmd_ = "workspace {} number {}";
static constexpr std::string_view persistent_workspace_switch_cmd_ = static constexpr std::string_view persistent_workspace_switch_cmd_ =
R"(workspace {} "{}"; move workspace to output "{}"; workspace {} "{}")"; R"(workspace {} "{}"; move workspace to output "{}"; workspace {} "{}")";
static int convertWorkspaceNameToNum(std::string name); static int convertWorkspaceNameToNum(const std::string& name);
static int windowRewritePriorityFunction(std::string const& window_rule); static int windowRewritePriorityFunction(std::string const& window_rule);
void onCmd(const struct Ipc::ipc_response&); void onCmd(const struct Ipc::ipc_response&);
@@ -40,7 +41,7 @@ class Workspaces : public AModule, public sigc::trackable {
std::string getIcon(const std::string&, const Json::Value&); std::string getIcon(const std::string&, const Json::Value&);
std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const; std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const;
uint16_t getWorkspaceIndex(const std::string& name) const; uint16_t getWorkspaceIndex(const std::string& name) const;
static std::string trimWorkspaceName(std::string); static std::string trimWorkspaceName(const std::string&);
bool handleScroll(GdkEventScroll* /*unused*/) override; bool handleScroll(GdkEventScroll* /*unused*/) override;
const Bar& bar_; const Bar& bar_;
+31 -11
View File
@@ -3,6 +3,7 @@
#include <giomm/dbusproxy.h> #include <giomm/dbusproxy.h>
#include <string> #include <string>
#include <vector>
#include "ALabel.hpp" #include "ALabel.hpp"
@@ -10,24 +11,43 @@ namespace waybar::modules {
class SystemdFailedUnits : public ALabel { class SystemdFailedUnits : public ALabel {
public: public:
SystemdFailedUnits(const std::string &, const Json::Value &); SystemdFailedUnits(const std::string&, const Json::Value&);
virtual ~SystemdFailedUnits(); virtual ~SystemdFailedUnits() = default;
auto update() -> void override; auto update() -> void override;
private: private:
bool hide_on_ok; struct FailedUnit {
std::string format_ok; std::string name;
std::string description;
std::string load_state;
std::string active_state;
std::string sub_state;
std::string scope;
};
bool update_pending; bool hide_on_ok_;
std::string system_state, user_state, overall_state; std::string format_ok_;
uint32_t nr_failed_system, nr_failed_user, nr_failed; std::string tooltip_format_;
std::string last_status; std::string tooltip_format_ok_;
Glib::RefPtr<Gio::DBus::Proxy> system_proxy, user_proxy; std::string tooltip_unit_format_;
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name, bool update_pending_;
const Glib::VariantContainerBase &arguments); std::string system_state_, user_state_, overall_state_;
uint32_t nr_failed_system_, nr_failed_user_, nr_failed_;
std::string last_status_;
Glib::RefPtr<Gio::DBus::Proxy> system_props_proxy_, user_props_proxy_;
Glib::RefPtr<Gio::DBus::Proxy> system_manager_proxy_, user_manager_proxy_;
std::vector<FailedUnit> failed_units_;
void notify_cb(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
const Glib::VariantContainerBase& arguments);
void RequestFailedUnits(); void RequestFailedUnits();
void RequestFailedUnitsList();
void RequestSystemState(); void RequestSystemState();
std::vector<FailedUnit> LoadFailedUnitsList(const char* kind,
Glib::RefPtr<Gio::DBus::Proxy>& proxy,
const std::string& scope);
std::string BuildTooltipFailedList() const;
void updateData(); void updateData();
}; };
+2
View File
@@ -14,6 +14,8 @@ class Temperature : public ALabel {
Temperature(const std::string&, const Json::Value&); Temperature(const std::string&, const Json::Value&);
virtual ~Temperature() = default; virtual ~Temperature() = default;
auto update() -> void override; auto update() -> void override;
void suspend() override;
void resume() override;
private: private:
float getTemperature(); float getTemperature();
+22 -22
View File
@@ -12,7 +12,7 @@ namespace waybar::modules {
class UPower final : public AIconLabel { class UPower final : public AIconLabel {
public: public:
UPower(const std::string &, const Json::Value &); UPower(const std::string&, const Json::Value&);
virtual ~UPower(); virtual ~UPower();
auto update() -> void override; auto update() -> void override;
@@ -30,17 +30,17 @@ class UPower final : public AIconLabel {
// UPower device info // UPower device info
struct upDevice_output { struct upDevice_output {
UpDevice *upDevice{NULL}; UpDevice* upDevice{NULL};
double percentage{0.0}; double percentage{0.0};
double temperature{0.0}; double temperature{0.0};
guint64 time_full{0u}; guint64 time_full{0u};
guint64 time_empty{0u}; guint64 time_empty{0u};
gchar *icon_name{(char *)'\0'}; gchar* icon_name{(char*)'\0'};
bool upDeviceValid{false}; bool upDeviceValid{false};
UpDeviceState state; UpDeviceState state;
UpDeviceKind kind; UpDeviceKind kind;
char *nativePath{(char *)'\0'}; char* nativePath{(char*)'\0'};
char *model{(char *)'\0'}; char* model{(char*)'\0'};
}; };
// Technical variables // Technical variables
@@ -53,13 +53,13 @@ class UPower final : public AIconLabel {
bool sleeping_; bool sleeping_;
// Technical functions // Technical functions
void addDevice(UpDevice *); void addDevice(UpDevice*);
void removeDevice(const gchar *); void removeDevice(const gchar*);
void removeDevices(); void removeDevices();
void resetDevices(); void resetDevices();
void setDisplayDevice(); void setDisplayDevice();
const Glib::ustring getText(const upDevice_output &upDevice_, const std::string &format); const Glib::ustring getText(const upDevice_output& upDevice_, const std::string& format);
bool queryTooltipCb(int, int, bool, const Glib::RefPtr<Gtk::Tooltip> &); bool queryTooltipCb(int, int, bool, const Glib::RefPtr<Gtk::Tooltip>&);
// DBUS variables // DBUS variables
guint watcherID_; guint watcherID_;
@@ -67,28 +67,28 @@ class UPower final : public AIconLabel {
guint subscrID_{0u}; guint subscrID_{0u};
// UPower variables // UPower variables
UpClient *upClient_; UpClient* upClient_;
upDevice_output upDevice_; // Device to display upDevice_output upDevice_; // Device to display
typedef std::unordered_map<std::string, upDevice_output> Devices; typedef std::unordered_map<std::string, upDevice_output> Devices;
Devices devices_; Devices devices_;
bool upRunning_{true}; bool upRunning_{true};
// DBus callbacks // DBus callbacks
void getConn_cb(Glib::RefPtr<Gio::AsyncResult> &result); void getConn_cb(Glib::RefPtr<Gio::AsyncResult>& result);
void onAppear(const Glib::RefPtr<Gio::DBus::Connection> &, const Glib::ustring &, void onAppear(const Glib::RefPtr<Gio::DBus::Connection>&, const Glib::ustring&,
const Glib::ustring &); const Glib::ustring&);
void onVanished(const Glib::RefPtr<Gio::DBus::Connection> &, const Glib::ustring &); void onVanished(const Glib::RefPtr<Gio::DBus::Connection>&, const Glib::ustring&);
void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection> &connection, void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection>& connection,
const Glib::ustring &sender_name, const Glib::ustring &object_path, const Glib::ustring& sender_name, const Glib::ustring& object_path,
const Glib::ustring &interface_name, const Glib::ustring &signal_name, const Glib::ustring& interface_name, const Glib::ustring& signal_name,
const Glib::VariantContainerBase &parameters); const Glib::VariantContainerBase& parameters);
// UPower callbacks // UPower callbacks
static void deviceAdded_cb(UpClient *client, UpDevice *device, gpointer data); static void deviceAdded_cb(UpClient* client, UpDevice* device, gpointer data);
static void deviceRemoved_cb(UpClient *client, const gchar *objectPath, gpointer data); static void deviceRemoved_cb(UpClient* client, const gchar* objectPath, gpointer data);
static void deviceNotify_cb(UpDevice *device, GParamSpec *pspec, gpointer user_data); static void deviceNotify_cb(UpDevice* device, GParamSpec* pspec, gpointer user_data);
// UPower secondary functions // UPower secondary functions
void getUpDeviceInfo(upDevice_output &upDevice_); void getUpDeviceInfo(upDevice_output& upDevice_);
}; };
} // namespace waybar::modules } // namespace waybar::modules
+5 -19
View File
@@ -12,6 +12,8 @@
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
#include "util/scoped_fd.hpp"
namespace waybar::modules::wayfire { namespace waybar::modules::wayfire {
using EventHandler = std::function<void(const std::string& event)>; using EventHandler = std::function<void(const std::string& event)>;
@@ -71,25 +73,9 @@ struct State {
auto update_view(const Json::Value& view) -> void; auto update_view(const Json::Value& view) -> void;
}; };
struct Sock { using Sock = util::ScopedFd;
int fd;
Sock(int fd) : fd{fd} {} class IPC : public std::enable_shared_from_this<IPC> {
~Sock() { close(fd); }
Sock(const Sock&) = delete;
auto operator=(const Sock&) = delete;
Sock(Sock&& rhs) noexcept {
fd = rhs.fd;
rhs.fd = -1;
}
auto& operator=(Sock&& rhs) noexcept {
fd = rhs.fd;
rhs.fd = -1;
return *this;
}
};
class IPC {
static std::weak_ptr<IPC> instance; static std::weak_ptr<IPC> instance;
Json::CharReaderBuilder reader_builder; Json::CharReaderBuilder reader_builder;
Json::StreamWriterBuilder writer_builder; Json::StreamWriterBuilder writer_builder;
@@ -98,7 +84,7 @@ class IPC {
State state; State state;
std::mutex state_mutex; std::mutex state_mutex;
IPC() { start(); } IPC() = default;
static auto connect() -> Sock; static auto connect() -> Sock;
auto receive(Sock& sock) -> Json::Value; auto receive(Sock& sock) -> Json::Value;
+35 -35
View File
@@ -33,8 +33,8 @@ class Taskbar;
class Task { class Task {
public: public:
Task(const waybar::Bar &, const Json::Value &, Taskbar *, Task(const waybar::Bar&, const Json::Value&, Taskbar*, struct zwlr_foreign_toplevel_handle_v1*,
struct zwlr_foreign_toplevel_handle_v1 *, struct wl_seat *); struct wl_seat*);
~Task(); ~Task();
public: public:
@@ -53,11 +53,11 @@ class Task {
static uint32_t global_id; static uint32_t global_id;
private: private:
const waybar::Bar &bar_; const waybar::Bar& bar_;
const Json::Value &config_; const Json::Value& config_;
Taskbar *tbar_; Taskbar* tbar_;
struct zwlr_foreign_toplevel_handle_v1 *handle_; struct zwlr_foreign_toplevel_handle_v1* handle_;
struct wl_seat *seat_; struct wl_seat* seat_;
uint32_t id_; uint32_t id_;
@@ -89,7 +89,7 @@ class Task {
std::string repr() const; std::string repr() const;
std::string state_string(bool = false) const; std::string state_string(bool = false) const;
void set_minimize_hint(); void set_minimize_hint();
void on_button_size_allocated(Gtk::Allocation &alloc); void on_button_size_allocated(Gtk::Allocation& alloc);
void hide_if_ignored(); void hide_if_ignored();
public: public:
@@ -105,26 +105,26 @@ class Task {
public: public:
/* Callbacks for the wlr protocol */ /* Callbacks for the wlr protocol */
void handle_title(const char *); void handle_title(const char*);
void handle_app_id(const char *); void handle_app_id(const char*);
void handle_output_enter(struct wl_output *); void handle_output_enter(struct wl_output*);
void handle_output_leave(struct wl_output *); void handle_output_leave(struct wl_output*);
void handle_state(struct wl_array *); void handle_state(struct wl_array*);
void handle_done(); void handle_done();
void handle_closed(); void handle_closed();
/* Callbacks for Gtk events */ /* Callbacks for Gtk events */
bool handle_clicked(GdkEventButton *); bool handle_clicked(GdkEventButton*);
bool handle_button_release(GdkEventButton *); bool handle_button_release(GdkEventButton*);
bool handle_motion_notify(GdkEventMotion *); bool handle_motion_notify(GdkEventMotion*);
void handle_drag_data_get(const Glib::RefPtr<Gdk::DragContext> &context, void handle_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context,
Gtk::SelectionData &selection_data, guint info, guint time); Gtk::SelectionData& selection_data, guint info, guint time);
void handle_drag_data_received(const Glib::RefPtr<Gdk::DragContext> &context, int x, int y, void handle_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y,
Gtk::SelectionData selection_data, guint info, guint time); Gtk::SelectionData selection_data, guint info, guint time);
public: public:
bool operator==(const Task &) const; bool operator==(const Task&) const;
bool operator!=(const Task &) const; bool operator!=(const Task&) const;
public: public:
void update(); void update();
@@ -142,12 +142,12 @@ using TaskPtr = std::unique_ptr<Task>;
class Taskbar : public waybar::AModule { class Taskbar : public waybar::AModule {
public: public:
Taskbar(const std::string &, const waybar::Bar &, const Json::Value &); Taskbar(const std::string&, const waybar::Bar&, const Json::Value&);
~Taskbar(); ~Taskbar();
void update(); void update();
private: private:
const waybar::Bar &bar_; const waybar::Bar& bar_;
Gtk::Box box_; Gtk::Box box_;
std::vector<TaskPtr> tasks_; std::vector<TaskPtr> tasks_;
@@ -155,30 +155,30 @@ class Taskbar : public waybar::AModule {
std::unordered_set<std::string> ignore_list_; std::unordered_set<std::string> ignore_list_;
std::map<std::string, std::string> app_ids_replace_map_; std::map<std::string, std::string> app_ids_replace_map_;
struct zwlr_foreign_toplevel_manager_v1 *manager_; struct zwlr_foreign_toplevel_manager_v1* manager_;
struct wl_seat *seat_; struct wl_seat* seat_;
public: public:
/* Callbacks for global registration */ /* Callbacks for global registration */
void register_manager(struct wl_registry *, uint32_t name, uint32_t version); void register_manager(struct wl_registry*, uint32_t name, uint32_t version);
void register_seat(struct wl_registry *, uint32_t name, uint32_t version); void register_seat(struct wl_registry*, uint32_t name, uint32_t version);
/* Callbacks for the wlr protocol */ /* Callbacks for the wlr protocol */
void handle_toplevel_create(struct zwlr_foreign_toplevel_handle_v1 *); void handle_toplevel_create(struct zwlr_foreign_toplevel_handle_v1*);
void handle_finished(); void handle_finished();
public: public:
void add_button(Gtk::Button &); void add_button(Gtk::Button&);
void move_button(Gtk::Button &, int); void move_button(Gtk::Button&, int);
void remove_button(Gtk::Button &); void remove_button(Gtk::Button&);
void remove_task(uint32_t); void remove_task(uint32_t);
bool show_output(struct wl_output *) const; bool show_output(struct wl_output*) const;
bool all_outputs() const; bool all_outputs() const;
const IconLoader &icon_loader() const; const IconLoader& icon_loader() const;
const std::unordered_set<std::string> &ignore_list() const; const std::unordered_set<std::string>& ignore_list() const;
const std::map<std::string, std::string> &app_ids_replace_map() const; const std::map<std::string, std::string>& app_ids_replace_map() const;
}; };
} /* namespace waybar::modules::wlr */ } /* namespace waybar::modules::wlr */
+20 -5
View File
@@ -3,6 +3,7 @@
#include <glibmm/dispatcher.h> #include <glibmm/dispatcher.h>
#include <sigc++/signal.h> #include <sigc++/signal.h>
#include <cstddef>
#include <functional> #include <functional>
#include <mutex> #include <mutex>
#include <queue> #include <queue>
@@ -11,11 +12,6 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#ifdef __OpenBSD__
#define SIGRTMIN SIGUSR1 - 1
#define SIGRTMAX SIGUSR1 + 1
#endif
namespace waybar { namespace waybar {
/** /**
@@ -27,6 +23,12 @@ struct SafeSignal : sigc::signal<void(std::decay_t<Args>...)> {
public: public:
SafeSignal() { dp_.connect(sigc::mem_fun(*this, &SafeSignal::handle_event)); } SafeSignal() { dp_.connect(sigc::mem_fun(*this, &SafeSignal::handle_event)); }
void set_max_queued_events(std::size_t max_queued_events) {
std::unique_lock lock(mutex_);
max_queued_events_ = max_queued_events;
trim_queue_locked();
}
template <typename... EmitArgs> template <typename... EmitArgs>
void emit(EmitArgs&&... args) { void emit(EmitArgs&&... args) {
if (main_tid_ == std::this_thread::get_id()) { if (main_tid_ == std::this_thread::get_id()) {
@@ -41,6 +43,9 @@ struct SafeSignal : sigc::signal<void(std::decay_t<Args>...)> {
} else { } else {
{ {
std::unique_lock lock(mutex_); std::unique_lock lock(mutex_);
if (max_queued_events_ != 0 && queue_.size() >= max_queued_events_) {
queue_.pop();
}
queue_.emplace(std::forward<EmitArgs>(args)...); queue_.emplace(std::forward<EmitArgs>(args)...);
} }
dp_.emit(); dp_.emit();
@@ -60,6 +65,15 @@ struct SafeSignal : sigc::signal<void(std::decay_t<Args>...)> {
using signal_t::emit_reverse; using signal_t::emit_reverse;
using signal_t::make_slot; using signal_t::make_slot;
void trim_queue_locked() {
if (max_queued_events_ == 0) {
return;
}
while (queue_.size() > max_queued_events_) {
queue_.pop();
}
}
void handle_event() { void handle_event() {
for (std::unique_lock lock(mutex_); !queue_.empty(); lock.lock()) { for (std::unique_lock lock(mutex_); !queue_.empty(); lock.lock()) {
auto args = queue_.front(); auto args = queue_.front();
@@ -72,6 +86,7 @@ struct SafeSignal : sigc::signal<void(std::decay_t<Args>...)> {
Glib::Dispatcher dp_; Glib::Dispatcher dp_;
std::mutex mutex_; std::mutex mutex_;
std::queue<arg_tuple_t> queue_; std::queue<arg_tuple_t> queue_;
std::size_t max_queued_events_ = 4096;
const std::thread::id main_tid_ = std::this_thread::get_id(); const std::thread::id main_tid_ = std::this_thread::get_id();
// cache functor for signal emission to avoid recreating it on each event // cache functor for signal emission to avoid recreating it on each event
const slot_t cached_fn_ = make_slot(); const slot_t cached_fn_ = make_slot();
+10 -1
View File
@@ -14,6 +14,11 @@
namespace waybar::util { namespace waybar::util {
enum class PulseaudioTarget {
Sink,
Source,
};
class AudioBackend { class AudioBackend {
private: private:
static void subscribeCb(pa_context*, pa_subscription_event_type_t, uint32_t, void*); static void subscribeCb(pa_context*, pa_subscription_event_type_t, uint32_t, void*);
@@ -92,7 +97,11 @@ class AudioBackend {
void toggleSourceMute(); void toggleSourceMute();
void toggleSourceMute(bool); void toggleSourceMute(bool);
uint16_t getVolume(PulseaudioTarget) const;
bool getMuted(PulseaudioTarget) const;
void unmute(PulseaudioTarget);
bool isBluetooth(); bool isBluetooth();
}; };
} // namespace waybar::util } // namespace waybar::util
+8 -8
View File
@@ -36,7 +36,7 @@ class BacklightDevice {
void set_max(int max); void set_max(int max);
bool get_powered() const; bool get_powered() const;
void set_powered(bool powered); void set_powered(bool powered);
friend inline bool operator==(const BacklightDevice &lhs, const BacklightDevice &rhs) { friend inline bool operator==(const BacklightDevice& lhs, const BacklightDevice& rhs) {
return lhs.name_ == rhs.name_ && lhs.actual_ == rhs.actual_ && lhs.max_ == rhs.max_; return lhs.name_ == rhs.name_ && lhs.actual_ == rhs.actual_ && lhs.max_ == rhs.max_;
} }
@@ -52,25 +52,25 @@ class BacklightBackend {
BacklightBackend(std::chrono::milliseconds interval, std::function<void()> on_updated_cb = NOOP); BacklightBackend(std::chrono::milliseconds interval, std::function<void()> on_updated_cb = NOOP);
// const inline BacklightDevice *get_best_device(std::string_view preferred_device); // const inline BacklightDevice *get_best_device(std::string_view preferred_device);
const BacklightDevice *get_previous_best_device(); const BacklightDevice* get_previous_best_device();
void set_previous_best_device(const BacklightDevice *device); void set_previous_best_device(const BacklightDevice* device);
void set_brightness(const std::string &preferred_device, ChangeType change_type, double step); void set_brightness(const std::string& preferred_device, ChangeType change_type, double step);
void set_scaled_brightness(const std::string &preferred_device, int brightness); void set_scaled_brightness(const std::string& preferred_device, int brightness);
int get_scaled_brightness(const std::string &preferred_device); int get_scaled_brightness(const std::string& preferred_device);
bool is_login_proxy_initialized() const { return static_cast<bool>(login_proxy_); } bool is_login_proxy_initialized() const { return static_cast<bool>(login_proxy_); }
static const BacklightDevice *best_device(const std::vector<BacklightDevice> &devices, static const BacklightDevice* best_device(const std::vector<BacklightDevice>& devices,
std::string_view); std::string_view);
std::vector<BacklightDevice> devices_; std::vector<BacklightDevice> devices_;
std::mutex udev_thread_mutex_; std::mutex udev_thread_mutex_;
private: private:
void set_brightness_internal(const std::string &device_name, int brightness, int max_brightness); void set_brightness_internal(const std::string& device_name, int brightness, int max_brightness);
std::function<void()> on_updated_cb_; std::function<void()> on_updated_cb_;
std::chrono::milliseconds polling_interval_; std::chrono::milliseconds polling_interval_;
+128 -128
View File
@@ -78,7 +78,7 @@ class Column {
class iterator { class iterator {
friend Column; friend Column;
Column const &m_column; Column const& m_column;
size_t m_stringIndex = 0; size_t m_stringIndex = 0;
size_t m_pos = 0; size_t m_pos = 0;
@@ -86,10 +86,10 @@ class Column {
size_t m_end = 0; size_t m_end = 0;
bool m_suffix = false; bool m_suffix = false;
iterator(Column const &column, size_t stringIndex) iterator(Column const& column, size_t stringIndex)
: m_column(column), m_stringIndex(stringIndex) {} : m_column(column), m_stringIndex(stringIndex) {}
auto line() const -> std::string const & { return m_column.m_strings[m_stringIndex]; } auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
auto isBoundary(size_t at) const -> bool { auto isBoundary(size_t at) const -> bool {
assert(at > 0); assert(at > 0);
@@ -129,18 +129,18 @@ class Column {
return initial == std::string::npos ? m_column.m_indent : initial; return initial == std::string::npos ? m_column.m_indent : initial;
} }
auto addIndentAndSuffix(std::string const &plain) const -> std::string { auto addIndentAndSuffix(std::string const& plain) const -> std::string {
return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain); return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain);
} }
public: public:
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = std::string; using value_type = std::string;
using pointer = value_type *; using pointer = value_type*;
using reference = value_type &; using reference = value_type&;
using iterator_category = std::forward_iterator_tag; using iterator_category = std::forward_iterator_tag;
explicit iterator(Column const &column) : m_column(column) { explicit iterator(Column const& column) : m_column(column) {
assert(m_column.m_width > m_column.m_indent); assert(m_column.m_width > m_column.m_indent);
assert(m_column.m_initialIndent == std::string::npos || assert(m_column.m_initialIndent == std::string::npos ||
m_column.m_width > m_column.m_initialIndent); m_column.m_width > m_column.m_initialIndent);
@@ -154,7 +154,7 @@ class Column {
return addIndentAndSuffix(line().substr(m_pos, m_len)); return addIndentAndSuffix(line().substr(m_pos, m_len));
} }
auto operator++() -> iterator & { auto operator++() -> iterator& {
m_pos += m_len; m_pos += m_len;
if (m_pos < line().size() && line()[m_pos] == '\n') if (m_pos < line().size() && line()[m_pos] == '\n')
m_pos += 1; m_pos += 1;
@@ -174,26 +174,26 @@ class Column {
return prev; return prev;
} }
auto operator==(iterator const &other) const -> bool { auto operator==(iterator const& other) const -> bool {
return m_pos == other.m_pos && m_stringIndex == other.m_stringIndex && return m_pos == other.m_pos && m_stringIndex == other.m_stringIndex &&
&m_column == &other.m_column; &m_column == &other.m_column;
} }
auto operator!=(iterator const &other) const -> bool { return !operator==(other); } auto operator!=(iterator const& other) const -> bool { return !operator==(other); }
}; };
using const_iterator = iterator; using const_iterator = iterator;
explicit Column(std::string const &text) { m_strings.push_back(text); } explicit Column(std::string const& text) { m_strings.push_back(text); }
auto width(size_t newWidth) -> Column & { auto width(size_t newWidth) -> Column& {
assert(newWidth > 0); assert(newWidth > 0);
m_width = newWidth; m_width = newWidth;
return *this; return *this;
} }
auto indent(size_t newIndent) -> Column & { auto indent(size_t newIndent) -> Column& {
m_indent = newIndent; m_indent = newIndent;
return *this; return *this;
} }
auto initialIndent(size_t newIndent) -> Column & { auto initialIndent(size_t newIndent) -> Column& {
m_initialIndent = newIndent; m_initialIndent = newIndent;
return *this; return *this;
} }
@@ -202,7 +202,7 @@ class Column {
auto begin() const -> iterator { return iterator(*this); } auto begin() const -> iterator { return iterator(*this); }
auto end() const -> iterator { return {*this, m_strings.size()}; } auto end() const -> iterator { return {*this, m_strings.size()}; }
inline friend std::ostream &operator<<(std::ostream &os, Column const &col) { inline friend std::ostream& operator<<(std::ostream& os, Column const& col) {
bool first = true; bool first = true;
for (auto line : col) { for (auto line : col) {
if (first) if (first)
@@ -214,7 +214,7 @@ class Column {
return os; return os;
} }
auto operator+(Column const &other) -> Columns; auto operator+(Column const& other) -> Columns;
auto toString() const -> std::string { auto toString() const -> std::string {
std::ostringstream oss; std::ostringstream oss;
@@ -236,34 +236,34 @@ class Columns {
friend Columns; friend Columns;
struct EndTag {}; struct EndTag {};
std::vector<Column> const &m_columns; std::vector<Column> const& m_columns;
std::vector<Column::iterator> m_iterators; std::vector<Column::iterator> m_iterators;
size_t m_activeIterators; size_t m_activeIterators;
iterator(Columns const &columns, EndTag) : m_columns(columns.m_columns), m_activeIterators(0) { iterator(Columns const& columns, EndTag) : m_columns(columns.m_columns), m_activeIterators(0) {
m_iterators.reserve(m_columns.size()); m_iterators.reserve(m_columns.size());
for (auto const &col : m_columns) m_iterators.push_back(col.end()); for (auto const& col : m_columns) m_iterators.push_back(col.end());
} }
public: public:
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = std::string; using value_type = std::string;
using pointer = value_type *; using pointer = value_type*;
using reference = value_type &; using reference = value_type&;
using iterator_category = std::forward_iterator_tag; using iterator_category = std::forward_iterator_tag;
explicit iterator(Columns const &columns) explicit iterator(Columns const& columns)
: m_columns(columns.m_columns), m_activeIterators(m_columns.size()) { : m_columns(columns.m_columns), m_activeIterators(m_columns.size()) {
m_iterators.reserve(m_columns.size()); m_iterators.reserve(m_columns.size());
for (auto const &col : m_columns) m_iterators.push_back(col.begin()); for (auto const& col : m_columns) m_iterators.push_back(col.begin());
} }
auto operator==(iterator const &other) const -> bool { auto operator==(iterator const& other) const -> bool {
return m_iterators == other.m_iterators; return m_iterators == other.m_iterators;
} }
auto operator!=(iterator const &other) const -> bool { auto operator!=(iterator const& other) const -> bool {
return m_iterators != other.m_iterators; return m_iterators != other.m_iterators;
} }
auto operator*() const -> std::string { auto operator*() const -> std::string {
@@ -284,7 +284,7 @@ class Columns {
} }
return row; return row;
} }
auto operator++() -> iterator & { auto operator++() -> iterator& {
for (size_t i = 0; i < m_columns.size(); ++i) { for (size_t i = 0; i < m_columns.size(); ++i) {
if (m_iterators[i] != m_columns[i].end()) ++m_iterators[i]; if (m_iterators[i] != m_columns[i].end()) ++m_iterators[i];
} }
@@ -301,17 +301,17 @@ class Columns {
auto begin() const -> iterator { return iterator(*this); } auto begin() const -> iterator { return iterator(*this); }
auto end() const -> iterator { return {*this, iterator::EndTag()}; } auto end() const -> iterator { return {*this, iterator::EndTag()}; }
auto operator+=(Column const &col) -> Columns & { auto operator+=(Column const& col) -> Columns& {
m_columns.push_back(col); m_columns.push_back(col);
return *this; return *this;
} }
auto operator+(Column const &col) -> Columns { auto operator+(Column const& col) -> Columns {
Columns combined = *this; Columns combined = *this;
combined += col; combined += col;
return combined; return combined;
} }
inline friend std::ostream &operator<<(std::ostream &os, Columns const &cols) { inline friend std::ostream& operator<<(std::ostream& os, Columns const& cols) {
bool first = true; bool first = true;
for (auto line : cols) { for (auto line : cols) {
if (first) if (first)
@@ -330,7 +330,7 @@ class Columns {
} }
}; };
inline auto Column::operator+(Column const &other) -> Columns { inline auto Column::operator+(Column const& other) -> Columns {
Columns cols; Columns cols;
cols += *this; cols += *this;
cols += other; cols += other;
@@ -381,7 +381,7 @@ class Args {
std::vector<std::string> m_args; std::vector<std::string> m_args;
public: public:
Args(int argc, char const *const *argv) : m_exeName(argv[0]), m_args(argv + 1, argv + argc) {} Args(int argc, char const* const* argv) : m_exeName(argv[0]), m_args(argv + 1, argv + argc) {}
Args(std::initializer_list<std::string> args) Args(std::initializer_list<std::string> args)
: m_exeName(*args.begin()), m_args(args.begin() + 1, args.end()) {} : m_exeName(*args.begin()), m_args(args.begin() + 1, args.end()) {}
@@ -419,7 +419,7 @@ class TokenStream {
while (it != itEnd && it->empty()) ++it; while (it != itEnd && it->empty()) ++it;
if (it != itEnd) { if (it != itEnd) {
auto const &next = *it; auto const& next = *it;
if (isOptPrefix(next[0])) { if (isOptPrefix(next[0])) {
auto delimiterPos = next.find_first_of(" :="); auto delimiterPos = next.find_first_of(" :=");
if (delimiterPos != std::string::npos) { if (delimiterPos != std::string::npos) {
@@ -443,7 +443,7 @@ class TokenStream {
} }
public: public:
explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {} explicit TokenStream(Args const& args) : TokenStream(args.m_args.begin(), args.m_args.end()) {}
TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { loadBuffer(); } TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { loadBuffer(); }
@@ -456,12 +456,12 @@ class TokenStream {
return m_tokenBuffer.front(); return m_tokenBuffer.front();
} }
auto operator->() const -> Token const * { auto operator->() const -> Token const* {
assert(!m_tokenBuffer.empty()); assert(!m_tokenBuffer.empty());
return &m_tokenBuffer.front(); return &m_tokenBuffer.front();
} }
auto operator++() -> TokenStream & { auto operator++() -> TokenStream& {
if (m_tokenBuffer.size() >= 2) { if (m_tokenBuffer.size() >= 2) {
m_tokenBuffer.erase(m_tokenBuffer.begin()); m_tokenBuffer.erase(m_tokenBuffer.begin());
} else { } else {
@@ -488,7 +488,7 @@ class ResultBase {
template <typename T> template <typename T>
class ResultValueBase : public ResultBase { class ResultValueBase : public ResultBase {
public: public:
auto value() const -> T const & { auto value() const -> T const& {
enforceOk(); enforceOk();
return m_value; return m_value;
} }
@@ -496,13 +496,13 @@ class ResultValueBase : public ResultBase {
protected: protected:
ResultValueBase(Type type) : ResultBase(type) {} ResultValueBase(Type type) : ResultBase(type) {}
ResultValueBase(ResultValueBase const &other) : ResultBase(other) { ResultValueBase(ResultValueBase const& other) : ResultBase(other) {
if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value); if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value);
} }
ResultValueBase(Type, T const &value) : ResultBase(Ok) { new (&m_value) T(value); } ResultValueBase(Type, T const& value) : ResultBase(Ok) { new (&m_value) T(value); }
auto operator=(ResultValueBase const &other) -> ResultValueBase & { auto operator=(ResultValueBase const& other) -> ResultValueBase& {
if (m_type == ResultBase::Ok) m_value.~T(); if (m_type == ResultBase::Ok) m_value.~T();
ResultBase::operator=(other); ResultBase::operator=(other);
if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value); if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value);
@@ -528,20 +528,20 @@ template <typename T = void>
class BasicResult : public ResultValueBase<T> { class BasicResult : public ResultValueBase<T> {
public: public:
template <typename U> template <typename U>
explicit BasicResult(BasicResult<U> const &other) explicit BasicResult(BasicResult<U> const& other)
: ResultValueBase<T>(other.type()), m_errorMessage(other.errorMessage()) { : ResultValueBase<T>(other.type()), m_errorMessage(other.errorMessage()) {
assert(type() != ResultBase::Ok); assert(type() != ResultBase::Ok);
} }
template <typename U> template <typename U>
static auto ok(U const &value) -> BasicResult { static auto ok(U const& value) -> BasicResult {
return {ResultBase::Ok, value}; return {ResultBase::Ok, value};
} }
static auto ok() -> BasicResult { return {ResultBase::Ok}; } static auto ok() -> BasicResult { return {ResultBase::Ok}; }
static auto logicError(std::string const &message) -> BasicResult { static auto logicError(std::string const& message) -> BasicResult {
return {ResultBase::LogicError, message}; return {ResultBase::LogicError, message};
} }
static auto runtimeError(std::string const &message) -> BasicResult { static auto runtimeError(std::string const& message) -> BasicResult {
return {ResultBase::RuntimeError, message}; return {ResultBase::RuntimeError, message};
} }
@@ -560,7 +560,7 @@ class BasicResult : public ResultValueBase<T> {
std::string m_errorMessage; // Only populated if resultType is an error std::string m_errorMessage; // Only populated if resultType is an error
BasicResult(ResultBase::Type type, std::string const &message) BasicResult(ResultBase::Type type, std::string const& message)
: ResultValueBase<T>(type), m_errorMessage(message) { : ResultValueBase<T>(type), m_errorMessage(message) {
assert(m_type != ResultBase::Ok); assert(m_type != ResultBase::Ok);
} }
@@ -573,7 +573,7 @@ enum class ParseResultType { Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
class ParseState { class ParseState {
public: public:
ParseState(ParseResultType type, TokenStream const &remainingTokens) ParseState(ParseResultType type, TokenStream const& remainingTokens)
: m_type(type), m_remainingTokens(remainingTokens) {} : m_type(type), m_remainingTokens(remainingTokens) {}
auto type() const -> ParseResultType { return m_type; } auto type() const -> ParseResultType { return m_type; }
@@ -594,7 +594,7 @@ struct HelpColumns {
}; };
template <typename T> template <typename T>
inline auto convertInto(std::string const &source, T &target) -> ParserResult { inline auto convertInto(std::string const& source, T& target) -> ParserResult {
std::stringstream ss; std::stringstream ss;
ss << source; ss << source;
ss >> target; ss >> target;
@@ -603,11 +603,11 @@ inline auto convertInto(std::string const &source, T &target) -> ParserResult {
else else
return ParserResult::ok(ParseResultType::Matched); return ParserResult::ok(ParseResultType::Matched);
} }
inline auto convertInto(std::string const &source, std::string &target) -> ParserResult { inline auto convertInto(std::string const& source, std::string& target) -> ParserResult {
target = source; target = source;
return ParserResult::ok(ParseResultType::Matched); return ParserResult::ok(ParseResultType::Matched);
} }
inline auto convertInto(std::string const &source, bool &target) -> ParserResult { inline auto convertInto(std::string const& source, bool& target) -> ParserResult {
std::string srcLC = source; std::string srcLC = source;
std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(),
[](char c) { return static_cast<char>(::tolower(c)); }); [](char c) { return static_cast<char>(::tolower(c)); });
@@ -622,7 +622,7 @@ inline auto convertInto(std::string const &source, bool &target) -> ParserResult
} }
#ifdef CLARA_CONFIG_OPTIONAL_TYPE #ifdef CLARA_CONFIG_OPTIONAL_TYPE
template <typename T> template <typename T>
inline auto convertInto(std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T> &target) inline auto convertInto(std::string const& source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target)
-> ParserResult { -> ParserResult {
T temp; T temp;
auto result = convertInto(source, temp); auto result = convertInto(source, temp);
@@ -633,10 +633,10 @@ inline auto convertInto(std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>
struct NonCopyable { struct NonCopyable {
NonCopyable() = default; NonCopyable() = default;
NonCopyable(NonCopyable const &) = delete; NonCopyable(NonCopyable const&) = delete;
NonCopyable(NonCopyable &&) = delete; NonCopyable(NonCopyable&&) = delete;
NonCopyable &operator=(NonCopyable const &) = delete; NonCopyable& operator=(NonCopyable const&) = delete;
NonCopyable &operator=(NonCopyable &&) = delete; NonCopyable& operator=(NonCopyable&&) = delete;
}; };
struct BoundRef : NonCopyable { struct BoundRef : NonCopyable {
@@ -645,7 +645,7 @@ struct BoundRef : NonCopyable {
virtual auto isFlag() const -> bool { return false; } virtual auto isFlag() const -> bool { return false; }
}; };
struct BoundValueRefBase : BoundRef { struct BoundValueRefBase : BoundRef {
virtual auto setValue(std::string const &arg) -> ParserResult = 0; virtual auto setValue(std::string const& arg) -> ParserResult = 0;
}; };
struct BoundFlagRefBase : BoundRef { struct BoundFlagRefBase : BoundRef {
virtual auto setFlag(bool flag) -> ParserResult = 0; virtual auto setFlag(bool flag) -> ParserResult = 0;
@@ -654,22 +654,22 @@ struct BoundFlagRefBase : BoundRef {
template <typename T> template <typename T>
struct BoundValueRef : BoundValueRefBase { struct BoundValueRef : BoundValueRefBase {
T &m_ref; T& m_ref;
explicit BoundValueRef(T &ref) : m_ref(ref) {} explicit BoundValueRef(T& ref) : m_ref(ref) {}
auto setValue(std::string const &arg) -> ParserResult override { return convertInto(arg, m_ref); } auto setValue(std::string const& arg) -> ParserResult override { return convertInto(arg, m_ref); }
}; };
template <typename T> template <typename T>
struct BoundValueRef<std::vector<T>> : BoundValueRefBase { struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
std::vector<T> &m_ref; std::vector<T>& m_ref;
explicit BoundValueRef(std::vector<T> &ref) : m_ref(ref) {} explicit BoundValueRef(std::vector<T>& ref) : m_ref(ref) {}
auto isContainer() const -> bool override { return true; } auto isContainer() const -> bool override { return true; }
auto setValue(std::string const &arg) -> ParserResult override { auto setValue(std::string const& arg) -> ParserResult override {
T temp; T temp;
auto result = convertInto(arg, temp); auto result = convertInto(arg, temp);
if (result) m_ref.push_back(temp); if (result) m_ref.push_back(temp);
@@ -678,9 +678,9 @@ struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
}; };
struct BoundFlagRef : BoundFlagRefBase { struct BoundFlagRef : BoundFlagRefBase {
bool &m_ref; bool& m_ref;
explicit BoundFlagRef(bool &ref) : m_ref(ref) {} explicit BoundFlagRef(bool& ref) : m_ref(ref) {}
auto setFlag(bool flag) -> ParserResult override { auto setFlag(bool flag) -> ParserResult override {
m_ref = flag; m_ref = flag;
@@ -694,7 +694,7 @@ struct LambdaInvoker {
"Lambda must return void or clara::ParserResult"); "Lambda must return void or clara::ParserResult");
template <typename L, typename ArgType> template <typename L, typename ArgType>
static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { static auto invoke(L const& lambda, ArgType const& arg) -> ParserResult {
return lambda(arg); return lambda(arg);
} }
}; };
@@ -702,14 +702,14 @@ struct LambdaInvoker {
template <> template <>
struct LambdaInvoker<void> { struct LambdaInvoker<void> {
template <typename L, typename ArgType> template <typename L, typename ArgType>
static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { static auto invoke(L const& lambda, ArgType const& arg) -> ParserResult {
lambda(arg); lambda(arg);
return ParserResult::ok(ParseResultType::Matched); return ParserResult::ok(ParseResultType::Matched);
} }
}; };
template <typename ArgType, typename L> template <typename ArgType, typename L>
inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult { inline auto invokeLambda(L const& lambda, std::string const& arg) -> ParserResult {
ArgType temp{}; ArgType temp{};
auto result = convertInto(arg, temp); auto result = convertInto(arg, temp);
return !result ? result return !result ? result
@@ -721,9 +721,9 @@ struct BoundLambda : BoundValueRefBase {
L m_lambda; L m_lambda;
static_assert(UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument"); static_assert(UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument");
explicit BoundLambda(L const &lambda) : m_lambda(lambda) {} explicit BoundLambda(L const& lambda) : m_lambda(lambda) {}
auto setValue(std::string const &arg) -> ParserResult override { auto setValue(std::string const& arg) -> ParserResult override {
return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(m_lambda, arg); return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(m_lambda, arg);
} }
}; };
@@ -736,7 +736,7 @@ struct BoundFlagLambda : BoundFlagRefBase {
static_assert(std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, static_assert(std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value,
"flags must be boolean"); "flags must be boolean");
explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {} explicit BoundFlagLambda(L const& lambda) : m_lambda(lambda) {}
auto setFlag(bool flag) -> ParserResult override { auto setFlag(bool flag) -> ParserResult override {
return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(m_lambda, flag); return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(m_lambda, flag);
@@ -751,11 +751,11 @@ class ParserBase {
public: public:
virtual ~ParserBase() = default; virtual ~ParserBase() = default;
virtual auto validate() const -> Result { return Result::ok(); } virtual auto validate() const -> Result { return Result::ok(); }
virtual auto parse(std::string const &exeName, TokenStream const &tokens) const virtual auto parse(std::string const& exeName, TokenStream const& tokens) const
-> InternalParseResult = 0; -> InternalParseResult = 0;
virtual auto cardinality() const -> size_t { return 1; } virtual auto cardinality() const -> size_t { return 1; }
auto parse(Args const &args) const -> InternalParseResult { auto parse(Args const& args) const -> InternalParseResult {
return parse(args.exeName(), TokenStream(args)); return parse(args.exeName(), TokenStream(args));
} }
}; };
@@ -764,10 +764,10 @@ template <typename DerivedT>
class ComposableParserImpl : public ParserBase { class ComposableParserImpl : public ParserBase {
public: public:
template <typename T> template <typename T>
auto operator|(T const &other) const -> Parser; auto operator|(T const& other) const -> Parser;
template <typename T> template <typename T>
auto operator+(T const &other) const -> Parser; auto operator+(T const& other) const -> Parser;
}; };
// Common code and state for Args and Opts // Common code and state for Args and Opts
@@ -779,30 +779,30 @@ class ParserRefImpl : public ComposableParserImpl<DerivedT> {
std::string m_hint; std::string m_hint;
std::string m_description; std::string m_description;
explicit ParserRefImpl(std::shared_ptr<BoundRef> const &ref) : m_ref(ref) {} explicit ParserRefImpl(std::shared_ptr<BoundRef> const& ref) : m_ref(ref) {}
public: public:
template <typename T> template <typename T>
ParserRefImpl(T &ref, std::string const &hint) ParserRefImpl(T& ref, std::string const& hint)
: m_ref(std::make_shared<BoundValueRef<T>>(ref)), m_hint(hint) {} : m_ref(std::make_shared<BoundValueRef<T>>(ref)), m_hint(hint) {}
template <typename LambdaT> template <typename LambdaT>
ParserRefImpl(LambdaT const &ref, std::string const &hint) ParserRefImpl(LambdaT const& ref, std::string const& hint)
: m_ref(std::make_shared<BoundLambda<LambdaT>>(ref)), m_hint(hint) {} : m_ref(std::make_shared<BoundLambda<LambdaT>>(ref)), m_hint(hint) {}
auto operator()(std::string const &description) -> DerivedT & { auto operator()(std::string const& description) -> DerivedT& {
m_description = description; m_description = description;
return static_cast<DerivedT &>(*this); return static_cast<DerivedT&>(*this);
} }
auto optional() -> DerivedT & { auto optional() -> DerivedT& {
m_optionality = Optionality::Optional; m_optionality = Optionality::Optional;
return static_cast<DerivedT &>(*this); return static_cast<DerivedT&>(*this);
}; };
auto required() -> DerivedT & { auto required() -> DerivedT& {
m_optionality = Optionality::Required; m_optionality = Optionality::Required;
return static_cast<DerivedT &>(*this); return static_cast<DerivedT&>(*this);
}; };
auto isOptional() const -> bool { return m_optionality == Optionality::Optional; } auto isOptional() const -> bool { return m_optionality == Optionality::Optional; }
@@ -822,29 +822,29 @@ class ExeName : public ComposableParserImpl<ExeName> {
std::shared_ptr<BoundValueRefBase> m_ref; std::shared_ptr<BoundValueRefBase> m_ref;
template <typename LambdaT> template <typename LambdaT>
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> { static auto makeRef(LambdaT const& lambda) -> std::shared_ptr<BoundValueRefBase> {
return std::make_shared<BoundLambda<LambdaT>>(lambda); return std::make_shared<BoundLambda<LambdaT>>(lambda);
} }
public: public:
ExeName() : m_name(std::make_shared<std::string>("<executable>")) {} ExeName() : m_name(std::make_shared<std::string>("<executable>")) {}
explicit ExeName(std::string &ref) : ExeName() { explicit ExeName(std::string& ref) : ExeName() {
m_ref = std::make_shared<BoundValueRef<std::string>>(ref); m_ref = std::make_shared<BoundValueRef<std::string>>(ref);
} }
template <typename LambdaT> template <typename LambdaT>
explicit ExeName(LambdaT const &lambda) : ExeName() { explicit ExeName(LambdaT const& lambda) : ExeName() {
m_ref = std::make_shared<BoundLambda<LambdaT>>(lambda); m_ref = std::make_shared<BoundLambda<LambdaT>>(lambda);
} }
// The exe name is not parsed out of the normal tokens, but is handled specially // The exe name is not parsed out of the normal tokens, but is handled specially
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { auto parse(std::string const&, TokenStream const& tokens) const -> InternalParseResult override {
return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens));
} }
auto name() const -> std::string { return *m_name; } auto name() const -> std::string { return *m_name; }
auto set(std::string const &newName) -> ParserResult { auto set(std::string const& newName) -> ParserResult {
auto lastSlash = newName.find_last_of("\\/"); auto lastSlash = newName.find_last_of("\\/");
auto filename = (lastSlash == std::string::npos) ? newName : newName.substr(lastSlash + 1); auto filename = (lastSlash == std::string::npos) ? newName : newName.substr(lastSlash + 1);
@@ -860,17 +860,17 @@ class Arg : public ParserRefImpl<Arg> {
public: public:
using ParserRefImpl::ParserRefImpl; using ParserRefImpl::ParserRefImpl;
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { auto parse(std::string const&, TokenStream const& tokens) const -> InternalParseResult override {
auto validationResult = validate(); auto validationResult = validate();
if (!validationResult) return InternalParseResult(validationResult); if (!validationResult) return InternalParseResult(validationResult);
auto remainingTokens = tokens; auto remainingTokens = tokens;
auto const &token = *remainingTokens; auto const& token = *remainingTokens;
if (token.type != TokenType::Argument) if (token.type != TokenType::Argument)
return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens));
assert(!m_ref->isFlag()); assert(!m_ref->isFlag());
auto valueRef = static_cast<detail::BoundValueRefBase *>(m_ref.get()); auto valueRef = static_cast<detail::BoundValueRefBase*>(m_ref.get());
auto result = valueRef->setValue(remainingTokens->token); auto result = valueRef->setValue(remainingTokens->token);
if (!result) if (!result)
@@ -880,7 +880,7 @@ class Arg : public ParserRefImpl<Arg> {
} }
}; };
inline auto normaliseOpt(std::string const &optName) -> std::string { inline auto normaliseOpt(std::string const& optName) -> std::string {
#ifdef CLARA_PLATFORM_WINDOWS #ifdef CLARA_PLATFORM_WINDOWS
if (optName[0] == '/') if (optName[0] == '/')
return "-" + optName.substr(1); return "-" + optName.substr(1);
@@ -895,18 +895,18 @@ class Opt : public ParserRefImpl<Opt> {
public: public:
template <typename LambdaT> template <typename LambdaT>
explicit Opt(LambdaT const &ref) explicit Opt(LambdaT const& ref)
: ParserRefImpl(std::make_shared<BoundFlagLambda<LambdaT>>(ref)) {} : ParserRefImpl(std::make_shared<BoundFlagLambda<LambdaT>>(ref)) {}
explicit Opt(bool &ref) : ParserRefImpl(std::make_shared<BoundFlagRef>(ref)) {} explicit Opt(bool& ref) : ParserRefImpl(std::make_shared<BoundFlagRef>(ref)) {}
template <typename LambdaT> template <typename LambdaT>
Opt(LambdaT const &ref, std::string const &hint) : ParserRefImpl(ref, hint) {} Opt(LambdaT const& ref, std::string const& hint) : ParserRefImpl(ref, hint) {}
template <typename T> template <typename T>
Opt(T &ref, std::string const &hint) : ParserRefImpl(ref, hint) {} Opt(T& ref, std::string const& hint) : ParserRefImpl(ref, hint) {}
auto operator[](std::string const &optName) -> Opt & { auto operator[](std::string const& optName) -> Opt& {
m_optNames.push_back(optName); m_optNames.push_back(optName);
return *this; return *this;
} }
@@ -914,7 +914,7 @@ class Opt : public ParserRefImpl<Opt> {
auto getHelpColumns() const -> std::vector<HelpColumns> { auto getHelpColumns() const -> std::vector<HelpColumns> {
std::ostringstream oss; std::ostringstream oss;
bool first = true; bool first = true;
for (auto const &opt : m_optNames) { for (auto const& opt : m_optNames) {
if (first) if (first)
first = false; first = false;
else else
@@ -925,9 +925,9 @@ class Opt : public ParserRefImpl<Opt> {
return {{oss.str(), m_description}}; return {{oss.str(), m_description}};
} }
auto isMatch(std::string const &optToken) const -> bool { auto isMatch(std::string const& optToken) const -> bool {
auto normalisedToken = normaliseOpt(optToken); auto normalisedToken = normaliseOpt(optToken);
for (auto const &name : m_optNames) { for (auto const& name : m_optNames) {
if (normaliseOpt(name) == normalisedToken) return true; if (normaliseOpt(name) == normalisedToken) return true;
} }
return false; return false;
@@ -935,26 +935,26 @@ class Opt : public ParserRefImpl<Opt> {
using ParserBase::parse; using ParserBase::parse;
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { auto parse(std::string const&, TokenStream const& tokens) const -> InternalParseResult override {
auto validationResult = validate(); auto validationResult = validate();
if (!validationResult) return InternalParseResult(validationResult); if (!validationResult) return InternalParseResult(validationResult);
auto remainingTokens = tokens; auto remainingTokens = tokens;
if (remainingTokens && remainingTokens->type == TokenType::Option) { if (remainingTokens && remainingTokens->type == TokenType::Option) {
auto const &token = *remainingTokens; auto const& token = *remainingTokens;
if (isMatch(token.token)) { if (isMatch(token.token)) {
if (m_ref->isFlag()) { if (m_ref->isFlag()) {
auto flagRef = static_cast<detail::BoundFlagRefBase *>(m_ref.get()); auto flagRef = static_cast<detail::BoundFlagRefBase*>(m_ref.get());
auto result = flagRef->setFlag(true); auto result = flagRef->setFlag(true);
if (!result) return InternalParseResult(result); if (!result) return InternalParseResult(result);
if (result.value() == ParseResultType::ShortCircuitAll) if (result.value() == ParseResultType::ShortCircuitAll)
return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
} else { } else {
auto valueRef = static_cast<detail::BoundValueRefBase *>(m_ref.get()); auto valueRef = static_cast<detail::BoundValueRefBase*>(m_ref.get());
++remainingTokens; ++remainingTokens;
if (!remainingTokens) if (!remainingTokens)
return InternalParseResult::runtimeError("Expected argument following " + token.token); return InternalParseResult::runtimeError("Expected argument following " + token.token);
auto const &argToken = *remainingTokens; auto const& argToken = *remainingTokens;
if (argToken.type != TokenType::Argument) if (argToken.type != TokenType::Argument)
return InternalParseResult::runtimeError("Expected argument following " + token.token); return InternalParseResult::runtimeError("Expected argument following " + token.token);
auto result = valueRef->setValue(argToken.token); auto result = valueRef->setValue(argToken.token);
@@ -970,7 +970,7 @@ class Opt : public ParserRefImpl<Opt> {
auto validate() const -> Result override { auto validate() const -> Result override {
if (m_optNames.empty()) return Result::logicError("No options supplied to Opt"); if (m_optNames.empty()) return Result::logicError("No options supplied to Opt");
for (auto const &name : m_optNames) { for (auto const& name : m_optNames) {
if (name.empty()) return Result::logicError("Option name cannot be empty"); if (name.empty()) return Result::logicError("Option name cannot be empty");
#ifdef CLARA_PLATFORM_WINDOWS #ifdef CLARA_PLATFORM_WINDOWS
if (name[0] != '-' && name[0] != '/') if (name[0] != '-' && name[0] != '/')
@@ -984,12 +984,12 @@ class Opt : public ParserRefImpl<Opt> {
}; };
struct Help : Opt { struct Help : Opt {
Help(bool &showHelpFlag) Help(bool& showHelpFlag)
: Opt([&](bool flag) { : Opt([&](bool flag) {
showHelpFlag = flag; showHelpFlag = flag;
return ParserResult::ok(ParseResultType::ShortCircuitAll); return ParserResult::ok(ParseResultType::ShortCircuitAll);
}) { }) {
static_cast<Opt &>(*this)("display usage information")["-?"]["-h"]["--help"].optional(); static_cast<Opt&>(*this)("display usage information")["-?"]["-h"]["--help"].optional();
} }
}; };
@@ -998,57 +998,57 @@ struct Parser : ParserBase {
std::vector<Opt> m_options; std::vector<Opt> m_options;
std::vector<Arg> m_args; std::vector<Arg> m_args;
auto operator|=(ExeName const &exeName) -> Parser & { auto operator|=(ExeName const& exeName) -> Parser& {
m_exeName = exeName; m_exeName = exeName;
return *this; return *this;
} }
auto operator|=(Arg const &arg) -> Parser & { auto operator|=(Arg const& arg) -> Parser& {
m_args.push_back(arg); m_args.push_back(arg);
return *this; return *this;
} }
auto operator|=(Opt const &opt) -> Parser & { auto operator|=(Opt const& opt) -> Parser& {
m_options.push_back(opt); m_options.push_back(opt);
return *this; return *this;
} }
auto operator|=(Parser const &other) -> Parser & { auto operator|=(Parser const& other) -> Parser& {
m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
return *this; return *this;
} }
template <typename T> template <typename T>
auto operator|(T const &other) const -> Parser { auto operator|(T const& other) const -> Parser {
return Parser(*this) |= other; return Parser(*this) |= other;
} }
// Forward deprecated interface with '+' instead of '|' // Forward deprecated interface with '+' instead of '|'
template <typename T> template <typename T>
auto operator+=(T const &other) -> Parser & { auto operator+=(T const& other) -> Parser& {
return operator|=(other); return operator|=(other);
} }
template <typename T> template <typename T>
auto operator+(T const &other) const -> Parser { auto operator+(T const& other) const -> Parser {
return operator|(other); return operator|(other);
} }
auto getHelpColumns() const -> std::vector<HelpColumns> { auto getHelpColumns() const -> std::vector<HelpColumns> {
std::vector<HelpColumns> cols; std::vector<HelpColumns> cols;
for (auto const &o : m_options) { for (auto const& o : m_options) {
auto childCols = o.getHelpColumns(); auto childCols = o.getHelpColumns();
cols.insert(cols.end(), childCols.begin(), childCols.end()); cols.insert(cols.end(), childCols.begin(), childCols.end());
} }
return cols; return cols;
} }
void writeToStream(std::ostream &os) const { void writeToStream(std::ostream& os) const {
if (!m_exeName.name().empty()) { if (!m_exeName.name().empty()) {
os << "usage:\n" os << "usage:\n"
<< " " << m_exeName.name() << " "; << " " << m_exeName.name() << " ";
bool required = true, first = true; bool required = true, first = true;
for (auto const &arg : m_args) { for (auto const& arg : m_args) {
if (first) if (first)
first = false; first = false;
else else
@@ -1068,28 +1068,28 @@ struct Parser : ParserBase {
auto rows = getHelpColumns(); auto rows = getHelpColumns();
size_t consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; size_t consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
size_t optWidth = 0; size_t optWidth = 0;
for (auto const &cols : rows) optWidth = (std::max)(optWidth, cols.left.size() + 2); for (auto const& cols : rows) optWidth = (std::max)(optWidth, cols.left.size() + 2);
optWidth = (std::min)(optWidth, consoleWidth / 2); optWidth = (std::min)(optWidth, consoleWidth / 2);
for (auto const &cols : rows) { for (auto const& cols : rows) {
auto row = TextFlow::Column(cols.left).width(optWidth).indent(2) + TextFlow::Spacer(4) + auto row = TextFlow::Column(cols.left).width(optWidth).indent(2) + TextFlow::Spacer(4) +
TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth); TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth);
os << row << std::endl; os << row << std::endl;
} }
} }
friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream & { friend auto operator<<(std::ostream& os, Parser const& parser) -> std::ostream& {
parser.writeToStream(os); parser.writeToStream(os);
return os; return os;
} }
auto validate() const -> Result override { auto validate() const -> Result override {
for (auto const &opt : m_options) { for (auto const& opt : m_options) {
auto result = opt.validate(); auto result = opt.validate();
if (!result) return result; if (!result) return result;
} }
for (auto const &arg : m_args) { for (auto const& arg : m_args) {
auto result = arg.validate(); auto result = arg.validate();
if (!result) return result; if (!result) return result;
} }
@@ -1098,10 +1098,10 @@ struct Parser : ParserBase {
using ParserBase::parse; using ParserBase::parse;
auto parse(std::string const &exeName, TokenStream const &tokens) const auto parse(std::string const& exeName, TokenStream const& tokens) const
-> InternalParseResult override { -> InternalParseResult override {
struct ParserInfo { struct ParserInfo {
ParserBase const *parser = nullptr; ParserBase const* parser = nullptr;
size_t count = 0; size_t count = 0;
}; };
const size_t totalParsers = m_options.size() + m_args.size(); const size_t totalParsers = m_options.size() + m_args.size();
@@ -1111,8 +1111,8 @@ struct Parser : ParserBase {
{ {
size_t i = 0; size_t i = 0;
for (auto const &opt : m_options) parseInfos[i++].parser = &opt; for (auto const& opt : m_options) parseInfos[i++].parser = &opt;
for (auto const &arg : m_args) parseInfos[i++].parser = &arg; for (auto const& arg : m_args) parseInfos[i++].parser = &arg;
} }
m_exeName.set(exeName); m_exeName.set(exeName);
@@ -1122,7 +1122,7 @@ struct Parser : ParserBase {
bool tokenParsed = false; bool tokenParsed = false;
for (size_t i = 0; i < totalParsers; ++i) { for (size_t i = 0; i < totalParsers; ++i) {
auto &parseInfo = parseInfos[i]; auto& parseInfo = parseInfos[i];
if (parseInfo.parser->cardinality() == 0 || if (parseInfo.parser->cardinality() == 0 ||
parseInfo.count < parseInfo.parser->cardinality()) { parseInfo.count < parseInfo.parser->cardinality()) {
result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
@@ -1147,8 +1147,8 @@ struct Parser : ParserBase {
template <typename DerivedT> template <typename DerivedT>
template <typename T> template <typename T>
auto ComposableParserImpl<DerivedT>::operator|(T const &other) const -> Parser { auto ComposableParserImpl<DerivedT>::operator|(T const& other) const -> Parser {
return Parser() | static_cast<DerivedT const &>(*this) | other; return Parser() | static_cast<DerivedT const&>(*this) | other;
} }
} // namespace detail } // namespace detail
+16 -4
View File
@@ -20,6 +20,8 @@ extern std::list<pid_t> reap;
namespace waybar::util::command { namespace waybar::util::command {
constexpr int kExecFailureExitCode = 127;
struct res { struct res {
int exit_code; int exit_code;
std::string out; std::string out;
@@ -59,6 +61,7 @@ inline int close(FILE* fp, pid_t pid) {
spdlog::debug("Cmd continued"); spdlog::debug("Cmd continued");
} else if (ret == -1) { } else if (ret == -1) {
spdlog::debug("waitpid failed: {}", strerror(errno)); spdlog::debug("waitpid failed: {}", strerror(errno));
break;
} else { } else {
break; break;
} }
@@ -109,11 +112,13 @@ inline FILE* open(const std::string& cmd, int& pid, const std::string& output_na
::close(fd[0]); ::close(fd[0]);
dup2(fd[1], 1); dup2(fd[1], 1);
setpgid(child_pid, child_pid); setpgid(child_pid, child_pid);
if (output_name != "") { if (!output_name.empty()) {
setenv("WAYBAR_OUTPUT_NAME", output_name.c_str(), 1); setenv("WAYBAR_OUTPUT_NAME", output_name.c_str(), 1);
} }
execlp("/bin/sh", "sh", "-c", cmd.c_str(), (char*)0); execlp("/bin/sh", "sh", "-c", cmd.c_str(), (char*)0);
exit(0); const int saved_errno = errno;
spdlog::error("execlp(/bin/sh) failed in open: {}", strerror(saved_errno));
_exit(kExecFailureExitCode);
} else { } else {
::close(fd[1]); ::close(fd[1]);
} }
@@ -138,7 +143,7 @@ inline struct res execNoRead(const std::string& cmd) {
return {WEXITSTATUS(stat), ""}; return {WEXITSTATUS(stat), ""};
} }
inline int32_t forkExec(const std::string& cmd) { inline int32_t forkExec(const std::string& cmd, const std::string& output_name) {
if (cmd == "") return -1; if (cmd == "") return -1;
pid_t pid = fork(); pid_t pid = fork();
@@ -157,8 +162,13 @@ inline int32_t forkExec(const std::string& cmd) {
err = pthread_sigmask(SIG_UNBLOCK, &mask, nullptr); err = pthread_sigmask(SIG_UNBLOCK, &mask, nullptr);
if (err != 0) spdlog::error("pthread_sigmask in forkExec failed: {}", strerror(err)); if (err != 0) spdlog::error("pthread_sigmask in forkExec failed: {}", strerror(err));
setpgid(pid, pid); setpgid(pid, pid);
if (!output_name.empty()) {
setenv("WAYBAR_OUTPUT_NAME", output_name.c_str(), 1);
}
execl("/bin/sh", "sh", "-c", cmd.c_str(), (char*)0); execl("/bin/sh", "sh", "-c", cmd.c_str(), (char*)0);
exit(0); const int saved_errno = errno;
spdlog::error("execl(/bin/sh) failed in forkExec: {}", strerror(saved_errno));
_exit(kExecFailureExitCode);
} else { } else {
reap_mtx.lock(); reap_mtx.lock();
reap.push_back(pid); reap.push_back(pid);
@@ -169,4 +179,6 @@ inline int32_t forkExec(const std::string& cmd) {
return pid; return pid;
} }
inline int32_t forkExec(const std::string& cmd) { return forkExec(cmd, ""); }
} // namespace waybar::util::command } // namespace waybar::util::command
+4 -2
View File
@@ -14,12 +14,14 @@ struct pollfd;
namespace waybar { namespace waybar {
class CssReloadHelper { class CssReloadHelper {
public: public:
CssReloadHelper(std::string cssFile, std::function<void()> callback); CssReloadHelper(std::string cssFile, std::function<void(const std::string&)> callback);
virtual ~CssReloadHelper() = default; virtual ~CssReloadHelper() = default;
virtual void monitorChanges(); virtual void monitorChanges();
virtual void changeCssFile(const std::string& newCssFile);
protected: protected:
std::vector<std::string> parseImports(const std::string& cssFile); std::vector<std::string> parseImports(const std::string& cssFile);
@@ -42,7 +44,7 @@ class CssReloadHelper {
private: private:
std::string m_cssFile; std::string m_cssFile;
std::function<void()> m_callback; std::function<void(const std::string&)> m_callback;
std::vector<std::tuple<Glib::RefPtr<Gio::FileMonitor>>> m_fileMonitors; std::vector<std::tuple<Glib::RefPtr<Gio::FileMonitor>>> m_fileMonitors;
}; };
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <string>
/**
* Result of transforming 8-bit hex codes to rgba().
*/
struct TransformResult {
std::string css;
bool was_transformed;
};
/**
* Reads a CSS file, searches for 8-bit hex codes (#RRGGBBAA),
* and transforms them into GTK-compatible rgba() syntax.
*/
TransformResult transform_8bit_to_hex(const std::string& file_path);
+9 -9
View File
@@ -17,18 +17,18 @@ class IconLoader {
std::vector<Glib::RefPtr<Gtk::IconTheme>> custom_icon_themes_; std::vector<Glib::RefPtr<Gtk::IconTheme>> custom_icon_themes_;
Glib::RefPtr<Gtk::IconTheme> default_icon_theme_ = Gtk::IconTheme::get_default(); Glib::RefPtr<Gtk::IconTheme> default_icon_theme_ = Gtk::IconTheme::get_default();
static std::vector<std::string> search_prefix(); static std::vector<std::string> search_prefix();
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string &app_id); static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string& app_id);
static Glib::RefPtr<Gio::DesktopAppInfo> get_desktop_app_info(const std::string &app_id); static Glib::RefPtr<Gio::DesktopAppInfo> get_desktop_app_info(const std::string& app_id);
static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string const &icon_path, int size); static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string const& icon_path, int size);
static std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme> &icon_theme, static std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
const std::string &app_id); const std::string& app_id);
static bool image_load_icon(Gtk::Image &image, const Glib::RefPtr<Gtk::IconTheme> &icon_theme, static bool image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size); Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
public: public:
void add_custom_icon_theme(const std::string &theme_name); void add_custom_icon_theme(const std::string& theme_name);
bool image_load_icon(Gtk::Image &image, Glib::RefPtr<Gio::DesktopAppInfo> app_info, bool image_load_icon(Gtk::Image& image, Glib::RefPtr<Gio::DesktopAppInfo> app_info,
int size) const; int size) const;
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_from_app_id_list( static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_from_app_id_list(
const std::string &app_id_list); const std::string& app_id_list);
}; };
+12 -5
View File
@@ -7,6 +7,7 @@
#include <codecvt> #include <codecvt>
#include <iostream> #include <iostream>
#include <locale> #include <locale>
#include <memory>
#include <regex> #include <regex>
#if (FMT_VERSION >= 90000) #if (FMT_VERSION >= 90000)
@@ -26,19 +27,25 @@ class JsonParser {
Json::Value root; Json::Value root;
// replace all occurrences of "\x" with "\u00", because JSON doesn't allow "\x" escape sequences // replace all occurrences of "\x" with "\u00", because JSON doesn't allow "\x" escape sequences
std::string modifiedJsonStr = replaceHexadecimalEscape(jsonStr); std::string modifiedJsonStr;
const std::string* json = &jsonStr;
if (jsonStr.find("\\x") != std::string::npos) {
modifiedJsonStr = replaceHexadecimalEscape(jsonStr);
json = &modifiedJsonStr;
}
std::istringstream jsonStream(modifiedJsonStr);
std::string errs; std::string errs;
if (!Json::parseFromStream(m_readerBuilder, jsonStream, &root, &errs)) { // Use local CharReaderBuilder for thread safety - the IPC singleton's
// parser can be called concurrently from multiple module threads
Json::CharReaderBuilder readerBuilder;
auto reader = std::unique_ptr<Json::CharReader>(readerBuilder.newCharReader());
if (!reader->parse(json->data(), json->data() + json->size(), &root, &errs)) {
throw std::runtime_error("Error parsing JSON: " + errs); throw std::runtime_error("Error parsing JSON: " + errs);
} }
return root; return root;
} }
private: private:
Json::CharReaderBuilder m_readerBuilder;
static std::string replaceHexadecimalEscape(const std::string& str) { static std::string replaceHexadecimalEscape(const std::string& str) {
static std::regex re("\\\\x"); static std::regex re("\\\\x");
return std::regex_replace(str, re, "\\u00"); return std::regex_replace(str, re, "\\u00");
+2 -2
View File
@@ -33,14 +33,14 @@ class PrivacyNodeInfo {
struct spa_hook object_listener; struct spa_hook object_listener;
struct spa_hook proxy_listener; struct spa_hook proxy_listener;
void *data; void* data;
std::string getName(); std::string getName();
std::string getIconName(); std::string getIconName();
// Handlers for PipeWire events // Handlers for PipeWire events
void handleProxyEventDestroy(); void handleProxyEventDestroy();
void handleNodeEventInfo(const struct pw_node_info *info); void handleNodeEventInfo(const struct pw_node_info* info);
}; };
} // namespace waybar::util::PipewireBackend } // namespace waybar::util::PipewireBackend
+54
View File
@@ -0,0 +1,54 @@
#pragma once
#include <unistd.h>
namespace waybar::util {
class ScopedFd {
public:
explicit ScopedFd(int fd = -1) : fd_(fd) {}
~ScopedFd() {
if (fd_ != -1) {
close(fd_);
}
}
// ScopedFd is non-copyable
ScopedFd(const ScopedFd&) = delete;
ScopedFd& operator=(const ScopedFd&) = delete;
// ScopedFd is moveable
ScopedFd(ScopedFd&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
ScopedFd& operator=(ScopedFd&& other) noexcept {
if (this != &other) {
if (fd_ != -1) {
close(fd_);
}
fd_ = other.fd_;
other.fd_ = -1;
}
return *this;
}
int get() const { return fd_; }
operator int() const { return fd_; }
void reset(int fd = -1) {
if (fd_ != -1) {
close(fd_);
}
fd_ = fd;
}
int release() {
int fd = fd_;
fd_ = -1;
return fd;
}
private:
int fd_;
};
} // namespace waybar::util
+54 -14
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <atomic>
#include <chrono> #include <chrono>
#include <condition_variable> #include <condition_variable>
#include <ctime> #include <ctime>
@@ -31,8 +32,8 @@ class SleeperThread {
SleeperThread(std::function<void()> func) SleeperThread(std::function<void()> func)
: thread_{[this, func] { : thread_{[this, func] {
while (do_run_) { while (do_run_.load(std::memory_order_relaxed)) {
signal_ = false; signal_.store(false, std::memory_order_relaxed);
func(); func();
} }
}} { }} {
@@ -42,9 +43,18 @@ class SleeperThread {
} }
SleeperThread& operator=(std::function<void()> func) { SleeperThread& operator=(std::function<void()> func) {
if (thread_.joinable()) {
stop();
thread_.join();
}
{
std::lock_guard<std::mutex> lck(mutex_);
do_run_.store(true, std::memory_order_relaxed);
signal_.store(false, std::memory_order_relaxed);
}
thread_ = std::thread([this, func] { thread_ = std::thread([this, func] {
while (do_run_) { while (do_run_.load(std::memory_order_relaxed)) {
signal_ = false; signal_.store(false, std::memory_order_relaxed);
func(); func();
} }
}); });
@@ -56,24 +66,34 @@ class SleeperThread {
return *this; return *this;
} }
bool isRunning() const { return do_run_; } bool isRunning() const { return do_run_.load(std::memory_order_relaxed); }
auto sleep() { auto sleep() {
std::unique_lock lk(mutex_); std::unique_lock lk(mutex_);
CancellationGuard cancel_lock; CancellationGuard cancel_lock;
return condvar_.wait(lk, [this] { return signal_ || !do_run_; }); return condvar_.wait(lk, [this] {
return signal_.load(std::memory_order_relaxed) || !do_run_.load(std::memory_order_relaxed);
});
} }
auto sleep_for(std::chrono::system_clock::duration dur) { auto sleep_for(std::chrono::system_clock::duration dur) {
std::unique_lock lk(mutex_); std::unique_lock lk(mutex_);
CancellationGuard cancel_lock; CancellationGuard cancel_lock;
condvar_.wait(lk, [this] {
return !is_paused_ || signal_.load(std::memory_order_relaxed) ||
!do_run_.load(std::memory_order_relaxed);
});
constexpr auto max_time_point = std::chrono::steady_clock::time_point::max(); constexpr auto max_time_point = std::chrono::steady_clock::time_point::max();
auto wait_end = max_time_point; auto wait_end = max_time_point;
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
if (now < max_time_point - dur) { if (now < max_time_point - dur) {
wait_end = now + dur; wait_end = now + dur;
} }
return condvar_.wait_until(lk, wait_end, [this] { return signal_ || !do_run_; }); return condvar_.wait_until(lk, wait_end, [this] {
return signal_.load(std::memory_order_relaxed) || !do_run_.load(std::memory_order_relaxed);
});
} }
auto sleep_until( auto sleep_until(
@@ -81,22 +101,30 @@ class SleeperThread {
time_point) { time_point) {
std::unique_lock lk(mutex_); std::unique_lock lk(mutex_);
CancellationGuard cancel_lock; CancellationGuard cancel_lock;
return condvar_.wait_until(lk, time_point, [this] { return signal_ || !do_run_; });
condvar_.wait(lk, [this] {
return !is_paused_ || signal_.load(std::memory_order_relaxed) ||
!do_run_.load(std::memory_order_relaxed);
});
return condvar_.wait_until(lk, time_point, [this] {
return signal_.load(std::memory_order_relaxed) || !do_run_.load(std::memory_order_relaxed);
});
} }
void wake_up() { void wake_up() {
{ {
std::lock_guard<std::mutex> lck(mutex_); std::lock_guard<std::mutex> lck(mutex_);
signal_ = true; signal_.store(true, std::memory_order_relaxed);
} }
condvar_.notify_all(); condvar_.notify_all();
} }
auto stop() { void stop() {
{ {
std::lock_guard<std::mutex> lck(mutex_); std::lock_guard<std::mutex> lck(mutex_);
signal_ = true; signal_.store(true, std::memory_order_relaxed);
do_run_ = false; do_run_.store(false, std::memory_order_relaxed);
} }
condvar_.notify_all(); condvar_.notify_all();
auto handle = thread_.native_handle(); auto handle = thread_.native_handle();
@@ -106,6 +134,17 @@ class SleeperThread {
} }
} }
void pause() {
std::lock_guard<std::mutex> lock(mutex_);
is_paused_ = true;
}
void resume() {
std::lock_guard<std::mutex> lock(mutex_);
is_paused_ = false;
condvar_.notify_all();
}
~SleeperThread() { ~SleeperThread() {
connection_.disconnect(); connection_.disconnect();
stop(); stop();
@@ -118,9 +157,10 @@ class SleeperThread {
std::thread thread_; std::thread thread_;
std::condition_variable condvar_; std::condition_variable condvar_;
std::mutex mutex_; std::mutex mutex_;
bool do_run_ = true; std::atomic<bool> do_run_ = true;
bool signal_ = false; std::atomic<bool> signal_ = false;
sigc::connection connection_; sigc::connection connection_;
bool is_paused_{false};
}; };
} // namespace waybar::util } // namespace waybar::util
+4 -4
View File
@@ -4,18 +4,18 @@
namespace waybar::util { namespace waybar::util {
struct UdevDeleter { struct UdevDeleter {
void operator()(udev *ptr) const { udev_unref(ptr); } void operator()(udev* ptr) const { udev_unref(ptr); }
}; };
struct UdevDeviceDeleter { struct UdevDeviceDeleter {
void operator()(udev_device *ptr) const { udev_device_unref(ptr); } void operator()(udev_device* ptr) const { udev_device_unref(ptr); }
}; };
struct UdevEnumerateDeleter { struct UdevEnumerateDeleter {
void operator()(udev_enumerate *ptr) const { udev_enumerate_unref(ptr); } void operator()(udev_enumerate* ptr) const { udev_enumerate_unref(ptr); }
}; };
struct UdevMonitorDeleter { struct UdevMonitorDeleter {
void operator()(udev_monitor *ptr) const { udev_monitor_unref(ptr); } void operator()(udev_monitor* ptr) const { udev_monitor_unref(ptr); }
}; };
} // namespace waybar::util } // namespace waybar::util
+1 -1
View File
@@ -2,4 +2,4 @@
#include <glibmm/ustring.h> #include <glibmm/ustring.h>
// calculate column width of ustring // calculate column width of ustring
int ustring_clen(const Glib::ustring &str); int ustring_clen(const Glib::ustring& str);
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include <string>
namespace waybar::util {
size_t utf8_width(const std::string& str);
void utf8_truncate(std::string& s, const std::string& ellipsis, size_t max_len);
} // namespace waybar::util
+9 -1
View File
@@ -27,6 +27,11 @@ The *battery* module displays the current capacity and state (eg. charging) of y
default: false ++ default: false ++
Option to use the battery design capacity instead of its current maximal capacity. Option to use the battery design capacity instead of its current maximal capacity.
*full-at-plugged*: ++
typeof: bool ++
default: false ++
When enabled, a battery that is *Full* while the adapter is online is reported with the *Plugged* status instead of *Full* (so you can style/format it separately). Disabled by default to preserve the existing *Full* behaviour.
*interval*: ++ *interval*: ++
typeof: integer ++ typeof: integer ++
default: 60 ++ default: 60 ++
@@ -182,6 +187,7 @@ Every entry in the *events* object consists of a *<event-name>* (typeof: *string
- *on-<status>-<state>* - *on-<status>-<state>*
- *on-<status>-<capacity>* - *on-<status>-<capacity>*
- *on-<status>*
Where: Where:
@@ -203,7 +209,9 @@ Where:
"events": { "events": {
"on-discharging-warning": "notify-send -u normal 'Low Battery'", "on-discharging-warning": "notify-send -u normal 'Low Battery'",
"on-discharging-critical": "notify-send -u critical 'Very Low Battery'", "on-discharging-critical": "notify-send -u critical 'Very Low Battery'",
"on-charging-100": "notify-send -u normal 'Battery Full!'" "on-charging-100": "notify-send -u normal 'Battery Full!'",
"on-discharging": "notify-send -u normal 'Power Switch' Discharging",
"on-charging": "notify-send -u normal 'Power Switch' Charging'"
}, },
"format": "{capacity}% {icon}", "format": "{capacity}% {icon}",
"format-icons": ["", "", "", "", ""], "format-icons": ["", "", "", "", ""],
+14 -2
View File
@@ -204,7 +204,7 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe
``` ```
"clock": { "clock": {
"format": "{:%H:%M}  ", "format": "{:%H:%M}  ",
"format-alt": "{:%A, %B %d, %Y (%R)} ", "format-alt": "{:%A, %B %d, %Y (%R)} 󰃰 ",
"tooltip-format": "<tt><small>{calendar}</small></tt>", "tooltip-format": "<tt><small>{calendar}</small></tt>",
"calendar": { "calendar": {
"mode" : "year", "mode" : "year",
@@ -259,7 +259,19 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe
"tooltip-format": "{tz_list}" "tooltip-format": "{tz_list}"
} }
``` ```
5. Simple calendar tooltip
```
"clock": {
"format": "{:%H:%M}",
"tooltip-format": "<tt>{calendar}</tt>",
"calendar": {
"format": {
"today": "<span color='#ffcc66'><b>{}</b></span>"
}
}
}
```
# STYLE # STYLE
- *#clock* - *#clock*
@@ -287,7 +299,7 @@ Example of working config
``` ```
"clock": { "clock": {
"format": "{:%H:%M}  ", "format": "{:%H:%M}  ",
"format-alt": "{:%A, %B %d, %Y (%R)} ", "format-alt": "{:%A, %B %d, %Y (%R)} 󰃰 ",
"tooltip-format": "\n<span size='9pt' font='WenQuanYi Zen Hei Mono'>{calendar}</span>", "tooltip-format": "\n<span size='9pt' font='WenQuanYi Zen Hei Mono'>{calendar}</span>",
"calendar": { "calendar": {
"mode" : "year", "mode" : "year",
+2 -2
View File
@@ -43,7 +43,7 @@ Feral Gamemode optimizations.
*glyph*: ++ *glyph*: ++
typeof: string ++ typeof: string ++
default: ++ default: 󰊴 ++
The string icon to display. Only visible if *use-icon* is set to false. The string icon to display. Only visible if *use-icon* is set to false.
*icon-name*: ++ *icon-name*: ++
@@ -82,7 +82,7 @@ Feral Gamemode optimizations.
"gamemode": { "gamemode": {
"format": "{glyph}", "format": "{glyph}",
"format-alt": "{glyph} {count}", "format-alt": "{glyph} {count}",
"glyph": "", "glyph": "󰊴",
"hide-not-running": true, "hide-not-running": true,
"use-icon": true, "use-icon": true,
"icon-name": "input-gaming-symbolic", "icon-name": "input-gaming-symbolic",
+36
View File
@@ -38,6 +38,20 @@ Addressed by *hyprland/language*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*tooltip*: ++
typeof: boolean ++
default: true ++
Enables or disables the tooltip for the language module. By default, the tooltip is enabled. Set to *false* to disable.
*tooltip-format*: ++
typeof: string ++
default: {long} ++
Specifies the format of the tooltip when it is enabled. It follows the same format replacement rules as the *format* key.
*tooltip-format-<lang>*: ++
typeof: string ++
Allows specifying a different tooltip format for each language. The *<lang>* should be replaced with the language code. This can be used to provide a custom tooltip for each language.
*expand*: ++ *expand*: ++
typeof: bool ++ typeof: bool ++
default: false ++ default: false ++
@@ -66,6 +80,28 @@ Addressed by *hyprland/language*
} }
``` ```
```
"hyprland/language": {
"format": "{}",
"format-en": "US",
"format-es": "ES",
"tooltip": true,
"tooltip-format": "{long}"
}
```
```
"hyprland/language": {
"format": "{}",
"format-en": "US",
"format-es": "ES",
"tooltip": true,
"tooltip-format": "{}",
"tooltip-format-es": "{Español}",
"tooltip-format-en": "{English (american)}"
}
```
# STYLE # STYLE
- *#language* - *#language*
+13
View File
@@ -130,6 +130,19 @@ This setting is ignored if *workspace-taskbar.enable* is set to true.
Otherwise, the workspace will open on the monitor where it was previously assigned. Otherwise, the workspace will open on the monitor where it was previously assigned.
Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland. Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland.
*enable-bar-scroll*: ++
typeof: bool ++
default: false ++
If set to false, you can't scroll to cycle throughout workspaces from the entire bar. If set to true this behaviour is enabled.
*on-scroll-up*: ++
typeof: string ++
Command to execute when scrolling up on the module. This replaces the default behaviour of workspace cycling.
*on-scroll-down*: ++
typeof: string ++
Command to execute when scrolling down on the module. This replaces the default behaviour of workspace cycling.
*ignore-workspaces*: ++ *ignore-workspaces*: ++
typeof: array ++ typeof: array ++
default: [] ++ default: [] ++
+2 -1
View File
@@ -26,7 +26,8 @@ The *image* module displays an image from a path.
*interval*: ++ *interval*: ++
typeof: integer or float ++ typeof: integer or float ++
The interval (in seconds) to re-render the image. ++ The interval (in seconds) to re-render the image. ++
Minimum value is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++ If set to a positive value, the minimum is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++
Zero or negative values are treated as "once". ++
This is useful if the contents of *path* changes. ++ This is useful if the contents of *path* changes. ++
If no *interval* is defined, the image will only be rendered once. If no *interval* is defined, the image will only be rendered once.
+12 -6
View File
@@ -102,23 +102,29 @@ Addressed by *memory*
default: false ++ default: false ++
Enables this module to consume all left over space dynamically. Enables this module to consume all left over space dynamically.
*unit*: ++
typeof: string ++
default: GiB ++
Used to specify unit for total, swapTotal, used, swapUsed, avail, swapAvail,
and swapState. Accepts B, kB, kiB, MB, MiB, GB, GiB, TB, and TiB.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{percentage}*: Percentage of memory in use. *{percentage}*: Percentage of memory in use.
*{swapPercentage}*: Percentage of swap in use. *{swapPercentage}*: Percentage of swap in use.
*{total}*: Amount of total memory available in GiB. *{total}*: Amount of total memory available. Defaults to GiB.
*{swapTotal}*: Amount of total swap available in GiB. *{swapTotal}*: Amount of total swap available. Defaults to GiB.
*{used}*: Amount of used memory in GiB. *{used}*: Amount of used memory. Defaults to GiB.
*{swapUsed}*: Amount of used swap in GiB. *{swapUsed}*: Amount of used swap. Defaults to GiB.
*{avail}*: Amount of available memory in GiB. *{avail}*: Amount of available memory. Defaults to GiB.
*{swapAvail}*: Amount of available swap in GiB. *{swapAvail}*: Amount of available swap. Defaults to GiB.
*{swapState}*: Signals if swap is activated or not *{swapState}*: Signals if swap is activated or not
+24 -4
View File
@@ -28,9 +28,20 @@ The volume can be controlled by dragging the slider across the bar or clicking o
The orientation of the slider. Can be either `horizontal` or `vertical`. The orientation of the slider. Can be either `horizontal` or `vertical`.
*expand*: ++ *expand*: ++
typeof: bool ++ typeof: bool ++
default: false ++ default: false ++
Enables this module to consume all left over space dynamically. Enables this module to consume all left over space dynamically.
*zero-on-mute*: ++
typeof: bool ++
default: true ++
`true` = The slider will be set to `min` when the source/sink is muted. ++
`false` = The slider will continue to show the unmuted volume level when the source/sink is muted.
*unmute-on-volume-change*: ++
typeof: bool ++
default: true ++
Specifies whether to unmute a muted souce/sink when its volume is changed by the user moving the slider.
# EXAMPLES # EXAMPLES
@@ -41,7 +52,9 @@ The volume can be controlled by dragging the slider across the bar or clicking o
"pulseaudio/slider": { "pulseaudio/slider": {
"min": 0, "min": 0,
"max": 100, "max": 100,
"orientation": "horizontal" "orientation": "horizontal",
"zero-on-mute": false,
"unmute-on-volume-change": false
} }
``` ```
@@ -52,6 +65,9 @@ The slider is a component with multiple CSS Nodes, of which the following are ex
*#pulseaudio-slider*: ++ *#pulseaudio-slider*: ++
Controls the style of the box *around* the slider and bar. Controls the style of the box *around* the slider and bar.
*#pulseaudio-slider.muted*: ++
Controls the style when the audio source/sink is muted.
*#pulseaudio-slider slider*: ++ *#pulseaudio-slider slider*: ++
Controls the style of the slider handle. Controls the style of the slider handle.
@@ -85,4 +101,8 @@ The slider is a component with multiple CSS Nodes, of which the following are ex
border-radius: 5px; border-radius: 5px;
background: green; background: green;
} }
#pulseaudio-slider.muted highlight {
background-color: orange;
}
``` ```
+7 -3
View File
@@ -97,7 +97,11 @@ Additionally, you can control the volume by scrolling *up* or *down* while the c
*reverse-scrolling*: ++ *reverse-scrolling*: ++
typeof: bool ++ typeof: bool ++
Option to reverse the scroll direction. Option to reverse the scroll direction for touchpads.
*reverse-mouse-scrolling*: ++
typeof: bool ++
Option to reverse the scroll direction for mice.
*tooltip*: ++ *tooltip*: ++
typeof: bool ++ typeof: bool ++
@@ -174,8 +178,8 @@ to be selected when the corresponding audio device is muted. This applies to *de
"alsa_output.pci-0000_00_1f.3.analog-stereo": "", "alsa_output.pci-0000_00_1f.3.analog-stereo": "",
"alsa_output.pci-0000_00_1f.3.analog-stereo-muted": "", "alsa_output.pci-0000_00_1f.3.analog-stereo-muted": "",
"headphone": "", "headphone": "",
"hands-free": "", "hands-free": "󰂑",
"headset": "", "headset": "󰂑",
"phone": "", "phone": "",
"phone-muted": "", "phone-muted": "",
"portable": "", "portable": "",
+1 -1
View File
@@ -87,7 +87,7 @@ Addressed by *river/mode*
``` ```
"river/mode": { "river/mode": {
"format": " {}" "format": " {}"
} }
``` ```
+20 -6
View File
@@ -8,13 +8,27 @@ waybar-styles - using stylesheets for waybar
Waybar uses Cascading Style Sheets (CSS) to configure its appearance. Waybar uses Cascading Style Sheets (CSS) to configure its appearance.
It uses the first file found in this search order: When the system appearance is light, Waybar first looks for *style-light.css*.
When the system appearance is dark, Waybar first looks for *style-dark.css*.
If no appearance-specific stylesheet is found, it falls back to *style.css*.
- *$XDG_CONFIG_HOME/waybar/style.css* Waybar uses the first file found in this search order for each stylesheet name:
- *~/.config/waybar/style.css*
- *~/waybar/style.css* - *$XDG_CONFIG_HOME/waybar/<stylesheet>*
- */etc/xdg/waybar/style.css* - *~/.config/waybar/<stylesheet>*
- *@sysconfdir@/xdg/waybar/style.css* - *~/waybar/<stylesheet>*
- */etc/xdg/waybar/<stylesheet>*
- *@sysconfdir@/xdg/waybar/<stylesheet>*
For example, a light theme is loaded from the first available file among:
- *$XDG_CONFIG_HOME/waybar/style-light.css*
- *~/.config/waybar/style-light.css*
- *~/waybar/style-light.css*
- */etc/xdg/waybar/style-light.css*
- *@sysconfdir@/xdg/waybar/style-light.css*
If no file is found there, Waybar repeats the same search using *style.css*.
# EXAMPLE # EXAMPLE
+1 -1
View File
@@ -92,7 +92,7 @@ Addressed by *sway/mode*
``` ```
"sway/mode": { "sway/mode": {
"format": " {}", "format": " {}",
"max-length": 50 "max-length": 50
} }
``` ```
+37 -8
View File
@@ -19,7 +19,7 @@ Addressed by *systemd-failed-units*
*format-ok*: ++ *format-ok*: ++
typeof: string ++ typeof: string ++
This format is used when there is no failing units. This format is used when there are no failing units.
*user*: ++ *user*: ++
typeof: bool ++ typeof: bool ++
@@ -34,15 +34,30 @@ Addressed by *systemd-failed-units*
*hide-on-ok*: ++ *hide-on-ok*: ++
typeof: bool ++ typeof: bool ++
default: *true* ++ default: *true* ++
Option to hide this module when there is no failing units. Option to hide this module when there are no failed units.
*tooltip-format*: ++
typeof: string ++
default: *System: {system_state}\nUser: {user_state}\nFailed units ({nr_failed}):\n{failed_units_list}* ++
Tooltip format shown when there are failed units.
*tooltip-format-ok*: ++
typeof: string ++
default: *System: {system_state}\nUser: {user_state}* ++
Tooltip format used when there are no failed units.
*tooltip-unit-format*: ++
typeof: string ++
default: *{name}: {description}* ++
Format used to render each failed unit inside the tooltip. Each item is prefixed with a bullet.
*menu*: ++ *menu*: ++
typeof: string ++ typeof: string ++
Action that popups the menu. Action that pops up the menu.
*menu-file*: ++ *menu-file*: ++
typeof: string ++ typeof: string ++
Location of the menu descriptor file. There need to be an element of type Location of the menu descriptor file. There needs to be an element of type
GtkMenu with id *menu* GtkMenu with id *menu*
*menu-actions*: ++ *menu-actions*: ++
@@ -52,7 +67,7 @@ Addressed by *systemd-failed-units*
*expand*: ++ *expand*: ++
typeof: bool ++ typeof: bool ++
default: false ++ default: false ++
Enables this module to consume all left over space dynamically. Enables this module to consume all leftover space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
@@ -62,11 +77,23 @@ Addressed by *systemd-failed-units*
*{nr_failed}*: Number of total failed units. *{nr_failed}*: Number of total failed units.
*{systemd_state}:* State of the systemd system session *{system_state}:* State of the systemd system session.
*{user_state}:* State of the systemd user session *{user_state}:* State of the systemd user session.
*{overall_state}:* Overall state of the systemd and user session. ("Ok" or "Degraded") *{overall_state}:* Overall state of the systemd and user session. ("ok" or "degraded")
*{failed_units_list}:* Bulleted list of failed units using *tooltip-unit-format*. Empty when
there are no failed units.
The *tooltip-unit-format* string supports the following replacements:
*{name}*: Unit name ++
*{description}*: Unit description ++
*{load_state}*: Unit load state ++
*{active_state}*: Unit active state ++
*{sub_state}*: Unit sub state ++
*{scope}*: Either *system* or *user* depending on where the unit originated
# EXAMPLES # EXAMPLES
@@ -77,6 +104,8 @@ Addressed by *systemd-failed-units*
"format-ok": "✓", "format-ok": "✓",
"system": true, "system": true,
"user": false, "user": false,
"tooltip-format": "{nr_failed} failed units:\n{failed_units_list}",
"tooltip-unit-format": "{scope}: {name} ({active_state})",
} }
``` ```
+1 -1
View File
@@ -128,7 +128,7 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
``` ```
"wireplumber#sink": { "wireplumber#sink": {
"format": "{volume}% {icon}", "format": "{volume}% {icon}",
"format-muted": "", "format-muted": "󰅶",
"format-icons": ["", "", ""], "format-icons": ["", "", ""],
"on-click": "helvum", "on-click": "helvum",
"on-click-right": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle", "on-click-right": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
+5
View File
@@ -57,6 +57,11 @@ Addressed by *wlr/taskbar*
default: false ++ default: false ++
If set to true, group tasks by their app_id. Cannot be used with 'active-first'. If set to true, group tasks by their app_id. Cannot be used with 'active-first'.
*expand*: ++
typeof: bool ++
default: false ++
If set to true, task buttons stretch to fill the available space in the taskbar and long titles are ellipsized to fit. Only takes effect on a horizontal bar; on a vertical bar the buttons keep their content-based size. If set to false, buttons are sized to their content.
*on-click*: ++ *on-click*: ++
typeof: string ++ typeof: string ++
The action which should be triggered when clicking on the application button with the left mouse button. The action which should be triggered when clicking on the application button with the left mouse button.
+8 -2
View File
@@ -19,7 +19,7 @@ Valid locations for this file are:
A good starting point is the default configuration found at https://github.com/Alexays/Waybar/blob/master/resources/config.jsonc A good starting point is the default configuration found at https://github.com/Alexays/Waybar/blob/master/resources/config.jsonc
Also, a minimal example configuration can be found at the bottom of this man page. Also, a minimal example configuration can be found at the bottom of this man page.
The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(5)* for details. The visual display elements for waybar use a CSS stylesheet. Waybar supports *style.css* and the appearance-specific *style-light.css* and *style-dark.css* files; see *waybar-styles(5)* for details.
# BAR CONFIGURATION # BAR CONFIGURATION
@@ -36,7 +36,7 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(
*expand-right* ++ *expand-right* ++
typeof: bool ++ typeof: bool ++
default: false ++ default: false ++
Enables the modules-left to consume all left over space dynamically. Enables the modules-right to consume all left over space dynamically.
*layer* ++ *layer* ++
typeof: string ++ typeof: string ++
@@ -168,6 +168,7 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(
# MODULE FORMAT # MODULE FORMAT
You can use PangoMarkupFormat (See https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat). You can use PangoMarkupFormat (See https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat).
Tooltip appearance is generally controlled globally via CSS and cannot be truly scoped per module. Some modules (such as the clock) provide limited workarounds for customization.
e.g. e.g.
@@ -363,6 +364,11 @@ A group may hide all but one element, showing them only on mouse hover. In order
default: false ++ default: false ++
Whether left click should reveal the content rather than mouse over. Note that grouped modules may still process their own on-click events. Whether left click should reveal the content rather than mouse over. Note that grouped modules may still process their own on-click events.
*start-expanded*: ++
typeof: bool ++
default: false ++
Defines whether the drawer should initialize in an expanded state.
*transition-left-to-right*: ++ *transition-left-to-right*: ++
typeof: bool ++ typeof: bool ++
default: true ++ default: true ++
+4 -2
View File
@@ -1,6 +1,6 @@
project( project(
'waybar', 'cpp', 'c', 'waybar', 'cpp', 'c',
version: '0.14.0', version: '0.15.0',
license: 'MIT', license: 'MIT',
meson_version: '>= 0.59.0', meson_version: '>= 0.59.0',
default_options : [ default_options : [
@@ -185,7 +185,9 @@ src_files = files(
'src/util/gtk_icon.cpp', 'src/util/gtk_icon.cpp',
'src/util/icon_loader.cpp', 'src/util/icon_loader.cpp',
'src/util/regex_collection.cpp', 'src/util/regex_collection.cpp',
'src/util/css_reload_helper.cpp' 'src/util/css_reload_helper.cpp',
'src/util/transform_8bit_to_rgba.cpp',
'src/util/utf8_string.cpp'
) )
man_files = files( man_files = files(

Some files were not shown because too many files have changed in this diff Show More