conflict
This commit is contained in:
12
.github/workflows/clang-format.yml
vendored
12
.github/workflows/clang-format.yml
vendored
@@ -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
|
|
||||||
|
|||||||
2
.github/workflows/clang-tidy.yml.bak
vendored
2
.github/workflows/clang-tidy.yml.bak
vendored
@@ -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
|
||||||
|
|||||||
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@@ -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
|
||||||
|
|||||||
4
.github/workflows/freebsd.yml
vendored
4
.github/workflows/freebsd.yml
vendored
@@ -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"
|
||||||
|
|||||||
2
.github/workflows/linux.yml
vendored
2
.github/workflows/linux.yml
vendored
@@ -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
|
||||||
|
|||||||
21
.github/workflows/nix-tests.yml
vendored
21
.github/workflows/nix-tests.yml
vendored
@@ -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
|
||||||
|
|||||||
10
.github/workflows/nix-update-flake-lock.yml
vendored
10
.github/workflows/nix-update-flake-lock.yml
vendored
@@ -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
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -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,4 @@ result
|
|||||||
result-*
|
result-*
|
||||||
|
|
||||||
.ccls-cache
|
.ccls-cache
|
||||||
|
_codeql_detected_source_root
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ sudo apt install \
|
|||||||
On Arch, you can use this command:
|
On Arch, you can use this command:
|
||||||
|
|
||||||
```
|
```
|
||||||
pacman -S \
|
pacman -S --asdeps \
|
||||||
gtkmm3 \
|
gtkmm3 \
|
||||||
jsoncpp \
|
jsoncpp \
|
||||||
libsigc++ \
|
libsigc++ \
|
||||||
@@ -151,6 +151,10 @@ Contributions welcome!<br>
|
|||||||
Have fun :)<br>
|
Have fun :)<br>
|
||||||
The style guidelines are [Google's](https://google.github.io/styleguide/cppguide.html)
|
The style guidelines are [Google's](https://google.github.io/styleguide/cppguide.html)
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> Distributions of Waybar are only released on the [official GitHub page](https://github.com/Alexays/Waybar).<br/>
|
||||||
|
> Waybar does **not** have an official website. Do not trust any sites that claim to be official.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Waybar is licensed under the MIT license. [See LICENSE for more information](https://github.com/Alexays/Waybar/blob/master/LICENSE).
|
Waybar is licensed under the MIT license. [See LICENSE for more information](https://github.com/Alexays/Waybar/blob/master/LICENSE).
|
||||||
|
|||||||
1
_codeql_detected_source_root
Symbolic link
1
_codeql_detected_source_root
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
.
|
||||||
12
flake.lock
generated
12
flake.lock
generated
@@ -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": 1760878510,
|
"lastModified": 1769461804,
|
||||||
"narHash": "sha256-K5Osef2qexezUfs0alLvZ7nQFTGS9DL2oTVsIXsqLgs=",
|
"narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "5e2a59a5b1a82f89f2c7e598302a9cacebb72a67",
|
"rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ namespace waybar {
|
|||||||
|
|
||||||
class ALabel : public AModule {
|
class ALabel : public AModule {
|
||||||
public:
|
public:
|
||||||
ALabel(const Json::Value &, const std::string &, const std::string &, const std::string &format,
|
ALabel(const Json::Value&, const std::string&, const std::string&, const std::string& format,
|
||||||
uint16_t interval = 0, bool ellipsize = false, bool enable_click = false,
|
uint16_t interval = 0, bool ellipsize = false, bool enable_click = false,
|
||||||
bool enable_scroll = false);
|
bool enable_scroll = false);
|
||||||
virtual ~ALabel() = default;
|
virtual ~ALabel() = default;
|
||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0);
|
virtual std::string getIcon(uint16_t, const std::string& alt = "", uint16_t max = 0);
|
||||||
virtual std::string getIcon(uint16_t, const std::vector<std::string> &alts, uint16_t max = 0);
|
virtual std::string getIcon(uint16_t, const std::vector<std::string>& alts, uint16_t max = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Gtk::Label label_;
|
Gtk::Label label_;
|
||||||
@@ -25,12 +25,12 @@ class ALabel : public AModule {
|
|||||||
bool alt_ = false;
|
bool alt_ = false;
|
||||||
std::string default_format_;
|
std::string default_format_;
|
||||||
|
|
||||||
bool handleToggle(GdkEventButton *const &e) override;
|
bool 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar
|
} // namespace waybar
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ 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;
|
||||||
@@ -28,30 +28,30 @@ class AModule : public IModule {
|
|||||||
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_;
|
GObject* menu_;
|
||||||
|
|
||||||
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_;
|
||||||
|
|||||||
@@ -62,11 +62,11 @@ class Bar : public sigc::trackable {
|
|||||||
static const std::string MODE_DEFAULT;
|
static const std::string MODE_DEFAULT;
|
||||||
static const std::string MODE_INVISIBLE;
|
static const std::string MODE_INVISIBLE;
|
||||||
|
|
||||||
Bar(struct waybar_output *w_output, const Json::Value &);
|
Bar(struct waybar_output* w_output, const Json::Value&);
|
||||||
Bar(const Bar &) = delete;
|
Bar(const Bar&) = delete;
|
||||||
~Bar();
|
~Bar();
|
||||||
|
|
||||||
void setMode(const std::string &mode);
|
void setMode(const std::string& mode);
|
||||||
void setVisible(bool value);
|
void setVisible(bool value);
|
||||||
void toggle();
|
void toggle();
|
||||||
void show();
|
void show();
|
||||||
@@ -75,9 +75,9 @@ class Bar : public sigc::trackable {
|
|||||||
util::KillSignalAction getOnSigusr1Action();
|
util::KillSignalAction getOnSigusr1Action();
|
||||||
util::KillSignalAction getOnSigusr2Action();
|
util::KillSignalAction getOnSigusr2Action();
|
||||||
|
|
||||||
struct waybar_output *output;
|
struct waybar_output* output;
|
||||||
Json::Value config;
|
Json::Value config;
|
||||||
struct wl_surface *surface;
|
struct wl_surface* surface;
|
||||||
bool visible = true;
|
bool visible = true;
|
||||||
Gtk::Window window;
|
Gtk::Window window;
|
||||||
Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL;
|
Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL;
|
||||||
@@ -91,15 +91,15 @@ 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 onConfigure(GdkEventConfigure* ev);
|
||||||
void configureGlobalOffset(int width, int height);
|
void configureGlobalOffset(int width, int height);
|
||||||
void onOutputGeometryChanged();
|
void onOutputGeometryChanged();
|
||||||
|
|
||||||
|
|||||||
@@ -17,35 +17,35 @@ 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 *);
|
static void handleOutputName(void*, struct zxdg_output_v1*, const char*);
|
||||||
static void handleOutputDescription(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 +56,8 @@ 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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar
|
} // namespace waybar
|
||||||
|
|||||||
@@ -14,29 +14,29 @@ namespace waybar {
|
|||||||
class Config {
|
class Config {
|
||||||
public:
|
public:
|
||||||
static const std::vector<std::string> CONFIG_DIRS;
|
static const std::vector<std::string> CONFIG_DIRS;
|
||||||
static const char *CONFIG_PATH_ENV;
|
static const char* CONFIG_PATH_ENV;
|
||||||
|
|
||||||
/* Try to find any of provided names in the supported set of config directories */
|
/* Try to find any of provided names in the supported set of config directories */
|
||||||
static std::optional<std::string> findConfigPath(
|
static std::optional<std::string> findConfigPath(
|
||||||
const std::vector<std::string> &names, const std::vector<std::string> &dirs = CONFIG_DIRS);
|
const std::vector<std::string>& names, const std::vector<std::string>& dirs = CONFIG_DIRS);
|
||||||
|
|
||||||
static std::vector<std::string> tryExpandPath(const std::string &base,
|
static std::vector<std::string> tryExpandPath(const std::string& base,
|
||||||
const std::string &filename);
|
const std::string& filename);
|
||||||
|
|
||||||
Config() = default;
|
Config() = default;
|
||||||
|
|
||||||
void load(const std::string &config);
|
void load(const std::string& config);
|
||||||
|
|
||||||
Json::Value &getConfig() { return config_; }
|
Json::Value& getConfig() { return config_; }
|
||||||
|
|
||||||
std::vector<Json::Value> getOutputConfigs(const std::string &name, const std::string &identifier);
|
std::vector<Json::Value> getOutputConfigs(const std::string& name, const std::string& identifier);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupConfig(Json::Value &dst, const std::string &config_file, int depth);
|
void setupConfig(Json::Value& dst, const std::string& config_file, int depth);
|
||||||
void resolveConfigIncludes(Json::Value &config, int depth);
|
void resolveConfigIncludes(Json::Value& config, int depth);
|
||||||
void mergeConfig(Json::Value &a_config_, Json::Value &b_config_);
|
void mergeConfig(Json::Value& a_config_, Json::Value& b_config_);
|
||||||
static std::vector<std::string> findIncludePath(
|
static std::vector<std::string> findIncludePath(
|
||||||
const std::string &name, const std::vector<std::string> &dirs = CONFIG_DIRS);
|
const std::string& name, const std::vector<std::string>& dirs = CONFIG_DIRS);
|
||||||
|
|
||||||
std::string config_file_;
|
std::string config_file_;
|
||||||
|
|
||||||
|
|||||||
@@ -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,9 @@ 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;
|
||||||
void show_group();
|
void show_group();
|
||||||
void hide_group();
|
void hide_group();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|
||||||
@@ -37,15 +39,17 @@ class Battery : public ALabel {
|
|||||||
void setBarClass(std::string&);
|
void setBarClass(std::string&);
|
||||||
void processEvents(std::string& state, std::string& status, uint8_t capacity);
|
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_;
|
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_;
|
||||||
|
|||||||
43
include/modules/cava/cavaGLSL.hpp
Normal file
43
include/modules/cava/cavaGLSL.hpp
Normal 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
|
||||||
@@ -9,20 +9,20 @@ class Cava final : public ALabel, public sigc::trackable {
|
|||||||
public:
|
public:
|
||||||
Cava(const std::string&, const Json::Value&);
|
Cava(const std::string&, const Json::Value&);
|
||||||
~Cava() = default;
|
~Cava() = default;
|
||||||
auto onUpdate(const std::string& input) -> void;
|
|
||||||
auto onSilence() -> void;
|
|
||||||
auto doAction(const std::string& name) -> void override;
|
auto doAction(const std::string& name) -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<CavaBackend> backend_;
|
std::shared_ptr<CavaBackend> backend_;
|
||||||
// Text to display
|
// Text to display
|
||||||
std::string label_text_{""};
|
Glib::ustring label_text_{""};
|
||||||
|
bool silence_{false};
|
||||||
bool hide_on_silence_{false};
|
bool hide_on_silence_{false};
|
||||||
std::string format_silent_{""};
|
std::string format_silent_{""};
|
||||||
int ascii_range_{0};
|
int ascii_range_{0};
|
||||||
bool silence_{false};
|
|
||||||
// Cava method
|
// Cava method
|
||||||
void pause_resume();
|
void pause_resume();
|
||||||
|
auto onUpdate(const std::string& input) -> void;
|
||||||
|
auto onSilence() -> void;
|
||||||
// ModuleActionMap
|
// ModuleActionMap
|
||||||
static inline std::map<const std::string, void (waybar::modules::cava::Cava::* const)()>
|
static inline std::map<const std::string, void (waybar::modules::cava::Cava::* const)()>
|
||||||
actionMap_{{"mode", &waybar::modules::cava::Cava::pause_resume}};
|
actionMap_{{"mode", &waybar::modules::cava::Cava::pause_resume}};
|
||||||
@@ -32,16 +32,22 @@ class CavaBackend final {
|
|||||||
int getAsciiRange();
|
int getAsciiRange();
|
||||||
void doPauseResume();
|
void doPauseResume();
|
||||||
void Update();
|
void Update();
|
||||||
|
const struct ::cava::config_params* getPrm();
|
||||||
|
std::chrono::milliseconds getFrameTimeMilsec();
|
||||||
|
|
||||||
// Signal accessor
|
// Signal accessor
|
||||||
using type_signal_update = sigc::signal<void(const std::string&)>;
|
using type_signal_update = sigc::signal<void(const std::string&)>;
|
||||||
type_signal_update signal_update();
|
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()>;
|
using type_signal_silence = sigc::signal<void()>;
|
||||||
type_signal_silence signal_silence();
|
type_signal_silence signal_silence();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CavaBackend(const Json::Value& config);
|
CavaBackend(const Json::Value& config);
|
||||||
util::SleeperThread thread_;
|
|
||||||
util::SleeperThread read_thread_;
|
util::SleeperThread read_thread_;
|
||||||
|
util::SleeperThread out_thread_;
|
||||||
|
|
||||||
// Cava API to read audio source
|
// Cava API to read audio source
|
||||||
::cava::ptr input_source_{NULL};
|
::cava::ptr input_source_{NULL};
|
||||||
|
|
||||||
@@ -55,6 +61,7 @@ class CavaBackend final {
|
|||||||
// Delay to handle audio source
|
// Delay to handle audio source
|
||||||
std::chrono::milliseconds frame_time_milsec_{1s};
|
std::chrono::milliseconds frame_time_milsec_{1s};
|
||||||
|
|
||||||
|
const Json::Value& config_;
|
||||||
int re_paint_{0};
|
int re_paint_{0};
|
||||||
bool silence_{false};
|
bool silence_{false};
|
||||||
bool silence_prev_{false};
|
bool silence_prev_{false};
|
||||||
@@ -66,9 +73,12 @@ class CavaBackend final {
|
|||||||
void execute();
|
void execute();
|
||||||
bool isSilence();
|
bool isSilence();
|
||||||
void doUpdate(bool force = false);
|
void doUpdate(bool force = false);
|
||||||
|
void loadConfig();
|
||||||
|
void freeBackend();
|
||||||
|
|
||||||
// Signal
|
// Signal
|
||||||
type_signal_update m_signal_update_;
|
type_signal_update m_signal_update_;
|
||||||
|
type_signal_audio_raw_update m_signal_audio_raw_;
|
||||||
type_signal_silence m_signal_silence_;
|
type_signal_silence m_signal_silence_;
|
||||||
};
|
};
|
||||||
} // namespace waybar::modules::cava
|
} // namespace waybar::modules::cava
|
||||||
|
|||||||
27
include/modules/cava/cava_frontend.hpp
Normal file
27
include/modules/cava/cava_frontend.hpp
Normal 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
|
||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -20,16 +20,16 @@ class Workspace;
|
|||||||
|
|
||||||
class WorkspaceManager final : public AModule {
|
class WorkspaceManager final : public AModule {
|
||||||
public:
|
public:
|
||||||
WorkspaceManager(const std::string &id, const waybar::Bar &bar, const Json::Value &config);
|
WorkspaceManager(const std::string& id, const waybar::Bar& bar, const Json::Value& config);
|
||||||
~WorkspaceManager() override;
|
~WorkspaceManager() override;
|
||||||
void register_manager(wl_registry *registry, uint32_t name, uint32_t version);
|
void register_manager(wl_registry* registry, uint32_t name, uint32_t version);
|
||||||
void remove_workspace_group(uint32_t id);
|
void remove_workspace_group(uint32_t id);
|
||||||
void remove_workspace(uint32_t id);
|
void remove_workspace(uint32_t id);
|
||||||
void set_needs_sorting() { needs_sorting_ = true; }
|
void set_needs_sorting() { needs_sorting_ = true; }
|
||||||
|
|
||||||
// wl events
|
// wl events
|
||||||
void handle_workspace_group(ext_workspace_group_handle_v1 *handle);
|
void handle_workspace_group(ext_workspace_group_handle_v1* handle);
|
||||||
void handle_workspace(ext_workspace_handle_v1 *handle);
|
void handle_workspace(ext_workspace_handle_v1* handle);
|
||||||
void handle_done();
|
void handle_done();
|
||||||
void handle_finished();
|
void handle_finished();
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ class WorkspaceManager final : public AModule {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void update() override;
|
void update() override;
|
||||||
bool has_button(const Gtk::Button *button);
|
bool has_button(const Gtk::Button* button);
|
||||||
void sort_workspaces();
|
void sort_workspaces();
|
||||||
void clear_buttons();
|
void clear_buttons();
|
||||||
void update_buttons();
|
void update_buttons();
|
||||||
@@ -52,10 +52,10 @@ class WorkspaceManager final : public AModule {
|
|||||||
bool sort_by_coordinates_ = false;
|
bool sort_by_coordinates_ = false;
|
||||||
bool all_outputs_ = false;
|
bool all_outputs_ = false;
|
||||||
|
|
||||||
const waybar::Bar &bar_;
|
const waybar::Bar& bar_;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
|
|
||||||
ext_workspace_manager_v1 *ext_manager_ = nullptr;
|
ext_workspace_manager_v1* ext_manager_ = nullptr;
|
||||||
std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
|
std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
|
||||||
std::vector<std::unique_ptr<Workspace>> workspaces_;
|
std::vector<std::unique_ptr<Workspace>> workspaces_;
|
||||||
|
|
||||||
@@ -64,60 +64,60 @@ class WorkspaceManager final : public AModule {
|
|||||||
|
|
||||||
class WorkspaceGroup {
|
class WorkspaceGroup {
|
||||||
public:
|
public:
|
||||||
WorkspaceGroup(WorkspaceManager &manager, ext_workspace_group_handle_v1 *handle, uint32_t id);
|
WorkspaceGroup(WorkspaceManager& manager, ext_workspace_group_handle_v1* handle, uint32_t id);
|
||||||
~WorkspaceGroup();
|
~WorkspaceGroup();
|
||||||
|
|
||||||
u_int32_t id() const { return id_; }
|
u_int32_t id() const { return id_; }
|
||||||
bool has_output(const wl_output *output);
|
bool has_output(const wl_output* output);
|
||||||
bool has_workspace(const ext_workspace_handle_v1 *workspace);
|
bool has_workspace(const ext_workspace_handle_v1* workspace);
|
||||||
|
|
||||||
// wl events
|
// wl events
|
||||||
void handle_capabilities(uint32_t capabilities);
|
void handle_capabilities(uint32_t capabilities);
|
||||||
void handle_output_enter(wl_output *output);
|
void handle_output_enter(wl_output* output);
|
||||||
void handle_output_leave(wl_output *output);
|
void handle_output_leave(wl_output* output);
|
||||||
void handle_workspace_enter(ext_workspace_handle_v1 *handle);
|
void handle_workspace_enter(ext_workspace_handle_v1* handle);
|
||||||
void handle_workspace_leave(ext_workspace_handle_v1 *handle);
|
void handle_workspace_leave(ext_workspace_handle_v1* handle);
|
||||||
void handle_removed();
|
void handle_removed();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WorkspaceManager &workspaces_manager_;
|
WorkspaceManager& workspaces_manager_;
|
||||||
ext_workspace_group_handle_v1 *ext_handle_;
|
ext_workspace_group_handle_v1* ext_handle_;
|
||||||
uint32_t id_;
|
uint32_t id_;
|
||||||
std::vector<wl_output *> outputs_;
|
std::vector<wl_output*> outputs_;
|
||||||
std::vector<ext_workspace_handle_v1 *> workspaces_;
|
std::vector<ext_workspace_handle_v1*> workspaces_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Workspace {
|
class Workspace {
|
||||||
public:
|
public:
|
||||||
Workspace(const Json::Value &config, WorkspaceManager &manager, ext_workspace_handle_v1 *handle,
|
Workspace(const Json::Value& config, WorkspaceManager& manager, ext_workspace_handle_v1* handle,
|
||||||
uint32_t id, const std::string &name);
|
uint32_t id, const std::string& name);
|
||||||
~Workspace();
|
~Workspace();
|
||||||
|
|
||||||
ext_workspace_handle_v1 *handle() const { return ext_handle_; }
|
ext_workspace_handle_v1* handle() const { return ext_handle_; }
|
||||||
u_int32_t id() const { return id_; }
|
u_int32_t id() const { return id_; }
|
||||||
std::string &workspace_id() { return workspace_id_; }
|
std::string& workspace_id() { return workspace_id_; }
|
||||||
std::string &name() { return name_; }
|
std::string& name() { return name_; }
|
||||||
std::vector<u_int32_t> &coordinates() { return coordinates_; }
|
std::vector<u_int32_t>& coordinates() { return coordinates_; }
|
||||||
Gtk::Button &button() { return button_; }
|
Gtk::Button& button() { return button_; }
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
// wl events
|
// wl events
|
||||||
void handle_id(const std::string &id);
|
void handle_id(const std::string& id);
|
||||||
void handle_name(const std::string &name);
|
void handle_name(const std::string& name);
|
||||||
void handle_coordinates(const std::vector<uint32_t> &coordinates);
|
void handle_coordinates(const std::vector<uint32_t>& coordinates);
|
||||||
void handle_state(uint32_t state);
|
void handle_state(uint32_t state);
|
||||||
void handle_capabilities(uint32_t capabilities);
|
void handle_capabilities(uint32_t capabilities);
|
||||||
void handle_removed();
|
void handle_removed();
|
||||||
|
|
||||||
// gdk events
|
// gdk events
|
||||||
bool handle_clicked(const GdkEventButton *button) const;
|
bool handle_clicked(const GdkEventButton* button) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool has_state(uint32_t state) const { return (state_ & state) == state; }
|
bool has_state(uint32_t state) const { return (state_ & state) == state; }
|
||||||
std::string icon();
|
std::string icon();
|
||||||
|
|
||||||
WorkspaceManager &workspace_manager_;
|
WorkspaceManager& workspace_manager_;
|
||||||
ext_workspace_handle_v1 *ext_handle_ = nullptr;
|
ext_workspace_handle_v1* ext_handle_ = nullptr;
|
||||||
uint32_t id_;
|
uint32_t id_;
|
||||||
uint32_t state_ = 0;
|
uint32_t state_ = 0;
|
||||||
std::string workspace_id_;
|
std::string workspace_id_;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#include "ext-workspace-v1-client-protocol.h"
|
#include "ext-workspace-v1-client-protocol.h"
|
||||||
|
|
||||||
namespace waybar::modules::ext {
|
namespace waybar::modules::ext {
|
||||||
void add_registry_listener(void *data);
|
void add_registry_listener(void* data);
|
||||||
void add_workspace_listener(ext_workspace_handle_v1 *workspace_handle, void *data);
|
void add_workspace_listener(ext_workspace_handle_v1* workspace_handle, void* data);
|
||||||
void add_workspace_group_listener(ext_workspace_group_handle_v1 *workspace_group_handle,
|
void add_workspace_group_listener(ext_workspace_group_handle_v1* workspace_group_handle,
|
||||||
void *data);
|
void* data);
|
||||||
ext_workspace_manager_v1 *workspace_manager_bind(wl_registry *registry, uint32_t name,
|
ext_workspace_manager_v1* workspace_manager_bind(wl_registry* registry, uint32_t name,
|
||||||
uint32_t version, void *data);
|
uint32_t version, void* data);
|
||||||
} // namespace waybar::modules::ext
|
} // namespace waybar::modules::ext
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
@@ -28,18 +28,18 @@ class Gamemode : public AModule {
|
|||||||
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 ¶meters);
|
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;
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
|
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
|
||||||
auto enableTaskbar() const -> bool { return m_enableTaskbar; }
|
auto enableTaskbar() const -> bool { return m_enableTaskbar; }
|
||||||
auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; }
|
auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; }
|
||||||
|
auto barScroll() const -> bool { return m_barScroll; }
|
||||||
|
|
||||||
auto getBarOutput() const -> std::string { return m_bar.output->name; }
|
auto getBarOutput() const -> std::string { return m_bar.output->name; }
|
||||||
auto formatBefore() const -> std::string { return m_formatBefore; }
|
auto formatBefore() const -> std::string { return m_formatBefore; }
|
||||||
@@ -122,6 +123,8 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
static std::pair<std::string, std::string> splitDoublePayload(std::string const& payload);
|
static std::pair<std::string, std::string> splitDoublePayload(std::string const& payload);
|
||||||
static std::tuple<std::string, std::string, std::string> splitTriplePayload(
|
static std::tuple<std::string, std::string, std::string> splitTriplePayload(
|
||||||
std::string const& payload);
|
std::string const& payload);
|
||||||
|
// scroll events
|
||||||
|
bool handleScroll(GdkEventScroll* e) override;
|
||||||
|
|
||||||
// Update methods
|
// Update methods
|
||||||
void doUpdate();
|
void doUpdate();
|
||||||
@@ -145,6 +148,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
bool m_specialVisibleOnly = false;
|
bool m_specialVisibleOnly = false;
|
||||||
bool m_persistentOnly = false;
|
bool m_persistentOnly = false;
|
||||||
bool m_moveToMonitor = false;
|
bool m_moveToMonitor = false;
|
||||||
|
bool m_barScroll = false;
|
||||||
Json::Value m_persistentWorkspaceConfig;
|
Json::Value m_persistentWorkspaceConfig;
|
||||||
|
|
||||||
// Map for windows stored in workspaces not present in the current bar.
|
// Map for windows stored in workspaces not present in the current bar.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ namespace waybar::modules::niri {
|
|||||||
|
|
||||||
class Language : public ALabel, public EventHandler {
|
class Language : public ALabel, public EventHandler {
|
||||||
public:
|
public:
|
||||||
Language(const std::string &, const Bar &, const Json::Value &);
|
Language(const std::string&, const Bar&, const Json::Value&);
|
||||||
~Language() override;
|
~Language() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateFromIPC();
|
void updateFromIPC();
|
||||||
void onEvent(const Json::Value &ev) override;
|
void onEvent(const Json::Value& ev) override;
|
||||||
void doUpdate();
|
void doUpdate();
|
||||||
|
|
||||||
struct Layout {
|
struct Layout {
|
||||||
@@ -26,10 +26,10 @@ class Language : public ALabel, public EventHandler {
|
|||||||
std::string short_description;
|
std::string short_description;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Layout getLayout(const std::string &fullName);
|
static Layout getLayout(const std::string& fullName);
|
||||||
|
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
const Bar &bar_;
|
const Bar& bar_;
|
||||||
|
|
||||||
std::vector<Layout> layouts_;
|
std::vector<Layout> layouts_;
|
||||||
unsigned current_idx_;
|
unsigned current_idx_;
|
||||||
|
|||||||
@@ -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_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -13,15 +13,15 @@ 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;
|
||||||
|
|||||||
@@ -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,25 +10,25 @@ namespace waybar::modules::river {
|
|||||||
|
|
||||||
class Layout : public waybar::ALabel {
|
class Layout : public waybar::ALabel {
|
||||||
public:
|
public:
|
||||||
Layout(const std::string &, const waybar::Bar &, const Json::Value &);
|
Layout(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
virtual ~Layout();
|
virtual ~Layout();
|
||||||
|
|
||||||
// Handlers for wayland events
|
// Handlers for wayland events
|
||||||
void handle_name(const char *name);
|
void handle_name(const char* name);
|
||||||
void handle_clear();
|
void handle_clear();
|
||||||
void handle_focused_output(struct wl_output *output);
|
void handle_focused_output(struct wl_output* output);
|
||||||
void handle_unfocused_output(struct wl_output *output);
|
void handle_unfocused_output(struct wl_output* output);
|
||||||
|
|
||||||
struct zriver_status_manager_v1 *status_manager_;
|
struct zriver_status_manager_v1* status_manager_;
|
||||||
struct wl_seat *seat_;
|
struct wl_seat* seat_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const waybar::Bar &bar_;
|
const waybar::Bar& bar_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
struct wl_output *output_; // stores the output this module belongs to
|
struct wl_output* output_; // stores the output this module belongs to
|
||||||
struct wl_output *focused_output_; // stores the currently focused output
|
struct wl_output* focused_output_; // stores the currently focused output
|
||||||
struct zriver_output_status_v1 *output_status_;
|
struct zriver_output_status_v1* output_status_;
|
||||||
struct zriver_seat_status_v1 *seat_status_;
|
struct zriver_seat_status_v1* seat_status_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace waybar::modules::river */
|
} /* namespace waybar::modules::river */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -13,27 +13,27 @@ namespace waybar::modules::river {
|
|||||||
|
|
||||||
class Tags : public waybar::AModule {
|
class Tags : public waybar::AModule {
|
||||||
public:
|
public:
|
||||||
Tags(const std::string &, const waybar::Bar &, const Json::Value &);
|
Tags(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
virtual ~Tags();
|
virtual ~Tags();
|
||||||
|
|
||||||
// Handlers for wayland events
|
// Handlers for wayland events
|
||||||
void handle_focused_tags(uint32_t tags);
|
void handle_focused_tags(uint32_t tags);
|
||||||
void handle_view_tags(struct wl_array *tags);
|
void handle_view_tags(struct wl_array* tags);
|
||||||
void handle_urgent_tags(uint32_t tags);
|
void handle_urgent_tags(uint32_t tags);
|
||||||
|
|
||||||
void handle_show();
|
void handle_show();
|
||||||
void handle_primary_clicked(uint32_t tag);
|
void handle_primary_clicked(uint32_t tag);
|
||||||
bool handle_button_press(GdkEventButton *event_button, uint32_t tag);
|
bool handle_button_press(GdkEventButton* event_button, uint32_t tag);
|
||||||
|
|
||||||
struct zriver_status_manager_v1 *status_manager_;
|
struct zriver_status_manager_v1* status_manager_;
|
||||||
struct zriver_control_v1 *control_;
|
struct zriver_control_v1* control_;
|
||||||
struct wl_seat *seat_;
|
struct wl_seat* seat_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const waybar::Bar &bar_;
|
const waybar::Bar& bar_;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
std::vector<Gtk::Button> buttons_;
|
std::vector<Gtk::Button> buttons_;
|
||||||
struct zriver_output_status_v1 *output_status_;
|
struct zriver_output_status_v1* output_status_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace waybar::modules::river */
|
} /* namespace waybar::modules::river */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "ipc.hpp"
|
#include "ipc.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
|
#include "util/SafeSignal.hpp"
|
||||||
|
|
||||||
namespace waybar::modules::sway {
|
namespace waybar::modules::sway {
|
||||||
|
|
||||||
@@ -27,21 +28,21 @@ 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_;
|
int fd_;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ 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();
|
||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
|
|
||||||
@@ -24,8 +24,8 @@ class SystemdFailedUnits : public ALabel {
|
|||||||
std::string last_status;
|
std::string last_status;
|
||||||
Glib::RefPtr<Gio::DBus::Proxy> system_proxy, user_proxy;
|
Glib::RefPtr<Gio::DBus::Proxy> system_proxy, user_proxy;
|
||||||
|
|
||||||
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 RequestFailedUnits();
|
void RequestFailedUnits();
|
||||||
void RequestSystemState();
|
void RequestSystemState();
|
||||||
void updateData();
|
void updateData();
|
||||||
|
|||||||
@@ -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 ¶meters);
|
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
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ class Taskbar;
|
|||||||
|
|
||||||
class Task {
|
class Task {
|
||||||
public:
|
public:
|
||||||
Task(const waybar::Bar &, const Json::Value &, Taskbar *,
|
Task(const waybar::Bar&, const Json::Value&, Taskbar*, struct zwlr_foreign_toplevel_handle_v1*,
|
||||||
struct zwlr_foreign_toplevel_handle_v1 *, struct wl_seat *);
|
struct wl_seat*);
|
||||||
~Task();
|
~Task();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -53,11 +53,11 @@ class Task {
|
|||||||
static uint32_t global_id;
|
static uint32_t global_id;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const waybar::Bar &bar_;
|
const waybar::Bar& bar_;
|
||||||
const Json::Value &config_;
|
const Json::Value& config_;
|
||||||
Taskbar *tbar_;
|
Taskbar* tbar_;
|
||||||
struct zwlr_foreign_toplevel_handle_v1 *handle_;
|
struct zwlr_foreign_toplevel_handle_v1* handle_;
|
||||||
struct wl_seat *seat_;
|
struct wl_seat* seat_;
|
||||||
|
|
||||||
uint32_t id_;
|
uint32_t id_;
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ class Task {
|
|||||||
std::string repr() const;
|
std::string repr() const;
|
||||||
std::string state_string(bool = false) const;
|
std::string state_string(bool = false) const;
|
||||||
void set_minimize_hint();
|
void set_minimize_hint();
|
||||||
void on_button_size_allocated(Gtk::Allocation &alloc);
|
void on_button_size_allocated(Gtk::Allocation& alloc);
|
||||||
void hide_if_ignored();
|
void hide_if_ignored();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -105,26 +105,26 @@ class Task {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/* Callbacks for the wlr protocol */
|
/* Callbacks for the wlr protocol */
|
||||||
void handle_title(const char *);
|
void handle_title(const char*);
|
||||||
void handle_app_id(const char *);
|
void handle_app_id(const char*);
|
||||||
void handle_output_enter(struct wl_output *);
|
void handle_output_enter(struct wl_output*);
|
||||||
void handle_output_leave(struct wl_output *);
|
void handle_output_leave(struct wl_output*);
|
||||||
void handle_state(struct wl_array *);
|
void handle_state(struct wl_array*);
|
||||||
void handle_done();
|
void handle_done();
|
||||||
void handle_closed();
|
void handle_closed();
|
||||||
|
|
||||||
/* Callbacks for Gtk events */
|
/* Callbacks for Gtk events */
|
||||||
bool handle_clicked(GdkEventButton *);
|
bool handle_clicked(GdkEventButton*);
|
||||||
bool handle_button_release(GdkEventButton *);
|
bool handle_button_release(GdkEventButton*);
|
||||||
bool handle_motion_notify(GdkEventMotion *);
|
bool handle_motion_notify(GdkEventMotion*);
|
||||||
void handle_drag_data_get(const Glib::RefPtr<Gdk::DragContext> &context,
|
void handle_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context,
|
||||||
Gtk::SelectionData &selection_data, guint info, guint time);
|
Gtk::SelectionData& selection_data, guint info, guint time);
|
||||||
void handle_drag_data_received(const Glib::RefPtr<Gdk::DragContext> &context, int x, int y,
|
void handle_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y,
|
||||||
Gtk::SelectionData selection_data, guint info, guint time);
|
Gtk::SelectionData selection_data, guint info, guint time);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool operator==(const Task &) const;
|
bool operator==(const Task&) const;
|
||||||
bool operator!=(const Task &) const;
|
bool operator!=(const Task&) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void update();
|
void update();
|
||||||
@@ -142,12 +142,12 @@ using TaskPtr = std::unique_ptr<Task>;
|
|||||||
|
|
||||||
class Taskbar : public waybar::AModule {
|
class Taskbar : public waybar::AModule {
|
||||||
public:
|
public:
|
||||||
Taskbar(const std::string &, const waybar::Bar &, const Json::Value &);
|
Taskbar(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
~Taskbar();
|
~Taskbar();
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const waybar::Bar &bar_;
|
const waybar::Bar& bar_;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
std::vector<TaskPtr> tasks_;
|
std::vector<TaskPtr> tasks_;
|
||||||
|
|
||||||
@@ -155,30 +155,30 @@ class Taskbar : public waybar::AModule {
|
|||||||
std::unordered_set<std::string> ignore_list_;
|
std::unordered_set<std::string> ignore_list_;
|
||||||
std::map<std::string, std::string> app_ids_replace_map_;
|
std::map<std::string, std::string> app_ids_replace_map_;
|
||||||
|
|
||||||
struct zwlr_foreign_toplevel_manager_v1 *manager_;
|
struct zwlr_foreign_toplevel_manager_v1* manager_;
|
||||||
struct wl_seat *seat_;
|
struct wl_seat* seat_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Callbacks for global registration */
|
/* Callbacks for global registration */
|
||||||
void register_manager(struct wl_registry *, uint32_t name, uint32_t version);
|
void register_manager(struct wl_registry*, uint32_t name, uint32_t version);
|
||||||
void register_seat(struct wl_registry *, uint32_t name, uint32_t version);
|
void register_seat(struct wl_registry*, uint32_t name, uint32_t version);
|
||||||
|
|
||||||
/* Callbacks for the wlr protocol */
|
/* Callbacks for the wlr protocol */
|
||||||
void handle_toplevel_create(struct zwlr_foreign_toplevel_handle_v1 *);
|
void handle_toplevel_create(struct zwlr_foreign_toplevel_handle_v1*);
|
||||||
void handle_finished();
|
void handle_finished();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void add_button(Gtk::Button &);
|
void add_button(Gtk::Button&);
|
||||||
void move_button(Gtk::Button &, int);
|
void move_button(Gtk::Button&, int);
|
||||||
void remove_button(Gtk::Button &);
|
void remove_button(Gtk::Button&);
|
||||||
void remove_task(uint32_t);
|
void remove_task(uint32_t);
|
||||||
|
|
||||||
bool show_output(struct wl_output *) const;
|
bool show_output(struct wl_output*) const;
|
||||||
bool all_outputs() const;
|
bool all_outputs() const;
|
||||||
|
|
||||||
const IconLoader &icon_loader() const;
|
const IconLoader& icon_loader() const;
|
||||||
const std::unordered_set<std::string> &ignore_list() const;
|
const std::unordered_set<std::string>& ignore_list() const;
|
||||||
const std::map<std::string, std::string> &app_ids_replace_map() const;
|
const std::map<std::string, std::string>& app_ids_replace_map() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace waybar::modules::wlr */
|
} /* namespace waybar::modules::wlr */
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ 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);
|
||||||
@@ -138,7 +138,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,6 +157,9 @@ 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);
|
exit(0);
|
||||||
} else {
|
} else {
|
||||||
@@ -169,4 +172,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
|
||||||
|
|||||||
@@ -17,18 +17,18 @@ class IconLoader {
|
|||||||
std::vector<Glib::RefPtr<Gtk::IconTheme>> custom_icon_themes_;
|
std::vector<Glib::RefPtr<Gtk::IconTheme>> custom_icon_themes_;
|
||||||
Glib::RefPtr<Gtk::IconTheme> default_icon_theme_ = Gtk::IconTheme::get_default();
|
Glib::RefPtr<Gtk::IconTheme> default_icon_theme_ = Gtk::IconTheme::get_default();
|
||||||
static std::vector<std::string> search_prefix();
|
static std::vector<std::string> search_prefix();
|
||||||
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string &app_id);
|
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string& app_id);
|
||||||
static Glib::RefPtr<Gio::DesktopAppInfo> get_desktop_app_info(const std::string &app_id);
|
static Glib::RefPtr<Gio::DesktopAppInfo> get_desktop_app_info(const std::string& app_id);
|
||||||
static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string const &icon_path, int size);
|
static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string const& icon_path, int size);
|
||||||
static std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
|
static std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
|
||||||
const std::string &app_id);
|
const std::string& app_id);
|
||||||
static bool image_load_icon(Gtk::Image &image, const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
|
static bool image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
|
||||||
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
|
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void add_custom_icon_theme(const std::string &theme_name);
|
void add_custom_icon_theme(const std::string& theme_name);
|
||||||
bool image_load_icon(Gtk::Image &image, Glib::RefPtr<Gio::DesktopAppInfo> app_info,
|
bool image_load_icon(Gtk::Image& image, Glib::RefPtr<Gio::DesktopAppInfo> app_info,
|
||||||
int size) const;
|
int size) const;
|
||||||
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_from_app_id_list(
|
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_from_app_id_list(
|
||||||
const std::string &app_id_list);
|
const std::string& app_id_list);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -30,15 +30,16 @@ class JsonParser {
|
|||||||
|
|
||||||
std::istringstream jsonStream(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;
|
||||||
|
if (!Json::parseFromStream(readerBuilder, jsonStream, &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");
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
21
include/util/udev_deleter.hpp
Normal file
21
include/util/udev_deleter.hpp
Normal 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
|
||||||
@@ -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);
|
||||||
@@ -91,6 +91,11 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
|||||||
typeof: string ++
|
typeof: string ++
|
||||||
Command to execute when scrolling up on the module.
|
Command to execute when scrolling up on the module.
|
||||||
|
|
||||||
|
*weighted-average*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Option to combine multiple batteries with different capacities.
|
||||||
|
|
||||||
*on-scroll-down*: ++
|
*on-scroll-down*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
Command to execute when scrolling down on the module.
|
Command to execute when scrolling down on the module.
|
||||||
@@ -175,8 +180,9 @@ The *battery* module allows one to define custom formats based on up to two fact
|
|||||||
Every entry in the *events* object consists of a *<event-name>* (typeof: *string*) and a *<command>* (typeof: *string*). ++
|
Every entry in the *events* object consists of a *<event-name>* (typeof: *string*) and a *<command>* (typeof: *string*). ++
|
||||||
*<event-name>* can be in one of the following formats:
|
*<event-name>* can be in one of the following formats:
|
||||||
|
|
||||||
- *on-<status>-<state>*
|
- *on-<status>-<state>*
|
||||||
- *on-<status>-<capacity>*
|
- *on-<status>-<capacity>*
|
||||||
|
- *on-<status>*
|
||||||
|
|
||||||
Where:
|
Where:
|
||||||
|
|
||||||
@@ -198,7 +204,9 @@ Where:
|
|||||||
"events": {
|
"events": {
|
||||||
"on-discharging-warning": "notify-send -u normal 'Low Battery'",
|
"on-discharging-warning": "notify-send -u normal 'Low Battery'",
|
||||||
"on-discharging-critical": "notify-send -u critical 'Very Low Battery'",
|
"on-discharging-critical": "notify-send -u critical 'Very Low Battery'",
|
||||||
"on-charging-100": "notify-send -u normal 'Battery Full!'"
|
"on-charging-100": "notify-send -u normal 'Battery Full!'",
|
||||||
|
"on-discharging": "notify-send -u normal 'Power Switch' Discharging",
|
||||||
|
"on-charging": "notify-send -u normal 'Power Switch' Charging'"
|
||||||
},
|
},
|
||||||
"format": "{capacity}% {icon}",
|
"format": "{capacity}% {icon}",
|
||||||
"format-icons": ["", "", "", "", ""],
|
"format-icons": ["", "", "", "", ""],
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ waybar - cava module
|
|||||||
|
|
||||||
*cava* module for karlstav/cava project. See it on github: https://github.com/karlstav/cava.
|
*cava* module for karlstav/cava project. See it on github: https://github.com/karlstav/cava.
|
||||||
|
|
||||||
|
Module supports two different frontends starting from the 0.15.0 release. The frontend that
|
||||||
|
will be used is managed by the method parameter in the [output] section of the cava configuration file.
|
||||||
|
|
||||||
# FILES
|
# FILES
|
||||||
|
|
||||||
@@ -32,6 +34,10 @@ libcava lives in:
|
|||||||
:[ string
|
:[ string
|
||||||
:[
|
:[
|
||||||
:< Path where cava configuration file is placed to
|
:< Path where cava configuration file is placed to
|
||||||
|
|[ *method* \[output\]
|
||||||
|
:[ string
|
||||||
|
:[
|
||||||
|
:< Manages which frontend Waybar cava module should use. Values: raw, sdl_glsl
|
||||||
|[ *framerate*
|
|[ *framerate*
|
||||||
:[ integer
|
:[ integer
|
||||||
:[ 30
|
:[ 30
|
||||||
@@ -43,7 +49,7 @@ libcava lives in:
|
|||||||
|[ *sensitivity*
|
|[ *sensitivity*
|
||||||
:[ integer
|
:[ integer
|
||||||
:[ 100
|
:[ 100
|
||||||
:[ Manual sensitivity in %. It's recommended to be omitted when *autosens* = 1
|
:[ Manual sensitivity in %. If autosens is enabled, this will only be the initial value. 200 means double height. Accepts only non-negative values
|
||||||
|[ *bars*
|
|[ *bars*
|
||||||
:[ integer
|
:[ integer
|
||||||
:[ 12
|
:[ 12
|
||||||
@@ -68,7 +74,7 @@ libcava lives in:
|
|||||||
:[ string
|
:[ string
|
||||||
:[
|
:[
|
||||||
:[ Widget's text after sleep_timer elapsed (hide_on_silence has to be false)
|
:[ Widget's text after sleep_timer elapsed (hide_on_silence has to be false)
|
||||||
|[ *method*
|
|[ *method* \[input\]
|
||||||
:[ string
|
:[ string
|
||||||
:[ pulse
|
:[ pulse
|
||||||
:[ Audio capturing method. Possible methods are: pipewire, pulse, alsa, fifo, sndio or shmem
|
:[ Audio capturing method. Possible methods are: pipewire, pulse, alsa, fifo, sndio or shmem
|
||||||
@@ -105,9 +111,9 @@ libcava lives in:
|
|||||||
:[ false
|
:[ false
|
||||||
:[ Disables or enables the so-called "Monstercat smoothing" with or without "waves"
|
:[ Disables or enables the so-called "Monstercat smoothing" with or without "waves"
|
||||||
|[ *noise_reduction*
|
|[ *noise_reduction*
|
||||||
:[ double
|
:[ integer
|
||||||
:[ 0.77
|
:[ 77
|
||||||
:[ Range between 0 - 1. The raw visualization is very noisy, this factor adjusts the integral and gravity filters to keep the signal smooth. 1 - will be very slow and smooth, 0 - will be fast but noisy
|
:[ Range between 0 - 100. The raw visualization is very noisy, this factor adjusts the integral and gravity filters to keep the signal smooth. 100 will be very slow and smooth, 0 will be fast but noisy
|
||||||
|[ *input_delay*
|
|[ *input_delay*
|
||||||
:[ integer
|
:[ integer
|
||||||
:[ 2
|
:[ 2
|
||||||
@@ -119,11 +125,11 @@ libcava lives in:
|
|||||||
|[ *data_format*
|
|[ *data_format*
|
||||||
:[ string
|
:[ string
|
||||||
:[ asci
|
:[ asci
|
||||||
:[ It's impossible to set it. Waybar sets it to = asci for internal needs
|
:[ Raw data format. Can be 'binary' or 'ascii'
|
||||||
|[ *raw_target*
|
|[ *raw_target*
|
||||||
:[ string
|
:[ string
|
||||||
:[ /dev/stdout
|
:[ /dev/stdout
|
||||||
:[ It's impossible to set it. Waybar sets it to = /dev/stdout for internal needs
|
:[ Raw output target. A fifo will be created if target does not exist
|
||||||
|[ *menu*
|
|[ *menu*
|
||||||
:[ string
|
:[ string
|
||||||
:[
|
:[
|
||||||
@@ -136,6 +142,50 @@ libcava lives in:
|
|||||||
:[ array
|
:[ array
|
||||||
:[
|
:[
|
||||||
:[ The actions corresponding to the buttons of the menu.
|
:[ The actions corresponding to the buttons of the menu.
|
||||||
|
|[ *bar_spacing*
|
||||||
|
:[ integer
|
||||||
|
:[
|
||||||
|
:[ Bars' space between bars in number of characters
|
||||||
|
|[ *bar_width*
|
||||||
|
:[ integer
|
||||||
|
:[
|
||||||
|
:[ Bars' width between bars in number of characters
|
||||||
|
|[ *bar_height*
|
||||||
|
:[ integer
|
||||||
|
:[
|
||||||
|
:[ Useless. bar_height is only used for output in "noritake" format
|
||||||
|
|[ *background*
|
||||||
|
:[ string
|
||||||
|
:[
|
||||||
|
:[ GLSL actual. Support hex code colors only. Must be within ''
|
||||||
|
|[ *foreground*
|
||||||
|
:[ string
|
||||||
|
:[
|
||||||
|
:[ GLSL actual. Support hex code colors only. Must be within ''
|
||||||
|
|[ *gradient*
|
||||||
|
:[ integer
|
||||||
|
:[ 0
|
||||||
|
:[ GLSL actual. Gradient mode(0/1 - on/off)
|
||||||
|
|[ *gradient_count*
|
||||||
|
:[ integer
|
||||||
|
:[ 0
|
||||||
|
:[ GLSL actual. The count of colors for the gradient
|
||||||
|
|[ *gradient_color_N*
|
||||||
|
:[ string
|
||||||
|
:[
|
||||||
|
:[ GLSL actual. N - the number of the gradient color between 1 and 8. Only hex defined colors are supported. Must be within ''
|
||||||
|
|[ *sdl_width*
|
||||||
|
:[ integer
|
||||||
|
:[
|
||||||
|
:[ GLSL actual. Manages the width of the waybar cava GLSL frontend module
|
||||||
|
|[ *sdl_height*
|
||||||
|
:[ integer
|
||||||
|
:[
|
||||||
|
:[ GLSL actual. Manages the height of the waybar cava GLSL frontend module
|
||||||
|
|[ *continuous_rendering*
|
||||||
|
:[ integer
|
||||||
|
:[ 0
|
||||||
|
:[ GLSL actual. Keep rendering even if no audio. Recommended to set to 1
|
||||||
|
|
||||||
Configuration can be provided as:
|
Configuration can be provided as:
|
||||||
- The only cava configuration file which is provided through *cava_config*. The rest configuration can be skipped
|
- The only cava configuration file which is provided through *cava_config*. The rest configuration can be skipped
|
||||||
@@ -153,16 +203,17 @@ Configuration can be provided as:
|
|||||||
|
|
||||||
- iniparser
|
- iniparser
|
||||||
- fftw3
|
- fftw3
|
||||||
|
- epoxy (GLSL frontend only)
|
||||||
|
|
||||||
# SOLVING ISSUES
|
# SOLVING ISSUES
|
||||||
|
|
||||||
. On start Waybar throws an exception "error while loading shared libraries: libcava.so: cannot open shared object file: No such file or directory".
|
. On start Waybar throws an exception "error while loading shared libraries: libcava.so: cannot open shared object file: No such file or directory".
|
||||||
It might happen when libcava for some reason hasn't been registered in the system. sudo ldconfig should help
|
It might happen when libcava for some reason hasn't been registered in the system. sudo ldconfig should help
|
||||||
. Waybar is starting but cava module doesn't react to the music
|
. Waybar is starting but cava module doesn't react to the music
|
||||||
1. In such cases at first need to make sure usual cava application is working as well
|
1. In such cases at first need to make sure usual cava application is working as well
|
||||||
2. If so, need to comment all configuration options. Uncomment cava_config and provide the path to the working cava config
|
2. If so, need to comment all configuration options. Uncomment cava_config and provide the path to the working cava config
|
||||||
3. You might set too huge or too small input_delay. Try to setup to 4 seconds, restart waybar, and check again 4 seconds past. Usual even on weak machines it should be enough
|
3. You might set too huge or too small input_delay. Try to setup to 4 seconds, restart waybar, and check again 4 seconds past. Usual even on weak machines it should be enough
|
||||||
4. You might accidentally switch action mode to pause mode
|
4. You might accidentally switch action mode to pause mode
|
||||||
|
|
||||||
# RISING ISSUES
|
# RISING ISSUES
|
||||||
|
|
||||||
@@ -205,3 +256,453 @@ In case when cava releases new version and you're wanna get it, it should be rai
|
|||||||
- *#cava*
|
- *#cava*
|
||||||
- *#cava.silent* Applied after no sound has been detected for sleep_timer seconds
|
- *#cava.silent* Applied after no sound has been detected for sleep_timer seconds
|
||||||
- *#cava.updated* Applied when a new frame is shown
|
- *#cava.updated* Applied when a new frame is shown
|
||||||
|
# FRONTENDS
|
||||||
|
|
||||||
|
## RAW
|
||||||
|
The cava raw frontend uses ASCII characters to visualize incoming audio data. Each ASCII symbol position corresponds to the value of the audio power pulse.
|
||||||
|
|
||||||
|
Under the hood:
|
||||||
|
```
|
||||||
|
. Incoming audio power pulse list is : 12684
|
||||||
|
. Configured array of ASCII codes is: ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" ]. See `format-icons` https://github.com/Alexays/Waybar/wiki/Module:-Cava#example
|
||||||
|
```
|
||||||
|
As a result cava frontend will give ▁▂▆█▄
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
waybar config
|
||||||
|
```
|
||||||
|
"cava": {
|
||||||
|
"cava_config": "$XDG_CONFIG_HOME/cava/waybar_raw.conf",
|
||||||
|
"input_delay": 2,
|
||||||
|
"format-icons" : ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" ],
|
||||||
|
"actions": {
|
||||||
|
"on-click-right": "mode"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
waybar_raw.conf
|
||||||
|
```
|
||||||
|
## Configuration file for CAVA.
|
||||||
|
# Remove the ; to change parameters.
|
||||||
|
|
||||||
|
|
||||||
|
[general]
|
||||||
|
|
||||||
|
# Smoothing mode. Can be 'normal', 'scientific' or 'waves'. DEPRECATED as of 0.6.0
|
||||||
|
|
||||||
|
# Accepts only non-negative values.
|
||||||
|
|
||||||
|
# 'autosens' will attempt to decrease sensitivity if the bars peak. 1 = on, 0 = off
|
||||||
|
# new as of 0.6.0 autosens of low values (dynamic range)
|
||||||
|
# 'overshoot' allows bars to overshoot (in % of terminal height) without initiating autosens. DEPRECATED as of 0.6.0
|
||||||
|
|
||||||
|
# Manual sensitivity in %. If autosens is enabled, this will only be the initial value.
|
||||||
|
# 200 means double height. Accepts only non-negative values.
|
||||||
|
|
||||||
|
# The number of bars (0-512). 0 sets it to auto (fill up console).
|
||||||
|
# Bars' width and space between bars in number of characters.
|
||||||
|
bars = 12
|
||||||
|
# bar_height is only used for output in "noritake" format
|
||||||
|
|
||||||
|
# For SDL width and space between bars is in pixels, defaults are:
|
||||||
|
|
||||||
|
# sdl_glsl have these default values, they are only used to calculate max number of bars.
|
||||||
|
|
||||||
|
|
||||||
|
# Lower and higher cutoff frequencies for lowest and highest bars
|
||||||
|
# the bandwidth of the visualizer.
|
||||||
|
# Note: there is a minimum total bandwidth of 43Mhz x number of bars.
|
||||||
|
# Cava will automatically increase the higher cutoff if a too low band is specified.
|
||||||
|
|
||||||
|
# Seconds with no input before cava goes to sleep mode. Cava will not perform FFT or drawing and
|
||||||
|
# only check for input once per second. Cava will wake up once input is detected. 0 = disable.
|
||||||
|
sleep_timer = 5
|
||||||
|
|
||||||
|
|
||||||
|
[input]
|
||||||
|
|
||||||
|
# Audio capturing method. Possible methods are: 'fifo', 'portaudio', 'pipewire', 'alsa', 'pulse', 'sndio', 'oss', 'jack' or 'shmem'
|
||||||
|
# Defaults to 'oss', 'pipewire', 'sndio', 'jack', 'pulse', 'alsa', 'portaudio' or 'fifo', in that order, dependent on what support cava was built with.
|
||||||
|
# On Mac it defaults to 'portaudio' or 'fifo'
|
||||||
|
# On windows this is automatic and no input settings are needed.
|
||||||
|
#
|
||||||
|
# All input methods uses the same config variable 'source'
|
||||||
|
# to define where it should get the audio.
|
||||||
|
#
|
||||||
|
# For pulseaudio and pipewire 'source' will be the source. Default: 'auto', which uses the monitor source of the default sink
|
||||||
|
# (all pulseaudio sinks(outputs) have 'monitor' sources(inputs) associated with them).
|
||||||
|
#
|
||||||
|
# For pipewire 'source' will be the object name or object.serial of the device to capture from.
|
||||||
|
# Both input and output devices are supported.
|
||||||
|
#
|
||||||
|
# For alsa 'source' will be the capture device.
|
||||||
|
# For fifo 'source' will be the path to fifo-file.
|
||||||
|
# For shmem 'source' will be /squeezelite-AA:BB:CC:DD:EE:FF where 'AA:BB:CC:DD:EE:FF' will be squeezelite's MAC address
|
||||||
|
#
|
||||||
|
# For sndio 'source' will be a raw recording audio descriptor or a monitoring sub-device, e.g. 'rsnd/2' or 'snd/1'. Default: 'default'.
|
||||||
|
# README.md contains further information on how to setup CAVA for sndio.
|
||||||
|
#
|
||||||
|
# For oss 'source' will be the path to a audio device, e.g. '/dev/dsp2'. Default: '/dev/dsp', i.e. the default audio device.
|
||||||
|
# README.md contains further information on how to setup CAVA for OSS on FreeBSD.
|
||||||
|
#
|
||||||
|
# For jack 'source' will be the name of the JACK server to connect to, e.g. 'foobar'. Default: 'default'.
|
||||||
|
# README.md contains further information on how to setup CAVA for JACK.
|
||||||
|
#
|
||||||
|
|
||||||
|
# The options 'sample_rate', 'sample_bits', 'channels' and 'autoconnect' can be configured for some input methods:
|
||||||
|
# sample_rate: fifo, pipewire, sndio, oss
|
||||||
|
# sample_bits: fifo, pipewire, sndio, oss
|
||||||
|
# channels: sndio, oss, jack
|
||||||
|
# autoconnect: jack
|
||||||
|
# Other methods ignore these settings.
|
||||||
|
#
|
||||||
|
# For 'sndio' and 'oss' they are only preferred values, i.e. if the values are not supported
|
||||||
|
# by the chosen audio device, the device will use other supported values instead.
|
||||||
|
# Example: 48000, 32 and 2, but the device only supports 44100, 16 and 1, then it
|
||||||
|
# will use 44100, 16 and 1.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
[output]
|
||||||
|
|
||||||
|
# Output method. Can be 'ncurses', 'noncurses', 'raw', 'noritake', 'sdl'
|
||||||
|
# or 'sdl_glsl'.
|
||||||
|
# 'noncurses' (default) uses a buffer and cursor movements to only print
|
||||||
|
# changes from frame to frame in the terminal. Uses less resources and is less
|
||||||
|
# prone to tearing (vsync issues) than 'ncurses'.
|
||||||
|
#
|
||||||
|
# 'raw' is an 8 or 16 bit (configurable via the 'bit_format' option) data
|
||||||
|
# stream of the bar heights that can be used to send to other applications.
|
||||||
|
# 'raw' defaults to 200 bars, which can be adjusted in the 'bars' option above.
|
||||||
|
#
|
||||||
|
# 'noritake' outputs a bitmap in the format expected by a Noritake VFD display
|
||||||
|
# in graphic mode. It only support the 3000 series graphical VFDs for now.
|
||||||
|
#
|
||||||
|
# 'sdl' uses the Simple DirectMedia Layer to render in a graphical context.
|
||||||
|
# 'sdl_glsl' uses SDL to create an OpenGL context. Write your own shaders or
|
||||||
|
# use one of the predefined ones.
|
||||||
|
method = raw
|
||||||
|
|
||||||
|
# Orientation of the visualization. Can be 'bottom', 'top', 'left', 'right' or
|
||||||
|
# 'horizontal'. Default is 'bottom'. 'left and 'right' are only supported on sdl
|
||||||
|
# and ncruses output. 'horizontal' (bars go up and down from center) is only supported
|
||||||
|
# on noncurses output.
|
||||||
|
# Note: many fonts have weird or missing glyphs for characters used in orientations
|
||||||
|
# other than 'bottom', which can make output not look right.
|
||||||
|
|
||||||
|
# Visual channels. Can be 'stereo' or 'mono'.
|
||||||
|
# 'stereo' mirrors both channels with low frequencies in center.
|
||||||
|
# 'mono' outputs left to right lowest to highest frequencies.
|
||||||
|
# 'mono_option' set mono to either take input from 'left', 'right' or 'average'.
|
||||||
|
# set 'reverse' to 1 to display frequencies the other way around.
|
||||||
|
|
||||||
|
# Raw output target. A fifo will be created if target does not exist.
|
||||||
|
raw_target = /dev/stdout
|
||||||
|
|
||||||
|
# Raw data format. Can be 'binary' or 'ascii'.
|
||||||
|
data_format = ascii
|
||||||
|
|
||||||
|
# Binary bit format, can be '8bit' (0-255) or '16bit' (0-65530).
|
||||||
|
|
||||||
|
# Ascii max value. In 'ascii' mode range will run from 0 to value specified here
|
||||||
|
|
||||||
|
# Ascii delimiters. In ascii format each bar and frame is separated by a delimiters.
|
||||||
|
# Use decimal value in ascii table (i.e. 59 = ';' and 10 = '\n' (line feed)).
|
||||||
|
bar_delimiter = 0
|
||||||
|
|
||||||
|
# sdl window size and position. -1,-1 is centered.
|
||||||
|
|
||||||
|
# set label on bars on the x-axis. Can be 'frequency' or 'none'. Default: 'none'
|
||||||
|
# 'frequency' displays the lower cut off frequency of the bar above.
|
||||||
|
# Only supported on ncurses and noncurses output.
|
||||||
|
|
||||||
|
# enable synchronized sync. 1 = on, 0 = off
|
||||||
|
# removes flickering in alacritty terminal emulator.
|
||||||
|
# defaults to off since the behaviour in other terminal emulators is unknown
|
||||||
|
|
||||||
|
# Shaders for sdl_glsl, located in $HOME/.config/cava/shaders
|
||||||
|
|
||||||
|
; for glsl output mode, keep rendering even if no audio
|
||||||
|
|
||||||
|
# disable console blank (screen saver) in tty
|
||||||
|
# (Not supported on FreeBSD)
|
||||||
|
|
||||||
|
# show a flat bar at the bottom of the screen when idle, 1 = on, 0 = off
|
||||||
|
|
||||||
|
# show waveform instead of frequency spectrum, 1 = on, 0 = off
|
||||||
|
|
||||||
|
[color]
|
||||||
|
|
||||||
|
# Colors can be one of seven predefined: black, blue, cyan, green, magenta, red, white, yellow.
|
||||||
|
# Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors requires
|
||||||
|
# a terminal that can change color definitions such as Gnome-terminal or rxvt.
|
||||||
|
# default is to keep current terminal color
|
||||||
|
|
||||||
|
# SDL and sdl_glsl only support hex code colors, these are the default:
|
||||||
|
|
||||||
|
# Gradient mode, only hex defined colors are supported,
|
||||||
|
# background must also be defined in hex or remain commented out. 1 = on, 0 = off.
|
||||||
|
# You can define as many as 8 different colors. They range from bottom to top of screen
|
||||||
|
|
||||||
|
[smoothing]
|
||||||
|
|
||||||
|
# Disables or enables the so-called "Monstercat smoothing" with or without "waves". Set to 0 to disable.
|
||||||
|
|
||||||
|
# Noise reduction, int 0 - 100. default 77
|
||||||
|
# the raw visualization is very noisy, this factor adjusts the integral and gravity filters to keep the signal smooth
|
||||||
|
# 100 will be very slow and smooth, 0 will be fast but noisy.
|
||||||
|
|
||||||
|
|
||||||
|
[eq]
|
||||||
|
|
||||||
|
# This one is tricky. You can have as much keys as you want.
|
||||||
|
# Remember to uncomment more than one key! More keys = more precision.
|
||||||
|
# Look at readme.md on github for further explanations and examples.
|
||||||
|
```
|
||||||
|
## GLSL
|
||||||
|
The Cava GLSL frontend delegates the visualization of incoming audio data to the GPU via OpenGL.
|
||||||
|
|
||||||
|
There are some mandatory dependencies that need to be satisfied in order for Cava GLSL to be built and function properly:
|
||||||
|
|
||||||
|
. epoxy library must be installed on the system
|
||||||
|
. Vertex and fragment shaders from the original project must be used. They should be downloaded, and the file paths must be configured correctly in the Waybar Cava configuration:
|
||||||
|
1. cava shaders [cava shaders](https://github.com/karlstav/cava/tree/master/output/shaders)
|
||||||
|
2. libcava shaders [libcava shaders](https://github.com/LukashonakV/cava/tree/master/output/shaders)
|
||||||
|
. It is highly recommended to have a separate cava configuration for the Waybar Cava GLSL module and to use this as the cava_config in the Waybar configuration.
|
||||||
|
. It is common for cava configurations to be placed in the XDG_CONFIG_HOME directory, including shaders as well. Consider keeping them in the $XDG_CONFIG_HOME/cava/shaders folder.
|
||||||
|
|
||||||
|
Key configuration options:
|
||||||
|
|
||||||
|
. bars. The more values the parameter has, the more interesting the visualization becomes.
|
||||||
|
. method in output section must be set to sdl_glsl
|
||||||
|
. sdl_width and sdl_height manage the size of the module. Adjust them according to your needs.
|
||||||
|
. Shaders for sdl_glsl, located in $HOME/.config/cava/shaders. Example: "vertex_shader" = "pass_through.vert" "fragment_shader" = "spectrogram.frag"
|
||||||
|
. Set continuous_rendering to 1 to enable smooth rendering; set it to 0 otherwise. It is recommended to keep it set to 1.
|
||||||
|
. background, foreground, and gradient_color_N (where N is a number between 1 and 8) must be defined using hex code
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
waybar config
|
||||||
|
```
|
||||||
|
"cava": {
|
||||||
|
"cava_config": "$XDG_CONFIG_HOME/cava/waybar_cava#3.conf",
|
||||||
|
"input_delay": 2,
|
||||||
|
"actions": {
|
||||||
|
"on-click-right": "mode"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
waybar_raw.conf
|
||||||
|
```
|
||||||
|
## Configuration file for CAVA.
|
||||||
|
# Remove the ; to change parameters.
|
||||||
|
|
||||||
|
|
||||||
|
[general]
|
||||||
|
|
||||||
|
# Smoothing mode. Can be 'normal', 'scientific' or 'waves'. DEPRECATED as of 0.6.0
|
||||||
|
|
||||||
|
# Accepts only non-negative values.
|
||||||
|
|
||||||
|
# 'autosens' will attempt to decrease sensitivity if the bars peak. 1 = on, 0 = off
|
||||||
|
# new as of 0.6.0 autosens of low values (dynamic range)
|
||||||
|
# 'overshoot' allows bars to overshoot (in % of terminal height) without initiating autosens. DEPRECATED as of 0.6.0
|
||||||
|
|
||||||
|
# Manual sensitivity in %. If autosens is enabled, this will only be the initial value.
|
||||||
|
# 200 means double height. Accepts only non-negative values.
|
||||||
|
|
||||||
|
# The number of bars (0-512). 0 sets it to auto (fill up console).
|
||||||
|
# Bars' width and space between bars in number of characters.
|
||||||
|
bars = 50
|
||||||
|
|
||||||
|
# bar_height is only used for output in "noritake" format
|
||||||
|
|
||||||
|
# For SDL width and space between bars is in pixels, defaults are:
|
||||||
|
|
||||||
|
# sdl_glsl have these default values, they are only used to calculate max number of bars.
|
||||||
|
|
||||||
|
# Lower and higher cutoff frequencies for lowest and highest bars
|
||||||
|
# the bandwidth of the visualizer.
|
||||||
|
# Note: there is a minimum total bandwidth of 43Mhz x number of bars.
|
||||||
|
# Cava will automatically increase the higher cutoff if a too low band is specified.
|
||||||
|
|
||||||
|
# Seconds with no input before cava goes to sleep mode. Cava will not perform FFT or drawing and
|
||||||
|
# only check for input once per second. Cava will wake up once input is detected. 0 = disable.
|
||||||
|
sleep_timer = 5
|
||||||
|
|
||||||
|
|
||||||
|
[input]
|
||||||
|
|
||||||
|
# Audio capturing method. Possible methods are: 'fifo', 'portaudio', 'pipewire', 'alsa', 'pulse', 'sndio', 'oss', 'jack' or 'shmem'
|
||||||
|
# Defaults to 'oss', 'pipewire', 'sndio', 'jack', 'pulse', 'alsa', 'portaudio' or 'fifo', in that order, dependent on what support cava was built with.
|
||||||
|
# On Mac it defaults to 'portaudio' or 'fifo'
|
||||||
|
# On windows this is automatic and no input settings are needed.
|
||||||
|
#
|
||||||
|
# All input methods uses the same config variable 'source'
|
||||||
|
# to define where it should get the audio.
|
||||||
|
#
|
||||||
|
# For pulseaudio and pipewire 'source' will be the source. Default: 'auto', which uses the monitor source of the default sink
|
||||||
|
# (all pulseaudio sinks(outputs) have 'monitor' sources(inputs) associated with them).
|
||||||
|
#
|
||||||
|
# For pipewire 'source' will be the object name or object.serial of the device to capture from.
|
||||||
|
# Both input and output devices are supported.
|
||||||
|
#
|
||||||
|
# For alsa 'source' will be the capture device.
|
||||||
|
# For fifo 'source' will be the path to fifo-file.
|
||||||
|
# For shmem 'source' will be /squeezelite-AA:BB:CC:DD:EE:FF where 'AA:BB:CC:DD:EE:FF' will be squeezelite's MAC address
|
||||||
|
#
|
||||||
|
# For sndio 'source' will be a raw recording audio descriptor or a monitoring sub-device, e.g. 'rsnd/2' or 'snd/1'. Default: 'default'.
|
||||||
|
# README.md contains further information on how to setup CAVA for sndio.
|
||||||
|
#
|
||||||
|
# For oss 'source' will be the path to a audio device, e.g. '/dev/dsp2'. Default: '/dev/dsp', i.e. the default audio device.
|
||||||
|
# README.md contains further information on how to setup CAVA for OSS on FreeBSD.
|
||||||
|
#
|
||||||
|
# For jack 'source' will be the name of the JACK server to connect to, e.g. 'foobar'. Default: 'default'.
|
||||||
|
# README.md contains further information on how to setup CAVA for JACK.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# The options 'sample_rate', 'sample_bits', 'channels' and 'autoconnect' can be configured for some input methods:
|
||||||
|
# sample_rate: fifo, pipewire, sndio, oss
|
||||||
|
# sample_bits: fifo, pipewire, sndio, oss
|
||||||
|
# channels: sndio, oss, jack
|
||||||
|
# autoconnect: jack
|
||||||
|
# Other methods ignore these settings.
|
||||||
|
#
|
||||||
|
# For 'sndio' and 'oss' they are only preferred values, i.e. if the values are not supported
|
||||||
|
# by the chosen audio device, the device will use other supported values instead.
|
||||||
|
# Example: 48000, 32 and 2, but the device only supports 44100, 16 and 1, then it
|
||||||
|
# will use 44100, 16 and 1.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
[output]
|
||||||
|
|
||||||
|
# Output method. Can be 'ncurses', 'noncurses', 'raw', 'noritake', 'sdl'
|
||||||
|
# or 'sdl_glsl'.
|
||||||
|
# 'noncurses' (default) uses a buffer and cursor movements to only print
|
||||||
|
# changes from frame to frame in the terminal. Uses less resources and is less
|
||||||
|
# prone to tearing (vsync issues) than 'ncurses'.
|
||||||
|
#
|
||||||
|
# 'raw' is an 8 or 16 bit (configurable via the 'bit_format' option) data
|
||||||
|
# stream of the bar heights that can be used to send to other applications.
|
||||||
|
# 'raw' defaults to 200 bars, which can be adjusted in the 'bars' option above.
|
||||||
|
#
|
||||||
|
# 'noritake' outputs a bitmap in the format expected by a Noritake VFD display
|
||||||
|
# in graphic mode. It only support the 3000 series graphical VFDs for now.
|
||||||
|
#
|
||||||
|
# 'sdl' uses the Simple DirectMedia Layer to render in a graphical context.
|
||||||
|
# 'sdl_glsl' uses SDL to create an OpenGL context. Write your own shaders or
|
||||||
|
# use one of the predefined ones.
|
||||||
|
method = sdl_glsl
|
||||||
|
|
||||||
|
# Orientation of the visualization. Can be 'bottom', 'top', 'left', 'right' or
|
||||||
|
# 'horizontal'. Default is 'bottom'. 'left and 'right' are only supported on sdl
|
||||||
|
# and ncruses output. 'horizontal' (bars go up and down from center) is only supported
|
||||||
|
# on noncurses output.
|
||||||
|
# Note: many fonts have weird or missing glyphs for characters used in orientations
|
||||||
|
# other than 'bottom', which can make output not look right.
|
||||||
|
|
||||||
|
# Visual channels. Can be 'stereo' or 'mono'.
|
||||||
|
# 'stereo' mirrors both channels with low frequencies in center.
|
||||||
|
# 'mono' outputs left to right lowest to highest frequencies.
|
||||||
|
# 'mono_option' set mono to either take input from 'left', 'right' or 'average'.
|
||||||
|
# set 'reverse' to 1 to display frequencies the other way around.
|
||||||
|
|
||||||
|
# Raw output target. A fifo will be created if target does not exist.
|
||||||
|
|
||||||
|
# Raw data format. Can be 'binary' or 'ascii'.
|
||||||
|
|
||||||
|
# Binary bit format, can be '8bit' (0-255) or '16bit' (0-65530).
|
||||||
|
|
||||||
|
# Ascii max value. In 'ascii' mode range will run from 0 to value specified here
|
||||||
|
|
||||||
|
# Ascii delimiters. In ascii format each bar and frame is separated by a delimiters.
|
||||||
|
# Use decimal value in ascii table (i.e. 59 = ';' and 10 = '\n' (line feed)).
|
||||||
|
bar_delimiter = 0
|
||||||
|
|
||||||
|
# sdl window size and position. -1,-1 is centered.
|
||||||
|
sdl_width = 150
|
||||||
|
sdl_height = 39
|
||||||
|
|
||||||
|
# set label on bars on the x-axis. Can be 'frequency' or 'none'. Default: 'none'
|
||||||
|
# 'frequency' displays the lower cut off frequency of the bar above.
|
||||||
|
# Only supported on ncurses and noncurses output.
|
||||||
|
|
||||||
|
# enable synchronized sync. 1 = on, 0 = off
|
||||||
|
# removes flickering in alacritty terminal emulator.
|
||||||
|
# defaults to off since the behaviour in other terminal emulators is unknown
|
||||||
|
|
||||||
|
# Shaders for sdl_glsl, located in $HOME/.config/cava/shaders
|
||||||
|
vertex_shader = pass_through.vert
|
||||||
|
fragment_shader = bar_spectrum.frag
|
||||||
|
|
||||||
|
; for glsl output mode, keep rendering even if no audio
|
||||||
|
continuous_rendering = 1;
|
||||||
|
|
||||||
|
# disable console blank (screen saver) in tty
|
||||||
|
# (Not supported on FreeBSD)
|
||||||
|
|
||||||
|
# show a flat bar at the bottom of the screen when idle, 1 = on, 0 = off
|
||||||
|
|
||||||
|
# show waveform instead of frequency spectrum, 1 = on, 0 = off
|
||||||
|
|
||||||
|
[color]
|
||||||
|
|
||||||
|
|
||||||
|
# Colors can be one of seven predefined: black, blue, cyan, green, magenta, red, white, yellow.
|
||||||
|
# Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors requires
|
||||||
|
# a terminal that can change color definitions such as Gnome-terminal or rxvt.
|
||||||
|
# default is to keep current terminal color
|
||||||
|
|
||||||
|
# SDL and sdl_glsl only support hex code colors, these are the default:
|
||||||
|
background = '#282C34'
|
||||||
|
|
||||||
|
# Gradient mode, only hex defined colors are supported,
|
||||||
|
# background must also be defined in hex or remain commented out. 1 = on, 0 = off.
|
||||||
|
# You can define as many as 8 different colors. They range from bottom to top of screen
|
||||||
|
gradient = 1
|
||||||
|
gradient_count = 2
|
||||||
|
gradient_color_1 = '#282C34'
|
||||||
|
gradient_color_2 = '#45475A'
|
||||||
|
|
||||||
|
; gradient_color_1 = '#59cc33'
|
||||||
|
; gradient_color_2 = '#80cc33'
|
||||||
|
gradient_color_3 = '#a6cc33'
|
||||||
|
gradient_color_4 = '#cccc33'
|
||||||
|
gradient_color_5 = '#cca633'
|
||||||
|
gradient_color_6 = '#cc8033'
|
||||||
|
gradient_color_7 = '#cc5933'
|
||||||
|
gradient_color_8 = '#cc3333'
|
||||||
|
|
||||||
|
[smoothing]
|
||||||
|
|
||||||
|
# Percentage value for integral smoothing. Takes values from 0 - 100.
|
||||||
|
# Higher values means smoother, but less precise. 0 to disable.
|
||||||
|
# DEPRECATED as of 0.8.0, use noise_reduction instead
|
||||||
|
|
||||||
|
# Disables or enables the so-called "Monstercat smoothing" with or without "waves". Set to 0 to disable.
|
||||||
|
|
||||||
|
# Set gravity percentage for "drop off". Higher values means bars will drop faster.
|
||||||
|
# Accepts only non-negative values. 50 means half gravity, 200 means double. Set to 0 to disable "drop off".
|
||||||
|
# DEPRECATED as of 0.8.0, use noise_reduction instead
|
||||||
|
|
||||||
|
|
||||||
|
# In bar height, bars that would have been lower that this will not be drawn.
|
||||||
|
# DEPRECATED as of 0.8.0
|
||||||
|
|
||||||
|
# Noise reduction, int 0 - 100. default 77
|
||||||
|
# the raw visualization is very noisy, this factor adjusts the integral and gravity filters to keep the signal smooth
|
||||||
|
# 100 will be very slow and smooth, 0 will be fast but noisy.
|
||||||
|
|
||||||
|
[eq]
|
||||||
|
|
||||||
|
# This one is tricky. You can have as much keys as you want.
|
||||||
|
# Remember to uncomment more than one key! More keys = more precision.
|
||||||
|
# Look at readme.md on github for further explanations and examples.
|
||||||
|
```
|
||||||
|
|
||||||
|
Different waybar_cava#N.conf see at [cava GLSL](https://github.com/Alexays/Waybar/wiki/Module:-Cava:-GLSL)
|
||||||
|
|||||||
@@ -234,7 +234,6 @@ $text\\n$tooltip\\n$class*
|
|||||||
```
|
```
|
||||||
"custom/pacman": {
|
"custom/pacman": {
|
||||||
"format": "{text} ",
|
"format": "{text} ",
|
||||||
"interval": 3600, // every hour
|
|
||||||
"exec": "checkupdates | wc -l", // # of updates
|
"exec": "checkupdates | wc -l", // # of updates
|
||||||
"exec-if": "exit 0", // always run; consider advanced run conditions
|
"exec-if": "exit 0", // always run; consider advanced run conditions
|
||||||
"on-click": "termite -e 'sudo pacman -Syu'; pkill -SIGRTMIN+8 waybar", // update system
|
"on-click": "termite -e 'sudo pacman -Syu'; pkill -SIGRTMIN+8 waybar", // update system
|
||||||
@@ -242,7 +241,7 @@ $text\\n$tooltip\\n$class*
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can use the signal and update the number of available packages with *pkill -RTMIN+8 waybar*.
|
Under the premise that interval is not defined, you can use the signal and update the number of available packages with *pkill -RTMIN+8 waybar*.
|
||||||
|
|
||||||
# STYLE
|
# STYLE
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ Addressed by *dwl/tags*
|
|||||||
|
|
||||||
- *#tags button*
|
- *#tags button*
|
||||||
- *#tags button.occupied*
|
- *#tags button.occupied*
|
||||||
|
- *#tags button.empty*
|
||||||
- *#tags button.focused*
|
- *#tags button.focused*
|
||||||
- *#tags button.urgent*
|
- *#tags button.urgent*
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,11 @@ This setting is ignored if *workspace-taskbar.enable* is set to true.
|
|||||||
Otherwise, the workspace will open on the monitor where it was previously assigned.
|
Otherwise, the workspace will open on the monitor where it was previously assigned.
|
||||||
Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland.
|
Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland.
|
||||||
|
|
||||||
|
*enable-bar-scroll*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If set to false, you can't scroll to cycle throughout workspaces from the entire bar. If set to true this behaviour is enabled.
|
||||||
|
|
||||||
*ignore-workspaces*: ++
|
*ignore-workspaces*: ++
|
||||||
typeof: array ++
|
typeof: array ++
|
||||||
default: [] ++
|
default: [] ++
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ The *image* module displays an image from a path.
|
|||||||
*interval*: ++
|
*interval*: ++
|
||||||
typeof: integer or float ++
|
typeof: integer or float ++
|
||||||
The interval (in seconds) to re-render the image. ++
|
The interval (in seconds) to re-render the image. ++
|
||||||
Minimum value is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++
|
If set to a positive value, the minimum is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++
|
||||||
|
Zero or negative values are treated as "once". ++
|
||||||
This is useful if the contents of *path* changes. ++
|
This is useful if the contents of *path* changes. ++
|
||||||
If no *interval* is defined, the image will only be rendered once.
|
If no *interval* is defined, the image will only be rendered once.
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,11 @@ Additionally, you can control the volume by scrolling *up* or *down* while the c
|
|||||||
|
|
||||||
*reverse-scrolling*: ++
|
*reverse-scrolling*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
Option to reverse the scroll direction.
|
Option to reverse the scroll direction for touchpads.
|
||||||
|
|
||||||
|
*reverse-mouse-scrolling*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
Option to reverse the scroll direction for mice.
|
||||||
|
|
||||||
*tooltip*: ++
|
*tooltip*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
@@ -173,8 +177,8 @@ to be selected when the corresponding audio device is muted. This applies to *de
|
|||||||
"format-icons": {
|
"format-icons": {
|
||||||
"alsa_output.pci-0000_00_1f.3.analog-stereo": "",
|
"alsa_output.pci-0000_00_1f.3.analog-stereo": "",
|
||||||
"alsa_output.pci-0000_00_1f.3.analog-stereo-muted": "",
|
"alsa_output.pci-0000_00_1f.3.analog-stereo-muted": "",
|
||||||
"headphones": "",
|
"headphone": "",
|
||||||
"handsfree": "",
|
"hands-free": "",
|
||||||
"headset": "",
|
"headset": "",
|
||||||
"phone": "",
|
"phone": "",
|
||||||
"phone-muted": "",
|
"phone-muted": "",
|
||||||
|
|||||||
@@ -179,7 +179,6 @@ n.b.: the list of outputs can be obtained from command line using *swaymsg -t ge
|
|||||||
"format": "<span size='larger'>{name}</span> {windows}",
|
"format": "<span size='larger'>{name}</span> {windows}",
|
||||||
"format-window-separator": " | ",
|
"format-window-separator": " | ",
|
||||||
"window-rewrite-default": "{name}",
|
"window-rewrite-default": "{name}",
|
||||||
"window-format": "<span color='#e0e0e0'>{name}</span>",
|
|
||||||
"window-rewrite": {
|
"window-rewrite": {
|
||||||
"class<firefox>": "",
|
"class<firefox>": "",
|
||||||
"class<kitty>": "k",
|
"class<kitty>": "k",
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(
|
|||||||
*expand-right* ++
|
*expand-right* ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: false ++
|
default: false ++
|
||||||
Enables the modules-left to consume all left over space dynamically.
|
Enables the modules-right to consume all left over space dynamically.
|
||||||
|
|
||||||
*layer* ++
|
*layer* ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
|
|||||||
19
meson.build
19
meson.build
@@ -1,6 +1,6 @@
|
|||||||
project(
|
project(
|
||||||
'waybar', 'cpp', 'c',
|
'waybar', 'cpp', 'c',
|
||||||
version: '0.14.0',
|
version: '0.15.0',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>= 0.59.0',
|
meson_version: '>= 0.59.0',
|
||||||
default_options : [
|
default_options : [
|
||||||
@@ -497,16 +497,24 @@ else
|
|||||||
man_files += files('man/waybar-clock.5.scd')
|
man_files += files('man/waybar-clock.5.scd')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
cava = dependency('cava',
|
cava = dependency('libcava',
|
||||||
version : '>=0.10.6',
|
version : '>=0.10.7',
|
||||||
required: get_option('cava'),
|
required: get_option('cava'),
|
||||||
fallback : ['cava', 'cava_dep'],
|
fallback : ['libcava', 'cava_dep'],
|
||||||
not_found_message: 'cava is not found. Building waybar without cava')
|
not_found_message: 'cava is not found. Building waybar without cava')
|
||||||
|
|
||||||
|
eproxy = dependency('epoxy', required: false)
|
||||||
|
|
||||||
if cava.found()
|
if cava.found()
|
||||||
add_project_arguments('-DHAVE_LIBCAVA', language: 'cpp')
|
add_project_arguments('-DHAVE_LIBCAVA', language: 'cpp')
|
||||||
src_files += files('src/modules/cava/cava.cpp', 'src/modules/cava/cava_backend.cpp')
|
src_files += files('src/modules/cava/cavaRaw.cpp',
|
||||||
|
'src/modules/cava/cava_backend.cpp')
|
||||||
man_files += files('man/waybar-cava.5.scd')
|
man_files += files('man/waybar-cava.5.scd')
|
||||||
|
|
||||||
|
if eproxy.found()
|
||||||
|
add_project_arguments('-DHAVE_LIBCAVAGLSL', language: 'cpp')
|
||||||
|
src_files += files('src/modules/cava/cavaGLSL.cpp')
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if libgps.found()
|
if libgps.found()
|
||||||
@@ -554,6 +562,7 @@ executable(
|
|||||||
tz_dep,
|
tz_dep,
|
||||||
xkbregistry,
|
xkbregistry,
|
||||||
cava,
|
cava,
|
||||||
|
eproxy,
|
||||||
libgps
|
libgps
|
||||||
],
|
],
|
||||||
include_directories: inc_dirs,
|
include_directories: inc_dirs,
|
||||||
|
|||||||
@@ -5,13 +5,14 @@
|
|||||||
version,
|
version,
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
libcava = {
|
libcava = rec {
|
||||||
|
version = "0.10.7-beta";
|
||||||
src = pkgs.fetchFromGitHub {
|
src = pkgs.fetchFromGitHub {
|
||||||
owner = "LukashonakV";
|
owner = "LukashonakV";
|
||||||
repo = "cava";
|
repo = "cava";
|
||||||
# NOTE: Needs to match the cava.wrap
|
# NOTE: Needs to match the cava.wrap
|
||||||
rev = "23efcced43b5a395747b18a2e5f2171fc0925d18";
|
tag = "v${version}";
|
||||||
hash = "sha256-CNspaoK5KuME0GfaNijpC24BfALngzNi04/VNwPqMvo=";
|
hash = "sha256-IX1B375gTwVDRjpRfwKGuzTAZOV2pgDWzUd4bW2cTDU=";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
@@ -39,7 +40,7 @@ waybar.overrideAttrs (oldAttrs: {
|
|||||||
|
|
||||||
postUnpack = ''
|
postUnpack = ''
|
||||||
pushd "$sourceRoot"
|
pushd "$sourceRoot"
|
||||||
cp -R --no-preserve=mode,ownership ${libcava.src} subprojects/cava
|
cp -R --no-preserve=mode,ownership ${libcava.src} subprojects/cava-${libcava.version}
|
||||||
patchShebangs .
|
patchShebangs .
|
||||||
popd
|
popd
|
||||||
'';
|
'';
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ void AAppIconLabel::updateAppIconName(const std::string& app_identifier,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AAppIconLabel::updateAppIcon() {
|
void AAppIconLabel::updateAppIcon() {
|
||||||
if (update_app_icon_) {
|
if (update_app_icon_ || (!iconEnabled() && image_.get_visible())) {
|
||||||
update_app_icon_ = false;
|
update_app_icon_ = false;
|
||||||
if (app_icon_name_.empty()) {
|
if (app_icon_name_.empty()) {
|
||||||
image_.set_visible(false);
|
image_.set_visible(false);
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
|
|
||||||
AIconLabel::AIconLabel(const Json::Value &config, const std::string &name, const std::string &id,
|
AIconLabel::AIconLabel(const Json::Value& config, const std::string& name, const std::string& id,
|
||||||
const std::string &format, uint16_t interval, bool ellipsize,
|
const std::string& format, uint16_t interval, bool ellipsize,
|
||||||
bool enable_click, bool enable_scroll)
|
bool enable_click, bool enable_scroll)
|
||||||
: ALabel(config, name, id, format, interval, ellipsize, enable_click, enable_scroll) {
|
: ALabel(config, name, id, format, interval, ellipsize, enable_click, enable_scroll) {
|
||||||
event_box_.remove();
|
event_box_.remove();
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ bool waybar::ALabel::handleToggle(GdkEventButton* const& e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ALabel::handleGtkMenuEvent(GtkMenuItem* /*menuitem*/, gpointer data) {
|
void ALabel::handleGtkMenuEvent(GtkMenuItem* /*menuitem*/, gpointer data) {
|
||||||
waybar::util::command::res res = waybar::util::command::exec((char*)data, "GtkMenu");
|
waybar::util::command::forkExec((char*)data, "GtkMenu");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ALabel::getState(uint8_t value, bool lesser) {
|
std::string ALabel::getState(uint8_t value, bool lesser) {
|
||||||
|
|||||||
@@ -229,7 +229,8 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
|||||||
gtk_layer_init_for_window(gtk_window);
|
gtk_layer_init_for_window(gtk_window);
|
||||||
gtk_layer_set_keyboard_mode(gtk_window, GTK_LAYER_SHELL_KEYBOARD_MODE_NONE);
|
gtk_layer_set_keyboard_mode(gtk_window, GTK_LAYER_SHELL_KEYBOARD_MODE_NONE);
|
||||||
gtk_layer_set_monitor(gtk_window, output->monitor->gobj());
|
gtk_layer_set_monitor(gtk_window, output->monitor->gobj());
|
||||||
gtk_layer_set_namespace(gtk_window, "waybar");
|
gtk_layer_set_namespace(gtk_window,
|
||||||
|
config["name"].isString() ? config["name"].asCString() : "waybar");
|
||||||
|
|
||||||
gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_LEFT, margins_.left);
|
gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_LEFT, margins_.left);
|
||||||
gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_RIGHT, margins_.right);
|
gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_RIGHT, margins_.right);
|
||||||
|
|||||||
@@ -11,60 +11,60 @@
|
|||||||
#include "util/clara.hpp"
|
#include "util/clara.hpp"
|
||||||
#include "util/format.hpp"
|
#include "util/format.hpp"
|
||||||
|
|
||||||
waybar::Client *waybar::Client::inst() {
|
waybar::Client* waybar::Client::inst() {
|
||||||
static auto *c = new Client();
|
static auto* c = new Client();
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleGlobal(void *data, struct wl_registry *registry, uint32_t name,
|
void waybar::Client::handleGlobal(void* data, struct wl_registry* registry, uint32_t name,
|
||||||
const char *interface, uint32_t version) {
|
const char* interface, uint32_t version) {
|
||||||
auto *client = static_cast<Client *>(data);
|
auto* client = static_cast<Client*>(data);
|
||||||
if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 &&
|
if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 &&
|
||||||
version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) {
|
version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) {
|
||||||
client->xdg_output_manager = static_cast<struct zxdg_output_manager_v1 *>(wl_registry_bind(
|
client->xdg_output_manager = static_cast<struct zxdg_output_manager_v1*>(wl_registry_bind(
|
||||||
registry, name, &zxdg_output_manager_v1_interface, ZXDG_OUTPUT_V1_NAME_SINCE_VERSION));
|
registry, name, &zxdg_output_manager_v1_interface, ZXDG_OUTPUT_V1_NAME_SINCE_VERSION));
|
||||||
} else if (strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) == 0) {
|
} else if (strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) == 0) {
|
||||||
client->idle_inhibit_manager = static_cast<struct zwp_idle_inhibit_manager_v1 *>(
|
client->idle_inhibit_manager = static_cast<struct zwp_idle_inhibit_manager_v1*>(
|
||||||
wl_registry_bind(registry, name, &zwp_idle_inhibit_manager_v1_interface, 1));
|
wl_registry_bind(registry, name, &zwp_idle_inhibit_manager_v1_interface, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleGlobalRemove(void *data, struct wl_registry * /*registry*/,
|
void waybar::Client::handleGlobalRemove(void* data, struct wl_registry* /*registry*/,
|
||||||
uint32_t name) {
|
uint32_t name) {
|
||||||
// Nothing here
|
// Nothing here
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleOutput(struct waybar_output &output) {
|
void waybar::Client::handleOutput(struct waybar_output& output) {
|
||||||
static const struct zxdg_output_v1_listener xdgOutputListener = {
|
static const struct zxdg_output_v1_listener xdgOutputListener = {
|
||||||
.logical_position = [](void *, struct zxdg_output_v1 *, int32_t, int32_t) {},
|
.logical_position = [](void*, struct zxdg_output_v1*, int32_t, int32_t) {},
|
||||||
.logical_size = [](void *, struct zxdg_output_v1 *, int32_t, int32_t) {},
|
.logical_size = [](void*, struct zxdg_output_v1*, int32_t, int32_t) {},
|
||||||
.done = &handleOutputDone,
|
.done = &handleOutputDone,
|
||||||
.name = &handleOutputName,
|
.name = &handleOutputName,
|
||||||
.description = &handleOutputDescription,
|
.description = &handleOutputDescription,
|
||||||
};
|
};
|
||||||
// owned by output->monitor; no need to destroy
|
// owned by output->monitor; no need to destroy
|
||||||
auto *wl_output = gdk_wayland_monitor_get_wl_output(output.monitor->gobj());
|
auto* wl_output = gdk_wayland_monitor_get_wl_output(output.monitor->gobj());
|
||||||
output.xdg_output.reset(zxdg_output_manager_v1_get_xdg_output(xdg_output_manager, wl_output));
|
output.xdg_output.reset(zxdg_output_manager_v1_get_xdg_output(xdg_output_manager, wl_output));
|
||||||
zxdg_output_v1_add_listener(output.xdg_output.get(), &xdgOutputListener, &output);
|
zxdg_output_v1_add_listener(output.xdg_output.get(), &xdgOutputListener, &output);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct waybar::waybar_output &waybar::Client::getOutput(void *addr) {
|
struct waybar::waybar_output& waybar::Client::getOutput(void* addr) {
|
||||||
auto it = std::find_if(outputs_.begin(), outputs_.end(),
|
auto it = std::find_if(outputs_.begin(), outputs_.end(),
|
||||||
[&addr](const auto &output) { return &output == addr; });
|
[&addr](const auto& output) { return &output == addr; });
|
||||||
if (it == outputs_.end()) {
|
if (it == outputs_.end()) {
|
||||||
throw std::runtime_error("Unable to find valid output");
|
throw std::runtime_error("Unable to find valid output");
|
||||||
}
|
}
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Json::Value> waybar::Client::getOutputConfigs(struct waybar_output &output) {
|
std::vector<Json::Value> waybar::Client::getOutputConfigs(struct waybar_output& output) {
|
||||||
return config.getOutputConfigs(output.name, output.identifier);
|
return config.getOutputConfigs(output.name, output.identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleOutputDone(void *data, struct zxdg_output_v1 * /*xdg_output*/) {
|
void waybar::Client::handleOutputDone(void* data, struct zxdg_output_v1* /*xdg_output*/) {
|
||||||
auto *client = waybar::Client::inst();
|
auto* client = waybar::Client::inst();
|
||||||
try {
|
try {
|
||||||
auto &output = client->getOutput(data);
|
auto& output = client->getOutput(data);
|
||||||
/**
|
/**
|
||||||
* Multiple .done events may arrive in batch. In this case libwayland would queue
|
* Multiple .done events may arrive in batch. In this case libwayland would queue
|
||||||
* xdg_output.destroy and dispatch all pending events, triggering this callback several times
|
* xdg_output.destroy and dispatch all pending events, triggering this callback several times
|
||||||
@@ -80,44 +80,44 @@ void waybar::Client::handleOutputDone(void *data, struct zxdg_output_v1 * /*xdg_
|
|||||||
|
|
||||||
auto configs = client->getOutputConfigs(output);
|
auto configs = client->getOutputConfigs(output);
|
||||||
if (!configs.empty()) {
|
if (!configs.empty()) {
|
||||||
for (const auto &config : configs) {
|
for (const auto& config : configs) {
|
||||||
client->bars.emplace_back(std::make_unique<Bar>(&output, config));
|
client->bars.emplace_back(std::make_unique<Bar>(&output, config));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception& e) {
|
||||||
spdlog::warn("caught exception in zxdg_output_v1_listener::done: {}", e.what());
|
spdlog::warn("caught exception in zxdg_output_v1_listener::done: {}", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleOutputName(void *data, struct zxdg_output_v1 * /*xdg_output*/,
|
void waybar::Client::handleOutputName(void* data, struct zxdg_output_v1* /*xdg_output*/,
|
||||||
const char *name) {
|
const char* name) {
|
||||||
auto *client = waybar::Client::inst();
|
auto* client = waybar::Client::inst();
|
||||||
try {
|
try {
|
||||||
auto &output = client->getOutput(data);
|
auto& output = client->getOutput(data);
|
||||||
output.name = name;
|
output.name = name;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception& e) {
|
||||||
spdlog::warn("caught exception in zxdg_output_v1_listener::name: {}", e.what());
|
spdlog::warn("caught exception in zxdg_output_v1_listener::name: {}", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleOutputDescription(void *data, struct zxdg_output_v1 * /*xdg_output*/,
|
void waybar::Client::handleOutputDescription(void* data, struct zxdg_output_v1* /*xdg_output*/,
|
||||||
const char *description) {
|
const char* description) {
|
||||||
auto *client = waybar::Client::inst();
|
auto* client = waybar::Client::inst();
|
||||||
try {
|
try {
|
||||||
auto &output = client->getOutput(data);
|
auto& output = client->getOutput(data);
|
||||||
|
|
||||||
// Description format: "identifier (name)"
|
// Description format: "identifier (name)"
|
||||||
auto s = std::string(description);
|
auto s = std::string(description);
|
||||||
auto pos = s.find(" (");
|
auto pos = s.find(" (");
|
||||||
output.identifier = pos != std::string::npos ? s.substr(0, pos) : s;
|
output.identifier = pos != std::string::npos ? s.substr(0, pos) : s;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception& e) {
|
||||||
spdlog::warn("caught exception in zxdg_output_v1_listener::description: {}", e.what());
|
spdlog::warn("caught exception in zxdg_output_v1_listener::description: {}", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor) {
|
void waybar::Client::handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor) {
|
||||||
auto &output = outputs_.emplace_back();
|
auto& output = outputs_.emplace_back();
|
||||||
output.monitor = std::move(monitor);
|
output.monitor = std::move(monitor);
|
||||||
handleOutput(output);
|
handleOutput(output);
|
||||||
}
|
}
|
||||||
@@ -146,10 +146,10 @@ void waybar::Client::handleDeferredMonitorRemoval(Glib::RefPtr<Gdk::Monitor> mon
|
|||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outputs_.remove_if([&monitor](const auto &output) { return output.monitor == monitor; });
|
outputs_.remove_if([&monitor](const auto& output) { return output.monitor == monitor; });
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string waybar::Client::getStyle(const std::string &style,
|
const std::string waybar::Client::getStyle(const std::string& style,
|
||||||
std::optional<Appearance> appearance = std::nullopt) {
|
std::optional<Appearance> appearance = std::nullopt) {
|
||||||
auto gtk_settings = Gtk::Settings::get_default();
|
auto gtk_settings = Gtk::Settings::get_default();
|
||||||
std::optional<std::string> css_file;
|
std::optional<std::string> css_file;
|
||||||
@@ -182,7 +182,7 @@ const std::string waybar::Client::getStyle(const std::string &style,
|
|||||||
return css_file.value();
|
return css_file.value();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto waybar::Client::setupCss(const std::string &css_file) -> void {
|
auto waybar::Client::setupCss(const std::string& css_file) -> void {
|
||||||
auto screen = Gdk::Screen::get_default();
|
auto screen = Gdk::Screen::get_default();
|
||||||
if (!screen) {
|
if (!screen) {
|
||||||
throw std::runtime_error("No default screen");
|
throw std::runtime_error("No default screen");
|
||||||
@@ -219,17 +219,26 @@ void waybar::Client::bindInterfaces() {
|
|||||||
if (xdg_output_manager == nullptr) {
|
if (xdg_output_manager == nullptr) {
|
||||||
throw std::runtime_error("Failed to acquire required resources.");
|
throw std::runtime_error("Failed to acquire required resources.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disconnect previous signal handlers to prevent duplicate handlers on reload
|
||||||
|
monitor_added_connection_.disconnect();
|
||||||
|
monitor_removed_connection_.disconnect();
|
||||||
|
|
||||||
|
// Clear stale outputs from previous run
|
||||||
|
outputs_.clear();
|
||||||
|
|
||||||
// add existing outputs and subscribe to updates
|
// add existing outputs and subscribe to updates
|
||||||
for (auto i = 0; i < gdk_display->get_n_monitors(); ++i) {
|
for (auto i = 0; i < gdk_display->get_n_monitors(); ++i) {
|
||||||
auto monitor = gdk_display->get_monitor(i);
|
auto monitor = gdk_display->get_monitor(i);
|
||||||
handleMonitorAdded(monitor);
|
handleMonitorAdded(monitor);
|
||||||
}
|
}
|
||||||
gdk_display->signal_monitor_added().connect(sigc::mem_fun(*this, &Client::handleMonitorAdded));
|
monitor_added_connection_ = gdk_display->signal_monitor_added().connect(
|
||||||
gdk_display->signal_monitor_removed().connect(
|
sigc::mem_fun(*this, &Client::handleMonitorAdded));
|
||||||
|
monitor_removed_connection_ = gdk_display->signal_monitor_removed().connect(
|
||||||
sigc::mem_fun(*this, &Client::handleMonitorRemoved));
|
sigc::mem_fun(*this, &Client::handleMonitorRemoved));
|
||||||
}
|
}
|
||||||
|
|
||||||
int waybar::Client::main(int argc, char *argv[]) {
|
int waybar::Client::main(int argc, char* argv[]) {
|
||||||
bool show_help = false;
|
bool show_help = false;
|
||||||
bool show_version = false;
|
bool show_version = false;
|
||||||
std::string config_opt;
|
std::string config_opt;
|
||||||
@@ -290,7 +299,7 @@ int waybar::Client::main(int argc, char *argv[]) {
|
|||||||
if (m_config.isObject() && m_config["reload_style_on_change"].asBool()) {
|
if (m_config.isObject() && m_config["reload_style_on_change"].asBool()) {
|
||||||
m_cssReloadHelper->monitorChanges();
|
m_cssReloadHelper->monitorChanges();
|
||||||
} else if (m_config.isArray()) {
|
} else if (m_config.isArray()) {
|
||||||
for (const auto &conf : m_config) {
|
for (const auto& conf : m_config) {
|
||||||
if (conf["reload_style_on_change"].asBool()) {
|
if (conf["reload_style_on_change"].asBool()) {
|
||||||
m_cssReloadHelper->monitorChanges();
|
m_cssReloadHelper->monitorChanges();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ const std::vector<std::string> Config::CONFIG_DIRS = {
|
|||||||
"/etc/xdg/waybar/", SYSCONFDIR "/xdg/waybar/", "./resources/",
|
"/etc/xdg/waybar/", SYSCONFDIR "/xdg/waybar/", "./resources/",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *Config::CONFIG_PATH_ENV = "WAYBAR_CONFIG_DIR";
|
const char* Config::CONFIG_PATH_ENV = "WAYBAR_CONFIG_DIR";
|
||||||
|
|
||||||
std::vector<std::string> Config::tryExpandPath(const std::string &base,
|
std::vector<std::string> Config::tryExpandPath(const std::string& base,
|
||||||
const std::string &filename) {
|
const std::string& filename) {
|
||||||
fs::path path;
|
fs::path path;
|
||||||
|
|
||||||
if (!filename.empty()) {
|
if (!filename.empty()) {
|
||||||
@@ -65,18 +65,18 @@ std::vector<std::string> Config::tryExpandPath(const std::string &base,
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> Config::findConfigPath(const std::vector<std::string> &names,
|
std::optional<std::string> Config::findConfigPath(const std::vector<std::string>& names,
|
||||||
const std::vector<std::string> &dirs) {
|
const std::vector<std::string>& dirs) {
|
||||||
if (const char *dir = std::getenv(Config::CONFIG_PATH_ENV)) {
|
if (const char* dir = std::getenv(Config::CONFIG_PATH_ENV)) {
|
||||||
for (const auto &name : names) {
|
for (const auto& name : names) {
|
||||||
if (auto res = tryExpandPath(dir, name); !res.empty()) {
|
if (auto res = tryExpandPath(dir, name); !res.empty()) {
|
||||||
return res.front();
|
return res.front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &dir : dirs) {
|
for (const auto& dir : dirs) {
|
||||||
for (const auto &name : names) {
|
for (const auto& name : names) {
|
||||||
if (auto res = tryExpandPath(dir, name); !res.empty()) {
|
if (auto res = tryExpandPath(dir, name); !res.empty()) {
|
||||||
return res.front();
|
return res.front();
|
||||||
}
|
}
|
||||||
@@ -85,7 +85,7 @@ std::optional<std::string> Config::findConfigPath(const std::vector<std::string>
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::setupConfig(Json::Value &dst, const std::string &config_file, int depth) {
|
void Config::setupConfig(Json::Value& dst, const std::string& config_file, int depth) {
|
||||||
if (depth > 100) {
|
if (depth > 100) {
|
||||||
throw std::runtime_error("Aborting due to likely recursive include in config files");
|
throw std::runtime_error("Aborting due to likely recursive include in config files");
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ void Config::setupConfig(Json::Value &dst, const std::string &config_file, int d
|
|||||||
util::JsonParser parser;
|
util::JsonParser parser;
|
||||||
Json::Value tmp_config = parser.parse(str);
|
Json::Value tmp_config = parser.parse(str);
|
||||||
if (tmp_config.isArray()) {
|
if (tmp_config.isArray()) {
|
||||||
for (auto &config_part : tmp_config) {
|
for (auto& config_part : tmp_config) {
|
||||||
resolveConfigIncludes(config_part, depth);
|
resolveConfigIncludes(config_part, depth);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -106,18 +106,18 @@ void Config::setupConfig(Json::Value &dst, const std::string &config_file, int d
|
|||||||
mergeConfig(dst, tmp_config);
|
mergeConfig(dst, tmp_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Config::findIncludePath(const std::string &name,
|
std::vector<std::string> Config::findIncludePath(const std::string& name,
|
||||||
const std::vector<std::string> &dirs) {
|
const std::vector<std::string>& dirs) {
|
||||||
auto match1 = tryExpandPath(name, "");
|
auto match1 = tryExpandPath(name, "");
|
||||||
if (!match1.empty()) {
|
if (!match1.empty()) {
|
||||||
return match1;
|
return match1;
|
||||||
}
|
}
|
||||||
if (const char *dir = std::getenv(Config::CONFIG_PATH_ENV)) {
|
if (const char* dir = std::getenv(Config::CONFIG_PATH_ENV)) {
|
||||||
if (auto res = tryExpandPath(dir, name); !res.empty()) {
|
if (auto res = tryExpandPath(dir, name); !res.empty()) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto &dir : dirs) {
|
for (const auto& dir : dirs) {
|
||||||
if (auto res = tryExpandPath(dir, name); !res.empty()) {
|
if (auto res = tryExpandPath(dir, name); !res.empty()) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -126,14 +126,14 @@ std::vector<std::string> Config::findIncludePath(const std::string &name,
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::resolveConfigIncludes(Json::Value &config, int depth) {
|
void Config::resolveConfigIncludes(Json::Value& config, int depth) {
|
||||||
Json::Value includes = config["include"];
|
Json::Value includes = config["include"];
|
||||||
if (includes.isArray()) {
|
if (includes.isArray()) {
|
||||||
for (const auto &include : includes) {
|
for (const auto& include : includes) {
|
||||||
spdlog::info("Including resource file: {}", include.asString());
|
spdlog::info("Including resource file: {}", include.asString());
|
||||||
auto matches = findIncludePath(include.asString());
|
auto matches = findIncludePath(include.asString());
|
||||||
if (!matches.empty()) {
|
if (!matches.empty()) {
|
||||||
for (const auto &match : matches) {
|
for (const auto& match : matches) {
|
||||||
setupConfig(config, match, depth + 1);
|
setupConfig(config, match, depth + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -144,7 +144,7 @@ void Config::resolveConfigIncludes(Json::Value &config, int depth) {
|
|||||||
spdlog::info("Including resource file: {}", includes.asString());
|
spdlog::info("Including resource file: {}", includes.asString());
|
||||||
auto matches = findIncludePath(includes.asString());
|
auto matches = findIncludePath(includes.asString());
|
||||||
if (!matches.empty()) {
|
if (!matches.empty()) {
|
||||||
for (const auto &match : matches) {
|
for (const auto& match : matches) {
|
||||||
setupConfig(config, match, depth + 1);
|
setupConfig(config, match, depth + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -153,12 +153,12 @@ void Config::resolveConfigIncludes(Json::Value &config, int depth) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::mergeConfig(Json::Value &a_config_, Json::Value &b_config_) {
|
void Config::mergeConfig(Json::Value& a_config_, Json::Value& b_config_) {
|
||||||
if (!a_config_) {
|
if (!a_config_) {
|
||||||
// For the first config
|
// For the first config
|
||||||
a_config_ = b_config_;
|
a_config_ = b_config_;
|
||||||
} else if (a_config_.isObject() && b_config_.isObject()) {
|
} else if (a_config_.isObject() && b_config_.isObject()) {
|
||||||
for (const auto &key : b_config_.getMemberNames()) {
|
for (const auto& key : b_config_.getMemberNames()) {
|
||||||
// [] creates key with default value. Use `get` to avoid that.
|
// [] creates key with default value. Use `get` to avoid that.
|
||||||
if (a_config_.get(key, Json::Value::nullSingleton()).isObject() &&
|
if (a_config_.get(key, Json::Value::nullSingleton()).isObject() &&
|
||||||
b_config_[key].isObject()) {
|
b_config_[key].isObject()) {
|
||||||
@@ -174,10 +174,10 @@ void Config::mergeConfig(Json::Value &a_config_, Json::Value &b_config_) {
|
|||||||
spdlog::error("Cannot merge config, conflicting or invalid JSON types");
|
spdlog::error("Cannot merge config, conflicting or invalid JSON types");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool isValidOutput(const Json::Value &config, const std::string &name,
|
bool isValidOutput(const Json::Value& config, const std::string& name,
|
||||||
const std::string &identifier) {
|
const std::string& identifier) {
|
||||||
if (config["output"].isArray()) {
|
if (config["output"].isArray()) {
|
||||||
for (auto const &output_conf : config["output"]) {
|
for (auto const& output_conf : config["output"]) {
|
||||||
if (output_conf.isString()) {
|
if (output_conf.isString()) {
|
||||||
auto config_output = output_conf.asString();
|
auto config_output = output_conf.asString();
|
||||||
if (config_output.substr(0, 1) == "!") {
|
if (config_output.substr(0, 1) == "!") {
|
||||||
@@ -211,7 +211,7 @@ bool isValidOutput(const Json::Value &config, const std::string &name,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::load(const std::string &config) {
|
void Config::load(const std::string& config) {
|
||||||
auto file = config.empty() ? findConfigPath({"config", "config.jsonc"}) : config;
|
auto file = config.empty() ? findConfigPath({"config", "config.jsonc"}) : config;
|
||||||
if (!file) {
|
if (!file) {
|
||||||
throw std::runtime_error("Missing required resource files");
|
throw std::runtime_error("Missing required resource files");
|
||||||
@@ -222,11 +222,11 @@ void Config::load(const std::string &config) {
|
|||||||
setupConfig(config_, config_file_, 0);
|
setupConfig(config_, config_file_, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Json::Value> Config::getOutputConfigs(const std::string &name,
|
std::vector<Json::Value> Config::getOutputConfigs(const std::string& name,
|
||||||
const std::string &identifier) {
|
const std::string& identifier) {
|
||||||
std::vector<Json::Value> configs;
|
std::vector<Json::Value> configs;
|
||||||
if (config_.isArray()) {
|
if (config_.isArray()) {
|
||||||
for (auto const &config : config_) {
|
for (auto const& config : config_) {
|
||||||
if (config.isObject() && isValidOutput(config, name, identifier)) {
|
if (config.isObject() && isValidOutput(config, name, identifier)) {
|
||||||
configs.push_back(config);
|
configs.push_back(config);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,15 +108,13 @@
|
|||||||
#ifdef HAVE_LIBWIREPLUMBER
|
#ifdef HAVE_LIBWIREPLUMBER
|
||||||
#include "modules/wireplumber.hpp"
|
#include "modules/wireplumber.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LIBCAVA
|
|
||||||
#include "modules/cava/cava.hpp"
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYSTEMD_MONITOR
|
#ifdef HAVE_SYSTEMD_MONITOR
|
||||||
#include "modules/systemd_failed_units.hpp"
|
#include "modules/systemd_failed_units.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LIBGPS
|
#ifdef HAVE_LIBGPS
|
||||||
#include "modules/gps.hpp"
|
#include "modules/gps.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#include "modules/cava/cava_frontend.hpp"
|
||||||
#include "modules/cffi.hpp"
|
#include "modules/cffi.hpp"
|
||||||
#include "modules/custom.hpp"
|
#include "modules/custom.hpp"
|
||||||
#include "modules/image.hpp"
|
#include "modules/image.hpp"
|
||||||
@@ -341,11 +339,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
|
|||||||
return new waybar::modules::Wireplumber(id, config_[name]);
|
return new waybar::modules::Wireplumber(id, config_[name]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LIBCAVA
|
|
||||||
if (ref == "cava") {
|
if (ref == "cava") {
|
||||||
return new waybar::modules::cava::Cava(id, config_[name]);
|
return waybar::modules::cava::getModule(id, config_[name]);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYSTEMD_MONITOR
|
#ifdef HAVE_SYSTEMD_MONITOR
|
||||||
if (ref == "systemd-failed-units") {
|
if (ref == "systemd-failed-units") {
|
||||||
return new waybar::modules::SystemdFailedUnits(id, config_[name]);
|
return new waybar::modules::SystemdFailedUnits(id, config_[name]);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ Gtk::RevealerTransitionType getPreferredTransitionType(bool is_vertical) {
|
|||||||
|
|
||||||
Group::Group(const std::string& name, const std::string& id, const Json::Value& config,
|
Group::Group(const std::string& name, const std::string& id, const Json::Value& config,
|
||||||
bool vertical)
|
bool vertical)
|
||||||
: AModule(config, name, id, true, true),
|
: AModule(config, name, id, true, false),
|
||||||
box{vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0},
|
box{vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0},
|
||||||
revealer_box{vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0} {
|
revealer_box{vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0} {
|
||||||
box.set_name(name_);
|
box.set_name(name_);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include "util/backend_common.hpp"
|
#include "util/backend_common.hpp"
|
||||||
#include "util/backlight_backend.hpp"
|
#include "util/backlight_backend.hpp"
|
||||||
|
|
||||||
waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value &config)
|
waybar::modules::Backlight::Backlight(const std::string& id, const Json::Value& config)
|
||||||
: ALabel(config, "backlight", id, "{percent}%", 2),
|
: ALabel(config, "backlight", id, "{percent}%", 2),
|
||||||
preferred_device_(config["device"].isString() ? config["device"].asString() : ""),
|
preferred_device_(config["device"].isString() ? config["device"].asString() : ""),
|
||||||
backend(interval_, [this] { dp.emit(); }) {
|
backend(interval_, [this] { dp.emit(); }) {
|
||||||
@@ -58,11 +58,11 @@ auto waybar::modules::Backlight::update() -> void {
|
|||||||
tooltip_format = config_["tooltip-format"].asString();
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
}
|
}
|
||||||
if (!tooltip_format.empty()) {
|
if (!tooltip_format.empty()) {
|
||||||
label_.set_tooltip_text(fmt::format(fmt::runtime(tooltip_format),
|
label_.set_tooltip_markup(fmt::format(fmt::runtime(tooltip_format),
|
||||||
fmt::arg("percent", percent),
|
fmt::arg("percent", percent),
|
||||||
fmt::arg("icon", getIcon(percent))));
|
fmt::arg("icon", getIcon(percent))));
|
||||||
} else {
|
} else {
|
||||||
label_.set_tooltip_text(desc);
|
label_.set_tooltip_markup(desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -79,7 +79,7 @@ auto waybar::modules::Backlight::update() -> void {
|
|||||||
ALabel::update();
|
ALabel::update();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waybar::modules::Backlight::handleScroll(GdkEventScroll *e) {
|
bool waybar::modules::Backlight::handleScroll(GdkEventScroll* e) {
|
||||||
// Check if the user has set a custom command for scrolling
|
// Check if the user has set a custom command for scrolling
|
||||||
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) {
|
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) {
|
||||||
return AModule::handleScroll(e);
|
return AModule::handleScroll(e);
|
||||||
|
|||||||
@@ -7,7 +7,10 @@
|
|||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <sys/signalfd.h>
|
||||||
|
|
||||||
waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const Json::Value& config)
|
waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||||
: ALabel(config, "battery", id, "{capacity}%", 60), last_event_(""), bar_(bar) {
|
: ALabel(config, "battery", id, "{capacity}%", 60), last_event_(""), bar_(bar) {
|
||||||
@@ -16,17 +19,21 @@ waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const J
|
|||||||
if (battery_watch_fd_ == -1) {
|
if (battery_watch_fd_ == -1) {
|
||||||
throw std::runtime_error("Unable to listen batteries.");
|
throw std::runtime_error("Unable to listen batteries.");
|
||||||
}
|
}
|
||||||
|
udev_ = std::unique_ptr<udev, util::UdevDeleter>(udev_new());
|
||||||
global_watch_fd_ = inotify_init1(IN_CLOEXEC);
|
if (udev_ == nullptr) {
|
||||||
if (global_watch_fd_ == -1) {
|
throw std::runtime_error("udev_new failed");
|
||||||
throw std::runtime_error("Unable to listen batteries.");
|
|
||||||
}
|
}
|
||||||
|
mon_ = std::unique_ptr<udev_monitor, util::UdevMonitorDeleter>(
|
||||||
// Watch the directory for any added or removed batteries
|
udev_monitor_new_from_netlink(udev_.get(), "kernel"));
|
||||||
global_watch = inotify_add_watch(global_watch_fd_, data_dir_.c_str(), IN_CREATE | IN_DELETE);
|
if (mon_ == nullptr) {
|
||||||
if (global_watch < 0) {
|
throw std::runtime_error("udev monitor new failed");
|
||||||
throw std::runtime_error("Could not watch for battery plug/unplug");
|
|
||||||
}
|
}
|
||||||
|
if (udev_monitor_filter_add_match_subsystem_devtype(mon_.get(), "power_supply", nullptr) < 0) {
|
||||||
|
throw std::runtime_error("udev failed to add monitor filter");
|
||||||
|
}
|
||||||
|
udev_monitor_enable_receiving(mon_.get());
|
||||||
|
|
||||||
|
if (config_["weighted-average"].isBool()) weightedAverage_ = config_["weighted-average"].asBool();
|
||||||
#endif
|
#endif
|
||||||
spdlog::debug("battery: worker interval is {}", interval_.count());
|
spdlog::debug("battery: worker interval is {}", interval_.count());
|
||||||
worker();
|
worker();
|
||||||
@@ -36,11 +43,6 @@ waybar::modules::Battery::~Battery() {
|
|||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
std::lock_guard<std::mutex> guard(battery_list_mutex_);
|
std::lock_guard<std::mutex> guard(battery_list_mutex_);
|
||||||
|
|
||||||
if (global_watch >= 0) {
|
|
||||||
inotify_rm_watch(global_watch_fd_, global_watch);
|
|
||||||
}
|
|
||||||
close(global_watch_fd_);
|
|
||||||
|
|
||||||
for (auto it = batteries_.cbegin(), next_it = it; it != batteries_.cend(); it = next_it) {
|
for (auto it = batteries_.cbegin(), next_it = it; it != batteries_.cend(); it = next_it) {
|
||||||
++next_it;
|
++next_it;
|
||||||
auto watch_id = (*it).second;
|
auto watch_id = (*it).second;
|
||||||
@@ -77,12 +79,18 @@ void waybar::modules::Battery::worker() {
|
|||||||
dp.emit();
|
dp.emit();
|
||||||
};
|
};
|
||||||
thread_battery_update_ = [this] {
|
thread_battery_update_ = [this] {
|
||||||
struct inotify_event event = {0};
|
poll_fds_[0].revents = 0;
|
||||||
int nbytes = read(global_watch_fd_, &event, sizeof(event));
|
poll_fds_[0].events = POLLIN;
|
||||||
if (nbytes != sizeof(event) || event.mask & IN_IGNORED) {
|
poll_fds_[0].fd = udev_monitor_get_fd(mon_.get());
|
||||||
|
int ret = poll(poll_fds_.data(), poll_fds_.size(), -1);
|
||||||
|
if (ret < 0) {
|
||||||
thread_.stop();
|
thread_.stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if ((poll_fds_[0].revents & POLLIN) != 0) {
|
||||||
|
signalfd_siginfo signal_info;
|
||||||
|
read(poll_fds_[0].fd, &signal_info, sizeof(signal_info));
|
||||||
|
}
|
||||||
refreshBatteries();
|
refreshBatteries();
|
||||||
dp.emit();
|
dp.emit();
|
||||||
};
|
};
|
||||||
@@ -585,8 +593,7 @@ waybar::modules::Battery::getInfos() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle weighted-average
|
// Handle weighted-average
|
||||||
if ((config_["weighted-average"].isBool() ? config_["weighted-average"].asBool() : false) &&
|
if (weightedAverage_ && total_energy_exists && total_energy_full_exists) {
|
||||||
total_energy_exists && total_energy_full_exists) {
|
|
||||||
if (total_energy_full > 0.0f)
|
if (total_energy_full > 0.0f)
|
||||||
calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full);
|
calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full);
|
||||||
}
|
}
|
||||||
@@ -679,6 +686,7 @@ auto waybar::modules::Battery::update() -> void {
|
|||||||
status = getAdapterStatus(capacity);
|
status = getAdapterStatus(capacity);
|
||||||
}
|
}
|
||||||
auto status_pretty = status;
|
auto status_pretty = status;
|
||||||
|
|
||||||
// Transform to lowercase and replace space with dash
|
// Transform to lowercase and replace space with dash
|
||||||
std::ranges::transform(status.begin(), status.end(), status.begin(),
|
std::ranges::transform(status.begin(), status.end(), status.begin(),
|
||||||
[](char ch) { return ch == ' ' ? '-' : std::tolower(ch); });
|
[](char ch) { return ch == ' ' ? '-' : std::tolower(ch); });
|
||||||
@@ -782,16 +790,19 @@ void waybar::modules::Battery::processEvents(std::string& state, std::string& st
|
|||||||
if (!events.isObject() || events.empty()) {
|
if (!events.isObject() || events.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string event_name = fmt::format("on-{}-{}", status == "discharging" ? status : "charging",
|
auto exec = [](Json::Value const& event) {
|
||||||
state.empty() ? std::to_string(capacity) : state);
|
if (!event.isString()) return;
|
||||||
|
if (auto command = event.asString(); !command.empty()) {
|
||||||
|
util::command::exec(command, "");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::string status_name = status == "discharging" ? "on-discharging" : "on-charging";
|
||||||
|
std::string event_name = status_name + '-' + (state.empty() ? std::to_string(capacity) : state);
|
||||||
if (last_event_ != event_name) {
|
if (last_event_ != event_name) {
|
||||||
spdlog::debug("battery: triggering event {}", event_name);
|
spdlog::debug("battery: triggering event {}", event_name);
|
||||||
if (events[event_name].isString()) {
|
exec(events[event_name]);
|
||||||
std::string exec = events[event_name].asString();
|
if (!last_event_.empty() && last_event_[3] != event_name[3]) {
|
||||||
// Execute the command if it is not empty
|
exec(events[status_name]);
|
||||||
if (!exec.empty()) {
|
|
||||||
util::command::exec(exec, "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
last_event_ = event_name;
|
last_event_ = event_name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ auto waybar::modules::Bluetooth::update() -> void {
|
|||||||
device_enumerate_.erase(0, 1);
|
device_enumerate_.erase(0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
label_.set_tooltip_text(fmt::format(
|
label_.set_tooltip_markup(fmt::format(
|
||||||
fmt::runtime(tooltip_format), fmt::arg("status", state_),
|
fmt::runtime(tooltip_format), fmt::arg("status", state_),
|
||||||
fmt::arg("num_connections", connected_devices_.size()),
|
fmt::arg("num_connections", connected_devices_.size()),
|
||||||
fmt::arg("controller_address", cur_controller_ ? cur_controller_->address : "null"),
|
fmt::arg("controller_address", cur_controller_ ? cur_controller_->address : "null"),
|
||||||
|
|||||||
271
src/modules/cava/cavaGLSL.cpp
Normal file
271
src/modules/cava/cavaGLSL.cpp
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
#include "modules/cava/cavaGLSL.hpp"
|
||||||
|
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
waybar::modules::cava::CavaGLSL::CavaGLSL(const std::string& id, const Json::Value& config)
|
||||||
|
: AModule(config, "cavaGLSL", id, false, false),
|
||||||
|
backend_{waybar::modules::cava::CavaBackend::inst(config)} {
|
||||||
|
set_name(name_);
|
||||||
|
if (config_["hide_on_silence"].isBool()) hide_on_silence_ = config_["hide_on_silence"].asBool();
|
||||||
|
if (!id.empty()) {
|
||||||
|
get_style_context()->add_class(id);
|
||||||
|
}
|
||||||
|
get_style_context()->add_class(MODULE_CLASS);
|
||||||
|
|
||||||
|
set_use_es(true);
|
||||||
|
// set_auto_render(true);
|
||||||
|
signal_realize().connect(sigc::mem_fun(*this, &CavaGLSL::onRealize));
|
||||||
|
signal_render().connect(sigc::mem_fun(*this, &CavaGLSL::onRender), false);
|
||||||
|
|
||||||
|
// Get parameters_config struct from the backend
|
||||||
|
prm_ = *backend_->getPrm();
|
||||||
|
|
||||||
|
// Set widget length
|
||||||
|
int length{0};
|
||||||
|
if (config_["min-length"].isUInt())
|
||||||
|
length = config_["min-length"].asUInt();
|
||||||
|
else if (config_["max-length"].isUInt())
|
||||||
|
length = config_["max-length"].asUInt();
|
||||||
|
else
|
||||||
|
length = prm_.sdl_width;
|
||||||
|
|
||||||
|
set_size_request(length, prm_.sdl_height);
|
||||||
|
|
||||||
|
// Subscribe for changes
|
||||||
|
backend_->signal_audio_raw_update().connect(sigc::mem_fun(*this, &CavaGLSL::onUpdate));
|
||||||
|
// Subscribe for silence
|
||||||
|
backend_->signal_silence().connect(sigc::mem_fun(*this, &CavaGLSL::onSilence));
|
||||||
|
event_box_.add(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto waybar::modules::cava::CavaGLSL::onUpdate(const ::cava::audio_raw& input) -> void {
|
||||||
|
Glib::signal_idle().connect_once([this, input]() {
|
||||||
|
m_data_ = std::make_shared<::cava::audio_raw>(input);
|
||||||
|
if (silence_) {
|
||||||
|
get_style_context()->remove_class("silent");
|
||||||
|
if (!get_style_context()->has_class("updated")) get_style_context()->add_class("updated");
|
||||||
|
show();
|
||||||
|
silence_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto waybar::modules::cava::CavaGLSL::onSilence() -> void {
|
||||||
|
Glib::signal_idle().connect_once([this]() {
|
||||||
|
if (!silence_) {
|
||||||
|
if (get_style_context()->has_class("updated")) get_style_context()->remove_class("updated");
|
||||||
|
|
||||||
|
if (hide_on_silence_) hide();
|
||||||
|
silence_ = true;
|
||||||
|
get_style_context()->add_class("silent");
|
||||||
|
// Set clear color to black
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
queue_render();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool waybar::modules::cava::CavaGLSL::onRender(const Glib::RefPtr<Gdk::GLContext>& context) {
|
||||||
|
if (!m_data_) return true;
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_);
|
||||||
|
glUniform1i(glGetUniformLocation(shaderProgram_, "inputTexture"), 0);
|
||||||
|
|
||||||
|
glUniform1fv(uniform_bars_, m_data_->number_of_bars, m_data_->bars_raw);
|
||||||
|
glUniform1fv(uniform_previous_bars_, m_data_->number_of_bars, m_data_->previous_bars_raw);
|
||||||
|
glUniform1i(uniform_bars_count_, m_data_->number_of_bars);
|
||||||
|
++frame_counter;
|
||||||
|
glUniform1f(uniform_time_, (frame_counter / backend_->getFrameTimeMilsec().count()) / 1e3);
|
||||||
|
|
||||||
|
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, nullptr);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
|
||||||
|
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, nullptr);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void waybar::modules::cava::CavaGLSL::onRealize() {
|
||||||
|
make_current();
|
||||||
|
initShaders();
|
||||||
|
initGLSL();
|
||||||
|
initSurface();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct colors {
|
||||||
|
uint16_t R;
|
||||||
|
uint16_t G;
|
||||||
|
uint16_t B;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void parse_color(char* color_string, struct colors* color) {
|
||||||
|
if (color_string[0] == '#') {
|
||||||
|
sscanf(++color_string, "%02hx%02hx%02hx", &color->R, &color->G, &color->B);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void waybar::modules::cava::CavaGLSL::initGLSL() {
|
||||||
|
GLint gVertexPos2DLocation{glGetAttribLocation(shaderProgram_, "vertexPosition_modelspace")};
|
||||||
|
if (gVertexPos2DLocation == -1) {
|
||||||
|
spdlog::error("{0}. Could not find vertex position shader variable", name_);
|
||||||
|
}
|
||||||
|
|
||||||
|
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||||
|
|
||||||
|
GLfloat vertexData[]{-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f};
|
||||||
|
GLint indexData[]{0, 1, 2, 3};
|
||||||
|
|
||||||
|
GLuint gVBO{0};
|
||||||
|
glGenBuffers(1, &gVBO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, gVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), vertexData, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
GLuint gIBO{0};
|
||||||
|
glGenBuffers(1, &gIBO);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLuint), indexData, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
GLuint gVAO{0};
|
||||||
|
glGenVertexArrays(1, &gVAO);
|
||||||
|
glBindVertexArray(gVAO);
|
||||||
|
glEnableVertexAttribArray(gVertexPos2DLocation);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, gVBO);
|
||||||
|
glVertexAttribPointer(gVertexPos2DLocation, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIBO);
|
||||||
|
|
||||||
|
glGenFramebuffers(1, &fbo_);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
|
||||||
|
|
||||||
|
// Create a texture to attach the framebuffer
|
||||||
|
glGenTextures(1, &texture_);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, prm_.sdl_width, prm_.sdl_height, 0, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_, 0);
|
||||||
|
|
||||||
|
// Check is framebuffer is complete
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
spdlog::error("{0}. Framebuffer not complete", name_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unbind the framebuffer
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
uniform_bars_ = glGetUniformLocation(shaderProgram_, "bars");
|
||||||
|
uniform_previous_bars_ = glGetUniformLocation(shaderProgram_, "previous_bars");
|
||||||
|
uniform_bars_count_ = glGetUniformLocation(shaderProgram_, "bars_count");
|
||||||
|
uniform_time_ = glGetUniformLocation(shaderProgram_, "shader_time");
|
||||||
|
|
||||||
|
GLuint err{glGetError()};
|
||||||
|
if (err != 0) {
|
||||||
|
spdlog::error("{0}. Error on initGLSL: {1}", name_, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void waybar::modules::cava::CavaGLSL::initSurface() {
|
||||||
|
colors color = {0};
|
||||||
|
GLint uniform_bg_col{glGetUniformLocation(shaderProgram_, "bg_color")};
|
||||||
|
parse_color(prm_.bcolor, &color);
|
||||||
|
glUniform3f(uniform_bg_col, (float)color.R / 255.0, (float)color.G / 255.0,
|
||||||
|
(float)color.B / 255.0);
|
||||||
|
GLint uniform_fg_col{glGetUniformLocation(shaderProgram_, "fg_color")};
|
||||||
|
parse_color(prm_.color, &color);
|
||||||
|
glUniform3f(uniform_fg_col, (float)color.R / 255.0, (float)color.G / 255.0,
|
||||||
|
(float)color.B / 255.0);
|
||||||
|
GLint uniform_res{glGetUniformLocation(shaderProgram_, "u_resolution")};
|
||||||
|
glUniform3f(uniform_res, (float)prm_.sdl_width, (float)prm_.sdl_height, 0.0f);
|
||||||
|
GLint uniform_bar_width{glGetUniformLocation(shaderProgram_, "bar_width")};
|
||||||
|
glUniform1i(uniform_bar_width, prm_.bar_width);
|
||||||
|
GLint uniform_bar_spacing{glGetUniformLocation(shaderProgram_, "bar_spacing")};
|
||||||
|
glUniform1i(uniform_bar_spacing, prm_.bar_spacing);
|
||||||
|
GLint uniform_gradient_count{glGetUniformLocation(shaderProgram_, "gradient_count")};
|
||||||
|
glUniform1i(uniform_gradient_count, prm_.gradient_count);
|
||||||
|
GLint uniform_gradient_colors{glGetUniformLocation(shaderProgram_, "gradient_colors")};
|
||||||
|
GLfloat gradient_colors[8][3];
|
||||||
|
for (int i{0}; i < prm_.gradient_count; ++i) {
|
||||||
|
parse_color(prm_.gradient_colors[i], &color);
|
||||||
|
gradient_colors[i][0] = (float)color.R / 255.0;
|
||||||
|
gradient_colors[i][1] = (float)color.G / 255.0;
|
||||||
|
gradient_colors[i][2] = (float)color.B / 255.0;
|
||||||
|
}
|
||||||
|
glUniform3fv(uniform_gradient_colors, 8, (const GLfloat*)gradient_colors);
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void waybar::modules::cava::CavaGLSL::initShaders() {
|
||||||
|
shaderProgram_ = glCreateProgram();
|
||||||
|
|
||||||
|
GLuint vertexShader{loadShader(prm_.vertex_shader, GL_VERTEX_SHADER)};
|
||||||
|
GLuint fragmentShader{loadShader(prm_.fragment_shader, GL_FRAGMENT_SHADER)};
|
||||||
|
|
||||||
|
glAttachShader(shaderProgram_, vertexShader);
|
||||||
|
glAttachShader(shaderProgram_, fragmentShader);
|
||||||
|
|
||||||
|
glLinkProgram(shaderProgram_);
|
||||||
|
|
||||||
|
glDeleteShader(vertexShader);
|
||||||
|
glDeleteShader(fragmentShader);
|
||||||
|
|
||||||
|
// Check for linking errors
|
||||||
|
GLint success, len;
|
||||||
|
glGetProgramiv(shaderProgram_, GL_LINK_STATUS, &success);
|
||||||
|
if (!success) {
|
||||||
|
glGetProgramiv(shaderProgram_, GL_INFO_LOG_LENGTH, &len);
|
||||||
|
GLchar* infoLog{(char*)'\0'};
|
||||||
|
glGetProgramInfoLog(shaderProgram_, len, &len, infoLog);
|
||||||
|
spdlog::error("{0}. Shader linking error: {1}", name_, infoLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
glReleaseShaderCompiler();
|
||||||
|
glUseProgram(shaderProgram_);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint waybar::modules::cava::CavaGLSL::loadShader(const std::string& fileName, GLenum type) {
|
||||||
|
spdlog::debug("{0}. loadShader: {1}", name_, fileName);
|
||||||
|
|
||||||
|
// Read shader source code from the file
|
||||||
|
std::ifstream shaderFile{fileName};
|
||||||
|
|
||||||
|
if (!shaderFile.is_open()) {
|
||||||
|
spdlog::error("{0}. Could not open shader file: {1}", name_, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream buffer;
|
||||||
|
buffer << shaderFile.rdbuf(); // read file content into stringstream
|
||||||
|
std::string str{buffer.str()};
|
||||||
|
const char* shaderSource = str.c_str();
|
||||||
|
shaderFile.close();
|
||||||
|
|
||||||
|
GLuint shaderID{glCreateShader(type)};
|
||||||
|
if (shaderID == 0) spdlog::error("{0}. Error creating shader type: {0}", type);
|
||||||
|
glShaderSource(shaderID, 1, &shaderSource, nullptr);
|
||||||
|
glCompileShader(shaderID);
|
||||||
|
|
||||||
|
// Check for compilation errors
|
||||||
|
GLint success, len;
|
||||||
|
|
||||||
|
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &len);
|
||||||
|
|
||||||
|
GLchar* infoLog{(char*)'\0'};
|
||||||
|
glGetShaderInfoLog(shaderID, len, nullptr, infoLog);
|
||||||
|
spdlog::error("{0}. Shader compilation error in {1}: {2}", name_, fileName, infoLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shaderID;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "modules/cava/cava.hpp"
|
#include "modules/cava/cavaRaw.hpp"
|
||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
@@ -24,28 +24,37 @@ auto waybar::modules::cava::Cava::doAction(const std::string& name) -> void {
|
|||||||
// Cava actions
|
// Cava actions
|
||||||
void waybar::modules::cava::Cava::pause_resume() { backend_->doPauseResume(); }
|
void waybar::modules::cava::Cava::pause_resume() { backend_->doPauseResume(); }
|
||||||
auto waybar::modules::cava::Cava::onUpdate(const std::string& input) -> void {
|
auto waybar::modules::cava::Cava::onUpdate(const std::string& input) -> void {
|
||||||
if (silence_) {
|
Glib::signal_idle().connect_once([this, input]() {
|
||||||
label_.get_style_context()->remove_class("silent");
|
if (silence_) {
|
||||||
label_.get_style_context()->add_class("updated");
|
silence_ = false;
|
||||||
}
|
label_.get_style_context()->remove_class("silent");
|
||||||
label_text_.clear();
|
if (!label_.get_style_context()->has_class("updated"))
|
||||||
for (auto& ch : input)
|
label_.get_style_context()->add_class("updated");
|
||||||
label_text_.append(getIcon((ch > ascii_range_) ? ascii_range_ : ch, "", ascii_range_ + 1));
|
}
|
||||||
|
label_text_.clear();
|
||||||
|
for (auto& ch : input)
|
||||||
|
label_text_.append(getIcon((ch > ascii_range_) ? ascii_range_ : ch, "", ascii_range_ + 1));
|
||||||
|
|
||||||
label_.set_markup(label_text_);
|
label_.set_markup(label_text_);
|
||||||
label_.show();
|
label_.show();
|
||||||
ALabel::update();
|
ALabel::update();
|
||||||
silence_ = false;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::cava::Cava::onSilence() -> void {
|
auto waybar::modules::cava::Cava::onSilence() -> void {
|
||||||
if (!silence_) {
|
Glib::signal_idle().connect_once([this]() {
|
||||||
label_.get_style_context()->remove_class("updated");
|
if (!silence_) {
|
||||||
|
if (label_.get_style_context()->has_class("updated"))
|
||||||
|
label_.get_style_context()->remove_class("updated");
|
||||||
|
|
||||||
if (hide_on_silence_)
|
if (hide_on_silence_) {
|
||||||
label_.hide();
|
// Clear the label markup before hiding to prevent GTK from rendering a NULL Pango layout
|
||||||
else if (config_["format_silent"].isString())
|
label_.set_markup("");
|
||||||
label_.set_markup(format_silent_);
|
label_.hide();
|
||||||
silence_ = true;
|
} else if (config_["format_silent"].isString())
|
||||||
label_.get_style_context()->add_class("silent");
|
label_.set_markup(format_silent_);
|
||||||
}
|
silence_ = true;
|
||||||
|
label_.get_style_context()->add_class("silent");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
@@ -9,91 +9,9 @@ std::shared_ptr<waybar::modules::cava::CavaBackend> waybar::modules::cava::CavaB
|
|||||||
return backend_ptr;
|
return backend_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
waybar::modules::cava::CavaBackend::CavaBackend(const Json::Value& config) {
|
waybar::modules::cava::CavaBackend::CavaBackend(const Json::Value& config) : config_(config) {
|
||||||
// Load waybar module config
|
// Load waybar module config
|
||||||
char cfgPath[PATH_MAX];
|
loadConfig();
|
||||||
cfgPath[0] = '\0';
|
|
||||||
|
|
||||||
if (config["cava_config"].isString()) strcpy(cfgPath, config["cava_config"].asString().data());
|
|
||||||
// Load cava config
|
|
||||||
error_.length = 0;
|
|
||||||
|
|
||||||
if (!load_config(cfgPath, &prm_, false, &error_, 0)) {
|
|
||||||
spdlog::error("cava backend. Error loading config. {0}", error_.message);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override cava parameters by the user config
|
|
||||||
prm_.inAtty = 0;
|
|
||||||
prm_.output = ::cava::output_method::OUTPUT_RAW;
|
|
||||||
if (prm_.data_format) free(prm_.data_format);
|
|
||||||
prm_.data_format = strdup("ascii");
|
|
||||||
if (prm_.raw_target) free(prm_.raw_target);
|
|
||||||
prm_.raw_target = strdup("/dev/stdout");
|
|
||||||
prm_.ascii_range = config["format-icons"].size() - 1;
|
|
||||||
|
|
||||||
prm_.bar_width = 2;
|
|
||||||
prm_.bar_spacing = 0;
|
|
||||||
prm_.bar_height = 32;
|
|
||||||
prm_.bar_width = 1;
|
|
||||||
prm_.orientation = ::cava::ORIENT_TOP;
|
|
||||||
prm_.xaxis = ::cava::xaxis_scale::NONE;
|
|
||||||
prm_.mono_opt = ::cava::AVERAGE;
|
|
||||||
prm_.autobars = 0;
|
|
||||||
prm_.gravity = 0;
|
|
||||||
prm_.integral = 1;
|
|
||||||
|
|
||||||
if (config["framerate"].isInt()) prm_.framerate = config["framerate"].asInt();
|
|
||||||
// Calculate delay for Update() thread
|
|
||||||
frame_time_milsec_ = std::chrono::milliseconds((int)(1e3 / prm_.framerate));
|
|
||||||
if (config["autosens"].isInt()) prm_.autosens = config["autosens"].asInt();
|
|
||||||
if (config["sensitivity"].isInt()) prm_.sens = config["sensitivity"].asInt();
|
|
||||||
if (config["bars"].isInt()) prm_.fixedbars = config["bars"].asInt();
|
|
||||||
if (config["lower_cutoff_freq"].isNumeric())
|
|
||||||
prm_.lower_cut_off = config["lower_cutoff_freq"].asLargestInt();
|
|
||||||
if (config["higher_cutoff_freq"].isNumeric())
|
|
||||||
prm_.upper_cut_off = config["higher_cutoff_freq"].asLargestInt();
|
|
||||||
if (config["sleep_timer"].isInt()) prm_.sleep_timer = config["sleep_timer"].asInt();
|
|
||||||
if (config["method"].isString())
|
|
||||||
prm_.input = ::cava::input_method_by_name(config["method"].asString().c_str());
|
|
||||||
if (config["source"].isString()) {
|
|
||||||
if (prm_.audio_source) free(prm_.audio_source);
|
|
||||||
prm_.audio_source = config["source"].asString().data();
|
|
||||||
}
|
|
||||||
if (config["sample_rate"].isNumeric()) prm_.samplerate = config["sample_rate"].asLargestInt();
|
|
||||||
if (config["sample_bits"].isInt()) prm_.samplebits = config["sample_bits"].asInt();
|
|
||||||
if (config["stereo"].isBool()) prm_.stereo = config["stereo"].asBool();
|
|
||||||
if (config["reverse"].isBool()) prm_.reverse = config["reverse"].asBool();
|
|
||||||
if (config["bar_delimiter"].isInt()) prm_.bar_delim = config["bar_delimiter"].asInt();
|
|
||||||
if (config["monstercat"].isBool()) prm_.monstercat = config["monstercat"].asBool();
|
|
||||||
if (config["waves"].isBool()) prm_.waves = config["waves"].asBool();
|
|
||||||
if (config["noise_reduction"].isDouble())
|
|
||||||
prm_.noise_reduction = config["noise_reduction"].asDouble();
|
|
||||||
if (config["input_delay"].isInt())
|
|
||||||
fetch_input_delay_ = std::chrono::seconds(config["input_delay"].asInt());
|
|
||||||
|
|
||||||
audio_raw_.height = prm_.ascii_range;
|
|
||||||
audio_data_.format = -1;
|
|
||||||
audio_data_.rate = 0;
|
|
||||||
audio_data_.samples_counter = 0;
|
|
||||||
audio_data_.channels = 2;
|
|
||||||
audio_data_.IEEE_FLOAT = 0;
|
|
||||||
audio_data_.input_buffer_size = BUFFER_SIZE * audio_data_.channels;
|
|
||||||
audio_data_.cava_buffer_size = audio_data_.input_buffer_size * 8;
|
|
||||||
audio_data_.terminate = 0;
|
|
||||||
audio_data_.suspendFlag = false;
|
|
||||||
input_source_ = get_input(&audio_data_, &prm_);
|
|
||||||
|
|
||||||
if (!input_source_) {
|
|
||||||
spdlog::error("cava backend API didn't provide input audio source method");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make cava parameters configuration
|
|
||||||
// Init cava plan, audio_raw structure
|
|
||||||
audio_raw_init(&audio_data_, &audio_raw_, &prm_, &plan_);
|
|
||||||
if (!plan_) spdlog::error("cava backend plan is not provided");
|
|
||||||
audio_raw_.previous_frame[0] = -1; // For first Update() call need to rePaint text message
|
|
||||||
// Read audio source trough cava API. Cava orginizes this process via infinity loop
|
// Read audio source trough cava API. Cava orginizes this process via infinity loop
|
||||||
read_thread_ = [this] {
|
read_thread_ = [this] {
|
||||||
try {
|
try {
|
||||||
@@ -102,41 +20,38 @@ waybar::modules::cava::CavaBackend::CavaBackend(const Json::Value& config) {
|
|||||||
spdlog::warn("Cava backend. Read source error: {0}", e.what());
|
spdlog::warn("Cava backend. Read source error: {0}", e.what());
|
||||||
}
|
}
|
||||||
read_thread_.sleep_for(fetch_input_delay_);
|
read_thread_.sleep_for(fetch_input_delay_);
|
||||||
|
loadConfig();
|
||||||
};
|
};
|
||||||
|
// Write outcoming data. Emit signals
|
||||||
thread_ = [this] {
|
out_thread_ = [this] {
|
||||||
doUpdate();
|
doUpdate(false);
|
||||||
thread_.sleep_for(frame_time_milsec_);
|
out_thread_.sleep_for(frame_time_milsec_);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
waybar::modules::cava::CavaBackend::~CavaBackend() {
|
waybar::modules::cava::CavaBackend::~CavaBackend() {
|
||||||
thread_.stop();
|
out_thread_.stop();
|
||||||
read_thread_.stop();
|
read_thread_.stop();
|
||||||
cava_destroy(plan_);
|
|
||||||
delete plan_;
|
freeBackend();
|
||||||
plan_ = nullptr;
|
|
||||||
audio_raw_clean(&audio_raw_);
|
|
||||||
pthread_mutex_lock(&audio_data_.lock);
|
|
||||||
audio_data_.terminate = 1;
|
|
||||||
pthread_mutex_unlock(&audio_data_.lock);
|
|
||||||
config_clean(&prm_);
|
|
||||||
free(audio_data_.source);
|
|
||||||
free(audio_data_.cava_in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void upThreadDelay(std::chrono::milliseconds& delay, std::chrono::seconds& delta) {
|
static bool upThreadDelay(std::chrono::milliseconds& delay, std::chrono::seconds& delta) {
|
||||||
if (delta == std::chrono::seconds{0}) {
|
if (delta == std::chrono::seconds{0}) {
|
||||||
delta += std::chrono::seconds{1};
|
delta += std::chrono::seconds{1};
|
||||||
delay += delta;
|
delay += delta;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void downThreadDelay(std::chrono::milliseconds& delay, std::chrono::seconds& delta) {
|
static bool downThreadDelay(std::chrono::milliseconds& delay, std::chrono::seconds& delta) {
|
||||||
if (delta > std::chrono::seconds{0}) {
|
if (delta > std::chrono::seconds{0}) {
|
||||||
delay -= delta;
|
delay -= delta;
|
||||||
delta -= std::chrono::seconds{1};
|
delta -= std::chrono::seconds{1};
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waybar::modules::cava::CavaBackend::isSilence() {
|
bool waybar::modules::cava::CavaBackend::isSilence() {
|
||||||
@@ -186,6 +101,7 @@ void waybar::modules::cava::CavaBackend::doPauseResume() {
|
|||||||
upThreadDelay(frame_time_milsec_, suspend_silence_delay_);
|
upThreadDelay(frame_time_milsec_, suspend_silence_delay_);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&audio_data_.lock);
|
pthread_mutex_unlock(&audio_data_.lock);
|
||||||
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
waybar::modules::cava::CavaBackend::type_signal_update
|
waybar::modules::cava::CavaBackend::type_signal_update
|
||||||
@@ -193,6 +109,11 @@ waybar::modules::cava::CavaBackend::signal_update() {
|
|||||||
return m_signal_update_;
|
return m_signal_update_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
waybar::modules::cava::CavaBackend::type_signal_audio_raw_update
|
||||||
|
waybar::modules::cava::CavaBackend::signal_audio_raw_update() {
|
||||||
|
return m_signal_audio_raw_;
|
||||||
|
}
|
||||||
|
|
||||||
waybar::modules::cava::CavaBackend::type_signal_silence
|
waybar::modules::cava::CavaBackend::type_signal_silence
|
||||||
waybar::modules::cava::CavaBackend::signal_silence() {
|
waybar::modules::cava::CavaBackend::signal_silence() {
|
||||||
return m_signal_silence_;
|
return m_signal_silence_;
|
||||||
@@ -215,12 +136,138 @@ void waybar::modules::cava::CavaBackend::doUpdate(bool force) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!silence_ || prm_.sleep_timer == 0) {
|
if (!silence_ || prm_.sleep_timer == 0) {
|
||||||
downThreadDelay(frame_time_milsec_, suspend_silence_delay_);
|
if (downThreadDelay(frame_time_milsec_, suspend_silence_delay_)) Update();
|
||||||
execute();
|
execute();
|
||||||
if (re_paint_ == 1 || force) m_signal_update_.emit(output_);
|
if (re_paint_ == 1 || force || prm_.continuous_rendering) {
|
||||||
|
m_signal_update_.emit(output_);
|
||||||
|
m_signal_audio_raw_.emit(audio_raw_);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
upThreadDelay(frame_time_milsec_, suspend_silence_delay_);
|
if (upThreadDelay(frame_time_milsec_, suspend_silence_delay_)) Update();
|
||||||
if (silence_ != silence_prev_ || force) m_signal_silence_.emit();
|
if (silence_ != silence_prev_ || force) m_signal_silence_.emit();
|
||||||
}
|
}
|
||||||
silence_prev_ = silence_;
|
silence_prev_ = silence_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waybar::modules::cava::CavaBackend::freeBackend() {
|
||||||
|
if (plan_ != NULL) {
|
||||||
|
cava_destroy(plan_);
|
||||||
|
plan_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_raw_clean(&audio_raw_);
|
||||||
|
pthread_mutex_lock(&audio_data_.lock);
|
||||||
|
audio_data_.terminate = 1;
|
||||||
|
pthread_mutex_unlock(&audio_data_.lock);
|
||||||
|
free_config(&prm_);
|
||||||
|
free(audio_data_.source);
|
||||||
|
free(audio_data_.cava_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
void waybar::modules::cava::CavaBackend::loadConfig() {
|
||||||
|
freeBackend();
|
||||||
|
// Load waybar module config
|
||||||
|
char cfgPath[PATH_MAX];
|
||||||
|
cfgPath[0] = '\0';
|
||||||
|
|
||||||
|
if (config_["cava_config"].isString()) strcpy(cfgPath, config_["cava_config"].asString().data());
|
||||||
|
// Load cava config
|
||||||
|
error_.length = 0;
|
||||||
|
|
||||||
|
if (!load_config(cfgPath, &prm_, &error_)) {
|
||||||
|
spdlog::error("cava backend. Error loading config. {0}", error_.message);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override cava parameters by the user config
|
||||||
|
prm_.inAtty = 0;
|
||||||
|
auto const output{prm_.output};
|
||||||
|
// prm_.output = ::cava::output_method::OUTPUT_RAW;
|
||||||
|
if (prm_.data_format) free(prm_.data_format);
|
||||||
|
// Default to ascii for format-icons output; allow user override
|
||||||
|
prm_.data_format = strdup(
|
||||||
|
config_["data_format"].isString() ? config_["data_format"].asString().c_str() : "ascii");
|
||||||
|
if (config_["raw_target"].isString()) {
|
||||||
|
if (prm_.raw_target) free(prm_.raw_target);
|
||||||
|
prm_.raw_target = strdup(config_["raw_target"].asString().c_str());
|
||||||
|
}
|
||||||
|
prm_.ascii_range = config_["format-icons"].size() - 1;
|
||||||
|
|
||||||
|
if (config_["bar_spacing"].isInt()) prm_.bar_spacing = config_["bar_spacing"].asInt();
|
||||||
|
if (config_["bar_width"].isInt()) prm_.bar_width = config_["bar_width"].asInt();
|
||||||
|
if (config_["bar_height"].isInt()) prm_.bar_height = config_["bar_height"].asInt();
|
||||||
|
prm_.orientation = ::cava::ORIENT_TOP;
|
||||||
|
prm_.xaxis = ::cava::xaxis_scale::NONE;
|
||||||
|
prm_.mono_opt = ::cava::AVERAGE;
|
||||||
|
prm_.autobars = 0;
|
||||||
|
if (config_["gravity"].isInt()) prm_.gravity = config_["gravity"].asInt();
|
||||||
|
if (config_["integral"].isInt()) prm_.integral = config_["integral"].asInt();
|
||||||
|
|
||||||
|
if (config_["framerate"].isInt()) prm_.framerate = config_["framerate"].asInt();
|
||||||
|
// Calculate delay for Update() thread
|
||||||
|
frame_time_milsec_ = std::chrono::milliseconds((int)(1e3 / prm_.framerate));
|
||||||
|
if (config_["autosens"].isInt()) prm_.autosens = config_["autosens"].asInt();
|
||||||
|
if (config_["sensitivity"].isInt()) prm_.sens = config_["sensitivity"].asInt();
|
||||||
|
if (config_["bars"].isInt()) prm_.fixedbars = config_["bars"].asInt();
|
||||||
|
if (config_["lower_cutoff_freq"].isNumeric())
|
||||||
|
prm_.lower_cut_off = config_["lower_cutoff_freq"].asLargestInt();
|
||||||
|
if (config_["higher_cutoff_freq"].isNumeric())
|
||||||
|
prm_.upper_cut_off = config_["higher_cutoff_freq"].asLargestInt();
|
||||||
|
if (config_["sleep_timer"].isInt()) prm_.sleep_timer = config_["sleep_timer"].asInt();
|
||||||
|
if (config_["method"].isString())
|
||||||
|
prm_.input = ::cava::input_method_by_name(config_["method"].asString().c_str());
|
||||||
|
if (config_["source"].isString()) {
|
||||||
|
if (prm_.audio_source) free(prm_.audio_source);
|
||||||
|
prm_.audio_source = config_["source"].asString().data();
|
||||||
|
}
|
||||||
|
if (config_["sample_rate"].isNumeric()) prm_.samplerate = config_["sample_rate"].asLargestInt();
|
||||||
|
if (config_["sample_bits"].isInt()) prm_.samplebits = config_["sample_bits"].asInt();
|
||||||
|
if (config_["stereo"].isBool()) prm_.stereo = config_["stereo"].asBool();
|
||||||
|
if (config_["reverse"].isBool()) prm_.reverse = config_["reverse"].asBool();
|
||||||
|
if (config_["bar_delimiter"].isInt()) prm_.bar_delim = config_["bar_delimiter"].asInt();
|
||||||
|
if (config_["monstercat"].isBool()) prm_.monstercat = config_["monstercat"].asBool();
|
||||||
|
if (config_["waves"].isBool()) prm_.waves = config_["waves"].asBool();
|
||||||
|
if (config_["noise_reduction"].isDouble())
|
||||||
|
prm_.noise_reduction = config_["noise_reduction"].asDouble();
|
||||||
|
if (config_["input_delay"].isInt())
|
||||||
|
fetch_input_delay_ = std::chrono::seconds(config_["input_delay"].asInt());
|
||||||
|
if (config_["gradient"].isInt()) prm_.gradient = config_["gradient"].asInt();
|
||||||
|
if (prm_.gradient == 0)
|
||||||
|
prm_.gradient_count = 0;
|
||||||
|
else if (config_["gradient_count"].isInt())
|
||||||
|
prm_.gradient_count = config_["gradient_count"].asInt();
|
||||||
|
if (config_["sdl_width"].isInt()) prm_.sdl_width = config_["sdl_width"].asInt();
|
||||||
|
if (config_["sdl_height"].isInt()) prm_.sdl_height = config_["sdl_height"].asInt();
|
||||||
|
|
||||||
|
audio_raw_.height = prm_.ascii_range;
|
||||||
|
audio_data_.format = -1;
|
||||||
|
audio_data_.rate = 0;
|
||||||
|
audio_data_.samples_counter = 0;
|
||||||
|
audio_data_.channels = 2;
|
||||||
|
audio_data_.IEEE_FLOAT = 0;
|
||||||
|
audio_data_.input_buffer_size = BUFFER_SIZE * audio_data_.channels;
|
||||||
|
audio_data_.cava_buffer_size = audio_data_.input_buffer_size * 8;
|
||||||
|
audio_data_.terminate = 0;
|
||||||
|
audio_data_.suspendFlag = false;
|
||||||
|
input_source_ = get_input(&audio_data_, &prm_);
|
||||||
|
|
||||||
|
if (!input_source_) {
|
||||||
|
spdlog::error("cava backend API didn't provide input audio source method");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
prm_.output = ::cava::output_method::OUTPUT_RAW;
|
||||||
|
|
||||||
|
// Make cava parameters configuration
|
||||||
|
// Init cava plan, audio_raw structure
|
||||||
|
audio_raw_init(&audio_data_, &audio_raw_, &prm_, &plan_);
|
||||||
|
if (!plan_) spdlog::error("cava backend plan is not provided");
|
||||||
|
audio_raw_.previous_frame[0] = -1; // For first Update() call need to rePaint text message
|
||||||
|
|
||||||
|
prm_.output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct ::cava::config_params* waybar::modules::cava::CavaBackend::getPrm() { return &prm_; }
|
||||||
|
std::chrono::milliseconds waybar::modules::cava::CavaBackend::getFrameTimeMilsec() {
|
||||||
|
return frame_time_milsec_;
|
||||||
|
};
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ auto waybar::modules::Cpu::update() -> void {
|
|||||||
auto [load1, load5, load15] = Load::getLoad();
|
auto [load1, load5, load15] = Load::getLoad();
|
||||||
auto [cpu_usage, tooltip] = CpuUsage::getCpuUsage(prev_times_);
|
auto [cpu_usage, tooltip] = CpuUsage::getCpuUsage(prev_times_);
|
||||||
auto [max_frequency, min_frequency, avg_frequency] = CpuFrequency::getCpuFrequency();
|
auto [max_frequency, min_frequency, avg_frequency] = CpuFrequency::getCpuFrequency();
|
||||||
if (tooltipEnabled()) {
|
|
||||||
label_.set_tooltip_text(tooltip);
|
|
||||||
}
|
|
||||||
auto format = format_;
|
auto format = format_;
|
||||||
auto total_usage = cpu_usage.empty() ? 0 : cpu_usage[0];
|
auto total_usage = cpu_usage.empty() ? 0 : cpu_usage[0];
|
||||||
auto state = getState(total_usage);
|
auto state = getState(total_usage);
|
||||||
@@ -56,6 +54,15 @@ auto waybar::modules::Cpu::update() -> void {
|
|||||||
store.push_back(fmt::arg(icon_format.c_str(), getIcon(cpu_usage[i], icons)));
|
store.push_back(fmt::arg(icon_format.c_str(), getIcon(cpu_usage[i], icons)));
|
||||||
}
|
}
|
||||||
label_.set_markup(fmt::vformat(format, store));
|
label_.set_markup(fmt::vformat(format, store));
|
||||||
|
|
||||||
|
if (tooltipEnabled()) {
|
||||||
|
if (config_["tooltip-format"].isString()) {
|
||||||
|
tooltip = config_["tooltip-format"].asString();
|
||||||
|
label_.set_tooltip_markup(fmt::vformat(tooltip, store));
|
||||||
|
} else {
|
||||||
|
label_.set_tooltip_markup(tooltip);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call parent update
|
// Call parent update
|
||||||
|
|||||||
@@ -20,12 +20,7 @@ waybar::modules::CpuFrequency::CpuFrequency(const std::string& id, const Json::V
|
|||||||
auto waybar::modules::CpuFrequency::update() -> void {
|
auto waybar::modules::CpuFrequency::update() -> void {
|
||||||
// TODO: as creating dynamic fmt::arg arrays is buggy we have to calc both
|
// TODO: as creating dynamic fmt::arg arrays is buggy we have to calc both
|
||||||
auto [max_frequency, min_frequency, avg_frequency] = CpuFrequency::getCpuFrequency();
|
auto [max_frequency, min_frequency, avg_frequency] = CpuFrequency::getCpuFrequency();
|
||||||
if (tooltipEnabled()) {
|
|
||||||
auto tooltip =
|
|
||||||
fmt::format("Minimum frequency: {}\nAverage frequency: {}\nMaximum frequency: {}\n",
|
|
||||||
min_frequency, avg_frequency, max_frequency);
|
|
||||||
label_.set_tooltip_text(tooltip);
|
|
||||||
}
|
|
||||||
auto format = format_;
|
auto format = format_;
|
||||||
auto state = getState(avg_frequency);
|
auto state = getState(avg_frequency);
|
||||||
if (!state.empty() && config_["format-" + state].isString()) {
|
if (!state.empty() && config_["format-" + state].isString()) {
|
||||||
@@ -43,6 +38,18 @@ auto waybar::modules::CpuFrequency::update() -> void {
|
|||||||
store.push_back(fmt::arg("min_frequency", min_frequency));
|
store.push_back(fmt::arg("min_frequency", min_frequency));
|
||||||
store.push_back(fmt::arg("avg_frequency", avg_frequency));
|
store.push_back(fmt::arg("avg_frequency", avg_frequency));
|
||||||
label_.set_markup(fmt::vformat(format, store));
|
label_.set_markup(fmt::vformat(format, store));
|
||||||
|
|
||||||
|
if (tooltipEnabled()) {
|
||||||
|
std::string tooltip;
|
||||||
|
if (config_["tooltip-format"].isString()) {
|
||||||
|
tooltip = config_["tooltip-format"].asString();
|
||||||
|
label_.set_tooltip_markup(fmt::vformat(tooltip, store));
|
||||||
|
} else {
|
||||||
|
tooltip = "Minimum frequency: {}\nAverage frequency: {}\nMaximum frequency: {}\n";
|
||||||
|
label_.set_tooltip_markup(
|
||||||
|
fmt::format(fmt::runtime(tooltip), min_frequency, avg_frequency, max_frequency));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call parent update
|
// Call parent update
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ std::vector<std::tuple<size_t, size_t>> waybar::modules::CpuUsage::parseCpuinfo(
|
|||||||
size_t sum_sz = sizeof(sum_cp_time);
|
size_t sum_sz = sizeof(sum_cp_time);
|
||||||
int ncpu = sysconf(_SC_NPROCESSORS_CONF);
|
int ncpu = sysconf(_SC_NPROCESSORS_CONF);
|
||||||
size_t sz = CPUSTATES * (ncpu + 1) * sizeof(pcp_time_t);
|
size_t sz = CPUSTATES * (ncpu + 1) * sizeof(pcp_time_t);
|
||||||
pcp_time_t *cp_time = static_cast<pcp_time_t *>(malloc(sz)), *pcp_time = cp_time;
|
pcp_time_t *cp_time = static_cast<pcp_time_t*>(malloc(sz)), *pcp_time = cp_time;
|
||||||
waybar::util::ScopeGuard cp_time_deleter([cp_time]() {
|
waybar::util::ScopeGuard cp_time_deleter([cp_time]() {
|
||||||
if (cp_time) {
|
if (cp_time) {
|
||||||
free(cp_time);
|
free(cp_time);
|
||||||
|
|||||||
@@ -20,9 +20,7 @@ waybar::modules::CpuUsage::CpuUsage(const std::string& id, const Json::Value& co
|
|||||||
auto waybar::modules::CpuUsage::update() -> void {
|
auto waybar::modules::CpuUsage::update() -> void {
|
||||||
// TODO: as creating dynamic fmt::arg arrays is buggy we have to calc both
|
// TODO: as creating dynamic fmt::arg arrays is buggy we have to calc both
|
||||||
auto [cpu_usage, tooltip] = CpuUsage::getCpuUsage(prev_times_);
|
auto [cpu_usage, tooltip] = CpuUsage::getCpuUsage(prev_times_);
|
||||||
if (tooltipEnabled()) {
|
|
||||||
label_.set_tooltip_text(tooltip);
|
|
||||||
}
|
|
||||||
auto format = format_;
|
auto format = format_;
|
||||||
auto total_usage = cpu_usage.empty() ? 0 : cpu_usage[0];
|
auto total_usage = cpu_usage.empty() ? 0 : cpu_usage[0];
|
||||||
auto state = getState(total_usage);
|
auto state = getState(total_usage);
|
||||||
@@ -46,6 +44,15 @@ auto waybar::modules::CpuUsage::update() -> void {
|
|||||||
store.push_back(fmt::arg(icon_format.c_str(), getIcon(cpu_usage[i], icons)));
|
store.push_back(fmt::arg(icon_format.c_str(), getIcon(cpu_usage[i], icons)));
|
||||||
}
|
}
|
||||||
label_.set_markup(fmt::vformat(format, store));
|
label_.set_markup(fmt::vformat(format, store));
|
||||||
|
|
||||||
|
if (tooltipEnabled()) {
|
||||||
|
if (config_["tooltip-format"].isString()) {
|
||||||
|
tooltip = config_["tooltip-format"].asString();
|
||||||
|
label_.set_tooltip_markup(fmt::vformat(tooltip, store));
|
||||||
|
} else {
|
||||||
|
label_.set_tooltip_markup(tooltip);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call parent update
|
// Call parent update
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ void waybar::modules::Custom::waitingWorker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::Custom::refresh(int sig) {
|
void waybar::modules::Custom::refresh(int sig) {
|
||||||
if (sig == SIGRTMIN + config_["signal"].asInt()) {
|
if (config_["signal"].isInt() && sig == SIGRTMIN + config_["signal"].asInt()) {
|
||||||
thread_.wake_up();
|
thread_.wake_up();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,13 +187,9 @@ auto waybar::modules::Custom::update() -> void {
|
|||||||
fmt::arg("icon", getIcon(percentage_, alt_)), fmt::arg("percentage", percentage_));
|
fmt::arg("icon", getIcon(percentage_, alt_)), fmt::arg("percentage", percentage_));
|
||||||
label_.set_tooltip_markup(tooltip);
|
label_.set_tooltip_markup(tooltip);
|
||||||
} else if (text_ == tooltip_) {
|
} else if (text_ == tooltip_) {
|
||||||
if (label_.get_tooltip_markup() != str) {
|
label_.set_tooltip_markup(str);
|
||||||
label_.set_tooltip_markup(str);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (label_.get_tooltip_markup() != tooltip_) {
|
label_.set_tooltip_markup(tooltip_);
|
||||||
label_.set_tooltip_markup(tooltip_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto style = label_.get_style_context();
|
auto style = label_.get_style_context();
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ auto waybar::modules::Disk::update() -> void {
|
|||||||
if (config_["tooltip-format"].isString()) {
|
if (config_["tooltip-format"].isString()) {
|
||||||
tooltip_format = config_["tooltip-format"].asString();
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
}
|
}
|
||||||
label_.set_tooltip_text(fmt::format(
|
label_.set_tooltip_markup(fmt::format(
|
||||||
fmt::runtime(tooltip_format), stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free),
|
fmt::runtime(tooltip_format), stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free),
|
||||||
fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), fmt::arg("used", used),
|
fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), fmt::arg("used", used),
|
||||||
fmt::arg("percentage_used", percentage_used), fmt::arg("total", total),
|
fmt::arg("percentage_used", percentage_used), fmt::arg("total", total),
|
||||||
@@ -112,4 +112,4 @@ float waybar::modules::Disk::calc_specific_divisor(std::string divisor) {
|
|||||||
} else { // default to Bytes if it is anything that we don't recongnise
|
} else { // default to Bytes if it is anything that we don't recongnise
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,39 +21,39 @@ wl_array tags, layouts;
|
|||||||
|
|
||||||
static uint num_tags = 0;
|
static uint num_tags = 0;
|
||||||
|
|
||||||
static void toggle_visibility(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
|
static void toggle_visibility(void* data, zdwl_ipc_output_v2* zdwl_output_v2) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
static void active(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t active) {
|
static void active(void* data, zdwl_ipc_output_v2* zdwl_output_v2, uint32_t active) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_tag(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t tag, uint32_t state,
|
static void set_tag(void* data, zdwl_ipc_output_v2* zdwl_output_v2, uint32_t tag, uint32_t state,
|
||||||
uint32_t clients, uint32_t focused) {
|
uint32_t clients, uint32_t focused) {
|
||||||
static_cast<Tags *>(data)->handle_view_tags(tag, state, clients, focused);
|
static_cast<Tags*>(data)->handle_view_tags(tag, state, clients, focused);
|
||||||
|
|
||||||
num_tags = (state & ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE) ? num_tags | (1 << tag)
|
num_tags = (state & ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE) ? num_tags | (1 << tag)
|
||||||
: num_tags & ~(1 << tag);
|
: num_tags & ~(1 << tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_layout_symbol(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *layout) {
|
static void set_layout_symbol(void* data, zdwl_ipc_output_v2* zdwl_output_v2, const char* layout) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
static void title(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *title) {
|
static void title(void* data, zdwl_ipc_output_v2* zdwl_output_v2, const char* title) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_frame(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
|
static void dwl_frame(void* data, zdwl_ipc_output_v2* zdwl_output_v2) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_layout(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t layout) {
|
static void set_layout(void* data, zdwl_ipc_output_v2* zdwl_output_v2, uint32_t layout) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
static void appid(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *appid) {
|
static void appid(void* data, zdwl_ipc_output_v2* zdwl_output_v2, const char* appid) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -68,35 +68,35 @@ static const zdwl_ipc_output_v2_listener output_status_listener_impl{
|
|||||||
.frame = dwl_frame,
|
.frame = dwl_frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
static void handle_global(void* data, struct wl_registry* registry, uint32_t name,
|
||||||
const char *interface, uint32_t version) {
|
const char* interface, uint32_t version) {
|
||||||
if (std::strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) {
|
if (std::strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) {
|
||||||
static_cast<Tags *>(data)->status_manager_ = static_cast<struct zdwl_ipc_manager_v2 *>(
|
static_cast<Tags*>(data)->status_manager_ = static_cast<struct zdwl_ipc_manager_v2*>(
|
||||||
(zdwl_ipc_manager_v2 *)wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 1));
|
(zdwl_ipc_manager_v2*)wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 1));
|
||||||
}
|
}
|
||||||
if (std::strcmp(interface, wl_seat_interface.name) == 0) {
|
if (std::strcmp(interface, wl_seat_interface.name) == 0) {
|
||||||
version = std::min<uint32_t>(version, 1);
|
version = std::min<uint32_t>(version, 1);
|
||||||
static_cast<Tags *>(data)->seat_ = static_cast<struct wl_seat *>(
|
static_cast<Tags*>(data)->seat_ =
|
||||||
wl_registry_bind(registry, name, &wl_seat_interface, version));
|
static_cast<struct wl_seat*>(wl_registry_bind(registry, name, &wl_seat_interface, version));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
|
static void handle_global_remove(void* data, struct wl_registry* registry, uint32_t name) {
|
||||||
/* Ignore event */
|
/* Ignore event */
|
||||||
}
|
}
|
||||||
|
|
||||||
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
|
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
|
||||||
.global_remove = handle_global_remove};
|
.global_remove = handle_global_remove};
|
||||||
|
|
||||||
Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &config)
|
Tags::Tags(const std::string& id, const waybar::Bar& bar, const Json::Value& config)
|
||||||
: waybar::AModule(config, "tags", id, false, false),
|
: waybar::AModule(config, "tags", id, false, false),
|
||||||
status_manager_{nullptr},
|
status_manager_{nullptr},
|
||||||
seat_{nullptr},
|
seat_{nullptr},
|
||||||
bar_(bar),
|
bar_(bar),
|
||||||
box_{bar.orientation, 0},
|
box_{bar.orientation, 0},
|
||||||
output_status_{nullptr} {
|
output_status_{nullptr} {
|
||||||
struct wl_display *display = Client::inst()->wl_display;
|
struct wl_display* display = Client::inst()->wl_display;
|
||||||
struct wl_registry *registry = wl_display_get_registry(display);
|
struct wl_registry* registry = wl_display_get_registry(display);
|
||||||
|
|
||||||
wl_registry_add_listener(registry, ®istry_listener_impl, this);
|
wl_registry_add_listener(registry, ®istry_listener_impl, this);
|
||||||
wl_display_roundtrip(display);
|
wl_display_roundtrip(display);
|
||||||
@@ -133,8 +133,8 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t i = 1;
|
uint32_t i = 1;
|
||||||
for (const auto &tag_label : tag_labels) {
|
for (const auto& tag_label : tag_labels) {
|
||||||
Gtk::Button &button = buttons_.emplace_back(tag_label);
|
Gtk::Button& button = buttons_.emplace_back(tag_label);
|
||||||
button.set_relief(Gtk::RELIEF_NONE);
|
button.set_relief(Gtk::RELIEF_NONE);
|
||||||
box_.pack_start(button, false, false, 0);
|
box_.pack_start(button, false, false, 0);
|
||||||
if (!config_["disable-click"].asBool()) {
|
if (!config_["disable-click"].asBool()) {
|
||||||
@@ -147,7 +147,7 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
|
|||||||
i <<= 1;
|
i <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wl_output *output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
struct wl_output* output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
||||||
output_status_ = zdwl_ipc_manager_v2_get_output(status_manager_, output);
|
output_status_ = zdwl_ipc_manager_v2_get_output(status_manager_, output);
|
||||||
zdwl_ipc_output_v2_add_listener(output_status_, &output_status_listener_impl, this);
|
zdwl_ipc_output_v2_add_listener(output_status_, &output_status_listener_impl, this);
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ void Tags::handle_primary_clicked(uint32_t tag) {
|
|||||||
zdwl_ipc_output_v2_set_tags(output_status_, tag, 1);
|
zdwl_ipc_output_v2_set_tags(output_status_, tag, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tags::handle_button_press(GdkEventButton *event_button, uint32_t tag) {
|
bool Tags::handle_button_press(GdkEventButton* event_button, uint32_t tag) {
|
||||||
if (event_button->type == GDK_BUTTON_PRESS && event_button->button == 3) {
|
if (event_button->type == GDK_BUTTON_PRESS && event_button->button == 3) {
|
||||||
if (!output_status_) return true;
|
if (!output_status_) return true;
|
||||||
zdwl_ipc_output_v2_set_tags(output_status_, num_tags ^ tag, 0);
|
zdwl_ipc_output_v2_set_tags(output_status_, num_tags ^ tag, 0);
|
||||||
@@ -180,13 +180,19 @@ bool Tags::handle_button_press(GdkEventButton *event_button, uint32_t tag) {
|
|||||||
|
|
||||||
void Tags::handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused) {
|
void Tags::handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused) {
|
||||||
// First clear all occupied state
|
// First clear all occupied state
|
||||||
auto &button = buttons_[tag];
|
auto& button = buttons_[tag];
|
||||||
if (clients) {
|
if (clients) {
|
||||||
button.get_style_context()->add_class("occupied");
|
button.get_style_context()->add_class("occupied");
|
||||||
} else {
|
} else {
|
||||||
button.get_style_context()->remove_class("occupied");
|
button.get_style_context()->remove_class("occupied");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (clients & TAG_INACTIVE) {
|
||||||
|
button.get_style_context()->remove_class("empty");
|
||||||
|
} else {
|
||||||
|
button.get_style_context()->add_class("empty");
|
||||||
|
}
|
||||||
|
|
||||||
if (state & TAG_ACTIVE) {
|
if (state & TAG_ACTIVE) {
|
||||||
button.get_style_context()->add_class("focused");
|
button.get_style_context()->add_class("focused");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -14,37 +14,37 @@
|
|||||||
|
|
||||||
namespace waybar::modules::dwl {
|
namespace waybar::modules::dwl {
|
||||||
|
|
||||||
static void toggle_visibility(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
|
static void toggle_visibility(void* data, zdwl_ipc_output_v2* zdwl_output_v2) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
static void active(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t active) {
|
static void active(void* data, zdwl_ipc_output_v2* zdwl_output_v2, uint32_t active) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_tag(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t tag, uint32_t state,
|
static void set_tag(void* data, zdwl_ipc_output_v2* zdwl_output_v2, uint32_t tag, uint32_t state,
|
||||||
uint32_t clients, uint32_t focused) {
|
uint32_t clients, uint32_t focused) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_layout_symbol(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *layout) {
|
static void set_layout_symbol(void* data, zdwl_ipc_output_v2* zdwl_output_v2, const char* layout) {
|
||||||
static_cast<Window *>(data)->handle_layout_symbol(layout);
|
static_cast<Window*>(data)->handle_layout_symbol(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void title(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *title) {
|
static void title(void* data, zdwl_ipc_output_v2* zdwl_output_v2, const char* title) {
|
||||||
static_cast<Window *>(data)->handle_title(title);
|
static_cast<Window*>(data)->handle_title(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwl_frame(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
|
static void dwl_frame(void* data, zdwl_ipc_output_v2* zdwl_output_v2) {
|
||||||
static_cast<Window *>(data)->handle_frame();
|
static_cast<Window*>(data)->handle_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_layout(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t layout) {
|
static void set_layout(void* data, zdwl_ipc_output_v2* zdwl_output_v2, uint32_t layout) {
|
||||||
static_cast<Window *>(data)->handle_layout(layout);
|
static_cast<Window*>(data)->handle_layout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void appid(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *appid) {
|
static void appid(void* data, zdwl_ipc_output_v2* zdwl_output_v2, const char* appid) {
|
||||||
static_cast<Window *>(data)->handle_appid(appid);
|
static_cast<Window*>(data)->handle_appid(appid);
|
||||||
};
|
};
|
||||||
|
|
||||||
static const zdwl_ipc_output_v2_listener output_status_listener_impl{
|
static const zdwl_ipc_output_v2_listener output_status_listener_impl{
|
||||||
@@ -58,25 +58,25 @@ static const zdwl_ipc_output_v2_listener output_status_listener_impl{
|
|||||||
.frame = dwl_frame,
|
.frame = dwl_frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
static void handle_global(void* data, struct wl_registry* registry, uint32_t name,
|
||||||
const char *interface, uint32_t version) {
|
const char* interface, uint32_t version) {
|
||||||
if (std::strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) {
|
if (std::strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) {
|
||||||
static_cast<Window *>(data)->status_manager_ = static_cast<struct zdwl_ipc_manager_v2 *>(
|
static_cast<Window*>(data)->status_manager_ = static_cast<struct zdwl_ipc_manager_v2*>(
|
||||||
(zdwl_ipc_manager_v2 *)wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 1));
|
(zdwl_ipc_manager_v2*)wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
|
static void handle_global_remove(void* data, struct wl_registry* registry, uint32_t name) {
|
||||||
/* Ignore event */
|
/* Ignore event */
|
||||||
}
|
}
|
||||||
|
|
||||||
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
|
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
|
||||||
.global_remove = handle_global_remove};
|
.global_remove = handle_global_remove};
|
||||||
|
|
||||||
Window::Window(const std::string &id, const Bar &bar, const Json::Value &config)
|
Window::Window(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||||
: AAppIconLabel(config, "window", id, "{}", 0, true), bar_(bar) {
|
: AAppIconLabel(config, "window", id, "{}", 0, true), bar_(bar) {
|
||||||
struct wl_display *display = Client::inst()->wl_display;
|
struct wl_display* display = Client::inst()->wl_display;
|
||||||
struct wl_registry *registry = wl_display_get_registry(display);
|
struct wl_registry* registry = wl_display_get_registry(display);
|
||||||
|
|
||||||
wl_registry_add_listener(registry, ®istry_listener_impl, this);
|
wl_registry_add_listener(registry, ®istry_listener_impl, this);
|
||||||
wl_display_roundtrip(display);
|
wl_display_roundtrip(display);
|
||||||
@@ -86,7 +86,7 @@ Window::Window(const std::string &id, const Bar &bar, const Json::Value &config)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wl_output *output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
struct wl_output* output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
||||||
output_status_ = zdwl_ipc_manager_v2_get_output(status_manager_, output);
|
output_status_ = zdwl_ipc_manager_v2_get_output(status_manager_, output);
|
||||||
zdwl_ipc_output_v2_add_listener(output_status_, &output_status_listener_impl, this);
|
zdwl_ipc_output_v2_add_listener(output_status_, &output_status_listener_impl, this);
|
||||||
zdwl_ipc_manager_v2_destroy(status_manager_);
|
zdwl_ipc_manager_v2_destroy(status_manager_);
|
||||||
@@ -98,11 +98,11 @@ Window::~Window() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::handle_title(const char *title) { title_ = Glib::Markup::escape_text(title); }
|
void Window::handle_title(const char* title) { title_ = Glib::Markup::escape_text(title); }
|
||||||
|
|
||||||
void Window::handle_appid(const char *appid) { appid_ = Glib::Markup::escape_text(appid); }
|
void Window::handle_appid(const char* appid) { appid_ = Glib::Markup::escape_text(appid); }
|
||||||
|
|
||||||
void Window::handle_layout_symbol(const char *layout_symbol) {
|
void Window::handle_layout_symbol(const char* layout_symbol) {
|
||||||
layout_symbol_ = Glib::Markup::escape_text(layout_symbol);
|
layout_symbol_ = Glib::Markup::escape_text(layout_symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ void Window::handle_frame() {
|
|||||||
updateAppIconName(appid_, "");
|
updateAppIconName(appid_, "");
|
||||||
updateAppIcon();
|
updateAppIcon();
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
label_.set_tooltip_text(title_);
|
label_.set_tooltip_markup(title_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ uint32_t WorkspaceManager::group_global_id = 0;
|
|||||||
uint32_t WorkspaceManager::workspace_global_id = 0;
|
uint32_t WorkspaceManager::workspace_global_id = 0;
|
||||||
std::map<std::string, std::string> Workspace::icon_map_;
|
std::map<std::string, std::string> Workspace::icon_map_;
|
||||||
|
|
||||||
WorkspaceManager::WorkspaceManager(const std::string &id, const waybar::Bar &bar,
|
WorkspaceManager::WorkspaceManager(const std::string& id, const waybar::Bar& bar,
|
||||||
const Json::Value &config)
|
const Json::Value& config)
|
||||||
: waybar::AModule(config, "workspaces", id, false, false), bar_(bar), box_(bar.orientation, 0) {
|
: waybar::AModule(config, "workspaces", id, false, false), bar_(bar), box_(bar.orientation, 0) {
|
||||||
add_registry_listener(this);
|
add_registry_listener(this);
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ WorkspaceManager::~WorkspaceManager() {
|
|||||||
groups_.clear();
|
groups_.clear();
|
||||||
|
|
||||||
if (ext_manager_ != nullptr) {
|
if (ext_manager_ != nullptr) {
|
||||||
auto *display = Client::inst()->wl_display;
|
auto* display = Client::inst()->wl_display;
|
||||||
// Send `stop` request and wait for one roundtrip.
|
// Send `stop` request and wait for one roundtrip.
|
||||||
ext_workspace_manager_v1_stop(ext_manager_);
|
ext_workspace_manager_v1_stop(ext_manager_);
|
||||||
wl_display_roundtrip(display);
|
wl_display_roundtrip(display);
|
||||||
@@ -84,7 +84,7 @@ WorkspaceManager::~WorkspaceManager() {
|
|||||||
spdlog::debug("[ext/workspaces]: Workspace manager destroyed");
|
spdlog::debug("[ext/workspaces]: Workspace manager destroyed");
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorkspaceManager::register_manager(wl_registry *registry, uint32_t name, uint32_t version) {
|
void WorkspaceManager::register_manager(wl_registry* registry, uint32_t name, uint32_t version) {
|
||||||
if (ext_manager_ != nullptr) {
|
if (ext_manager_ != nullptr) {
|
||||||
spdlog::warn("[ext/workspaces]: Register workspace manager again although already registered!");
|
spdlog::warn("[ext/workspaces]: Register workspace manager again although already registered!");
|
||||||
return;
|
return;
|
||||||
@@ -99,7 +99,7 @@ void WorkspaceManager::register_manager(wl_registry *registry, uint32_t name, ui
|
|||||||
|
|
||||||
void WorkspaceManager::remove_workspace_group(uint32_t id) {
|
void WorkspaceManager::remove_workspace_group(uint32_t id) {
|
||||||
const auto it =
|
const auto it =
|
||||||
std::find_if(groups_.begin(), groups_.end(), [id](const auto &g) { return g->id() == id; });
|
std::find_if(groups_.begin(), groups_.end(), [id](const auto& g) { return g->id() == id; });
|
||||||
|
|
||||||
if (it == groups_.end()) {
|
if (it == groups_.end()) {
|
||||||
spdlog::warn("[ext/workspaces]: Can't find workspace group with id {}", id);
|
spdlog::warn("[ext/workspaces]: Can't find workspace group with id {}", id);
|
||||||
@@ -111,7 +111,7 @@ void WorkspaceManager::remove_workspace_group(uint32_t id) {
|
|||||||
|
|
||||||
void WorkspaceManager::remove_workspace(uint32_t id) {
|
void WorkspaceManager::remove_workspace(uint32_t id) {
|
||||||
const auto it = std::find_if(workspaces_.begin(), workspaces_.end(),
|
const auto it = std::find_if(workspaces_.begin(), workspaces_.end(),
|
||||||
[id](const auto &w) { return w->id() == id; });
|
[id](const auto& w) { return w->id() == id; });
|
||||||
|
|
||||||
if (it == workspaces_.end()) {
|
if (it == workspaces_.end()) {
|
||||||
spdlog::warn("[ext/workspaces]: Can't find workspace with id {}", id);
|
spdlog::warn("[ext/workspaces]: Can't find workspace with id {}", id);
|
||||||
@@ -121,13 +121,13 @@ void WorkspaceManager::remove_workspace(uint32_t id) {
|
|||||||
workspaces_.erase(it);
|
workspaces_.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorkspaceManager::handle_workspace_group(ext_workspace_group_handle_v1 *handle) {
|
void WorkspaceManager::handle_workspace_group(ext_workspace_group_handle_v1* handle) {
|
||||||
const auto new_id = ++group_global_id;
|
const auto new_id = ++group_global_id;
|
||||||
groups_.push_back(std::make_unique<WorkspaceGroup>(*this, handle, new_id));
|
groups_.push_back(std::make_unique<WorkspaceGroup>(*this, handle, new_id));
|
||||||
spdlog::debug("[ext/workspaces]: Workspace group {} created", new_id);
|
spdlog::debug("[ext/workspaces]: Workspace group {} created", new_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorkspaceManager::handle_workspace(ext_workspace_handle_v1 *handle) {
|
void WorkspaceManager::handle_workspace(ext_workspace_handle_v1* handle) {
|
||||||
const auto new_id = ++workspace_global_id;
|
const auto new_id = ++workspace_global_id;
|
||||||
const auto new_name = std::to_string(++workspace_name);
|
const auto new_name = std::to_string(++workspace_name);
|
||||||
workspaces_.push_back(std::make_unique<Workspace>(config_, *this, handle, new_id, new_name));
|
workspaces_.push_back(std::make_unique<Workspace>(config_, *this, handle, new_id, new_name));
|
||||||
@@ -158,7 +158,7 @@ void WorkspaceManager::update() {
|
|||||||
AModule::update();
|
AModule::update();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorkspaceManager::has_button(const Gtk::Button *button) {
|
bool WorkspaceManager::has_button(const Gtk::Button* button) {
|
||||||
const auto buttons = box_.get_children();
|
const auto buttons = box_.get_children();
|
||||||
return std::find(buttons.begin(), buttons.end(), button) != buttons.end();
|
return std::find(buttons.begin(), buttons.end(), button) != buttons.end();
|
||||||
}
|
}
|
||||||
@@ -166,20 +166,20 @@ bool WorkspaceManager::has_button(const Gtk::Button *button) {
|
|||||||
void WorkspaceManager::sort_workspaces() {
|
void WorkspaceManager::sort_workspaces() {
|
||||||
// determine if workspace ID's and names can be sort numerically or literally
|
// determine if workspace ID's and names can be sort numerically or literally
|
||||||
|
|
||||||
auto is_numeric = [](const std::string &s) {
|
auto is_numeric = [](const std::string& s) {
|
||||||
return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
|
return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto sort_by_workspace_id_numerically =
|
auto sort_by_workspace_id_numerically =
|
||||||
std::all_of(workspaces_.begin(), workspaces_.end(),
|
std::all_of(workspaces_.begin(), workspaces_.end(),
|
||||||
[&](const auto &w) { return is_numeric(w->workspace_id()); });
|
[&](const auto& w) { return is_numeric(w->workspace_id()); });
|
||||||
|
|
||||||
auto sort_by_name_numerically = std::all_of(workspaces_.begin(), workspaces_.end(),
|
auto sort_by_name_numerically = std::all_of(workspaces_.begin(), workspaces_.end(),
|
||||||
[&](const auto &w) { return is_numeric(w->name()); });
|
[&](const auto& w) { return is_numeric(w->name()); });
|
||||||
|
|
||||||
// sort based on configuration setting with sort-by-id as fallback
|
// sort based on configuration setting with sort-by-id as fallback
|
||||||
|
|
||||||
std::sort(workspaces_.begin(), workspaces_.end(), [&](const auto &w1, const auto &w2) {
|
std::sort(workspaces_.begin(), workspaces_.end(), [&](const auto& w1, const auto& w2) {
|
||||||
if (sort_by_id_ || (!sort_by_name_ && !sort_by_coordinates_)) {
|
if (sort_by_id_ || (!sort_by_name_ && !sort_by_coordinates_)) {
|
||||||
if (w1->workspace_id() == w2->workspace_id()) {
|
if (w1->workspace_id() == w2->workspace_id()) {
|
||||||
return w1->id() < w2->id();
|
return w1->id() < w2->id();
|
||||||
@@ -218,7 +218,7 @@ void WorkspaceManager::sort_workspaces() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorkspaceManager::clear_buttons() {
|
void WorkspaceManager::clear_buttons() {
|
||||||
for (const auto &workspace : workspaces_) {
|
for (const auto& workspace : workspaces_) {
|
||||||
if (has_button(&workspace->button())) {
|
if (has_button(&workspace->button())) {
|
||||||
box_.remove(workspace->button());
|
box_.remove(workspace->button());
|
||||||
}
|
}
|
||||||
@@ -226,13 +226,13 @@ void WorkspaceManager::clear_buttons() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorkspaceManager::update_buttons() {
|
void WorkspaceManager::update_buttons() {
|
||||||
const auto *output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
const auto* output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
||||||
|
|
||||||
// go through all workspace
|
// go through all workspace
|
||||||
|
|
||||||
for (const auto &workspace : workspaces_) {
|
for (const auto& workspace : workspaces_) {
|
||||||
const bool workspace_on_any_group_for_output =
|
const bool workspace_on_any_group_for_output =
|
||||||
std::any_of(groups_.begin(), groups_.end(), [&](const auto &group) {
|
std::any_of(groups_.begin(), groups_.end(), [&](const auto& group) {
|
||||||
const bool group_on_output = group->has_output(output) || all_outputs_;
|
const bool group_on_output = group->has_output(output) || all_outputs_;
|
||||||
const bool workspace_on_group = group->has_workspace(workspace->handle());
|
const bool workspace_on_group = group->has_workspace(workspace->handle());
|
||||||
return group_on_output && workspace_on_group;
|
return group_on_output && workspace_on_group;
|
||||||
@@ -259,7 +259,7 @@ void WorkspaceManager::update_buttons() {
|
|||||||
|
|
||||||
// WorkspaceGroup
|
// WorkspaceGroup
|
||||||
|
|
||||||
WorkspaceGroup::WorkspaceGroup(WorkspaceManager &manager, ext_workspace_group_handle_v1 *handle,
|
WorkspaceGroup::WorkspaceGroup(WorkspaceManager& manager, ext_workspace_group_handle_v1* handle,
|
||||||
uint32_t id)
|
uint32_t id)
|
||||||
: workspaces_manager_(manager), ext_handle_(handle), id_(id) {
|
: workspaces_manager_(manager), ext_handle_(handle), id_(id) {
|
||||||
add_workspace_group_listener(ext_handle_, this);
|
add_workspace_group_listener(ext_handle_, this);
|
||||||
@@ -272,11 +272,11 @@ WorkspaceGroup::~WorkspaceGroup() {
|
|||||||
spdlog::debug("[ext/workspaces]: Workspace group {} destroyed", id_);
|
spdlog::debug("[ext/workspaces]: Workspace group {} destroyed", id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorkspaceGroup::has_output(const wl_output *output) {
|
bool WorkspaceGroup::has_output(const wl_output* output) {
|
||||||
return std::find(outputs_.begin(), outputs_.end(), output) != outputs_.end();
|
return std::find(outputs_.begin(), outputs_.end(), output) != outputs_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorkspaceGroup::has_workspace(const ext_workspace_handle_v1 *workspace) {
|
bool WorkspaceGroup::has_workspace(const ext_workspace_handle_v1* workspace) {
|
||||||
return std::find(workspaces_.begin(), workspaces_.end(), workspace) != workspaces_.end();
|
return std::find(workspaces_.begin(), workspaces_.end(), workspace) != workspaces_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,20 +288,20 @@ void WorkspaceGroup::handle_capabilities(uint32_t capabilities) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorkspaceGroup::handle_output_enter(wl_output *output) { outputs_.push_back(output); }
|
void WorkspaceGroup::handle_output_enter(wl_output* output) { outputs_.push_back(output); }
|
||||||
|
|
||||||
void WorkspaceGroup::handle_output_leave(wl_output *output) {
|
void WorkspaceGroup::handle_output_leave(wl_output* output) {
|
||||||
const auto it = std::find(outputs_.begin(), outputs_.end(), output);
|
const auto it = std::find(outputs_.begin(), outputs_.end(), output);
|
||||||
if (it != outputs_.end()) {
|
if (it != outputs_.end()) {
|
||||||
outputs_.erase(it);
|
outputs_.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorkspaceGroup::handle_workspace_enter(ext_workspace_handle_v1 *handle) {
|
void WorkspaceGroup::handle_workspace_enter(ext_workspace_handle_v1* handle) {
|
||||||
workspaces_.push_back(handle);
|
workspaces_.push_back(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorkspaceGroup::handle_workspace_leave(ext_workspace_handle_v1 *handle) {
|
void WorkspaceGroup::handle_workspace_leave(ext_workspace_handle_v1* handle) {
|
||||||
const auto it = std::find(workspaces_.begin(), workspaces_.end(), handle);
|
const auto it = std::find(workspaces_.begin(), workspaces_.end(), handle);
|
||||||
if (it != workspaces_.end()) {
|
if (it != workspaces_.end()) {
|
||||||
workspaces_.erase(it);
|
workspaces_.erase(it);
|
||||||
@@ -315,30 +315,30 @@ void WorkspaceGroup::handle_removed() {
|
|||||||
|
|
||||||
// Workspace
|
// Workspace
|
||||||
|
|
||||||
Workspace::Workspace(const Json::Value &config, WorkspaceManager &manager,
|
Workspace::Workspace(const Json::Value& config, WorkspaceManager& manager,
|
||||||
ext_workspace_handle_v1 *handle, uint32_t id, const std::string &name)
|
ext_workspace_handle_v1* handle, uint32_t id, const std::string& name)
|
||||||
: workspace_manager_(manager), ext_handle_(handle), id_(id), workspace_id_(name), name_(name) {
|
: workspace_manager_(manager), ext_handle_(handle), id_(id), workspace_id_(name), name_(name) {
|
||||||
add_workspace_listener(ext_handle_, this);
|
add_workspace_listener(ext_handle_, this);
|
||||||
|
|
||||||
// parse configuration
|
// parse configuration
|
||||||
|
|
||||||
const auto &config_active_only = config["active-only"];
|
const auto& config_active_only = config["active-only"];
|
||||||
if (config_active_only.isBool()) {
|
if (config_active_only.isBool()) {
|
||||||
active_only_ = config_active_only.asBool();
|
active_only_ = config_active_only.asBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &config_ignore_hidden = config["ignore-hidden"];
|
const auto& config_ignore_hidden = config["ignore-hidden"];
|
||||||
if (config_ignore_hidden.isBool()) {
|
if (config_ignore_hidden.isBool()) {
|
||||||
ignore_hidden_ = config_ignore_hidden.asBool();
|
ignore_hidden_ = config_ignore_hidden.asBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &config_format = config["format"];
|
const auto& config_format = config["format"];
|
||||||
format_ = config_format.isString() ? config_format.asString() : "{name}";
|
format_ = config_format.isString() ? config_format.asString() : "{name}";
|
||||||
with_icon_ = format_.find("{icon}") != std::string::npos;
|
with_icon_ = format_.find("{icon}") != std::string::npos;
|
||||||
|
|
||||||
if (with_icon_ && icon_map_.empty()) {
|
if (with_icon_ && icon_map_.empty()) {
|
||||||
const auto &format_icons = config["format-icons"];
|
const auto& format_icons = config["format-icons"];
|
||||||
for (auto &n : format_icons.getMemberNames()) {
|
for (auto& n : format_icons.getMemberNames()) {
|
||||||
icon_map_.emplace(n, format_icons[n].asString());
|
icon_map_.emplace(n, format_icons[n].asString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -413,19 +413,19 @@ void Workspace::update() {
|
|||||||
fmt::arg("icon", with_icon_ ? icon() : "")));
|
fmt::arg("icon", with_icon_ ? icon() : "")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::handle_id(const std::string &id) {
|
void Workspace::handle_id(const std::string& id) {
|
||||||
spdlog::debug("[ext/workspaces]: ID for workspace {}: {}", id_, id);
|
spdlog::debug("[ext/workspaces]: ID for workspace {}: {}", id_, id);
|
||||||
workspace_id_ = id;
|
workspace_id_ = id;
|
||||||
workspace_manager_.set_needs_sorting();
|
workspace_manager_.set_needs_sorting();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::handle_name(const std::string &name) {
|
void Workspace::handle_name(const std::string& name) {
|
||||||
spdlog::debug("[ext/workspaces]: Name for workspace {}: {}", id_, name);
|
spdlog::debug("[ext/workspaces]: Name for workspace {}: {}", id_, name);
|
||||||
name_ = name;
|
name_ = name;
|
||||||
workspace_manager_.set_needs_sorting();
|
workspace_manager_.set_needs_sorting();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::handle_coordinates(const std::vector<uint32_t> &coordinates) {
|
void Workspace::handle_coordinates(const std::vector<uint32_t>& coordinates) {
|
||||||
coordinates_ = coordinates;
|
coordinates_ = coordinates;
|
||||||
workspace_manager_.set_needs_sorting();
|
workspace_manager_.set_needs_sorting();
|
||||||
}
|
}
|
||||||
@@ -453,7 +453,7 @@ void Workspace::handle_removed() {
|
|||||||
workspace_manager_.remove_workspace(id_);
|
workspace_manager_.remove_workspace(id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Workspace::handle_clicked(const GdkEventButton *button) const {
|
bool Workspace::handle_clicked(const GdkEventButton* button) const {
|
||||||
std::string action;
|
std::string action;
|
||||||
if (button->button == GDK_BUTTON_PRIMARY) {
|
if (button->button == GDK_BUTTON_PRIMARY) {
|
||||||
action = on_click_action_;
|
action = on_click_action_;
|
||||||
|
|||||||
@@ -9,44 +9,44 @@
|
|||||||
|
|
||||||
namespace waybar::modules::ext {
|
namespace waybar::modules::ext {
|
||||||
|
|
||||||
static void handle_global(void *data, wl_registry *registry, uint32_t name, const char *interface,
|
static void handle_global(void* data, wl_registry* registry, uint32_t name, const char* interface,
|
||||||
uint32_t version) {
|
uint32_t version) {
|
||||||
if (std::strcmp(interface, ext_workspace_manager_v1_interface.name) == 0) {
|
if (std::strcmp(interface, ext_workspace_manager_v1_interface.name) == 0) {
|
||||||
static_cast<WorkspaceManager *>(data)->register_manager(registry, name, version);
|
static_cast<WorkspaceManager*>(data)->register_manager(registry, name, version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_global_remove(void *data, wl_registry *registry, uint32_t name) {
|
static void handle_global_remove(void* data, wl_registry* registry, uint32_t name) {
|
||||||
/* Nothing to do here */
|
/* Nothing to do here */
|
||||||
}
|
}
|
||||||
|
|
||||||
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
|
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
|
||||||
.global_remove = handle_global_remove};
|
.global_remove = handle_global_remove};
|
||||||
|
|
||||||
void add_registry_listener(void *data) {
|
void add_registry_listener(void* data) {
|
||||||
wl_display *display = Client::inst()->wl_display;
|
wl_display* display = Client::inst()->wl_display;
|
||||||
wl_registry *registry = wl_display_get_registry(display);
|
wl_registry* registry = wl_display_get_registry(display);
|
||||||
|
|
||||||
wl_registry_add_listener(registry, ®istry_listener_impl, data);
|
wl_registry_add_listener(registry, ®istry_listener_impl, data);
|
||||||
wl_display_roundtrip(display);
|
wl_display_roundtrip(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_manager_handle_workspace_group(
|
static void workspace_manager_handle_workspace_group(
|
||||||
void *data, ext_workspace_manager_v1 *_, ext_workspace_group_handle_v1 *workspace_group) {
|
void* data, ext_workspace_manager_v1* _, ext_workspace_group_handle_v1* workspace_group) {
|
||||||
static_cast<WorkspaceManager *>(data)->handle_workspace_group(workspace_group);
|
static_cast<WorkspaceManager*>(data)->handle_workspace_group(workspace_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_manager_handle_workspace(void *data, ext_workspace_manager_v1 *_,
|
static void workspace_manager_handle_workspace(void* data, ext_workspace_manager_v1* _,
|
||||||
ext_workspace_handle_v1 *workspace) {
|
ext_workspace_handle_v1* workspace) {
|
||||||
static_cast<WorkspaceManager *>(data)->handle_workspace(workspace);
|
static_cast<WorkspaceManager*>(data)->handle_workspace(workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_manager_handle_done(void *data, ext_workspace_manager_v1 *_) {
|
static void workspace_manager_handle_done(void* data, ext_workspace_manager_v1* _) {
|
||||||
static_cast<WorkspaceManager *>(data)->handle_done();
|
static_cast<WorkspaceManager*>(data)->handle_done();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_manager_handle_finished(void *data, ext_workspace_manager_v1 *_) {
|
static void workspace_manager_handle_finished(void* data, ext_workspace_manager_v1* _) {
|
||||||
static_cast<WorkspaceManager *>(data)->handle_finished();
|
static_cast<WorkspaceManager*>(data)->handle_finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ext_workspace_manager_v1_listener workspace_manager_impl = {
|
static const ext_workspace_manager_v1_listener workspace_manager_impl = {
|
||||||
@@ -56,9 +56,9 @@ static const ext_workspace_manager_v1_listener workspace_manager_impl = {
|
|||||||
.finished = workspace_manager_handle_finished,
|
.finished = workspace_manager_handle_finished,
|
||||||
};
|
};
|
||||||
|
|
||||||
ext_workspace_manager_v1 *workspace_manager_bind(wl_registry *registry, uint32_t name,
|
ext_workspace_manager_v1* workspace_manager_bind(wl_registry* registry, uint32_t name,
|
||||||
uint32_t version, void *data) {
|
uint32_t version, void* data) {
|
||||||
auto *workspace_manager = static_cast<ext_workspace_manager_v1 *>(
|
auto* workspace_manager = static_cast<ext_workspace_manager_v1*>(
|
||||||
wl_registry_bind(registry, name, &ext_workspace_manager_v1_interface, version));
|
wl_registry_bind(registry, name, &ext_workspace_manager_v1_interface, version));
|
||||||
|
|
||||||
if (workspace_manager)
|
if (workspace_manager)
|
||||||
@@ -69,33 +69,33 @@ ext_workspace_manager_v1 *workspace_manager_bind(wl_registry *registry, uint32_t
|
|||||||
return workspace_manager;
|
return workspace_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_group_handle_capabilities(void *data, ext_workspace_group_handle_v1 *_,
|
static void workspace_group_handle_capabilities(void* data, ext_workspace_group_handle_v1* _,
|
||||||
uint32_t capabilities) {
|
uint32_t capabilities) {
|
||||||
static_cast<WorkspaceGroup *>(data)->handle_capabilities(capabilities);
|
static_cast<WorkspaceGroup*>(data)->handle_capabilities(capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_group_handle_output_enter(void *data, ext_workspace_group_handle_v1 *_,
|
static void workspace_group_handle_output_enter(void* data, ext_workspace_group_handle_v1* _,
|
||||||
wl_output *output) {
|
wl_output* output) {
|
||||||
static_cast<WorkspaceGroup *>(data)->handle_output_enter(output);
|
static_cast<WorkspaceGroup*>(data)->handle_output_enter(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_group_handle_output_leave(void *data, ext_workspace_group_handle_v1 *_,
|
static void workspace_group_handle_output_leave(void* data, ext_workspace_group_handle_v1* _,
|
||||||
wl_output *output) {
|
wl_output* output) {
|
||||||
static_cast<WorkspaceGroup *>(data)->handle_output_leave(output);
|
static_cast<WorkspaceGroup*>(data)->handle_output_leave(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_group_handle_workspace_enter(void *data, ext_workspace_group_handle_v1 *_,
|
static void workspace_group_handle_workspace_enter(void* data, ext_workspace_group_handle_v1* _,
|
||||||
ext_workspace_handle_v1 *workspace) {
|
ext_workspace_handle_v1* workspace) {
|
||||||
static_cast<WorkspaceGroup *>(data)->handle_workspace_enter(workspace);
|
static_cast<WorkspaceGroup*>(data)->handle_workspace_enter(workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_group_handle_workspace_leave(void *data, ext_workspace_group_handle_v1 *_,
|
static void workspace_group_handle_workspace_leave(void* data, ext_workspace_group_handle_v1* _,
|
||||||
ext_workspace_handle_v1 *workspace) {
|
ext_workspace_handle_v1* workspace) {
|
||||||
static_cast<WorkspaceGroup *>(data)->handle_workspace_leave(workspace);
|
static_cast<WorkspaceGroup*>(data)->handle_workspace_leave(workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_group_handle_removed(void *data, ext_workspace_group_handle_v1 *_) {
|
static void workspace_group_handle_removed(void* data, ext_workspace_group_handle_v1* _) {
|
||||||
static_cast<WorkspaceGroup *>(data)->handle_removed();
|
static_cast<WorkspaceGroup*>(data)->handle_removed();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ext_workspace_group_handle_v1_listener workspace_group_impl = {
|
static const ext_workspace_group_handle_v1_listener workspace_group_impl = {
|
||||||
@@ -106,43 +106,43 @@ static const ext_workspace_group_handle_v1_listener workspace_group_impl = {
|
|||||||
.workspace_leave = workspace_group_handle_workspace_leave,
|
.workspace_leave = workspace_group_handle_workspace_leave,
|
||||||
.removed = workspace_group_handle_removed};
|
.removed = workspace_group_handle_removed};
|
||||||
|
|
||||||
void add_workspace_group_listener(ext_workspace_group_handle_v1 *workspace_group_handle,
|
void add_workspace_group_listener(ext_workspace_group_handle_v1* workspace_group_handle,
|
||||||
void *data) {
|
void* data) {
|
||||||
ext_workspace_group_handle_v1_add_listener(workspace_group_handle, &workspace_group_impl, data);
|
ext_workspace_group_handle_v1_add_listener(workspace_group_handle, &workspace_group_impl, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void workspace_handle_name(void *data, struct ext_workspace_handle_v1 *_, const char *name) {
|
void workspace_handle_name(void* data, struct ext_workspace_handle_v1* _, const char* name) {
|
||||||
static_cast<Workspace *>(data)->handle_name(name);
|
static_cast<Workspace*>(data)->handle_name(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void workspace_handle_id(void *data, struct ext_workspace_handle_v1 *_, const char *id) {
|
void workspace_handle_id(void* data, struct ext_workspace_handle_v1* _, const char* id) {
|
||||||
static_cast<Workspace *>(data)->handle_id(id);
|
static_cast<Workspace*>(data)->handle_id(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void workspace_handle_coordinates(void *data, struct ext_workspace_handle_v1 *_,
|
void workspace_handle_coordinates(void* data, struct ext_workspace_handle_v1* _,
|
||||||
struct wl_array *coordinates) {
|
struct wl_array* coordinates) {
|
||||||
std::vector<uint32_t> coords_vec;
|
std::vector<uint32_t> coords_vec;
|
||||||
auto coords = static_cast<uint32_t *>(coordinates->data);
|
auto coords = static_cast<uint32_t*>(coordinates->data);
|
||||||
for (size_t i = 0; i < coordinates->size / sizeof(uint32_t); ++i) {
|
for (size_t i = 0; i < coordinates->size / sizeof(uint32_t); ++i) {
|
||||||
coords_vec.push_back(coords[i]);
|
coords_vec.push_back(coords[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static_cast<Workspace *>(data)->handle_coordinates(coords_vec);
|
static_cast<Workspace*>(data)->handle_coordinates(coords_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void workspace_handle_state(void *data, struct ext_workspace_handle_v1 *workspace_handle,
|
void workspace_handle_state(void* data, struct ext_workspace_handle_v1* workspace_handle,
|
||||||
uint32_t state) {
|
uint32_t state) {
|
||||||
static_cast<Workspace *>(data)->handle_state(state);
|
static_cast<Workspace*>(data)->handle_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void workspace_handle_capabilities(void *data,
|
static void workspace_handle_capabilities(void* data,
|
||||||
struct ext_workspace_handle_v1 *workspace_handle,
|
struct ext_workspace_handle_v1* workspace_handle,
|
||||||
uint32_t capabilities) {
|
uint32_t capabilities) {
|
||||||
static_cast<Workspace *>(data)->handle_capabilities(capabilities);
|
static_cast<Workspace*>(data)->handle_capabilities(capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
void workspace_handle_removed(void *data, struct ext_workspace_handle_v1 *workspace_handle) {
|
void workspace_handle_removed(void* data, struct ext_workspace_handle_v1* workspace_handle) {
|
||||||
static_cast<Workspace *>(data)->handle_removed();
|
static_cast<Workspace*>(data)->handle_removed();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ext_workspace_handle_v1_listener workspace_impl = {
|
static const ext_workspace_handle_v1_listener workspace_impl = {
|
||||||
@@ -153,7 +153,7 @@ static const ext_workspace_handle_v1_listener workspace_impl = {
|
|||||||
.capabilities = workspace_handle_capabilities,
|
.capabilities = workspace_handle_capabilities,
|
||||||
.removed = workspace_handle_removed};
|
.removed = workspace_handle_removed};
|
||||||
|
|
||||||
void add_workspace_listener(ext_workspace_handle_v1 *workspace_handle, void *data) {
|
void add_workspace_listener(ext_workspace_handle_v1* workspace_handle, void* data) {
|
||||||
ext_workspace_handle_v1_add_listener(workspace_handle, &workspace_impl, data);
|
ext_workspace_handle_v1_add_listener(workspace_handle, &workspace_impl, data);
|
||||||
}
|
}
|
||||||
} // namespace waybar::modules::ext
|
} // namespace waybar::modules::ext
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ auto Gamemode::update() -> void {
|
|||||||
// Tooltip
|
// Tooltip
|
||||||
if (tooltip) {
|
if (tooltip) {
|
||||||
std::string text = fmt::format(fmt::runtime(tooltip_format), fmt::arg("count", gameCount));
|
std::string text = fmt::format(fmt::runtime(tooltip_format), fmt::arg("count", gameCount));
|
||||||
box_.set_tooltip_text(text);
|
box_.set_tooltip_markup(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Label format
|
// Label format
|
||||||
|
|||||||
@@ -44,12 +44,23 @@ auto Submap::parseConfig(const Json::Value& config) -> void {
|
|||||||
auto Submap::update() -> void {
|
auto Submap::update() -> void {
|
||||||
std::lock_guard<std::mutex> lg(mutex_);
|
std::lock_guard<std::mutex> lg(mutex_);
|
||||||
|
|
||||||
|
// Handle style class changes
|
||||||
|
if (!prev_submap_.empty()) {
|
||||||
|
label_.get_style_context()->remove_class(prev_submap_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!submap_.empty()) {
|
||||||
|
label_.get_style_context()->add_class(submap_);
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_submap_ = submap_;
|
||||||
|
|
||||||
if (submap_.empty()) {
|
if (submap_.empty()) {
|
||||||
event_box_.hide();
|
event_box_.hide();
|
||||||
} else {
|
} else {
|
||||||
label_.set_markup(fmt::format(fmt::runtime(format_), submap_));
|
label_.set_markup(fmt::format(fmt::runtime(format_), submap_));
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
label_.set_tooltip_text(submap_);
|
label_.set_tooltip_markup(submap_);
|
||||||
}
|
}
|
||||||
event_box_.show();
|
event_box_.show();
|
||||||
}
|
}
|
||||||
@@ -66,18 +77,12 @@ void Submap::onEvent(const std::string& ev) {
|
|||||||
|
|
||||||
auto submapName = ev.substr(ev.find_first_of('>') + 2);
|
auto submapName = ev.substr(ev.find_first_of('>') + 2);
|
||||||
|
|
||||||
if (!submap_.empty()) {
|
|
||||||
label_.get_style_context()->remove_class(submap_);
|
|
||||||
}
|
|
||||||
|
|
||||||
submap_ = submapName;
|
submap_ = submapName;
|
||||||
|
|
||||||
if (submap_.empty() && always_on_) {
|
if (submap_.empty() && always_on_) {
|
||||||
submap_ = default_submap_;
|
submap_ = default_submap_;
|
||||||
}
|
}
|
||||||
|
|
||||||
label_.get_style_context()->add_class(submap_);
|
|
||||||
|
|
||||||
spdlog::debug("hyprland submap onevent with {}", submap_);
|
spdlog::debug("hyprland submap onevent with {}", submap_);
|
||||||
|
|
||||||
dp.emit();
|
dp.emit();
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ Window::~Window() {
|
|||||||
auto Window::update() -> void {
|
auto Window::update() -> void {
|
||||||
std::shared_lock<std::shared_mutex> windowIpcShareLock(windowIpcSmtx);
|
std::shared_lock<std::shared_mutex> windowIpcShareLock(windowIpcSmtx);
|
||||||
|
|
||||||
|
queryActiveWorkspace();
|
||||||
|
|
||||||
std::string windowName = waybar::util::sanitize_string(workspace_.last_window_title);
|
std::string windowName = waybar::util::sanitize_string(workspace_.last_window_title);
|
||||||
std::string windowAddress = workspace_.last_window;
|
std::string windowAddress = workspace_.last_window;
|
||||||
|
|
||||||
@@ -70,13 +72,13 @@ auto Window::update() -> void {
|
|||||||
tooltip_format = config_["tooltip-format"].asString();
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
}
|
}
|
||||||
if (!tooltip_format.empty()) {
|
if (!tooltip_format.empty()) {
|
||||||
label_.set_tooltip_text(
|
label_.set_tooltip_markup(
|
||||||
fmt::format(fmt::runtime(tooltip_format), fmt::arg("title", windowName),
|
fmt::format(fmt::runtime(tooltip_format), fmt::arg("title", windowName),
|
||||||
fmt::arg("initialTitle", windowData_.initial_title),
|
fmt::arg("initialTitle", windowData_.initial_title),
|
||||||
fmt::arg("class", windowData_.class_name),
|
fmt::arg("class", windowData_.class_name),
|
||||||
fmt::arg("initialClass", windowData_.initial_class_name)));
|
fmt::arg("initialClass", windowData_.initial_class_name)));
|
||||||
} else if (!label_text.empty()) {
|
} else if (!label_text.empty()) {
|
||||||
label_.set_tooltip_text(label_text);
|
label_.set_tooltip_markup(label_text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,11 +237,7 @@ void Window::queryActiveWorkspace() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::onEvent(const std::string& ev) {
|
void Window::onEvent(const std::string& ev) { dp.emit(); }
|
||||||
queryActiveWorkspace();
|
|
||||||
|
|
||||||
dp.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::setClass(const std::string& classname, bool enable) {
|
void Window::setClass(const std::string& classname, bool enable) {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ WindowCount::~WindowCount() {
|
|||||||
auto WindowCount::update() -> void {
|
auto WindowCount::update() -> void {
|
||||||
std::lock_guard<std::mutex> lg(mutex_);
|
std::lock_guard<std::mutex> lg(mutex_);
|
||||||
|
|
||||||
|
queryActiveWorkspace();
|
||||||
|
|
||||||
std::string format = config_["format"].asString();
|
std::string format = config_["format"].asString();
|
||||||
std::string formatEmpty = config_["format-empty"].asString();
|
std::string formatEmpty = config_["format-empty"].asString();
|
||||||
std::string formatWindowed = config_["format-windowed"].asString();
|
std::string formatWindowed = config_["format-windowed"].asString();
|
||||||
@@ -56,7 +58,7 @@ auto WindowCount::update() -> void {
|
|||||||
} else if (!format.empty()) {
|
} else if (!format.empty()) {
|
||||||
label_.set_markup(fmt::format(fmt::runtime(format), workspace_.windows));
|
label_.set_markup(fmt::format(fmt::runtime(format), workspace_.windows));
|
||||||
} else {
|
} else {
|
||||||
label_.set_text(fmt::format("{}", workspace_.windows));
|
label_.set_markup(fmt::format("{}", workspace_.windows));
|
||||||
}
|
}
|
||||||
|
|
||||||
label_.show();
|
label_.show();
|
||||||
@@ -116,8 +118,6 @@ auto WindowCount::Workspace::parse(const Json::Value& value) -> WindowCount::Wor
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WindowCount::queryActiveWorkspace() {
|
void WindowCount::queryActiveWorkspace() {
|
||||||
std::lock_guard<std::mutex> lg(mutex_);
|
|
||||||
|
|
||||||
if (separateOutputs_) {
|
if (separateOutputs_) {
|
||||||
workspace_ = getActiveWorkspace(this->bar_.output->name);
|
workspace_ = getActiveWorkspace(this->bar_.output->name);
|
||||||
} else {
|
} else {
|
||||||
@@ -125,10 +125,7 @@ void WindowCount::queryActiveWorkspace() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowCount::onEvent(const std::string& ev) {
|
void WindowCount::onEvent(const std::string& ev) { dp.emit(); }
|
||||||
queryActiveWorkspace();
|
|
||||||
dp.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowCount::setClass(const std::string& classname, bool enable) {
|
void WindowCount::setClass(const std::string& classname, bool enable) {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
namespace waybar::modules::hyprland {
|
namespace waybar::modules::hyprland {
|
||||||
|
|
||||||
WindowCreationPayload::WindowCreationPayload(Json::Value const &client_data)
|
WindowCreationPayload::WindowCreationPayload(Json::Value const& client_data)
|
||||||
: m_window(std::make_pair(client_data["class"].asString(), client_data["title"].asString())),
|
: m_window(std::make_pair(client_data["class"].asString(), client_data["title"].asString())),
|
||||||
m_windowAddress(client_data["address"].asString()),
|
m_windowAddress(client_data["address"].asString()),
|
||||||
m_workspaceName(client_data["workspace"]["name"].asString()) {
|
m_workspaceName(client_data["workspace"]["name"].asString()) {
|
||||||
@@ -73,7 +73,7 @@ void WindowCreationPayload::clearWorkspaceName() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowCreationPayload::isEmpty(Workspaces &workspace_manager) {
|
bool WindowCreationPayload::isEmpty(Workspaces& workspace_manager) {
|
||||||
if (std::holds_alternative<Repr>(m_window)) {
|
if (std::holds_alternative<Repr>(m_window)) {
|
||||||
return std::get<Repr>(m_window).empty();
|
return std::get<Repr>(m_window).empty();
|
||||||
}
|
}
|
||||||
@@ -89,16 +89,16 @@ bool WindowCreationPayload::isEmpty(Workspaces &workspace_manager) {
|
|||||||
|
|
||||||
int WindowCreationPayload::incrementTimeSpentUncreated() { return m_timeSpentUncreated++; }
|
int WindowCreationPayload::incrementTimeSpentUncreated() { return m_timeSpentUncreated++; }
|
||||||
|
|
||||||
void WindowCreationPayload::moveToWorkspace(std::string &new_workspace_name) {
|
void WindowCreationPayload::moveToWorkspace(std::string& new_workspace_name) {
|
||||||
m_workspaceName = new_workspace_name;
|
m_workspaceName = new_workspace_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowRepr WindowCreationPayload::repr(Workspaces &workspace_manager) {
|
WindowRepr WindowCreationPayload::repr(Workspaces& workspace_manager) {
|
||||||
if (std::holds_alternative<Repr>(m_window)) {
|
if (std::holds_alternative<Repr>(m_window)) {
|
||||||
return std::get<Repr>(m_window);
|
return std::get<Repr>(m_window);
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<ClassAndTitle>(m_window)) {
|
if (std::holds_alternative<ClassAndTitle>(m_window)) {
|
||||||
auto const &[window_class, window_title] = std::get<ClassAndTitle>(m_window);
|
auto const& [window_class, window_title] = std::get<ClassAndTitle>(m_window);
|
||||||
return {m_windowAddress, window_class, window_title,
|
return {m_windowAddress, window_class, window_title,
|
||||||
workspace_manager.getRewrite(window_class, window_title), m_isActive};
|
workspace_manager.getRewrite(window_class, window_title), m_isActive};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
|
|
||||||
namespace waybar::modules::hyprland {
|
namespace waybar::modules::hyprland {
|
||||||
|
|
||||||
Workspace::Workspace(const Json::Value &workspace_data, Workspaces &workspace_manager,
|
Workspace::Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager,
|
||||||
const Json::Value &clients_data)
|
const Json::Value& clients_data)
|
||||||
: m_workspaceManager(workspace_manager),
|
: m_workspaceManager(workspace_manager),
|
||||||
m_id(workspace_data["id"].asInt()),
|
m_id(workspace_data["id"].asInt()),
|
||||||
m_name(workspace_data["name"].asString()),
|
m_name(workspace_data["name"].asString()),
|
||||||
@@ -45,8 +45,8 @@ Workspace::Workspace(const Json::Value &workspace_data, Workspaces &workspace_ma
|
|||||||
initializeWindowMap(clients_data);
|
initializeWindowMap(clients_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addOrRemoveClass(const Glib::RefPtr<Gtk::StyleContext> &context, bool condition,
|
void addOrRemoveClass(const Glib::RefPtr<Gtk::StyleContext>& context, bool condition,
|
||||||
const std::string &class_name) {
|
const std::string& class_name) {
|
||||||
if (condition) {
|
if (condition) {
|
||||||
context->add_class(class_name);
|
context->add_class(class_name);
|
||||||
} else {
|
} else {
|
||||||
@@ -54,9 +54,9 @@ void addOrRemoveClass(const Glib::RefPtr<Gtk::StyleContext> &context, bool condi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<WindowRepr> Workspace::closeWindow(WindowAddress const &addr) {
|
std::optional<WindowRepr> Workspace::closeWindow(WindowAddress const& addr) {
|
||||||
auto it = std::ranges::find_if(m_windowMap,
|
auto it = std::ranges::find_if(m_windowMap,
|
||||||
[&addr](const auto &window) { return window.address == addr; });
|
[&addr](const auto& window) { return window.address == addr; });
|
||||||
// If the vector contains the address, remove it and return the window representation
|
// If the vector contains the address, remove it and return the window representation
|
||||||
if (it != m_windowMap.end()) {
|
if (it != m_windowMap.end()) {
|
||||||
WindowRepr windowRepr = *it;
|
WindowRepr windowRepr = *it;
|
||||||
@@ -66,7 +66,7 @@ std::optional<WindowRepr> Workspace::closeWindow(WindowAddress const &addr) {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Workspace::handleClicked(GdkEventButton *bt) const {
|
bool Workspace::handleClicked(GdkEventButton* bt) const {
|
||||||
if (bt->type == GDK_BUTTON_PRESS) {
|
if (bt->type == GDK_BUTTON_PRESS) {
|
||||||
try {
|
try {
|
||||||
if (id() > 0) { // normal
|
if (id() > 0) { // normal
|
||||||
@@ -87,14 +87,14 @@ bool Workspace::handleClicked(GdkEventButton *bt) const {
|
|||||||
m_ipc.getSocket1Reply("dispatch togglespecialworkspace");
|
m_ipc.getSocket1Reply("dispatch togglespecialworkspace");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception& e) {
|
||||||
spdlog::error("Failed to dispatch workspace: {}", e.what());
|
spdlog::error("Failed to dispatch workspace: {}", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::initializeWindowMap(const Json::Value &clients_data) {
|
void Workspace::initializeWindowMap(const Json::Value& clients_data) {
|
||||||
m_windowMap.clear();
|
m_windowMap.clear();
|
||||||
for (auto client : clients_data) {
|
for (auto client : clients_data) {
|
||||||
if (client["workspace"]["id"].asInt() == id()) {
|
if (client["workspace"]["id"].asInt() == id()) {
|
||||||
@@ -103,10 +103,10 @@ void Workspace::initializeWindowMap(const Json::Value &clients_data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::setActiveWindow(WindowAddress const &addr) {
|
void Workspace::setActiveWindow(WindowAddress const& addr) {
|
||||||
std::optional<long> activeIdx;
|
std::optional<long> activeIdx;
|
||||||
for (size_t i = 0; i < m_windowMap.size(); ++i) {
|
for (size_t i = 0; i < m_windowMap.size(); ++i) {
|
||||||
auto &window = m_windowMap[i];
|
auto& window = m_windowMap[i];
|
||||||
bool isActive = (window.address == addr);
|
bool isActive = (window.address == addr);
|
||||||
window.setActive(isActive);
|
window.setActive(isActive);
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
@@ -133,7 +133,7 @@ void Workspace::insertWindow(WindowCreationPayload create_window_payload) {
|
|||||||
if (!repr.empty() || m_workspaceManager.enableTaskbar()) {
|
if (!repr.empty() || m_workspaceManager.enableTaskbar()) {
|
||||||
auto addr = create_window_payload.getAddress();
|
auto addr = create_window_payload.getAddress();
|
||||||
auto it = std::ranges::find_if(
|
auto it = std::ranges::find_if(
|
||||||
m_windowMap, [&addr](const auto &window) { return window.address == addr; });
|
m_windowMap, [&addr](const auto& window) { return window.address == addr; });
|
||||||
// If the vector contains the address, update the window representation, otherwise insert it
|
// If the vector contains the address, update the window representation, otherwise insert it
|
||||||
if (it != m_windowMap.end()) {
|
if (it != m_windowMap.end()) {
|
||||||
*it = repr;
|
*it = repr;
|
||||||
@@ -144,7 +144,7 @@ void Workspace::insertWindow(WindowCreationPayload create_window_payload) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Workspace::onWindowOpened(WindowCreationPayload const &create_window_payload) {
|
bool Workspace::onWindowOpened(WindowCreationPayload const& create_window_payload) {
|
||||||
if (create_window_payload.getWorkspaceName() == name()) {
|
if (create_window_payload.getWorkspaceName() == name()) {
|
||||||
insertWindow(create_window_payload);
|
insertWindow(create_window_payload);
|
||||||
return true;
|
return true;
|
||||||
@@ -152,7 +152,7 @@ bool Workspace::onWindowOpened(WindowCreationPayload const &create_window_payloa
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string &Workspace::selectIcon(std::map<std::string, std::string> &icons_map) {
|
std::string& Workspace::selectIcon(std::map<std::string, std::string>& icons_map) {
|
||||||
spdlog::trace("Selecting icon for workspace {}", name());
|
spdlog::trace("Selecting icon for workspace {}", name());
|
||||||
if (isUrgent()) {
|
if (isUrgent()) {
|
||||||
auto urgentIconIt = icons_map.find("urgent");
|
auto urgentIconIt = icons_map.find("urgent");
|
||||||
@@ -209,7 +209,7 @@ std::string &Workspace::selectIcon(std::map<std::string, std::string> &icons_map
|
|||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::update(const std::string &workspace_icon) {
|
void Workspace::update(const std::string& workspace_icon) {
|
||||||
if (this->m_workspaceManager.persistentOnly() && !this->isPersistent()) {
|
if (this->m_workspaceManager.persistentOnly() && !this->isPersistent()) {
|
||||||
m_button.hide();
|
m_button.hide();
|
||||||
return;
|
return;
|
||||||
@@ -248,7 +248,7 @@ void Workspace::update(const std::string &workspace_icon) {
|
|||||||
|
|
||||||
bool isNotFirst = false;
|
bool isNotFirst = false;
|
||||||
|
|
||||||
for (const auto &window_repr : m_windowMap) {
|
for (const auto& window_repr : m_windowMap) {
|
||||||
if (isNotFirst) {
|
if (isNotFirst) {
|
||||||
windows.append(windowSeparator);
|
windows.append(windowSeparator);
|
||||||
}
|
}
|
||||||
@@ -284,12 +284,10 @@ bool Workspace::isEmpty() const {
|
|||||||
// Otherwise, check if every window in the map should be skipped (ignored)
|
// Otherwise, check if every window in the map should be skipped (ignored)
|
||||||
return std::all_of(
|
return std::all_of(
|
||||||
m_windowMap.begin(), m_windowMap.end(),
|
m_windowMap.begin(), m_windowMap.end(),
|
||||||
[this, &ignore_list](const auto &window_repr) {
|
[this, &ignore_list](const auto& window_repr) { return shouldSkipWindow(window_repr); });
|
||||||
return shouldSkipWindow(window_repr);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::updateTaskbar(const std::string &workspace_icon) {
|
void Workspace::updateTaskbar(const std::string& workspace_icon) {
|
||||||
for (auto child : m_content.get_children()) {
|
for (auto child : m_content.get_children()) {
|
||||||
if (child != &m_labelBefore) {
|
if (child != &m_labelBefore) {
|
||||||
m_content.remove(*child);
|
m_content.remove(*child);
|
||||||
@@ -297,7 +295,7 @@ void Workspace::updateTaskbar(const std::string &workspace_icon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isFirst = true;
|
bool isFirst = true;
|
||||||
auto processWindow = [&](const WindowRepr &window_repr) {
|
auto processWindow = [&](const WindowRepr& window_repr) {
|
||||||
if (shouldSkipWindow(window_repr)) {
|
if (shouldSkipWindow(window_repr)) {
|
||||||
return; // skip
|
return; // skip
|
||||||
}
|
}
|
||||||
@@ -310,7 +308,7 @@ void Workspace::updateTaskbar(const std::string &workspace_icon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto window_box = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_HORIZONTAL);
|
auto window_box = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_HORIZONTAL);
|
||||||
window_box->set_tooltip_text(window_repr.window_title);
|
window_box->set_tooltip_markup(window_repr.window_title);
|
||||||
window_box->get_style_context()->add_class("taskbar-window");
|
window_box->get_style_context()->add_class("taskbar-window");
|
||||||
if (window_repr.isActive) {
|
if (window_repr.isActive) {
|
||||||
window_box->get_style_context()->add_class("active");
|
window_box->get_style_context()->add_class("active");
|
||||||
@@ -353,7 +351,7 @@ void Workspace::updateTaskbar(const std::string &workspace_icon) {
|
|||||||
processWindow(*it);
|
processWindow(*it);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const auto &window_repr : m_windowMap) {
|
for (const auto& window_repr : m_windowMap) {
|
||||||
processWindow(window_repr);
|
processWindow(window_repr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,7 +366,7 @@ void Workspace::updateTaskbar(const std::string &workspace_icon) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Workspace::handleClick(const GdkEventButton *event_button, WindowAddress const &addr) const {
|
bool Workspace::handleClick(const GdkEventButton* event_button, WindowAddress const& addr) const {
|
||||||
if (event_button->type == GDK_BUTTON_PRESS) {
|
if (event_button->type == GDK_BUTTON_PRESS) {
|
||||||
std::string command = std::regex_replace(m_workspaceManager.onClickWindow(),
|
std::string command = std::regex_replace(m_workspaceManager.onClickWindow(),
|
||||||
std::regex("\\{address\\}"), "0x" + addr);
|
std::regex("\\{address\\}"), "0x" + addr);
|
||||||
@@ -382,9 +380,9 @@ bool Workspace::handleClick(const GdkEventButton *event_button, WindowAddress co
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Workspace::shouldSkipWindow(const WindowRepr &window_repr) const {
|
bool Workspace::shouldSkipWindow(const WindowRepr& window_repr) const {
|
||||||
auto ignore_list = m_workspaceManager.getIgnoredWindows();
|
auto ignore_list = m_workspaceManager.getIgnoredWindows();
|
||||||
auto it = std::ranges::find_if(ignore_list, [&window_repr](const auto &ignoreItem) {
|
auto it = std::ranges::find_if(ignore_list, [&window_repr](const auto& ignoreItem) {
|
||||||
return std::regex_match(window_repr.window_class, ignoreItem) ||
|
return std::regex_match(window_repr.window_class, ignoreItem) ||
|
||||||
std::regex_match(window_repr.window_title, ignoreItem);
|
std::regex_match(window_repr.window_title, ignoreItem);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
namespace waybar::modules::hyprland {
|
namespace waybar::modules::hyprland {
|
||||||
|
|
||||||
Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config)
|
Workspaces::Workspaces(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||||
: AModule(config, "workspaces", id, false, false),
|
: AModule(config, "workspaces", id, false, false),
|
||||||
m_bar(bar),
|
m_bar(bar),
|
||||||
m_box(bar.orientation, 0),
|
m_box(bar.orientation, 0),
|
||||||
@@ -43,11 +43,18 @@ void Workspaces::init() {
|
|||||||
m_activeWorkspaceId = m_ipc.getSocket1JsonReply("activeworkspace")["id"].asInt();
|
m_activeWorkspaceId = m_ipc.getSocket1JsonReply("activeworkspace")["id"].asInt();
|
||||||
|
|
||||||
initializeWorkspaces();
|
initializeWorkspaces();
|
||||||
|
|
||||||
|
if (barScroll()) {
|
||||||
|
auto &window = const_cast<Bar &>(m_bar).window;
|
||||||
|
window.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
||||||
|
window.signal_scroll_event().connect(sigc::mem_fun(*this, &Workspaces::handleScroll));
|
||||||
|
}
|
||||||
|
|
||||||
dp.emit();
|
dp.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value Workspaces::createMonitorWorkspaceData(std::string const &name,
|
Json::Value Workspaces::createMonitorWorkspaceData(std::string const& name,
|
||||||
std::string const &monitor) {
|
std::string const& monitor) {
|
||||||
spdlog::trace("Creating persistent workspace: {} on monitor {}", name, monitor);
|
spdlog::trace("Creating persistent workspace: {} on monitor {}", name, monitor);
|
||||||
Json::Value workspaceData;
|
Json::Value workspaceData;
|
||||||
|
|
||||||
@@ -62,14 +69,14 @@ Json::Value Workspaces::createMonitorWorkspaceData(std::string const &name,
|
|||||||
return workspaceData;
|
return workspaceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::createWorkspace(Json::Value const &workspace_data,
|
void Workspaces::createWorkspace(Json::Value const& workspace_data,
|
||||||
Json::Value const &clients_data) {
|
Json::Value const& clients_data) {
|
||||||
auto workspaceName = workspace_data["name"].asString();
|
auto workspaceName = workspace_data["name"].asString();
|
||||||
auto workspaceId = workspace_data["id"].asInt();
|
auto workspaceId = workspace_data["id"].asInt();
|
||||||
spdlog::debug("Creating workspace {}", workspaceName);
|
spdlog::debug("Creating workspace {}", workspaceName);
|
||||||
|
|
||||||
// avoid recreating existing workspaces
|
// avoid recreating existing workspaces
|
||||||
auto workspace = std::ranges::find_if(m_workspaces, [&](std::unique_ptr<Workspace> const &w) {
|
auto workspace = std::ranges::find_if(m_workspaces, [&](std::unique_ptr<Workspace> const& w) {
|
||||||
if (workspaceId > 0) {
|
if (workspaceId > 0) {
|
||||||
return w->id() == workspaceId;
|
return w->id() == workspaceId;
|
||||||
}
|
}
|
||||||
@@ -81,7 +88,7 @@ void Workspaces::createWorkspace(Json::Value const &workspace_data,
|
|||||||
// don't recreate workspace, but update persistency if necessary
|
// don't recreate workspace, but update persistency if necessary
|
||||||
const auto keys = workspace_data.getMemberNames();
|
const auto keys = workspace_data.getMemberNames();
|
||||||
|
|
||||||
const auto *k = "persistent-rule";
|
const auto* k = "persistent-rule";
|
||||||
if (std::ranges::find(keys, k) != keys.end()) {
|
if (std::ranges::find(keys, k) != keys.end()) {
|
||||||
spdlog::debug("Set dynamic persistency of workspace {} to: {}", workspaceName,
|
spdlog::debug("Set dynamic persistency of workspace {} to: {}", workspaceName,
|
||||||
workspace_data[k].asBool() ? "true" : "false");
|
workspace_data[k].asBool() ? "true" : "false");
|
||||||
@@ -100,14 +107,14 @@ void Workspaces::createWorkspace(Json::Value const &workspace_data,
|
|||||||
|
|
||||||
// create new workspace
|
// create new workspace
|
||||||
m_workspaces.emplace_back(std::make_unique<Workspace>(workspace_data, *this, clients_data));
|
m_workspaces.emplace_back(std::make_unique<Workspace>(workspace_data, *this, clients_data));
|
||||||
Gtk::Button &newWorkspaceButton = m_workspaces.back()->button();
|
Gtk::Button& newWorkspaceButton = m_workspaces.back()->button();
|
||||||
m_box.pack_start(newWorkspaceButton, false, false);
|
m_box.pack_start(newWorkspaceButton, false, false);
|
||||||
sortWorkspaces();
|
sortWorkspaces();
|
||||||
newWorkspaceButton.show_all();
|
newWorkspaceButton.show_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::createWorkspacesToCreate() {
|
void Workspaces::createWorkspacesToCreate() {
|
||||||
for (const auto &[workspaceData, clientsData] : m_workspacesToCreate) {
|
for (const auto& [workspaceData, clientsData] : m_workspacesToCreate) {
|
||||||
createWorkspace(workspaceData, clientsData);
|
createWorkspace(workspaceData, clientsData);
|
||||||
}
|
}
|
||||||
if (!m_workspacesToCreate.empty()) {
|
if (!m_workspacesToCreate.empty()) {
|
||||||
@@ -139,9 +146,9 @@ void Workspaces::doUpdate() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::extendOrphans(int workspaceId, Json::Value const &clientsJson) {
|
void Workspaces::extendOrphans(int workspaceId, Json::Value const& clientsJson) {
|
||||||
spdlog::trace("Extending orphans with workspace {}", workspaceId);
|
spdlog::trace("Extending orphans with workspace {}", workspaceId);
|
||||||
for (const auto &client : clientsJson) {
|
for (const auto& client : clientsJson) {
|
||||||
if (client["workspace"]["id"].asInt() == workspaceId) {
|
if (client["workspace"]["id"].asInt() == workspaceId) {
|
||||||
registerOrphanWindow({client});
|
registerOrphanWindow({client});
|
||||||
}
|
}
|
||||||
@@ -163,7 +170,7 @@ std::string Workspaces::getRewrite(std::string window_class, std::string window_
|
|||||||
std::vector<int> Workspaces::getVisibleWorkspaces() {
|
std::vector<int> Workspaces::getVisibleWorkspaces() {
|
||||||
std::vector<int> visibleWorkspaces;
|
std::vector<int> visibleWorkspaces;
|
||||||
auto monitors = IPC::inst().getSocket1JsonReply("monitors");
|
auto monitors = IPC::inst().getSocket1JsonReply("monitors");
|
||||||
for (const auto &monitor : monitors) {
|
for (const auto& monitor : monitors) {
|
||||||
auto ws = monitor["activeWorkspace"];
|
auto ws = monitor["activeWorkspace"];
|
||||||
if (ws.isObject() && ws["id"].isInt()) {
|
if (ws.isObject() && ws["id"].isInt()) {
|
||||||
visibleWorkspaces.push_back(ws["id"].asInt());
|
visibleWorkspaces.push_back(ws["id"].asInt());
|
||||||
@@ -181,7 +188,7 @@ void Workspaces::initializeWorkspaces() {
|
|||||||
spdlog::debug("Initializing workspaces");
|
spdlog::debug("Initializing workspaces");
|
||||||
|
|
||||||
// if the workspace rules changed since last initialization, make sure we reset everything:
|
// if the workspace rules changed since last initialization, make sure we reset everything:
|
||||||
for (auto &workspace : m_workspaces) {
|
for (auto& workspace : m_workspaces) {
|
||||||
m_workspacesToRemove.push_back(std::to_string(workspace->id()));
|
m_workspacesToRemove.push_back(std::to_string(workspace->id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +216,7 @@ void Workspaces::initializeWorkspaces() {
|
|||||||
loadPersistentWorkspacesFromWorkspaceRules(clientsJson);
|
loadPersistentWorkspacesFromWorkspaceRules(clientsJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDoubleSpecial(std::string const &workspace_name) {
|
bool isDoubleSpecial(std::string const& workspace_name) {
|
||||||
// Hyprland's IPC sometimes reports the creation of workspaces strangely named
|
// Hyprland's IPC sometimes reports the creation of workspaces strangely named
|
||||||
// `special:special:<some_name>`. This function checks for that and is used
|
// `special:special:<some_name>`. This function checks for that and is used
|
||||||
// to avoid creating (and then removing) such workspaces.
|
// to avoid creating (and then removing) such workspaces.
|
||||||
@@ -217,8 +224,8 @@ bool isDoubleSpecial(std::string const &workspace_name) {
|
|||||||
return workspace_name.find("special:special:") != std::string::npos;
|
return workspace_name.find("special:special:") != std::string::npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Workspaces::isWorkspaceIgnored(std::string const &name) {
|
bool Workspaces::isWorkspaceIgnored(std::string const& name) {
|
||||||
for (auto &rule : m_ignoreWorkspaces) {
|
for (auto& rule : m_ignoreWorkspaces) {
|
||||||
if (std::regex_match(name, rule)) {
|
if (std::regex_match(name, rule)) {
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
@@ -228,19 +235,19 @@ bool Workspaces::isWorkspaceIgnored(std::string const &name) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::loadPersistentWorkspacesFromConfig(Json::Value const &clientsJson) {
|
void Workspaces::loadPersistentWorkspacesFromConfig(Json::Value const& clientsJson) {
|
||||||
spdlog::info("Loading persistent workspaces from Waybar config");
|
spdlog::info("Loading persistent workspaces from Waybar config");
|
||||||
const std::vector<std::string> keys = m_persistentWorkspaceConfig.getMemberNames();
|
const std::vector<std::string> keys = m_persistentWorkspaceConfig.getMemberNames();
|
||||||
std::vector<std::string> persistentWorkspacesToCreate;
|
std::vector<std::string> persistentWorkspacesToCreate;
|
||||||
|
|
||||||
const std::string currentMonitor = m_bar.output->name;
|
const std::string currentMonitor = m_bar.output->name;
|
||||||
const bool monitorInConfig = std::ranges::find(keys, currentMonitor) != keys.end();
|
const bool monitorInConfig = std::ranges::find(keys, currentMonitor) != keys.end();
|
||||||
for (const std::string &key : keys) {
|
for (const std::string& key : keys) {
|
||||||
// only add if either:
|
// only add if either:
|
||||||
// 1. key is the current monitor name
|
// 1. key is the current monitor name
|
||||||
// 2. key is "*" and this monitor is not already defined in the config
|
// 2. key is "*" and this monitor is not already defined in the config
|
||||||
bool canCreate = key == currentMonitor || (key == "*" && !monitorInConfig);
|
bool canCreate = key == currentMonitor || (key == "*" && !monitorInConfig);
|
||||||
const Json::Value &value = m_persistentWorkspaceConfig[key];
|
const Json::Value& value = m_persistentWorkspaceConfig[key];
|
||||||
spdlog::trace("Parsing persistent workspace config: {} => {}", key, value.toStyledString());
|
spdlog::trace("Parsing persistent workspace config: {} => {}", key, value.toStyledString());
|
||||||
|
|
||||||
if (value.isInt()) {
|
if (value.isInt()) {
|
||||||
@@ -255,13 +262,13 @@ void Workspaces::loadPersistentWorkspacesFromConfig(Json::Value const &clientsJs
|
|||||||
} else if (value.isArray() && !value.empty()) {
|
} else if (value.isArray() && !value.empty()) {
|
||||||
// value is an array => create defined workspaces for this monitor
|
// value is an array => create defined workspaces for this monitor
|
||||||
if (canCreate) {
|
if (canCreate) {
|
||||||
for (const Json::Value &workspace : value) {
|
for (const Json::Value& workspace : value) {
|
||||||
spdlog::debug("Creating workspace {} on monitor {}", workspace, currentMonitor);
|
spdlog::debug("Creating workspace {} on monitor {}", workspace, currentMonitor);
|
||||||
persistentWorkspacesToCreate.emplace_back(workspace.asString());
|
persistentWorkspacesToCreate.emplace_back(workspace.asString());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// key is the workspace and value is array of monitors to create on
|
// key is the workspace and value is array of monitors to create on
|
||||||
for (const Json::Value &monitor : value) {
|
for (const Json::Value& monitor : value) {
|
||||||
if (monitor.isString() && monitor.asString() == currentMonitor) {
|
if (monitor.isString() && monitor.asString() == currentMonitor) {
|
||||||
persistentWorkspacesToCreate.emplace_back(currentMonitor);
|
persistentWorkspacesToCreate.emplace_back(currentMonitor);
|
||||||
break;
|
break;
|
||||||
@@ -274,18 +281,18 @@ void Workspaces::loadPersistentWorkspacesFromConfig(Json::Value const &clientsJs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const &workspace : persistentWorkspacesToCreate) {
|
for (auto const& workspace : persistentWorkspacesToCreate) {
|
||||||
auto workspaceData = createMonitorWorkspaceData(workspace, m_bar.output->name);
|
auto workspaceData = createMonitorWorkspaceData(workspace, m_bar.output->name);
|
||||||
workspaceData["persistent-config"] = true;
|
workspaceData["persistent-config"] = true;
|
||||||
m_workspacesToCreate.emplace_back(workspaceData, clientsJson);
|
m_workspacesToCreate.emplace_back(workspaceData, clientsJson);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::loadPersistentWorkspacesFromWorkspaceRules(const Json::Value &clientsJson) {
|
void Workspaces::loadPersistentWorkspacesFromWorkspaceRules(const Json::Value& clientsJson) {
|
||||||
spdlog::info("Loading persistent workspaces from Hyprland workspace rules");
|
spdlog::info("Loading persistent workspaces from Hyprland workspace rules");
|
||||||
|
|
||||||
auto const workspaceRules = m_ipc.getSocket1JsonReply("workspacerules");
|
auto const workspaceRules = m_ipc.getSocket1JsonReply("workspacerules");
|
||||||
for (Json::Value const &rule : workspaceRules) {
|
for (Json::Value const& rule : workspaceRules) {
|
||||||
if (!rule["workspaceString"].isString()) {
|
if (!rule["workspaceString"].isString()) {
|
||||||
spdlog::warn("Workspace rules: invalid workspaceString, skipping: {}", rule);
|
spdlog::warn("Workspace rules: invalid workspaceString, skipping: {}", rule);
|
||||||
continue;
|
continue;
|
||||||
@@ -296,11 +303,16 @@ void Workspaces::loadPersistentWorkspacesFromWorkspaceRules(const Json::Value &c
|
|||||||
auto workspace = rule.isMember("defaultName") ? rule["defaultName"].asString()
|
auto workspace = rule.isMember("defaultName") ? rule["defaultName"].asString()
|
||||||
: rule["workspaceString"].asString();
|
: rule["workspaceString"].asString();
|
||||||
|
|
||||||
|
// There could be persistent special workspaces, only show those when show-special is enabled.
|
||||||
|
if (workspace.starts_with("special:") && !showSpecial()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// The prefix "name:" cause mismatches with workspace names taken anywhere else.
|
// The prefix "name:" cause mismatches with workspace names taken anywhere else.
|
||||||
if (workspace.starts_with("name:")) {
|
if (workspace.starts_with("name:")) {
|
||||||
workspace = workspace.substr(5);
|
workspace = workspace.substr(5);
|
||||||
}
|
}
|
||||||
auto const &monitor = rule["monitor"].asString();
|
auto const& monitor = rule["monitor"].asString();
|
||||||
// create this workspace persistently if:
|
// create this workspace persistently if:
|
||||||
// 1. the allOutputs config option is enabled
|
// 1. the allOutputs config option is enabled
|
||||||
// 2. the rule's monitor is the current monitor
|
// 2. the rule's monitor is the current monitor
|
||||||
@@ -317,7 +329,7 @@ void Workspaces::loadPersistentWorkspacesFromWorkspaceRules(const Json::Value &c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onEvent(const std::string &ev) {
|
void Workspaces::onEvent(const std::string& ev) {
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
std::string eventName(begin(ev), begin(ev) + ev.find_first_of('>'));
|
std::string eventName(begin(ev), begin(ev) + ev.find_first_of('>'));
|
||||||
std::string payload = ev.substr(eventName.size() + 2);
|
std::string payload = ev.substr(eventName.size() + 2);
|
||||||
@@ -355,7 +367,7 @@ void Workspaces::onEvent(const std::string &ev) {
|
|||||||
dp.emit();
|
dp.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onWorkspaceActivated(std::string const &payload) {
|
void Workspaces::onWorkspaceActivated(std::string const& payload) {
|
||||||
const auto [workspaceIdStr, workspaceName] = splitDoublePayload(payload);
|
const auto [workspaceIdStr, workspaceName] = splitDoublePayload(payload);
|
||||||
const auto workspaceId = parseWorkspaceId(workspaceIdStr);
|
const auto workspaceId = parseWorkspaceId(workspaceIdStr);
|
||||||
if (workspaceId.has_value()) {
|
if (workspaceId.has_value()) {
|
||||||
@@ -363,19 +375,19 @@ void Workspaces::onWorkspaceActivated(std::string const &payload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onSpecialWorkspaceActivated(std::string const &payload) {
|
void Workspaces::onSpecialWorkspaceActivated(std::string const& payload) {
|
||||||
std::string name(begin(payload), begin(payload) + payload.find_first_of(','));
|
std::string name(begin(payload), begin(payload) + payload.find_first_of(','));
|
||||||
m_activeSpecialWorkspaceName = (!name.starts_with("special:") ? name : name.substr(8));
|
m_activeSpecialWorkspaceName = (!name.starts_with("special:") ? name : name.substr(8));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onWorkspaceDestroyed(std::string const &payload) {
|
void Workspaces::onWorkspaceDestroyed(std::string const& payload) {
|
||||||
const auto [workspaceId, workspaceName] = splitDoublePayload(payload);
|
const auto [workspaceId, workspaceName] = splitDoublePayload(payload);
|
||||||
if (!isDoubleSpecial(workspaceName)) {
|
if (!isDoubleSpecial(workspaceName)) {
|
||||||
m_workspacesToRemove.push_back(workspaceId);
|
m_workspacesToRemove.push_back(workspaceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onWorkspaceCreated(std::string const &payload, Json::Value const &clientsData) {
|
void Workspaces::onWorkspaceCreated(std::string const& payload, Json::Value const& clientsData) {
|
||||||
spdlog::debug("Workspace created: {}", payload);
|
spdlog::debug("Workspace created: {}", payload);
|
||||||
|
|
||||||
const auto [workspaceIdStr, _] = splitDoublePayload(payload);
|
const auto [workspaceIdStr, _] = splitDoublePayload(payload);
|
||||||
@@ -402,7 +414,7 @@ void Workspaces::onWorkspaceCreated(std::string const &payload, Json::Value cons
|
|||||||
if ((allOutputs() || m_bar.output->name == workspaceJson["monitor"].asString()) &&
|
if ((allOutputs() || m_bar.output->name == workspaceJson["monitor"].asString()) &&
|
||||||
(showSpecial() || !workspaceName.starts_with("special")) &&
|
(showSpecial() || !workspaceName.starts_with("special")) &&
|
||||||
!isDoubleSpecial(workspaceName)) {
|
!isDoubleSpecial(workspaceName)) {
|
||||||
for (Json::Value const &rule : workspaceRules) {
|
for (Json::Value const& rule : workspaceRules) {
|
||||||
auto ruleWorkspaceName = rule.isMember("defaultName")
|
auto ruleWorkspaceName = rule.isMember("defaultName")
|
||||||
? rule["defaultName"].asString()
|
? rule["defaultName"].asString()
|
||||||
: rule["workspaceString"].asString();
|
: rule["workspaceString"].asString();
|
||||||
@@ -421,7 +433,7 @@ void Workspaces::onWorkspaceCreated(std::string const &payload, Json::Value cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onWorkspaceMoved(std::string const &payload) {
|
void Workspaces::onWorkspaceMoved(std::string const& payload) {
|
||||||
spdlog::debug("Workspace moved: {}", payload);
|
spdlog::debug("Workspace moved: {}", payload);
|
||||||
|
|
||||||
// Update active workspace
|
// Update active workspace
|
||||||
@@ -442,7 +454,7 @@ void Workspaces::onWorkspaceMoved(std::string const &payload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onWorkspaceRenamed(std::string const &payload) {
|
void Workspaces::onWorkspaceRenamed(std::string const& payload) {
|
||||||
spdlog::debug("Workspace renamed: {}", payload);
|
spdlog::debug("Workspace renamed: {}", payload);
|
||||||
const auto [workspaceIdStr, newName] = splitDoublePayload(payload);
|
const auto [workspaceIdStr, newName] = splitDoublePayload(payload);
|
||||||
|
|
||||||
@@ -451,7 +463,7 @@ void Workspaces::onWorkspaceRenamed(std::string const &payload) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &workspace : m_workspaces) {
|
for (auto& workspace : m_workspaces) {
|
||||||
if (workspace->id() == *workspaceId) {
|
if (workspace->id() == *workspaceId) {
|
||||||
workspace->setName(newName);
|
workspace->setName(newName);
|
||||||
break;
|
break;
|
||||||
@@ -460,7 +472,7 @@ void Workspaces::onWorkspaceRenamed(std::string const &payload) {
|
|||||||
sortWorkspaces();
|
sortWorkspaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onMonitorFocused(std::string const &payload) {
|
void Workspaces::onMonitorFocused(std::string const& payload) {
|
||||||
spdlog::trace("Monitor focused: {}", payload);
|
spdlog::trace("Monitor focused: {}", payload);
|
||||||
|
|
||||||
const auto [monitorName, workspaceIdStr] = splitDoublePayload(payload);
|
const auto [monitorName, workspaceIdStr] = splitDoublePayload(payload);
|
||||||
@@ -472,7 +484,7 @@ void Workspaces::onMonitorFocused(std::string const &payload) {
|
|||||||
|
|
||||||
m_activeWorkspaceId = *workspaceId;
|
m_activeWorkspaceId = *workspaceId;
|
||||||
|
|
||||||
for (Json::Value &monitor : m_ipc.getSocket1JsonReply("monitors")) {
|
for (Json::Value& monitor : m_ipc.getSocket1JsonReply("monitors")) {
|
||||||
if (monitor["name"].asString() == monitorName) {
|
if (monitor["name"].asString() == monitorName) {
|
||||||
const auto name = monitor["specialWorkspace"]["name"].asString();
|
const auto name = monitor["specialWorkspace"]["name"].asString();
|
||||||
m_activeSpecialWorkspaceName = !name.starts_with("special:") ? name : name.substr(8);
|
m_activeSpecialWorkspaceName = !name.starts_with("special:") ? name : name.substr(8);
|
||||||
@@ -480,7 +492,7 @@ void Workspaces::onMonitorFocused(std::string const &payload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onWindowOpened(std::string const &payload) {
|
void Workspaces::onWindowOpened(std::string const& payload) {
|
||||||
spdlog::trace("Window opened: {}", payload);
|
spdlog::trace("Window opened: {}", payload);
|
||||||
updateWindowCount();
|
updateWindowCount();
|
||||||
size_t lastCommaIdx = 0;
|
size_t lastCommaIdx = 0;
|
||||||
@@ -501,18 +513,18 @@ void Workspaces::onWindowOpened(std::string const &payload) {
|
|||||||
m_windowsToCreate.emplace_back(workspaceName, windowAddress, windowClass, windowTitle, isActive);
|
m_windowsToCreate.emplace_back(workspaceName, windowAddress, windowClass, windowTitle, isActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onWindowClosed(std::string const &addr) {
|
void Workspaces::onWindowClosed(std::string const& addr) {
|
||||||
spdlog::trace("Window closed: {}", addr);
|
spdlog::trace("Window closed: {}", addr);
|
||||||
updateWindowCount();
|
updateWindowCount();
|
||||||
m_orphanWindowMap.erase(addr);
|
m_orphanWindowMap.erase(addr);
|
||||||
for (auto &workspace : m_workspaces) {
|
for (auto& workspace : m_workspaces) {
|
||||||
if (workspace->closeWindow(addr)) {
|
if (workspace->closeWindow(addr)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onWindowMoved(std::string const &payload) {
|
void Workspaces::onWindowMoved(std::string const& payload) {
|
||||||
spdlog::trace("Window moved: {}", payload);
|
spdlog::trace("Window moved: {}", payload);
|
||||||
updateWindowCount();
|
updateWindowCount();
|
||||||
auto [windowAddress, _, workspaceName] = splitTriplePayload(payload);
|
auto [windowAddress, _, workspaceName] = splitTriplePayload(payload);
|
||||||
@@ -521,7 +533,7 @@ void Workspaces::onWindowMoved(std::string const &payload) {
|
|||||||
|
|
||||||
// If the window was still queued to be created, just change its destination
|
// If the window was still queued to be created, just change its destination
|
||||||
// and exit
|
// and exit
|
||||||
for (auto &window : m_windowsToCreate) {
|
for (auto& window : m_windowsToCreate) {
|
||||||
if (window.getAddress() == windowAddress) {
|
if (window.getAddress() == windowAddress) {
|
||||||
window.moveToWorkspace(workspaceName);
|
window.moveToWorkspace(workspaceName);
|
||||||
return;
|
return;
|
||||||
@@ -529,7 +541,7 @@ void Workspaces::onWindowMoved(std::string const &payload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Take the window's representation from the old workspace...
|
// Take the window's representation from the old workspace...
|
||||||
for (auto &workspace : m_workspaces) {
|
for (auto& workspace : m_workspaces) {
|
||||||
if (auto windowAddr = workspace->closeWindow(windowAddress); windowAddr != std::nullopt) {
|
if (auto windowAddr = workspace->closeWindow(windowAddress); windowAddr != std::nullopt) {
|
||||||
windowRepr = windowAddr.value();
|
windowRepr = windowAddr.value();
|
||||||
break;
|
break;
|
||||||
@@ -548,7 +560,7 @@ void Workspaces::onWindowMoved(std::string const &payload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onWindowTitleEvent(std::string const &payload) {
|
void Workspaces::onWindowTitleEvent(std::string const& payload) {
|
||||||
spdlog::trace("Window title changed: {}", payload);
|
spdlog::trace("Window title changed: {}", payload);
|
||||||
std::optional<std::function<void(WindowCreationPayload)>> inserter;
|
std::optional<std::function<void(WindowCreationPayload)>> inserter;
|
||||||
|
|
||||||
@@ -558,7 +570,7 @@ void Workspaces::onWindowTitleEvent(std::string const &payload) {
|
|||||||
if (m_orphanWindowMap.contains(windowAddress)) {
|
if (m_orphanWindowMap.contains(windowAddress)) {
|
||||||
inserter = [this](WindowCreationPayload wcp) { this->registerOrphanWindow(std::move(wcp)); };
|
inserter = [this](WindowCreationPayload wcp) { this->registerOrphanWindow(std::move(wcp)); };
|
||||||
} else {
|
} else {
|
||||||
auto windowWorkspace = std::ranges::find_if(m_workspaces, [windowAddress](auto &workspace) {
|
auto windowWorkspace = std::ranges::find_if(m_workspaces, [windowAddress](auto& workspace) {
|
||||||
return workspace->containsWindow(windowAddress);
|
return workspace->containsWindow(windowAddress);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -570,7 +582,7 @@ void Workspaces::onWindowTitleEvent(std::string const &payload) {
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
auto queuedWindow =
|
auto queuedWindow =
|
||||||
std::ranges::find_if(m_windowsToCreate, [&windowAddress](auto &windowPayload) {
|
std::ranges::find_if(m_windowsToCreate, [&windowAddress](auto& windowPayload) {
|
||||||
return windowPayload.getAddress() == windowAddress;
|
return windowPayload.getAddress() == windowAddress;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -585,7 +597,7 @@ void Workspaces::onWindowTitleEvent(std::string const &payload) {
|
|||||||
Json::Value clientsData = m_ipc.getSocket1JsonReply("clients");
|
Json::Value clientsData = m_ipc.getSocket1JsonReply("clients");
|
||||||
std::string jsonWindowAddress = fmt::format("0x{}", windowAddress);
|
std::string jsonWindowAddress = fmt::format("0x{}", windowAddress);
|
||||||
|
|
||||||
auto client = std::ranges::find_if(clientsData, [jsonWindowAddress](auto &client) {
|
auto client = std::ranges::find_if(clientsData, [jsonWindowAddress](auto& client) {
|
||||||
return client["address"].asString() == jsonWindowAddress;
|
return client["address"].asString() == jsonWindowAddress;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -595,17 +607,17 @@ void Workspaces::onWindowTitleEvent(std::string const &payload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onActiveWindowChanged(WindowAddress const &activeWindowAddress) {
|
void Workspaces::onActiveWindowChanged(WindowAddress const& activeWindowAddress) {
|
||||||
spdlog::trace("Active window changed: {}", activeWindowAddress);
|
spdlog::trace("Active window changed: {}", activeWindowAddress);
|
||||||
m_currentActiveWindowAddress = activeWindowAddress;
|
m_currentActiveWindowAddress = activeWindowAddress;
|
||||||
|
|
||||||
for (auto &[address, window] : m_orphanWindowMap) {
|
for (auto& [address, window] : m_orphanWindowMap) {
|
||||||
window.setActive(address == activeWindowAddress);
|
window.setActive(address == activeWindowAddress);
|
||||||
}
|
}
|
||||||
for (auto const &workspace : m_workspaces) {
|
for (auto const& workspace : m_workspaces) {
|
||||||
workspace->setActiveWindow(activeWindowAddress);
|
workspace->setActiveWindow(activeWindowAddress);
|
||||||
}
|
}
|
||||||
for (auto &window : m_windowsToCreate) {
|
for (auto& window : m_windowsToCreate) {
|
||||||
window.setActive(window.getAddress() == activeWindowAddress);
|
window.setActive(window.getAddress() == activeWindowAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -615,8 +627,8 @@ void Workspaces::onConfigReloaded() {
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspaces::parseConfig(const Json::Value &config) -> void {
|
auto Workspaces::parseConfig(const Json::Value& config) -> void {
|
||||||
const auto &configFormat = config["format"];
|
const auto& configFormat = config["format"];
|
||||||
m_formatBefore = configFormat.isString() ? configFormat.asString() : "{name}";
|
m_formatBefore = configFormat.isString() ? configFormat.asString() : "{name}";
|
||||||
m_withIcon = m_formatBefore.find("{icon}") != std::string::npos;
|
m_withIcon = m_formatBefore.find("{icon}") != std::string::npos;
|
||||||
auto withWindows = m_formatBefore.find("{windows}") != std::string::npos;
|
auto withWindows = m_formatBefore.find("{windows}") != std::string::npos;
|
||||||
@@ -631,6 +643,7 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void {
|
|||||||
populateBoolConfig(config, "persistent-only", m_persistentOnly);
|
populateBoolConfig(config, "persistent-only", m_persistentOnly);
|
||||||
populateBoolConfig(config, "active-only", m_activeOnly);
|
populateBoolConfig(config, "active-only", m_activeOnly);
|
||||||
populateBoolConfig(config, "move-to-monitor", m_moveToMonitor);
|
populateBoolConfig(config, "move-to-monitor", m_moveToMonitor);
|
||||||
|
populateBoolConfig(config, "enable-bar-scroll", m_barScroll);
|
||||||
|
|
||||||
m_persistentWorkspaceConfig = config.get("persistent-workspaces", Json::Value());
|
m_persistentWorkspaceConfig = config.get("persistent-workspaces", Json::Value());
|
||||||
populateSortByConfig(config);
|
populateSortByConfig(config);
|
||||||
@@ -648,28 +661,28 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspaces::populateIconsMap(const Json::Value &formatIcons) -> void {
|
auto Workspaces::populateIconsMap(const Json::Value& formatIcons) -> void {
|
||||||
for (const auto &name : formatIcons.getMemberNames()) {
|
for (const auto& name : formatIcons.getMemberNames()) {
|
||||||
m_iconsMap.emplace(name, formatIcons[name].asString());
|
m_iconsMap.emplace(name, formatIcons[name].asString());
|
||||||
}
|
}
|
||||||
m_iconsMap.emplace("", "");
|
m_iconsMap.emplace("", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspaces::populateBoolConfig(const Json::Value &config, const std::string &key, bool &member)
|
auto Workspaces::populateBoolConfig(const Json::Value& config, const std::string& key, bool& member)
|
||||||
-> void {
|
-> void {
|
||||||
const auto &configValue = config[key];
|
const auto& configValue = config[key];
|
||||||
if (configValue.isBool()) {
|
if (configValue.isBool()) {
|
||||||
member = configValue.asBool();
|
member = configValue.asBool();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspaces::populateSortByConfig(const Json::Value &config) -> void {
|
auto Workspaces::populateSortByConfig(const Json::Value& config) -> void {
|
||||||
const auto &configSortBy = config["sort-by"];
|
const auto& configSortBy = config["sort-by"];
|
||||||
if (configSortBy.isString()) {
|
if (configSortBy.isString()) {
|
||||||
auto sortByStr = configSortBy.asString();
|
auto sortByStr = configSortBy.asString();
|
||||||
try {
|
try {
|
||||||
m_sortBy = m_enumParser.parseStringToEnum(sortByStr, m_sortMap);
|
m_sortBy = m_enumParser.parseStringToEnum(sortByStr, m_sortMap);
|
||||||
} catch (const std::invalid_argument &e) {
|
} catch (const std::invalid_argument& e) {
|
||||||
m_sortBy = SortMethod::DEFAULT;
|
m_sortBy = SortMethod::DEFAULT;
|
||||||
spdlog::warn(
|
spdlog::warn(
|
||||||
"Invalid string representation for sort-by. Falling back to default sort method.");
|
"Invalid string representation for sort-by. Falling back to default sort method.");
|
||||||
@@ -677,16 +690,16 @@ auto Workspaces::populateSortByConfig(const Json::Value &config) -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspaces::populateIgnoreWorkspacesConfig(const Json::Value &config) -> void {
|
auto Workspaces::populateIgnoreWorkspacesConfig(const Json::Value& config) -> void {
|
||||||
auto ignoreWorkspaces = config["ignore-workspaces"];
|
auto ignoreWorkspaces = config["ignore-workspaces"];
|
||||||
if (ignoreWorkspaces.isArray()) {
|
if (ignoreWorkspaces.isArray()) {
|
||||||
for (const auto &workspaceRegex : ignoreWorkspaces) {
|
for (const auto& workspaceRegex : ignoreWorkspaces) {
|
||||||
if (workspaceRegex.isString()) {
|
if (workspaceRegex.isString()) {
|
||||||
std::string ruleString = workspaceRegex.asString();
|
std::string ruleString = workspaceRegex.asString();
|
||||||
try {
|
try {
|
||||||
const std::regex rule{ruleString, std::regex_constants::icase};
|
const std::regex rule{ruleString, std::regex_constants::icase};
|
||||||
m_ignoreWorkspaces.emplace_back(rule);
|
m_ignoreWorkspaces.emplace_back(rule);
|
||||||
} catch (const std::regex_error &e) {
|
} catch (const std::regex_error& e) {
|
||||||
spdlog::error("Invalid rule {}: {}", ruleString, e.what());
|
spdlog::error("Invalid rule {}: {}", ruleString, e.what());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -696,30 +709,30 @@ auto Workspaces::populateIgnoreWorkspacesConfig(const Json::Value &config) -> vo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspaces::populateFormatWindowSeparatorConfig(const Json::Value &config) -> void {
|
auto Workspaces::populateFormatWindowSeparatorConfig(const Json::Value& config) -> void {
|
||||||
const auto &formatWindowSeparator = config["format-window-separator"];
|
const auto& formatWindowSeparator = config["format-window-separator"];
|
||||||
m_formatWindowSeparator =
|
m_formatWindowSeparator =
|
||||||
formatWindowSeparator.isString() ? formatWindowSeparator.asString() : " ";
|
formatWindowSeparator.isString() ? formatWindowSeparator.asString() : " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspaces::populateWindowRewriteConfig(const Json::Value &config) -> void {
|
auto Workspaces::populateWindowRewriteConfig(const Json::Value& config) -> void {
|
||||||
const auto &windowRewrite = config["window-rewrite"];
|
const auto& windowRewrite = config["window-rewrite"];
|
||||||
if (!windowRewrite.isObject()) {
|
if (!windowRewrite.isObject()) {
|
||||||
spdlog::debug("window-rewrite is not defined or is not an object, using default rules.");
|
spdlog::debug("window-rewrite is not defined or is not an object, using default rules.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &windowRewriteDefaultConfig = config["window-rewrite-default"];
|
const auto& windowRewriteDefaultConfig = config["window-rewrite-default"];
|
||||||
std::string windowRewriteDefault =
|
std::string windowRewriteDefault =
|
||||||
windowRewriteDefaultConfig.isString() ? windowRewriteDefaultConfig.asString() : "?";
|
windowRewriteDefaultConfig.isString() ? windowRewriteDefaultConfig.asString() : "?";
|
||||||
|
|
||||||
m_windowRewriteRules = util::RegexCollection(
|
m_windowRewriteRules = util::RegexCollection(
|
||||||
windowRewrite, windowRewriteDefault,
|
windowRewrite, windowRewriteDefault,
|
||||||
[this](std::string &window_rule) { return windowRewritePriorityFunction(window_rule); });
|
[this](std::string& window_rule) { return windowRewritePriorityFunction(window_rule); });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspaces::populateWorkspaceTaskbarConfig(const Json::Value &config) -> void {
|
auto Workspaces::populateWorkspaceTaskbarConfig(const Json::Value& config) -> void {
|
||||||
const auto &workspaceTaskbar = config["workspace-taskbar"];
|
const auto& workspaceTaskbar = config["workspace-taskbar"];
|
||||||
if (!workspaceTaskbar.isObject()) {
|
if (!workspaceTaskbar.isObject()) {
|
||||||
spdlog::debug("workspace-taskbar is not defined or is not an object, using default rules.");
|
spdlog::debug("workspace-taskbar is not defined or is not an object, using default rules.");
|
||||||
return;
|
return;
|
||||||
@@ -746,7 +759,7 @@ auto Workspaces::populateWorkspaceTaskbarConfig(const Json::Value &config) -> vo
|
|||||||
|
|
||||||
auto iconTheme = workspaceTaskbar["icon-theme"];
|
auto iconTheme = workspaceTaskbar["icon-theme"];
|
||||||
if (iconTheme.isArray()) {
|
if (iconTheme.isArray()) {
|
||||||
for (auto &c : iconTheme) {
|
for (auto& c : iconTheme) {
|
||||||
m_iconLoader.add_custom_icon_theme(c.asString());
|
m_iconLoader.add_custom_icon_theme(c.asString());
|
||||||
}
|
}
|
||||||
} else if (iconTheme.isString()) {
|
} else if (iconTheme.isString()) {
|
||||||
@@ -766,11 +779,11 @@ auto Workspaces::populateWorkspaceTaskbarConfig(const Json::Value &config) -> vo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (workspaceTaskbar["ignore-list"].isArray()) {
|
if (workspaceTaskbar["ignore-list"].isArray()) {
|
||||||
for (auto &windowRegex : workspaceTaskbar["ignore-list"]) {
|
for (auto& windowRegex : workspaceTaskbar["ignore-list"]) {
|
||||||
std::string ruleString = windowRegex.asString();
|
std::string ruleString = windowRegex.asString();
|
||||||
try {
|
try {
|
||||||
m_ignoreWindows.emplace_back(ruleString, std::regex_constants::icase);
|
m_ignoreWindows.emplace_back(ruleString, std::regex_constants::icase);
|
||||||
} catch (const std::regex_error &e) {
|
} catch (const std::regex_error& e) {
|
||||||
spdlog::error("Invalid rule {}: {}", ruleString, e.what());
|
spdlog::error("Invalid rule {}: {}", ruleString, e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -781,7 +794,7 @@ auto Workspaces::populateWorkspaceTaskbarConfig(const Json::Value &config) -> vo
|
|||||||
try {
|
try {
|
||||||
m_activeWindowPosition =
|
m_activeWindowPosition =
|
||||||
m_activeWindowEnumParser.parseStringToEnum(posStr, m_activeWindowPositionMap);
|
m_activeWindowEnumParser.parseStringToEnum(posStr, m_activeWindowPositionMap);
|
||||||
} catch (const std::invalid_argument &e) {
|
} catch (const std::invalid_argument& e) {
|
||||||
spdlog::warn(
|
spdlog::warn(
|
||||||
"Invalid string representation for active-window-position. Falling back to 'none'.");
|
"Invalid string representation for active-window-position. Falling back to 'none'.");
|
||||||
m_activeWindowPosition = ActiveWindowPosition::NONE;
|
m_activeWindowPosition = ActiveWindowPosition::NONE;
|
||||||
@@ -824,13 +837,13 @@ auto Workspaces::registerIpc() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::removeWorkspacesToRemove() {
|
void Workspaces::removeWorkspacesToRemove() {
|
||||||
for (const auto &workspaceString : m_workspacesToRemove) {
|
for (const auto& workspaceString : m_workspacesToRemove) {
|
||||||
removeWorkspace(workspaceString);
|
removeWorkspace(workspaceString);
|
||||||
}
|
}
|
||||||
m_workspacesToRemove.clear();
|
m_workspacesToRemove.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::removeWorkspace(std::string const &workspaceString) {
|
void Workspaces::removeWorkspace(std::string const& workspaceString) {
|
||||||
spdlog::debug("Removing workspace {}", workspaceString);
|
spdlog::debug("Removing workspace {}", workspaceString);
|
||||||
|
|
||||||
// If this succeeds, we have a workspace ID.
|
// If this succeeds, we have a workspace ID.
|
||||||
@@ -848,7 +861,7 @@ void Workspaces::removeWorkspace(std::string const &workspaceString) {
|
|||||||
name = workspaceString;
|
name = workspaceString;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto workspace = std::ranges::find_if(m_workspaces, [&](std::unique_ptr<Workspace> &x) {
|
const auto workspace = std::ranges::find_if(m_workspaces, [&](std::unique_ptr<Workspace>& x) {
|
||||||
if (workspaceId.has_value()) {
|
if (workspaceId.has_value()) {
|
||||||
return *workspaceId == x->id();
|
return *workspaceId == x->id();
|
||||||
}
|
}
|
||||||
@@ -874,7 +887,7 @@ void Workspaces::setCurrentMonitorId() {
|
|||||||
// get monitor ID from name (used by persistent workspaces)
|
// get monitor ID from name (used by persistent workspaces)
|
||||||
m_monitorId = 0;
|
m_monitorId = 0;
|
||||||
auto monitors = m_ipc.getSocket1JsonReply("monitors");
|
auto monitors = m_ipc.getSocket1JsonReply("monitors");
|
||||||
auto currentMonitor = std::ranges::find_if(monitors, [this](const Json::Value &m) {
|
auto currentMonitor = std::ranges::find_if(monitors, [this](const Json::Value& m) {
|
||||||
return m["name"].asString() == m_bar.output->name;
|
return m["name"].asString() == m_bar.output->name;
|
||||||
});
|
});
|
||||||
if (currentMonitor == monitors.end()) {
|
if (currentMonitor == monitors.end()) {
|
||||||
@@ -890,7 +903,7 @@ void Workspaces::sortSpecialCentered() {
|
|||||||
std::vector<std::unique_ptr<Workspace>> hiddenWorkspaces;
|
std::vector<std::unique_ptr<Workspace>> hiddenWorkspaces;
|
||||||
std::vector<std::unique_ptr<Workspace>> normalWorkspaces;
|
std::vector<std::unique_ptr<Workspace>> normalWorkspaces;
|
||||||
|
|
||||||
for (auto &workspace : m_workspaces) {
|
for (auto& workspace : m_workspaces) {
|
||||||
if (workspace->isSpecial()) {
|
if (workspace->isSpecial()) {
|
||||||
specialWorkspaces.push_back(std::move(workspace));
|
specialWorkspaces.push_back(std::move(workspace));
|
||||||
} else {
|
} else {
|
||||||
@@ -921,7 +934,7 @@ void Workspaces::sortSpecialCentered() {
|
|||||||
|
|
||||||
void Workspaces::sortWorkspaces() {
|
void Workspaces::sortWorkspaces() {
|
||||||
std::ranges::sort( //
|
std::ranges::sort( //
|
||||||
m_workspaces, [&](std::unique_ptr<Workspace> &a, std::unique_ptr<Workspace> &b) {
|
m_workspaces, [&](std::unique_ptr<Workspace>& a, std::unique_ptr<Workspace>& b) {
|
||||||
// Helper comparisons
|
// Helper comparisons
|
||||||
auto isIdLess = a->id() < b->id();
|
auto isIdLess = a->id() < b->id();
|
||||||
auto isNameLess = a->name() < b->name();
|
auto isNameLess = a->name() < b->name();
|
||||||
@@ -934,7 +947,7 @@ void Workspaces::sortWorkspaces() {
|
|||||||
case SortMethod::NUMBER:
|
case SortMethod::NUMBER:
|
||||||
try {
|
try {
|
||||||
return std::stoi(a->name()) < std::stoi(b->name());
|
return std::stoi(a->name()) < std::stoi(b->name());
|
||||||
} catch (const std::invalid_argument &) {
|
} catch (const std::exception& e) {
|
||||||
// Handle the exception if necessary.
|
// Handle the exception if necessary.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -986,7 +999,7 @@ void Workspaces::sortWorkspaces() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::setUrgentWorkspace(std::string const &windowaddress) {
|
void Workspaces::setUrgentWorkspace(std::string const& windowaddress) {
|
||||||
const Json::Value clientsJson = m_ipc.getSocket1JsonReply("clients");
|
const Json::Value clientsJson = m_ipc.getSocket1JsonReply("clients");
|
||||||
int workspaceId = -1;
|
int workspaceId = -1;
|
||||||
|
|
||||||
@@ -997,7 +1010,7 @@ void Workspaces::setUrgentWorkspace(std::string const &windowaddress) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto workspace = std::ranges::find_if(m_workspaces, [workspaceId](std::unique_ptr<Workspace> &x) {
|
auto workspace = std::ranges::find_if(m_workspaces, [workspaceId](std::unique_ptr<Workspace>& x) {
|
||||||
return x->id() == workspaceId;
|
return x->id() == workspaceId;
|
||||||
});
|
});
|
||||||
if (workspace != m_workspaces.end()) {
|
if (workspace != m_workspaces.end()) {
|
||||||
@@ -1012,8 +1025,8 @@ auto Workspaces::update() -> void {
|
|||||||
|
|
||||||
void Workspaces::updateWindowCount() {
|
void Workspaces::updateWindowCount() {
|
||||||
const Json::Value workspacesJson = m_ipc.getSocket1JsonReply("workspaces");
|
const Json::Value workspacesJson = m_ipc.getSocket1JsonReply("workspaces");
|
||||||
for (auto const &workspace : m_workspaces) {
|
for (auto const& workspace : m_workspaces) {
|
||||||
auto workspaceJson = std::ranges::find_if(workspacesJson, [&](Json::Value const &x) {
|
auto workspaceJson = std::ranges::find_if(workspacesJson, [&](Json::Value const& x) {
|
||||||
return x["name"].asString() == workspace->name() ||
|
return x["name"].asString() == workspace->name() ||
|
||||||
(workspace->isSpecial() && x["name"].asString() == "special:" + workspace->name());
|
(workspace->isSpecial() && x["name"].asString() == "special:" + workspace->name());
|
||||||
});
|
});
|
||||||
@@ -1021,7 +1034,7 @@ void Workspaces::updateWindowCount() {
|
|||||||
if (workspaceJson != workspacesJson.end()) {
|
if (workspaceJson != workspacesJson.end()) {
|
||||||
try {
|
try {
|
||||||
count = (*workspaceJson)["windows"].asUInt();
|
count = (*workspaceJson)["windows"].asUInt();
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception& e) {
|
||||||
spdlog::error("Failed to update window count: {}", e.what());
|
spdlog::error("Failed to update window count: {}", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1032,9 +1045,9 @@ void Workspaces::updateWindowCount() {
|
|||||||
bool Workspaces::updateWindowsToCreate() {
|
bool Workspaces::updateWindowsToCreate() {
|
||||||
bool anyWindowCreated = false;
|
bool anyWindowCreated = false;
|
||||||
std::vector<WindowCreationPayload> notCreated;
|
std::vector<WindowCreationPayload> notCreated;
|
||||||
for (auto &windowPayload : m_windowsToCreate) {
|
for (auto& windowPayload : m_windowsToCreate) {
|
||||||
bool created = false;
|
bool created = false;
|
||||||
for (auto &workspace : m_workspaces) {
|
for (auto& workspace : m_workspaces) {
|
||||||
if (workspace->onWindowOpened(windowPayload)) {
|
if (workspace->onWindowOpened(windowPayload)) {
|
||||||
created = true;
|
created = true;
|
||||||
anyWindowCreated = true;
|
anyWindowCreated = true;
|
||||||
@@ -1063,7 +1076,7 @@ void Workspaces::updateWorkspaceStates() {
|
|||||||
std::string currentWorkspaceName =
|
std::string currentWorkspaceName =
|
||||||
currentWorkspace.isMember("name") ? currentWorkspace["name"].asString() : "";
|
currentWorkspace.isMember("name") ? currentWorkspace["name"].asString() : "";
|
||||||
|
|
||||||
for (auto &workspace : m_workspaces) {
|
for (auto& workspace : m_workspaces) {
|
||||||
bool isActiveByName =
|
bool isActiveByName =
|
||||||
!currentWorkspaceName.empty() && workspace->name() == currentWorkspaceName;
|
!currentWorkspaceName.empty() && workspace->name() == currentWorkspaceName;
|
||||||
|
|
||||||
@@ -1075,11 +1088,11 @@ void Workspaces::updateWorkspaceStates() {
|
|||||||
}
|
}
|
||||||
workspace->setVisible(std::ranges::find(visibleWorkspaces, workspace->id()) !=
|
workspace->setVisible(std::ranges::find(visibleWorkspaces, workspace->id()) !=
|
||||||
visibleWorkspaces.end());
|
visibleWorkspaces.end());
|
||||||
std::string &workspaceIcon = m_iconsMap[""];
|
std::string& workspaceIcon = m_iconsMap[""];
|
||||||
if (m_withIcon) {
|
if (m_withIcon) {
|
||||||
workspaceIcon = workspace->selectIcon(m_iconsMap);
|
workspaceIcon = workspace->selectIcon(m_iconsMap);
|
||||||
}
|
}
|
||||||
auto updatedWorkspace = std::ranges::find_if(updatedWorkspaces, [&workspace](const auto &w) {
|
auto updatedWorkspace = std::ranges::find_if(updatedWorkspaces, [&workspace](const auto& w) {
|
||||||
auto wNameRaw = w["name"].asString();
|
auto wNameRaw = w["name"].asString();
|
||||||
auto wName = wNameRaw.starts_with("special:") ? wNameRaw.substr(8) : wNameRaw;
|
auto wName = wNameRaw.starts_with("special:") ? wNameRaw.substr(8) : wNameRaw;
|
||||||
return wName == workspace->name();
|
return wName == workspace->name();
|
||||||
@@ -1091,7 +1104,7 @@ void Workspaces::updateWorkspaceStates() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Workspaces::windowRewritePriorityFunction(std::string const &window_rule) {
|
int Workspaces::windowRewritePriorityFunction(std::string const& window_rule) {
|
||||||
// Rules that match against title are prioritized
|
// Rules that match against title are prioritized
|
||||||
// Rules that don't specify if they're matching against either title or class are deprioritized
|
// Rules that don't specify if they're matching against either title or class are deprioritized
|
||||||
bool const hasTitle = window_rule.find("title") != std::string::npos;
|
bool const hasTitle = window_rule.find("title") != std::string::npos;
|
||||||
@@ -1112,21 +1125,21 @@ int Workspaces::windowRewritePriorityFunction(std::string const &window_rule) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
std::string Workspaces::makePayload(Args const &...args) {
|
std::string Workspaces::makePayload(Args const&... args) {
|
||||||
std::ostringstream result;
|
std::ostringstream result;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
((result << (first ? "" : ",") << args, first = false), ...);
|
((result << (first ? "" : ",") << args, first = false), ...);
|
||||||
return result.str();
|
return result.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::string, std::string> Workspaces::splitDoublePayload(std::string const &payload) {
|
std::pair<std::string, std::string> Workspaces::splitDoublePayload(std::string const& payload) {
|
||||||
const std::string part1 = payload.substr(0, payload.find(','));
|
const std::string part1 = payload.substr(0, payload.find(','));
|
||||||
const std::string part2 = payload.substr(part1.size() + 1);
|
const std::string part2 = payload.substr(part1.size() + 1);
|
||||||
return {part1, part2};
|
return {part1, part2};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<std::string, std::string, std::string> Workspaces::splitTriplePayload(
|
std::tuple<std::string, std::string, std::string> Workspaces::splitTriplePayload(
|
||||||
std::string const &payload) {
|
std::string const& payload) {
|
||||||
const size_t firstComma = payload.find(',');
|
const size_t firstComma = payload.find(',');
|
||||||
const size_t secondComma = payload.find(',', firstComma + 1);
|
const size_t secondComma = payload.find(',', firstComma + 1);
|
||||||
|
|
||||||
@@ -1137,13 +1150,40 @@ std::tuple<std::string, std::string, std::string> Workspaces::splitTriplePayload
|
|||||||
return {part1, part2, part3};
|
return {part1, part2, part3};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<int> Workspaces::parseWorkspaceId(std::string const &workspaceIdStr) {
|
std::optional<int> Workspaces::parseWorkspaceId(std::string const& workspaceIdStr) {
|
||||||
try {
|
try {
|
||||||
return workspaceIdStr == "special" ? -99 : std::stoi(workspaceIdStr);
|
return workspaceIdStr == "special" ? -99 : std::stoi(workspaceIdStr);
|
||||||
} catch (std::exception const &e) {
|
} catch (std::exception const& e) {
|
||||||
spdlog::debug("Workspace \"{}\" is not bound to an id: {}", workspaceIdStr, e.what());
|
spdlog::debug("Workspace \"{}\" is not bound to an id: {}", workspaceIdStr, e.what());
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Workspaces::handleScroll(GdkEventScroll *e) {
|
||||||
|
// Ignore emulated scroll events on window
|
||||||
|
if (gdk_event_get_pointer_emulated((GdkEvent *)e)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto dir = AModule::getScrollDir(e);
|
||||||
|
if (dir == SCROLL_DIR::NONE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir == SCROLL_DIR::DOWN || dir == SCROLL_DIR::RIGHT) {
|
||||||
|
if (allOutputs()) {
|
||||||
|
m_ipc.getSocket1Reply("dispatch workspace e+1");
|
||||||
|
} else {
|
||||||
|
m_ipc.getSocket1Reply("dispatch workspace m+1");
|
||||||
|
}
|
||||||
|
} else if (dir == SCROLL_DIR::UP || dir == SCROLL_DIR::LEFT) {
|
||||||
|
if (allOutputs()) {
|
||||||
|
m_ipc.getSocket1Reply("dispatch workspace e-1");
|
||||||
|
} else {
|
||||||
|
m_ipc.getSocket1Reply("dispatch workspace m-1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace waybar::modules::hyprland
|
} // namespace waybar::modules::hyprland
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user