Merge remote-tracking branch 'origin/master' into ico277/master

# Conflicts:
#	src/modules/temperature.cpp
This commit is contained in:
Alex
2026-07-03 22:27:43 +02:00
256 changed files with 8645 additions and 4554 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
@@ -20,8 +20,12 @@ debug-run: build-debug
./build/waybar --log-level debug ./build/waybar --log-level debug
test: test:
meson test -C build --no-rebuild --verbose --suite waybar meson test -C build --verbose --suite waybar
.PHONY: test .PHONY: test
test-detailed:
meson test -C build --verbose --print-errorlogs --test-args='--reporter console -s'
.PHONY: test-detailed
clean: clean:
rm -rf build rm -rf build
+34
View File
@@ -116,11 +116,45 @@ sudo apt install \
libxkbregistry-dev libxkbregistry-dev
``` ```
On Arch, you can use this command:
```
pacman -S --asdeps \
gtkmm3 \
jsoncpp \
libsigc++ \
fmt \
wayland \
chrono-date \
spdlog \
gtk3 \
gobject-introspection \
libgirepository \
libpulse \
libnl \
libappindicator-gtk3 \
libdbusmenu-gtk3 \
libmpdclient \
sndio \
libevdev \
libxkbcommon \
upower \
meson \
cmake \
scdoc \
wayland-protocols \
glib2-devel
```
Contributions welcome!<br> 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 @@
.
+5
View File
@@ -0,0 +1,5 @@
# Suppress common address sanitizer issues in dependencies, these are often non-fixable or not an issue.
# Use it like this (when in repo root): ASAN_OPTIONS="suppressions=./asan.supp" ./build/waybar
leak:libpangoft2-1.0.so.0
leak:libgtk-3.so.0
leak:libfontconfig.so.1
Generated
+6 -6
View File
@@ -3,11 +3,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1747046372, "lastModified": 1767039857,
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -18,11 +18,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1751011381, "lastModified": 1769461804,
"narHash": "sha256-krGXKxvkBhnrSC/kGBmg5MyupUUT5R6IBCLEzx9jhMM=", "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "30e2e2857ba47844aa71991daa6ed1fc678bcbb7", "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
"type": "github" "type": "github"
}, },
"original": { "original": {
+20 -22
View File
@@ -65,7 +65,7 @@
nativeBuildInputs = nativeBuildInputs =
pkgs.waybar.nativeBuildInputs pkgs.waybar.nativeBuildInputs
++ (with pkgs; [ ++ (with pkgs; [
nixfmt-rfc-style nixfmt
clang-tools clang-tools
gdb gdb
]); ]);
@@ -75,28 +75,26 @@
formatter = genSystems ( formatter = genSystems (
pkgs: pkgs:
pkgs.treefmt.withConfig { pkgs.treefmt.withConfig {
settings = [ settings = {
{ formatter = {
formatter = { clang-format = {
clang-format = { options = [ "-i" ];
options = [ "-i" ]; command = lib.getExe' pkgs.clang-tools "clang-format";
command = lib.getExe' pkgs.clang-tools "clang-format"; excludes = [ ];
excludes = [ ]; includes = [
includes = [ "*.c"
"*.c" "*.cpp"
"*.cpp" "*.h"
"*.h" "*.hpp"
"*.hpp" ];
];
};
nixfmt = {
command = lib.getExe pkgs.nixfmt-rfc-style;
includes = [ "*.nix" ];
};
}; };
tree-root-file = ".git/index"; nixfmt = {
} command = lib.getExe pkgs.nixfmt;
]; includes = [ "*.nix" ];
};
};
tree-root-file = ".git/index";
};
} }
); );
+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;
+16 -7
View File
@@ -4,33 +4,42 @@
#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_;
std::string format_; std::string format_;
const std::chrono::seconds interval_; const std::chrono::milliseconds interval_;
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"},
+22 -11
View File
@@ -14,6 +14,7 @@
#include "AModule.hpp" #include "AModule.hpp"
#include "group.hpp" #include "group.hpp"
#include "util/kill_signal.hpp"
#include "xdg-output-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h"
namespace waybar { namespace waybar {
@@ -61,18 +62,24 @@ 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 hide();
void handleSignal(int); void handleSignal(int);
util::KillSignalAction getOnSigusr1Action();
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;
@@ -86,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();
@@ -118,6 +126,9 @@ class Bar : public sigc::trackable {
std::unique_ptr<BarIpcClient> _ipc_client; std::unique_ptr<BarIpcClient> _ipc_client;
#endif #endif
std::vector<std::shared_ptr<waybar::AModule>> modules_all_; std::vector<std::shared_ptr<waybar::AModule>> modules_all_;
waybar::util::KillSignalAction onSigusr1 = util::SIGNALACTION_DEFAULT_SIGUSR1;
waybar::util::KillSignalAction onSigusr2 = util::SIGNALACTION_DEFAULT_SIGUSR2;
}; };
} // namespace waybar } // namespace waybar
+22 -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);
@@ -56,6 +57,10 @@ class Client {
std::list<struct waybar_output> outputs_; std::list<struct waybar_output> outputs_;
std::unique_ptr<CssReloadHelper> m_cssReloadHelper; std::unique_ptr<CssReloadHelper> m_cssReloadHelper;
std::string m_cssFile; std::string m_cssFile;
sigc::connection monitor_added_connection_;
sigc::connection monitor_removed_connection_;
std::list<waybar_output*> pending_outputs_;
bool bars_scheduled_ = false;
}; };
} // namespace waybar } // namespace waybar
+12 -10
View File
@@ -14,27 +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(
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_;
+8 -2
View File
@@ -6,6 +6,7 @@
#if defined(__linux__) #if defined(__linux__)
#include <sys/inotify.h> #include <sys/inotify.h>
#endif #endif
#include <poll.h>
#include <algorithm> #include <algorithm>
#include <fstream> #include <fstream>
@@ -15,6 +16,7 @@
#include "ALabel.hpp" #include "ALabel.hpp"
#include "bar.hpp" #include "bar.hpp"
#include "util/sleeper_thread.hpp" #include "util/sleeper_thread.hpp"
#include "util/udev_deleter.hpp"
namespace waybar::modules { namespace waybar::modules {
@@ -35,15 +37,19 @@ class Battery : public ALabel {
std::tuple<uint8_t, float, std::string, float, uint16_t, float> getInfos(); std::tuple<uint8_t, float, std::string, float, uint16_t, float> getInfos();
const std::string formatTimeRemaining(float hoursRemaining); const std::string formatTimeRemaining(float hoursRemaining);
void setBarClass(std::string&); void setBarClass(std::string&);
void processEvents(std::string& state, std::string& status, uint8_t capacity);
int global_watch;
std::map<fs::path, int> batteries_; std::map<fs::path, int> batteries_;
std::unique_ptr<udev, util::UdevDeleter> udev_;
std::array<pollfd, 1> poll_fds_;
std::unique_ptr<udev_monitor, util::UdevMonitorDeleter> mon_;
fs::path adapter_; fs::path adapter_;
int battery_watch_fd_; int battery_watch_fd_;
int global_watch_fd_;
std::mutex battery_list_mutex_; std::mutex battery_list_mutex_;
std::string old_status_; std::string old_status_;
std::string last_event_;
bool warnFirstTime_{true}; bool warnFirstTime_{true};
bool weightedAverage_{true};
const Bar& bar_; const Bar& bar_;
util::SleeperThread thread_; util::SleeperThread thread_;
-59
View File
@@ -1,59 +0,0 @@
#pragma once
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace cava {
extern "C" {
// Need sdl_glsl output feature to be enabled on libcava
#ifndef SDL_GLSL
#define SDL_GLSL
#endif
#include <cava/common.h>
#ifdef SDL_GLSL
#undef SDL_GLSL
#endif
}
} // namespace cava
namespace waybar::modules {
using namespace std::literals::chrono_literals;
class Cava final : public ALabel {
public:
Cava(const std::string&, const Json::Value&);
virtual ~Cava();
auto update() -> void override;
auto doAction(const std::string& name) -> void override;
private:
util::SleeperThread thread_;
util::SleeperThread thread_fetch_input_;
struct cava::error_s error_{}; // cava errors
struct cava::config_params prm_{}; // cava parameters
struct cava::audio_raw audio_raw_{}; // cava handled raw audio data(is based on audio_data)
struct cava::audio_data audio_data_{}; // cava audio data
struct cava::cava_plan* plan_; //{new cava_plan{}};
// Cava API to read audio source
cava::ptr input_source_;
// Delay to handle audio source
std::chrono::milliseconds frame_time_milsec_{1s};
// Text to display
std::string text_{""};
int rePaint_{1};
std::chrono::seconds fetch_input_delay_{4};
std::chrono::seconds suspend_silence_delay_{0};
bool silence_{false};
bool hide_on_silence_{false};
std::string format_silent_{""};
int sleep_counter_{0};
// Cava method
void pause_resume();
// ModuleActionMap
static inline std::map<const std::string, void (waybar::modules::Cava::* const)()> actionMap_{
{"mode", &waybar::modules::Cava::pause_resume}};
};
} // namespace waybar::modules
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <epoxy/gl.h>
#include "AModule.hpp"
#include "cava_backend.hpp"
namespace waybar::modules::cava {
class CavaGLSL final : public AModule, public Gtk::GLArea {
public:
CavaGLSL(const std::string&, const Json::Value&);
~CavaGLSL() = default;
private:
std::shared_ptr<CavaBackend> backend_;
struct ::cava::config_params prm_;
int frame_counter{0};
bool silence_{false};
bool hide_on_silence_{false};
// Cava method
auto onUpdate(const ::cava::audio_raw& input) -> void;
auto onSilence() -> void;
// Member variable to store the shared pointer
std::shared_ptr<::cava::audio_raw> m_data_;
GLuint shaderProgram_;
// OpenGL variables
GLuint fbo_;
GLuint texture_;
GLint uniform_bars_;
GLint uniform_previous_bars_;
GLint uniform_bars_count_;
GLint uniform_time_;
// Methods
void onRealize();
bool onRender(const Glib::RefPtr<Gdk::GLContext>& context);
void initShaders();
void initSurface();
void initGLSL();
GLuint loadShader(const std::string& fileName, GLenum type);
};
} // namespace waybar::modules::cava
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include "ALabel.hpp"
#include "cava_backend.hpp"
namespace waybar::modules::cava {
class Cava final : public ALabel, public sigc::trackable {
public:
Cava(const std::string&, const Json::Value&);
~Cava() = default;
auto doAction(const std::string& name) -> void override;
private:
std::shared_ptr<CavaBackend> backend_;
// Text to display
Glib::ustring label_text_{""};
bool silence_{false};
bool hide_on_silence_{false};
std::string format_silent_{""};
int ascii_range_{0};
// Cava method
void pause_resume();
auto onUpdate(const std::string& input) -> void;
auto onSilence() -> void;
// ModuleActionMap
static inline std::map<const std::string, void (waybar::modules::cava::Cava::* const)()>
actionMap_{{"mode", &waybar::modules::cava::Cava::pause_resume}};
};
} // namespace waybar::modules::cava
+84
View File
@@ -0,0 +1,84 @@
#pragma once
#include <json/json.h>
#include <sigc++/sigc++.h>
#include "util/sleeper_thread.hpp"
namespace cava {
extern "C" {
// Need sdl_glsl output feature to be enabled on libcava
#ifndef SDL_GLSL
#define SDL_GLSL
#endif
#include <cava/common.h>
#ifdef SDL_GLSL
#undef SDL_GLSL
#endif
}
} // namespace cava
namespace waybar::modules::cava {
using namespace std::literals::chrono_literals;
class CavaBackend final {
public:
static std::shared_ptr<CavaBackend> inst(const Json::Value& config);
virtual ~CavaBackend();
// Methods
int getAsciiRange();
void doPauseResume();
void Update();
const struct ::cava::config_params* getPrm();
std::chrono::milliseconds getFrameTimeMilsec();
// Signal accessor
using type_signal_update = sigc::signal<void(const std::string&)>;
type_signal_update signal_update();
using type_signal_audio_raw_update = sigc::signal<void(const ::cava::audio_raw&)>;
type_signal_audio_raw_update signal_audio_raw_update();
using type_signal_silence = sigc::signal<void()>;
type_signal_silence signal_silence();
private:
CavaBackend(const Json::Value& config);
util::SleeperThread read_thread_;
util::SleeperThread out_thread_;
// Cava API to read audio source
::cava::ptr input_source_{NULL};
struct ::cava::error_s error_{}; // cava errors
struct ::cava::config_params prm_{}; // cava parameters
struct ::cava::audio_raw audio_raw_{}; // cava handled raw audio data(is based on audio_data)
struct ::cava::audio_data audio_data_{}; // cava audio data
struct ::cava::cava_plan* plan_{NULL}; //{new cava_plan{}};
std::chrono::seconds fetch_input_delay_{4};
// Delay to handle audio source
std::chrono::milliseconds frame_time_milsec_{1s};
const Json::Value& config_;
int re_paint_{0};
bool silence_{false};
bool silence_prev_{false};
std::chrono::seconds suspend_silence_delay_{0};
int sleep_counter_{0};
std::string output_{};
// Methods
void invoke();
void execute();
bool isSilence();
void doUpdate(bool force = false);
void loadConfig();
void freeBackend();
// Signal
type_signal_update m_signal_update_;
type_signal_audio_raw_update m_signal_audio_raw_;
type_signal_silence m_signal_silence_;
};
} // namespace waybar::modules::cava
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#ifdef HAVE_LIBCAVA
#include "cavaRaw.hpp"
#include "cava_backend.hpp"
#ifdef HAVE_LIBCAVAGLSL
#include "cavaGLSL.hpp"
#endif
#endif
namespace waybar::modules::cava {
AModule* getModule(const std::string& id, const Json::Value& config) {
#ifdef HAVE_LIBCAVA
const std::shared_ptr<CavaBackend> backend_{waybar::modules::cava::CavaBackend::inst(config)};
switch (backend_->getPrm()->output) {
#ifdef HAVE_LIBCAVAGLSL
case ::cava::output_method::OUTPUT_SDL_GLSL:
return new waybar::modules::cava::CavaGLSL(id, config);
#endif
default:
return new waybar::modules::cava::Cava(id, config);
}
#else
throw std::runtime_error("Unknown module");
#endif
};
} // namespace waybar::modules::cava
+4 -2
View File
@@ -48,8 +48,9 @@ class Clock final : public ALabel {
std::string cldYearCached_; // calendar Year mode. Cached calendar std::string cldYearCached_; // calendar Year mode. Cached calendar
date::year_month cldMonShift_; // calendar Month mode. Cached ym date::year_month cldMonShift_; // calendar Month mode. Cached ym
std::string cldMonCached_; // calendar Month mode. Cached calendar std::string cldMonCached_; // calendar Month mode. Cached calendar
date::day cldBaseDay_{0}; // calendar Cached day. Is used when today is changing(midnight) date::day cldBaseDay_{0}; // calendar Cached day. Is used when today is changing(midnight)
std::string cldText_{""}; // calendar text to print std::string cldText_{""}; // calendar text to print
bool iso8601Calendar_{false}; // whether the calendar is in ISO8601
CldMode cldMode_{CldMode::MONTH}; CldMode cldMode_{CldMode::MONTH};
auto get_calendar(const date::year_month_day& today, const date::year_month_day& ymd, auto get_calendar(const date::year_month_day& today, const date::year_month_day& ymd,
const date::time_zone* tz) -> const std::string; const date::time_zone* tz) -> const std::string;
@@ -62,6 +63,7 @@ class Clock final : public ALabel {
std::vector<const date::time_zone*> tzList_; // time zones list std::vector<const date::time_zone*> tzList_; // time zones list
int tzCurrIdx_; // current time zone index for tzList_ int tzCurrIdx_; // current time zone index for tzList_
std::string tzText_{""}; // time zones text to print std::string tzText_{""}; // time zones text to print
std::string tzTooltipFormat_{""}; // optional timezone tooltip format
util::SleeperThread thread_; util::SleeperThread thread_;
// ordinal date in tooltip // ordinal date in tooltip
+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
+141
View File
@@ -0,0 +1,141 @@
#pragma once
#include <fmt/format.h>
#include <gtkmm/button.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>
#include <map>
#include <memory>
#include <vector>
#include "AModule.hpp"
#include "bar.hpp"
#include "ext-workspace-v1-client-protocol.h"
namespace waybar::modules::ext {
class WorkspaceGroup;
class Workspace;
class WorkspaceManager final : public AModule {
public:
WorkspaceManager(const std::string& id, const waybar::Bar& bar, const Json::Value& config);
~WorkspaceManager() override;
void register_manager(wl_registry* registry, uint32_t name, uint32_t version);
void remove_workspace_group(uint32_t id);
void remove_workspace(uint32_t id);
void set_needs_sorting() { needs_sorting_ = true; }
// wl events
void handle_workspace_group(ext_workspace_group_handle_v1* handle);
void handle_workspace(ext_workspace_handle_v1* handle);
void handle_done();
void handle_finished();
// wl requests
void commit() const;
private:
void update() override;
bool has_button(const Gtk::Button* button);
void sort_workspaces();
void clear_buttons();
void update_buttons();
static uint32_t group_global_id;
static uint32_t workspace_global_id;
uint32_t workspace_name = 0;
bool sort_by_id_ = false;
bool sort_by_name_ = true;
bool sort_by_coordinates_ = false;
bool all_outputs_ = false;
const waybar::Bar& bar_;
Gtk::Box box_;
ext_workspace_manager_v1* ext_manager_ = nullptr;
std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
std::vector<std::unique_ptr<Workspace>> workspaces_;
bool needs_sorting_ = false;
};
class WorkspaceGroup {
public:
WorkspaceGroup(WorkspaceManager& manager, ext_workspace_group_handle_v1* handle, uint32_t id);
~WorkspaceGroup();
u_int32_t id() const { return id_; }
bool has_output(const wl_output* output);
bool has_workspace(const ext_workspace_handle_v1* workspace);
// wl events
void handle_capabilities(uint32_t capabilities);
void handle_output_enter(wl_output* output);
void handle_output_leave(wl_output* output);
void handle_workspace_enter(ext_workspace_handle_v1* handle);
void handle_workspace_leave(ext_workspace_handle_v1* handle);
void handle_removed();
private:
WorkspaceManager& workspaces_manager_;
ext_workspace_group_handle_v1* ext_handle_;
uint32_t id_;
std::vector<wl_output*> outputs_;
std::vector<ext_workspace_handle_v1*> workspaces_;
};
class Workspace {
public:
Workspace(const Json::Value& config, WorkspaceManager& manager, ext_workspace_handle_v1* handle,
uint32_t id, const std::string& name);
~Workspace();
ext_workspace_handle_v1* handle() const { return ext_handle_; }
u_int32_t id() const { return id_; }
std::string& workspace_id() { return workspace_id_; }
std::string& name() { return name_; }
std::vector<u_int32_t>& coordinates() { return coordinates_; }
Gtk::Button& button() { return button_; }
void update();
// wl events
void handle_id(const std::string& id);
void handle_name(const std::string& name);
void handle_coordinates(const std::vector<uint32_t>& coordinates);
void handle_state(uint32_t state);
void handle_capabilities(uint32_t capabilities);
void handle_removed();
// gdk events
bool handle_clicked(const GdkEventButton* button) const;
private:
bool has_state(uint32_t state) const { return (state_ & state) == state; }
std::string icon();
WorkspaceManager& workspace_manager_;
ext_workspace_handle_v1* ext_handle_ = nullptr;
uint32_t id_;
uint32_t state_ = 0;
std::string workspace_id_;
std::string name_;
std::vector<uint32_t> coordinates_;
bool active_only_ = false;
bool ignore_hidden_ = true;
std::string format_;
bool with_icon_ = false;
static std::map<std::string, std::string> icon_map_;
std::string on_click_action_;
std::string on_click_middle_action_;
std::string on_click_right_action_;
Gtk::Button button_;
Gtk::Box content_;
Gtk::Label label_;
};
} // namespace waybar::modules::ext
@@ -0,0 +1,10 @@
#include "ext-workspace-v1-client-protocol.h"
namespace waybar::modules::ext {
void add_registry_listener(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* data);
ext_workspace_manager_v1* workspace_manager_bind(wl_registry* registry, uint32_t name,
uint32_t version, void* data);
} // 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;
+24 -6
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>
@@ -17,9 +19,13 @@ class EventHandler {
virtual ~EventHandler() = default; virtual ~EventHandler() = default;
}; };
/// If you want to use the Hyprland IPC, simply use IPC::inst() to get the singleton instance.
/// Do not create multiple instances.
class IPC { class IPC {
protected:
IPC(); // use IPC::inst() instead.
public: public:
IPC();
~IPC(); ~IPC();
static IPC& inst(); static IPC& inst();
@@ -30,21 +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
bool running_ = true; pid_t socketOwnerPid_ = -1;
std::atomic<bool> running_ = true; // the ipcThread will stop running when this is false
}; };
inline bool modulesReady = false;
inline std::unique_ptr<IPC> gIPC;
}; // 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;
}; };
+3 -3
View File
@@ -7,7 +7,6 @@
#include "AAppIconLabel.hpp" #include "AAppIconLabel.hpp"
#include "bar.hpp" #include "bar.hpp"
#include "modules/hyprland/backend.hpp" #include "modules/hyprland/backend.hpp"
#include "util/json.hpp"
namespace waybar::modules::hyprland { namespace waybar::modules::hyprland {
@@ -26,8 +25,8 @@ class WindowCount : public waybar::AAppIconLabel, public EventHandler {
static auto parse(const Json::Value& value) -> Workspace; static auto parse(const Json::Value& value) -> Workspace;
}; };
static auto getActiveWorkspace(const std::string&) -> Workspace; auto getActiveWorkspace(const std::string&) -> Workspace;
static auto getActiveWorkspace() -> Workspace; auto getActiveWorkspace() -> Workspace;
void onEvent(const std::string& ev) override; void onEvent(const std::string& ev) override;
void queryActiveWorkspace(); void queryActiveWorkspace();
void setClass(const std::string&, bool enable); void setClass(const std::string&, bool enable);
@@ -36,6 +35,7 @@ class WindowCount : public waybar::AAppIconLabel, public EventHandler {
std::mutex mutex_; std::mutex mutex_;
const Bar& bar_; const Bar& bar_;
Workspace workspace_; Workspace workspace_;
IPC& m_ipc;
}; };
} // namespace waybar::modules::hyprland } // namespace waybar::modules::hyprland
@@ -26,18 +26,32 @@ namespace waybar::modules::hyprland {
class Workspaces; class Workspaces;
struct WindowRepr {
std::string address;
std::string window_class;
std::string window_title;
std::string repr_rewrite;
bool isActive = false;
public:
bool empty() const { return address.empty(); }
void setActive(bool value) { isActive = value; }
};
class WindowCreationPayload { class WindowCreationPayload {
public: public:
WindowCreationPayload(std::string workspace_name, WindowAddress window_address, WindowCreationPayload(const std::string& workspace_name, WindowAddress window_address,
std::string 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); 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();
bool isEmpty(Workspaces& workspace_manager); bool isEmpty(Workspaces& workspace_manager);
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); } bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
std::string repr(Workspaces& workspace_manager); WindowRepr repr(Workspaces& workspace_manager);
void setActive(bool value) { m_isActive = value; }
std::string getWorkspaceName() const { return m_workspaceName; } std::string getWorkspaceName() const { return m_workspaceName; }
WindowAddress getAddress() const { return m_windowAddress; } WindowAddress getAddress() const { return m_windowAddress; }
@@ -48,12 +62,13 @@ class WindowCreationPayload {
void clearAddr(); void clearAddr();
void clearWorkspaceName(); void clearWorkspaceName();
using Repr = std::string; using Repr = WindowRepr;
using ClassAndTitle = std::pair<std::string, std::string>; using ClassAndTitle = std::pair<std::string, std::string>;
std::variant<Repr, ClassAndTitle> m_window; std::variant<Repr, ClassAndTitle> m_window;
WindowAddress m_windowAddress; WindowAddress m_windowAddress;
std::string m_workspaceName; std::string m_workspaceName;
bool m_isActive = false;
int m_timeSpentUncreated = 0; int m_timeSpentUncreated = 0;
}; };
+27 -7
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; };
@@ -42,10 +43,18 @@ class Workspace {
bool isPersistentConfig() const { return m_isPersistentConfig; }; bool isPersistentConfig() const { return m_isPersistentConfig; };
bool isPersistentRule() const { return m_isPersistentRule; }; bool isPersistentRule() const { return m_isPersistentRule; };
bool isVisible() const { return m_isVisible; }; bool isVisible() const { return m_isVisible; };
bool isEmpty() const { return m_windows == 0; };
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; };
@@ -54,15 +63,18 @@ class Workspace {
void setWindows(uint value) { m_windows = value; }; void setWindows(uint value) { m_windows = value; };
void setName(std::string const& value) { m_name = value; }; void setName(std::string const& value) { m_name = value; };
void setOutput(std::string const& value) { m_output = value; }; void setOutput(std::string const& value) { m_output = value; };
bool containsWindow(WindowAddress const& addr) const { return m_windowMap.contains(addr); } bool containsWindow(WindowAddress const& addr) const {
return std::ranges::any_of(m_windowMap,
[&addr](const auto& window) { return window.address == addr; });
};
void insertWindow(WindowCreationPayload create_window_payload); void insertWindow(WindowCreationPayload create_window_payload);
std::string removeWindow(WindowAddress const& addr);
void initializeWindowMap(const Json::Value& clients_data); void initializeWindowMap(const Json::Value& clients_data);
void setActiveWindow(WindowAddress const& addr);
bool onWindowOpened(WindowCreationPayload const& create_window_payload); bool onWindowOpened(WindowCreationPayload const& create_window_payload);
std::optional<std::string> closeWindow(WindowAddress const& addr); std::optional<WindowRepr> closeWindow(WindowAddress const& addr);
void update(const std::string& format, const std::string& icon); void update(const std::string& workspace_icon);
private: private:
Workspaces& m_workspaceManager; Workspaces& m_workspaceManager;
@@ -78,11 +90,19 @@ class Workspace {
bool m_isUrgent = false; bool m_isUrgent = false;
bool m_isVisible = false; bool m_isVisible = false;
std::map<WindowAddress, std::string> m_windowMap; sigc::connection m_hoverCheckConnection;
std::vector<WindowRepr> m_windowMap;
Gtk::Button m_button; Gtk::Button m_button;
Gtk::Box m_content; Gtk::Box m_content;
Gtk::Label m_label; Gtk::Label m_labelBefore;
Gtk::Label m_labelAfter;
bool isEmpty() const;
void updateTaskbar(const std::string& workspace_icon);
bool handleClick(const GdkEventButton* event_button, WindowAddress const& addr) const;
bool shouldSkipWindow(const WindowRepr& window_repr) const;
IPC& m_ipc; IPC& m_ipc;
}; };
+50 -3
View File
@@ -1,8 +1,10 @@
#pragma once #pragma once
#include <gtkmm/button.h> #include <gtkmm/button.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>
@@ -18,6 +20,7 @@
#include "modules/hyprland/windowcreationpayload.hpp" #include "modules/hyprland/windowcreationpayload.hpp"
#include "modules/hyprland/workspace.hpp" #include "modules/hyprland/workspace.hpp"
#include "util/enum.hpp" #include "util/enum.hpp"
#include "util/icon_loader.hpp"
#include "util/regex_collection.hpp" #include "util/regex_collection.hpp"
using WindowAddress = std::string; using WindowAddress = std::string;
@@ -39,14 +42,30 @@ class Workspaces : public AModule, public EventHandler {
auto specialVisibleOnly() const -> bool { return m_specialVisibleOnly; } auto specialVisibleOnly() const -> bool { return m_specialVisibleOnly; }
auto persistentOnly() const -> bool { return m_persistentOnly; } auto persistentOnly() const -> bool { return m_persistentOnly; }
auto moveToMonitor() const -> bool { return m_moveToMonitor; } auto moveToMonitor() const -> bool { return m_moveToMonitor; }
auto enableTaskbar() const -> bool { return m_enableTaskbar; }
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 formatAfter() const -> std::string { return m_formatAfter; }
auto taskbarFormatBefore() const -> std::string { return m_taskbarFormatBefore; }
auto taskbarFormatAfter() const -> std::string { return m_taskbarFormatAfter; }
auto taskbarIconSize() const -> int { return m_taskbarIconSize; }
auto taskbarOrientation() const -> Gtk::Orientation { return m_taskbarOrientation; }
auto taskbarReverseDirection() const -> bool { return m_taskbarReverseDirection; }
auto onClickWindow() const -> std::string { return m_onClickWindow; }
auto getIgnoredWindows() const -> std::vector<std::regex> { return m_ignoreWindows; }
std::string getRewrite(std::string window_class, std::string window_title); enum class ActiveWindowPosition { NONE, FIRST, LAST };
auto activeWindowPosition() const -> ActiveWindowPosition { return m_activeWindowPosition; }
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);
bool windowRewriteConfigUsesTitle() const { return m_anyWindowRewriteRuleUsesTitle; } bool windowRewriteConfigUsesTitle() const { return m_anyWindowRewriteRuleUsesTitle; }
const IconLoader& iconLoader() const { return m_iconLoader; }
private: private:
void onEvent(const std::string& e) override; void onEvent(const std::string& e) override;
@@ -70,6 +89,7 @@ class Workspaces : public AModule, public EventHandler {
auto populateIgnoreWorkspacesConfig(const Json::Value& config) -> void; auto populateIgnoreWorkspacesConfig(const Json::Value& config) -> void;
auto populateFormatWindowSeparatorConfig(const Json::Value& config) -> void; auto populateFormatWindowSeparatorConfig(const Json::Value& config) -> void;
auto populateWindowRewriteConfig(const Json::Value& config) -> void; auto populateWindowRewriteConfig(const Json::Value& config) -> void;
auto populateWorkspaceTaskbarConfig(const Json::Value& config) -> void;
void registerIpc(); void registerIpc();
@@ -92,6 +112,7 @@ class Workspaces : public AModule, public EventHandler {
void onWindowMoved(std::string const& payload); void onWindowMoved(std::string const& payload);
void onWindowTitleEvent(std::string const& payload); void onWindowTitleEvent(std::string const& payload);
void onActiveWindowChanged(WindowAddress const& payload);
void onConfigReloaded(); void onConfigReloaded();
@@ -103,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();
@@ -126,12 +149,13 @@ 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.
// This happens when the user has multiple monitors (hence, multiple bars) // This happens when the user has multiple monitors (hence, multiple bars)
// and doesn't share windows across bars (a.k.a `all-outputs` = false) // and doesn't share windows across bars (a.k.a `all-outputs` = false)
std::map<WindowAddress, std::string> m_orphanWindowMap; std::map<WindowAddress, WindowRepr, std::less<>> m_orphanWindowMap;
enum class SortMethod { ID, NAME, NUMBER, SPECIAL_CENTERED, DEFAULT }; enum class SortMethod { ID, NAME, NUMBER, SPECIAL_CENTERED, DEFAULT };
util::EnumParser<SortMethod> m_enumParser; util::EnumParser<SortMethod> m_enumParser;
@@ -142,7 +166,8 @@ class Workspaces : public AModule, public EventHandler {
{"SPECIAL-CENTERED", SortMethod::SPECIAL_CENTERED}, {"SPECIAL-CENTERED", SortMethod::SPECIAL_CENTERED},
{"DEFAULT", SortMethod::DEFAULT}}; {"DEFAULT", SortMethod::DEFAULT}};
std::string m_format; std::string m_formatBefore;
std::string m_formatAfter;
std::map<std::string, std::string> m_iconsMap; std::map<std::string, std::string> m_iconsMap;
util::RegexCollection m_windowRewriteRules; util::RegexCollection m_windowRewriteRules;
@@ -158,11 +183,33 @@ class Workspaces : public AModule, public EventHandler {
std::vector<std::string> m_workspacesToRemove; std::vector<std::string> m_workspacesToRemove;
std::vector<WindowCreationPayload> m_windowsToCreate; std::vector<WindowCreationPayload> m_windowsToCreate;
IconLoader m_iconLoader;
bool m_enableTaskbar = false;
bool m_updateActiveWindow = false;
bool m_taskbarWithIcon = false;
bool m_taskbarWithTitle = false;
std::string m_taskbarFormatBefore;
std::string m_taskbarFormatAfter;
int m_taskbarIconSize = 16;
Gtk::Orientation m_taskbarOrientation = Gtk::ORIENTATION_HORIZONTAL;
bool m_taskbarReverseDirection = false;
util::EnumParser<ActiveWindowPosition> m_activeWindowEnumParser;
ActiveWindowPosition m_activeWindowPosition = ActiveWindowPosition::NONE;
std::map<std::string, ActiveWindowPosition> m_activeWindowPositionMap = {
{"NONE", ActiveWindowPosition::NONE},
{"FIRST", ActiveWindowPosition::FIRST},
{"LAST", ActiveWindowPosition::LAST},
};
std::string m_onClickWindow;
std::string m_currentActiveWindowAddress;
std::vector<std::regex> m_ignoreWorkspaces; std::vector<std::regex> m_ignoreWorkspaces;
std::vector<std::regex> m_ignoreWindows;
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;
}; };
+1 -1
View File
@@ -31,7 +31,7 @@ class Image : public AModule {
std::string path_; std::string path_;
std::string tooltip_; std::string tooltip_;
int size_; int size_;
int interval_; std::chrono::milliseconds interval_;
util::command::res output_; util::command::res output_;
util::SleeperThread thread_; util::SleeperThread thread_;
+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;
+28 -24
View File
@@ -9,6 +9,7 @@
#include <sys/epoll.h> #include <sys/epoll.h>
#include <optional> #include <optional>
#include <vector>
#include "ALabel.hpp" #include "ALabel.hpp"
#include "util/sleeper_thread.hpp" #include "util/sleeper_thread.hpp"
@@ -27,8 +28,8 @@ class Network : public ALabel {
auto update() -> void override; auto update() -> void override;
private: private:
static const uint8_t MAX_RETRY = 5; static const uint8_t MAX_RETRY{5};
static const uint8_t EPOLL_MAX = 200; static const uint8_t EPOLL_MAX{200};
static int handleEvents(struct nl_msg*, void*); static int handleEvents(struct nl_msg*, void*);
static int handleEventsDone(struct nl_msg*, void*); static int handleEventsDone(struct nl_msg*, void*);
@@ -44,44 +45,47 @@ class Network : public ALabel {
void parseFreq(struct nlattr**); void parseFreq(struct nlattr**);
void parseBssid(struct nlattr**); void parseBssid(struct nlattr**);
bool associatedOrJoined(struct nlattr**); bool associatedOrJoined(struct nlattr**);
bool checkInterface(std::string name); bool matchInterface(const std::string& ifname, const std::vector<std::string>& altnames,
std::string& matched) const;
auto getInfo() -> void; auto getInfo() -> void;
const std::string getNetworkState() const; const std::string getNetworkState() const;
void clearIface(); void clearIface();
bool wildcardMatch(const std::string& pattern, const std::string& text) const;
std::optional<std::pair<unsigned long long, unsigned long long>> readBandwidthUsage(); std::optional<std::pair<unsigned long long, unsigned long long>> readBandwidthUsage();
int ifid_; int ifid_{-1};
ip_addr_pref addr_pref_; ip_addr_pref addr_pref_{ip_addr_pref::IPV4};
struct sockaddr_nl nladdr_ = {0}; struct sockaddr_nl nladdr_{0};
struct nl_sock* sock_ = nullptr; struct nl_sock* sock_{nullptr};
struct nl_sock* ev_sock_ = nullptr; struct nl_sock* ev_sock_{nullptr};
int efd_; int efd_{-1};
int ev_fd_; int ev_fd_{-1};
int nl80211_id_; int nl80211_id_{-1};
std::mutex mutex_; std::mutex mutex_;
bool want_route_dump_; bool want_route_dump_{false};
bool want_link_dump_; bool want_link_dump_{false};
bool want_addr_dump_; bool want_addr_dump_{false};
bool dump_in_progress_; bool dump_in_progress_{false};
bool is_p2p_; bool is_p2p_{false};
unsigned long long bandwidth_down_total_; unsigned long long bandwidth_down_total_{0};
unsigned long long bandwidth_up_total_; 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_;
std::string bssid_; std::string bssid_;
bool carrier_; bool carrier_{false};
std::string ifname_; std::string ifname_;
std::string ipaddr_; std::string ipaddr_;
std::string ipaddr6_; std::string ipaddr6_;
std::string gwaddr_; std::string gwaddr_;
std::string netmask_; std::string netmask_;
std::string netmask6_; std::string netmask6_;
int cidr_; int cidr_{0};
int cidr6_; int cidr6_{0};
int32_t signal_strength_dbm_; int32_t signal_strength_dbm_;
uint8_t signal_strength_; uint8_t signal_strength_;
std::string signal_strength_app_; std::string signal_strength_app_;
@@ -90,9 +94,9 @@ class Network : public ALabel {
util::SleeperThread thread_; util::SleeperThread thread_;
util::SleeperThread thread_timer_; util::SleeperThread thread_timer_;
#ifdef WANT_RFKILL #ifdef WANT_RFKILL
util::Rfkill rfkill_; util::Rfkill rfkill_{RFKILL_TYPE_WLAN};
#endif #endif
float frequency_; float frequency_{0};
}; };
} // namespace waybar::modules } // namespace waybar::modules
+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);
+5 -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,13 +26,14 @@ 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_;
std::string last_short_name_;
}; };
} // namespace waybar::modules::niri } // namespace waybar::modules::niri
+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
+12 -11
View File
@@ -10,24 +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_;
struct wl_output *output_; // stores the output this module belongs to std::string name_;
struct wl_output *focused_output_; // stores the currently focused output struct wl_output* output_; // stores the output this module belongs to
struct zriver_output_status_v1 *output_status_; struct wl_output* focused_output_; // stores the currently focused output
struct zriver_seat_status_v1 *seat_status_; struct zriver_output_status_v1* output_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 */
+9 -8
View File
@@ -13,26 +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_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
+23 -3
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,8 +26,12 @@ 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&,
~Item() = default; const std::function<void(Item&)>&, const std::function<void(Item&)>&,
const std::function<void()>&);
~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
View File
@@ -19,6 +19,7 @@ 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;
Gtk::Box box_; Gtk::Box box_;
+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;
+7
View File
@@ -22,6 +22,8 @@ class Wireplumber : public ALabel {
void activatePlugins(); void activatePlugins();
static void updateVolume(waybar::modules::Wireplumber* self, uint32_t id); static void updateVolume(waybar::modules::Wireplumber* self, uint32_t id);
static void updateNodeName(waybar::modules::Wireplumber* self, uint32_t id); static void updateNodeName(waybar::modules::Wireplumber* self, uint32_t id);
static void updateSourceVolume(waybar::modules::Wireplumber* self, uint32_t id);
static void updateSourceName(waybar::modules::Wireplumber* self, uint32_t id); // NEW
static void onPluginActivated(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self); static void onPluginActivated(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
static void onDefaultNodesApiLoaded(WpObject* p, GAsyncResult* res, static void onDefaultNodesApiLoaded(WpObject* p, GAsyncResult* res,
waybar::modules::Wireplumber* self); waybar::modules::Wireplumber* self);
@@ -46,7 +48,12 @@ class Wireplumber : public ALabel {
double min_step_; double min_step_;
uint32_t node_id_{0}; uint32_t node_id_{0};
std::string node_name_; std::string node_name_;
std::string source_name_;
gchar* type_; gchar* type_;
uint32_t source_node_id_;
bool source_muted_;
double source_volume_;
gchar* default_source_name_;
}; };
} // namespace waybar::modules } // namespace waybar::modules
+37 -39
View File
@@ -19,6 +19,7 @@
#include "bar.hpp" #include "bar.hpp"
#include "client.hpp" #include "client.hpp"
#include "giomm/desktopappinfo.h" #include "giomm/desktopappinfo.h"
#include "util/icon_loader.hpp"
#include "util/json.hpp" #include "util/json.hpp"
#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h" #include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
@@ -32,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:
@@ -52,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_;
@@ -88,10 +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 set_app_info_from_app_id_list(const std::string &app_id_list);
bool image_load_icon(Gtk::Image &image, const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
void hide_if_ignored(); void hide_if_ignored();
public: public:
@@ -107,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();
@@ -144,43 +142,43 @@ 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_;
std::vector<Glib::RefPtr<Gtk::IconTheme>> icon_themes_; IconLoader icon_loader_;
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 std::vector<Glib::RefPtr<Gtk::IconTheme>> &icon_themes() 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 */
-172
View File
@@ -1,172 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <gtkmm/button.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>
#include <functional>
#include <map>
#include <memory>
#include <vector>
#include "AModule.hpp"
#include "bar.hpp"
#include "ext-workspace-unstable-v1-client-protocol.h"
namespace waybar::modules::wlr {
class WorkspaceManager;
class WorkspaceGroup;
class Workspace {
public:
Workspace(const waybar::Bar &bar, const Json::Value &config, WorkspaceGroup &workspace_group,
zext_workspace_handle_v1 *workspace, uint32_t id, std::string name);
~Workspace();
auto update() -> void;
auto id() const -> uint32_t { return id_; }
auto is_active() const -> bool { return state_ & static_cast<uint32_t>(State::ACTIVE); }
auto is_urgent() const -> bool { return state_ & static_cast<uint32_t>(State::URGENT); }
auto is_hidden() const -> bool { return state_ & static_cast<uint32_t>(State::HIDDEN); }
auto is_empty() const -> bool { return state_ & static_cast<uint32_t>(State::EMPTY); }
auto is_persistent() const -> bool { return persistent_; }
// wlr stuff
auto handle_name(const std::string &name) -> void;
auto handle_coordinates(const std::vector<uint32_t> &coordinates) -> void;
auto handle_state(const std::vector<uint32_t> &state) -> void;
auto handle_remove() -> void;
auto make_persistent() -> void;
auto handle_duplicate() -> void;
auto handle_done() -> void;
auto handle_clicked(GdkEventButton *bt) -> bool;
auto show() -> void;
auto hide() -> void;
auto get_button_ref() -> Gtk::Button & { return button_; }
auto get_name() -> std::string & { return name_; }
auto get_coords() -> std::vector<uint32_t> & { return coordinates_; }
enum class State {
ACTIVE = (1 << 0),
URGENT = (1 << 1),
HIDDEN = (1 << 2),
EMPTY = (1 << 3),
};
private:
auto get_icon() -> std::string;
const Bar &bar_;
const Json::Value &config_;
WorkspaceGroup &workspace_group_;
// wlr stuff
zext_workspace_handle_v1 *workspace_handle_;
uint32_t state_ = 0;
uint32_t id_;
std::string name_;
std::vector<uint32_t> coordinates_;
static std::map<std::string, std::string> icons_map_;
std::string format_;
bool with_icon_ = false;
bool persistent_ = false;
Gtk::Button button_;
Gtk::Box content_;
Gtk::Label label_;
};
class WorkspaceGroup {
public:
WorkspaceGroup(const waybar::Bar &bar, Gtk::Box &box, const Json::Value &config,
WorkspaceManager &manager, zext_workspace_group_handle_v1 *workspace_group_handle,
uint32_t id);
~WorkspaceGroup();
auto update() -> void;
auto id() const -> uint32_t { return id_; }
auto is_visible() const -> bool;
auto remove_workspace(uint32_t id_) -> void;
auto active_only() const -> bool;
auto creation_delayed() const -> bool;
auto workspaces() -> std::vector<std::unique_ptr<Workspace>> & { return workspaces_; }
auto persistent_workspaces() -> std::vector<std::string> & { return persistent_workspaces_; }
auto sort_workspaces() -> void;
auto set_need_to_sort() -> void { need_to_sort = true; }
auto add_button(Gtk::Button &button) -> void;
auto remove_button(Gtk::Button &button) -> void;
auto fill_persistent_workspaces() -> void;
auto create_persistent_workspaces() -> void;
// wlr stuff
auto handle_workspace_create(zext_workspace_handle_v1 *workspace_handle) -> void;
auto handle_remove() -> void;
auto handle_output_enter(wl_output *output) -> void;
auto handle_output_leave() -> void;
auto handle_done() -> void;
auto commit() -> void;
private:
static uint32_t workspace_global_id;
const waybar::Bar &bar_;
Gtk::Box &box_;
const Json::Value &config_;
WorkspaceManager &workspace_manager_;
// wlr stuff
zext_workspace_group_handle_v1 *workspace_group_handle_;
wl_output *output_ = nullptr;
uint32_t id_;
std::vector<std::unique_ptr<Workspace>> workspaces_;
bool need_to_sort = false;
std::vector<std::string> persistent_workspaces_;
bool persistent_created_ = false;
};
class WorkspaceManager : public AModule {
public:
WorkspaceManager(const std::string &id, const waybar::Bar &bar, const Json::Value &config);
~WorkspaceManager() override;
auto update() -> void override;
auto all_outputs() const -> bool { return all_outputs_; }
auto active_only() const -> bool { return active_only_; }
auto workspace_comparator() const
-> std::function<bool(std::unique_ptr<Workspace> &, std::unique_ptr<Workspace> &)>;
auto creation_delayed() const -> bool { return creation_delayed_; }
auto sort_workspaces() -> void;
auto remove_workspace_group(uint32_t id_) -> void;
// wlr stuff
auto register_manager(wl_registry *registry, uint32_t name, uint32_t version) -> void;
auto handle_workspace_group_create(zext_workspace_group_handle_v1 *workspace_group_handle)
-> void;
auto handle_done() -> void;
auto handle_finished() -> void;
auto commit() -> void;
private:
const waybar::Bar &bar_;
Gtk::Box box_;
std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
// wlr stuff
zext_workspace_manager_v1 *workspace_manager_ = nullptr;
static uint32_t group_global_id;
bool sort_by_name_ = true;
bool sort_by_coordinates_ = true;
bool sort_by_number_ = false;
bool all_outputs_ = false;
bool active_only_ = false;
bool creation_delayed_ = false;
};
} // namespace waybar::modules::wlr
@@ -1,10 +0,0 @@
#include "ext-workspace-unstable-v1-client-protocol.h"
namespace waybar::modules::wlr {
void add_registry_listener(void *data);
void add_workspace_listener(zext_workspace_handle_v1 *workspace_handle, void *data);
void add_workspace_group_listener(zext_workspace_group_handle_v1 *workspace_group_handle,
void *data);
zext_workspace_manager_v1 *workspace_manager_bind(wl_registry *registry, uint32_t name,
uint32_t version, void *data);
} // namespace waybar::modules::wlr
+20
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>
@@ -22,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()) {
@@ -36,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();
@@ -55,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();
@@ -67,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);
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <gdkmm/general.h>
#include <gio/gdesktopappinfo.h>
#include <giomm/desktopappinfo.h>
#include <glibmm/fileutils.h>
#include <gtkmm/image.h>
#include <spdlog/spdlog.h>
#include <string>
#include <vector>
#include "util/gtk_icon.hpp"
class IconLoader {
private:
std::vector<Glib::RefPtr<Gtk::IconTheme>> custom_icon_themes_;
Glib::RefPtr<Gtk::IconTheme> default_icon_theme_ = Gtk::IconTheme::get_default();
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_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 std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
const std::string& app_id);
static bool image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
public:
void add_custom_icon_theme(const std::string& theme_name);
bool image_load_icon(Gtk::Image& image, Glib::RefPtr<Gio::DesktopAppInfo> app_info,
int size) const;
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_from_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");
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include <json/value.h>
#include <cstdint>
namespace waybar::util {
enum class KillSignalAction : std::uint8_t {
TOGGLE,
RELOAD,
SHOW,
HIDE,
NOOP,
};
const std::map<std::string, KillSignalAction> userKillSignalActions = {
{"TOGGLE", KillSignalAction::TOGGLE},
{"RELOAD", KillSignalAction::RELOAD},
{"SHOW", KillSignalAction::SHOW},
{"HIDE", KillSignalAction::HIDE},
{"NOOP", KillSignalAction::NOOP}};
const KillSignalAction SIGNALACTION_DEFAULT_SIGUSR1 = KillSignalAction::TOGGLE;
const KillSignalAction SIGNALACTION_DEFAULT_SIGUSR2 = KillSignalAction::RELOAD;
}; // namespace waybar::util
+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
+3 -1
View File
@@ -5,6 +5,8 @@
#include <sigc++/signal.h> #include <sigc++/signal.h>
#include <sigc++/trackable.h> #include <sigc++/trackable.h>
#include <atomic>
namespace waybar::util { namespace waybar::util {
class Rfkill : public sigc::trackable { class Rfkill : public sigc::trackable {
@@ -17,7 +19,7 @@ class Rfkill : public sigc::trackable {
private: private:
enum rfkill_type rfkill_type_; enum rfkill_type rfkill_type_;
bool state_ = false; std::atomic_bool state_ = false;
int fd_ = -1; int fd_ = -1;
bool on_event(Glib::IOCondition cond); bool on_event(Glib::IOCondition cond);
+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
+23
View File
@@ -23,3 +23,26 @@ inline std::string capitalize(const std::string& str) {
[](unsigned char c) { return std::toupper(c); }); [](unsigned char c) { return std::toupper(c); });
return result; return result;
} }
inline std::string toLower(const std::string& str) {
std::string result = str;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::tolower(c); });
return result;
}
inline std::vector<std::string> split(std::string_view s, std::string_view delimiter,
int max_splits = -1) {
std::vector<std::string> result;
size_t pos = 0;
size_t next_pos = 0;
while ((next_pos = s.find(delimiter, pos)) != std::string::npos) {
result.push_back(std::string(s.substr(pos, next_pos - pos)));
pos = next_pos + delimiter.size();
if (max_splits > 0 && result.size() == static_cast<size_t>(max_splits)) {
break;
}
}
result.push_back(std::string(s.substr(pos)));
return result;
}
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include <libudev.h>
namespace waybar::util {
struct UdevDeleter {
void operator()(udev* ptr) const { udev_unref(ptr); }
};
struct UdevDeviceDeleter {
void operator()(udev_device* ptr) const { udev_device_unref(ptr); }
};
struct UdevEnumerateDeleter {
void operator()(udev_enumerate* ptr) const { udev_enumerate_unref(ptr); }
};
struct UdevMonitorDeleter {
void operator()(udev_monitor* ptr) const { udev_monitor_unref(ptr); }
};
} // 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

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