Compare commits

...

111 Commits

Author SHA1 Message Date
4d2fb11a05 Merge tag '0.15.0' of https://github.com/Alexays/Waybar
Some checks failed
clang-format / lint (push) Has been cancelled
freebsd / build (push) Has been cancelled
linux / build (c++20, alpine) (push) Has been cancelled
linux / build (c++20, archlinux) (push) Has been cancelled
linux / build (c++20, debian) (push) Has been cancelled
linux / build (c++20, fedora) (push) Has been cancelled
linux / build (c++20, gentoo) (push) Has been cancelled
linux / build (c++20, opensuse) (push) Has been cancelled
Nix-Tests / nix-flake-check (push) Has been cancelled
2026-02-19 20:54:36 -08:00
90b209add8 chore: 0.15.0 2026-02-06 21:15:03 +01:00
a8bbc90efe Merge pull request #4819 from cebem1nt/master
fix: backlight/slider fix rounding issue on scroll up
2026-02-06 19:10:58 +01:00
429d7df52b fix: backlight/slider fix rounding issue on scroll up 2026-02-05 23:38:47 -03:00
26c09f1e2e Merge pull request #4814 from Alexays/copilot/fix-menu-freeze-issue
Fix menu freezing when launching applications
2026-02-04 10:33:52 +01:00
65e708779b Fix function overload order to resolve compilation error
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 09:26:20 +00:00
04766452b4 Use idiomatic empty() check for strings
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 09:15:25 +00:00
c4982efa95 Add output_name parameter to forkExec for WAYBAR_OUTPUT_NAME env var
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 09:14:45 +00:00
dad6e8a257 Merge pull request #4812 from Alexays/copilot/fix-tooltip-sync-issue
Fix custom module tooltip not updating on exec output change
2026-02-04 10:12:20 +01:00
98c2ace0ec Merge pull request #4813 from Alexays/copilot/fix-bluetooth-module-issue
Fix Pango markup rendering in bluetooth module tooltips
2026-02-04 10:11:18 +01:00
68d3e13fdd Fix menu freezing when launching applications
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 09:09:44 +00:00
2b29c9a5d6 Fix tooltip sync issue by removing conditional checks
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 09:08:42 +00:00
08baa3fd40 Merge pull request #4808 from Alexays/copilot/fix-corrupted-double-linked-list
Fix heap corruption from GTK operations on IPC thread in Hyprland modules
2026-02-04 10:08:13 +01:00
717cc4a4d1 Fix Pango markup rendering in bluetooth module tooltip
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 09:07:46 +00:00
be9d9c87e6 Initial plan 2026-02-04 09:06:33 +00:00
e8558dd696 Initial plan 2026-02-04 09:05:50 +00:00
7921ab4008 Initial plan 2026-02-04 09:05:41 +00:00
4c5167083d Merge pull request #4809 from Alexays/copilot/fix-unhandled-exception
Fix unhandled JSON exception in signal handler
2026-02-04 10:04:16 +01:00
7261d00c31 Merge pull request #4810 from Alexays/copilot/fix-waybar-crash-pango
Fix Pango NULL layout crash in cava module
2026-02-04 10:03:11 +01:00
cb54b98fd5 Final updates - thread safety fix complete
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 09:00:09 +00:00
da8fd864c6 Simplify mutex locking in WindowCount module
- Acquire lock once at start of update() and hold for entire function
- Remove redundant lock from queryActiveWorkspace() since it's only called from update()
This addresses code review feedback and makes the locking strategy clearer

Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 08:57:53 +00:00
0a8b7b096a Simplify fix: only add isInt() check in refresh methods
Changed approach per maintainer feedback - instead of caching signal values,
just add isInt() check before accessing config_["signal"].asInt() in refresh()
methods. This is simpler and more minimal.

Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 08:57:08 +00:00
c1240a98aa Fix mutex locking in WindowCount module
Ensure workspace_ accesses are properly protected by mutex after queryActiveWorkspace call

Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 08:56:17 +00:00
e0a2cb8f8f Complete fix for Pango NULL layout crash
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 08:55:08 +00:00
74fb2f252f Remove CodeQL artifact from repository
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 08:54:48 +00:00
330c77c87a Fix thread safety in Hyprland modules to prevent corrupted double-linked list crash
- Move GTK operations from IPC thread to GTK main thread in Window module
- Move GTK operations from IPC thread to GTK main thread in WindowCount module
- Move GTK style class operations from IPC thread to GTK main thread in Submap module
- Language and Workspaces modules already safe (only update internal state)

Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 08:54:36 +00:00
19ede92d7f Complete fix for unhandled exception in signal handler
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 08:54:36 +00:00
03de38b4d0 Fix Pango NULL layout crash by clearing markup before hiding label
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 08:54:32 +00:00
4cadae83b3 Improve comments for cached signal values
Clarify that -1 indicates signal-based refresh is disabled

Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 08:54:14 +00:00
1466ca8bef Merge pull request #4729 from xav-ie/fix-cava-audio-height-init
fix-cava-audio-height-init
2026-02-04 09:54:00 +01:00
c34b1b6a19 Fix unhandled JSON exception in signal handlers
Cache signal value during module construction to avoid accessing JSON config
in signal handler context. This prevents crashes when signal field is missing
or not an integer type.

- Custom module: Cache signal_ value in constructor
- Image module: Cache signal_ value in constructor
- Both modules: Use cached value in refresh() method

Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
2026-02-04 08:53:47 +00:00
2c3aab88de Initial plan 2026-02-04 08:51:23 +00:00
f16a6c7dcf Initial plan 2026-02-04 08:51:07 +00:00
68e1e6dc26 Initial plan 2026-02-04 08:50:37 +00:00
39e59e557f fix: double free / uncatched errors 2026-02-04 09:47:00 +01:00
47fb21a2c1 chore: upgrade to clang-format@21 2026-02-04 09:24:14 +01:00
6cecaf56b9 Merge pull request #4806 from jackinfurs/fraudulent-website-notice
docs: add fraudulent site notice on proj README.md
2026-02-04 09:16:19 +01:00
60e73e8d12 docs: add fraudulent site notice on proj README.md 2026-02-03 23:28:53 +00:00
0d27c093b1 Merge pull request #4803 from BBaoVanC/fix-4776-set_namespace-string-return-type
Fix return type of input to gtk_layer_set_namespace
2026-02-03 18:53:14 +01:00
5ab28b901c Fix return type of input to gtk_layer_set_namespace 2026-02-01 22:01:04 -06:00
ddab2971fa Merge pull request #4776 from Holbormon/master
feat: Disambiguate wayland layer namespace
2026-02-01 17:14:06 +01:00
09cbec0a3c Merge pull request #4796 from Alexays/update_flake_lock_action
flake.lock: Update
2026-02-01 15:06:05 +01:00
c12658dea5 flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/c0b0e0fddf73fd517c3471e546c0df87a42d53f4?narHash=sha256-coBu0ONtFzlwwVBzmjacUQwj3G%2BlybcZ1oeNSQkgC0M%3D' (2025-12-28)
  → 'github:NixOS/nixpkgs/bfc1b8a4574108ceef22f02bafcf6611380c100d?narHash=sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI%3D' (2026-01-26)
2026-02-01 00:18:11 +00:00
2f94435014 Merge pull request #4789 from xander1421/fix/json-type-check-crash
fix(json): use local CharReaderBuilder for thread safety
2026-01-25 21:59:41 +01:00
1639dec7d8 fix(json): use local CharReaderBuilder for thread safety 2026-01-24 23:40:07 +02:00
762c4f2e27 Use name config field to set GTK layer namespace
Provides an easy way to disambiguate several waybars so that compositors like Hyprland may apply granular layer rules to different waybars.
2026-01-16 15:12:09 +00:00
b4854f96a3 Merge pull request #4766 from zjeffer/fix/zjeffer/persistent-special-workspaces
hyprland/workspaces: don't show persistent special workspaces if show-special is disabled
2026-01-14 18:27:30 +01:00
8f5fc990a5 hyprland/workspaces: don't show persistent special workspaces if show-special is disabled 2026-01-10 13:29:40 +01:00
a02180a815 Merge pull request #4739 from LorenzBischof/man-reverse-mouse-scrolling
docs: add missing reverse-mouse-scrolling to pulseaudio module man page
2026-01-09 20:02:15 +01:00
af7eebba5e Merge pull request #4745 from cartok/docs/arch-update-readme
docs(arch): install build deps as deps to keep system clean
2026-01-09 20:01:17 +01:00
479ea9f3e8 Merge pull request #4746 from cartok/chore/maintainance
chore: update .gitingore
2026-01-09 20:01:02 +01:00
f990486a40 Merge pull request #4748 from Alexays/update_flake_lock_action
flake.lock: Update
2026-01-09 20:00:50 +01:00
d0f5fab52b flake.lock: Update
Flake lock file updates:

• Updated input 'flake-compat':
    'github:edolstra/flake-compat/f387cd2afec9419c8ee37694406ca490c3f34ee5?narHash=sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4%3D' (2025-10-27)
  → 'github:edolstra/flake-compat/5edf11c44bc78a0d334f6334cdaf7d60d732daab?narHash=sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns%3D' (2025-12-29)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/2fad6eac6077f03fe109c4d4eb171cf96791faa4?narHash=sha256-sKoIWfnijJ0%2B9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI%3D' (2025-11-27)
  → 'github:NixOS/nixpkgs/c0b0e0fddf73fd517c3471e546c0df87a42d53f4?narHash=sha256-coBu0ONtFzlwwVBzmjacUQwj3G%2BlybcZ1oeNSQkgC0M%3D' (2025-12-28)
2026-01-01 00:14:44 +00:00
a05e6c6f74 chore: update .gitingore 2025-12-31 18:18:04 +01:00
99867005a0 docs(arch): install build deps as deps to keep system clean 2025-12-31 13:43:21 +01:00
959f41ca9c docs: add missing reverse-mouse-scrolling to pulseaudio module man page 2025-12-30 12:30:30 +01:00
19bb89874e fix(cava): default data_format to ascii for correct bar scaling
data_format was changed from always "ascii" to user-configurable,
but without a default. This caused cava to use "binary", calculating
height as 65535 instead of ascii_range, making bars always peak.
2025-12-28 20:09:33 -05:00
06484547d1 Merge pull request #4677 from mliszcz/remove-window-format
fix(sway/workspaces): window-rewrite: do not check for window-format
2025-12-28 23:12:44 +01:00
46a6f60138 Merge pull request #4728 from xav-ie/fix-cava-config
fix-cava-config
2025-12-28 23:11:05 +01:00
83a6998fcb Merge pull request #4708 from khaneliman/cava
nix: bump cava again
2025-12-28 21:50:21 +01:00
386036a67a Merge pull request #4710 from LukashonakV/cavaMan
cava man
2025-12-28 21:50:04 +01:00
e3186abdce fix(cava): handle all output methods in frontend
Default to raw Cava module for non-GLSL output methods.
Fixes "Unknown module" error when no cava_config is specified.
2025-12-27 14:52:28 -05:00
c8c3287be3 cava man 2025-12-20 15:35:20 +03:00
601b5f0241 nix: bump cava again
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-12-18 23:47:01 -06:00
97eb60677e Merge pull request #4616 from schmop/battery-plugging-instant-updates
2. Try: Make battery module update on plugging/unplugging again (refs #2519)
2025-12-18 19:11:18 +01:00
3d0b942956 Merge pull request #4689 from ospafford/feat-dwl_tag_state
feat(dwl/tags): add empty tag option
2025-12-18 19:09:39 +01:00
c3d29b1185 Merge branch 'master' into battery-plugging-instant-updates 2025-12-18 19:04:31 +01:00
c6844781ea Merge pull request #4671 from touero/dev
Fix example error about update moudle by signal in man page
2025-12-18 19:03:11 +01:00
c1218fa889 Merge pull request #4646 from gszy/swap-abused
modules: memory: fix fully utilized swap percentage calculation
2025-12-18 19:02:47 +01:00
11c4e55376 Merge pull request #4591 from rrrnld/fix/multiple-batteries
Improve multiple battery support
2025-12-18 19:02:31 +01:00
6b05d73a64 Merge pull request #4589 from cebem1nt/master
fix: crash on group scrolling #4510
2025-12-18 19:01:15 +01:00
374ccbb878 Merge pull request #4705 from rwwiv/fix/duplicate-layers-on-monitor-hotplug
fix: prevent duplicate layer surfaces on monitor hotplug
2025-12-18 19:00:48 +01:00
d012de3cde Merge pull request #4682 from LukashonakV/cavaGLSL
Cava GLSL
2025-12-18 18:59:27 +01:00
7ecad3229d Merge pull request #4650 from BartiX259/master
fix(docs): pulseaudio man page example
2025-12-18 18:59:01 +01:00
278e8822ff Merge pull request #4686 from marvelpokemaster/fix-wireplumber-init-order
fix(wireplumber): reorder initializer list to match header and fix -Wreorder
2025-12-18 18:58:10 +01:00
a23cef457f Merge pull request #4615 from Alexays/update_flake_lock_action
flake.lock: Update
2025-12-18 18:57:57 +01:00
a9ef11a2b3 fix: prevent duplicate layer surfaces on monitor hotplug
The monitor signal handlers (signal_monitor_added, signal_monitor_removed)
were never disconnected during SIGUSR2 reload. Each reload accumulated
additional handlers, causing multiple layer surfaces to be created when
monitors were hotplugged.

This fix:
- Stores signal connections as class members
- Disconnects them before reconnecting in bindInterfaces()
- Clears stale outputs_ on reload
2025-12-17 22:17:35 -05:00
07cb2c02d2 feat(dwl/tags): add empty tag option
Added option in the `dwl/tags` to theme empty tags (i.e. tags without any clients) in `style.css` using
`#tags button.empty`.

Signed-off-by: ospafford <ospafford@gmail.com>
2025-12-09 07:28:18 -08:00
e03119fe94 Factory. cava_frontend 2025-12-09 18:13:45 +03:00
5ee3bd5325 fix(wireplumber): reorder initializer list to match header and fix -Wreorder warnings 2025-12-08 01:44:19 +05:30
3773021546 cavaGLSL 2025-12-07 23:08:55 +03:00
52f4db1154 Moving GTK dispatcher into frontend 2025-12-05 10:04:52 +03:00
e362550e27 fix(sway/workspaces): window-rewrite: do not check for window-format
Remove check for unused window-format option.

Fixes #3797.
2025-12-02 17:19:44 +01:00
cb0ee665a3 flake.lock: Update
Flake lock file updates:

• Updated input 'flake-compat':
    'github:edolstra/flake-compat/9100a0f413b0c601e0533d1d94ffd501ce2e7885?narHash=sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX%2BfjA8Xf8PUmqCY%3D' (2025-05-12)
  → 'github:edolstra/flake-compat/f387cd2afec9419c8ee37694406ca490c3f34ee5?narHash=sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4%3D' (2025-10-27)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/5e2a59a5b1a82f89f2c7e598302a9cacebb72a67?narHash=sha256-K5Osef2qexezUfs0alLvZ7nQFTGS9DL2oTVsIXsqLgs%3D' (2025-10-19)
  → 'github:NixOS/nixpkgs/2fad6eac6077f03fe109c4d4eb171cf96791faa4?narHash=sha256-sKoIWfnijJ0%2B9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI%3D' (2025-11-27)
2025-12-01 00:15:02 +00:00
e189649c33 docs(custom): fix example error about update moudle by signal 2025-11-29 17:29:52 +08:00
13519ca5bf cava. nonsafe thread.= & cava bump 2025-11-26 13:26:32 +03:00
097c00c7bd fix(docs): pulseaudio man page example
The example configuration in the man page used 'headphones' and 'handsfree' as keys for format-icons. The correct keys are 'headphone' and 'hands-free'.
2025-11-22 20:09:34 +01:00
73808dfacc modules: memory: fix fully utilized swap percentage calculation
Do calculate used swap percentage even if swapfree is 0, otherwise
reported used_swap_percentage would be 0, even though it should be 100.

Signed-off-by: Grzegorz Szymaszek <gszymaszek@short.pl>
2025-11-18 11:50:04 +01:00
ce1da5a178 Make udev_deleter not linux-only and fix freebsd build 2025-11-01 10:57:18 +01:00
4e25871655 Reapply "Make battery module update on plugging/unplugging again (refs #2519)"
This reverts commit bb2c67ebad.
2025-10-31 13:43:36 +01:00
ca62481dc9 fix: default weighted average to true 2025-10-26 06:44:53 +01:00
b701d7f70b docs: add information about weighted-average config option 2025-10-26 06:34:04 +01:00
68cbb507d9 fixing crash on group scrolling 2025-10-24 21:57:58 -03:00
161367d961 Merge pull request #4579 from khaneliman/freebsd
fix(clock): fix freebsd compatibility
2025-10-23 09:36:19 +02:00
a62455e1b9 Merge pull request #4578 from khaneliman/fmt
fix(subprojects): fmt hash mismatch
2025-10-23 09:35:49 +02:00
588c344c8a Merge pull request #4577 from khaneliman/cava
fix(nix): bump cava and fix nix build
2025-10-23 09:35:39 +02:00
bf0ccfd90c fix(clock): fix freebsd compatibility
Recently introduced for ISO 8601 calendar compatibility. But, lib
differences causing the explicit type to break freebsd.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-10-21 23:07:04 -05:00
8b0a82ad34 fix(subprojects): fmt hash mismatch
Failing ci for multiple runners

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-10-21 22:56:33 -05:00
37ac2daac8 flake.lock: update
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-10-21 22:08:57 -05:00
97682a1332 nix: bump cava
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-10-21 22:08:57 -05:00
4beb7ddac7 nix: remove useless parens
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-10-19 17:35:07 -05:00
84ec25bbeb Merge pull request #4551 from LukashonakV/cavaBump
cava bump & fixing memory leaks
2025-10-19 13:38:58 +02:00
b475399a22 Merge pull request #4541 from aanderse/master
backlight: gracefully handle a null epoll device
2025-10-19 13:38:39 +02:00
15a503ae21 Merge pull request #4546 from kosa12/fix/fmt-version
fix: FMT version update from 11.0.2 to 12.0.0
2025-10-19 13:38:15 +02:00
46d3e80bce Merge pull request #4559 from carljustineoyales/chore/update-pulseaudio-slider-module
fix(pulseaudio-slider): Use `background` in CSS example
2025-10-19 13:38:03 +02:00
9221508e51 Merge pull request #4560 from NicolasBuchin/fix-css-memory-leak
fix: resolve memory leak by removing old CSS provider before reloading CSS styles
2025-10-19 13:37:48 +02:00
9d37dedb57 fix: resolve memory leak by removing old CSS provider before reloading styles 2025-10-16 10:04:12 +02:00
6021261383 fix(pulseaudio-slider): Use background in CSS example
The `background-color` property does not work as expected for the slider. Using the `background` shorthand property correctly applies the color.
2025-10-15 20:47:35 +08:00
966da11f3b cava bump & fixing memory leaks 2025-10-12 14:53:49 +03:00
7add8b2726 fix: FMT version update from 11.0.2 to 12.0.0 2025-10-10 19:40:43 +03:00
bef35e48fe backlight: gracefully handle a null epoll device 2025-10-09 20:52:51 -04:00
116 changed files with 2513 additions and 1511 deletions

View File

@ -2,4 +2,5 @@
;;; For more information see (info "(emacs) Directory Variables") ;;; For more information see (info "(emacs) Directory Variables")
((nil . ((ff-search-directories . ("../include/*/" "../../include/*/" ((nil . ((ff-search-directories . ("../include/*/" "../../include/*/"
"../src/*/" "../../src/*/"))))) "../src/*/" "../../src/*/"))
(apheleia-inhibit . t))))

View File

@ -11,12 +11,8 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
# 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

4
.gitignore vendored
View File

@ -7,6 +7,7 @@ vgcore.*
*.swp *.swp
packagecache packagecache
/subprojects/**/ /subprojects/**/
/subprojects/.wraplock
/build* /build*
/dist /dist
/meson.egg-info /meson.egg-info
@ -50,5 +51,4 @@ result
result-* result-*
.ccls-cache .ccls-cache
_codeql_detected_source_root
.wraplock

View File

@ -125,7 +125,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++ \
@ -157,6 +157,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).

View File

@ -0,0 +1 @@
.

12
flake.lock generated
View File

@ -3,11 +3,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1747046372, "lastModified": 1767039857,
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -18,11 +18,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1759036355, "lastModified": 1769461804,
"narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -9,15 +9,15 @@ namespace waybar {
class AAppIconLabel : public AIconLabel { class AAppIconLabel : public AIconLabel {
public: public:
AAppIconLabel(const Json::Value &config, const std::string &name, const std::string &id, AAppIconLabel(const Json::Value& config, const std::string& name, const std::string& id,
const std::string &format, uint16_t interval = 0, bool ellipsize = false, const std::string& format, uint16_t interval = 0, bool ellipsize = false,
bool enable_click = false, bool enable_scroll = false); bool enable_click = false, bool enable_scroll = false);
virtual ~AAppIconLabel() = default; virtual ~AAppIconLabel() = default;
auto update() -> void override; auto update() -> void override;
protected: protected:
void updateAppIconName(const std::string &app_identifier, void updateAppIconName(const std::string& app_identifier,
const std::string &alternative_app_identifier); const std::string& alternative_app_identifier);
void updateAppIcon(); void updateAppIcon();
unsigned app_icon_size_{24}; unsigned app_icon_size_{24};
bool update_app_icon_{true}; bool update_app_icon_{true};

View File

@ -9,8 +9,8 @@ namespace waybar {
class AIconLabel : public ALabel { class AIconLabel : public ALabel {
public: public:
AIconLabel(const Json::Value &config, const std::string &name, const std::string &id, AIconLabel(const Json::Value& config, const std::string& name, const std::string& id,
const std::string &format, uint16_t interval = 0, bool ellipsize = false, const std::string& format, uint16_t interval = 0, bool ellipsize = false,
bool enable_click = false, bool enable_scroll = false); bool enable_click = false, bool enable_scroll = false);
virtual ~AIconLabel() = default; virtual ~AIconLabel() = default;
auto update() -> void override; auto update() -> void override;

View File

@ -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

View File

@ -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_;

View File

@ -62,11 +62,11 @@ class Bar : public sigc::trackable {
static const std::string MODE_DEFAULT; static const std::string MODE_DEFAULT;
static const std::string MODE_INVISIBLE; static const std::string MODE_INVISIBLE;
Bar(struct waybar_output *w_output, const Json::Value &); Bar(struct waybar_output* w_output, const Json::Value&);
Bar(const Bar &) = delete; Bar(const Bar&) = delete;
~Bar(); ~Bar();
void setMode(const std::string &mode); void setMode(const std::string& mode);
void setVisible(bool value); void setVisible(bool value);
void toggle(); void toggle();
void show(); void show();
@ -75,9 +75,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();

View File

@ -63,6 +63,8 @@ class Client {
std::string m_cssFile; std::string m_cssFile;
std::map<int, bool> signal_toggle_state; std::map<int, bool> signal_toggle_state;
sigc::connection monitor_added_connection_;
sigc::connection monitor_removed_connection_;
}; };
} // namespace waybar } // namespace waybar

View File

@ -14,29 +14,29 @@ namespace waybar {
class Config { class Config {
public: public:
static const std::vector<std::string> CONFIG_DIRS; static const std::vector<std::string> CONFIG_DIRS;
static const char *CONFIG_PATH_ENV; static const char* CONFIG_PATH_ENV;
/* Try to find any of provided names in the supported set of config directories */ /* Try to find any of provided names in the supported set of config directories */
static std::optional<std::string> findConfigPath( static std::optional<std::string> findConfigPath(
const std::vector<std::string> &names, const std::vector<std::string> &dirs = CONFIG_DIRS); const std::vector<std::string>& names, const std::vector<std::string>& dirs = CONFIG_DIRS);
static std::vector<std::string> tryExpandPath(const std::string &base, static std::vector<std::string> tryExpandPath(const std::string& base,
const std::string &filename); const std::string& filename);
Config() = default; Config() = default;
void load(const std::string &config); void load(const std::string& config);
Json::Value &getConfig() { return config_; } Json::Value& getConfig() { return config_; }
std::vector<Json::Value> getOutputConfigs(const std::string &name, const std::string &identifier); std::vector<Json::Value> getOutputConfigs(const std::string& name, const std::string& identifier);
private: private:
void setupConfig(Json::Value &dst, const std::string &config_file, int depth); void setupConfig(Json::Value& dst, const std::string& config_file, int depth);
void resolveConfigIncludes(Json::Value &config, int depth); void resolveConfigIncludes(Json::Value& config, int depth);
void mergeConfig(Json::Value &a_config_, Json::Value &b_config_); void mergeConfig(Json::Value& a_config_, Json::Value& b_config_);
static std::vector<std::string> findIncludePath( static std::vector<std::string> findIncludePath(
const std::string &name, const std::vector<std::string> &dirs = CONFIG_DIRS); const std::string& name, const std::vector<std::string>& dirs = CONFIG_DIRS);
std::string config_file_; std::string config_file_;

View File

@ -17,11 +17,11 @@ namespace waybar::modules {
class Backlight : public ALabel { class Backlight : public ALabel {
public: public:
Backlight(const std::string &, const Json::Value &); Backlight(const std::string&, const Json::Value&);
virtual ~Backlight() = default; virtual ~Backlight() = default;
auto update() -> void override; auto update() -> void override;
bool handleScroll(GdkEventScroll *e) override; bool handleScroll(GdkEventScroll* e) override;
const std::string preferred_device_; const std::string preferred_device_;

View File

@ -6,6 +6,7 @@
#if defined(__linux__) #if defined(__linux__)
#include <sys/inotify.h> #include <sys/inotify.h>
#endif #endif
#include <sys/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_;

View File

@ -0,0 +1,43 @@
#pragma once
#include <epoxy/gl.h>
#include "AModule.hpp"
#include "cava_backend.hpp"
namespace waybar::modules::cava {
class CavaGLSL final : public AModule, public Gtk::GLArea {
public:
CavaGLSL(const std::string&, const Json::Value&);
~CavaGLSL() = default;
private:
std::shared_ptr<CavaBackend> backend_;
struct ::cava::config_params prm_;
int frame_counter{0};
bool silence_{false};
bool hide_on_silence_{false};
// Cava method
auto onUpdate(const ::cava::audio_raw& input) -> void;
auto onSilence() -> void;
// Member variable to store the shared pointer
std::shared_ptr<::cava::audio_raw> m_data_;
GLuint shaderProgram_;
// OpenGL variables
GLuint fbo_;
GLuint texture_;
GLint uniform_bars_;
GLint uniform_previous_bars_;
GLint uniform_bars_count_;
GLint uniform_time_;
// Methods
void onRealize();
bool onRender(const Glib::RefPtr<Gdk::GLContext>& context);
void initShaders();
void initSurface();
void initGLSL();
GLuint loadShader(const std::string& fileName, GLenum type);
};
} // namespace waybar::modules::cava

View File

@ -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}};

View File

@ -32,29 +32,36 @@ 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_; ::cava::ptr input_source_{NULL};
struct ::cava::error_s error_{}; // cava errors struct ::cava::error_s error_{}; // cava errors
struct ::cava::config_params prm_{}; // cava parameters struct ::cava::config_params prm_{}; // cava parameters
struct ::cava::audio_raw audio_raw_{}; // cava handled raw audio data(is based on audio_data) struct ::cava::audio_raw audio_raw_{}; // cava handled raw audio data(is based on audio_data)
struct ::cava::audio_data audio_data_{}; // cava audio data struct ::cava::audio_data audio_data_{}; // cava audio data
struct ::cava::cava_plan* plan_; //{new cava_plan{}}; struct ::cava::cava_plan* plan_{NULL}; //{new cava_plan{}};
std::chrono::seconds fetch_input_delay_{4}; std::chrono::seconds fetch_input_delay_{4};
// 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

View File

@ -0,0 +1,27 @@
#pragma once
#ifdef HAVE_LIBCAVA
#include "cavaRaw.hpp"
#include "cava_backend.hpp"
#ifdef HAVE_LIBCAVAGLSL
#include "cavaGLSL.hpp"
#endif
#endif
namespace waybar::modules::cava {
AModule* getModule(const std::string& id, const Json::Value& config) {
#ifdef HAVE_LIBCAVA
const std::shared_ptr<CavaBackend> backend_{waybar::modules::cava::CavaBackend::inst(config)};
switch (backend_->getPrm()->output) {
#ifdef HAVE_LIBCAVAGLSL
case ::cava::output_method::OUTPUT_SDL_GLSL:
return new waybar::modules::cava::CavaGLSL(id, config);
#endif
default:
return new waybar::modules::cava::Cava(id, config);
}
#else
throw std::runtime_error("Unknown module");
#endif
};
} // namespace waybar::modules::cava

View File

@ -12,23 +12,23 @@ namespace waybar::modules::dwl {
class Tags : public waybar::AModule { class Tags : public waybar::AModule {
public: public:
Tags(const std::string &, const waybar::Bar &, const Json::Value &); Tags(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Tags(); virtual ~Tags();
// Handlers for wayland events // Handlers for wayland events
void handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused); void handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused);
void handle_primary_clicked(uint32_t tag); void handle_primary_clicked(uint32_t tag);
bool handle_button_press(GdkEventButton *event_button, uint32_t tag); bool handle_button_press(GdkEventButton* event_button, uint32_t tag);
struct zdwl_ipc_manager_v2 *status_manager_; struct zdwl_ipc_manager_v2* status_manager_;
struct wl_seat *seat_; struct wl_seat* seat_;
private: private:
const waybar::Bar &bar_; const waybar::Bar& bar_;
Gtk::Box box_; Gtk::Box box_;
std::vector<Gtk::Button> buttons_; std::vector<Gtk::Button> buttons_;
struct zdwl_ipc_output_v2 *output_status_; struct zdwl_ipc_output_v2* output_status_;
}; };
} /* namespace waybar::modules::dwl */ } /* namespace waybar::modules::dwl */

View File

@ -13,26 +13,26 @@ namespace waybar::modules::dwl {
class Window : public AAppIconLabel, public sigc::trackable { class Window : public AAppIconLabel, public sigc::trackable {
public: public:
Window(const std::string &, const waybar::Bar &, const Json::Value &); Window(const std::string&, const waybar::Bar&, const Json::Value&);
~Window(); ~Window();
void handle_layout(const uint32_t layout); void handle_layout(const uint32_t layout);
void handle_title(const char *title); void handle_title(const char* title);
void handle_appid(const char *ppid); void handle_appid(const char* ppid);
void handle_layout_symbol(const char *layout_symbol); void handle_layout_symbol(const char* layout_symbol);
void handle_frame(); void handle_frame();
struct zdwl_ipc_manager_v2 *status_manager_; struct zdwl_ipc_manager_v2* status_manager_;
private: private:
const Bar &bar_; const Bar& bar_;
std::string title_; std::string title_;
std::string appid_; std::string appid_;
std::string layout_symbol_; std::string layout_symbol_;
uint32_t layout_; uint32_t layout_;
struct zdwl_ipc_output_v2 *output_status_; struct zdwl_ipc_output_v2* output_status_;
}; };
} // namespace waybar::modules::dwl } // namespace waybar::modules::dwl

View File

@ -20,16 +20,16 @@ class Workspace;
class WorkspaceManager final : public AModule { class WorkspaceManager final : public AModule {
public: public:
WorkspaceManager(const std::string &id, const waybar::Bar &bar, const Json::Value &config); WorkspaceManager(const std::string& id, const waybar::Bar& bar, const Json::Value& config);
~WorkspaceManager() override; ~WorkspaceManager() override;
void register_manager(wl_registry *registry, uint32_t name, uint32_t version); void register_manager(wl_registry* registry, uint32_t name, uint32_t version);
void remove_workspace_group(uint32_t id); void remove_workspace_group(uint32_t id);
void remove_workspace(uint32_t id); void remove_workspace(uint32_t id);
void set_needs_sorting() { needs_sorting_ = true; } void set_needs_sorting() { needs_sorting_ = true; }
// wl events // wl events
void handle_workspace_group(ext_workspace_group_handle_v1 *handle); void handle_workspace_group(ext_workspace_group_handle_v1* handle);
void handle_workspace(ext_workspace_handle_v1 *handle); void handle_workspace(ext_workspace_handle_v1* handle);
void handle_done(); void handle_done();
void handle_finished(); void handle_finished();
@ -38,7 +38,7 @@ class WorkspaceManager final : public AModule {
private: private:
void update() override; void update() override;
bool has_button(const Gtk::Button *button); bool has_button(const Gtk::Button* button);
void sort_workspaces(); void sort_workspaces();
void clear_buttons(); void clear_buttons();
void update_buttons(); void update_buttons();
@ -52,10 +52,10 @@ class WorkspaceManager final : public AModule {
bool sort_by_coordinates_ = false; bool sort_by_coordinates_ = false;
bool all_outputs_ = false; bool all_outputs_ = false;
const waybar::Bar &bar_; const waybar::Bar& bar_;
Gtk::Box box_; Gtk::Box box_;
ext_workspace_manager_v1 *ext_manager_ = nullptr; ext_workspace_manager_v1* ext_manager_ = nullptr;
std::vector<std::unique_ptr<WorkspaceGroup>> groups_; std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
std::vector<std::unique_ptr<Workspace>> workspaces_; std::vector<std::unique_ptr<Workspace>> workspaces_;
@ -64,60 +64,60 @@ class WorkspaceManager final : public AModule {
class WorkspaceGroup { class WorkspaceGroup {
public: public:
WorkspaceGroup(WorkspaceManager &manager, ext_workspace_group_handle_v1 *handle, uint32_t id); WorkspaceGroup(WorkspaceManager& manager, ext_workspace_group_handle_v1* handle, uint32_t id);
~WorkspaceGroup(); ~WorkspaceGroup();
u_int32_t id() const { return id_; } u_int32_t id() const { return id_; }
bool has_output(const wl_output *output); bool has_output(const wl_output* output);
bool has_workspace(const ext_workspace_handle_v1 *workspace); bool has_workspace(const ext_workspace_handle_v1* workspace);
// wl events // wl events
void handle_capabilities(uint32_t capabilities); void handle_capabilities(uint32_t capabilities);
void handle_output_enter(wl_output *output); void handle_output_enter(wl_output* output);
void handle_output_leave(wl_output *output); void handle_output_leave(wl_output* output);
void handle_workspace_enter(ext_workspace_handle_v1 *handle); void handle_workspace_enter(ext_workspace_handle_v1* handle);
void handle_workspace_leave(ext_workspace_handle_v1 *handle); void handle_workspace_leave(ext_workspace_handle_v1* handle);
void handle_removed(); void handle_removed();
private: private:
WorkspaceManager &workspaces_manager_; WorkspaceManager& workspaces_manager_;
ext_workspace_group_handle_v1 *ext_handle_; ext_workspace_group_handle_v1* ext_handle_;
uint32_t id_; uint32_t id_;
std::vector<wl_output *> outputs_; std::vector<wl_output*> outputs_;
std::vector<ext_workspace_handle_v1 *> workspaces_; std::vector<ext_workspace_handle_v1*> workspaces_;
}; };
class Workspace { class Workspace {
public: public:
Workspace(const Json::Value &config, WorkspaceManager &manager, ext_workspace_handle_v1 *handle, Workspace(const Json::Value& config, WorkspaceManager& manager, ext_workspace_handle_v1* handle,
uint32_t id, const std::string &name); uint32_t id, const std::string& name);
~Workspace(); ~Workspace();
ext_workspace_handle_v1 *handle() const { return ext_handle_; } ext_workspace_handle_v1* handle() const { return ext_handle_; }
u_int32_t id() const { return id_; } u_int32_t id() const { return id_; }
std::string &workspace_id() { return workspace_id_; } std::string& workspace_id() { return workspace_id_; }
std::string &name() { return name_; } std::string& name() { return name_; }
std::vector<u_int32_t> &coordinates() { return coordinates_; } std::vector<u_int32_t>& coordinates() { return coordinates_; }
Gtk::Button &button() { return button_; } Gtk::Button& button() { return button_; }
void update(); void update();
// wl events // wl events
void handle_id(const std::string &id); void handle_id(const std::string& id);
void handle_name(const std::string &name); void handle_name(const std::string& name);
void handle_coordinates(const std::vector<uint32_t> &coordinates); void handle_coordinates(const std::vector<uint32_t>& coordinates);
void handle_state(uint32_t state); void handle_state(uint32_t state);
void handle_capabilities(uint32_t capabilities); void handle_capabilities(uint32_t capabilities);
void handle_removed(); void handle_removed();
// gdk events // gdk events
bool handle_clicked(const GdkEventButton *button) const; bool handle_clicked(const GdkEventButton* button) const;
private: private:
bool has_state(uint32_t state) const { return (state_ & state) == state; } bool has_state(uint32_t state) const { return (state_ & state) == state; }
std::string icon(); std::string icon();
WorkspaceManager &workspace_manager_; WorkspaceManager& workspace_manager_;
ext_workspace_handle_v1 *ext_handle_ = nullptr; ext_workspace_handle_v1* ext_handle_ = nullptr;
uint32_t id_; uint32_t id_;
uint32_t state_ = 0; uint32_t state_ = 0;
std::string workspace_id_; std::string workspace_id_;

View File

@ -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

View File

@ -17,7 +17,7 @@ namespace waybar::modules {
class Gamemode : public AModule { class Gamemode : public AModule {
public: public:
Gamemode(const std::string &, const Json::Value &); Gamemode(const std::string&, const Json::Value&);
virtual ~Gamemode(); virtual ~Gamemode();
auto update() -> void override; auto update() -> void override;
@ -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 &parameters); const Glib::VariantContainerBase& parameters);
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name, void notify_cb(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
const Glib::VariantContainerBase &arguments); const Glib::VariantContainerBase& arguments);
void getData(); void getData();
bool handleToggle(GdkEventButton *const &) override; bool handleToggle(GdkEventButton* const&) override;
// Config // Config
std::string format = DEFAULT_FORMAT; std::string format = DEFAULT_FORMAT;

View File

@ -26,6 +26,7 @@ class Submap : public waybar::ALabel, public EventHandler {
const Bar& bar_; const Bar& bar_;
util::JsonParser parser_; util::JsonParser parser_;
std::string submap_; std::string submap_;
std::string prev_submap_;
bool always_on_ = false; bool always_on_ = false;
std::string default_submap_ = "Default"; std::string default_submap_ = "Default";

View File

@ -13,7 +13,7 @@ namespace waybar::modules {
class JACK : public ALabel { class JACK : public ALabel {
public: public:
JACK(const std::string &, const Json::Value &); JACK(const std::string&, const Json::Value&);
virtual ~JACK() = default; virtual ~JACK() = default;
auto update() -> void override; auto update() -> void override;
@ -25,7 +25,7 @@ class JACK : public ALabel {
private: private:
std::string JACKState(); std::string JACKState();
jack_client_t *client_; jack_client_t* client_;
jack_nframes_t bufsize_; jack_nframes_t bufsize_;
jack_nframes_t samplerate_; jack_nframes_t samplerate_;
unsigned int xruns_; unsigned int xruns_;
@ -38,7 +38,7 @@ class JACK : public ALabel {
} // namespace waybar::modules } // namespace waybar::modules
int bufSizeCallback(jack_nframes_t size, void *obj); int bufSizeCallback(jack_nframes_t size, void* obj);
int sampleRateCallback(jack_nframes_t rate, void *obj); int sampleRateCallback(jack_nframes_t rate, void* obj);
int xrunCallback(void *obj); int xrunCallback(void* obj);
void shutdownCallback(void *obj); void shutdownCallback(void* obj);

View File

@ -10,13 +10,13 @@ namespace waybar::modules::niri {
class Language : public ALabel, public EventHandler { class Language : public ALabel, public EventHandler {
public: public:
Language(const std::string &, const Bar &, const Json::Value &); Language(const std::string&, const Bar&, const Json::Value&);
~Language() override; ~Language() override;
void update() override; void update() override;
private: private:
void updateFromIPC(); void updateFromIPC();
void onEvent(const Json::Value &ev) override; void onEvent(const Json::Value& ev) override;
void doUpdate(); void doUpdate();
struct Layout { struct Layout {
@ -26,10 +26,10 @@ class Language : public ALabel, public EventHandler {
std::string short_description; std::string short_description;
}; };
static Layout getLayout(const std::string &fullName); static Layout getLayout(const std::string& fullName);
std::mutex mutex_; std::mutex mutex_;
const Bar &bar_; const Bar& bar_;
std::vector<Layout> layouts_; std::vector<Layout> layouts_;
unsigned current_idx_; unsigned current_idx_;

View File

@ -11,16 +11,16 @@ namespace waybar::modules::niri {
class Window : public AAppIconLabel, public EventHandler { class Window : public AAppIconLabel, public EventHandler {
public: public:
Window(const std::string &, const Bar &, const Json::Value &); Window(const std::string&, const Bar&, const Json::Value&);
~Window() override; ~Window() override;
void update() override; void update() override;
private: private:
void onEvent(const Json::Value &ev) override; void onEvent(const Json::Value& ev) override;
void doUpdate(); void doUpdate();
void setClass(const std::string &className, bool enable); void setClass(const std::string& className, bool enable);
const Bar &bar_; const Bar& bar_;
std::string oldAppId_; std::string oldAppId_;
}; };

View File

@ -11,17 +11,17 @@ namespace waybar::modules::niri {
class Workspaces : public AModule, public EventHandler { class Workspaces : public AModule, public EventHandler {
public: public:
Workspaces(const std::string &, const Bar &, const Json::Value &); Workspaces(const std::string&, const Bar&, const Json::Value&);
~Workspaces() override; ~Workspaces() override;
void update() override; void update() override;
private: private:
void onEvent(const Json::Value &ev) override; void onEvent(const Json::Value& ev) override;
void doUpdate(); void doUpdate();
Gtk::Button &addButton(const Json::Value &ws); Gtk::Button& addButton(const Json::Value& ws);
std::string getIcon(const std::string &value, const Json::Value &ws); std::string getIcon(const std::string& value, const Json::Value& ws);
const Bar &bar_; const Bar& bar_;
Gtk::Box box_; Gtk::Box box_;
// Map from niri workspace id to button. // Map from niri workspace id to button.
std::unordered_map<uint64_t, Gtk::Button> buttons_; std::unordered_map<uint64_t, Gtk::Button> buttons_;

View File

@ -16,15 +16,15 @@ struct Profile {
class PowerProfilesDaemon : public ALabel { class PowerProfilesDaemon : public ALabel {
public: public:
PowerProfilesDaemon(const std::string &, const Json::Value &); PowerProfilesDaemon(const std::string&, const Json::Value&);
auto update() -> void override; auto update() -> void override;
void profileChangedCb(const Gio::DBus::Proxy::MapChangedProperties &, void profileChangedCb(const Gio::DBus::Proxy::MapChangedProperties&,
const std::vector<Glib::ustring> &); const std::vector<Glib::ustring>&);
void busConnectedCb(Glib::RefPtr<Gio::AsyncResult> &r); void busConnectedCb(Glib::RefPtr<Gio::AsyncResult>& r);
void getAllPropsCb(Glib::RefPtr<Gio::AsyncResult> &r); void getAllPropsCb(Glib::RefPtr<Gio::AsyncResult>& r);
void setPropCb(Glib::RefPtr<Gio::AsyncResult> &r); void setPropCb(Glib::RefPtr<Gio::AsyncResult>& r);
void populateInitState(); void populateInitState();
bool handleToggle(GdkEventButton *const &e) override; bool handleToggle(GdkEventButton* const& e) override;
private: private:
// True if we're connected to the dbug interface. False if we're // True if we're connected to the dbug interface. False if we're
@ -32,7 +32,7 @@ class PowerProfilesDaemon : public ALabel {
bool connected_; bool connected_;
// Look for a profile name in the list of available profiles and // Look for a profile name in the list of available profiles and
// switch activeProfile_ to it. // switch activeProfile_ to it.
void switchToProfile(std::string const &); void switchToProfile(std::string const&);
// Used to toggle/display the profiles // Used to toggle/display the profiles
std::vector<Profile> availableProfiles_; std::vector<Profile> availableProfiles_;
// Points to the active profile in the profiles list // Points to the active profile in the profiles list

View File

@ -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;

View File

@ -16,16 +16,16 @@ namespace waybar::modules::privacy {
class PrivacyItem : public Gtk::Revealer { class PrivacyItem : public Gtk::Revealer {
public: public:
PrivacyItem(const Json::Value &config_, enum PrivacyNodeType privacy_type_, PrivacyItem(const Json::Value& config_, enum PrivacyNodeType privacy_type_,
std::list<PrivacyNodeInfo *> *nodes, Gtk::Orientation orientation, std::list<PrivacyNodeInfo*>* nodes, Gtk::Orientation orientation,
const std::string &pos, const uint icon_size, const uint transition_duration); const std::string& pos, const uint icon_size, const uint transition_duration);
enum PrivacyNodeType privacy_type; enum PrivacyNodeType privacy_type;
void set_in_use(bool in_use); void set_in_use(bool in_use);
private: private:
std::list<PrivacyNodeInfo *> *nodes; std::list<PrivacyNodeInfo*>* nodes;
sigc::connection signal_conn; sigc::connection signal_conn;

View File

@ -10,25 +10,25 @@ namespace waybar::modules::river {
class Layout : public waybar::ALabel { class Layout : public waybar::ALabel {
public: public:
Layout(const std::string &, const waybar::Bar &, const Json::Value &); Layout(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Layout(); virtual ~Layout();
// Handlers for wayland events // Handlers for wayland events
void handle_name(const char *name); void handle_name(const char* name);
void handle_clear(); void handle_clear();
void handle_focused_output(struct wl_output *output); void handle_focused_output(struct wl_output* output);
void handle_unfocused_output(struct wl_output *output); void handle_unfocused_output(struct wl_output* output);
struct zriver_status_manager_v1 *status_manager_; struct zriver_status_manager_v1* status_manager_;
struct wl_seat *seat_; struct wl_seat* seat_;
private: private:
const waybar::Bar &bar_; const waybar::Bar& bar_;
std::string name_; std::string name_;
struct wl_output *output_; // stores the output this module belongs to struct wl_output* output_; // stores the output this module belongs to
struct wl_output *focused_output_; // stores the currently focused output struct wl_output* focused_output_; // stores the currently focused output
struct zriver_output_status_v1 *output_status_; struct zriver_output_status_v1* output_status_;
struct zriver_seat_status_v1 *seat_status_; struct zriver_seat_status_v1* seat_status_;
}; };
} /* namespace waybar::modules::river */ } /* namespace waybar::modules::river */

View File

@ -10,20 +10,20 @@ 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::set<std::string> hidden_modes_; std::set<std::string> hidden_modes_;
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 */

View File

@ -13,32 +13,32 @@ 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_focused_view(const char *title, uint32_t tags); void handle_focused_view(const char *title, 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 zriver_seat_status_v1 *seat_status_; struct zriver_seat_status_v1 *seat_status_;
struct wl_seat *seat_; struct wl_seat* seat_;
// used to make sure the focused view tags are on the correct output // used to make sure the focused view tags are on the correct output
const wl_output *output_; const wl_output* output_;
const wl_output *focused_output_; const wl_output* focused_output_;
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 */

View File

@ -14,23 +14,23 @@ 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, uint32_t); void handle_focused_view(const char* title, uint32_t tags);
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::optional<std::string> default_format_; // format when there is no window std::optional<std::string> default_format_; // format when there is no window
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 */

View File

@ -11,18 +11,18 @@ namespace waybar::modules {
class Sndio : public ALabel { class Sndio : public ALabel {
public: public:
Sndio(const std::string &, const Json::Value &); Sndio(const std::string&, const Json::Value&);
virtual ~Sndio(); virtual ~Sndio();
auto update() -> void override; auto update() -> void override;
auto set_desc(struct sioctl_desc *, unsigned int) -> void; auto set_desc(struct sioctl_desc*, unsigned int) -> void;
auto put_val(unsigned int, unsigned int) -> void; auto put_val(unsigned int, unsigned int) -> void;
bool handleScroll(GdkEventScroll *) override; bool handleScroll(GdkEventScroll*) override;
bool handleToggle(GdkEventButton *const &) override; bool handleToggle(GdkEventButton* const&) override;
private: private:
auto connect_to_sndio() -> void; auto connect_to_sndio() -> void;
util::SleeperThread thread_; util::SleeperThread thread_;
struct sioctl_hdl *hdl_; struct sioctl_hdl* hdl_;
std::vector<struct pollfd> pfds_; std::vector<struct pollfd> pfds_;
unsigned int addr_; unsigned int addr_;
unsigned int volume_, old_volume_, maxval_; unsigned int volume_, old_volume_, maxval_;

View File

@ -30,27 +30,27 @@ class Watcher {
typedef struct { typedef struct {
GfWatchType type; GfWatchType type;
Watcher *watcher; Watcher* watcher;
gchar *service; gchar* service;
gchar *bus_name; gchar* bus_name;
gchar *object_path; gchar* object_path;
guint watch_id; guint watch_id;
} GfWatch; } GfWatch;
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection> &, Glib::ustring); void busAcquired(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
static gboolean handleRegisterHost(Watcher *, GDBusMethodInvocation *, const gchar *); static gboolean handleRegisterHost(Watcher*, GDBusMethodInvocation*, const gchar*);
static gboolean handleRegisterItem(Watcher *, GDBusMethodInvocation *, const gchar *); static gboolean handleRegisterItem(Watcher*, GDBusMethodInvocation*, const gchar*);
static GfWatch *gfWatchFind(GSList *list, const gchar *bus_name, const gchar *object_path); static GfWatch* gfWatchFind(GSList* list, const gchar* bus_name, const gchar* object_path);
static GfWatch *gfWatchNew(GfWatchType, const gchar *, const gchar *, const gchar *, Watcher *); static GfWatch* gfWatchNew(GfWatchType, const gchar*, const gchar*, const gchar*, Watcher*);
static void nameVanished(GDBusConnection *connection, const char *name, gpointer data); static void nameVanished(GDBusConnection* connection, const char* name, gpointer data);
static void gfWatchFree(gpointer data); static void gfWatchFree(gpointer data);
void updateRegisteredItems(SnWatcher *obj); void updateRegisteredItems(SnWatcher* obj);
uint32_t bus_name_id_; uint32_t bus_name_id_;
GSList *hosts_ = nullptr; GSList* hosts_ = nullptr;
GSList *items_ = nullptr; GSList* items_ = nullptr;
SnWatcher *watcher_ = nullptr; SnWatcher* watcher_ = nullptr;
}; };
} // namespace waybar::modules::SNI } // namespace waybar::modules::SNI

View File

@ -27,21 +27,21 @@ class Ipc {
std::string payload; std::string payload;
}; };
sigc::signal<void, const struct ipc_response &> signal_event; sigc::signal<void, const struct ipc_response&> signal_event;
sigc::signal<void, const struct ipc_response &> signal_cmd; sigc::signal<void, 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_;

View File

@ -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();

View File

@ -12,7 +12,7 @@ namespace waybar::modules {
class UPower final : public AIconLabel { class UPower final : public AIconLabel {
public: public:
UPower(const std::string &, const Json::Value &); UPower(const std::string&, const Json::Value&);
virtual ~UPower(); virtual ~UPower();
auto update() -> void override; auto update() -> void override;
@ -30,17 +30,17 @@ class UPower final : public AIconLabel {
// UPower device info // UPower device info
struct upDevice_output { struct upDevice_output {
UpDevice *upDevice{NULL}; UpDevice* upDevice{NULL};
double percentage{0.0}; double percentage{0.0};
double temperature{0.0}; double temperature{0.0};
guint64 time_full{0u}; guint64 time_full{0u};
guint64 time_empty{0u}; guint64 time_empty{0u};
gchar *icon_name{(char *)'\0'}; gchar* icon_name{(char*)'\0'};
bool upDeviceValid{false}; bool upDeviceValid{false};
UpDeviceState state; UpDeviceState state;
UpDeviceKind kind; UpDeviceKind kind;
char *nativePath{(char *)'\0'}; char* nativePath{(char*)'\0'};
char *model{(char *)'\0'}; char* model{(char*)'\0'};
}; };
// Technical variables // Technical variables
@ -53,13 +53,13 @@ class UPower final : public AIconLabel {
bool sleeping_; bool sleeping_;
// Technical functions // Technical functions
void addDevice(UpDevice *); void addDevice(UpDevice*);
void removeDevice(const gchar *); void removeDevice(const gchar*);
void removeDevices(); void removeDevices();
void resetDevices(); void resetDevices();
void setDisplayDevice(); void setDisplayDevice();
const Glib::ustring getText(const upDevice_output &upDevice_, const std::string &format); const Glib::ustring getText(const upDevice_output& upDevice_, const std::string& format);
bool queryTooltipCb(int, int, bool, const Glib::RefPtr<Gtk::Tooltip> &); bool queryTooltipCb(int, int, bool, const Glib::RefPtr<Gtk::Tooltip>&);
// DBUS variables // DBUS variables
guint watcherID_; guint watcherID_;
@ -67,28 +67,28 @@ class UPower final : public AIconLabel {
guint subscrID_{0u}; guint subscrID_{0u};
// UPower variables // UPower variables
UpClient *upClient_; UpClient* upClient_;
upDevice_output upDevice_; // Device to display upDevice_output upDevice_; // Device to display
typedef std::unordered_map<std::string, upDevice_output> Devices; typedef std::unordered_map<std::string, upDevice_output> Devices;
Devices devices_; Devices devices_;
bool upRunning_{true}; bool upRunning_{true};
// DBus callbacks // DBus callbacks
void getConn_cb(Glib::RefPtr<Gio::AsyncResult> &result); void getConn_cb(Glib::RefPtr<Gio::AsyncResult>& result);
void onAppear(const Glib::RefPtr<Gio::DBus::Connection> &, const Glib::ustring &, void onAppear(const Glib::RefPtr<Gio::DBus::Connection>&, const Glib::ustring&,
const Glib::ustring &); const Glib::ustring&);
void onVanished(const Glib::RefPtr<Gio::DBus::Connection> &, const Glib::ustring &); void onVanished(const Glib::RefPtr<Gio::DBus::Connection>&, const Glib::ustring&);
void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection> &connection, void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection>& connection,
const Glib::ustring &sender_name, const Glib::ustring &object_path, const Glib::ustring& sender_name, const Glib::ustring& object_path,
const Glib::ustring &interface_name, const Glib::ustring &signal_name, const Glib::ustring& interface_name, const Glib::ustring& signal_name,
const Glib::VariantContainerBase &parameters); const Glib::VariantContainerBase& parameters);
// UPower callbacks // UPower callbacks
static void deviceAdded_cb(UpClient *client, UpDevice *device, gpointer data); static void deviceAdded_cb(UpClient* client, UpDevice* device, gpointer data);
static void deviceRemoved_cb(UpClient *client, const gchar *objectPath, gpointer data); static void deviceRemoved_cb(UpClient* client, const gchar* objectPath, gpointer data);
static void deviceNotify_cb(UpDevice *device, GParamSpec *pspec, gpointer user_data); static void deviceNotify_cb(UpDevice* device, GParamSpec* pspec, gpointer user_data);
// UPower secondary functions // UPower secondary functions
void getUpDeviceInfo(upDevice_output &upDevice_); void getUpDeviceInfo(upDevice_output& upDevice_);
}; };
} // namespace waybar::modules } // namespace waybar::modules

View File

@ -33,8 +33,8 @@ class Taskbar;
class Task { class Task {
public: public:
Task(const waybar::Bar &, const Json::Value &, Taskbar *, Task(const waybar::Bar&, const Json::Value&, Taskbar*, struct zwlr_foreign_toplevel_handle_v1*,
struct zwlr_foreign_toplevel_handle_v1 *, struct wl_seat *); struct wl_seat*);
~Task(); ~Task();
public: public:
@ -53,11 +53,11 @@ class Task {
static uint32_t global_id; static uint32_t global_id;
private: private:
const waybar::Bar &bar_; const waybar::Bar& bar_;
const Json::Value &config_; const Json::Value& config_;
Taskbar *tbar_; Taskbar* tbar_;
struct zwlr_foreign_toplevel_handle_v1 *handle_; struct zwlr_foreign_toplevel_handle_v1* handle_;
struct wl_seat *seat_; struct wl_seat* seat_;
uint32_t id_; uint32_t id_;
@ -89,7 +89,7 @@ class Task {
std::string repr() const; std::string repr() const;
std::string state_string(bool = false) const; std::string state_string(bool = false) const;
void set_minimize_hint(); void set_minimize_hint();
void on_button_size_allocated(Gtk::Allocation &alloc); void on_button_size_allocated(Gtk::Allocation& alloc);
void hide_if_ignored(); void hide_if_ignored();
public: public:
@ -105,26 +105,26 @@ class Task {
public: public:
/* Callbacks for the wlr protocol */ /* Callbacks for the wlr protocol */
void handle_title(const char *); void handle_title(const char*);
void handle_app_id(const char *); void handle_app_id(const char*);
void handle_output_enter(struct wl_output *); void handle_output_enter(struct wl_output*);
void handle_output_leave(struct wl_output *); void handle_output_leave(struct wl_output*);
void handle_state(struct wl_array *); void handle_state(struct wl_array*);
void handle_done(); void handle_done();
void handle_closed(); void handle_closed();
/* Callbacks for Gtk events */ /* Callbacks for Gtk events */
bool handle_clicked(GdkEventButton *); bool handle_clicked(GdkEventButton*);
bool handle_button_release(GdkEventButton *); bool handle_button_release(GdkEventButton*);
bool handle_motion_notify(GdkEventMotion *); bool handle_motion_notify(GdkEventMotion*);
void handle_drag_data_get(const Glib::RefPtr<Gdk::DragContext> &context, void handle_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context,
Gtk::SelectionData &selection_data, guint info, guint time); Gtk::SelectionData& selection_data, guint info, guint time);
void handle_drag_data_received(const Glib::RefPtr<Gdk::DragContext> &context, int x, int y, void handle_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y,
Gtk::SelectionData selection_data, guint info, guint time); Gtk::SelectionData selection_data, guint info, guint time);
public: public:
bool operator==(const Task &) const; bool operator==(const Task&) const;
bool operator!=(const Task &) const; bool operator!=(const Task&) const;
public: public:
void update(); void update();
@ -142,12 +142,12 @@ using TaskPtr = std::unique_ptr<Task>;
class Taskbar : public waybar::AModule { class Taskbar : public waybar::AModule {
public: public:
Taskbar(const std::string &, const waybar::Bar &, const Json::Value &); Taskbar(const std::string&, const waybar::Bar&, const Json::Value&);
~Taskbar(); ~Taskbar();
void update(); void update();
private: private:
const waybar::Bar &bar_; const waybar::Bar& bar_;
Gtk::Box box_; Gtk::Box box_;
std::vector<TaskPtr> tasks_; std::vector<TaskPtr> tasks_;
@ -155,30 +155,30 @@ class Taskbar : public waybar::AModule {
std::unordered_set<std::string> ignore_list_; std::unordered_set<std::string> ignore_list_;
std::map<std::string, std::string> app_ids_replace_map_; std::map<std::string, std::string> app_ids_replace_map_;
struct zwlr_foreign_toplevel_manager_v1 *manager_; struct zwlr_foreign_toplevel_manager_v1* manager_;
struct wl_seat *seat_; struct wl_seat* seat_;
public: public:
/* Callbacks for global registration */ /* Callbacks for global registration */
void register_manager(struct wl_registry *, uint32_t name, uint32_t version); void register_manager(struct wl_registry*, uint32_t name, uint32_t version);
void register_seat(struct wl_registry *, uint32_t name, uint32_t version); void register_seat(struct wl_registry*, uint32_t name, uint32_t version);
/* Callbacks for the wlr protocol */ /* Callbacks for the wlr protocol */
void handle_toplevel_create(struct zwlr_foreign_toplevel_handle_v1 *); void handle_toplevel_create(struct zwlr_foreign_toplevel_handle_v1*);
void handle_finished(); void handle_finished();
public: public:
void add_button(Gtk::Button &); void add_button(Gtk::Button&);
void move_button(Gtk::Button &, int); void move_button(Gtk::Button&, int);
void remove_button(Gtk::Button &); void remove_button(Gtk::Button&);
void remove_task(uint32_t); void remove_task(uint32_t);
bool show_output(struct wl_output *) const; bool show_output(struct wl_output*) const;
bool all_outputs() const; bool all_outputs() const;
const IconLoader &icon_loader() const; const IconLoader& icon_loader() const;
const std::unordered_set<std::string> &ignore_list() const; const std::unordered_set<std::string>& ignore_list() const;
const std::map<std::string, std::string> &app_ids_replace_map() const; const std::map<std::string, std::string>& app_ids_replace_map() const;
}; };
} /* namespace waybar::modules::wlr */ } /* namespace waybar::modules::wlr */

View File

@ -36,7 +36,7 @@ class BacklightDevice {
void set_max(int max); void set_max(int max);
bool get_powered() const; bool get_powered() const;
void set_powered(bool powered); void set_powered(bool powered);
friend inline bool operator==(const BacklightDevice &lhs, const BacklightDevice &rhs) { friend inline bool operator==(const BacklightDevice& lhs, const BacklightDevice& rhs) {
return lhs.name_ == rhs.name_ && lhs.actual_ == rhs.actual_ && lhs.max_ == rhs.max_; return lhs.name_ == rhs.name_ && lhs.actual_ == rhs.actual_ && lhs.max_ == rhs.max_;
} }
@ -52,25 +52,25 @@ class BacklightBackend {
BacklightBackend(std::chrono::milliseconds interval, std::function<void()> on_updated_cb = NOOP); BacklightBackend(std::chrono::milliseconds interval, std::function<void()> on_updated_cb = NOOP);
// const inline BacklightDevice *get_best_device(std::string_view preferred_device); // const inline BacklightDevice *get_best_device(std::string_view preferred_device);
const BacklightDevice *get_previous_best_device(); const BacklightDevice* get_previous_best_device();
void set_previous_best_device(const BacklightDevice *device); void set_previous_best_device(const BacklightDevice* device);
void set_brightness(const std::string &preferred_device, ChangeType change_type, double step); void set_brightness(const std::string& preferred_device, ChangeType change_type, double step);
void set_scaled_brightness(const std::string &preferred_device, int brightness); void set_scaled_brightness(const std::string& preferred_device, int brightness);
int get_scaled_brightness(const std::string &preferred_device); int get_scaled_brightness(const std::string& preferred_device);
bool is_login_proxy_initialized() const { return static_cast<bool>(login_proxy_); } bool is_login_proxy_initialized() const { return static_cast<bool>(login_proxy_); }
static const BacklightDevice *best_device(const std::vector<BacklightDevice> &devices, static const BacklightDevice* best_device(const std::vector<BacklightDevice>& devices,
std::string_view); std::string_view);
std::vector<BacklightDevice> devices_; std::vector<BacklightDevice> devices_;
std::mutex udev_thread_mutex_; std::mutex udev_thread_mutex_;
private: private:
void set_brightness_internal(const std::string &device_name, int brightness, int max_brightness); void set_brightness_internal(const std::string& device_name, int brightness, int max_brightness);
std::function<void()> on_updated_cb_; std::function<void()> on_updated_cb_;
std::chrono::milliseconds polling_interval_; std::chrono::milliseconds polling_interval_;

View File

@ -78,7 +78,7 @@ class Column {
class iterator { class iterator {
friend Column; friend Column;
Column const &m_column; Column const& m_column;
size_t m_stringIndex = 0; size_t m_stringIndex = 0;
size_t m_pos = 0; size_t m_pos = 0;
@ -86,10 +86,10 @@ class Column {
size_t m_end = 0; size_t m_end = 0;
bool m_suffix = false; bool m_suffix = false;
iterator(Column const &column, size_t stringIndex) iterator(Column const& column, size_t stringIndex)
: m_column(column), m_stringIndex(stringIndex) {} : m_column(column), m_stringIndex(stringIndex) {}
auto line() const -> std::string const & { return m_column.m_strings[m_stringIndex]; } auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
auto isBoundary(size_t at) const -> bool { auto isBoundary(size_t at) const -> bool {
assert(at > 0); assert(at > 0);
@ -129,18 +129,18 @@ class Column {
return initial == std::string::npos ? m_column.m_indent : initial; return initial == std::string::npos ? m_column.m_indent : initial;
} }
auto addIndentAndSuffix(std::string const &plain) const -> std::string { auto addIndentAndSuffix(std::string const& plain) const -> std::string {
return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain); return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain);
} }
public: public:
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = std::string; using value_type = std::string;
using pointer = value_type *; using pointer = value_type*;
using reference = value_type &; using reference = value_type&;
using iterator_category = std::forward_iterator_tag; using iterator_category = std::forward_iterator_tag;
explicit iterator(Column const &column) : m_column(column) { explicit iterator(Column const& column) : m_column(column) {
assert(m_column.m_width > m_column.m_indent); assert(m_column.m_width > m_column.m_indent);
assert(m_column.m_initialIndent == std::string::npos || assert(m_column.m_initialIndent == std::string::npos ||
m_column.m_width > m_column.m_initialIndent); m_column.m_width > m_column.m_initialIndent);
@ -154,7 +154,7 @@ class Column {
return addIndentAndSuffix(line().substr(m_pos, m_len)); return addIndentAndSuffix(line().substr(m_pos, m_len));
} }
auto operator++() -> iterator & { auto operator++() -> iterator& {
m_pos += m_len; m_pos += m_len;
if (m_pos < line().size() && line()[m_pos] == '\n') if (m_pos < line().size() && line()[m_pos] == '\n')
m_pos += 1; m_pos += 1;
@ -174,26 +174,26 @@ class Column {
return prev; return prev;
} }
auto operator==(iterator const &other) const -> bool { auto operator==(iterator const& other) const -> bool {
return m_pos == other.m_pos && m_stringIndex == other.m_stringIndex && return m_pos == other.m_pos && m_stringIndex == other.m_stringIndex &&
&m_column == &other.m_column; &m_column == &other.m_column;
} }
auto operator!=(iterator const &other) const -> bool { return !operator==(other); } auto operator!=(iterator const& other) const -> bool { return !operator==(other); }
}; };
using const_iterator = iterator; using const_iterator = iterator;
explicit Column(std::string const &text) { m_strings.push_back(text); } explicit Column(std::string const& text) { m_strings.push_back(text); }
auto width(size_t newWidth) -> Column & { auto width(size_t newWidth) -> Column& {
assert(newWidth > 0); assert(newWidth > 0);
m_width = newWidth; m_width = newWidth;
return *this; return *this;
} }
auto indent(size_t newIndent) -> Column & { auto indent(size_t newIndent) -> Column& {
m_indent = newIndent; m_indent = newIndent;
return *this; return *this;
} }
auto initialIndent(size_t newIndent) -> Column & { auto initialIndent(size_t newIndent) -> Column& {
m_initialIndent = newIndent; m_initialIndent = newIndent;
return *this; return *this;
} }
@ -202,7 +202,7 @@ class Column {
auto begin() const -> iterator { return iterator(*this); } auto begin() const -> iterator { return iterator(*this); }
auto end() const -> iterator { return {*this, m_strings.size()}; } auto end() const -> iterator { return {*this, m_strings.size()}; }
inline friend std::ostream &operator<<(std::ostream &os, Column const &col) { inline friend std::ostream& operator<<(std::ostream& os, Column const& col) {
bool first = true; bool first = true;
for (auto line : col) { for (auto line : col) {
if (first) if (first)
@ -214,7 +214,7 @@ class Column {
return os; return os;
} }
auto operator+(Column const &other) -> Columns; auto operator+(Column const& other) -> Columns;
auto toString() const -> std::string { auto toString() const -> std::string {
std::ostringstream oss; std::ostringstream oss;
@ -236,34 +236,34 @@ class Columns {
friend Columns; friend Columns;
struct EndTag {}; struct EndTag {};
std::vector<Column> const &m_columns; std::vector<Column> const& m_columns;
std::vector<Column::iterator> m_iterators; std::vector<Column::iterator> m_iterators;
size_t m_activeIterators; size_t m_activeIterators;
iterator(Columns const &columns, EndTag) : m_columns(columns.m_columns), m_activeIterators(0) { iterator(Columns const& columns, EndTag) : m_columns(columns.m_columns), m_activeIterators(0) {
m_iterators.reserve(m_columns.size()); m_iterators.reserve(m_columns.size());
for (auto const &col : m_columns) m_iterators.push_back(col.end()); for (auto const& col : m_columns) m_iterators.push_back(col.end());
} }
public: public:
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = std::string; using value_type = std::string;
using pointer = value_type *; using pointer = value_type*;
using reference = value_type &; using reference = value_type&;
using iterator_category = std::forward_iterator_tag; using iterator_category = std::forward_iterator_tag;
explicit iterator(Columns const &columns) explicit iterator(Columns const& columns)
: m_columns(columns.m_columns), m_activeIterators(m_columns.size()) { : m_columns(columns.m_columns), m_activeIterators(m_columns.size()) {
m_iterators.reserve(m_columns.size()); m_iterators.reserve(m_columns.size());
for (auto const &col : m_columns) m_iterators.push_back(col.begin()); for (auto const& col : m_columns) m_iterators.push_back(col.begin());
} }
auto operator==(iterator const &other) const -> bool { auto operator==(iterator const& other) const -> bool {
return m_iterators == other.m_iterators; return m_iterators == other.m_iterators;
} }
auto operator!=(iterator const &other) const -> bool { auto operator!=(iterator const& other) const -> bool {
return m_iterators != other.m_iterators; return m_iterators != other.m_iterators;
} }
auto operator*() const -> std::string { auto operator*() const -> std::string {
@ -284,7 +284,7 @@ class Columns {
} }
return row; return row;
} }
auto operator++() -> iterator & { auto operator++() -> iterator& {
for (size_t i = 0; i < m_columns.size(); ++i) { for (size_t i = 0; i < m_columns.size(); ++i) {
if (m_iterators[i] != m_columns[i].end()) ++m_iterators[i]; if (m_iterators[i] != m_columns[i].end()) ++m_iterators[i];
} }
@ -301,17 +301,17 @@ class Columns {
auto begin() const -> iterator { return iterator(*this); } auto begin() const -> iterator { return iterator(*this); }
auto end() const -> iterator { return {*this, iterator::EndTag()}; } auto end() const -> iterator { return {*this, iterator::EndTag()}; }
auto operator+=(Column const &col) -> Columns & { auto operator+=(Column const& col) -> Columns& {
m_columns.push_back(col); m_columns.push_back(col);
return *this; return *this;
} }
auto operator+(Column const &col) -> Columns { auto operator+(Column const& col) -> Columns {
Columns combined = *this; Columns combined = *this;
combined += col; combined += col;
return combined; return combined;
} }
inline friend std::ostream &operator<<(std::ostream &os, Columns const &cols) { inline friend std::ostream& operator<<(std::ostream& os, Columns const& cols) {
bool first = true; bool first = true;
for (auto line : cols) { for (auto line : cols) {
if (first) if (first)
@ -330,7 +330,7 @@ class Columns {
} }
}; };
inline auto Column::operator+(Column const &other) -> Columns { inline auto Column::operator+(Column const& other) -> Columns {
Columns cols; Columns cols;
cols += *this; cols += *this;
cols += other; cols += other;
@ -381,7 +381,7 @@ class Args {
std::vector<std::string> m_args; std::vector<std::string> m_args;
public: public:
Args(int argc, char const *const *argv) : m_exeName(argv[0]), m_args(argv + 1, argv + argc) {} Args(int argc, char const* const* argv) : m_exeName(argv[0]), m_args(argv + 1, argv + argc) {}
Args(std::initializer_list<std::string> args) Args(std::initializer_list<std::string> args)
: m_exeName(*args.begin()), m_args(args.begin() + 1, args.end()) {} : m_exeName(*args.begin()), m_args(args.begin() + 1, args.end()) {}
@ -419,7 +419,7 @@ class TokenStream {
while (it != itEnd && it->empty()) ++it; while (it != itEnd && it->empty()) ++it;
if (it != itEnd) { if (it != itEnd) {
auto const &next = *it; auto const& next = *it;
if (isOptPrefix(next[0])) { if (isOptPrefix(next[0])) {
auto delimiterPos = next.find_first_of(" :="); auto delimiterPos = next.find_first_of(" :=");
if (delimiterPos != std::string::npos) { if (delimiterPos != std::string::npos) {
@ -443,7 +443,7 @@ class TokenStream {
} }
public: public:
explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {} explicit TokenStream(Args const& args) : TokenStream(args.m_args.begin(), args.m_args.end()) {}
TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { loadBuffer(); } TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { loadBuffer(); }
@ -456,12 +456,12 @@ class TokenStream {
return m_tokenBuffer.front(); return m_tokenBuffer.front();
} }
auto operator->() const -> Token const * { auto operator->() const -> Token const* {
assert(!m_tokenBuffer.empty()); assert(!m_tokenBuffer.empty());
return &m_tokenBuffer.front(); return &m_tokenBuffer.front();
} }
auto operator++() -> TokenStream & { auto operator++() -> TokenStream& {
if (m_tokenBuffer.size() >= 2) { if (m_tokenBuffer.size() >= 2) {
m_tokenBuffer.erase(m_tokenBuffer.begin()); m_tokenBuffer.erase(m_tokenBuffer.begin());
} else { } else {
@ -488,7 +488,7 @@ class ResultBase {
template <typename T> template <typename T>
class ResultValueBase : public ResultBase { class ResultValueBase : public ResultBase {
public: public:
auto value() const -> T const & { auto value() const -> T const& {
enforceOk(); enforceOk();
return m_value; return m_value;
} }
@ -496,13 +496,13 @@ class ResultValueBase : public ResultBase {
protected: protected:
ResultValueBase(Type type) : ResultBase(type) {} ResultValueBase(Type type) : ResultBase(type) {}
ResultValueBase(ResultValueBase const &other) : ResultBase(other) { ResultValueBase(ResultValueBase const& other) : ResultBase(other) {
if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value); if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value);
} }
ResultValueBase(Type, T const &value) : ResultBase(Ok) { new (&m_value) T(value); } ResultValueBase(Type, T const& value) : ResultBase(Ok) { new (&m_value) T(value); }
auto operator=(ResultValueBase const &other) -> ResultValueBase & { auto operator=(ResultValueBase const& other) -> ResultValueBase& {
if (m_type == ResultBase::Ok) m_value.~T(); if (m_type == ResultBase::Ok) m_value.~T();
ResultBase::operator=(other); ResultBase::operator=(other);
if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value); if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value);
@ -528,20 +528,20 @@ template <typename T = void>
class BasicResult : public ResultValueBase<T> { class BasicResult : public ResultValueBase<T> {
public: public:
template <typename U> template <typename U>
explicit BasicResult(BasicResult<U> const &other) explicit BasicResult(BasicResult<U> const& other)
: ResultValueBase<T>(other.type()), m_errorMessage(other.errorMessage()) { : ResultValueBase<T>(other.type()), m_errorMessage(other.errorMessage()) {
assert(type() != ResultBase::Ok); assert(type() != ResultBase::Ok);
} }
template <typename U> template <typename U>
static auto ok(U const &value) -> BasicResult { static auto ok(U const& value) -> BasicResult {
return {ResultBase::Ok, value}; return {ResultBase::Ok, value};
} }
static auto ok() -> BasicResult { return {ResultBase::Ok}; } static auto ok() -> BasicResult { return {ResultBase::Ok}; }
static auto logicError(std::string const &message) -> BasicResult { static auto logicError(std::string const& message) -> BasicResult {
return {ResultBase::LogicError, message}; return {ResultBase::LogicError, message};
} }
static auto runtimeError(std::string const &message) -> BasicResult { static auto runtimeError(std::string const& message) -> BasicResult {
return {ResultBase::RuntimeError, message}; return {ResultBase::RuntimeError, message};
} }
@ -560,7 +560,7 @@ class BasicResult : public ResultValueBase<T> {
std::string m_errorMessage; // Only populated if resultType is an error std::string m_errorMessage; // Only populated if resultType is an error
BasicResult(ResultBase::Type type, std::string const &message) BasicResult(ResultBase::Type type, std::string const& message)
: ResultValueBase<T>(type), m_errorMessage(message) { : ResultValueBase<T>(type), m_errorMessage(message) {
assert(m_type != ResultBase::Ok); assert(m_type != ResultBase::Ok);
} }
@ -573,7 +573,7 @@ enum class ParseResultType { Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
class ParseState { class ParseState {
public: public:
ParseState(ParseResultType type, TokenStream const &remainingTokens) ParseState(ParseResultType type, TokenStream const& remainingTokens)
: m_type(type), m_remainingTokens(remainingTokens) {} : m_type(type), m_remainingTokens(remainingTokens) {}
auto type() const -> ParseResultType { return m_type; } auto type() const -> ParseResultType { return m_type; }
@ -594,7 +594,7 @@ struct HelpColumns {
}; };
template <typename T> template <typename T>
inline auto convertInto(std::string const &source, T &target) -> ParserResult { inline auto convertInto(std::string const& source, T& target) -> ParserResult {
std::stringstream ss; std::stringstream ss;
ss << source; ss << source;
ss >> target; ss >> target;
@ -603,11 +603,11 @@ inline auto convertInto(std::string const &source, T &target) -> ParserResult {
else else
return ParserResult::ok(ParseResultType::Matched); return ParserResult::ok(ParseResultType::Matched);
} }
inline auto convertInto(std::string const &source, std::string &target) -> ParserResult { inline auto convertInto(std::string const& source, std::string& target) -> ParserResult {
target = source; target = source;
return ParserResult::ok(ParseResultType::Matched); return ParserResult::ok(ParseResultType::Matched);
} }
inline auto convertInto(std::string const &source, bool &target) -> ParserResult { inline auto convertInto(std::string const& source, bool& target) -> ParserResult {
std::string srcLC = source; std::string srcLC = source;
std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(),
[](char c) { return static_cast<char>(::tolower(c)); }); [](char c) { return static_cast<char>(::tolower(c)); });
@ -622,7 +622,7 @@ inline auto convertInto(std::string const &source, bool &target) -> ParserResult
} }
#ifdef CLARA_CONFIG_OPTIONAL_TYPE #ifdef CLARA_CONFIG_OPTIONAL_TYPE
template <typename T> template <typename T>
inline auto convertInto(std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T> &target) inline auto convertInto(std::string const& source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target)
-> ParserResult { -> ParserResult {
T temp; T temp;
auto result = convertInto(source, temp); auto result = convertInto(source, temp);
@ -633,10 +633,10 @@ inline auto convertInto(std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>
struct NonCopyable { struct NonCopyable {
NonCopyable() = default; NonCopyable() = default;
NonCopyable(NonCopyable const &) = delete; NonCopyable(NonCopyable const&) = delete;
NonCopyable(NonCopyable &&) = delete; NonCopyable(NonCopyable&&) = delete;
NonCopyable &operator=(NonCopyable const &) = delete; NonCopyable& operator=(NonCopyable const&) = delete;
NonCopyable &operator=(NonCopyable &&) = delete; NonCopyable& operator=(NonCopyable&&) = delete;
}; };
struct BoundRef : NonCopyable { struct BoundRef : NonCopyable {
@ -645,7 +645,7 @@ struct BoundRef : NonCopyable {
virtual auto isFlag() const -> bool { return false; } virtual auto isFlag() const -> bool { return false; }
}; };
struct BoundValueRefBase : BoundRef { struct BoundValueRefBase : BoundRef {
virtual auto setValue(std::string const &arg) -> ParserResult = 0; virtual auto setValue(std::string const& arg) -> ParserResult = 0;
}; };
struct BoundFlagRefBase : BoundRef { struct BoundFlagRefBase : BoundRef {
virtual auto setFlag(bool flag) -> ParserResult = 0; virtual auto setFlag(bool flag) -> ParserResult = 0;
@ -654,22 +654,22 @@ struct BoundFlagRefBase : BoundRef {
template <typename T> template <typename T>
struct BoundValueRef : BoundValueRefBase { struct BoundValueRef : BoundValueRefBase {
T &m_ref; T& m_ref;
explicit BoundValueRef(T &ref) : m_ref(ref) {} explicit BoundValueRef(T& ref) : m_ref(ref) {}
auto setValue(std::string const &arg) -> ParserResult override { return convertInto(arg, m_ref); } auto setValue(std::string const& arg) -> ParserResult override { return convertInto(arg, m_ref); }
}; };
template <typename T> template <typename T>
struct BoundValueRef<std::vector<T>> : BoundValueRefBase { struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
std::vector<T> &m_ref; std::vector<T>& m_ref;
explicit BoundValueRef(std::vector<T> &ref) : m_ref(ref) {} explicit BoundValueRef(std::vector<T>& ref) : m_ref(ref) {}
auto isContainer() const -> bool override { return true; } auto isContainer() const -> bool override { return true; }
auto setValue(std::string const &arg) -> ParserResult override { auto setValue(std::string const& arg) -> ParserResult override {
T temp; T temp;
auto result = convertInto(arg, temp); auto result = convertInto(arg, temp);
if (result) m_ref.push_back(temp); if (result) m_ref.push_back(temp);
@ -678,9 +678,9 @@ struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
}; };
struct BoundFlagRef : BoundFlagRefBase { struct BoundFlagRef : BoundFlagRefBase {
bool &m_ref; bool& m_ref;
explicit BoundFlagRef(bool &ref) : m_ref(ref) {} explicit BoundFlagRef(bool& ref) : m_ref(ref) {}
auto setFlag(bool flag) -> ParserResult override { auto setFlag(bool flag) -> ParserResult override {
m_ref = flag; m_ref = flag;
@ -694,7 +694,7 @@ struct LambdaInvoker {
"Lambda must return void or clara::ParserResult"); "Lambda must return void or clara::ParserResult");
template <typename L, typename ArgType> template <typename L, typename ArgType>
static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { static auto invoke(L const& lambda, ArgType const& arg) -> ParserResult {
return lambda(arg); return lambda(arg);
} }
}; };
@ -702,14 +702,14 @@ struct LambdaInvoker {
template <> template <>
struct LambdaInvoker<void> { struct LambdaInvoker<void> {
template <typename L, typename ArgType> template <typename L, typename ArgType>
static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { static auto invoke(L const& lambda, ArgType const& arg) -> ParserResult {
lambda(arg); lambda(arg);
return ParserResult::ok(ParseResultType::Matched); return ParserResult::ok(ParseResultType::Matched);
} }
}; };
template <typename ArgType, typename L> template <typename ArgType, typename L>
inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult { inline auto invokeLambda(L const& lambda, std::string const& arg) -> ParserResult {
ArgType temp{}; ArgType temp{};
auto result = convertInto(arg, temp); auto result = convertInto(arg, temp);
return !result ? result return !result ? result
@ -721,9 +721,9 @@ struct BoundLambda : BoundValueRefBase {
L m_lambda; L m_lambda;
static_assert(UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument"); static_assert(UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument");
explicit BoundLambda(L const &lambda) : m_lambda(lambda) {} explicit BoundLambda(L const& lambda) : m_lambda(lambda) {}
auto setValue(std::string const &arg) -> ParserResult override { auto setValue(std::string const& arg) -> ParserResult override {
return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(m_lambda, arg); return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(m_lambda, arg);
} }
}; };
@ -736,7 +736,7 @@ struct BoundFlagLambda : BoundFlagRefBase {
static_assert(std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, static_assert(std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value,
"flags must be boolean"); "flags must be boolean");
explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {} explicit BoundFlagLambda(L const& lambda) : m_lambda(lambda) {}
auto setFlag(bool flag) -> ParserResult override { auto setFlag(bool flag) -> ParserResult override {
return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(m_lambda, flag); return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(m_lambda, flag);
@ -751,11 +751,11 @@ class ParserBase {
public: public:
virtual ~ParserBase() = default; virtual ~ParserBase() = default;
virtual auto validate() const -> Result { return Result::ok(); } virtual auto validate() const -> Result { return Result::ok(); }
virtual auto parse(std::string const &exeName, TokenStream const &tokens) const virtual auto parse(std::string const& exeName, TokenStream const& tokens) const
-> InternalParseResult = 0; -> InternalParseResult = 0;
virtual auto cardinality() const -> size_t { return 1; } virtual auto cardinality() const -> size_t { return 1; }
auto parse(Args const &args) const -> InternalParseResult { auto parse(Args const& args) const -> InternalParseResult {
return parse(args.exeName(), TokenStream(args)); return parse(args.exeName(), TokenStream(args));
} }
}; };
@ -764,10 +764,10 @@ template <typename DerivedT>
class ComposableParserImpl : public ParserBase { class ComposableParserImpl : public ParserBase {
public: public:
template <typename T> template <typename T>
auto operator|(T const &other) const -> Parser; auto operator|(T const& other) const -> Parser;
template <typename T> template <typename T>
auto operator+(T const &other) const -> Parser; auto operator+(T const& other) const -> Parser;
}; };
// Common code and state for Args and Opts // Common code and state for Args and Opts
@ -779,30 +779,30 @@ class ParserRefImpl : public ComposableParserImpl<DerivedT> {
std::string m_hint; std::string m_hint;
std::string m_description; std::string m_description;
explicit ParserRefImpl(std::shared_ptr<BoundRef> const &ref) : m_ref(ref) {} explicit ParserRefImpl(std::shared_ptr<BoundRef> const& ref) : m_ref(ref) {}
public: public:
template <typename T> template <typename T>
ParserRefImpl(T &ref, std::string const &hint) ParserRefImpl(T& ref, std::string const& hint)
: m_ref(std::make_shared<BoundValueRef<T>>(ref)), m_hint(hint) {} : m_ref(std::make_shared<BoundValueRef<T>>(ref)), m_hint(hint) {}
template <typename LambdaT> template <typename LambdaT>
ParserRefImpl(LambdaT const &ref, std::string const &hint) ParserRefImpl(LambdaT const& ref, std::string const& hint)
: m_ref(std::make_shared<BoundLambda<LambdaT>>(ref)), m_hint(hint) {} : m_ref(std::make_shared<BoundLambda<LambdaT>>(ref)), m_hint(hint) {}
auto operator()(std::string const &description) -> DerivedT & { auto operator()(std::string const& description) -> DerivedT& {
m_description = description; m_description = description;
return static_cast<DerivedT &>(*this); return static_cast<DerivedT&>(*this);
} }
auto optional() -> DerivedT & { auto optional() -> DerivedT& {
m_optionality = Optionality::Optional; m_optionality = Optionality::Optional;
return static_cast<DerivedT &>(*this); return static_cast<DerivedT&>(*this);
}; };
auto required() -> DerivedT & { auto required() -> DerivedT& {
m_optionality = Optionality::Required; m_optionality = Optionality::Required;
return static_cast<DerivedT &>(*this); return static_cast<DerivedT&>(*this);
}; };
auto isOptional() const -> bool { return m_optionality == Optionality::Optional; } auto isOptional() const -> bool { return m_optionality == Optionality::Optional; }
@ -822,29 +822,29 @@ class ExeName : public ComposableParserImpl<ExeName> {
std::shared_ptr<BoundValueRefBase> m_ref; std::shared_ptr<BoundValueRefBase> m_ref;
template <typename LambdaT> template <typename LambdaT>
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> { static auto makeRef(LambdaT const& lambda) -> std::shared_ptr<BoundValueRefBase> {
return std::make_shared<BoundLambda<LambdaT>>(lambda); return std::make_shared<BoundLambda<LambdaT>>(lambda);
} }
public: public:
ExeName() : m_name(std::make_shared<std::string>("<executable>")) {} ExeName() : m_name(std::make_shared<std::string>("<executable>")) {}
explicit ExeName(std::string &ref) : ExeName() { explicit ExeName(std::string& ref) : ExeName() {
m_ref = std::make_shared<BoundValueRef<std::string>>(ref); m_ref = std::make_shared<BoundValueRef<std::string>>(ref);
} }
template <typename LambdaT> template <typename LambdaT>
explicit ExeName(LambdaT const &lambda) : ExeName() { explicit ExeName(LambdaT const& lambda) : ExeName() {
m_ref = std::make_shared<BoundLambda<LambdaT>>(lambda); m_ref = std::make_shared<BoundLambda<LambdaT>>(lambda);
} }
// The exe name is not parsed out of the normal tokens, but is handled specially // The exe name is not parsed out of the normal tokens, but is handled specially
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { auto parse(std::string const&, TokenStream const& tokens) const -> InternalParseResult override {
return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens));
} }
auto name() const -> std::string { return *m_name; } auto name() const -> std::string { return *m_name; }
auto set(std::string const &newName) -> ParserResult { auto set(std::string const& newName) -> ParserResult {
auto lastSlash = newName.find_last_of("\\/"); auto lastSlash = newName.find_last_of("\\/");
auto filename = (lastSlash == std::string::npos) ? newName : newName.substr(lastSlash + 1); auto filename = (lastSlash == std::string::npos) ? newName : newName.substr(lastSlash + 1);
@ -860,17 +860,17 @@ class Arg : public ParserRefImpl<Arg> {
public: public:
using ParserRefImpl::ParserRefImpl; using ParserRefImpl::ParserRefImpl;
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { auto parse(std::string const&, TokenStream const& tokens) const -> InternalParseResult override {
auto validationResult = validate(); auto validationResult = validate();
if (!validationResult) return InternalParseResult(validationResult); if (!validationResult) return InternalParseResult(validationResult);
auto remainingTokens = tokens; auto remainingTokens = tokens;
auto const &token = *remainingTokens; auto const& token = *remainingTokens;
if (token.type != TokenType::Argument) if (token.type != TokenType::Argument)
return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens));
assert(!m_ref->isFlag()); assert(!m_ref->isFlag());
auto valueRef = static_cast<detail::BoundValueRefBase *>(m_ref.get()); auto valueRef = static_cast<detail::BoundValueRefBase*>(m_ref.get());
auto result = valueRef->setValue(remainingTokens->token); auto result = valueRef->setValue(remainingTokens->token);
if (!result) if (!result)
@ -880,7 +880,7 @@ class Arg : public ParserRefImpl<Arg> {
} }
}; };
inline auto normaliseOpt(std::string const &optName) -> std::string { inline auto normaliseOpt(std::string const& optName) -> std::string {
#ifdef CLARA_PLATFORM_WINDOWS #ifdef CLARA_PLATFORM_WINDOWS
if (optName[0] == '/') if (optName[0] == '/')
return "-" + optName.substr(1); return "-" + optName.substr(1);
@ -895,18 +895,18 @@ class Opt : public ParserRefImpl<Opt> {
public: public:
template <typename LambdaT> template <typename LambdaT>
explicit Opt(LambdaT const &ref) explicit Opt(LambdaT const& ref)
: ParserRefImpl(std::make_shared<BoundFlagLambda<LambdaT>>(ref)) {} : ParserRefImpl(std::make_shared<BoundFlagLambda<LambdaT>>(ref)) {}
explicit Opt(bool &ref) : ParserRefImpl(std::make_shared<BoundFlagRef>(ref)) {} explicit Opt(bool& ref) : ParserRefImpl(std::make_shared<BoundFlagRef>(ref)) {}
template <typename LambdaT> template <typename LambdaT>
Opt(LambdaT const &ref, std::string const &hint) : ParserRefImpl(ref, hint) {} Opt(LambdaT const& ref, std::string const& hint) : ParserRefImpl(ref, hint) {}
template <typename T> template <typename T>
Opt(T &ref, std::string const &hint) : ParserRefImpl(ref, hint) {} Opt(T& ref, std::string const& hint) : ParserRefImpl(ref, hint) {}
auto operator[](std::string const &optName) -> Opt & { auto operator[](std::string const& optName) -> Opt& {
m_optNames.push_back(optName); m_optNames.push_back(optName);
return *this; return *this;
} }
@ -914,7 +914,7 @@ class Opt : public ParserRefImpl<Opt> {
auto getHelpColumns() const -> std::vector<HelpColumns> { auto getHelpColumns() const -> std::vector<HelpColumns> {
std::ostringstream oss; std::ostringstream oss;
bool first = true; bool first = true;
for (auto const &opt : m_optNames) { for (auto const& opt : m_optNames) {
if (first) if (first)
first = false; first = false;
else else
@ -925,9 +925,9 @@ class Opt : public ParserRefImpl<Opt> {
return {{oss.str(), m_description}}; return {{oss.str(), m_description}};
} }
auto isMatch(std::string const &optToken) const -> bool { auto isMatch(std::string const& optToken) const -> bool {
auto normalisedToken = normaliseOpt(optToken); auto normalisedToken = normaliseOpt(optToken);
for (auto const &name : m_optNames) { for (auto const& name : m_optNames) {
if (normaliseOpt(name) == normalisedToken) return true; if (normaliseOpt(name) == normalisedToken) return true;
} }
return false; return false;
@ -935,26 +935,26 @@ class Opt : public ParserRefImpl<Opt> {
using ParserBase::parse; using ParserBase::parse;
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { auto parse(std::string const&, TokenStream const& tokens) const -> InternalParseResult override {
auto validationResult = validate(); auto validationResult = validate();
if (!validationResult) return InternalParseResult(validationResult); if (!validationResult) return InternalParseResult(validationResult);
auto remainingTokens = tokens; auto remainingTokens = tokens;
if (remainingTokens && remainingTokens->type == TokenType::Option) { if (remainingTokens && remainingTokens->type == TokenType::Option) {
auto const &token = *remainingTokens; auto const& token = *remainingTokens;
if (isMatch(token.token)) { if (isMatch(token.token)) {
if (m_ref->isFlag()) { if (m_ref->isFlag()) {
auto flagRef = static_cast<detail::BoundFlagRefBase *>(m_ref.get()); auto flagRef = static_cast<detail::BoundFlagRefBase*>(m_ref.get());
auto result = flagRef->setFlag(true); auto result = flagRef->setFlag(true);
if (!result) return InternalParseResult(result); if (!result) return InternalParseResult(result);
if (result.value() == ParseResultType::ShortCircuitAll) if (result.value() == ParseResultType::ShortCircuitAll)
return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
} else { } else {
auto valueRef = static_cast<detail::BoundValueRefBase *>(m_ref.get()); auto valueRef = static_cast<detail::BoundValueRefBase*>(m_ref.get());
++remainingTokens; ++remainingTokens;
if (!remainingTokens) if (!remainingTokens)
return InternalParseResult::runtimeError("Expected argument following " + token.token); return InternalParseResult::runtimeError("Expected argument following " + token.token);
auto const &argToken = *remainingTokens; auto const& argToken = *remainingTokens;
if (argToken.type != TokenType::Argument) if (argToken.type != TokenType::Argument)
return InternalParseResult::runtimeError("Expected argument following " + token.token); return InternalParseResult::runtimeError("Expected argument following " + token.token);
auto result = valueRef->setValue(argToken.token); auto result = valueRef->setValue(argToken.token);
@ -970,7 +970,7 @@ class Opt : public ParserRefImpl<Opt> {
auto validate() const -> Result override { auto validate() const -> Result override {
if (m_optNames.empty()) return Result::logicError("No options supplied to Opt"); if (m_optNames.empty()) return Result::logicError("No options supplied to Opt");
for (auto const &name : m_optNames) { for (auto const& name : m_optNames) {
if (name.empty()) return Result::logicError("Option name cannot be empty"); if (name.empty()) return Result::logicError("Option name cannot be empty");
#ifdef CLARA_PLATFORM_WINDOWS #ifdef CLARA_PLATFORM_WINDOWS
if (name[0] != '-' && name[0] != '/') if (name[0] != '-' && name[0] != '/')
@ -984,12 +984,12 @@ class Opt : public ParserRefImpl<Opt> {
}; };
struct Help : Opt { struct Help : Opt {
Help(bool &showHelpFlag) Help(bool& showHelpFlag)
: Opt([&](bool flag) { : Opt([&](bool flag) {
showHelpFlag = flag; showHelpFlag = flag;
return ParserResult::ok(ParseResultType::ShortCircuitAll); return ParserResult::ok(ParseResultType::ShortCircuitAll);
}) { }) {
static_cast<Opt &>(*this)("display usage information")["-?"]["-h"]["--help"].optional(); static_cast<Opt&>(*this)("display usage information")["-?"]["-h"]["--help"].optional();
} }
}; };
@ -998,57 +998,57 @@ struct Parser : ParserBase {
std::vector<Opt> m_options; std::vector<Opt> m_options;
std::vector<Arg> m_args; std::vector<Arg> m_args;
auto operator|=(ExeName const &exeName) -> Parser & { auto operator|=(ExeName const& exeName) -> Parser& {
m_exeName = exeName; m_exeName = exeName;
return *this; return *this;
} }
auto operator|=(Arg const &arg) -> Parser & { auto operator|=(Arg const& arg) -> Parser& {
m_args.push_back(arg); m_args.push_back(arg);
return *this; return *this;
} }
auto operator|=(Opt const &opt) -> Parser & { auto operator|=(Opt const& opt) -> Parser& {
m_options.push_back(opt); m_options.push_back(opt);
return *this; return *this;
} }
auto operator|=(Parser const &other) -> Parser & { auto operator|=(Parser const& other) -> Parser& {
m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
return *this; return *this;
} }
template <typename T> template <typename T>
auto operator|(T const &other) const -> Parser { auto operator|(T const& other) const -> Parser {
return Parser(*this) |= other; return Parser(*this) |= other;
} }
// Forward deprecated interface with '+' instead of '|' // Forward deprecated interface with '+' instead of '|'
template <typename T> template <typename T>
auto operator+=(T const &other) -> Parser & { auto operator+=(T const& other) -> Parser& {
return operator|=(other); return operator|=(other);
} }
template <typename T> template <typename T>
auto operator+(T const &other) const -> Parser { auto operator+(T const& other) const -> Parser {
return operator|(other); return operator|(other);
} }
auto getHelpColumns() const -> std::vector<HelpColumns> { auto getHelpColumns() const -> std::vector<HelpColumns> {
std::vector<HelpColumns> cols; std::vector<HelpColumns> cols;
for (auto const &o : m_options) { for (auto const& o : m_options) {
auto childCols = o.getHelpColumns(); auto childCols = o.getHelpColumns();
cols.insert(cols.end(), childCols.begin(), childCols.end()); cols.insert(cols.end(), childCols.begin(), childCols.end());
} }
return cols; return cols;
} }
void writeToStream(std::ostream &os) const { void writeToStream(std::ostream& os) const {
if (!m_exeName.name().empty()) { if (!m_exeName.name().empty()) {
os << "usage:\n" os << "usage:\n"
<< " " << m_exeName.name() << " "; << " " << m_exeName.name() << " ";
bool required = true, first = true; bool required = true, first = true;
for (auto const &arg : m_args) { for (auto const& arg : m_args) {
if (first) if (first)
first = false; first = false;
else else
@ -1068,28 +1068,28 @@ struct Parser : ParserBase {
auto rows = getHelpColumns(); auto rows = getHelpColumns();
size_t consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; size_t consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
size_t optWidth = 0; size_t optWidth = 0;
for (auto const &cols : rows) optWidth = (std::max)(optWidth, cols.left.size() + 2); for (auto const& cols : rows) optWidth = (std::max)(optWidth, cols.left.size() + 2);
optWidth = (std::min)(optWidth, consoleWidth / 2); optWidth = (std::min)(optWidth, consoleWidth / 2);
for (auto const &cols : rows) { for (auto const& cols : rows) {
auto row = TextFlow::Column(cols.left).width(optWidth).indent(2) + TextFlow::Spacer(4) + auto row = TextFlow::Column(cols.left).width(optWidth).indent(2) + TextFlow::Spacer(4) +
TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth); TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth);
os << row << std::endl; os << row << std::endl;
} }
} }
friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream & { friend auto operator<<(std::ostream& os, Parser const& parser) -> std::ostream& {
parser.writeToStream(os); parser.writeToStream(os);
return os; return os;
} }
auto validate() const -> Result override { auto validate() const -> Result override {
for (auto const &opt : m_options) { for (auto const& opt : m_options) {
auto result = opt.validate(); auto result = opt.validate();
if (!result) return result; if (!result) return result;
} }
for (auto const &arg : m_args) { for (auto const& arg : m_args) {
auto result = arg.validate(); auto result = arg.validate();
if (!result) return result; if (!result) return result;
} }
@ -1098,10 +1098,10 @@ struct Parser : ParserBase {
using ParserBase::parse; using ParserBase::parse;
auto parse(std::string const &exeName, TokenStream const &tokens) const auto parse(std::string const& exeName, TokenStream const& tokens) const
-> InternalParseResult override { -> InternalParseResult override {
struct ParserInfo { struct ParserInfo {
ParserBase const *parser = nullptr; ParserBase const* parser = nullptr;
size_t count = 0; size_t count = 0;
}; };
const size_t totalParsers = m_options.size() + m_args.size(); const size_t totalParsers = m_options.size() + m_args.size();
@ -1111,8 +1111,8 @@ struct Parser : ParserBase {
{ {
size_t i = 0; size_t i = 0;
for (auto const &opt : m_options) parseInfos[i++].parser = &opt; for (auto const& opt : m_options) parseInfos[i++].parser = &opt;
for (auto const &arg : m_args) parseInfos[i++].parser = &arg; for (auto const& arg : m_args) parseInfos[i++].parser = &arg;
} }
m_exeName.set(exeName); m_exeName.set(exeName);
@ -1122,7 +1122,7 @@ struct Parser : ParserBase {
bool tokenParsed = false; bool tokenParsed = false;
for (size_t i = 0; i < totalParsers; ++i) { for (size_t i = 0; i < totalParsers; ++i) {
auto &parseInfo = parseInfos[i]; auto& parseInfo = parseInfos[i];
if (parseInfo.parser->cardinality() == 0 || if (parseInfo.parser->cardinality() == 0 ||
parseInfo.count < parseInfo.parser->cardinality()) { parseInfo.count < parseInfo.parser->cardinality()) {
result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
@ -1147,8 +1147,8 @@ struct Parser : ParserBase {
template <typename DerivedT> template <typename DerivedT>
template <typename T> template <typename T>
auto ComposableParserImpl<DerivedT>::operator|(T const &other) const -> Parser { auto ComposableParserImpl<DerivedT>::operator|(T const& other) const -> Parser {
return Parser() | static_cast<DerivedT const &>(*this) | other; return Parser() | static_cast<DerivedT const&>(*this) | other;
} }
} // namespace detail } // namespace detail

View File

@ -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,8 @@ 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

View File

@ -17,18 +17,18 @@ class IconLoader {
std::vector<Glib::RefPtr<Gtk::IconTheme>> custom_icon_themes_; std::vector<Glib::RefPtr<Gtk::IconTheme>> custom_icon_themes_;
Glib::RefPtr<Gtk::IconTheme> default_icon_theme_ = Gtk::IconTheme::get_default(); Glib::RefPtr<Gtk::IconTheme> default_icon_theme_ = Gtk::IconTheme::get_default();
static std::vector<std::string> search_prefix(); static std::vector<std::string> search_prefix();
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string &app_id); static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string& app_id);
static Glib::RefPtr<Gio::DesktopAppInfo> get_desktop_app_info(const std::string &app_id); static Glib::RefPtr<Gio::DesktopAppInfo> get_desktop_app_info(const std::string& app_id);
static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string const &icon_path, int size); static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string const& icon_path, int size);
static std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme> &icon_theme, static std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
const std::string &app_id); const std::string& app_id);
static bool image_load_icon(Gtk::Image &image, const Glib::RefPtr<Gtk::IconTheme> &icon_theme, static bool image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size); Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
public: public:
void add_custom_icon_theme(const std::string &theme_name); void add_custom_icon_theme(const std::string& theme_name);
bool image_load_icon(Gtk::Image &image, Glib::RefPtr<Gio::DesktopAppInfo> app_info, bool image_load_icon(Gtk::Image& image, Glib::RefPtr<Gio::DesktopAppInfo> app_info,
int size) const; int size) const;
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_from_app_id_list( static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_from_app_id_list(
const std::string &app_id_list); const std::string& app_id_list);
}; };

View File

@ -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");

View File

@ -33,14 +33,14 @@ class PrivacyNodeInfo {
struct spa_hook object_listener; struct spa_hook object_listener;
struct spa_hook proxy_listener; struct spa_hook proxy_listener;
void *data; void* data;
std::string getName(); std::string getName();
std::string getIconName(); std::string getIconName();
// Handlers for PipeWire events // Handlers for PipeWire events
void handleProxyEventDestroy(); void handleProxyEventDestroy();
void handleNodeEventInfo(const struct pw_node_info *info); void handleNodeEventInfo(const struct pw_node_info* info);
}; };
} // namespace waybar::util::PipewireBackend } // namespace waybar::util::PipewireBackend

View File

@ -0,0 +1,21 @@
#pragma once
#include <libudev.h>
namespace waybar::util {
struct UdevDeleter {
void operator()(udev* ptr) const { udev_unref(ptr); }
};
struct UdevDeviceDeleter {
void operator()(udev_device* ptr) const { udev_device_unref(ptr); }
};
struct UdevEnumerateDeleter {
void operator()(udev_enumerate* ptr) const { udev_enumerate_unref(ptr); }
};
struct UdevMonitorDeleter {
void operator()(udev_monitor* ptr) const { udev_monitor_unref(ptr); }
};
} // namespace waybar::util

View File

@ -2,4 +2,4 @@
#include <glibmm/ustring.h> #include <glibmm/ustring.h>
// calculate column width of ustring // calculate column width of ustring
int ustring_clen(const Glib::ustring &str); int ustring_clen(const Glib::ustring& str);

View File

@ -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,7 +180,7 @@ 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>*
Where: Where:

View File

@ -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)

View File

@ -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

View File

@ -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*

View File

@ -77,12 +77,12 @@ The slider is a component with multiple CSS Nodes, of which the following are ex
min-height: 80px; min-height: 80px;
min-width: 10px; min-width: 10px;
border-radius: 5px; border-radius: 5px;
background-color: black; background: black;
} }
#pulseaudio-slider highlight { #pulseaudio-slider highlight {
min-width: 10px; min-width: 10px;
border-radius: 5px; border-radius: 5px;
background-color: green; background: green;
} }
``` ```

View File

@ -97,7 +97,11 @@ Additionally, you can control the volume by scrolling *up* or *down* while the c
*reverse-scrolling*: ++ *reverse-scrolling*: ++
typeof: bool ++ typeof: bool ++
Option to reverse the scroll direction. Option to reverse the scroll direction for touchpads.
*reverse-mouse-scrolling*: ++
typeof: bool ++
Option to reverse the scroll direction for mice.
*tooltip*: ++ *tooltip*: ++
typeof: bool ++ typeof: bool ++
@ -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": "",

View File

@ -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",

View File

@ -1,6 +1,6 @@
project( project(
'waybar', 'cpp', 'c', 'waybar', 'cpp', 'c',
version: '0.14.0', version: '0.15.0',
license: 'MIT', license: 'MIT',
meson_version: '>= 0.59.0', meson_version: '>= 0.59.0',
default_options : [ default_options : [
@ -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.4', 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,

View File

@ -6,16 +6,17 @@
}: }:
let let
libcava = rec { libcava = rec {
version = "0.10.4"; version = "0.10.7-beta";
src = pkgs.fetchFromGitHub { src = pkgs.fetchFromGitHub {
owner = "LukashonakV"; owner = "LukashonakV";
repo = "cava"; repo = "cava";
tag = version; # NOTE: Needs to match the cava.wrap
hash = "sha256-9eTDqM+O1tA/3bEfd1apm8LbEcR9CVgELTIspSVPMKM="; tag = "v${version}";
hash = "sha256-IX1B375gTwVDRjpRfwKGuzTAZOV2pgDWzUd4bW2cTDU=";
}; };
}; };
in in
(waybar.overrideAttrs (oldAttrs: { waybar.overrideAttrs (oldAttrs: {
inherit version; inherit version;
src = lib.cleanSourceWith { src = lib.cleanSourceWith {
@ -43,4 +44,4 @@ in
patchShebangs . patchShebangs .
popd popd
''; '';
})) })

View File

@ -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();

View File

@ -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) {

View File

@ -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);

View File

@ -184,16 +184,24 @@ const std::string waybar::Client::getStyle(const std::string& style,
}; };
auto waybar::Client::setupCss(const std::string& css_file) -> void { auto waybar::Client::setupCss(const std::string& css_file) -> void {
css_provider_ = Gtk::CssProvider::create(); auto screen = Gdk::Screen::get_default();
style_context_ = Gtk::StyleContext::create(); if (!screen) {
throw std::runtime_error("No default screen");
}
// Load our css file, wherever that may be hiding if (css_provider_) {
Gtk::StyleContext::remove_provider_for_screen(screen, css_provider_);
css_provider_.reset();
}
css_provider_ = Gtk::CssProvider::create();
if (!css_provider_->load_from_path(css_file)) { if (!css_provider_->load_from_path(css_file)) {
css_provider_.reset();
throw std::runtime_error("Can't open style file"); throw std::runtime_error("Can't open style file");
} }
// there's always only one screen
style_context_->add_provider_for_screen(Gdk::Screen::get_default(), css_provider_, Gtk::StyleContext::add_provider_for_screen(screen, css_provider_,
GTK_STYLE_PROVIDER_PRIORITY_USER); GTK_STYLE_PROVIDER_PRIORITY_USER);
} }
void waybar::Client::bindInterfaces() { void waybar::Client::bindInterfaces() {
@ -212,13 +220,22 @@ 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));
} }

View File

@ -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);
} }

View File

@ -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]);

View File

@ -27,7 +27,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_);

View File

@ -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(); }) {
@ -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);

View File

@ -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;
puts(status.c_str());
// 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); });

View File

@ -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"),

View 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;
}

View File

@ -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"); label_.get_style_context()->remove_class("silent");
} if (!label_.get_style_context()->has_class("updated"))
label_text_.clear(); label_.get_style_context()->add_class("updated");
for (auto& ch : input) }
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; silence_ = false;
} }
auto waybar::modules::cava::Cava::onSilence() -> void {
if (!silence_) {
label_.get_style_context()->remove_class("updated");
if (hide_on_silence_) auto waybar::modules::cava::Cava::onSilence() -> void {
label_.hide(); Glib::signal_idle().connect_once([this]() {
else if (config_["format_silent"].isString()) if (!silence_) {
label_.set_markup(format_silent_); if (label_.get_style_context()->has_class("updated"))
silence_ = true; label_.get_style_context()->remove_class("updated");
label_.get_style_context()->add_class("silent");
} if (hide_on_silence_) {
// Clear the label markup before hiding to prevent GTK from rendering a NULL Pango layout
label_.set_markup("");
label_.hide();
} else if (config_["format_silent"].isString())
label_.set_markup(format_silent_);
silence_ = true;
label_.get_style_context()->add_class("silent");
}
});
} }

View File

@ -9,96 +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_)) {
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;
strcpy(prm_.data_format, "ascii");
strcpy(prm_.raw_target, "/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()) 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());
// Make cava parameters configuration
plan_ = new ::cava::cava_plan{};
audio_raw_.height = prm_.ascii_range;
audio_data_.format = -1;
audio_data_.source = new char[1 + strlen(prm_.audio_source)];
audio_data_.source[0] = '\0';
strcpy(audio_data_.source, prm_.audio_source);
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_.cava_in = new double[audio_data_.cava_buffer_size]{0.0};
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);
}
// 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 {
@ -107,33 +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();
delete plan_;
plan_ = nullptr; freeBackend();
} }
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() {
@ -183,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
@ -190,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_;
@ -212,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_;
};

View File

@ -230,7 +230,7 @@ const unsigned cldRowsInMonth(const year_month& ym, const weekday& firstdow) {
auto cldGetWeekForLine(const year_month& ym, const weekday& firstdow, const unsigned line) auto cldGetWeekForLine(const year_month& ym, const weekday& firstdow, const unsigned line)
-> const year_month_weekday { -> const year_month_weekday {
const unsigned idx = line - 2; const unsigned idx = line - 2;
const std::chrono::weekday_indexed indexed_first_day_of_week = const auto indexed_first_day_of_week =
weekday{ym / 1} == firstdow ? firstdow[idx + 1] : firstdow[idx]; weekday{ym / 1} == firstdow ? firstdow[idx + 1] : firstdow[idx];
return ym / indexed_first_day_of_week; return ym / indexed_first_day_of_week;

View File

@ -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);

View File

@ -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();

View File

@ -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, &registry_listener_impl, this); wl_registry_add_listener(registry, &registry_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 {

View File

@ -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, &registry_listener_impl, this); wl_registry_add_listener(registry, &registry_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);
} }

View File

@ -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_;

View File

@ -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, &registry_listener_impl, data); wl_registry_add_listener(registry, &registry_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

View File

@ -44,6 +44,17 @@ 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 {
@ -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();

View File

@ -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;
@ -236,8 +238,6 @@ void Window::queryActiveWorkspace() {
} }
void Window::onEvent(const std::string& ev) { void Window::onEvent(const std::string& ev) {
queryActiveWorkspace();
dp.emit(); dp.emit();
} }

View File

@ -38,6 +38,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();
@ -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 {
@ -126,7 +126,6 @@ void WindowCount::queryActiveWorkspace() {
} }
void WindowCount::onEvent(const std::string& ev) { void WindowCount::onEvent(const std::string& ev) {
queryActiveWorkspace();
dp.emit(); dp.emit();
} }

View File

@ -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};
} }

View File

@ -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);
} }
@ -276,10 +276,10 @@ bool Workspace::isEmpty() const {
// If there are windows but they are all ignored, consider the workspace empty // If there are windows but they are all ignored, consider the workspace empty
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) { return shouldSkipWindow(window_repr); }); [this, &ignore_list](const auto& 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);
@ -287,7 +287,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
} }
@ -343,7 +343,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);
} }
} }
@ -358,7 +358,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);
@ -372,9 +372,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);
}); });

View File

@ -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),
@ -46,8 +46,8 @@ void Workspaces::init() {
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 +62,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 +81,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 +100,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 +139,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 +163,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 +181,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 +209,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 +217,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 +228,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 +255,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 +274,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 +296,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 +322,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 +360,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 +368,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 +407,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 +426,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 +447,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 +456,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 +465,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 +477,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 +485,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 +506,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 +526,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 +534,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 +553,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 +563,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 +575,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 +590,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 +600,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 +620,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;
@ -648,28 +653,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 +682,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 +701,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 +751,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 +771,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 +786,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 +829,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 +853,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 +879,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 +895,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 +926,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 +939,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 +991,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 +1002,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 +1017,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 +1026,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 +1037,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 +1068,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 +1080,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 +1096,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 +1117,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,10 +1142,10 @@ 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;
} }

View File

@ -41,7 +41,7 @@ void waybar::modules::Image::delayWorker() {
} }
void waybar::modules::Image::refresh(int sig) { void waybar::modules::Image::refresh(int sig) {
if (sig == SIGRTMIN + config_["signal"].asInt()) { if (config_["signal"].isInt() && sig == SIGRTMIN + config_["signal"].asInt()) {
thread_.wake_up(); thread_.wake_up();
} }
} }

View File

@ -2,7 +2,7 @@
namespace waybar::modules { namespace waybar::modules {
JACK::JACK(const std::string &id, const Json::Value &config) JACK::JACK(const std::string& id, const Json::Value& config)
: ALabel(config, "jack", id, "{load}%", 1) { : ALabel(config, "jack", id, "{load}%", 1) {
running_ = false; running_ = false;
client_ = NULL; client_ = NULL;
@ -113,14 +113,14 @@ void JACK::shutdown() {
} // namespace waybar::modules } // namespace waybar::modules
int bufSizeCallback(jack_nframes_t size, void *obj) { int bufSizeCallback(jack_nframes_t size, void* obj) {
return static_cast<waybar::modules::JACK *>(obj)->bufSize(size); return static_cast<waybar::modules::JACK*>(obj)->bufSize(size);
} }
int sampleRateCallback(jack_nframes_t rate, void *obj) { int sampleRateCallback(jack_nframes_t rate, void* obj) {
return static_cast<waybar::modules::JACK *>(obj)->sampleRate(rate); return static_cast<waybar::modules::JACK*>(obj)->sampleRate(rate);
} }
int xrunCallback(void *obj) { return static_cast<waybar::modules::JACK *>(obj)->xrun(); } int xrunCallback(void* obj) { return static_cast<waybar::modules::JACK*>(obj)->xrun(); }
void shutdownCallback(void *obj) { return static_cast<waybar::modules::JACK *>(obj)->shutdown(); } void shutdownCallback(void* obj) { return static_cast<waybar::modules::JACK*>(obj)->shutdown(); }

View File

@ -36,7 +36,7 @@ auto waybar::modules::Memory::update() -> void {
float total_swap_gigabytes = 0.01 * round(swaptotal / 10485.76); float total_swap_gigabytes = 0.01 * round(swaptotal / 10485.76);
int used_ram_percentage = 100 * (memtotal - memfree) / memtotal; int used_ram_percentage = 100 * (memtotal - memfree) / memtotal;
int used_swap_percentage = 0; int used_swap_percentage = 0;
if (swaptotal && swapfree) { if (swaptotal) {
used_swap_percentage = 100 * (swaptotal - swapfree) / swaptotal; used_swap_percentage = 100 * (swaptotal - swapfree) / swaptotal;
} }
float used_ram_gigabytes = 0.01 * round((memtotal - memfree) / 10485.76); float used_ram_gigabytes = 0.01 * round((memtotal - memfree) / 10485.76);

View File

@ -21,10 +21,10 @@
namespace { namespace {
using namespace waybar::util; using namespace waybar::util;
constexpr const char *DEFAULT_FORMAT = "{ifname}"; constexpr const char* DEFAULT_FORMAT = "{ifname}";
} // namespace } // namespace
constexpr const char *NETDEV_FILE = constexpr const char* NETDEV_FILE =
"/proc/net/dev"; // std::ifstream does not take std::string_view as param "/proc/net/dev"; // std::ifstream does not take std::string_view as param
std::optional<std::pair<unsigned long long, unsigned long long>> std::optional<std::pair<unsigned long long, unsigned long long>>
waybar::modules::Network::readBandwidthUsage() { waybar::modules::Network::readBandwidthUsage() {
@ -82,7 +82,7 @@ waybar::modules::Network::readBandwidthUsage() {
return {{receivedBytes, transmittedBytes}}; return {{receivedBytes, transmittedBytes}};
} }
waybar::modules::Network::Network(const std::string &id, const Json::Value &config) waybar::modules::Network::Network(const std::string& id, const Json::Value& config)
: ALabel(config, "network", id, DEFAULT_FORMAT, 60) { : ALabel(config, "network", id, DEFAULT_FORMAT, 60) {
// Start with some "text" in the module's label_. update() will then // Start with some "text" in the module's label_. update() will then
// update it. Since the text should be different, update() will be able // update it. Since the text should be different, update() will be able
@ -216,7 +216,7 @@ void waybar::modules::Network::worker() {
thread_timer_.sleep_for(interval_); thread_timer_.sleep_for(interval_);
}; };
#ifdef WANT_RFKILL #ifdef WANT_RFKILL
rfkill_.on_update.connect([this](auto &) { rfkill_.on_update.connect([this](auto&) {
/* If we are here, it's likely that the network thread already holds the mutex and will be /* If we are here, it's likely that the network thread already holds the mutex and will be
* holding it for a next few seconds. * holding it for a next few seconds.
* Let's delegate the update to the timer thread instead of blocking the main thread. * Let's delegate the update to the timer thread instead of blocking the main thread.
@ -397,7 +397,7 @@ auto waybar::modules::Network::update() -> void {
} }
// https://gist.github.com/rressi/92af77630faf055934c723ce93ae2495 // https://gist.github.com/rressi/92af77630faf055934c723ce93ae2495
static bool wildcardMatch(const std::string &pattern, const std::string &text) { static bool wildcardMatch(const std::string& pattern, const std::string& text) {
auto P = int(pattern.size()); auto P = int(pattern.size());
auto T = int(text.size()); auto T = int(text.size());
@ -435,9 +435,9 @@ static bool wildcardMatch(const std::string &pattern, const std::string &text) {
return p == P; return p == P;
} }
bool waybar::modules::Network::matchInterface(const std::string &ifname, bool waybar::modules::Network::matchInterface(const std::string& ifname,
const std::vector<std::string> &altnames, const std::vector<std::string>& altnames,
std::string &matched) const { std::string& matched) const {
if (!config_["interface"].isString()) { if (!config_["interface"].isString()) {
return false; return false;
} }
@ -448,7 +448,7 @@ bool waybar::modules::Network::matchInterface(const std::string &ifname,
return true; return true;
} }
for (const auto &altname : altnames) { for (const auto& altname : altnames) {
if (config_ifname == altname || wildcardMatch(config_ifname, altname)) { if (config_ifname == altname || wildcardMatch(config_ifname, altname)) {
matched = altname; matched = altname;
return true; return true;
@ -478,8 +478,8 @@ void waybar::modules::Network::clearIface() {
frequency_ = 0.0; frequency_ = 0.0;
} }
int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) { int waybar::modules::Network::handleEvents(struct nl_msg* msg, void* data) {
auto net = static_cast<waybar::modules::Network *>(data); auto net = static_cast<waybar::modules::Network*>(data);
std::lock_guard<std::mutex> lock(net->mutex_); std::lock_guard<std::mutex> lock(net->mutex_);
auto nh = nlmsg_hdr(msg); auto nh = nlmsg_hdr(msg);
bool is_del_event = false; bool is_del_event = false;
@ -488,8 +488,8 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
case RTM_DELLINK: case RTM_DELLINK:
is_del_event = true; is_del_event = true;
case RTM_NEWLINK: { case RTM_NEWLINK: {
struct ifinfomsg *ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh)); struct ifinfomsg* ifi = static_cast<struct ifinfomsg*>(NLMSG_DATA(nh));
struct nlattr *attrs[IFLA_MAX + 1]; struct nlattr* attrs[IFLA_MAX + 1];
std::string ifname; std::string ifname;
std::vector<std::string> altnames; std::vector<std::string> altnames;
std::optional<bool> carrier; std::optional<bool> carrier;
@ -517,7 +517,7 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
} }
if (attrs[IFLA_IFNAME] != nullptr) { if (attrs[IFLA_IFNAME] != nullptr) {
const char *ifname_ptr = nla_get_string(attrs[IFLA_IFNAME]); const char* ifname_ptr = nla_get_string(attrs[IFLA_IFNAME]);
size_t ifname_len = nla_len(attrs[IFLA_IFNAME]) - 1; // minus \0 size_t ifname_len = nla_len(attrs[IFLA_IFNAME]) - 1; // minus \0
ifname = std::string(ifname_ptr, ifname_len); ifname = std::string(ifname_ptr, ifname_len);
} }
@ -527,12 +527,12 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
} }
if (attrs[IFLA_PROP_LIST] != nullptr) { if (attrs[IFLA_PROP_LIST] != nullptr) {
struct nlattr *prop; struct nlattr* prop;
int rem; int rem;
nla_for_each_nested(prop, attrs[IFLA_PROP_LIST], rem) { nla_for_each_nested(prop, attrs[IFLA_PROP_LIST], rem) {
if (nla_type(prop) == IFLA_ALT_IFNAME) { if (nla_type(prop) == IFLA_ALT_IFNAME) {
const char *altname_ptr = nla_get_string(prop); const char* altname_ptr = nla_get_string(prop);
size_t altname_len = nla_len(prop) - 1; // minus \0 size_t altname_len = nla_len(prop) - 1; // minus \0
altnames.emplace_back(altname_ptr, altname_len); altnames.emplace_back(altname_ptr, altname_len);
} }
@ -605,9 +605,9 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
case RTM_DELADDR: case RTM_DELADDR:
is_del_event = true; is_del_event = true;
case RTM_NEWADDR: { case RTM_NEWADDR: {
struct ifaddrmsg *ifa = static_cast<struct ifaddrmsg *>(NLMSG_DATA(nh)); struct ifaddrmsg* ifa = static_cast<struct ifaddrmsg*>(NLMSG_DATA(nh));
ssize_t attrlen = IFA_PAYLOAD(nh); ssize_t attrlen = IFA_PAYLOAD(nh);
struct rtattr *ifa_rta = IFA_RTA(ifa); struct rtattr* ifa_rta = IFA_RTA(ifa);
if ((int)ifa->ifa_index != net->ifid_) { if ((int)ifa->ifa_index != net->ifid_) {
return NL_OK; return NL_OK;
@ -681,10 +681,10 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
// Based on https://gist.github.com/Yawning/c70d804d4b8ae78cc698 // Based on https://gist.github.com/Yawning/c70d804d4b8ae78cc698
// to find the interface used to reach the outside world // to find the interface used to reach the outside world
struct rtmsg *rtm = static_cast<struct rtmsg *>(NLMSG_DATA(nh)); struct rtmsg* rtm = static_cast<struct rtmsg*>(NLMSG_DATA(nh));
int family = rtm->rtm_family; int family = rtm->rtm_family;
ssize_t attrlen = RTM_PAYLOAD(nh); ssize_t attrlen = RTM_PAYLOAD(nh);
struct rtattr *attr = RTM_RTA(rtm); struct rtattr* attr = RTM_RTA(rtm);
char gateway_addr[INET6_ADDRSTRLEN]; char gateway_addr[INET6_ADDRSTRLEN];
bool has_gateway = false; bool has_gateway = false;
bool has_destination = false; bool has_destination = false;
@ -725,17 +725,17 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
break; break;
} }
for (uint32_t i = 0; i < dstlen; i += 1) { for (uint32_t i = 0; i < dstlen; i += 1) {
c |= *((unsigned char *)RTA_DATA(attr) + i); c |= *((unsigned char*)RTA_DATA(attr) + i);
} }
has_destination = (c == 0); has_destination = (c == 0);
break; break;
} }
case RTA_OIF: case RTA_OIF:
/* The output interface index. */ /* The output interface index. */
temp_idx = *static_cast<int *>(RTA_DATA(attr)); temp_idx = *static_cast<int*>(RTA_DATA(attr));
break; break;
case RTA_PRIORITY: case RTA_PRIORITY:
priority = *(uint32_t *)RTA_DATA(attr); priority = *(uint32_t*)RTA_DATA(attr);
break; break;
default: default:
break; break;
@ -826,18 +826,18 @@ void waybar::modules::Network::askForStateDump(void) {
} }
} }
int waybar::modules::Network::handleEventsDone(struct nl_msg *msg, void *data) { int waybar::modules::Network::handleEventsDone(struct nl_msg* msg, void* data) {
auto net = static_cast<waybar::modules::Network *>(data); auto net = static_cast<waybar::modules::Network*>(data);
net->dump_in_progress_ = false; net->dump_in_progress_ = false;
net->askForStateDump(); net->askForStateDump();
return NL_OK; return NL_OK;
} }
int waybar::modules::Network::handleScan(struct nl_msg *msg, void *data) { int waybar::modules::Network::handleScan(struct nl_msg* msg, void* data) {
auto net = static_cast<waybar::modules::Network *>(data); auto net = static_cast<waybar::modules::Network*>(data);
auto gnlh = static_cast<genlmsghdr *>(nlmsg_data(nlmsg_hdr(msg))); auto gnlh = static_cast<genlmsghdr*>(nlmsg_data(nlmsg_hdr(msg)));
struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct nlattr* tb[NL80211_ATTR_MAX + 1];
struct nlattr *bss[NL80211_BSS_MAX + 1]; struct nlattr* bss[NL80211_BSS_MAX + 1];
struct nla_policy bss_policy[NL80211_BSS_MAX + 1]{}; struct nla_policy bss_policy[NL80211_BSS_MAX + 1]{};
bss_policy[NL80211_BSS_TSF].type = NLA_U64; bss_policy[NL80211_BSS_TSF].type = NLA_U64;
bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32; bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32;
@ -869,9 +869,9 @@ int waybar::modules::Network::handleScan(struct nl_msg *msg, void *data) {
return NL_OK; return NL_OK;
} }
void waybar::modules::Network::parseEssid(struct nlattr **bss) { void waybar::modules::Network::parseEssid(struct nlattr** bss) {
if (bss[NL80211_BSS_INFORMATION_ELEMENTS] != nullptr) { if (bss[NL80211_BSS_INFORMATION_ELEMENTS] != nullptr) {
auto ies = static_cast<char *>(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS])); auto ies = static_cast<char*>(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
auto ies_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]); auto ies_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
const auto hdr_len = 2; const auto hdr_len = 2;
while (ies_len > hdr_len && ies[0] != 0) { while (ies_len > hdr_len && ies[0] != 0) {
@ -888,7 +888,7 @@ void waybar::modules::Network::parseEssid(struct nlattr **bss) {
} }
} }
void waybar::modules::Network::parseSignal(struct nlattr **bss) { void waybar::modules::Network::parseSignal(struct nlattr** bss) {
if (bss[NL80211_BSS_SIGNAL_MBM] != nullptr) { if (bss[NL80211_BSS_SIGNAL_MBM] != nullptr) {
// signalstrength in dBm from mBm // signalstrength in dBm from mBm
signal_strength_dbm_ = nla_get_s32(bss[NL80211_BSS_SIGNAL_MBM]) / 100; signal_strength_dbm_ = nla_get_s32(bss[NL80211_BSS_SIGNAL_MBM]) / 100;
@ -924,16 +924,16 @@ void waybar::modules::Network::parseSignal(struct nlattr **bss) {
} }
} }
void waybar::modules::Network::parseFreq(struct nlattr **bss) { void waybar::modules::Network::parseFreq(struct nlattr** bss) {
if (bss[NL80211_BSS_FREQUENCY] != nullptr) { if (bss[NL80211_BSS_FREQUENCY] != nullptr) {
// in GHz // in GHz
frequency_ = (double)nla_get_u32(bss[NL80211_BSS_FREQUENCY]) / 1000; frequency_ = (double)nla_get_u32(bss[NL80211_BSS_FREQUENCY]) / 1000;
} }
} }
void waybar::modules::Network::parseBssid(struct nlattr **bss) { void waybar::modules::Network::parseBssid(struct nlattr** bss) {
if (bss[NL80211_BSS_BSSID] != nullptr) { if (bss[NL80211_BSS_BSSID] != nullptr) {
auto bssid = static_cast<uint8_t *>(nla_data(bss[NL80211_BSS_BSSID])); auto bssid = static_cast<uint8_t*>(nla_data(bss[NL80211_BSS_BSSID]));
auto bssid_len = nla_len(bss[NL80211_BSS_BSSID]); auto bssid_len = nla_len(bss[NL80211_BSS_BSSID]);
if (bssid_len == 6) { if (bssid_len == 6) {
bssid_ = fmt::format("{:x}:{:x}:{:x}:{:x}:{:x}:{:x}", bssid[0], bssid[1], bssid[2], bssid[3], bssid_ = fmt::format("{:x}:{:x}:{:x}:{:x}:{:x}:{:x}", bssid[0], bssid[1], bssid[2], bssid[3],
@ -942,7 +942,7 @@ void waybar::modules::Network::parseBssid(struct nlattr **bss) {
} }
} }
bool waybar::modules::Network::associatedOrJoined(struct nlattr **bss) { bool waybar::modules::Network::associatedOrJoined(struct nlattr** bss) {
if (bss[NL80211_BSS_STATUS] == nullptr) { if (bss[NL80211_BSS_STATUS] == nullptr) {
return false; return false;
} }
@ -958,7 +958,7 @@ bool waybar::modules::Network::associatedOrJoined(struct nlattr **bss) {
} }
auto waybar::modules::Network::getInfo() -> void { auto waybar::modules::Network::getInfo() -> void {
struct nl_msg *nl_msg = nlmsg_alloc(); struct nl_msg* nl_msg = nlmsg_alloc();
if (nl_msg == nullptr) { if (nl_msg == nullptr) {
return; return;
} }

View File

@ -21,7 +21,7 @@
namespace waybar::modules::niri { namespace waybar::modules::niri {
int IPC::connectToSocket() { int IPC::connectToSocket() {
const char *socket_path = getenv("NIRI_SOCKET"); const char* socket_path = getenv("NIRI_SOCKET");
if (socket_path == nullptr) { if (socket_path == nullptr) {
spdlog::warn("Niri is not running, niri IPC will not be available."); spdlog::warn("Niri is not running, niri IPC will not be available.");
@ -43,7 +43,7 @@ int IPC::connectToSocket() {
int l = sizeof(struct sockaddr_un); int l = sizeof(struct sockaddr_un);
if (connect(socketfd, (struct sockaddr *)&addr, l) == -1) { if (connect(socketfd, (struct sockaddr*)&addr, l) == -1) {
close(socketfd); close(socketfd);
throw std::runtime_error("unable to connect"); throw std::runtime_error("unable to connect");
} }
@ -58,7 +58,7 @@ void IPC::startIPC() {
int socketfd; int socketfd;
try { try {
socketfd = connectToSocket(); socketfd = connectToSocket();
} catch (std::exception &e) { } catch (std::exception& e) {
spdlog::error("Niri IPC: failed to start, reason: {}", e.what()); spdlog::error("Niri IPC: failed to start, reason: {}", e.what());
return; return;
} }
@ -87,7 +87,7 @@ void IPC::startIPC() {
try { try {
parseIPC(line); parseIPC(line);
} catch (std::exception &e) { } catch (std::exception& e) {
spdlog::warn("Failed to parse IPC message: {}, reason: {}", line, e.what()); spdlog::warn("Failed to parse IPC message: {}, reason: {}", line, e.what());
} catch (...) { } catch (...) {
throw; throw;
@ -98,7 +98,7 @@ void IPC::startIPC() {
}).detach(); }).detach();
} }
void IPC::parseIPC(const std::string &line) { void IPC::parseIPC(const std::string& line) {
const auto ev = parser_.parse(line); const auto ev = parser_.parse(line);
const auto members = ev.getMemberNames(); const auto members = ev.getMemberNames();
if (members.size() != 1) throw std::runtime_error("Event must have a single member"); if (members.size() != 1) throw std::runtime_error("Event must have a single member");
@ -106,28 +106,28 @@ void IPC::parseIPC(const std::string &line) {
{ {
auto lock = lockData(); auto lock = lockData();
if (const auto &payload = ev["WorkspacesChanged"]) { if (const auto& payload = ev["WorkspacesChanged"]) {
workspaces_.clear(); workspaces_.clear();
const auto &values = payload["workspaces"]; const auto& values = payload["workspaces"];
std::copy(values.begin(), values.end(), std::back_inserter(workspaces_)); std::copy(values.begin(), values.end(), std::back_inserter(workspaces_));
std::sort(workspaces_.begin(), workspaces_.end(), [](const auto &a, const auto &b) { std::sort(workspaces_.begin(), workspaces_.end(), [](const auto& a, const auto& b) {
const auto &aOutput = a["output"].asString(); const auto& aOutput = a["output"].asString();
const auto &bOutput = b["output"].asString(); const auto& bOutput = b["output"].asString();
const auto aIdx = a["idx"].asUInt(); const auto aIdx = a["idx"].asUInt();
const auto bIdx = b["idx"].asUInt(); const auto bIdx = b["idx"].asUInt();
if (aOutput == bOutput) return aIdx < bIdx; if (aOutput == bOutput) return aIdx < bIdx;
return aOutput < bOutput; return aOutput < bOutput;
}); });
} else if (const auto &payload = ev["WorkspaceActivated"]) { } else if (const auto& payload = ev["WorkspaceActivated"]) {
const auto id = payload["id"].asUInt64(); const auto id = payload["id"].asUInt64();
const auto focused = payload["focused"].asBool(); const auto focused = payload["focused"].asBool();
auto it = std::find_if(workspaces_.begin(), workspaces_.end(), auto it = std::find_if(workspaces_.begin(), workspaces_.end(),
[id](const auto &ws) { return ws["id"].asUInt64() == id; }); [id](const auto& ws) { return ws["id"].asUInt64() == id; });
if (it != workspaces_.end()) { if (it != workspaces_.end()) {
const auto &ws = *it; const auto& ws = *it;
const auto &output = ws["output"].asString(); const auto& output = ws["output"].asString();
for (auto &ws : workspaces_) { for (auto& ws : workspaces_) {
const auto got_activated = (ws["id"].asUInt64() == id); const auto got_activated = (ws["id"].asUInt64() == id);
if (ws["output"] == output) ws["is_active"] = got_activated; if (ws["output"] == output) ws["is_active"] = got_activated;
@ -136,70 +136,70 @@ void IPC::parseIPC(const std::string &line) {
} else { } else {
spdlog::error("Activated unknown workspace"); spdlog::error("Activated unknown workspace");
} }
} else if (const auto &payload = ev["WorkspaceActiveWindowChanged"]) { } else if (const auto& payload = ev["WorkspaceActiveWindowChanged"]) {
const auto workspaceId = payload["workspace_id"].asUInt64(); const auto workspaceId = payload["workspace_id"].asUInt64();
auto it = std::find_if(workspaces_.begin(), workspaces_.end(), [workspaceId](const auto &ws) { auto it = std::find_if(workspaces_.begin(), workspaces_.end(), [workspaceId](const auto& ws) {
return ws["id"].asUInt64() == workspaceId; return ws["id"].asUInt64() == workspaceId;
}); });
if (it != workspaces_.end()) { if (it != workspaces_.end()) {
auto &ws = *it; auto& ws = *it;
ws["active_window_id"] = payload["active_window_id"]; ws["active_window_id"] = payload["active_window_id"];
} else { } else {
spdlog::error("Active window changed on unknown workspace"); spdlog::error("Active window changed on unknown workspace");
} }
} else if (const auto &payload = ev["WorkspaceUrgencyChanged"]) { } else if (const auto& payload = ev["WorkspaceUrgencyChanged"]) {
const auto id = payload["id"].asUInt64(); const auto id = payload["id"].asUInt64();
const auto urgent = payload["urgent"].asBool(); const auto urgent = payload["urgent"].asBool();
auto it = std::find_if(workspaces_.begin(), workspaces_.end(), auto it = std::find_if(workspaces_.begin(), workspaces_.end(),
[id](const auto &ws) { return ws["id"].asUInt64() == id; }); [id](const auto& ws) { return ws["id"].asUInt64() == id; });
if (it != workspaces_.end()) { if (it != workspaces_.end()) {
auto &ws = *it; auto& ws = *it;
ws["is_urgent"] = urgent; ws["is_urgent"] = urgent;
} else { } else {
spdlog::error("Urgency changed for unknown workspace"); spdlog::error("Urgency changed for unknown workspace");
} }
} else if (const auto &payload = ev["KeyboardLayoutsChanged"]) { } else if (const auto& payload = ev["KeyboardLayoutsChanged"]) {
const auto &layouts = payload["keyboard_layouts"]; const auto& layouts = payload["keyboard_layouts"];
const auto &names = layouts["names"]; const auto& names = layouts["names"];
keyboardLayoutCurrent_ = layouts["current_idx"].asUInt(); keyboardLayoutCurrent_ = layouts["current_idx"].asUInt();
keyboardLayoutNames_.clear(); keyboardLayoutNames_.clear();
for (const auto &fullName : names) keyboardLayoutNames_.push_back(fullName.asString()); for (const auto& fullName : names) keyboardLayoutNames_.push_back(fullName.asString());
} else if (const auto &payload = ev["KeyboardLayoutSwitched"]) { } else if (const auto& payload = ev["KeyboardLayoutSwitched"]) {
keyboardLayoutCurrent_ = payload["idx"].asUInt(); keyboardLayoutCurrent_ = payload["idx"].asUInt();
} else if (const auto &payload = ev["WindowsChanged"]) { } else if (const auto& payload = ev["WindowsChanged"]) {
windows_.clear(); windows_.clear();
const auto &values = payload["windows"]; const auto& values = payload["windows"];
std::copy(values.begin(), values.end(), std::back_inserter(windows_)); std::copy(values.begin(), values.end(), std::back_inserter(windows_));
} else if (const auto &payload = ev["WindowOpenedOrChanged"]) { } else if (const auto& payload = ev["WindowOpenedOrChanged"]) {
const auto &window = payload["window"]; const auto& window = payload["window"];
const auto id = window["id"].asUInt64(); const auto id = window["id"].asUInt64();
auto it = std::find_if(windows_.begin(), windows_.end(), auto it = std::find_if(windows_.begin(), windows_.end(),
[id](const auto &win) { return win["id"].asUInt64() == id; }); [id](const auto& win) { return win["id"].asUInt64() == id; });
if (it == windows_.end()) { if (it == windows_.end()) {
windows_.push_back(window); windows_.push_back(window);
if (window["is_focused"].asBool()) { if (window["is_focused"].asBool()) {
for (auto &win : windows_) { for (auto& win : windows_) {
win["is_focused"] = win["id"].asUInt64() == id; win["is_focused"] = win["id"].asUInt64() == id;
} }
} }
} else { } else {
*it = window; *it = window;
} }
} else if (const auto &payload = ev["WindowClosed"]) { } else if (const auto& payload = ev["WindowClosed"]) {
const auto id = payload["id"].asUInt64(); const auto id = payload["id"].asUInt64();
auto it = std::find_if(windows_.begin(), windows_.end(), auto it = std::find_if(windows_.begin(), windows_.end(),
[id](const auto &win) { return win["id"].asUInt64() == id; }); [id](const auto& win) { return win["id"].asUInt64() == id; });
if (it != windows_.end()) { if (it != windows_.end()) {
windows_.erase(it); windows_.erase(it);
} else { } else {
spdlog::error("Unknown window closed"); spdlog::error("Unknown window closed");
} }
} else if (const auto &payload = ev["WindowFocusChanged"]) { } else if (const auto& payload = ev["WindowFocusChanged"]) {
const auto focused = !payload["id"].isNull(); const auto focused = !payload["id"].isNull();
const auto id = payload["id"].asUInt64(); const auto id = payload["id"].asUInt64();
for (auto &win : windows_) { for (auto& win : windows_) {
win["is_focused"] = focused && win["id"].asUInt64() == id; win["is_focused"] = focused && win["id"].asUInt64() == id;
} }
} }
@ -207,14 +207,14 @@ void IPC::parseIPC(const std::string &line) {
std::unique_lock lock(callbackMutex_); std::unique_lock lock(callbackMutex_);
for (auto &[eventname, handler] : callbacks_) { for (auto& [eventname, handler] : callbacks_) {
if (eventname == members[0]) { if (eventname == members[0]) {
handler->onEvent(ev); handler->onEvent(ev);
} }
} }
} }
void IPC::registerForIPC(const std::string &ev, EventHandler *ev_handler) { void IPC::registerForIPC(const std::string& ev, EventHandler* ev_handler) {
if (ev_handler == nullptr) { if (ev_handler == nullptr) {
return; return;
} }
@ -223,7 +223,7 @@ void IPC::registerForIPC(const std::string &ev, EventHandler *ev_handler) {
callbacks_.emplace_back(ev, ev_handler); callbacks_.emplace_back(ev, ev_handler);
} }
void IPC::unregisterForIPC(EventHandler *ev_handler) { void IPC::unregisterForIPC(EventHandler* ev_handler) {
if (ev_handler == nullptr) { if (ev_handler == nullptr) {
return; return;
} }
@ -231,7 +231,7 @@ void IPC::unregisterForIPC(EventHandler *ev_handler) {
std::unique_lock lock(callbackMutex_); std::unique_lock lock(callbackMutex_);
for (auto it = callbacks_.begin(); it != callbacks_.end();) { for (auto it = callbacks_.begin(); it != callbacks_.end();) {
auto &[eventname, handler] = *it; auto& [eventname, handler] = *it;
if (handler == ev_handler) { if (handler == ev_handler) {
it = callbacks_.erase(it); it = callbacks_.erase(it);
} else { } else {
@ -240,7 +240,7 @@ void IPC::unregisterForIPC(EventHandler *ev_handler) {
} }
} }
Json::Value IPC::send(const Json::Value &request) { Json::Value IPC::send(const Json::Value& request) {
int socketfd = connectToSocket(); int socketfd = connectToSocket();
if (socketfd == -1) throw std::runtime_error("Niri is not running"); if (socketfd == -1) throw std::runtime_error("Niri is not running");

View File

@ -8,7 +8,7 @@
namespace waybar::modules::niri { namespace waybar::modules::niri {
Language::Language(const std::string &id, const Bar &bar, const Json::Value &config) Language::Language(const std::string& id, const Bar& bar, const Json::Value& config)
: ALabel(config, "language", id, "{}", 0, false), bar_(bar) { : ALabel(config, "language", id, "{}", 0, false), bar_(bar) {
label_.hide(); label_.hide();
@ -32,7 +32,7 @@ void Language::updateFromIPC() {
auto ipcLock = gIPC->lockData(); auto ipcLock = gIPC->lockData();
layouts_.clear(); layouts_.clear();
for (const auto &fullName : gIPC->keyboardLayoutNames()) layouts_.push_back(getLayout(fullName)); for (const auto& fullName : gIPC->keyboardLayoutNames()) layouts_.push_back(getLayout(fullName));
current_idx_ = gIPC->keyboardLayoutCurrent(); current_idx_ = gIPC->keyboardLayoutCurrent();
} }
@ -51,7 +51,7 @@ void Language::doUpdate() {
label_.hide(); label_.hide();
return; return;
} }
const auto &layout = layouts_[current_idx_]; const auto& layout = layouts_[current_idx_];
spdlog::debug("niri language update with full name {}", layout.full_name); spdlog::debug("niri language update with full name {}", layout.full_name);
spdlog::debug("niri language update with short name {}", layout.short_name); spdlog::debug("niri language update with short name {}", layout.short_name);
@ -97,7 +97,7 @@ void Language::update() {
ALabel::update(); ALabel::update();
} }
void Language::onEvent(const Json::Value &ev) { void Language::onEvent(const Json::Value& ev) {
if (ev["KeyboardLayoutsChanged"]) { if (ev["KeyboardLayoutsChanged"]) {
updateFromIPC(); updateFromIPC();
} else if (ev["KeyboardLayoutSwitched"]) { } else if (ev["KeyboardLayoutSwitched"]) {
@ -109,11 +109,11 @@ void Language::onEvent(const Json::Value &ev) {
dp.emit(); dp.emit();
} }
Language::Layout Language::getLayout(const std::string &fullName) { Language::Layout Language::getLayout(const std::string& fullName) {
auto *const context = rxkb_context_new(RXKB_CONTEXT_LOAD_EXOTIC_RULES); auto* const context = rxkb_context_new(RXKB_CONTEXT_LOAD_EXOTIC_RULES);
rxkb_context_parse_default_ruleset(context); rxkb_context_parse_default_ruleset(context);
rxkb_layout *layout = rxkb_layout_first(context); rxkb_layout* layout = rxkb_layout_first(context);
while (layout != nullptr) { while (layout != nullptr) {
std::string nameOfLayout = rxkb_layout_get_description(layout); std::string nameOfLayout = rxkb_layout_get_description(layout);
@ -123,10 +123,10 @@ Language::Layout Language::getLayout(const std::string &fullName) {
} }
auto name = std::string(rxkb_layout_get_name(layout)); auto name = std::string(rxkb_layout_get_name(layout));
const auto *variantPtr = rxkb_layout_get_variant(layout); const auto* variantPtr = rxkb_layout_get_variant(layout);
std::string variant = variantPtr == nullptr ? "" : std::string(variantPtr); std::string variant = variantPtr == nullptr ? "" : std::string(variantPtr);
const auto *descriptionPtr = rxkb_layout_get_brief(layout); const auto* descriptionPtr = rxkb_layout_get_brief(layout);
std::string description = descriptionPtr == nullptr ? "" : std::string(descriptionPtr); std::string description = descriptionPtr == nullptr ? "" : std::string(descriptionPtr);
Layout info = Layout{nameOfLayout, name, variant, description}; Layout info = Layout{nameOfLayout, name, variant, description};

View File

@ -9,7 +9,7 @@
namespace waybar::modules::niri { namespace waybar::modules::niri {
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, "{title}", 0, true), bar_(bar) { : AAppIconLabel(config, "window", id, "{title}", 0, true), bar_(bar) {
if (!gIPC) gIPC = std::make_unique<IPC>(); if (!gIPC) gIPC = std::make_unique<IPC>();
@ -23,16 +23,16 @@ Window::Window(const std::string &id, const Bar &bar, const Json::Value &config)
Window::~Window() { gIPC->unregisterForIPC(this); } Window::~Window() { gIPC->unregisterForIPC(this); }
void Window::onEvent(const Json::Value &ev) { dp.emit(); } void Window::onEvent(const Json::Value& ev) { dp.emit(); }
void Window::doUpdate() { void Window::doUpdate() {
auto ipcLock = gIPC->lockData(); auto ipcLock = gIPC->lockData();
const auto &windows = gIPC->windows(); const auto& windows = gIPC->windows();
const auto &workspaces = gIPC->workspaces(); const auto& workspaces = gIPC->workspaces();
const auto separateOutputs = config_["separate-outputs"].asBool(); const auto separateOutputs = config_["separate-outputs"].asBool();
const auto ws_it = std::find_if(workspaces.cbegin(), workspaces.cend(), [&](const auto &ws) { const auto ws_it = std::find_if(workspaces.cbegin(), workspaces.cend(), [&](const auto& ws) {
if (separateOutputs) { if (separateOutputs) {
return ws["is_active"].asBool() && ws["output"].asString() == bar_.output->name; return ws["is_active"].asBool() && ws["output"].asString() == bar_.output->name;
} }
@ -46,13 +46,13 @@ void Window::doUpdate() {
} else { } else {
const auto id = (*ws_it)["active_window_id"].asUInt64(); const auto id = (*ws_it)["active_window_id"].asUInt64();
it = std::find_if(windows.cbegin(), windows.cend(), it = std::find_if(windows.cbegin(), windows.cend(),
[id](const auto &win) { return win["id"].asUInt64() == id; }); [id](const auto& win) { return win["id"].asUInt64() == id; });
} }
setClass("empty", ws_it == workspaces.cend() || (*ws_it)["active_window_id"].isNull()); setClass("empty", ws_it == workspaces.cend() || (*ws_it)["active_window_id"].isNull());
if (it != windows.cend()) { if (it != windows.cend()) {
const auto &window = *it; const auto& window = *it;
const auto title = window["title"].asString(); const auto title = window["title"].asString();
const auto appId = window["app_id"].asString(); const auto appId = window["app_id"].asString();
@ -71,7 +71,7 @@ void Window::doUpdate() {
const auto id = window["id"].asUInt64(); const auto id = window["id"].asUInt64();
const auto workspaceId = window["workspace_id"].asUInt64(); const auto workspaceId = window["workspace_id"].asUInt64();
const auto isSolo = std::none_of(windows.cbegin(), windows.cend(), [&](const auto &win) { const auto isSolo = std::none_of(windows.cbegin(), windows.cend(), [&](const auto& win) {
return win["id"].asUInt64() != id && win["workspace_id"].asUInt64() == workspaceId; return win["id"].asUInt64() != id && win["workspace_id"].asUInt64() == workspaceId;
}); });
setClass("solo", isSolo); setClass("solo", isSolo);
@ -95,7 +95,7 @@ void Window::update() {
AAppIconLabel::update(); AAppIconLabel::update();
} }
void Window::setClass(const std::string &className, bool enable) { void Window::setClass(const std::string& className, bool enable) {
auto styleContext = bar_.window.get_style_context(); auto styleContext = bar_.window.get_style_context();
if (enable) { if (enable) {
if (!styleContext->has_class(className)) { if (!styleContext->has_class(className)) {

View File

@ -6,7 +6,7 @@
namespace waybar::modules::niri { namespace waybar::modules::niri {
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), bar_(bar), box_(bar.orientation, 0) { : AModule(config, "workspaces", id, false, false), bar_(bar), box_(bar.orientation, 0) {
box_.set_name("workspaces"); box_.set_name("workspaces");
if (!id.empty()) { if (!id.empty()) {
@ -27,16 +27,16 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
Workspaces::~Workspaces() { gIPC->unregisterForIPC(this); } Workspaces::~Workspaces() { gIPC->unregisterForIPC(this); }
void Workspaces::onEvent(const Json::Value &ev) { dp.emit(); } void Workspaces::onEvent(const Json::Value& ev) { dp.emit(); }
void Workspaces::doUpdate() { void Workspaces::doUpdate() {
auto ipcLock = gIPC->lockData(); auto ipcLock = gIPC->lockData();
const auto alloutputs = config_["all-outputs"].asBool(); const auto alloutputs = config_["all-outputs"].asBool();
std::vector<Json::Value> my_workspaces; std::vector<Json::Value> my_workspaces;
const auto &workspaces = gIPC->workspaces(); const auto& workspaces = gIPC->workspaces();
std::copy_if(workspaces.cbegin(), workspaces.cend(), std::back_inserter(my_workspaces), std::copy_if(workspaces.cbegin(), workspaces.cend(), std::back_inserter(my_workspaces),
[&](const auto &ws) { [&](const auto& ws) {
if (alloutputs) return true; if (alloutputs) return true;
return ws["output"].asString() == bar_.output->name; return ws["output"].asString() == bar_.output->name;
}); });
@ -44,7 +44,7 @@ void Workspaces::doUpdate() {
// Remove buttons for removed workspaces. // Remove buttons for removed workspaces.
for (auto it = buttons_.begin(); it != buttons_.end();) { for (auto it = buttons_.begin(); it != buttons_.end();) {
auto ws = std::find_if(my_workspaces.begin(), my_workspaces.end(), auto ws = std::find_if(my_workspaces.begin(), my_workspaces.end(),
[it](const auto &ws) { return ws["id"].asUInt64() == it->first; }); [it](const auto& ws) { return ws["id"].asUInt64() == it->first; });
if (ws == my_workspaces.end()) { if (ws == my_workspaces.end()) {
it = buttons_.erase(it); it = buttons_.erase(it);
} else { } else {
@ -53,9 +53,9 @@ void Workspaces::doUpdate() {
} }
// Add buttons for new workspaces, update existing ones. // Add buttons for new workspaces, update existing ones.
for (const auto &ws : my_workspaces) { for (const auto& ws : my_workspaces) {
auto bit = buttons_.find(ws["id"].asUInt64()); auto bit = buttons_.find(ws["id"].asUInt64());
auto &button = bit == buttons_.end() ? addButton(ws) : bit->second; auto& button = bit == buttons_.end() ? addButton(ws) : bit->second;
auto style_context = button.get_style_context(); auto style_context = button.get_style_context();
if (ws["is_focused"].asBool()) if (ws["is_focused"].asBool())
@ -103,13 +103,13 @@ void Workspaces::doUpdate() {
fmt::arg("output", ws["output"].asString())); fmt::arg("output", ws["output"].asString()));
} }
if (!config_["disable-markup"].asBool()) { if (!config_["disable-markup"].asBool()) {
static_cast<Gtk::Label *>(button.get_children()[0])->set_markup(name); static_cast<Gtk::Label*>(button.get_children()[0])->set_markup(name);
} else { } else {
button.set_label(name); button.set_label(name);
} }
if (config_["current-only"].asBool()) { if (config_["current-only"].asBool()) {
const auto *property = alloutputs ? "is_focused" : "is_active"; const auto* property = alloutputs ? "is_focused" : "is_active";
if (ws[property].asBool()) if (ws[property].asBool())
button.show(); button.show();
else else
@ -121,12 +121,12 @@ void Workspaces::doUpdate() {
// Refresh the button order. // Refresh the button order.
for (auto it = my_workspaces.cbegin(); it != my_workspaces.cend(); ++it) { for (auto it = my_workspaces.cbegin(); it != my_workspaces.cend(); ++it) {
const auto &ws = *it; const auto& ws = *it;
auto pos = ws["idx"].asUInt() - 1; auto pos = ws["idx"].asUInt() - 1;
if (alloutputs) pos = it - my_workspaces.cbegin(); if (alloutputs) pos = it - my_workspaces.cbegin();
auto &button = buttons_[ws["id"].asUInt64()]; auto& button = buttons_[ws["id"].asUInt64()];
box_.reorder_child(button, pos); box_.reorder_child(button, pos);
} }
} }
@ -136,7 +136,7 @@ void Workspaces::update() {
AModule::update(); AModule::update();
} }
Gtk::Button &Workspaces::addButton(const Json::Value &ws) { Gtk::Button& Workspaces::addButton(const Json::Value& ws) {
std::string name; std::string name;
if (ws["name"]) { if (ws["name"]) {
name = ws["name"].asString(); name = ws["name"].asString();
@ -145,7 +145,7 @@ Gtk::Button &Workspaces::addButton(const Json::Value &ws) {
} }
auto pair = buttons_.emplace(ws["id"].asUInt64(), name); auto pair = buttons_.emplace(ws["id"].asUInt64(), name);
auto &&button = pair.first->second; auto&& button = pair.first->second;
box_.pack_start(button, false, false, 0); box_.pack_start(button, false, false, 0);
button.set_relief(Gtk::RELIEF_NONE); button.set_relief(Gtk::RELIEF_NONE);
if (!config_["disable-click"].asBool()) { if (!config_["disable-click"].asBool()) {
@ -154,13 +154,13 @@ Gtk::Button &Workspaces::addButton(const Json::Value &ws) {
try { try {
// {"Action":{"FocusWorkspace":{"reference":{"Id":1}}}} // {"Action":{"FocusWorkspace":{"reference":{"Id":1}}}}
Json::Value request(Json::objectValue); Json::Value request(Json::objectValue);
auto &action = (request["Action"] = Json::Value(Json::objectValue)); auto& action = (request["Action"] = Json::Value(Json::objectValue));
auto &focusWorkspace = (action["FocusWorkspace"] = Json::Value(Json::objectValue)); auto& focusWorkspace = (action["FocusWorkspace"] = Json::Value(Json::objectValue));
auto &reference = (focusWorkspace["reference"] = Json::Value(Json::objectValue)); auto& reference = (focusWorkspace["reference"] = Json::Value(Json::objectValue));
reference["Id"] = id; reference["Id"] = id;
IPC::send(request); IPC::send(request);
} catch (const std::exception &e) { } catch (const std::exception& e) {
spdlog::error("Error switching workspace: {}", e.what()); spdlog::error("Error switching workspace: {}", e.what());
} }
}); });
@ -168,8 +168,8 @@ Gtk::Button &Workspaces::addButton(const Json::Value &ws) {
return button; return button;
} }
std::string Workspaces::getIcon(const std::string &value, const Json::Value &ws) { std::string Workspaces::getIcon(const std::string& value, const Json::Value& ws) {
const auto &icons = config_["format-icons"]; const auto& icons = config_["format-icons"];
if (!icons) return value; if (!icons) return value;
if (ws["is_urgent"].asBool() && icons["urgent"]) return icons["urgent"].asString(); if (ws["is_urgent"].asBool() && icons["urgent"]) return icons["urgent"].asString();
@ -181,7 +181,7 @@ std::string Workspaces::getIcon(const std::string &value, const Json::Value &ws)
if (ws["is_active"].asBool() && icons["active"]) return icons["active"].asString(); if (ws["is_active"].asBool() && icons["active"]) return icons["active"].asString();
if (ws["name"]) { if (ws["name"]) {
const auto &name = ws["name"].asString(); const auto& name = ws["name"].asString();
if (icons[name]) return icons[name].asString(); if (icons[name]) return icons[name].asString();
} }

View File

@ -12,9 +12,9 @@
namespace waybar::modules::privacy { namespace waybar::modules::privacy {
PrivacyItem::PrivacyItem(const Json::Value &config_, enum PrivacyNodeType privacy_type_, PrivacyItem::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 std::string& pos, const uint icon_size,
const uint transition_duration) const uint transition_duration)
: Gtk::Revealer(), : Gtk::Revealer(),
privacy_type(privacy_type_), privacy_type(privacy_type_),
@ -83,7 +83,7 @@ PrivacyItem::PrivacyItem(const Json::Value &config_, enum PrivacyNodeType privac
// Sets the window to use when showing the tooltip // Sets the window to use when showing the tooltip
update_tooltip(); update_tooltip();
this->signal_query_tooltip().connect(sigc::track_obj( this->signal_query_tooltip().connect(sigc::track_obj(
[this](int x, int y, bool keyboard_tooltip, const Glib::RefPtr<Gtk::Tooltip> &tooltip) { [this](int x, int y, bool keyboard_tooltip, const Glib::RefPtr<Gtk::Tooltip>& tooltip) {
tooltip->set_custom(tooltip_window); tooltip->set_custom(tooltip_window);
return true; return true;
}, },
@ -97,23 +97,23 @@ PrivacyItem::PrivacyItem(const Json::Value &config_, enum PrivacyNodeType privac
void PrivacyItem::update_tooltip() { void PrivacyItem::update_tooltip() {
// Removes all old nodes // Removes all old nodes
for (auto *child : tooltip_window.get_children()) { for (auto* child : tooltip_window.get_children()) {
tooltip_window.remove(*child); tooltip_window.remove(*child);
// despite the remove, still needs a delete to prevent memory leak. Speculating that this might // despite the remove, still needs a delete to prevent memory leak. Speculating that this might
// work differently in GTK4. // work differently in GTK4.
delete child; delete child;
} }
for (auto *node : *nodes) { for (auto* node : *nodes) {
auto *box = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_HORIZONTAL, 4); auto* box = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_HORIZONTAL, 4);
// Set device icon // Set device icon
auto *node_icon = Gtk::make_managed<Gtk::Image>(); auto* node_icon = Gtk::make_managed<Gtk::Image>();
node_icon->set_pixel_size(tooltipIconSize); node_icon->set_pixel_size(tooltipIconSize);
node_icon->set_from_icon_name(node->getIconName(), Gtk::ICON_SIZE_INVALID); node_icon->set_from_icon_name(node->getIconName(), Gtk::ICON_SIZE_INVALID);
box->add(*node_icon); box->add(*node_icon);
// Set model // Set model
auto *nodeName = Gtk::make_managed<Gtk::Label>(node->getName()); auto* nodeName = Gtk::make_managed<Gtk::Label>(node->getName());
box->add(*nodeName); box->add(*nodeName);
tooltip_window.add(*box); tooltip_window.add(*box);

View File

@ -1,6 +1,6 @@
#include "modules/pulseaudio.hpp" #include "modules/pulseaudio.hpp"
waybar::modules::Pulseaudio::Pulseaudio(const std::string &id, const Json::Value &config) waybar::modules::Pulseaudio::Pulseaudio(const std::string& id, const Json::Value& config)
: ALabel(config, "pulseaudio", id, "{volume}%") { : ALabel(config, "pulseaudio", id, "{volume}%") {
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &Pulseaudio::handleScroll)); event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &Pulseaudio::handleScroll));
@ -9,7 +9,7 @@ waybar::modules::Pulseaudio::Pulseaudio(const std::string &id, const Json::Value
backend->setIgnoredSinks(config_["ignored-sinks"]); backend->setIgnoredSinks(config_["ignored-sinks"]);
} }
bool waybar::modules::Pulseaudio::handleScroll(GdkEventScroll *e) { bool waybar::modules::Pulseaudio::handleScroll(GdkEventScroll* e) {
// change the pulse volume only when no user provided // change the pulse volume only when no user provided
// events are configured // events are configured
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) { if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) {
@ -51,7 +51,7 @@ const std::vector<std::string> waybar::modules::Pulseaudio::getPulseIcon() const
res.push_back(backend->getDefaultSourceName()); res.push_back(backend->getDefaultSourceName());
std::string nameLC = backend->getSinkPortName() + backend->getFormFactor(); std::string nameLC = backend->getSinkPortName() + backend->getFormFactor();
std::transform(nameLC.begin(), nameLC.end(), nameLC.begin(), ::tolower); std::transform(nameLC.begin(), nameLC.end(), nameLC.begin(), ::tolower);
for (auto const &port : ports) { for (auto const& port : ports) {
if (nameLC.find(port) != std::string::npos) { if (nameLC.find(port) != std::string::npos) {
if (sink_muted) { if (sink_muted) {
res.emplace_back(port + "-muted"); res.emplace_back(port + "-muted");

View File

@ -7,48 +7,48 @@
namespace waybar::modules::river { namespace waybar::modules::river {
static void listen_focused_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, static void listen_focused_tags(void* data, struct zriver_output_status_v1* zriver_output_status_v1,
uint32_t tags) { uint32_t tags) {
// Intentionally empty // Intentionally empty
} }
static void listen_view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, static void listen_view_tags(void* data, struct zriver_output_status_v1* zriver_output_status_v1,
struct wl_array *tags) { struct wl_array* tags) {
// Intentionally empty // Intentionally empty
} }
static void listen_urgent_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, static void listen_urgent_tags(void* data, struct zriver_output_status_v1* zriver_output_status_v1,
uint32_t tags) { uint32_t tags) {
// Intentionally empty // Intentionally empty
} }
static void listen_layout_name(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, static void listen_layout_name(void* data, struct zriver_output_status_v1* zriver_output_status_v1,
const char *layout) { const char* layout) {
static_cast<Layout *>(data)->handle_name(layout); static_cast<Layout*>(data)->handle_name(layout);
} }
static void listen_layout_name_clear(void *data, static void listen_layout_name_clear(void* data,
struct zriver_output_status_v1 *zriver_output_status_v1) { struct zriver_output_status_v1* zriver_output_status_v1) {
static_cast<Layout *>(data)->handle_clear(); static_cast<Layout*>(data)->handle_clear();
} }
static void listen_focused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, static void listen_focused_output(void* data, struct zriver_seat_status_v1* zriver_seat_status_v1,
struct wl_output *output) { struct wl_output* output) {
static_cast<Layout *>(data)->handle_focused_output(output); static_cast<Layout*>(data)->handle_focused_output(output);
} }
static void listen_unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, static void listen_unfocused_output(void* data, struct zriver_seat_status_v1* zriver_seat_status_v1,
struct wl_output *output) { struct wl_output* output) {
static_cast<Layout *>(data)->handle_unfocused_output(output); static_cast<Layout*>(data)->handle_unfocused_output(output);
} }
static void listen_focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, static void listen_focused_view(void* data, struct zriver_seat_status_v1* zriver_seat_status_v1,
const char *title, uint32_t tags) { const char* title, uint32_t tags) {
// Intentionally empty // Intentionally empty
} }
static void listen_mode(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, static void listen_mode(void* data, struct zriver_seat_status_v1* zriver_seat_status_v1,
const char *mode) { const char* mode) {
// Intentionally empty // Intentionally empty
} }
@ -67,8 +67,8 @@ static const zriver_seat_status_v1_listener seat_status_listener_impl{
.mode = listen_mode, .mode = listen_mode,
}; };
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, zriver_status_manager_v1_interface.name) == 0) { if (std::strcmp(interface, zriver_status_manager_v1_interface.name) == 0) {
version = std::min<uint32_t>(version, 4); version = std::min<uint32_t>(version, 4);
@ -80,32 +80,32 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam
std::to_string(version)); std::to_string(version));
return; return;
} }
static_cast<Layout *>(data)->status_manager_ = static_cast<struct zriver_status_manager_v1 *>( static_cast<Layout*>(data)->status_manager_ = static_cast<struct zriver_status_manager_v1*>(
wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, version)); wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, version));
} }
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<Layout *>(data)->seat_ = static_cast<struct wl_seat *>( static_cast<Layout*>(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) {
// Nobody cares // Nobody cares
} }
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};
Layout::Layout(const std::string &id, const waybar::Bar &bar, const Json::Value &config) Layout::Layout(const std::string& id, const waybar::Bar& bar, const Json::Value& config)
: waybar::ALabel(config, "layout", id, "{}"), : waybar::ALabel(config, "layout", id, "{}"),
status_manager_{nullptr}, status_manager_{nullptr},
seat_{nullptr}, seat_{nullptr},
bar_(bar), bar_(bar),
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, &registry_listener_impl, this); wl_registry_add_listener(registry, &registry_listener_impl, this);
wl_display_roundtrip(display); wl_display_roundtrip(display);
@ -141,7 +141,7 @@ Layout::~Layout() {
} }
} }
void Layout::handle_name(const char *name) { void Layout::handle_name(const char* name) {
if (std::strcmp(name, "") == 0 || format_.empty()) { if (std::strcmp(name, "") == 0 || format_.empty()) {
label_.hide(); // hide empty labels or labels with empty format label_.hide(); // hide empty labels or labels with empty format
} else { } else {
@ -162,7 +162,7 @@ void Layout::handle_clear() {
ALabel::update(); ALabel::update();
} }
void Layout::handle_focused_output(struct wl_output *output) { void Layout::handle_focused_output(struct wl_output* output) {
if (output_ == output) { // if we focused the output this bar belongs to if (output_ == output) { // if we focused the output this bar belongs to
label_.get_style_context()->add_class("focused"); label_.get_style_context()->add_class("focused");
ALabel::update(); ALabel::update();
@ -170,7 +170,7 @@ void Layout::handle_focused_output(struct wl_output *output) {
focused_output_ = output; focused_output_ = output;
} }
void Layout::handle_unfocused_output(struct wl_output *output) { void Layout::handle_unfocused_output(struct wl_output* output) {
if (output_ == output) { // if we unfocused the output this bar belongs to if (output_ == output) { // if we unfocused the output this bar belongs to
label_.get_style_context()->remove_class("focused"); label_.get_style_context()->remove_class("focused");
ALabel::update(); ALabel::update();

View File

@ -7,23 +7,23 @@
namespace waybar::modules::river { namespace waybar::modules::river {
static void listen_focused_output(void *data, struct zriver_seat_status_v1 *seat_status, static void listen_focused_output(void* data, struct zriver_seat_status_v1* seat_status,
struct wl_output *output) { struct wl_output* output) {
// Intentionally empty // Intentionally empty
} }
static void listen_unfocused_output(void *data, struct zriver_seat_status_v1 *seat_status, static void listen_unfocused_output(void* data, struct zriver_seat_status_v1* seat_status,
struct wl_output *output) { struct wl_output* output) {
// Intentionally empty // Intentionally empty
} }
static void listen_focused_view(void *data, struct zriver_seat_status_v1 *seat_status, static void listen_focused_view(void* data, struct zriver_seat_status_v1* seat_status,
const char *title, uint32_t tags) { const char* title, uint32_t tags) {
// Intentionally empty // Intentionally empty
} }
static void listen_mode(void *data, struct zriver_seat_status_v1 *seat_status, const char *mode) { static void listen_mode(void* data, struct zriver_seat_status_v1* seat_status, const char* mode) {
static_cast<Mode *>(data)->handle_mode(mode); static_cast<Mode*>(data)->handle_mode(mode);
} }
static const zriver_seat_status_v1_listener seat_status_listener_impl = { static const zriver_seat_status_v1_listener seat_status_listener_impl = {
@ -33,8 +33,8 @@ static const zriver_seat_status_v1_listener seat_status_listener_impl = {
.mode = listen_mode, .mode = listen_mode,
}; };
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, zriver_status_manager_v1_interface.name) == 0) { if (std::strcmp(interface, zriver_status_manager_v1_interface.name) == 0) {
version = std::min<uint32_t>(version, 4); version = std::min<uint32_t>(version, 4);
if (version < ZRIVER_SEAT_STATUS_V1_MODE_SINCE_VERSION) { if (version < ZRIVER_SEAT_STATUS_V1_MODE_SINCE_VERSION) {
@ -42,31 +42,31 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam
"river server does not support the \"mode\" event; the module will be disabled"); "river server does not support the \"mode\" event; the module will be disabled");
return; return;
} }
static_cast<Mode *>(data)->status_manager_ = static_cast<struct zriver_status_manager_v1 *>( static_cast<Mode*>(data)->status_manager_ = static_cast<struct zriver_status_manager_v1*>(
wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, version)); wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, version));
} else if (std::strcmp(interface, wl_seat_interface.name) == 0) { } else 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<Mode *>(data)->seat_ = static_cast<struct wl_seat *>( static_cast<Mode*>(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) {
// Nobody cares // Nobody cares
} }
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};
Mode::Mode(const std::string &id, const waybar::Bar &bar, const Json::Value &config) Mode::Mode(const std::string& id, const waybar::Bar& bar, const Json::Value& config)
: waybar::ALabel(config, "mode", id, "{}"), : waybar::ALabel(config, "mode", id, "{}"),
status_manager_{nullptr}, status_manager_{nullptr},
seat_{nullptr}, seat_{nullptr},
bar_(bar), bar_(bar),
mode_{""}, mode_{""},
seat_status_{nullptr} { seat_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, &registry_listener_impl, this); wl_registry_add_listener(registry, &registry_listener_impl, this);
wl_display_roundtrip(display); wl_display_roundtrip(display);
@ -102,7 +102,7 @@ Mode::~Mode() {
} }
} }
void Mode::handle_mode(const char *mode) { void Mode::handle_mode(const char* mode) {
if (format_.empty() || hidden_modes_.contains(mode)) { if (format_.empty() || hidden_modes_.contains(mode)) {
label_.hide(); label_.hide();
} else { } else {

View File

@ -12,19 +12,19 @@
namespace waybar::modules::river { namespace waybar::modules::river {
static void listen_focused_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, static void listen_focused_tags(void* data, struct zriver_output_status_v1* zriver_output_status_v1,
uint32_t tags) { uint32_t tags) {
static_cast<Tags *>(data)->handle_focused_tags(tags); static_cast<Tags*>(data)->handle_focused_tags(tags);
} }
static void listen_view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, static void listen_view_tags(void* data, struct zriver_output_status_v1* zriver_output_status_v1,
struct wl_array *tags) { struct wl_array* tags) {
static_cast<Tags *>(data)->handle_view_tags(tags); static_cast<Tags*>(data)->handle_view_tags(tags);
} }
static void listen_urgent_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, static void listen_urgent_tags(void* data, struct zriver_output_status_v1* zriver_output_status_v1,
uint32_t tags) { uint32_t tags) {
static_cast<Tags *>(data)->handle_urgent_tags(tags); static_cast<Tags*>(data)->handle_urgent_tags(tags);
} }
static void listen_layout_name(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, static void listen_layout_name(void *data, struct zriver_output_status_v1 *zriver_output_status_v1,
@ -45,15 +45,15 @@ static const zriver_output_status_v1_listener output_status_listener_impl{
.layout_name_clear = listen_layout_name_clear, .layout_name_clear = listen_layout_name_clear,
}; };
static void listen_command_success(void *data, static void listen_command_success(void* data,
struct zriver_command_callback_v1 *zriver_command_callback_v1, struct zriver_command_callback_v1* zriver_command_callback_v1,
const char *output) { const char* output) {
// Do nothing but keep listener to avoid crashing when command was successful // Do nothing but keep listener to avoid crashing when command was successful
} }
static void listen_command_failure(void *data, static void listen_command_failure(void* data,
struct zriver_command_callback_v1 *zriver_command_callback_v1, struct zriver_command_callback_v1* zriver_command_callback_v1,
const char *output) { const char* output) {
spdlog::error("failure when selecting/toggling tags {}", output); spdlog::error("failure when selecting/toggling tags {}", output);
} }
@ -88,38 +88,38 @@ static const zriver_seat_status_v1_listener seat_status_listener_impl{
.mode = listen_mode, .mode = listen_mode,
}; };
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, zriver_status_manager_v1_interface.name) == 0) { if (std::strcmp(interface, zriver_status_manager_v1_interface.name) == 0) {
version = std::min(version, 4u); version = std::min(version, 4u);
if (version < ZRIVER_OUTPUT_STATUS_V1_URGENT_TAGS_SINCE_VERSION) { if (version < ZRIVER_OUTPUT_STATUS_V1_URGENT_TAGS_SINCE_VERSION) {
spdlog::warn("river server does not support urgent tags"); spdlog::warn("river server does not support urgent tags");
} }
static_cast<Tags *>(data)->status_manager_ = static_cast<struct zriver_status_manager_v1 *>( static_cast<Tags*>(data)->status_manager_ = static_cast<struct zriver_status_manager_v1*>(
wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, version)); wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, version));
} }
if (std::strcmp(interface, zriver_control_v1_interface.name) == 0) { if (std::strcmp(interface, zriver_control_v1_interface.name) == 0) {
version = std::min(version, 1u); version = std::min(version, 1u);
static_cast<Tags *>(data)->control_ = static_cast<struct zriver_control_v1 *>( static_cast<Tags*>(data)->control_ = static_cast<struct zriver_control_v1*>(
wl_registry_bind(registry, name, &zriver_control_v1_interface, version)); wl_registry_bind(registry, name, &zriver_control_v1_interface, version));
} }
if (std::strcmp(interface, wl_seat_interface.name) == 0) { if (std::strcmp(interface, wl_seat_interface.name) == 0) {
version = std::min(version, 1u); version = std::min(version, 1u);
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},
control_{nullptr}, control_{nullptr},
@ -129,8 +129,8 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
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, &registry_listener_impl, this); wl_registry_add_listener(registry, &registry_listener_impl, this);
wl_display_roundtrip(display); wl_display_roundtrip(display);
@ -174,7 +174,7 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
buttons_.emplace_back(std::to_string(tag + 1)); buttons_.emplace_back(std::to_string(tag + 1));
} }
auto &button = buttons_[tag]; auto& button = buttons_[tag];
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);
@ -217,7 +217,7 @@ Tags::~Tags() {
} }
void Tags::handle_show() { void Tags::handle_show() {
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_ = zriver_status_manager_v1_get_river_output_status(status_manager_, output); output_status_ = zriver_status_manager_v1_get_river_output_status(status_manager_, output);
zriver_output_status_v1_add_listener(output_status_, &output_status_listener_impl, this); zriver_output_status_v1_add_listener(output_status_, &output_status_listener_impl, this);
@ -227,24 +227,24 @@ void Tags::handle_show() {
void Tags::handle_primary_clicked(uint32_t tag) { void Tags::handle_primary_clicked(uint32_t tag) {
// Send river command to select tag on left mouse click // Send river command to select tag on left mouse click
zriver_command_callback_v1 *callback; zriver_command_callback_v1* callback;
zriver_control_v1_add_argument(control_, "set-focused-tags"); zriver_control_v1_add_argument(control_, "set-focused-tags");
zriver_control_v1_add_argument(control_, std::to_string(tag).c_str()); zriver_control_v1_add_argument(control_, std::to_string(tag).c_str());
callback = zriver_control_v1_run_command(control_, seat_); callback = zriver_control_v1_run_command(control_, seat_);
zriver_command_callback_v1_add_listener(callback, &command_callback_listener_impl, nullptr); zriver_command_callback_v1_add_listener(callback, &command_callback_listener_impl, nullptr);
} }
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) {
// Send river command to move view to tag on right mouse click // Send river command to move view to tag on right mouse click
zriver_command_callback_v1 *callback; zriver_command_callback_v1* callback;
zriver_control_v1_add_argument(control_, "set-view-tags"); zriver_control_v1_add_argument(control_, "set-view-tags");
zriver_control_v1_add_argument(control_, std::to_string(tag).c_str()); zriver_control_v1_add_argument(control_, std::to_string(tag).c_str());
callback = zriver_control_v1_run_command(control_, seat_); callback = zriver_control_v1_run_command(control_, seat_);
zriver_command_callback_v1_add_listener(callback, &command_callback_listener_impl, nullptr); zriver_command_callback_v1_add_listener(callback, &command_callback_listener_impl, nullptr);
} else if (event_button->type == GDK_BUTTON_PRESS && event_button->button == 2) { } else if (event_button->type == GDK_BUTTON_PRESS && event_button->button == 2) {
// Send river command to toggle tag on middle mouse click // Send river command to toggle tag on middle mouse click
zriver_command_callback_v1 *callback; zriver_command_callback_v1* callback;
zriver_control_v1_add_argument(control_, "toggle-focused-tags"); zriver_control_v1_add_argument(control_, "toggle-focused-tags");
zriver_control_v1_add_argument(control_, std::to_string(tag).c_str()); zriver_control_v1_add_argument(control_, std::to_string(tag).c_str());
callback = zriver_control_v1_run_command(control_, seat_); callback = zriver_control_v1_run_command(control_, seat_);
@ -273,9 +273,9 @@ void Tags::handle_focused_tags(uint32_t tags) {
} }
} }
void Tags::handle_view_tags(struct wl_array *view_tags) { void Tags::handle_view_tags(struct wl_array* view_tags) {
uint32_t tags = 0; uint32_t tags = 0;
auto view_tag = reinterpret_cast<uint32_t *>(view_tags->data); auto view_tag = reinterpret_cast<uint32_t*>(view_tags->data);
auto end = view_tag + (view_tags->size / sizeof(uint32_t)); auto end = view_tag + (view_tags->size / sizeof(uint32_t));
for (; view_tag < end; ++view_tag) { for (; view_tag < end; ++view_tag) {
tags |= *view_tag; tags |= *view_tag;

View File

@ -4,29 +4,28 @@
#include <wayland-client.h> #include <wayland-client.h>
#include <algorithm> #include <algorithm>
#include <iostream>
#include "client.hpp" #include "client.hpp"
namespace waybar::modules::river { namespace waybar::modules::river {
static void listen_focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, static void listen_focused_view(void* data, struct zriver_seat_status_v1* zriver_seat_status_v1,
const char *title, uint32_t tags) { const char* title, uint32_t tags) {
static_cast<Window *>(data)->handle_focused_view(title, tags); static_cast<Window *>(data)->handle_focused_view(title, tags);
} }
static void listen_focused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, static void listen_focused_output(void* data, struct zriver_seat_status_v1* zriver_seat_status_v1,
struct wl_output *output) { struct wl_output* output) {
static_cast<Window *>(data)->handle_focused_output(output); static_cast<Window*>(data)->handle_focused_output(output);
} }
static void listen_unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, static void listen_unfocused_output(void* data, struct zriver_seat_status_v1* zriver_seat_status_v1,
struct wl_output *output) { struct wl_output* output) {
static_cast<Window *>(data)->handle_unfocused_output(output); static_cast<Window*>(data)->handle_unfocused_output(output);
} }
static void listen_mode(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, static void listen_mode(void* data, struct zriver_seat_status_v1* zriver_seat_status_v1,
const char *mode) { const char* mode) {
// This module doesn't care // This module doesn't care
} }
@ -37,29 +36,29 @@ static const zriver_seat_status_v1_listener seat_status_listener_impl{
.mode = listen_mode, .mode = listen_mode,
}; };
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, zriver_status_manager_v1_interface.name) == 0) { if (std::strcmp(interface, zriver_status_manager_v1_interface.name) == 0) {
version = std::min<uint32_t>(version, 4); version = std::min<uint32_t>(version, 4);
static_cast<Window *>(data)->status_manager_ = static_cast<struct zriver_status_manager_v1 *>( static_cast<Window *>(data)->status_manager_ = static_cast<struct zriver_status_manager_v1*>(
wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, version)); wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, version));
} }
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<Window *>(data)->seat_ = static_cast<struct wl_seat *>( static_cast<Window*>(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};
Window::Window(const std::string &id, const waybar::Bar &bar, const Json::Value &config) Window::Window(const std::string& id, const waybar::Bar& bar, const Json::Value& config)
: waybar::ALabel(config, "window", id, "{}", 30, true), : waybar::ALabel(config, "window", id, "{}", 30, true),
status_manager_{nullptr}, status_manager_{nullptr},
seat_{nullptr}, seat_{nullptr},
@ -69,8 +68,8 @@ Window::Window(const std::string &id, const waybar::Bar &bar, const Json::Value
default_format_ = config_["default-format"].asString(); default_format_ = config_["default-format"].asString();
} }
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, &registry_listener_impl, this); wl_registry_add_listener(registry, &registry_listener_impl, this);
wl_display_roundtrip(display); wl_display_roundtrip(display);
@ -100,7 +99,7 @@ Window::~Window() {
} }
} }
void Window::handle_focused_view(const char *title, uint32_t tags) { void Window::handle_focused_view(const char* title, uint32_t tags) {
// don't change the label on unfocused outputs. // don't change the label on unfocused outputs.
// this makes the current output report its currently focused view, and unfocused outputs will // this makes the current output report its currently focused view, and unfocused outputs will
// report their last focused views. when freshly starting the bar, unfocused outputs don't have a // report their last focused views. when freshly starting the bar, unfocused outputs don't have a
@ -130,7 +129,7 @@ void Window::handle_focused_view(const char *title, uint32_t tags) {
ALabel::update(); ALabel::update();
} }
void Window::handle_focused_output(struct wl_output *output) { void Window::handle_focused_output(struct wl_output* output) {
if (output_ == output) { // if we focused the output this bar belongs to if (output_ == output) { // if we focused the output this bar belongs to
label_.get_style_context()->add_class("focused"); label_.get_style_context()->add_class("focused");
ALabel::update(); ALabel::update();
@ -138,7 +137,7 @@ void Window::handle_focused_output(struct wl_output *output) {
focused_output_ = output; focused_output_ = output;
} }
void Window::handle_unfocused_output(struct wl_output *output) { void Window::handle_unfocused_output(struct wl_output* output) {
if (output_ == output) { // if we unfocused the output this bar belongs to if (output_ == output) { // if we unfocused the output this bar belongs to
label_.get_style_context()->remove_class("focused"); label_.get_style_context()->remove_class("focused");
ALabel::update(); ALabel::update();

View File

@ -9,8 +9,8 @@
namespace waybar::modules { namespace waybar::modules {
void ondesc(void *arg, struct sioctl_desc *d, int curval) { void ondesc(void* arg, struct sioctl_desc* d, int curval) {
auto self = static_cast<Sndio *>(arg); auto self = static_cast<Sndio*>(arg);
if (d == NULL) { if (d == NULL) {
// d is NULL when the list is done // d is NULL when the list is done
return; return;
@ -18,8 +18,8 @@ void ondesc(void *arg, struct sioctl_desc *d, int curval) {
self->set_desc(d, curval); self->set_desc(d, curval);
} }
void onval(void *arg, unsigned int addr, unsigned int val) { void onval(void* arg, unsigned int addr, unsigned int val) {
auto self = static_cast<Sndio *>(arg); auto self = static_cast<Sndio*>(arg);
self->put_val(addr, val); self->put_val(addr, val);
} }
@ -40,7 +40,7 @@ auto Sndio::connect_to_sndio() -> void {
pfds_.reserve(sioctl_nfds(hdl_)); pfds_.reserve(sioctl_nfds(hdl_));
} }
Sndio::Sndio(const std::string &id, const Json::Value &config) Sndio::Sndio(const std::string& id, const Json::Value& config)
: ALabel(config, "sndio", id, "{volume}%", 1, false, true), : ALabel(config, "sndio", id, "{volume}%", 1, false, true),
hdl_(nullptr), hdl_(nullptr),
pfds_(0), pfds_(0),
@ -80,7 +80,7 @@ Sndio::Sndio(const std::string &id, const Json::Value &config)
while (thread_.isRunning()) { while (thread_.isRunning()) {
try { try {
connect_to_sndio(); connect_to_sndio();
} catch (std::runtime_error const &e) { } catch (std::runtime_error const& e) {
// avoid leaking hdl_ // avoid leaking hdl_
if (hdl_) { if (hdl_) {
sioctl_close(hdl_); sioctl_close(hdl_);
@ -122,7 +122,7 @@ auto Sndio::update() -> void {
ALabel::update(); ALabel::update();
} }
auto Sndio::set_desc(struct sioctl_desc *d, unsigned int val) -> void { auto Sndio::set_desc(struct sioctl_desc* d, unsigned int val) -> void {
std::string name{d->func}; std::string name{d->func};
std::string node_name{d->node0.name}; std::string node_name{d->node0.name};
@ -140,7 +140,7 @@ auto Sndio::put_val(unsigned int addr, unsigned int val) -> void {
} }
} }
bool Sndio::handleScroll(GdkEventScroll *e) { bool Sndio::handleScroll(GdkEventScroll* e) {
// change the volume only when no user provided // change the volume only when no user provided
// events are configured // events are configured
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) { if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) {
@ -180,7 +180,7 @@ bool Sndio::handleScroll(GdkEventScroll *e) {
return true; return true;
} }
bool Sndio::handleToggle(GdkEventButton *const &e) { bool Sndio::handleToggle(GdkEventButton* const& e) {
// toggle mute only when no user provided events are configured // toggle mute only when no user provided events are configured
if (config_["on-click"].isString()) { if (config_["on-click"].isString()) {
return AModule::handleToggle(e); return AModule::handleToggle(e);

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