Merge remote-tracking branch 'origin/master' into feat/brightness-percent-exp

# Conflicts:
#	src/modules/backlight.cpp
This commit is contained in:
Alex
2026-07-03 22:39:10 +02:00
357 changed files with 24986 additions and 8301 deletions
+29
View File
@@ -0,0 +1,29 @@
Checks: >
-*,
bugprone-*
misc-*,
modernize-*,
performance-*,
portability-*,
readability-*,
-fuchsia-trailing-return,
-readability-magic-numbers,
-modernize-use-nodiscard,
-modernize-use-trailing-return-type,
-readability-braces-around-statements,
-readability-redundant-access-specifiers,
-readability-redundant-member-init,
-readability-redundant-string-init,
-readability-identifier-length
# CheckOptions:
# - { key: readability-identifier-naming.NamespaceCase, value: lower_case }
# - { key: readability-identifier-naming.ClassCase, value: CamelCase }
# - { key: readability-identifier-naming.StructCase, value: CamelCase }
# - { key: readability-identifier-naming.FunctionCase, value: camelBack }
# - { key: readability-identifier-naming.VariableCase, value: camelBack }
# - { key: readability-identifier-naming.PrivateMemberCase, value: camelBack }
# - { key: readability-identifier-naming.PrivateMemberSuffix, value: _ }
# - { key: readability-identifier-naming.EnumCase, value: CamelCase }
# - { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE }
# - { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }
# - { key: readability-identifier-naming.StaticConstantCase, value: UPPER_CASE }
View File
+65
View File
@@ -0,0 +1,65 @@
bug:
- "(crash|bug|error|coredump|freeze|segfault|issue|problem)"
enhancement:
- "(feature|enhancement|improvement|request|suggestion)"
hyprland:
- "(hyprland)"
network:
- "(network|wifi|ethernet)"
bluetooth:
- "(bluetooth|bluez)"
sway:
- "(sway)"
cpu:
- "(cpu)"
memory:
- "(memory|ram)"
disk:
- "(disk|storage)"
battery:
- "(upower|battery)"
sni:
- "(sni|tray)"
dwl:
- "(dwl)"
custom:
- "(custom|module|extension|plugin|script)"
mpd:
- "(mpd|music)"
audio:
- "(pulseaudio|alsa|jack|audio|pirewire|wireplumber)"
temperature:
- "(temperature|thermal|hwmon)"
clock:
- "(clock|time|date)"
gamemode:
- "(gamemode|game|gaming)"
inhibitor:
- "(inhibitor|idle|lock|suspend|hibernate|logout)"
cava:
- "(cava|audio-visualizer)"
backlight:
- "(backlight|brightness)"
keyboard:
- "(keyboard|keymap|layout|shortcut)"
+18
View File
@@ -0,0 +1,18 @@
name: clang-format
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-format-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: RafikFarhad/clang-format-github-action@v6
name: clang-format
with:
sources: "src/**/*.hpp,src/**/*.cpp"
style: "file"
+39
View File
@@ -0,0 +1,39 @@
name: clang-tidy
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-tidy-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
container:
image: alexays/waybar:debian
steps:
- uses: actions/checkout@v6
- name: configure
run: |
meson -Dcpp_std=c++20 build # necessary to generate compile_commands.json
ninja -C build # necessary to find certain .h files (xdg, wayland, etc.)
- uses: actions/setup-python@v5
with:
python-version: '3.10' # to be kept in sync with cpp-linter-action
update-environment: true # the python dist installed by the action needs LD_LIBRARY_PATH to work
- uses: cpp-linter/cpp-linter-action@v2.9.1
name: clang-tidy
id: clang-tidy-check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PIP_NO_CACHE_DIR: false
with:
style: "" # empty string => don't do clang-format checks here, we do them in clang-format.yml
files-changed-only: true # only check files that have changed
lines-changed-only: true # only check lines that have changed
tidy-checks: "" # empty string => use the .clang-tidy file
version: "17" # clang-tools version
database: "build" # path to the compile_commands.json file
- name: Check if clang-tidy failed on any files
if: steps.clang-tidy-check.outputs.checks-failed > 0
run: echo "Some files failed the linting checks!" && exit 1
+34
View File
@@ -0,0 +1,34 @@
name: Build and Push Docker Image
on:
workflow_dispatch:
schedule:
# run monthly
- cron: '0 0 1 * *'
jobs:
build-and-push:
runs-on: ubuntu-latest
if: github.event_name != 'schedule' || github.repository == 'Alexays/Waybar'
strategy:
fail-fast: false # don't fail the other jobs if one of the images fails to build
matrix:
os: [ 'alpine', 'archlinux', 'debian', 'fedora', 'gentoo', 'opensuse' ]
steps:
- name: Checkout repository
- uses: actions/checkout@v6
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfiles/${{ matrix.os }}
push: true
tags: alexays/waybar:${{ matrix.os }}
+24 -18
View File
@@ -1,29 +1,35 @@
name: freebsd
on: [ push, pull_request ]
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-freebsd-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
clang:
# Run actions in a FreeBSD VM on the macos-12 runner
build:
# Run actions in a FreeBSD VM on the ubuntu runner
# https://github.com/actions/runner/issues/385 - for FreeBSD runner support
# https://github.com/actions/virtual-environments/issues/4060 - for lack of VirtualBox on MacOS 11 runners
runs-on: macos-12
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: Test in FreeBSD VM
uses: vmactions/freebsd-vm@v0
uses: cross-platform-actions/action@v0.28.0
timeout-minutes: 180
env:
CPPFLAGS: '-isystem/usr/local/include'
LDFLAGS: '-L/usr/local/lib'
with:
mem: 2048
usesh: true
prepare: |
export CPPFLAGS=-isystem/usr/local/include LDFLAGS=-L/usr/local/lib # sndio
sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
pkg install -y git # subprojects/date
pkg install -y catch evdev-proto gtk-layer-shell gtkmm30 jsoncpp \
libdbusmenu libevdev libfmt libmpdclient libudev-devd meson \
pkgconf pulseaudio scdoc sndio spdlog wayland-protocols upower \
libinotify
operating_system: freebsd
version: "14.2"
environment_variables: CPPFLAGS LDFLAGS
sync_files: runner-to-vm
run: |
meson build -Dman-pages=enabled
sudo pkg install -y git # subprojects/date
sudo pkg install -y catch evdev-proto gtk-layer-shell gtkmm30 jsoncpp \
libdbusmenu libevdev libfmt libmpdclient libudev-devd meson \
pkgconf pipewire pulseaudio scdoc sndio spdlog wayland-protocols upower \
libinotify
meson setup build -Dman-pages=enabled
ninja -C build
meson test -C build --no-rebuild --print-errorlogs --suite waybar
+19
View File
@@ -0,0 +1,19 @@
name: "Issue Labeler"
on:
issues:
types: [opened, edited]
permissions:
issues: write
contents: read
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: github/issue-labeler@v3.4
with:
configuration-path: .github/labeler.yml
enable-versioned-regex: 0
include-title: 1
repo-token: ${{ secrets.GITHUB_TOKEN }}
-14
View File
@@ -1,14 +0,0 @@
name: Linter
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: DoozyX/clang-format-lint-action@v0.13
with:
source: '.'
extensions: 'h,cpp,c'
clangFormatVersion: 12
+8 -6
View File
@@ -2,9 +2,14 @@ name: linux
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-linux-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
fail-fast: false
matrix:
distro:
- alpine
@@ -13,19 +18,16 @@ jobs:
- fedora
- opensuse
- gentoo
cpp_std: [c++17]
include:
- distro: fedora
cpp_std: c++20
cpp_std: [c++20]
runs-on: ubuntu-latest
container:
image: alexays/waybar:${{ matrix.distro }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: configure
run: meson -Dman-pages=enabled -Dcpp_std=${{matrix.cpp_std}} build
run: meson setup -Dman-pages=enabled -Dcpp_std=${{matrix.cpp_std}} build
- name: build
run: ninja -C build
- name: test
+20
View File
@@ -0,0 +1,20 @@
name: "Nix-Tests"
on:
pull_request:
push:
concurrency:
group: ${{ github.workflow }}-nix-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
nix-flake-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
experimental-features = nix-command flakes
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- run: nix flake show
- run: nix flake check --print-build-logs
- run: nix build --print-build-logs
@@ -0,0 +1,22 @@
name: update-flake-lock
on:
workflow_dispatch: # allows manual triggering
schedule:
- cron: '0 0 1 * *' # Run monthly
push:
paths:
- 'flake.nix'
jobs:
lockfile:
runs-on: ubuntu-latest
if: github.event_name != 'schedule' || github.repository == 'Alexays/Waybar'
steps:
- name: Checkout repository
- uses: actions/checkout@v6
- name: Install Nix
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@v28
+9
View File
@@ -7,6 +7,7 @@ vgcore.*
*.swp
packagecache
/subprojects/**/
/subprojects/.wraplock
/build*
/dist
/meson.egg-info
@@ -44,3 +45,11 @@ packagecache
*.out
*.app
/.direnv/
# Nix
result
result-*
.ccls-cache
_codeql_detected_source_root
heaptrack*
+1 -1
View File
@@ -3,5 +3,5 @@
FROM archlinux:base-devel
RUN pacman -Syu --noconfirm && \
pacman -S --noconfirm git meson base-devel libinput wayland wayland-protocols pixman libxkbcommon mesa gtkmm3 jsoncpp pugixml scdoc libpulse libdbusmenu-gtk3 libmpdclient gobject-introspection libxkbcommon playerctl && \
pacman -S --noconfirm git meson base-devel libinput wayland wayland-protocols glib2-devel pixman libxkbcommon mesa gtkmm3 jsoncpp pugixml scdoc libpulse libdbusmenu-gtk3 libmpdclient gobject-introspection libxkbcommon playerctl iniparser fftw && \
sed -Ei 's/#(en_(US|GB)\.UTF)/\1/' /etc/locale.gen && locale-gen
+46 -4
View File
@@ -1,7 +1,49 @@
# vim: ft=Dockerfile
FROM debian:sid
FROM debian:sid-slim
RUN apt-get update && \
apt-get install -y build-essential meson ninja-build git pkg-config libinput10 libpugixml-dev libinput-dev wayland-protocols libwayland-client0 libwayland-cursor0 libwayland-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev libxkbcommon-dev libudev-dev libpixman-1-dev libgtkmm-3.0-dev libjsoncpp-dev scdoc libdbusmenu-gtk3-dev libnl-3-dev libnl-genl-3-dev libpulse-dev libmpdclient-dev gobject-introspection libgirepository1.0-dev libxkbcommon-dev libxkbregistry-dev libxkbregistry0 libplayerctl-dev && \
apt-get clean
RUN apt update && \
apt install --no-install-recommends --no-install-suggests -y \
build-essential \
catch2 \
cmake \
git \
gobject-introspection \
libdbusmenu-gtk3-dev \
libegl1-mesa-dev \
libfmt-dev \
libgbm-dev \
libgirepository1.0-dev \
libgles2-mesa-dev \
libgtk-layer-shell-dev \
libgtkmm-3.0-dev \
libhowardhinnant-date-dev \
libiniparser-dev \
libinput-dev \
libjack-jackd2-dev \
libjsoncpp-dev \
libmpdclient-dev \
libnl-3-dev \
libnl-genl-3-dev \
libpixman-1-dev \
libplayerctl-dev \
libpugixml-dev \
libpulse-dev \
libsndio-dev \
libspdlog-dev \
libudev-dev \
libupower-glib-dev \
libwayland-dev \
libwireplumber-0.5-dev \
libxkbcommon-dev \
libxkbregistry-dev \
locales \
meson \
ninja-build \
pkg-config \
python3-pip \
python3-venv \
scdoc \
sudo \
wayland-protocols \
&& apt clean
+1 -1
View File
@@ -29,6 +29,6 @@ RUN dnf install -y @c-development \
'pkgconfig(wayland-client)' \
'pkgconfig(wayland-cursor)' \
'pkgconfig(wayland-protocols)' \
'pkgconfig(wireplumber-0.4)' \
'pkgconfig(wireplumber-0.5)' \
'pkgconfig(xkbregistry)' && \
dnf clean all -y
+1 -1
View File
@@ -6,6 +6,6 @@ RUN export FEATURES="-ipc-sandbox -network-sandbox -pid-sandbox -sandbox -usersa
emerge --sync && \
eselect news read --quiet new 1>/dev/null 2>&1 && \
emerge --verbose --update --deep --with-bdeps=y --backtrack=30 --newuse @world && \
USE="wayland gtk3 gtk -doc X pulseaudio minimal" emerge dev-vcs/git dev-libs/wayland dev-libs/wayland-protocols =dev-cpp/gtkmm-3.24.6 x11-libs/libxkbcommon \
USE="wayland gtk3 gtk -doc X pulseaudio minimal" emerge dev-vcs/git dev-libs/wayland dev-libs/wayland-protocols dev-cpp/gtkmm:3.0 x11-libs/libxkbcommon \
x11-libs/gtk+:3 dev-libs/libdbusmenu dev-libs/libnl sys-power/upower media-libs/libpulse dev-libs/libevdev media-libs/libmpdclient \
media-sound/sndio gui-libs/gtk-layer-shell app-text/scdoc media-sound/playerctl dev-libs/iniparser sci-libs/fftw
+1 -1
View File
@@ -6,4 +6,4 @@ RUN zypper -n up && \
zypper addrepo https://download.opensuse.org/repositories/X11:Wayland/openSUSE_Tumbleweed/X11:Wayland.repo | echo 'a' && \
zypper -n refresh && \
zypper -n install -t pattern devel_C_C++ && \
zypper -n install git meson clang libinput10 libinput-devel pugixml-devel libwayland-client0 libwayland-cursor0 wayland-protocols-devel wayland-devel Mesa-libEGL-devel Mesa-libGLESv2-devel libgbm-devel libxkbcommon-devel libudev-devel libpixman-1-0-devel gtkmm3-devel jsoncpp-devel libxkbregistry-devel scdoc playerctl-devel
zypper -n install git meson clang libinput10 libinput-devel pugixml-devel libwayland-client0 libwayland-cursor0 wayland-protocols-devel wayland-devel Mesa-libEGL-devel Mesa-libGLESv2-devel libgbm-devel libxkbcommon-devel libudev-devel libpixman-1-0-devel gtkmm3-devel jsoncpp-devel libxkbregistry-devel scdoc playerctl-devel python3-packaging
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2018 Alex
Copyright (c) 2025 Alex
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+7 -3
View File
@@ -3,11 +3,11 @@
default: build
build:
meson build
meson setup build
ninja -C build
build-debug:
meson build --buildtype=debug
meson setup build --buildtype=debug
ninja -C build
install: build
@@ -20,8 +20,12 @@ debug-run: build-debug
./build/waybar --log-level debug
test:
meson test -C build --no-rebuild --verbose --suite waybar
meson test -C build --verbose --suite waybar
.PHONY: test
test-detailed:
meson test -C build --verbose --print-errorlogs --test-args='--reporter console -s'
.PHONY: test-detailed
clean:
rm -rf build
+42 -6
View File
@@ -1,22 +1,24 @@
# Waybar [![Licence](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Paypal Donate](https://img.shields.io/badge/Donate-Paypal-2244dd.svg)](https://paypal.me/ARouillard)<br>![Waybar](https://raw.githubusercontent.com/alexays/waybar/master/preview-2.png)
> Highly customizable Wayland bar for Sway and Wlroots based compositors.<br>
> Available in Arch [community](https://www.archlinux.org/packages/extra/x86_64/waybar/) or
[AUR](https://aur.archlinux.org/packages/waybar-git/), [Gentoo](https://packages.gentoo.org/packages/gui-apps/waybar), [openSUSE](https://build.opensuse.org/package/show/X11:Wayland/waybar), and [Alpine Linux](https://pkgs.alpinelinux.org/packages?name=waybar).<br>
> Available in [all major distributions](https://github.com/Alexays/Waybar/wiki/Installation)<br>
> *Waybar [examples](https://github.com/Alexays/Waybar/wiki/Examples)*
#### Current features
- Sway (Workspaces, Binding mode, Focused window name)
- River (Mapping mode, Tags, Focused window name)
- Hyprland (Focused window name)
- DWL (Tags) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc)
- Hyprland (Window Icons, Workspaces, Focused window name)
- Niri (Workspaces, Focused window name, Language)
- DWL (Tags, Focused window name) [requires dwl ipc patch](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/ipc)
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
- Local time
- Battery
- UPower
- Power profiles daemon
- Network
- Bluetooth
- Pulseaudio
- Privacy Info
- Wireplumber
- Disk
- Memory
@@ -36,7 +38,7 @@
Waybar is available from a number of Linux distributions:
[![Packaging status](https://repology.org/badge/vertical-allrepos/waybar.svg)](https://repology.org/project/waybar/versions)
[![Packaging status](https://repology.org/badge/vertical-allrepos/waybar.svg?columns=3&header=Waybar%20Downstream%20Packaging)](https://repology.org/project/waybar/versions)
An Ubuntu PPA with more recent versions is available
[here](https://launchpad.net/~nschloe/+archive/ubuntu/waybar).
@@ -47,7 +49,7 @@ An Ubuntu PPA with more recent versions is available
```bash
$ git clone https://github.com/Alexays/Waybar
$ cd Waybar
$ meson build
$ meson setup build
$ ninja -C build
$ ./build/waybar
# If you want to install it
@@ -114,11 +116,45 @@ sudo apt install \
libxkbregistry-dev
```
On Arch, you can use this command:
```
pacman -S --asdeps \
gtkmm3 \
jsoncpp \
libsigc++ \
fmt \
wayland \
chrono-date \
spdlog \
gtk3 \
gobject-introspection \
libgirepository \
libpulse \
libnl \
libappindicator-gtk3 \
libdbusmenu-gtk3 \
libmpdclient \
sndio \
libevdev \
libxkbcommon \
upower \
meson \
cmake \
scdoc \
wayland-protocols \
glib2-devel
```
Contributions welcome!<br>
Have fun :)<br>
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
Waybar is licensed under the MIT license. [See LICENSE for more information](https://github.com/Alexays/Waybar/blob/master/LICENSE).
+1
View File
@@ -0,0 +1 @@
.
+5
View File
@@ -0,0 +1,5 @@
# Suppress common address sanitizer issues in dependencies, these are often non-fixable or not an issue.
# Use it like this (when in repo root): ASAN_OPTIONS="suppressions=./asan.supp" ./build/waybar
leak:libpangoft2-1.0.so.0
leak:libgtk-3.so.0
leak:libfontconfig.so.1
+5 -6
View File
@@ -1,10 +1,9 @@
(import
(
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
(import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{ src = ./.; }
).defaultNix
) { src = ./.; }).defaultNix
Generated
+7 -74
View File
@@ -1,32 +1,13 @@
{
"nodes": {
"devshell": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1676293499,
"narHash": "sha256-uIOTlTxvrXxpKeTvwBI1JGDGtCxMXE3BI0LFwoQMhiQ=",
"owner": "numtide",
"repo": "devshell",
"rev": "71e3022e3ab20bbf1342640547ef5bc14fb43bf4",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"lastModified": 1767039857,
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"type": "github"
},
"original": {
@@ -35,59 +16,13 @@
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1642700792,
"narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "846b2ae0fc4cc943637d3d1def4454213e203cba",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1676283394,
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1643381941,
"narHash": "sha256-pHTwvnN4tTsEKkWlXQ8JMY423epos8wUOhthpwJjtpc=",
"lastModified": 1769461804,
"narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5efc8ca954272c4376ac929f4c5ffefcc20551d5",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1676300157,
"narHash": "sha256-1HjRzfp6LOLfcj/HJHdVKWAkX9QRAouoh6AjzJiIerU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "545c7a31e5dedea4a6d372712a18e00ce097d462",
"rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
"type": "github"
},
"original": {
@@ -99,10 +34,8 @@
},
"root": {
"inputs": {
"devshell": "devshell",
"flake-compat": "flake-compat",
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_2"
"nixpkgs": "nixpkgs"
}
}
},
+97 -64
View File
@@ -1,93 +1,126 @@
{
description = "Highly customizable Wayland bar for Sway and Wlroots based compositors.";
description = "Highly customizable Wayland bar for Sway and Wlroots based compositors";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
devshell.url = "github:numtide/devshell";
flake-utils.url = "github:numtide/flake-utils";
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
};
outputs = { self, flake-utils, devshell, nixpkgs, flake-compat }:
outputs =
{ self, nixpkgs, ... }:
let
inherit (nixpkgs) lib;
genSystems = lib.genAttrs [
genSystems =
func:
lib.genAttrs
[
"x86_64-linux"
];
pkgsFor = genSystems (system:
"aarch64-linux"
]
(
system:
func (
import nixpkgs {
inherit system;
});
overlays = with self.overlays; [
waybar
];
}
)
);
mkDate = longDate: (lib.concatStringsSep "-" [
mkDate =
longDate:
(lib.concatStringsSep "-" [
(builtins.substring 0 4 longDate)
(builtins.substring 4 2 longDate)
(builtins.substring 6 2 longDate)
]);
in
{
overlays.default = _: prev: {
waybar = prev.callPackage ./nix/default.nix {
version = prev.waybar.version + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
};
};
packages = genSystems
(system:
(self.overlays.default null pkgsFor.${system})
// {
default = self.packages.${system}.waybar;
});
} //
flake-utils.lib.eachDefaultSystem (system: {
devShell =
let pkgs = import nixpkgs {
inherit system;
devShells = genSystems (pkgs: {
default = pkgs.mkShell {
name = "waybar-shell";
overlays = [ devshell.overlay ];
};
in
pkgs.devshell.mkShell {
imports = [ "${pkgs.devshell.extraModulesDir}/language/c.nix" ];
commands = [
{
package = pkgs.devshell.cli;
help = "Per project developer environments";
}
];
devshell.packages = with pkgs; [
# inherit attributes from upstream nixpkgs derivation
inherit (pkgs.waybar)
buildInputs
depsBuildBuild
depsBuildBuildPropagated
depsBuildTarget
depsBuildTargetPropagated
depsHostHost
depsHostHostPropagated
depsTargetTarget
depsTargetTargetPropagated
propagatedBuildInputs
propagatedNativeBuildInputs
strictDeps
;
# overrides for local development
nativeBuildInputs =
pkgs.waybar.nativeBuildInputs
++ (with pkgs; [
nixfmt
clang-tools
gdb
# from nativeBuildInputs
gnumake
meson
ninja
pkg-config
scdoc
] ++ (map lib.getDev [
# from buildInputs
wayland wlroots gtkmm3 libsigcxx jsoncpp spdlog gtk-layer-shell howard-hinnant-date libxkbcommon
# optional dependencies
gobject-introspection glib playerctl python3.pkgs.pygobject3
libevdev libinput libjack2 libmpdclient playerctl libnl
libpulseaudio sndio sway libdbusmenu-gtk3 udev upower wireplumber
# from propagated build inputs?
at-spi2-atk atkmm cairo cairomm catch2 fmt_8 fontconfig
gdk-pixbuf glibmm gtk3 harfbuzz pango pangomm wayland-protocols
]);
env = with pkgs; [
{ name = "CPLUS_INCLUDE_PATH"; prefix = "$DEVSHELL_DIR/include"; }
{ name = "PKG_CONFIG_PATH"; prefix = "$DEVSHELL_DIR/lib/pkgconfig"; }
{ name = "PKG_CONFIG_PATH"; prefix = "$DEVSHELL_DIR/share/pkgconfig"; }
{ name = "PATH"; prefix = "${wayland.bin}/bin"; }
{ name = "LIBRARY_PATH"; prefix = "${lib.getLib sndio}/lib"; }
{ name = "LIBRARY_PATH"; prefix = "${lib.getLib zlib}/lib"; }
{ name = "LIBRARY_PATH"; prefix = "${lib.getLib howard-hinnant-date}/lib"; }
];
};
});
formatter = genSystems (
pkgs:
pkgs.treefmt.withConfig {
settings = {
formatter = {
clang-format = {
options = [ "-i" ];
command = lib.getExe' pkgs.clang-tools "clang-format";
excludes = [ ];
includes = [
"*.c"
"*.cpp"
"*.h"
"*.hpp"
];
};
nixfmt = {
command = lib.getExe pkgs.nixfmt;
includes = [ "*.nix" ];
};
};
tree-root-file = ".git/index";
};
}
);
overlays = {
default = self.overlays.waybar;
waybar = final: prev: {
waybar = final.callPackage ./nix/default.nix {
waybar = prev.waybar;
# take the first "version: '...'" from meson.build
version =
(builtins.head (
builtins.split "'" (
builtins.elemAt (builtins.split " version: '" (builtins.readFile ./meson.build)) 2
)
))
+ "+date="
+ (mkDate (self.lastModifiedDate or "19700101"))
+ "_"
+ (self.shortRev or "dirty");
};
};
};
packages = genSystems (pkgs: {
default = self.packages.${pkgs.stdenv.hostPlatform.system}.waybar;
inherit (pkgs) waybar;
});
};
}
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include <gtkmm/box.h>
#include <gtkmm/image.h>
#include "AIconLabel.hpp"
namespace waybar {
class AAppIconLabel : public AIconLabel {
public:
AAppIconLabel(const Json::Value& config, const std::string& name, const std::string& id,
const std::string& format, uint16_t interval = 0, bool ellipsize = false,
bool enable_click = false, bool enable_scroll = false);
virtual ~AAppIconLabel() = default;
auto update() -> void override;
protected:
void updateAppIconName(const std::string& app_identifier,
const std::string& alternative_app_identifier);
void updateAppIcon();
unsigned app_icon_size_{24};
bool update_app_icon_{true};
std::string app_icon_name_;
};
} // namespace waybar
+6 -2
View File
@@ -9,15 +9,19 @@ namespace waybar {
class AIconLabel : public ALabel {
public:
AIconLabel(const Json::Value &config, const std::string &name, const std::string &id,
const std::string &format, uint16_t interval = 0, bool ellipsize = false,
AIconLabel(const Json::Value& config, const std::string& name, const std::string& id,
const std::string& format, uint16_t interval = 0, bool ellipsize = false,
bool enable_click = false, bool enable_scroll = false);
virtual ~AIconLabel() = default;
auto update() -> void override;
static std::tuple<std::string, std::string> extractIcon(const std::string& input);
protected:
Gtk::Image image_;
Gtk::Box box_;
unsigned app_icon_size_{24};
bool label_contains_icon{false};
bool iconEnabled() const;
};
+18 -5
View File
@@ -4,29 +4,42 @@
#include <gtkmm/label.h>
#include <json/json.h>
#include <optional>
#include "AModule.hpp"
namespace waybar {
class ALabel : public AModule {
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,
bool enable_scroll = false);
virtual ~ALabel() = default;
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::vector<std::string> &alts, 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);
protected:
Gtk::Label label_;
std::string format_;
const std::chrono::seconds interval_;
const std::chrono::milliseconds interval_;
bool alt_ = false;
std::string default_format_;
bool handleToggle(GdkEventButton *const &e) override;
bool setLabelMarkup(const Glib::ustring& markup);
bool setTooltipMarkup(const Glib::ustring& markup);
bool handleToggle(GdkEventButton* const& e) override;
virtual std::string getState(uint8_t value, bool lesser = false);
std::map<std::string, GtkMenuItem*> submenus_;
std::map<std::string, std::string> menuActionsMap_;
static void handleGtkMenuEvent(GtkMenuItem* menuitem, gpointer data);
private:
std::optional<Glib::ustring> last_label_markup_;
std::optional<Glib::ustring> last_tooltip_markup_;
};
} // namespace waybar
+40 -12
View File
@@ -2,6 +2,7 @@
#include <glibmm/dispatcher.h>
#include <glibmm/markup.h>
#include <gtkmm.h>
#include <gtkmm/eventbox.h>
#include <json/json.h>
@@ -11,51 +12,78 @@ namespace waybar {
class AModule : public IModule {
public:
virtual ~AModule();
auto update() -> void override;
virtual auto refresh(int) -> void{};
operator Gtk::Widget &() override;
auto doAction(const std::string &name) -> void override;
static constexpr const char* MODULE_CLASS = "module";
~AModule() override;
auto update() -> void override;
virtual auto refresh(int shouldRefresh) -> void {};
operator Gtk::Widget&() override;
auto doAction(const std::string& name) -> void override;
/// Emitting on this dispatcher triggers a update() call
Glib::Dispatcher dp;
bool expandEnabled() const;
virtual void suspend() {};
virtual void resume() {};
bool shouldSuspend() const { return disable_on_sleep_; }
protected:
// Don't need to make an object directly
// 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);
enum SCROLL_DIR { NONE, UP, DOWN, LEFT, RIGHT };
SCROLL_DIR getScrollDir(GdkEventScroll *e);
bool tooltipEnabled();
SCROLL_DIR getScrollDir(GdkEventScroll* e);
bool tooltipEnabled() const;
std::vector<int> pid_children_;
const std::string name_;
const Json::Value &config_;
const Json::Value& config_;
Gtk::EventBox event_box_;
virtual bool handleToggle(GdkEventButton *const &ev);
virtual bool handleScroll(GdkEventScroll *);
virtual void setCursor(Gdk::CursorType const& c);
virtual bool handleToggle(GdkEventButton* const& ev);
virtual bool handleMouseEnter(GdkEventCrossing* const& ev);
virtual bool handleMouseLeave(GdkEventCrossing* const& ev);
virtual bool handleScroll(GdkEventScroll*);
virtual bool handleRelease(GdkEventButton* const& ev);
bool disable_on_sleep_{false};
GObject* menu_ = nullptr;
private:
std::vector<int> pid_;
bool handleUserEvent(GdkEventButton* const& ev);
const bool isTooltip;
const bool isExpand;
bool hasUserEvents_;
gdouble distance_scrolled_y_;
gdouble distance_scrolled_x_;
sigc::connection cursor_timeout_conn_;
std::map<std::string, std::string> eventActionMap_;
static const inline std::map<std::pair<uint, GdkEventType>, std::string> eventMap_{
{std::make_pair(1, GdkEventType::GDK_BUTTON_PRESS), "on-click"},
{std::make_pair(1, GdkEventType::GDK_BUTTON_RELEASE), "on-click-release"},
{std::make_pair(1, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click"},
{std::make_pair(1, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click"},
{std::make_pair(2, GdkEventType::GDK_BUTTON_PRESS), "on-click-middle"},
{std::make_pair(2, GdkEventType::GDK_BUTTON_RELEASE), "on-click-middle-release"},
{std::make_pair(2, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-middle"},
{std::make_pair(2, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-middle"},
{std::make_pair(3, GdkEventType::GDK_BUTTON_PRESS), "on-click-right"},
{std::make_pair(3, GdkEventType::GDK_BUTTON_RELEASE), "on-click-right-release"},
{std::make_pair(3, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-right"},
{std::make_pair(3, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-right"},
{std::make_pair(8, GdkEventType::GDK_BUTTON_PRESS), "on-click-backward"},
{std::make_pair(8, GdkEventType::GDK_BUTTON_RELEASE), "on-click-backward-release"},
{std::make_pair(8, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-backward"},
{std::make_pair(8, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-backward"},
{std::make_pair(9, GdkEventType::GDK_BUTTON_PRESS), "on-click-forward"},
{std::make_pair(9, GdkEventType::GDK_BUTTON_RELEASE), "on-click-forward-release"},
{std::make_pair(9, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-forward"},
{std::make_pair(9, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-forward"}};
};
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include "AModule.hpp"
#include "gtkmm/scale.h"
namespace waybar {
class ASlider : public AModule {
public:
ASlider(const Json::Value& config, const std::string& name, const std::string& id);
virtual void onValueChanged();
protected:
bool vertical_ = false;
int min_ = 0, max_ = 100, curr_ = 50;
Gtk::Scale scale_;
};
} // namespace waybar
+42 -33
View File
@@ -9,9 +9,12 @@
#include <json/json.h>
#include <memory>
#include <optional>
#include <vector>
#include "AModule.hpp"
#include "group.hpp"
#include "util/kill_signal.hpp"
#include "xdg-output-unstable-v1-client-protocol.h"
namespace waybar {
@@ -52,62 +55,65 @@ class BarIpcClient;
}
#endif // HAVE_SWAY
class BarSurface {
protected:
BarSurface() = default;
class Bar : public sigc::trackable {
public:
virtual void setExclusiveZone(bool enable) = 0;
virtual void setLayer(bar_layer layer) = 0;
virtual void setMargins(const struct bar_margins &margins) = 0;
virtual void setPassThrough(bool enable) = 0;
virtual void setPosition(const std::string_view &position) = 0;
virtual void setSize(uint32_t width, uint32_t height) = 0;
virtual void commit(){};
virtual ~BarSurface() = default;
};
class Bar {
public:
using bar_mode_map = std::map<std::string_view, struct bar_mode>;
using bar_mode_map = std::map<std::string, struct bar_mode>;
static const bar_mode_map PRESET_MODES;
static const std::string_view MODE_DEFAULT;
static const std::string_view MODE_INVISIBLE;
static const std::string MODE_DEFAULT;
static const std::string MODE_INVISIBLE;
Bar(struct waybar_output *w_output, const Json::Value &);
Bar(const Bar &) = delete;
Bar(struct waybar_output* w_output, const Json::Value&);
Bar(const Bar&) = delete;
~Bar();
void setMode(const std::string_view &);
void setVisible(bool visible);
void setMode(const std::string& mode);
void setVisible(bool value);
void toggle();
void show();
void hide();
void handleSignal(int);
util::KillSignalAction getOnSigusr1Action();
util::KillSignalAction getOnSigusr2Action();
struct waybar_output *output;
void toggleSuspend(bool suspend);
struct waybar_output* output;
Json::Value config;
struct wl_surface *surface;
struct wl_surface* surface;
bool visible = true;
bool vertical = false;
Gtk::Window window;
Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL;
Gtk::PositionType position = Gtk::POS_TOP;
int x_global;
int y_global;
#ifdef HAVE_SWAY
std::string bar_id;
#endif
private:
void onMap(GdkEventAny *);
void onMap(GdkEventAny*);
auto setupWidgets() -> void;
void getModules(const Factory &, const std::string &, Gtk::Box *);
void setupAltFormatKeyForModule(const std::string &module_name);
void setupAltFormatKeyForModuleList(const char *module_list_name);
void setMode(const bar_mode &);
void getModules(const Factory&, const std::string&, waybar::Group*);
void setupAltFormatKeyForModule(const std::string& module_name);
void setupAltFormatKeyForModuleList(const char* module_list_name);
void setMode(const bar_mode&);
void setPassThrough(bool passthrough);
void setPosition(Gtk::PositionType position);
void forceLayerCommit();
void onConfigure(GdkEventConfigure* ev);
void configureGlobalOffset(int width, int height);
void onOutputGeometryChanged();
/* Copy initial set of modes to allow customization */
bar_mode_map configured_modes = PRESET_MODES;
std::string last_mode_{MODE_DEFAULT};
std::unique_ptr<BarSurface> surface_impl_;
struct bar_margins margins_;
uint32_t width_, height_;
bool passthrough_;
Gtk::Box left_;
Gtk::Box center_;
Gtk::Box right_;
@@ -120,6 +126,9 @@ class Bar {
std::unique_ptr<BarIpcClient> _ipc_client;
#endif
std::vector<std::shared_ptr<waybar::AModule>> modules_all_;
waybar::util::KillSignalAction onSigusr1 = util::SIGNALACTION_DEFAULT_SIGUSR1;
waybar::util::KillSignalAction onSigusr2 = util::SIGNALACTION_DEFAULT_SIGUSR2;
};
} // namespace waybar
+27 -19
View File
@@ -7,8 +7,9 @@
#include "bar.hpp"
#include "config.hpp"
#include "util/css_reload_helper.hpp"
#include "util/portal.hpp"
struct zwlr_layer_shell_v1;
struct zwp_idle_inhibitor_v1;
struct zwp_idle_inhibit_manager_v1;
@@ -16,43 +17,50 @@ namespace waybar {
class Client {
public:
static Client *inst();
int main(int argc, char *argv[]);
static Client* inst();
int main(int argc, char* argv[]);
void reset();
Glib::RefPtr<Gtk::Application> gtk_app;
Glib::RefPtr<Gdk::Display> gdk_display;
struct wl_display *wl_display = nullptr;
struct wl_registry *registry = nullptr;
struct zwlr_layer_shell_v1 *layer_shell = nullptr;
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager = nullptr;
struct wl_display* wl_display = nullptr;
struct wl_registry* registry = nullptr;
struct zxdg_output_manager_v1* xdg_output_manager = nullptr;
struct zwp_idle_inhibit_manager_v1* idle_inhibit_manager = nullptr;
std::vector<std::unique_ptr<Bar>> bars;
Config config;
std::string bar_id;
private:
Client() = default;
const std::string getStyle(const std::string &style);
const std::string getStyle(const std::string& style, std::optional<Appearance> appearance);
void bindInterfaces();
void handleOutput(struct waybar_output &output);
auto setupCss(const std::string &css_file) -> void;
struct waybar_output &getOutput(void *);
std::vector<Json::Value> getOutputConfigs(struct waybar_output &output);
void handleOutput(struct waybar_output& output);
auto setupCss(const std::string& css_file) -> void;
struct waybar_output& getOutput(void*);
std::vector<Json::Value> getOutputConfigs(struct waybar_output& output);
static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name,
const char *interface, uint32_t version);
static void handleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name);
static void handleOutputDone(void *, struct zxdg_output_v1 *);
static void handleOutputName(void *, struct zxdg_output_v1 *, const char *);
static void handleOutputDescription(void *, struct zxdg_output_v1 *, const char *);
static void handleGlobal(void* data, struct wl_registry* registry, uint32_t name,
const char* interface, uint32_t version);
static void handleGlobalRemove(void* data, struct wl_registry* registry, uint32_t name);
static void handleOutputDone(void*, struct zxdg_output_v1*);
void createBarsBatch();
static void handleOutputName(void*, struct zxdg_output_v1*, const char*);
static void handleOutputDescription(void*, struct zxdg_output_v1*, const char*);
void handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor);
void handleMonitorRemoved(Glib::RefPtr<Gdk::Monitor> monitor);
void handleDeferredMonitorRemoval(Glib::RefPtr<Gdk::Monitor> monitor);
Glib::RefPtr<Gtk::StyleContext> style_context_;
Glib::RefPtr<Gtk::CssProvider> css_provider_;
std::unique_ptr<Portal> portal;
std::list<struct waybar_output> outputs_;
std::unique_ptr<CssReloadHelper> m_cssReloadHelper;
std::string m_cssFile;
sigc::connection monitor_added_connection_;
sigc::connection monitor_removed_connection_;
std::list<waybar_output*> pending_outputs_;
bool bars_scheduled_ = false;
};
} // namespace waybar
+13 -8
View File
@@ -14,24 +14,29 @@ namespace waybar {
class Config {
public:
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 */
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,
const std::string& filename);
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:
void setupConfig(Json::Value &dst, const std::string &config_file, int depth);
void resolveConfigIncludes(Json::Value &config, int depth);
void mergeConfig(Json::Value &a_config_, Json::Value &b_config_);
void setupConfig(Json::Value& dst, const std::string& config_file, int depth);
void resolveConfigIncludes(Json::Value& config, int depth);
void mergeConfig(Json::Value& a_config_, Json::Value& b_config_);
static std::vector<std::string> findIncludePath(
const std::string& name, const std::vector<std::string>& dirs = CONFIG_DIRS);
std::string config_file_;
+5 -92
View File
@@ -1,104 +1,17 @@
#pragma once
#include <json/json.h>
#if defined(HAVE_CHRONO_TIMEZONES) || defined(HAVE_LIBDATE)
#include "modules/clock.hpp"
#else
#include "modules/simpleclock.hpp"
#endif
#ifdef HAVE_SWAY
#include "modules/sway/language.hpp"
#include "modules/sway/mode.hpp"
#include "modules/sway/scratchpad.hpp"
#include "modules/sway/window.hpp"
#include "modules/sway/workspaces.hpp"
#endif
#ifdef HAVE_WLR
#include "modules/wlr/taskbar.hpp"
#include "modules/wlr/workspace_manager.hpp"
#endif
#ifdef HAVE_RIVER
#include "modules/river/layout.hpp"
#include "modules/river/mode.hpp"
#include "modules/river/tags.hpp"
#include "modules/river/window.hpp"
#endif
#ifdef HAVE_DWL
#include "modules/dwl/tags.hpp"
#endif
#ifdef HAVE_HYPRLAND
#include "modules/hyprland/backend.hpp"
#include "modules/hyprland/language.hpp"
#include "modules/hyprland/submap.hpp"
#include "modules/hyprland/window.hpp"
#include "modules/hyprland/workspaces.hpp"
#endif
#if defined(__FreeBSD__) || (defined(__linux__) && !defined(NO_FILESYSTEM))
#include "modules/battery.hpp"
#endif
#if defined(HAVE_CPU_LINUX) || defined(HAVE_CPU_BSD)
#include "modules/cpu.hpp"
#endif
#include "modules/idle_inhibitor.hpp"
#if defined(HAVE_MEMORY_LINUX) || defined(HAVE_MEMORY_BSD)
#include "modules/memory.hpp"
#endif
#include "modules/disk.hpp"
#ifdef HAVE_DBUSMENU
#include "modules/sni/tray.hpp"
#endif
#ifdef HAVE_MPRIS
#include "modules/mpris/mpris.hpp"
#endif
#ifdef HAVE_LIBNL
#include "modules/network.hpp"
#endif
#ifdef HAVE_LIBUDEV
#include "modules/backlight.hpp"
#endif
#ifdef HAVE_LIBEVDEV
#include "modules/keyboard_state.hpp"
#endif
#ifdef HAVE_GAMEMODE
#include "modules/gamemode.hpp"
#endif
#ifdef HAVE_UPOWER
#include "modules/upower/upower.hpp"
#endif
#ifdef HAVE_LIBPULSE
#include "modules/pulseaudio.hpp"
#endif
#ifdef HAVE_LIBMPDCLIENT
#include "modules/mpd/mpd.hpp"
#endif
#ifdef HAVE_LIBSNDIO
#include "modules/sndio.hpp"
#endif
#ifdef HAVE_GIO_UNIX
#include "modules/bluetooth.hpp"
#include "modules/inhibitor.hpp"
#endif
#ifdef HAVE_LIBJACK
#include "modules/jack.hpp"
#endif
#ifdef HAVE_LIBWIREPLUMBER
#include "modules/wireplumber.hpp"
#endif
#ifdef HAVE_LIBCAVA
#include "modules/cava.hpp"
#endif
#include "bar.hpp"
#include "modules/custom.hpp"
#include "modules/image.hpp"
#include "modules/temperature.hpp"
#include "modules/user.hpp"
#include <AModule.hpp>
namespace waybar {
class Bar;
class Factory {
public:
Factory(const Bar& bar, const Json::Value& config);
AModule* makeModule(const std::string& name) const;
AModule* makeModule(const std::string& name, const std::string& pos) const;
private:
const Bar& bar_;
+22 -3
View File
@@ -5,18 +5,37 @@
#include <json/json.h>
#include "AModule.hpp"
#include "bar.hpp"
#include "factory.hpp"
#include "gtkmm/revealer.h"
namespace waybar {
class Group : public AModule {
sigc::connection reveal_timeout_;
public:
Group(const std::string&, const std::string&, const Json::Value&, bool);
~Group() = default;
~Group() override = default;
auto update() -> void override;
operator Gtk::Widget&() override;
virtual Gtk::Box& getBox();
void addWidget(Gtk::Widget& widget);
protected:
Gtk::Box box;
Gtk::Box revealer_box;
Gtk::Revealer revealer;
bool is_first_widget = true;
bool is_drawer = false;
bool click_to_reveal = false;
int reveal_delay = 0;
std::string add_class_to_drawer_children;
bool handleMouseEnter(GdkEventCrossing* const& ev) override;
bool handleMouseLeave(GdkEventCrossing* const& ev) override;
bool handleToggle(GdkEventButton* const& ev) override;
bool handleScroll(GdkEventScroll* e) override;
void show_group();
void hide_group();
};
} // namespace waybar
+6 -43
View File
@@ -1,14 +1,14 @@
#pragma once
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include "ALabel.hpp"
#include "giomm/dbusproxy.h"
#include "util/backlight_backend.hpp"
#include "util/json.hpp"
#include "util/sleeper_thread.hpp"
struct udev;
struct udev_device;
@@ -16,54 +16,17 @@ struct udev_device;
namespace waybar::modules {
class Backlight : public ALabel {
class BacklightDev {
public:
BacklightDev() = default;
BacklightDev(std::string name, int actual, int max, bool powered);
std::string_view name() const;
int get_actual() const;
void set_actual(int actual);
int get_max() const;
void set_max(int max);
bool get_powered() const;
void set_powered(bool powered);
friend inline bool operator==(const BacklightDev &lhs, const BacklightDev &rhs) {
return lhs.name_ == rhs.name_ && lhs.actual_ == rhs.actual_ && lhs.max_ == rhs.max_;
}
private:
std::string name_;
int actual_ = 1;
int max_ = 1;
bool powered_ = true;
};
public:
Backlight(const std::string &, const Json::Value &);
virtual ~Backlight();
Backlight(const std::string&, const Json::Value&);
virtual ~Backlight() = default;
auto update() -> void override;
private:
template <class ForwardIt>
static const BacklightDev *best_device(ForwardIt first, ForwardIt last, std::string_view);
template <class ForwardIt, class Inserter>
static void upsert_device(ForwardIt first, ForwardIt last, Inserter inserter, udev_device *dev);
template <class ForwardIt, class Inserter>
static void enumerate_devices(ForwardIt first, ForwardIt last, Inserter inserter, udev *udev);
bool handleScroll(GdkEventScroll *e) override;
bool handleScroll(GdkEventScroll* e) override;
const std::string preferred_device_;
static constexpr int EPOLL_MAX_EVENTS = 16;
std::optional<BacklightDev> previous_best_;
std::string previous_format_;
std::mutex udev_thread_mutex_;
std::vector<BacklightDev> devices_;
// thread must destruct before shared data
util::SleeperThread udev_thread_;
Glib::RefPtr<Gio::DBus::Proxy> login_proxy_;
util::BacklightBackend backend;
};
} // namespace waybar::modules
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include <chrono>
#include "ASlider.hpp"
#include "util/backlight_backend.hpp"
namespace waybar::modules {
class BacklightSlider : public ASlider {
public:
BacklightSlider(const std::string&, const Json::Value&);
virtual ~BacklightSlider() = default;
void update() override;
void onValueChanged() override;
private:
std::chrono::milliseconds interval_;
std::string preferred_device_;
util::BacklightBackend backend;
};
} // namespace waybar::modules
+21 -13
View File
@@ -1,34 +1,31 @@
#pragma once
#ifdef FILESYSTEM_EXPERIMENTAL
#include <experimental/filesystem>
#else
#include <filesystem>
#endif
#include <fmt/format.h>
#include <filesystem>
#if defined(__linux__)
#include <sys/inotify.h>
#endif
#include <poll.h>
#include <algorithm>
#include <chrono>
#include <fstream>
#include <string>
#include <vector>
#include "ALabel.hpp"
#include "bar.hpp"
#include "util/sleeper_thread.hpp"
#include "util/udev_deleter.hpp"
namespace waybar::modules {
#ifdef FILESYSTEM_EXPERIMENTAL
namespace fs = std::experimental::filesystem;
#else
namespace fs = std::filesystem;
#endif
class Battery : public ALabel {
public:
Battery(const std::string&, const Json::Value&);
Battery(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Battery();
auto update() -> void override;
@@ -38,17 +35,28 @@ class Battery : public ALabel {
void refreshBatteries();
void worker();
const std::string getAdapterStatus(uint8_t capacity) const;
const std::tuple<uint8_t, float, std::string, float> getInfos();
std::tuple<uint8_t, float, std::string, float, uint16_t, float> getInfos();
const std::string formatTimeRemaining(float hoursRemaining);
void setBarClass(std::string&);
void processEvents(std::string& state, std::string& status, uint8_t capacity);
int global_watch;
std::map<fs::path, int> batteries_;
std::unique_ptr<udev, util::UdevDeleter> udev_;
std::array<pollfd, 1> poll_fds_;
std::unique_ptr<udev_monitor, util::UdevMonitorDeleter> mon_;
fs::path adapter_;
int battery_watch_fd_;
int global_watch_fd_;
std::mutex battery_list_mutex_;
std::string old_status_;
std::string last_event_;
bool warnFirstTime_{true};
bool weightedAverage_{true};
const Bar& bar_;
bool smoothPowerEnable_{false};
double time_constant_s_{260.0};
double smooth_power_{0.0}; // µW
std::chrono::steady_clock::time_point last_t_{std::chrono::steady_clock::now()};
std::string old_status_raw_{""};
util::SleeperThread thread_;
util::SleeperThread thread_battery_update_;
+6 -2
View File
@@ -49,6 +49,9 @@ class Bluetooth : public ALabel {
auto update() -> void override;
private:
static auto onObjectAdded(GDBusObjectManager*, GDBusObject*, gpointer) -> void;
static auto onObjectRemoved(GDBusObjectManager*, GDBusObject*, gpointer) -> void;
static auto onInterfaceAddedOrRemoved(GDBusObjectManager*, GDBusObject*, GDBusInterface*,
gpointer) -> void;
static auto onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient*, GDBusObjectProxy*,
@@ -59,7 +62,8 @@ class Bluetooth : public ALabel {
auto getDeviceProperties(GDBusObject*, DeviceInfo&) -> bool;
auto getControllerProperties(GDBusObject*, ControllerInfo&) -> bool;
auto findCurController(ControllerInfo&) -> bool;
// Returns std::nullopt if no controller could be found
auto findCurController() -> std::optional<ControllerInfo>;
auto findConnectedDevices(const std::string&, std::vector<DeviceInfo>&) -> void;
#ifdef WANT_RFKILL
@@ -68,7 +72,7 @@ class Bluetooth : public ALabel {
const std::unique_ptr<GDBusObjectManager, void (*)(GDBusObjectManager*)> manager_;
std::string state_;
ControllerInfo cur_controller_;
std::optional<ControllerInfo> cur_controller_;
std::vector<DeviceInfo> connected_devices_;
DeviceInfo cur_focussed_device_;
std::string device_enumerate_;
-46
View File
@@ -1,46 +0,0 @@
#pragma once
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
extern "C" {
#include <cava/common.h>
}
namespace waybar::modules {
using namespace std::literals::chrono_literals;
class Cava final : public ALabel {
public:
Cava(const std::string&, const Json::Value&);
virtual ~Cava();
auto update() -> void override;
auto doAction(const std::string& name) -> void override;
private:
util::SleeperThread thread_;
util::SleeperThread thread_fetch_input_;
struct error_s error_ {}; // cava errors
struct config_params prm_ {}; // cava parameters
struct audio_raw audio_raw_ {}; // cava handled raw audio data(is based on audio_data)
struct audio_data audio_data_ {}; // cava audio data
struct cava_plan* plan_; //{new cava_plan{}};
// Cava API to read audio source
ptr input_source_;
// Delay to handle audio source
std::chrono::milliseconds frame_time_milsec_{1s};
// Text to display
std::string text_{""};
int rePaint_{1};
std::chrono::seconds fetch_input_delay_{4};
std::chrono::seconds suspend_silence_delay_{0};
bool silence_{false};
int sleep_counter_{0};
// Cava method
void pause_resume();
// ModuleActionMap
static inline std::map<const std::string, void (waybar::modules::Cava::*const)()> actionMap_{
{"mode", &waybar::modules::Cava::pause_resume}};
};
} // namespace waybar::modules
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <epoxy/gl.h>
#include "AModule.hpp"
#include "cava_backend.hpp"
namespace waybar::modules::cava {
class CavaGLSL final : public AModule, public Gtk::GLArea {
public:
CavaGLSL(const std::string&, const Json::Value&);
~CavaGLSL() = default;
private:
std::shared_ptr<CavaBackend> backend_;
struct ::cava::config_params prm_;
int frame_counter{0};
bool silence_{false};
bool hide_on_silence_{false};
// Cava method
auto onUpdate(const ::cava::audio_raw& input) -> void;
auto onSilence() -> void;
// Member variable to store the shared pointer
std::shared_ptr<::cava::audio_raw> m_data_;
GLuint shaderProgram_;
// OpenGL variables
GLuint fbo_;
GLuint texture_;
GLint uniform_bars_;
GLint uniform_previous_bars_;
GLint uniform_bars_count_;
GLint uniform_time_;
// Methods
void onRealize();
bool onRender(const Glib::RefPtr<Gdk::GLContext>& context);
void initShaders();
void initSurface();
void initGLSL();
GLuint loadShader(const std::string& fileName, GLenum type);
};
} // namespace waybar::modules::cava
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include "ALabel.hpp"
#include "cava_backend.hpp"
namespace waybar::modules::cava {
class Cava final : public ALabel, public sigc::trackable {
public:
Cava(const std::string&, const Json::Value&);
~Cava() = default;
auto doAction(const std::string& name) -> void override;
private:
std::shared_ptr<CavaBackend> backend_;
// Text to display
Glib::ustring label_text_{""};
bool silence_{false};
bool hide_on_silence_{false};
std::string format_silent_{""};
int ascii_range_{0};
// Cava method
void pause_resume();
auto onUpdate(const std::string& input) -> void;
auto onSilence() -> void;
// ModuleActionMap
static inline std::map<const std::string, void (waybar::modules::cava::Cava::* const)()>
actionMap_{{"mode", &waybar::modules::cava::Cava::pause_resume}};
};
} // namespace waybar::modules::cava
+84
View File
@@ -0,0 +1,84 @@
#pragma once
#include <json/json.h>
#include <sigc++/sigc++.h>
#include "util/sleeper_thread.hpp"
namespace cava {
extern "C" {
// Need sdl_glsl output feature to be enabled on libcava
#ifndef SDL_GLSL
#define SDL_GLSL
#endif
#include <cava/common.h>
#ifdef SDL_GLSL
#undef SDL_GLSL
#endif
}
} // namespace cava
namespace waybar::modules::cava {
using namespace std::literals::chrono_literals;
class CavaBackend final {
public:
static std::shared_ptr<CavaBackend> inst(const Json::Value& config);
virtual ~CavaBackend();
// Methods
int getAsciiRange();
void doPauseResume();
void Update();
const struct ::cava::config_params* getPrm();
std::chrono::milliseconds getFrameTimeMilsec();
// Signal accessor
using type_signal_update = sigc::signal<void(const std::string&)>;
type_signal_update signal_update();
using type_signal_audio_raw_update = sigc::signal<void(const ::cava::audio_raw&)>;
type_signal_audio_raw_update signal_audio_raw_update();
using type_signal_silence = sigc::signal<void()>;
type_signal_silence signal_silence();
private:
CavaBackend(const Json::Value& config);
util::SleeperThread read_thread_;
util::SleeperThread out_thread_;
// Cava API to read audio source
::cava::ptr input_source_{NULL};
struct ::cava::error_s error_{}; // cava errors
struct ::cava::config_params prm_{}; // cava parameters
struct ::cava::audio_raw audio_raw_{}; // cava handled raw audio data(is based on audio_data)
struct ::cava::audio_data audio_data_{}; // cava audio data
struct ::cava::cava_plan* plan_{NULL}; //{new cava_plan{}};
std::chrono::seconds fetch_input_delay_{4};
// Delay to handle audio source
std::chrono::milliseconds frame_time_milsec_{1s};
const Json::Value& config_;
int re_paint_{0};
bool silence_{false};
bool silence_prev_{false};
std::chrono::seconds suspend_silence_delay_{0};
int sleep_counter_{0};
std::string output_{};
// Methods
void invoke();
void execute();
bool isSilence();
void doUpdate(bool force = false);
void loadConfig();
void freeBackend();
// Signal
type_signal_update m_signal_update_;
type_signal_audio_raw_update m_signal_audio_raw_;
type_signal_silence m_signal_silence_;
};
} // namespace waybar::modules::cava
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#ifdef HAVE_LIBCAVA
#include "cavaRaw.hpp"
#include "cava_backend.hpp"
#ifdef HAVE_LIBCAVAGLSL
#include "cavaGLSL.hpp"
#endif
#endif
namespace waybar::modules::cava {
AModule* getModule(const std::string& id, const Json::Value& config) {
#ifdef HAVE_LIBCAVA
const std::shared_ptr<CavaBackend> backend_{waybar::modules::cava::CavaBackend::inst(config)};
switch (backend_->getPrm()->output) {
#ifdef HAVE_LIBCAVAGLSL
case ::cava::output_method::OUTPUT_SDL_GLSL:
return new waybar::modules::cava::CavaGLSL(id, config);
#endif
default:
return new waybar::modules::cava::Cava(id, config);
}
#else
throw std::runtime_error("Unknown module");
#endif
};
} // namespace waybar::modules::cava
+60
View File
@@ -0,0 +1,60 @@
#pragma once
#include <string>
#include "AModule.hpp"
#include "util/command.hpp"
#include "util/json.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
namespace ffi {
extern "C" {
typedef struct wbcffi_module wbcffi_module;
typedef struct {
wbcffi_module* obj;
const char* waybar_version;
GtkContainer* (*get_root_widget)(wbcffi_module*);
void (*queue_update)(wbcffi_module*);
} wbcffi_init_info;
struct wbcffi_config_entry {
const char* key;
const char* value;
};
}
} // namespace ffi
class CFFI : public AModule {
public:
CFFI(const std::string&, const std::string&, const Json::Value&);
virtual ~CFFI();
virtual auto refresh(int signal) -> void override;
virtual auto doAction(const std::string& name) -> void override;
virtual auto update() -> void override;
private:
///
void* cffi_instance_ = nullptr;
typedef void*(InitFn)(const ffi::wbcffi_init_info* init_info,
const ffi::wbcffi_config_entry* config_entries, size_t config_entries_len);
typedef void(DenitFn)(void* instance);
typedef void(RefreshFn)(void* instance, int signal);
typedef void(DoActionFn)(void* instance, const char* name);
typedef void(UpdateFn)(void* instance);
// FFI hooks
struct {
std::function<InitFn> init = nullptr;
std::function<DenitFn> deinit = nullptr;
std::function<RefreshFn> refresh = [](void*, int) {};
std::function<DoActionFn> doAction = [](void*, const char*) {};
std::function<UpdateFn> update = [](void*) {};
} hooks_;
};
} // namespace waybar::modules
+61 -40
View File
@@ -6,67 +6,88 @@
namespace waybar::modules {
const std::string kCalendarPlaceholder = "calendar";
const std::string KTimezonedTimeListPlaceholder = "timezoned_time_list";
enum class WeeksSide {
LEFT,
RIGHT,
HIDDEN,
};
const std::string kCldPlaceholder{"calendar"};
const std::string kTZPlaceholder{"tz_list"};
const std::string kOrdPlaceholder{"ordinal_date"};
enum class CldMode { MONTH, YEAR };
enum class WS { LEFT, RIGHT, HIDDEN };
class Clock final : public ALabel {
public:
Clock(const std::string&, const Json::Value&);
virtual ~Clock() = default;
auto update() -> void override;
auto doAction(const std::string& name) -> void override;
auto doAction(const std::string&) -> void override;
private:
util::SleeperThread thread_;
std::locale locale_;
std::vector<const date::time_zone*> time_zones_;
int current_time_zone_idx_;
bool is_calendar_in_tooltip_;
bool is_timezoned_list_in_tooltip_;
auto first_day_of_week() -> date::weekday;
const date::time_zone* current_timezone();
bool is_timezone_fixed();
auto timezones_text(std::chrono::system_clock::time_point* now) -> std::string;
/*Calendar properties*/
WeeksSide cldWPos_{WeeksSide::HIDDEN};
const std::locale m_locale_;
// tooltip
const std::string m_tlpFmt_;
std::string m_tlpText_{""}; // tooltip text to print
const Glib::RefPtr<Gtk::Label> m_tooltip_; // tooltip as a separate Gtk::Label
bool query_tlp_cb(int, int, bool, const Glib::RefPtr<Gtk::Tooltip>& tooltip);
// Calendar
const bool cldInTooltip_; // calendar in tooltip
/*
0 - calendar.format.months
1 - calendar.format.weekdays
2 - calendar.format.days
3 - calendar.format.today
4 - calendar.format.weeks
5 - tooltip-format
*/
std::map<int, std::string const> fmtMap_;
uint cldMonCols_{3}; // calendar count month columns
int cldWnLen_{3}; // calendar week number length
const int cldMonColLen_{20}; // calendar month column length
WS cldWPos_{WS::HIDDEN}; // calendar week side to print
date::months cldCurrShift_{0}; // calendar months shift
int cldShift_{1}; // calendar months shift factor
date::year_month_day cldYearShift_; // calendar Year mode. Cached ymd
std::string cldYearCached_; // calendar Year mode. Cached calendar
date::year_month cldMonShift_; // calendar Month mode. Cached ym
std::string cldMonCached_; // calendar Month mode. Cached calendar
date::day cldBaseDay_{0}; // calendar Cached day. Is used when today is changing(midnight)
std::string cldText_{""}; // calendar text to print
bool iso8601Calendar_{false}; // whether the calendar is in ISO8601
CldMode cldMode_{CldMode::MONTH};
uint cldMonCols_{3}; // Count of the month in the row
int cldMonColLen_{20}; // Length of the month column
int cldWnLen_{3}; // Length of the week number
date::year_month_day cldYearShift_;
date::year_month cldMonShift_;
date::months cldCurrShift_{0};
date::months cldShift_{0};
std::string cldYearCached_{};
std::string cldMonCached_{};
date::day cldBaseDay_{0};
/*Calendar functions*/
auto get_calendar(const date::zoned_seconds& now, const date::zoned_seconds& wtime)
-> std::string;
/*Clock actions*/
auto get_calendar(const date::year_month_day& today, const date::year_month_day& ymd,
const date::time_zone* tz) -> const std::string;
// get local time zone
auto local_zone() -> const date::time_zone*;
// time zoned time in tooltip
const bool tzInTooltip_; // if need to print time zones text
std::vector<const date::time_zone*> tzList_; // time zones list
int tzCurrIdx_; // current time zone index for tzList_
std::string tzText_{""}; // time zones text to print
std::string tzTooltipFormat_{""}; // optional timezone tooltip format
util::SleeperThread thread_;
// ordinal date in tooltip
const bool ordInTooltip_;
std::string ordText_{""};
auto get_ordinal_date(const date::year_month_day& today) -> std::string;
auto getTZtext(date::sys_seconds now) -> std::string;
auto first_day_of_week() -> date::weekday;
// Module actions
void cldModeSwitch();
void cldShift_up();
void cldShift_down();
void cldShift_reset();
void tz_up();
void tz_down();
// ModuleActionMap
static inline std::map<const std::string, void (waybar::modules::Clock::*const)()> actionMap_{
// Module Action Map
static inline std::map<const std::string, void (waybar::modules::Clock::* const)()> actionMap_{
{"mode", &waybar::modules::Clock::cldModeSwitch},
{"shift_up", &waybar::modules::Clock::cldShift_up},
{"shift_down", &waybar::modules::Clock::cldShift_down},
{"shift_reset", &waybar::modules::Clock::cldShift_reset},
{"tz_up", &waybar::modules::Clock::tz_up},
{"tz_down", &waybar::modules::Clock::tz_down}};
};
} // namespace waybar::modules
-6
View File
@@ -21,12 +21,6 @@ class Cpu : public ALabel {
auto update() -> void override;
private:
double getCpuLoad();
std::tuple<std::vector<uint16_t>, std::string> getCpuUsage();
std::tuple<float, float, float> getCpuFrequency();
std::vector<std::tuple<size_t, size_t>> parseCpuinfo();
std::vector<float> parseCpuFrequencies();
std::vector<std::tuple<size_t, size_t>> prev_times_;
util::SleeperThread thread_;
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <fmt/format.h>
#include <cstdint>
#include <fstream>
#include <numeric>
#include <string>
#include <utility>
#include <vector>
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class CpuFrequency : public ALabel {
public:
CpuFrequency(const std::string&, const Json::Value&);
virtual ~CpuFrequency() = default;
auto update() -> void override;
// This is a static member because it is also used by the cpu module.
static std::tuple<float, float, float> getCpuFrequency();
private:
static std::vector<float> parseCpuFrequencies();
util::SleeperThread thread_;
};
} // namespace waybar::modules
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include <fmt/format.h>
#include <cstdint>
#include <fstream>
#include <numeric>
#include <string>
#include <utility>
#include <vector>
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class CpuUsage : public ALabel {
public:
CpuUsage(const std::string&, const Json::Value&);
virtual ~CpuUsage() = default;
auto update() -> void override;
// This is a static member because it is also used by the cpu module.
static std::tuple<std::vector<uint16_t>, std::string> getCpuUsage(
std::vector<std::tuple<size_t, size_t>>&);
private:
static std::vector<std::tuple<size_t, size_t>> parseCpuinfo();
std::vector<std::tuple<size_t, size_t>> prev_times_;
util::SleeperThread thread_;
};
} // namespace waybar::modules
+5 -1
View File
@@ -14,7 +14,7 @@ namespace waybar::modules {
class Custom : public ALabel {
public:
Custom(const std::string&, const std::string&, const Json::Value&);
Custom(const std::string&, const std::string&, const Json::Value&, const std::string&);
virtual ~Custom();
auto update() -> void override;
void refresh(int /*signal*/) override;
@@ -22,6 +22,7 @@ class Custom : public ALabel {
private:
void delayWorker();
void continuousWorker();
void waitingWorker();
void parseOutputRaw();
void parseOutputJson();
void handleEvent();
@@ -29,10 +30,13 @@ class Custom : public ALabel {
bool handleToggle(GdkEventButton* const& e) override;
const std::string name_;
const std::string output_name_;
std::string text_;
std::string id_;
std::string alt_;
std::string tooltip_;
std::string last_tooltip_markup_;
const bool tooltip_format_enabled_;
std::vector<std::string> class_;
int percentage_;
FILE* fp_;
+3
View File
@@ -20,6 +20,9 @@ class Disk : public ALabel {
private:
util::SleeperThread thread_;
std::string path_;
std::string unit_;
float calc_specific_divisor(const std::string& divisor);
};
} // namespace waybar::modules
+6 -6
View File
@@ -12,23 +12,23 @@ namespace waybar::modules::dwl {
class Tags : public waybar::AModule {
public:
Tags(const std::string &, const waybar::Bar &, const Json::Value &);
Tags(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Tags();
// Handlers for wayland events
void handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused);
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 wl_seat *seat_;
struct zdwl_ipc_manager_v2* status_manager_;
struct wl_seat* seat_;
private:
const waybar::Bar &bar_;
const waybar::Bar& bar_;
Gtk::Box box_;
std::vector<Gtk::Button> buttons_;
struct zdwl_ipc_output_v2 *output_status_;
struct zdwl_ipc_output_v2* output_status_;
};
} /* namespace waybar::modules::dwl */
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include <fmt/format.h>
#include <string>
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "dwl-ipc-unstable-v2-client-protocol.h"
#include "util/json.hpp"
namespace waybar::modules::dwl {
class Window : public AAppIconLabel, public sigc::trackable {
public:
Window(const std::string&, const waybar::Bar&, const Json::Value&);
~Window();
void handle_layout(const uint32_t layout);
void handle_title(const char* title);
void handle_appid(const char* ppid);
void handle_layout_symbol(const char* layout_symbol);
void handle_frame();
struct zdwl_ipc_manager_v2* status_manager_;
private:
const Bar& bar_;
std::string title_;
std::string appid_;
std::string layout_symbol_;
uint32_t layout_;
struct zdwl_ipc_output_v2* output_status_;
};
} // namespace waybar::modules::dwl
+141
View File
@@ -0,0 +1,141 @@
#pragma once
#include <fmt/format.h>
#include <gtkmm/button.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>
#include <map>
#include <memory>
#include <vector>
#include "AModule.hpp"
#include "bar.hpp"
#include "ext-workspace-v1-client-protocol.h"
namespace waybar::modules::ext {
class WorkspaceGroup;
class Workspace;
class WorkspaceManager final : public AModule {
public:
WorkspaceManager(const std::string& id, const waybar::Bar& bar, const Json::Value& config);
~WorkspaceManager() override;
void register_manager(wl_registry* registry, uint32_t name, uint32_t version);
void remove_workspace_group(uint32_t id);
void remove_workspace(uint32_t id);
void set_needs_sorting() { needs_sorting_ = true; }
// wl events
void handle_workspace_group(ext_workspace_group_handle_v1* handle);
void handle_workspace(ext_workspace_handle_v1* handle);
void handle_done();
void handle_finished();
// wl requests
void commit() const;
private:
void update() override;
bool has_button(const Gtk::Button* button);
void sort_workspaces();
void clear_buttons();
void update_buttons();
static uint32_t group_global_id;
static uint32_t workspace_global_id;
uint32_t workspace_name = 0;
bool sort_by_id_ = false;
bool sort_by_name_ = true;
bool sort_by_coordinates_ = false;
bool all_outputs_ = false;
const waybar::Bar& bar_;
Gtk::Box box_;
ext_workspace_manager_v1* ext_manager_ = nullptr;
std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
std::vector<std::unique_ptr<Workspace>> workspaces_;
bool needs_sorting_ = false;
};
class WorkspaceGroup {
public:
WorkspaceGroup(WorkspaceManager& manager, ext_workspace_group_handle_v1* handle, uint32_t id);
~WorkspaceGroup();
u_int32_t id() const { return id_; }
bool has_output(const wl_output* output);
bool has_workspace(const ext_workspace_handle_v1* workspace);
// wl events
void handle_capabilities(uint32_t capabilities);
void handle_output_enter(wl_output* output);
void handle_output_leave(wl_output* output);
void handle_workspace_enter(ext_workspace_handle_v1* handle);
void handle_workspace_leave(ext_workspace_handle_v1* handle);
void handle_removed();
private:
WorkspaceManager& workspaces_manager_;
ext_workspace_group_handle_v1* ext_handle_;
uint32_t id_;
std::vector<wl_output*> outputs_;
std::vector<ext_workspace_handle_v1*> workspaces_;
};
class Workspace {
public:
Workspace(const Json::Value& config, WorkspaceManager& manager, ext_workspace_handle_v1* handle,
uint32_t id, const std::string& name);
~Workspace();
ext_workspace_handle_v1* handle() const { return ext_handle_; }
u_int32_t id() const { return id_; }
std::string& workspace_id() { return workspace_id_; }
std::string& name() { return name_; }
std::vector<u_int32_t>& coordinates() { return coordinates_; }
Gtk::Button& button() { return button_; }
void update();
// wl events
void handle_id(const std::string& id);
void handle_name(const std::string& name);
void handle_coordinates(const std::vector<uint32_t>& coordinates);
void handle_state(uint32_t state);
void handle_capabilities(uint32_t capabilities);
void handle_removed();
// gdk events
bool handle_clicked(const GdkEventButton* button) const;
private:
bool has_state(uint32_t state) const { return (state_ & state) == state; }
std::string icon();
WorkspaceManager& workspace_manager_;
ext_workspace_handle_v1* ext_handle_ = nullptr;
uint32_t id_;
uint32_t state_ = 0;
std::string workspace_id_;
std::string name_;
std::vector<uint32_t> coordinates_;
bool active_only_ = false;
bool ignore_hidden_ = true;
std::string format_;
bool with_icon_ = false;
static std::map<std::string, std::string> icon_map_;
std::string on_click_action_;
std::string on_click_middle_action_;
std::string on_click_right_action_;
Gtk::Button button_;
Gtk::Box content_;
Gtk::Label label_;
};
} // namespace waybar::modules::ext
@@ -0,0 +1,10 @@
#include "ext-workspace-v1-client-protocol.h"
namespace waybar::modules::ext {
void add_registry_listener(void* data);
void add_workspace_listener(ext_workspace_handle_v1* workspace_handle, void* data);
void add_workspace_group_listener(ext_workspace_group_handle_v1* workspace_group_handle,
void* data);
ext_workspace_manager_v1* workspace_manager_bind(wl_registry* registry, uint32_t name,
uint32_t version, void* data);
} // namespace waybar::modules::ext
+12 -12
View File
@@ -17,7 +17,7 @@ namespace waybar::modules {
class Gamemode : public AModule {
public:
Gamemode(const std::string &, const Json::Value &);
Gamemode(const std::string&, const Json::Value&);
virtual ~Gamemode();
auto update() -> void override;
@@ -26,20 +26,20 @@ class Gamemode : public AModule {
const std::string DEFAULT_FORMAT = "{glyph}";
const std::string DEFAULT_FORMAT_ALT = "{glyph} {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,
const Glib::ustring &name_owner);
void disappear(const Glib::RefPtr<Gio::DBus::Connection> &connection, const Glib::ustring &name);
void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection> &connection,
const Glib::ustring &sender_name, const Glib::ustring &object_path,
const Glib::ustring &interface_name, const Glib::ustring &signal_name,
const Glib::VariantContainerBase &parameters);
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name,
const Glib::VariantContainerBase &arguments);
void appear(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& name,
const Glib::ustring& name_owner);
void disappear(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& name);
void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection>& connection,
const Glib::ustring& sender_name, const Glib::ustring& object_path,
const Glib::ustring& interface_name, const Glib::ustring& signal_name,
const Glib::VariantContainerBase& parameters);
void notify_cb(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
const Glib::VariantContainerBase& arguments);
void getData();
bool handleToggle(GdkEventButton *const &) override;
bool handleToggle(GdkEventButton* const&) override;
// Config
std::string format = DEFAULT_FORMAT;
+40
View File
@@ -0,0 +1,40 @@
#pragma once
#include <fmt/format.h>
#include <sys/statvfs.h>
#ifdef WANT_RFKILL
#include "util/rfkill.hpp"
#endif
#include <gps.h>
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Gps : public ALabel {
public:
Gps(const std::string&, const Json::Value&);
virtual ~Gps();
auto update() -> void override;
private:
#ifdef WANT_RFKILL
util::Rfkill rfkill_;
#endif
const std::string getFixModeName() const;
const std::string getFixModeString() const;
const std::string getFixStatusString() const;
util::SleeperThread thread_, gps_thread_;
gps_data_t gps_data_;
std::string state_;
bool hideDisconnected = true;
bool hideNoFix = false;
};
} // namespace waybar::modules
+40 -12
View File
@@ -1,10 +1,13 @@
#pragma once
#include <functional>
#include <atomic>
#include <filesystem>
#include <list>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <thread>
#include <utility>
#include "util/json.hpp"
@@ -16,25 +19,50 @@ class EventHandler {
virtual ~EventHandler() = default;
};
/// If you want to use the Hyprland IPC, simply use IPC::inst() to get the singleton instance.
/// Do not create multiple instances.
class IPC {
protected:
IPC(); // use IPC::inst() instead.
public:
IPC() { startIPC(); }
~IPC();
static IPC& inst();
void registerForIPC(const std::string&, EventHandler*);
void unregisterForIPC(EventHandler*);
void registerForIPC(const std::string& ev, EventHandler* ev_handler);
void unregisterForIPC(EventHandler* handler);
std::string getSocket1Reply(const std::string& rq);
static std::string getSocket1Reply(const std::string& rq);
Json::Value getSocket1JsonReply(const std::string& rq);
static std::filesystem::path getSocketFolder(const char* instanceSig);
/// Dispatch a Hyprland command. Automatically uses the correct protocol
/// (legacy text or Lua-based) depending on the running Hyprland version.
static std::string dispatch(const std::string& dispatcher, const std::string& arg);
/// Build a Lua-format dispatch command string.
static std::string buildLuaDispatch(const std::string& dispatcher, const std::string& arg);
protected:
static std::filesystem::path socketFolder_;
/// Detect whether the running Hyprland uses the Lua-based IPC protocol.
/// Returns true for Hyprland >= 0.54 (Lua config), false for older versions.
static bool isLuaProtocol();
static std::optional<bool> s_luaProtocolDetected_; // cached detection result
private:
void startIPC();
void socketListener();
void parseIPC(const std::string&);
std::mutex callbackMutex;
std::thread ipcThread_;
std::mutex callbackMutex_;
std::mutex socketMutex_;
util::JsonParser parser_;
std::list<std::pair<std::string, EventHandler*>> callbacks;
std::list<std::pair<std::string, EventHandler*>> callbacks_;
int socketfd_ = -1; // the hyprland socket file descriptor
pid_t socketOwnerPid_ = -1;
std::atomic<bool> running_ = true; // the ipcThread will stop running when this is false
};
inline std::unique_ptr<IPC> gIPC;
inline bool modulesReady = false;
}; // namespace waybar::modules::hyprland
+7 -1
View File
@@ -1,5 +1,9 @@
#pragma once
#include <fmt/format.h>
#include <string>
#include "ALabel.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
@@ -26,13 +30,15 @@ class Language : public waybar::ALabel, public EventHandler {
std::string short_description;
};
auto getLayout(const std::string&) -> Layout;
static auto getLayout(const std::string&) -> Layout;
std::mutex mutex_;
const Bar& bar_;
util::JsonParser parser_;
Layout layout_;
IPC& m_ipc;
};
} // namespace waybar::modules::hyprland
+12 -2
View File
@@ -1,5 +1,9 @@
#pragma once
#include <fmt/format.h>
#include <string>
#include "ALabel.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
@@ -10,17 +14,23 @@ namespace waybar::modules::hyprland {
class Submap : public waybar::ALabel, public EventHandler {
public:
Submap(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Submap();
~Submap() override;
auto update() -> void override;
private:
void onEvent(const std::string&) override;
auto parseConfig(const Json::Value&) -> void;
void onEvent(const std::string& ev) override;
std::mutex mutex_;
const Bar& bar_;
util::JsonParser parser_;
std::string submap_;
std::string prev_submap_;
bool always_on_ = false;
std::string default_submap_ = "Default";
IPC& m_ipc;
};
} // namespace waybar::modules::hyprland
+37 -16
View File
@@ -1,46 +1,67 @@
#pragma once
#include <fmt/format.h>
#include "ALabel.hpp"
#include <string>
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
#include "util/json.hpp"
namespace waybar::modules::hyprland {
class Window : public waybar::ALabel, public EventHandler {
class Window : public waybar::AAppIconLabel, public EventHandler {
public:
Window(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Window();
~Window() override;
auto update() -> void override;
private:
struct Workspace {
int id;
int windows;
int id = 0;
int windows = 0;
std::string last_window;
std::string last_window_title;
static auto parse(const Json::Value&) -> Workspace;
static auto parse(const Json::Value& value) -> Workspace;
};
auto getActiveWorkspace(const std::string&) -> Workspace;
auto getActiveWorkspace() -> Workspace;
void onEvent(const std::string&) override;
struct WindowData {
bool floating = false;
int monitor = -1;
std::string class_name;
std::string initial_class_name;
std::string title;
std::string initial_title;
bool fullscreen = false;
bool grouped = false;
static auto parse(const Json::Value&) -> WindowData;
};
static auto getActiveWorkspace(const std::string&) -> Workspace;
static auto getActiveWorkspace() -> Workspace;
void onEvent(const std::string& ev) override;
void queryActiveWorkspace();
void setClass(const std::string&, bool enable);
bool separate_outputs;
bool separateOutputs_ = false;
std::mutex mutex_;
const Bar& bar_;
util::JsonParser parser_;
std::string last_title_;
WindowData windowData_;
Workspace workspace_;
std::string solo_class_;
std::string last_solo_class_;
bool solo_;
bool all_floating_;
bool fullscreen_;
std::string soloClass_;
std::string lastSoloClass_;
bool solo_ = false;
bool allFloating_ = false;
bool swallowing_ = false;
bool fullscreen_ = false;
bool focused_ = false;
IPC& m_ipc;
};
} // namespace waybar::modules::hyprland
+41
View File
@@ -0,0 +1,41 @@
#pragma once
#include <fmt/format.h>
#include <string>
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
namespace waybar::modules::hyprland {
class WindowCount : public waybar::AAppIconLabel, public EventHandler {
public:
WindowCount(const std::string&, const waybar::Bar&, const Json::Value&);
~WindowCount() override;
auto update() -> void override;
private:
struct Workspace {
int id;
int windows;
bool hasfullscreen;
static auto parse(const Json::Value& value) -> Workspace;
};
auto getActiveWorkspace(const std::string&) -> Workspace;
auto getActiveWorkspace() -> Workspace;
void onEvent(const std::string& ev) override;
void queryActiveWorkspace();
void setClass(const std::string&, bool enable);
bool separateOutputs_;
std::mutex mutex_;
const Bar& bar_;
Workspace workspace_;
IPC& m_ipc;
};
} // namespace waybar::modules::hyprland
@@ -0,0 +1,76 @@
#pragma once
#include <gtkmm/button.h>
#include <gtkmm/label.h>
#include <json/value.h>
#include <cstddef>
#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <regex>
#include <string>
#include <variant>
#include <vector>
#include "AModule.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
#include "util/enum.hpp"
#include "util/regex_collection.hpp"
using WindowAddress = std::string;
namespace waybar::modules::hyprland {
class Workspaces;
struct WindowRepr {
std::string address;
std::string window_class;
std::string window_title;
std::string repr_rewrite;
bool isActive = false;
public:
bool empty() const { return address.empty(); }
void setActive(bool value) { isActive = value; }
};
class WindowCreationPayload {
public:
WindowCreationPayload(const std::string& workspace_name, WindowAddress window_address,
WindowRepr window_repr);
WindowCreationPayload(const std::string& workspace_name, WindowAddress window_address,
const std::string& window_class, const std::string& window_title,
bool is_active);
WindowCreationPayload(Json::Value const& client_data);
int incrementTimeSpentUncreated();
bool isEmpty(Workspaces& workspace_manager);
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
WindowRepr repr(Workspaces& workspace_manager);
void setActive(bool value) { m_isActive = value; }
std::string getWorkspaceName() const { return m_workspaceName; }
WindowAddress getAddress() const { return m_windowAddress; }
void moveToWorkspace(std::string& new_workspace_name);
private:
void clearAddr();
void clearWorkspaceName();
using Repr = WindowRepr;
using ClassAndTitle = std::pair<std::string, std::string>;
std::variant<Repr, ClassAndTitle> m_window;
WindowAddress m_windowAddress;
std::string m_workspaceName;
bool m_isActive = false;
int m_timeSpentUncreated = 0;
};
} // namespace waybar::modules::hyprland
+109
View File
@@ -0,0 +1,109 @@
#pragma once
#include <gtkmm/button.h>
#include <gtkmm/label.h>
#include <json/value.h>
#include <cstddef>
#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <regex>
#include <string>
#include <variant>
#include <vector>
#include "AModule.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
#include "modules/hyprland/windowcreationpayload.hpp"
#include "util/enum.hpp"
#include "util/regex_collection.hpp"
using WindowAddress = std::string;
namespace waybar::modules::hyprland {
class Workspaces;
class Workspace {
public:
explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager,
const Json::Value& clients_data = Json::Value::nullRef);
~Workspace();
std::string& selectIcon(std::map<std::string, std::string>& icons_map);
Gtk::Button& button() { return m_button; };
int id() const { return m_id; };
std::string name() const { return m_name; };
std::string output() const { return m_output; };
bool isActive() const { return m_isActive; };
bool isSpecial() const { return m_isSpecial; };
bool isPersistent() const { return m_isPersistentRule || m_isPersistentConfig; };
bool isPersistentConfig() const { return m_isPersistentConfig; };
bool isPersistentRule() const { return m_isPersistentRule; };
bool isVisible() const { return m_isVisible; };
bool isUrgent() const { return m_isUrgent; };
bool handleClicked(GdkEventButton* bt) const;
bool handleEnter(GdkEventCrossing* event);
bool handleLeave(GdkEventCrossing* event);
void startHoverCheck();
void stopHoverCheck();
bool syncHoverClass();
bool pointerInsideButton();
void setActive(bool value = true) { m_isActive = value; };
void setPersistentRule(bool value = true) { m_isPersistentRule = value; };
void setPersistentConfig(bool value = true) { m_isPersistentConfig = value; };
void setUrgent(bool value = true) { m_isUrgent = value; };
void setVisible(bool value = true) { m_isVisible = value; };
void setWindows(uint value) { m_windows = value; };
void setName(std::string const& value) { m_name = value; };
void setOutput(std::string const& value) { m_output = value; };
bool containsWindow(WindowAddress const& addr) const {
return std::ranges::any_of(m_windowMap,
[&addr](const auto& window) { return window.address == addr; });
};
void insertWindow(WindowCreationPayload create_window_payload);
void initializeWindowMap(const Json::Value& clients_data);
void setActiveWindow(WindowAddress const& addr);
bool onWindowOpened(WindowCreationPayload const& create_window_payload);
std::optional<WindowRepr> closeWindow(WindowAddress const& addr);
void update(const std::string& workspace_icon);
private:
Workspaces& m_workspaceManager;
int m_id;
std::string m_name;
std::string m_output;
uint m_windows;
bool m_isActive = false;
bool m_isSpecial = false;
bool m_isPersistentRule = false; // represents the persistent state in hyprland
bool m_isPersistentConfig = false; // represents the persistent state in the Waybar config
bool m_isUrgent = false;
bool m_isVisible = false;
sigc::connection m_hoverCheckConnection;
std::vector<WindowRepr> m_windowMap;
Gtk::Button m_button;
Gtk::Box m_content;
Gtk::Label m_labelBefore;
Gtk::Label m_labelAfter;
bool isEmpty() const;
void updateTaskbar(const std::string& workspace_icon);
bool handleClick(const GdkEventButton* event_button, WindowAddress const& addr) const;
bool shouldSkipWindow(const WindowRepr& window_repr) const;
IPC& m_ipc;
};
} // namespace waybar::modules::hyprland
+196 -44
View File
@@ -1,64 +1,216 @@
#include <gtkmm/button.h>
#include <gtkmm/label.h>
#pragma once
#include <gtkmm/button.h>
#include <gtkmm/enums.h>
#include <gtkmm/label.h>
#include <json/value.h>
#include <sigc++/connection.h>
#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <regex>
#include <string>
#include <vector>
#include "AModule.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
#include "modules/hyprland/windowcreationpayload.hpp"
#include "modules/hyprland/workspace.hpp"
#include "util/enum.hpp"
#include "util/icon_loader.hpp"
#include "util/regex_collection.hpp"
using WindowAddress = std::string;
namespace waybar::modules::hyprland {
struct WorkspaceDto {
int id;
static WorkspaceDto parse(const Json::Value& value);
};
class Workspace {
public:
Workspace(int id);
Workspace(WorkspaceDto dto);
int id() const { return id_; };
int active() const { return active_; };
std::string& select_icon(std::map<std::string, std::string>& icons_map);
void set_active(bool value = true) { active_ = value; };
Gtk::Button& button() { return button_; };
void update(const std::string& format, const std::string& icon);
private:
int id_;
bool active_;
Gtk::Button button_;
Gtk::Box content_;
Gtk::Label label_;
};
class Workspaces;
class Workspaces : public AModule, public EventHandler {
public:
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Workspaces();
~Workspaces() override;
void update() override;
void init();
private:
void onEvent(const std::string&) override;
void sort_workspaces();
void create_workspace(int id);
void remove_workspace(int id);
auto allOutputs() const -> bool { return m_allOutputs; }
auto showSpecial() const -> bool { return m_showSpecial; }
auto activeOnly() const -> bool { return m_activeOnly; }
auto specialVisibleOnly() const -> bool { return m_specialVisibleOnly; }
auto persistentOnly() const -> bool { return m_persistentOnly; }
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
auto enableTaskbar() const -> bool { return m_enableTaskbar; }
auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; }
auto barScroll() const -> bool { return m_barScroll; }
std::string format_;
std::map<std::string, std::string> icons_map_;
bool with_icon_;
int active_workspace_id;
std::vector<std::unique_ptr<Workspace>> workspaces_;
std::vector<int> workspaces_to_create_;
std::vector<int> workspaces_to_remove_;
std::mutex mutex_;
const Bar& bar_;
Gtk::Box box_;
auto getBarOutput() const -> std::string { return m_bar.output->name; }
auto formatBefore() const -> std::string { return m_formatBefore; }
auto formatAfter() const -> std::string { return m_formatAfter; }
auto taskbarFormatBefore() const -> std::string { return m_taskbarFormatBefore; }
auto taskbarFormatAfter() const -> std::string { return m_taskbarFormatAfter; }
auto taskbarIconSize() const -> int { return m_taskbarIconSize; }
auto taskbarOrientation() const -> Gtk::Orientation { return m_taskbarOrientation; }
auto taskbarReverseDirection() const -> bool { return m_taskbarReverseDirection; }
auto onClickWindow() const -> std::string { return m_onClickWindow; }
auto getIgnoredWindows() const -> std::vector<std::regex> { return m_ignoreWindows; }
enum class ActiveWindowPosition { NONE, FIRST, LAST };
auto activeWindowPosition() const -> ActiveWindowPosition { return m_activeWindowPosition; }
std::string getRewrite(const std::string& window_class, const std::string& window_title);
std::string& getWindowSeparator() { return m_formatWindowSeparator; }
bool isWorkspaceIgnored(std::string const& workspace_name);
bool windowRewriteConfigUsesTitle() const { return m_anyWindowRewriteRuleUsesTitle; }
const IconLoader& iconLoader() const { return m_iconLoader; }
private:
void onEvent(const std::string& e) override;
void updateWindowCount();
void sortSpecialCentered();
void sortWorkspaces();
void createWorkspace(Json::Value const& workspace_data,
Json::Value const& clients_data = Json::Value::nullRef);
static Json::Value createMonitorWorkspaceData(std::string const& name,
std::string const& monitor);
void removeWorkspace(std::string const& workspaceString);
void setUrgentWorkspace(std::string const& windowaddress);
// Config
void parseConfig(const Json::Value& config);
auto populateIconsMap(const Json::Value& formatIcons) -> void;
static auto populateBoolConfig(const Json::Value& config, const std::string& key, bool& member)
-> void;
auto populateSortByConfig(const Json::Value& config) -> void;
auto populateIgnoreWorkspacesConfig(const Json::Value& config) -> void;
auto populateFormatWindowSeparatorConfig(const Json::Value& config) -> void;
auto populateWindowRewriteConfig(const Json::Value& config) -> void;
auto populateWorkspaceTaskbarConfig(const Json::Value& config) -> void;
void registerIpc();
// workspace events
void onWorkspaceActivated(std::string const& payload);
void onSpecialWorkspaceActivated(std::string const& payload);
void onWorkspaceDestroyed(std::string const& payload);
void onWorkspaceCreated(std::string const& payload,
Json::Value const& clientsData = Json::Value::nullRef);
void onWorkspaceMoved(std::string const& payload);
void onWorkspaceRenamed(std::string const& payload);
static std::optional<int> parseWorkspaceId(std::string const& workspaceIdStr);
// monitor events
void onMonitorFocused(std::string const& payload);
// window events
void onWindowOpened(std::string const& payload);
void onWindowClosed(std::string const& addr);
void onWindowMoved(std::string const& payload);
void onWindowTitleEvent(std::string const& payload);
void onActiveWindowChanged(WindowAddress const& payload);
void onConfigReloaded();
int windowRewritePriorityFunction(std::string const& window_rule);
// event payload management
template <typename... Args>
static std::string makePayload(Args const&... args);
static std::pair<std::string, std::string> splitDoublePayload(std::string const& payload);
static std::tuple<std::string, std::string, std::string> splitTriplePayload(
std::string const& payload);
// scroll events
bool handleScroll(GdkEventScroll* e) override;
// Update methods
void doUpdate();
void removeWorkspacesToRemove();
void createWorkspacesToCreate();
static std::vector<int> getVisibleWorkspaces();
void updateWorkspaceStates();
bool updateWindowsToCreate();
void extendOrphans(int workspaceId, Json::Value const& clientsJson);
void registerOrphanWindow(WindowCreationPayload create_window_payload);
void initializeWorkspaces();
void setCurrentMonitorId();
void loadPersistentWorkspacesFromConfig(Json::Value const& clientsJson);
void loadPersistentWorkspacesFromWorkspaceRules(const Json::Value& clientsJson);
bool m_allOutputs = false;
bool m_showSpecial = false;
bool m_activeOnly = false;
bool m_specialVisibleOnly = false;
bool m_persistentOnly = false;
bool m_moveToMonitor = false;
bool m_barScroll = false;
Json::Value m_persistentWorkspaceConfig;
// Map for windows stored in workspaces not present in the current bar.
// This happens when the user has multiple monitors (hence, multiple bars)
// and doesn't share windows across bars (a.k.a `all-outputs` = false)
std::map<WindowAddress, WindowRepr, std::less<>> m_orphanWindowMap;
enum class SortMethod { ID, NAME, NUMBER, SPECIAL_CENTERED, DEFAULT };
util::EnumParser<SortMethod> m_enumParser;
SortMethod m_sortBy = SortMethod::DEFAULT;
std::map<std::string, SortMethod> m_sortMap = {{"ID", SortMethod::ID},
{"NAME", SortMethod::NAME},
{"NUMBER", SortMethod::NUMBER},
{"SPECIAL-CENTERED", SortMethod::SPECIAL_CENTERED},
{"DEFAULT", SortMethod::DEFAULT}};
std::string m_formatBefore;
std::string m_formatAfter;
std::map<std::string, std::string> m_iconsMap;
util::RegexCollection m_windowRewriteRules;
bool m_anyWindowRewriteRuleUsesTitle = false;
std::string m_formatWindowSeparator;
bool m_withIcon;
uint64_t m_monitorId;
int m_activeWorkspaceId;
std::string m_activeSpecialWorkspaceName;
std::vector<std::unique_ptr<Workspace>> m_workspaces;
std::vector<std::pair<Json::Value, Json::Value>> m_workspacesToCreate;
std::vector<std::string> m_workspacesToRemove;
std::vector<WindowCreationPayload> m_windowsToCreate;
IconLoader m_iconLoader;
bool m_enableTaskbar = false;
bool m_updateActiveWindow = false;
bool m_taskbarWithIcon = false;
bool m_taskbarWithTitle = false;
std::string m_taskbarFormatBefore;
std::string m_taskbarFormatAfter;
int m_taskbarIconSize = 16;
Gtk::Orientation m_taskbarOrientation = Gtk::ORIENTATION_HORIZONTAL;
bool m_taskbarReverseDirection = false;
util::EnumParser<ActiveWindowPosition> m_activeWindowEnumParser;
ActiveWindowPosition m_activeWindowPosition = ActiveWindowPosition::NONE;
std::map<std::string, ActiveWindowPosition> m_activeWindowPositionMap = {
{"NONE", ActiveWindowPosition::NONE},
{"FIRST", ActiveWindowPosition::FIRST},
{"LAST", ActiveWindowPosition::LAST},
};
std::string m_onClickWindow;
std::string m_currentActiveWindowAddress;
std::vector<std::regex> m_ignoreWorkspaces;
std::vector<std::regex> m_ignoreWindows;
std::mutex m_mutex;
const Bar& m_bar;
Gtk::Box m_box;
sigc::connection m_scrollEventConnection_;
IPC& m_ipc;
};
} // namespace waybar::modules::hyprland
+1 -1
View File
@@ -31,7 +31,7 @@ class Image : public AModule {
std::string path_;
std::string tooltip_;
int size_;
int interval_;
std::chrono::milliseconds interval_;
util::command::res output_;
util::SleeperThread thread_;
+6 -6
View File
@@ -13,7 +13,7 @@ namespace waybar::modules {
class JACK : public ALabel {
public:
JACK(const std::string &, const Json::Value &);
JACK(const std::string&, const Json::Value&);
virtual ~JACK() = default;
auto update() -> void override;
@@ -25,7 +25,7 @@ class JACK : public ALabel {
private:
std::string JACKState();
jack_client_t *client_;
jack_client_t* client_;
jack_nframes_t bufsize_;
jack_nframes_t samplerate_;
unsigned int xruns_;
@@ -38,7 +38,7 @@ class JACK : public ALabel {
} // namespace waybar::modules
int bufSizeCallback(jack_nframes_t size, void *obj);
int sampleRateCallback(jack_nframes_t rate, void *obj);
int xrunCallback(void *obj);
void shutdownCallback(void *obj);
int bufSizeCallback(jack_nframes_t size, void* obj);
int sampleRateCallback(jack_nframes_t rate, void* obj);
int xrunCallback(void* obj);
void shutdownCallback(void* obj);
+5 -2
View File
@@ -3,6 +3,8 @@
#include <fmt/chrono.h>
#include <gtkmm/label.h>
#include <mutex>
#include <set>
#include <unordered_map>
#include "AModule.hpp"
@@ -34,12 +36,13 @@ class KeyboardState : public AModule {
std::string capslock_format_;
std::string scrolllock_format_;
const std::chrono::seconds interval_;
std::string icon_locked_;
std::string icon_unlocked_;
std::unordered_map<std::string, std::vector<std::string>> key_icon_states_;
std::string devices_path_;
struct libinput* libinput_;
std::unordered_map<std::string, struct libinput_device*> libinput_devices_;
std::mutex devices_mutex_; // protects libinput_devices_
std::set<int> binding_keys;
util::SleeperThread libinput_thread_, hotplug_thread_;
};
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <fmt/format.h>
#include <cstdint>
#include <fstream>
#include <numeric>
#include <string>
#include <utility>
#include <vector>
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Load : public ALabel {
public:
Load(const std::string&, const Json::Value&);
virtual ~Load() = default;
auto update() -> void override;
// This is a static member because it is also used by the cpu module.
static std::tuple<double, double, double> getLoad();
private:
util::SleeperThread thread_;
};
} // namespace waybar::modules
+2
View File
@@ -22,6 +22,8 @@ class Memory : public ALabel {
std::unordered_map<std::string, unsigned long> meminfo_;
util::SleeperThread thread_;
std::string unit_;
};
} // namespace waybar::modules
+6 -2
View File
@@ -33,6 +33,7 @@ class MPD : public ALabel {
detail::unique_status status_;
mpd_state state_;
detail::unique_song song_;
std::string ellipsis_;
public:
MPD(const std::string&, const Json::Value&);
@@ -44,7 +45,11 @@ class MPD : public ALabel {
std::string getFilename() const;
void setLabel();
std::string getStateIcon() const;
std::string getOptionIcon(std::string optionName, bool activated) const;
std::string getOptionIcon(const std::string& optionName, bool activated) const;
std::string getArtistStr(bool truncated) const;
std::string getAlbumArtistStr(bool truncated) const;
std::string getAlbumStr(bool truncated) const;
std::string getTitleStr(bool truncated) const;
// GUI-side methods
bool handlePlayPause(GdkEventButton* const&);
@@ -54,7 +59,6 @@ class MPD : public ALabel {
void tryConnect();
void checkErrors(mpd_connection* conn);
void fetchState();
void queryMPD();
inline bool stopped() const { return connection_ && state_ == MPD_STATE_STOP; }
inline bool playing() const { return connection_ && state_ == MPD_STATE_PLAY; }
+2 -2
View File
@@ -148,6 +148,7 @@ class Stopped : public State {
class Disconnected : public State {
Context* const ctx_;
sigc::connection timer_connection_;
int last_interval_;
public:
Disconnected(Context* const ctx) : ctx_{ctx} {}
@@ -162,7 +163,7 @@ class Disconnected : public State {
Disconnected(Disconnected const&) = delete;
Disconnected& operator=(Disconnected const&) = delete;
void arm_timer(int interval) noexcept;
bool arm_timer(int interval) noexcept;
void disarm_timer() noexcept;
bool on_timer();
@@ -196,7 +197,6 @@ class Context {
void tryConnect() const;
void checkErrors(mpd_connection*) const;
void do_update();
void queryMPD() const;
void fetchState() const;
constexpr mpd_state state() const;
void emit() const;
+2 -2
View File
@@ -1,13 +1,14 @@
#pragma once
namespace detail {
using namespace std::literals::chrono_literals;
inline bool Context::is_connected() const { return mpd_module_->connection_ != nullptr; }
inline bool Context::is_playing() const { return mpd_module_->playing(); }
inline bool Context::is_paused() const { return mpd_module_->paused(); }
inline bool Context::is_stopped() const { return mpd_module_->stopped(); }
constexpr inline std::size_t Context::interval() const { return mpd_module_->interval_.count(); }
constexpr inline std::size_t Context::interval() const { return mpd_module_->interval_ / 1s; }
inline void Context::tryConnect() const { mpd_module_->tryConnect(); }
inline unique_connection& Context::connection() { return mpd_module_->connection_; }
constexpr inline mpd_state Context::state() const { return mpd_module_->state_; }
@@ -15,7 +16,6 @@ constexpr inline mpd_state Context::state() const { return mpd_module_->state_;
inline void Context::do_update() { mpd_module_->setLabel(); }
inline void Context::checkErrors(mpd_connection* conn) const { mpd_module_->checkErrors(conn); }
inline void Context::queryMPD() const { mpd_module_->queryMPD(); }
inline void Context::fetchState() const { mpd_module_->fetchState(); }
inline void Context::emit() const { mpd_module_->emit(); }
+3 -2
View File
@@ -66,9 +66,9 @@ class Mpris : public ALabel {
int album_len_;
int title_len_;
int dynamic_len_;
std::string dynamic_separator_;
std::vector<std::string> dynamic_order_;
std::vector<std::string> dynamic_prio_;
std::vector<std::string> dynamic_order_;
std::string dynamic_separator_;
bool truncate_hours_;
bool tooltip_len_limits_;
std::string ellipsis_;
@@ -78,6 +78,7 @@ class Mpris : public ALabel {
PlayerctlPlayerManager* manager;
PlayerctlPlayer* player;
PlayerctlPlayer* last_active_player_ = nullptr;
std::string lastStatus;
std::string lastPlayer;
+34 -23
View File
@@ -9,6 +9,7 @@
#include <sys/epoll.h>
#include <optional>
#include <vector>
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
@@ -16,6 +17,8 @@
#include "util/rfkill.hpp"
#endif
enum ip_addr_pref : uint8_t { IPV4, IPV6, IPV4_6 };
namespace waybar::modules {
class Network : public ALabel {
@@ -25,8 +28,8 @@ class Network : public ALabel {
auto update() -> void override;
private:
static const uint8_t MAX_RETRY = 5;
static const uint8_t EPOLL_MAX = 200;
static const uint8_t MAX_RETRY{5};
static const uint8_t EPOLL_MAX{200};
static int handleEvents(struct nl_msg*, void*);
static int handleEventsDone(struct nl_msg*, void*);
@@ -40,41 +43,49 @@ class Network : public ALabel {
void parseEssid(struct nlattr**);
void parseSignal(struct nlattr**);
void parseFreq(struct nlattr**);
void parseBssid(struct nlattr**);
bool associatedOrJoined(struct nlattr**);
bool checkInterface(std::string name);
bool matchInterface(const std::string& ifname, const std::vector<std::string>& altnames,
std::string& matched) const;
auto getInfo() -> void;
const std::string getNetworkState() const;
void clearIface();
bool wildcardMatch(const std::string& pattern, const std::string& text) const;
std::optional<std::pair<unsigned long long, unsigned long long>> readBandwidthUsage();
int ifid_;
sa_family_t family_;
struct sockaddr_nl nladdr_ = {0};
struct nl_sock* sock_ = nullptr;
struct nl_sock* ev_sock_ = nullptr;
int efd_;
int ev_fd_;
int nl80211_id_;
int ifid_{-1};
ip_addr_pref addr_pref_{ip_addr_pref::IPV4};
struct sockaddr_nl nladdr_{0};
struct nl_sock* sock_{nullptr};
struct nl_sock* ev_sock_{nullptr};
int efd_{-1};
int ev_fd_{-1};
int nl80211_id_{-1};
std::mutex mutex_;
bool want_route_dump_;
bool want_link_dump_;
bool want_addr_dump_;
bool dump_in_progress_;
bool is_p2p_;
bool want_route_dump_{false};
bool want_link_dump_{false};
bool want_addr_dump_{false};
bool dump_in_progress_{false};
bool is_p2p_{false};
unsigned long long bandwidth_down_total_;
unsigned long long bandwidth_up_total_;
unsigned long long bandwidth_down_total_{0};
unsigned long long bandwidth_up_total_{0};
unsigned long long bandwidth_down_prev_{0};
unsigned long long bandwidth_up_prev_{0};
std::chrono::steady_clock::time_point bandwidth_last_sample_time_;
std::string state_;
std::string essid_;
bool carrier_;
std::string bssid_;
bool carrier_{false};
std::string ifname_;
std::string ipaddr_;
std::string ipaddr6_;
std::string gwaddr_;
std::string netmask_;
int cidr_;
std::string netmask6_;
int cidr_{0};
int cidr6_{0};
int32_t signal_strength_dbm_;
uint8_t signal_strength_;
std::string signal_strength_app_;
@@ -83,9 +94,9 @@ class Network : public ALabel {
util::SleeperThread thread_;
util::SleeperThread thread_timer_;
#ifdef WANT_RFKILL
util::Rfkill rfkill_;
util::Rfkill rfkill_{RFKILL_TYPE_WLAN};
#endif
float frequency_;
float frequency_{0};
};
} // namespace waybar::modules
+52
View File
@@ -0,0 +1,52 @@
#pragma once
#include <list>
#include <mutex>
#include <string>
#include <utility>
#include "util/json.hpp"
namespace waybar::modules::niri {
class EventHandler {
public:
virtual void onEvent(const Json::Value& ev) = 0;
virtual ~EventHandler() = default;
};
class IPC {
public:
IPC();
void registerForIPC(const std::string& ev, EventHandler* ev_handler);
void unregisterForIPC(EventHandler* handler);
static Json::Value send(const Json::Value& request);
// The data members are only safe to access while dataMutex_ is locked.
std::lock_guard<std::mutex> lockData() { return std::lock_guard(dataMutex_); }
const std::vector<Json::Value>& workspaces() const { return workspaces_; }
const std::vector<Json::Value>& windows() const { return windows_; }
const std::vector<std::string>& keyboardLayoutNames() const { return keyboardLayoutNames_; }
unsigned keyboardLayoutCurrent() const { return keyboardLayoutCurrent_; }
private:
void startIPC();
static int connectToSocket();
void parseIPC(const std::string&);
std::mutex dataMutex_;
std::vector<Json::Value> workspaces_;
std::vector<Json::Value> windows_;
std::vector<std::string> keyboardLayoutNames_;
unsigned keyboardLayoutCurrent_;
util::JsonParser parser_;
std::mutex callbackMutex_;
std::list<std::pair<std::string, EventHandler*>> callbacks_;
};
inline std::unique_ptr<IPC> gIPC;
}; // namespace waybar::modules::niri
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <string>
#include "ALabel.hpp"
#include "bar.hpp"
#include "modules/niri/backend.hpp"
namespace waybar::modules::niri {
class Language : public ALabel, public EventHandler {
public:
Language(const std::string&, const Bar&, const Json::Value&);
~Language() override;
void update() override;
private:
void updateFromIPC();
void onEvent(const Json::Value& ev) override;
void doUpdate();
struct Layout {
std::string full_name;
std::string short_name;
std::string variant;
std::string short_description;
};
static Layout getLayout(const std::string& fullName);
std::mutex mutex_;
const Bar& bar_;
std::vector<Layout> layouts_;
unsigned current_idx_;
std::string last_short_name_;
};
} // namespace waybar::modules::niri
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <gtkmm/button.h>
#include <json/value.h>
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "modules/niri/backend.hpp"
namespace waybar::modules::niri {
class Window : public AAppIconLabel, public EventHandler {
public:
Window(const std::string&, const Bar&, const Json::Value&);
~Window() override;
void update() override;
private:
void onEvent(const Json::Value& ev) override;
void doUpdate();
void setClass(const std::string& className, bool enable);
const Bar& bar_;
std::string oldAppId_;
};
} // namespace waybar::modules::niri
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <gtkmm/button.h>
#include <json/value.h>
#include "AModule.hpp"
#include "bar.hpp"
#include "modules/niri/backend.hpp"
namespace waybar::modules::niri {
class Workspaces : public AModule, public EventHandler {
public:
Workspaces(const std::string&, const Bar&, const Json::Value&);
~Workspaces() override;
void update() override;
private:
void onEvent(const Json::Value& ev) override;
void doUpdate();
Gtk::Button& addButton(const Json::Value& ws);
std::string getIcon(const std::string& value, const Json::Value& ws);
const Bar& bar_;
Gtk::Box box_;
// Map from niri workspace id to button.
std::unordered_map<uint64_t, Gtk::Button> buttons_;
};
} // namespace waybar::modules::niri
+57
View File
@@ -0,0 +1,57 @@
#pragma once
#include <fmt/format.h>
#include "ALabel.hpp"
#include "giomm/dbusproxy.h"
namespace waybar::modules {
struct Profile {
std::string name;
// Legacy driver field, kept for backward compatibility with the
// `{driver}` format placeholder and with older power-profiles-daemon
// versions that only expose a single `Driver` DBus property.
std::string driver;
std::string cpuDriver;
std::string platformDriver;
Profile(std::string n, std::string d, std::string cd, std::string pd)
: name(std::move(n)),
driver(std::move(d)),
cpuDriver(std::move(cd)),
platformDriver(std::move(pd)) {}
};
class PowerProfilesDaemon : public ALabel {
public:
PowerProfilesDaemon(const std::string&, const Json::Value&);
auto update() -> void override;
void profileChangedCb(const Gio::DBus::Proxy::MapChangedProperties&,
const std::vector<Glib::ustring>&);
void busConnectedCb(Glib::RefPtr<Gio::AsyncResult>& r);
void getAllPropsCb(Glib::RefPtr<Gio::AsyncResult>& r);
void setPropCb(Glib::RefPtr<Gio::AsyncResult>& r);
void populateInitState();
bool handleToggle(GdkEventButton* const& e) override;
private:
// True if we're connected to the dbug interface. False if we're
// not.
bool connected_;
// Look for a profile name in the list of available profiles and
// switch activeProfile_ to it.
void switchToProfile(std::string const&);
// Used to toggle/display the profiles
std::vector<Profile> availableProfiles_;
// Points to the active profile in the profiles list
std::vector<Profile>::iterator activeProfile_;
// Current CSS class applied to the label
std::string currentStyle_;
// Format string
std::string tooltipFormat_;
// DBus Proxy used to track the current active profile
Glib::RefPtr<Gio::DBus::Proxy> powerProfilesProxy_;
};
} // namespace waybar::modules
+41
View File
@@ -0,0 +1,41 @@
#pragma once
#include <string>
#include "gtkmm/box.h"
#include "modules/privacy/privacy_item.hpp"
#include "util/pipewire/pipewire_backend.hpp"
#include "util/pipewire/privacy_node_info.hpp"
using waybar::util::PipewireBackend::PrivacyNodeInfo;
namespace waybar::modules::privacy {
class Privacy : public AModule {
public:
Privacy(const std::string&, const Json::Value&, Gtk::Orientation, const std::string& pos);
auto update() -> void override;
void onPrivacyNodesChanged();
private:
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_out; // Application is outputting audio
std::mutex mutex_;
sigc::connection visibility_conn;
// Config
Gtk::Box box_;
std::vector<PrivacyItem*> modules_;
uint iconSpacing = 4;
uint iconSize = 20;
uint transition_duration = 250;
std::set<std::pair<PrivacyNodeType, std::string>> ignore;
bool ignore_monitor = true;
std::shared_ptr<util::PipewireBackend::PipewireBackend> backend = nullptr;
};
} // namespace waybar::modules::privacy
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#include <json/value.h>
#include <string>
#include "gtkmm/box.h"
#include "gtkmm/image.h"
#include "gtkmm/revealer.h"
#include "util/pipewire/privacy_node_info.hpp"
using waybar::util::PipewireBackend::PrivacyNodeInfo;
using waybar::util::PipewireBackend::PrivacyNodeType;
namespace waybar::modules::privacy {
class PrivacyItem : public Gtk::Revealer {
public:
PrivacyItem(const Json::Value& config_, enum PrivacyNodeType privacy_type_,
std::list<PrivacyNodeInfo*>* nodes, Gtk::Orientation orientation,
const std::string& pos, const uint icon_size, const uint transition_duration);
enum PrivacyNodeType privacy_type;
void set_in_use(bool in_use);
private:
std::list<PrivacyNodeInfo*>* nodes;
sigc::connection signal_conn;
Gtk::Box tooltip_window;
bool init = false;
bool in_use = false;
// Config
std::string iconName = "image-missing-symbolic";
bool tooltip = true;
uint tooltipIconSize = 24;
Gtk::Box box_;
Gtk::Image icon_;
void update_tooltip();
};
} // namespace waybar::modules::privacy
+4 -31
View File
@@ -1,54 +1,27 @@
#pragma once
#include <fmt/format.h>
#include <pulse/pulseaudio.h>
#include <pulse/volume.h>
#include <algorithm>
#include <array>
#include <memory>
#include "ALabel.hpp"
#include "util/audio_backend.hpp"
namespace waybar::modules {
class Pulseaudio : public ALabel {
public:
Pulseaudio(const std::string&, const Json::Value&);
virtual ~Pulseaudio();
virtual ~Pulseaudio() = default;
auto update() -> void override;
private:
static void subscribeCb(pa_context*, pa_subscription_event_type_t, uint32_t, void*);
static void contextStateCb(pa_context*, void*);
static void sinkInfoCb(pa_context*, const pa_sink_info*, int, void*);
static void sourceInfoCb(pa_context*, const pa_source_info* i, int, void* data);
static void serverInfoCb(pa_context*, const pa_server_info*, void*);
static void volumeModifyCb(pa_context*, int, void*);
bool handleScroll(GdkEventScroll* e) override;
const std::vector<std::string> getPulseIcon() const;
pa_threaded_mainloop* mainloop_;
pa_mainloop_api* mainloop_api_;
pa_context* context_;
// SINK
uint32_t sink_idx_{0};
uint16_t volume_;
pa_cvolume pa_volume_;
bool muted_;
std::string port_name_;
std::string form_factor_;
std::string desc_;
std::string monitor_;
std::string current_sink_name_;
bool current_sink_running_;
// SOURCE
uint32_t source_idx_{0};
uint16_t source_volume_;
bool source_muted_;
std::string source_port_name_;
std::string source_desc_;
std::string default_source_name_;
std::shared_ptr<util::AudioBackend> backend = nullptr;
};
} // namespace waybar::modules
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <memory>
#include "ASlider.hpp"
#include "util/audio_backend.hpp"
namespace waybar::modules {
class PulseaudioSlider : public ASlider {
public:
PulseaudioSlider(const std::string&, const Json::Value&);
virtual ~PulseaudioSlider() = default;
void update() override;
void onValueChanged() override;
private:
std::shared_ptr<util::AudioBackend> backend = nullptr;
util::PulseaudioTarget target = util::PulseaudioTarget::Sink;
bool zero_on_mute = true;
bool unmute_on_volume_change = true;
// zero_on_mute and unmute_on_volume_change default to true
// in order to maintain previous behaviour when using a
// config in which these values are undefined
bool previously_muted = false;
};
} // namespace waybar::modules
+12 -11
View File
@@ -10,24 +10,25 @@ namespace waybar::modules::river {
class Layout : public waybar::ALabel {
public:
Layout(const std::string &, const waybar::Bar &, const Json::Value &);
Layout(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Layout();
// Handlers for wayland events
void handle_name(const char *name);
void handle_name(const char* name);
void handle_clear();
void handle_focused_output(struct wl_output *output);
void handle_unfocused_output(struct wl_output *output);
void handle_focused_output(struct wl_output* output);
void handle_unfocused_output(struct wl_output* output);
struct zriver_status_manager_v1 *status_manager_;
struct wl_seat *seat_;
struct zriver_status_manager_v1* status_manager_;
struct wl_seat* seat_;
private:
const waybar::Bar &bar_;
struct wl_output *output_; // stores the output this module belongs to
struct wl_output *focused_output_; // stores the currently focused output
struct zriver_output_status_v1 *output_status_;
struct zriver_seat_status_v1 *seat_status_;
const waybar::Bar& bar_;
std::string name_;
struct wl_output* output_; // stores the output this module belongs to
struct wl_output* focused_output_; // stores the currently focused output
struct zriver_output_status_v1* output_status_;
struct zriver_seat_status_v1* seat_status_;
};
} /* namespace waybar::modules::river */
+6 -6
View File
@@ -10,19 +10,19 @@ namespace waybar::modules::river {
class Mode : public waybar::ALabel {
public:
Mode(const std::string &, const waybar::Bar &, const Json::Value &);
Mode(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Mode();
// Handlers for wayland events
void handle_mode(const char *mode);
void handle_mode(const char* mode);
struct zriver_status_manager_v1 *status_manager_;
struct wl_seat *seat_;
struct zriver_status_manager_v1* status_manager_;
struct wl_seat* seat_;
private:
const waybar::Bar &bar_;
const waybar::Bar& bar_;
std::string mode_;
struct zriver_seat_status_v1 *seat_status_;
struct zriver_seat_status_v1* seat_status_;
};
} /* namespace waybar::modules::river */
+9 -8
View File
@@ -13,26 +13,27 @@ namespace waybar::modules::river {
class Tags : public waybar::AModule {
public:
Tags(const std::string &, const waybar::Bar &, const Json::Value &);
Tags(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Tags();
// Handlers for wayland events
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_show();
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_control_v1 *control_;
struct wl_seat *seat_;
struct zriver_status_manager_v1* status_manager_;
struct zriver_control_v1* control_;
struct wl_seat* seat_;
private:
const waybar::Bar &bar_;
const waybar::Bar& bar_;
Gtk::Box box_;
std::vector<Gtk::Button> buttons_;
struct zriver_output_status_v1 *output_status_;
struct zriver_output_status_v1* output_status_;
};
} /* namespace waybar::modules::river */
+10 -10
View File
@@ -12,22 +12,22 @@ namespace waybar::modules::river {
class Window : public waybar::ALabel {
public:
Window(const std::string &, const waybar::Bar &, const Json::Value &);
Window(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Window();
// Handlers for wayland events
void handle_focused_view(const char *title);
void handle_focused_output(struct wl_output *output);
void handle_unfocused_output(struct wl_output *output);
void handle_focused_view(const char* title);
void handle_focused_output(struct wl_output* output);
void handle_unfocused_output(struct wl_output* output);
struct zriver_status_manager_v1 *status_manager_;
struct wl_seat *seat_;
struct zriver_status_manager_v1* status_manager_;
struct wl_seat* seat_;
private:
const waybar::Bar &bar_;
struct wl_output *output_; // stores the output this module belongs to
struct wl_output *focused_output_; // stores the currently focused output
struct zriver_seat_status_v1 *seat_status_;
const waybar::Bar& bar_;
struct wl_output* output_; // stores the output this module belongs to
struct wl_output* focused_output_; // stores the currently focused output
struct zriver_seat_status_v1* seat_status_;
};
} /* namespace waybar::modules::river */
+5 -5
View File
@@ -11,18 +11,18 @@ namespace waybar::modules {
class Sndio : public ALabel {
public:
Sndio(const std::string &, const Json::Value &);
Sndio(const std::string&, const Json::Value&);
virtual ~Sndio();
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;
bool handleScroll(GdkEventScroll *) override;
bool handleToggle(GdkEventButton *const &) override;
bool handleScroll(GdkEventScroll*) override;
bool handleToggle(GdkEventButton* const&) override;
private:
auto connect_to_sndio() -> void;
util::SleeperThread thread_;
struct sioctl_hdl *hdl_;
struct sioctl_hdl* hdl_;
std::vector<struct pollfd> pfds_;
unsigned int addr_;
unsigned int volume_, old_volume_, maxval_;
+9 -2
View File
@@ -16,7 +16,7 @@ class Host {
public:
Host(const std::size_t id, const Json::Value&, const Bar&,
const std::function<void(std::unique_ptr<Item>&)>&,
const std::function<void(std::unique_ptr<Item>&)>&);
const std::function<void(std::unique_ptr<Item>&)>&, const std::function<void()>&);
~Host();
private:
@@ -28,9 +28,13 @@ class Host {
static void registerHost(GObject*, GAsyncResult*, gpointer);
static void itemRegistered(SnWatcher*, const gchar*, gpointer);
static void itemUnregistered(SnWatcher*, const gchar*, gpointer);
void itemReady(Item&);
void itemInvalidated(Item&);
void removeItem(std::vector<std::unique_ptr<Item>>::iterator);
void clearItems();
std::tuple<std::string, std::string> getBusNameAndObjectPath(const std::string);
void addRegisteredItem(std::string service);
void addRegisteredItem(const std::string& service);
std::vector<std::unique_ptr<Item>> items_;
const std::string bus_name_;
@@ -39,10 +43,13 @@ class Host {
std::size_t watcher_id_;
GCancellable* cancellable_ = nullptr;
SnWatcher* watcher_ = nullptr;
sigc::connection retry_connection_;
unsigned retry_count_ = 0;
const Json::Value& config_;
const Bar& bar_;
const std::function<void(std::unique_ptr<Item>&)> on_add_;
const std::function<void(std::unique_ptr<Item>&)> on_remove_;
const std::function<void()> on_update_;
};
} // namespace waybar::modules::SNI
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <json/json.h>
#include <spdlog/spdlog.h>
#include <string>
#include <unordered_map>
class IconManager {
public:
static IconManager& instance() {
static IconManager instance;
return instance;
}
void setIconsConfig(const Json::Value& icons_config) {
if (icons_config.isObject()) {
for (const auto& key : icons_config.getMemberNames()) {
std::string app_name = key;
const Json::Value& icon_value = icons_config[key];
if (icon_value.isString()) {
std::string icon_path = icon_value.asString();
icons_map_[app_name] = icon_path;
}
}
} else {
spdlog::warn("Invalid icon config format.");
}
}
std::string getIconForApp(const std::string& app_name) const {
auto it = icons_map_.find(app_name);
if (it != icons_map_.end()) {
return it->second;
}
return "";
}
private:
IconManager() = default;
std::unordered_map<std::string, std::string> icons_map_;
};
+28 -3
View File
@@ -11,6 +11,7 @@
#include <libdbusmenu-gtk/dbusmenu-gtk.h>
#include <sigc++/trackable.h>
#include <functional>
#include <set>
#include <string_view>
@@ -25,8 +26,12 @@ struct ToolTip {
class Item : public sigc::trackable {
public:
Item(const std::string&, const std::string&, const Json::Value&, const Bar&);
~Item() = default;
Item(const std::string&, const std::string&, const Json::Value&, const Bar&,
const std::function<void(Item&)>&, const std::function<void(Item&)>&,
const std::function<void()>&);
~Item();
bool isReady() const;
std::string bus_name;
std::string object_path;
@@ -41,9 +46,12 @@ class Item : public sigc::trackable {
std::string title;
std::string icon_name;
Glib::RefPtr<Gdk::Pixbuf> icon_pixmap;
bool has_custom_icon_ = false;
Glib::RefPtr<Gtk::IconTheme> icon_theme;
std::string overlay_icon_name;
Glib::RefPtr<Gdk::Pixbuf> overlay_icon_pixmap;
std::string attention_icon_name;
Glib::RefPtr<Gdk::Pixbuf> attention_icon_pixmap;
std::string attention_movie_name;
std::string icon_theme_path;
std::string menu;
@@ -62,20 +70,30 @@ class Item : public sigc::trackable {
void proxyReady(Glib::RefPtr<Gio::AsyncResult>& result);
void setProperty(const Glib::ustring& name, Glib::VariantBase& value);
void setStatus(const Glib::ustring& value);
void setReady();
void invalidate();
void setCustomIcon(const std::string& id);
void getUpdatedProperties();
void processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& result);
void onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
const Glib::VariantContainerBase& arguments);
void updateImage();
Glib::RefPtr<Gdk::Pixbuf> extractPixBuf(GVariant* variant);
static Glib::RefPtr<Gdk::Pixbuf> extractPixBuf(GVariant* variant);
Glib::RefPtr<Gdk::Pixbuf> getIconPixbuf();
Glib::RefPtr<Gdk::Pixbuf> getAttentionIconPixbuf();
Glib::RefPtr<Gdk::Pixbuf> getOverlayIconPixbuf();
Glib::RefPtr<Gdk::Pixbuf> loadIconFromNameOrFile(const std::string& name, bool log_failure);
static Glib::RefPtr<Gdk::Pixbuf> overlayPixbufs(const Glib::RefPtr<Gdk::Pixbuf>&,
const Glib::RefPtr<Gdk::Pixbuf>&);
Glib::RefPtr<Gdk::Pixbuf> getIconByName(const std::string& name, int size);
double getScaledIconSize();
static void onMenuDestroyed(Item* self, GObject* old_menu_pointer);
void makeMenu();
bool handleClick(GdkEventButton* const& /*ev*/);
bool handleScroll(GdkEventScroll* const&);
bool handleMouseEnter(GdkEventCrossing* const&);
bool handleMouseLeave(GdkEventCrossing* const&);
// smooth scrolling threshold
gdouble scroll_threshold_ = 0;
@@ -83,6 +101,13 @@ class Item : public sigc::trackable {
gdouble distance_scrolled_y_ = 0;
// visibility of items with Status == Passive
bool show_passive_ = false;
bool ready_ = false;
Glib::ustring status_ = "active";
const Bar& bar_;
const std::function<void(Item&)> on_ready_;
const std::function<void(Item&)> on_invalidate_;
const std::function<void()> on_updated_;
Glib::RefPtr<Gio::DBus::Proxy> proxy_;
Glib::RefPtr<Gio::Cancellable> cancellable_;
+1
View File
@@ -19,6 +19,7 @@ class Tray : public AModule {
private:
void onAdd(std::unique_ptr<Item>& item);
void onRemove(std::unique_ptr<Item>& item);
void queueUpdate();
static inline std::size_t nb_hosts_ = 0;
Gtk::Box box_;
+14 -14
View File
@@ -30,27 +30,27 @@ class Watcher {
typedef struct {
GfWatchType type;
Watcher *watcher;
gchar *service;
gchar *bus_name;
gchar *object_path;
Watcher* watcher;
gchar* service;
gchar* bus_name;
gchar* object_path;
guint watch_id;
} GfWatch;
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection> &, Glib::ustring);
static gboolean handleRegisterHost(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 *gfWatchNew(GfWatchType, const gchar *, const gchar *, const gchar *, Watcher *);
static void nameVanished(GDBusConnection *connection, const char *name, gpointer data);
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
static gboolean handleRegisterHost(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* gfWatchNew(GfWatchType, const gchar*, const gchar*, const gchar*, Watcher*);
static void nameVanished(GDBusConnection* connection, const char* name, gpointer data);
static void gfWatchFree(gpointer data);
void updateRegisteredItems(SnWatcher *obj);
void updateRegisteredItems(SnWatcher* obj);
uint32_t bus_name_id_;
GSList *hosts_ = nullptr;
GSList *items_ = nullptr;
SnWatcher *watcher_ = nullptr;
GSList* hosts_ = nullptr;
GSList* items_ = nullptr;
SnWatcher* watcher_ = nullptr;
};
} // namespace waybar::modules::SNI
+1 -1
View File
@@ -37,7 +37,7 @@ class BarIpcClient {
void onModeUpdate(bool visible_by_modifier);
void onUrgencyUpdate(bool visible_by_urgency);
void update();
bool isModuleEnabled(std::string name);
bool isModuleEnabled(const std::string& name);
Bar& bar_;
util::JsonParser parser_;
+11 -9
View File
@@ -12,6 +12,8 @@
#include <string>
#include "ipc.hpp"
#include "util/SafeSignal.hpp"
#include "util/scoped_fd.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules::sway {
@@ -27,25 +29,25 @@ class Ipc {
std::string payload;
};
sigc::signal<void, const struct ipc_response &> signal_event;
sigc::signal<void, const struct ipc_response &> signal_cmd;
::waybar::SafeSignal<const struct ipc_response&> signal_event;
::waybar::SafeSignal<const struct ipc_response&> signal_cmd;
void sendCmd(uint32_t type, const std::string &payload = "");
void subscribe(const std::string &payload);
void sendCmd(uint32_t type, const std::string& payload = "");
void subscribe(const std::string& payload);
void handleEvent();
void setWorker(std::function<void()> &&func);
void setWorker(std::function<void()>&& func);
protected:
static inline const std::string ipc_magic_ = "i3-ipc";
static inline const size_t ipc_header_size_ = ipc_magic_.size() + 8;
const std::string getSocketPath() const;
int open(const std::string &) const;
struct ipc_response send(int fd, uint32_t type, const std::string &payload = "");
int open(const std::string&) const;
struct ipc_response send(int fd, uint32_t type, const std::string& payload = "");
struct ipc_response recv(int fd);
int fd_;
int fd_event_;
util::ScopedFd fd_;
util::ScopedFd fd_event_;
std::mutex mutex_;
util::SleeperThread thread_;
};
+4 -3
View File
@@ -21,7 +21,7 @@ class Language : public ALabel, public sigc::trackable {
auto update() -> void override;
private:
enum class DispayedShortFlag { None = 0, ShortName = 1, ShortDescription = 1 << 1 };
enum class DisplayedShortFlag { None = 0, ShortName = 1, ShortDescription = 1 << 1 };
struct Layout {
std::string full_name;
@@ -47,7 +47,7 @@ class Language : public ALabel, public sigc::trackable {
void onEvent(const struct Ipc::ipc_response&);
void onCmd(const struct Ipc::ipc_response&);
auto set_current_layout(std::string current_layout) -> void;
auto set_current_layout(const std::string& current_layout) -> void;
auto init_layouts_map(const std::vector<std::string>& used_layouts) -> void;
const static std::string XKB_LAYOUT_NAMES_KEY;
@@ -56,8 +56,9 @@ class Language : public ALabel, public sigc::trackable {
Layout layout_;
std::string tooltip_format_ = "";
std::map<std::string, Layout> layouts_map_;
bool hide_single_;
bool is_variant_displayed;
std::byte displayed_short_flag = static_cast<std::byte>(DispayedShortFlag::None);
std::byte displayed_short_flag = static_cast<std::byte>(DisplayedShortFlag::None);
util::JsonParser parser_;
std::mutex mutex_;
+6 -9
View File
@@ -4,7 +4,7 @@
#include <tuple>
#include "AIconLabel.hpp"
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
@@ -12,21 +12,20 @@
namespace waybar::modules::sway {
class Window : public AIconLabel, public sigc::trackable {
class Window : public AAppIconLabel, public sigc::trackable {
public:
Window(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Window() = default;
auto update() -> void override;
private:
void setClass(std::string classname, bool enable);
void setClass(const std::string& classname, bool enable);
void onEvent(const struct Ipc::ipc_response&);
void onCmd(const struct Ipc::ipc_response&);
std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string>
std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string,
std::string>
getFocusedNode(const Json::Value& nodes, std::string& output);
void getTree();
void updateAppIconName();
void updateAppIcon();
const Bar& bar_;
std::string window_;
@@ -37,9 +36,7 @@ class Window : public AIconLabel, public sigc::trackable {
std::string old_app_id_;
std::size_t app_nb_;
std::string shell_;
unsigned app_icon_size_{24};
bool update_app_icon_{true};
std::string app_icon_name_;
std::string marks_;
int floating_count_;
util::JsonParser parser_;
std::mutex mutex_;
+13 -5
View File
@@ -12,37 +12,45 @@
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
#include "util/json.hpp"
#include "util/regex_collection.hpp"
namespace waybar::modules::sway {
class Workspaces : public AModule, public sigc::trackable {
public:
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Workspaces() = default;
~Workspaces() override = default;
auto update() -> void override;
private:
static constexpr std::string_view workspace_switch_cmd_ = "workspace {} \"{}\"";
static constexpr std::string_view workspace_switch_number_cmd_ = "workspace {} number {}";
static constexpr std::string_view persistent_workspace_switch_cmd_ =
R"(workspace {} "{}"; move workspace to output "{}"; workspace {} "{}")";
static int convertWorkspaceNameToNum(std::string name);
static int convertWorkspaceNameToNum(const std::string& name);
static int windowRewritePriorityFunction(std::string const& window_rule);
void onCmd(const struct Ipc::ipc_response&);
void onEvent(const struct Ipc::ipc_response&);
bool filterButtons();
static bool hasFlag(const Json::Value&, const std::string&);
void updateWindows(const Json::Value&, std::string&);
Gtk::Button& addButton(const Json::Value&);
void onButtonReady(const Json::Value&, Gtk::Button&);
std::string getIcon(const std::string&, const Json::Value&);
const std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const;
std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const;
uint16_t getWorkspaceIndex(const std::string& name) const;
std::string trimWorkspaceName(std::string);
bool handleScroll(GdkEventScroll*) override;
static std::string trimWorkspaceName(const std::string&);
bool handleScroll(GdkEventScroll* /*unused*/) override;
const Bar& bar_;
std::vector<Json::Value> workspaces_;
std::vector<std::string> high_priority_named_;
std::vector<std::string> workspaces_order_;
Gtk::Box box_;
std::string m_formatWindowSeparator;
util::RegexCollection m_windowRewriteRules;
util::JsonParser parser_;
std::unordered_map<std::string, Gtk::Button> buttons_;
std::mutex mutex_;

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