Compare commits
222 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6a9b63189 | ||
|
|
7dfc72003f | ||
|
|
1c1a39f597 | ||
|
|
121dcc645f | ||
|
|
8555456050 | ||
|
|
22dc87934a | ||
|
|
335a736eed | ||
|
|
1149e51f72 | ||
|
|
9012cebbf2 | ||
|
|
6425bd2fe0 | ||
|
|
241938a86d | ||
|
|
f511e61832 | ||
|
|
b9b89cce7e | ||
|
|
e9a66d68b7 | ||
|
|
b37d0df89b | ||
|
|
67422eea36 | ||
|
|
e46f66b468 | ||
|
|
1f0ce1a5d9 | ||
|
|
95b0647c91 | ||
|
|
9ef8faf9b1 | ||
|
|
7d8c1494d7 | ||
|
|
33f8a02fb5 | ||
|
|
1618ee78b7 | ||
|
|
efab1daa7e | ||
|
|
9a305b2d73 | ||
|
|
799fce0dc6 | ||
|
|
68dfd6aa3a | ||
|
|
dd1de3efbf | ||
|
|
521dac8086 | ||
|
|
ad7d4eb07d | ||
|
|
a459d8a9b3 | ||
|
|
4aee5977d6 | ||
|
|
f2085fcd92 | ||
|
|
c47d75ceda | ||
|
|
9ecdbcc7bc | ||
|
|
dafe49d28c | ||
|
|
2d33c20231 | ||
|
|
5963bf6ace | ||
|
|
dab1493644 | ||
|
|
acc911737d | ||
|
|
2d614c68f5 | ||
|
|
d0cab2a367 | ||
|
|
7576611782 | ||
|
|
ed65d9cdbd | ||
|
|
dbb887b4a9 | ||
|
|
06f4028697 | ||
|
|
3413b70413 | ||
|
|
6a8b510db8 | ||
|
|
f598e348c4 | ||
|
|
6dd2cfba34 | ||
|
|
ae748b2644 | ||
|
|
a0b63d6b1e | ||
|
|
89e85db790 | ||
|
|
a73669be6a | ||
|
|
8c57756556 | ||
|
|
b8afde043c | ||
|
|
eefd6e8336 | ||
|
|
6829ed1bb4 | ||
|
|
7d5577a2ed | ||
|
|
a41225c4e0 | ||
|
|
a0d2d95b41 | ||
|
|
e14a3b8687 | ||
|
|
846842be80 | ||
|
|
e845db84ad | ||
|
|
193040c41e | ||
|
|
871f9a1269 | ||
|
|
5319cb6e10 | ||
|
|
208928ded5 | ||
|
|
4d7eb3bd15 | ||
|
|
6b73e2aa58 | ||
|
|
6ddd283d0f | ||
|
|
e70a67d958 | ||
|
|
67c0c9a66c | ||
|
|
42741c963e | ||
|
|
9d316de15a | ||
|
|
ecbcf242d5 | ||
|
|
fd3710d869 | ||
|
|
11d7ca1d73 | ||
|
|
c3779dd16e | ||
|
|
442a4b0da0 | ||
|
|
c9e129cda2 | ||
|
|
64d7fae03a | ||
|
|
44d8245605 | ||
|
|
93daf089b5 | ||
|
|
7645ae1907 | ||
|
|
3d496c2200 | ||
|
|
ff9b6c9469 | ||
|
|
05b97e9ec2 | ||
|
|
8f32d102ae | ||
|
|
5a380da3bb | ||
|
|
5e44cb6ba2 | ||
|
|
fad858782c | ||
|
|
5246ab15cb | ||
|
|
bbb7fb0c82 | ||
|
|
c59264d6b4 | ||
|
|
a3774dc586 | ||
|
|
ee652677a6 | ||
|
|
ceeb5bf8bd | ||
|
|
c995bafa7a | ||
|
|
f8340d88be | ||
|
|
592d5645a5 | ||
|
|
f9a7ecf3a9 | ||
|
|
387e54498e | ||
|
|
fad43d4b16 | ||
|
|
8d057e6f96 | ||
|
|
b2e88347b3 | ||
|
|
1af02e0a67 | ||
|
|
30cc88a4c5 | ||
|
|
32d326ca4a | ||
|
|
ae92d7d186 | ||
|
|
c16e791cdc | ||
|
|
fbd62e0071 | ||
|
|
1eb0777799 | ||
|
|
58e506a675 | ||
|
|
1b98a04c93 | ||
|
|
4c0347d9f2 | ||
|
|
9a3238c20b | ||
|
|
6e48b236a1 | ||
|
|
16f6d9dfa0 | ||
|
|
d37954322a | ||
|
|
258ab8b147 | ||
|
|
6663ca3d75 | ||
|
|
adbc9d95de | ||
|
|
fbe544984c | ||
|
|
b9d5912a4f | ||
|
|
3e2761e81f | ||
|
|
6997b34a81 | ||
|
|
5960e8f1ee | ||
|
|
81ffeebfb1 | ||
|
|
f14fe96e19 | ||
|
|
954bea36f4 | ||
|
|
388c024298 | ||
|
|
9b8adc1951 | ||
|
|
bf371f70d1 | ||
|
|
7c28ffc856 | ||
|
|
14820e5d18 | ||
|
|
80a34eec81 | ||
|
|
d5203e5b37 | ||
|
|
91b6629103 | ||
|
|
93d66a9258 | ||
|
|
8d7341da6e | ||
|
|
d1602e383c | ||
|
|
c45f6681b3 | ||
|
|
dce6a98f38 | ||
|
|
982ffde002 | ||
|
|
888adb57ec | ||
|
|
c36fe3a004 | ||
|
|
729564cc27 | ||
|
|
4d32991bee | ||
|
|
69736d68aa | ||
|
|
28a2d15fef | ||
|
|
a90e275d5e | ||
|
|
fc67558717 | ||
|
|
196b400abf | ||
|
|
05a2af2d7c | ||
|
|
1ff4464b2f | ||
|
|
60611e9c2b | ||
|
|
79cf33b9f1 | ||
|
|
b8630968b2 | ||
|
|
2fee12d930 | ||
|
|
3ae2fe3272 | ||
|
|
2b8c92e8fd | ||
|
|
8ce64ea784 | ||
|
|
8ea2626de8 | ||
|
|
65ba449460 | ||
|
|
cbc12e5443 | ||
|
|
587bd0cd62 | ||
|
|
309edd0585 | ||
|
|
2837b72064 | ||
|
|
38ef38b72f | ||
|
|
6c3565c520 | ||
|
|
9bb2c01a44 | ||
|
|
09873f0ed9 | ||
|
|
c9e1899594 | ||
|
|
b405dc436c | ||
|
|
4a6c1269fb | ||
|
|
44ac6b8044 | ||
|
|
80de22a159 | ||
|
|
04b39ea64e | ||
|
|
116aa5cdbd | ||
|
|
9c49f46b01 | ||
|
|
f7ff005dd5 | ||
|
|
d40ccd0da8 | ||
|
|
6f66af9ab9 | ||
|
|
2d27e484c7 | ||
|
|
a77ccf4bd1 | ||
|
|
4cb8efbecc | ||
|
|
8fc4187713 | ||
|
|
ce076927f3 | ||
|
|
8eb614f69e | ||
|
|
347dd1c799 | ||
|
|
82b7e4ea01 | ||
|
|
d7d4a6c632 | ||
|
|
a18b41911d | ||
|
|
52309615c1 | ||
|
|
65dfabc430 | ||
|
|
936937ec78 | ||
|
|
e163dd8216 | ||
|
|
06a9f98878 | ||
|
|
b665843085 | ||
|
|
ee4fbc58f7 | ||
|
|
3081b0c576 | ||
|
|
b7a527b122 | ||
|
|
54a6668846 | ||
|
|
ed0f7453c9 | ||
|
|
19fe929d1f | ||
|
|
392e863e6d | ||
|
|
2ff347f9a8 | ||
|
|
1d8331d0c5 | ||
|
|
718db71638 | ||
|
|
0a28b50a8c | ||
|
|
70bc318a01 | ||
|
|
22817089db | ||
|
|
aecd80702e | ||
|
|
abd7a0cf25 | ||
|
|
e30fba0b8f | ||
|
|
b5ea14c896 | ||
|
|
5b33a5917c | ||
|
|
66b71cc857 | ||
|
|
c8237437d2 | ||
|
|
57544fe694 | ||
|
|
bad6cfae6f |
38
.github/workflows/freebsd.yml
vendored
38
.github/workflows/freebsd.yml
vendored
@@ -1,6 +1,6 @@
|
||||
name: freebsd
|
||||
|
||||
on: [ push, pull_request ]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
clang:
|
||||
@@ -9,21 +9,21 @@ jobs:
|
||||
# https://github.com/actions/virtual-environments/issues/4060 - for lack of VirtualBox on MacOS 11 runners
|
||||
runs-on: macos-12
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test in FreeBSD VM
|
||||
uses: vmactions/freebsd-vm@v0
|
||||
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
|
||||
run: |
|
||||
meson build -Dman-pages=enabled
|
||||
ninja -C build
|
||||
meson test -C build --no-rebuild --print-errorlogs --suite waybar
|
||||
- uses: actions/checkout@v3
|
||||
- name: Test in FreeBSD VM
|
||||
uses: cross-platform-actions/action@v0.19.1
|
||||
timeout-minutes: 180
|
||||
with:
|
||||
operating_system: freebsd
|
||||
version: "13.2"
|
||||
environment_variables: CPPFLAGS=-isystem/usr/local/include LDFLAGS=-L/usr/local/lib
|
||||
run: |
|
||||
sudo sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
|
||||
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 pulseaudio scdoc sndio spdlog wayland-protocols upower \
|
||||
libinotify
|
||||
meson build -Dman-pages=enabled
|
||||
ninja -C build
|
||||
meson test -C build --no-rebuild --print-errorlogs --suite waybar
|
||||
|
||||
6
.github/workflows/lint.yml
vendored
6
.github/workflows/lint.yml
vendored
@@ -7,8 +7,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: DoozyX/clang-format-lint-action@v0.13
|
||||
- uses: DoozyX/clang-format-lint-action@v0.16.2
|
||||
with:
|
||||
source: '.'
|
||||
extensions: 'h,cpp,c'
|
||||
clangFormatVersion: 12
|
||||
extensions: 'hpp,h,cpp,c'
|
||||
clangFormatVersion: 16
|
||||
|
||||
76
flake.lock
generated
76
flake.lock
generated
@@ -2,15 +2,15 @@
|
||||
"nodes": {
|
||||
"devshell": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
"nixpkgs": "nixpkgs",
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1676293499,
|
||||
"narHash": "sha256-uIOTlTxvrXxpKeTvwBI1JGDGtCxMXE3BI0LFwoQMhiQ=",
|
||||
"lastModified": 1692523566,
|
||||
"narHash": "sha256-VDJDihK6jNebVw9y3qKCVD6+6QaC/x8kxZzL4MaIPPY=",
|
||||
"owner": "numtide",
|
||||
"repo": "devshell",
|
||||
"rev": "71e3022e3ab20bbf1342640547ef5bc14fb43bf4",
|
||||
"rev": "d208c58e2f7afef838add5f18a9936b12a71d695",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -36,27 +36,15 @@
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1642700792,
|
||||
"narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "846b2ae0fc4cc943637d3d1def4454213e203cba",
|
||||
"type": "github"
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"locked": {
|
||||
"lastModified": 1676283394,
|
||||
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
|
||||
"lastModified": 1689068808,
|
||||
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
|
||||
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -67,11 +55,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1643381941,
|
||||
"narHash": "sha256-pHTwvnN4tTsEKkWlXQ8JMY423epos8wUOhthpwJjtpc=",
|
||||
"lastModified": 1677383253,
|
||||
"narHash": "sha256-UfpzWfSxkfXHnb4boXZNaKsAcUrZT9Hw+tao1oZxd08=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5efc8ca954272c4376ac929f4c5ffefcc20551d5",
|
||||
"rev": "9952d6bc395f5841262b006fbace8dd7e143b634",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -83,11 +71,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1676300157,
|
||||
"narHash": "sha256-1HjRzfp6LOLfcj/HJHdVKWAkX9QRAouoh6AjzJiIerU=",
|
||||
"lastModified": 1692638711,
|
||||
"narHash": "sha256-J0LgSFgJVGCC1+j5R2QndadWI1oumusg6hCtYAzLID4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "545c7a31e5dedea4a6d372712a18e00ce097d462",
|
||||
"rev": "91a22f76cd1716f9d0149e8a5c68424bb691de15",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -101,9 +89,39 @@
|
||||
"inputs": {
|
||||
"devshell": "devshell",
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
||||
11
flake.nix
11
flake.nix
@@ -16,6 +16,7 @@
|
||||
inherit (nixpkgs) lib;
|
||||
genSystems = lib.genAttrs [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
|
||||
pkgsFor = genSystems (system:
|
||||
@@ -47,17 +48,12 @@
|
||||
let pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
|
||||
overlays = [ devshell.overlay ];
|
||||
overlays = [ devshell.overlays.default ];
|
||||
};
|
||||
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; [
|
||||
clang-tools
|
||||
gdb
|
||||
@@ -79,6 +75,7 @@
|
||||
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"; }
|
||||
|
||||
@@ -36,8 +36,11 @@ class AModule : public IModule {
|
||||
|
||||
virtual bool handleToggle(GdkEventButton *const &ev);
|
||||
virtual bool handleScroll(GdkEventScroll *);
|
||||
virtual bool handleRelease(GdkEventButton *const &ev);
|
||||
|
||||
private:
|
||||
bool handleUserEvent(GdkEventButton *const &ev);
|
||||
|
||||
std::vector<int> pid_;
|
||||
gdouble distance_scrolled_y_;
|
||||
gdouble distance_scrolled_x_;
|
||||
|
||||
19
include/ASlider.hpp
Normal file
19
include/ASlider.hpp
Normal 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
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "AModule.hpp"
|
||||
#include "group.hpp"
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
|
||||
namespace waybar {
|
||||
@@ -91,6 +92,9 @@ class Bar {
|
||||
bool vertical = false;
|
||||
Gtk::Window window;
|
||||
|
||||
int x_global;
|
||||
int y_global;
|
||||
|
||||
#ifdef HAVE_SWAY
|
||||
std::string bar_id;
|
||||
#endif
|
||||
@@ -98,15 +102,20 @@ class Bar {
|
||||
private:
|
||||
void onMap(GdkEventAny *);
|
||||
auto setupWidgets() -> void;
|
||||
void getModules(const Factory &, const std::string &, Gtk::Box *);
|
||||
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 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};
|
||||
|
||||
struct bar_margins margins_;
|
||||
|
||||
std::unique_ptr<BarSurface> surface_impl_;
|
||||
Gtk::Box left_;
|
||||
Gtk::Box center_;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "bar.hpp"
|
||||
#include "config.hpp"
|
||||
#include "util/portal.hpp"
|
||||
|
||||
struct zwlr_layer_shell_v1;
|
||||
struct zwp_idle_inhibitor_v1;
|
||||
@@ -33,7 +34,7 @@ class Client {
|
||||
|
||||
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;
|
||||
@@ -52,6 +53,7 @@ class Client {
|
||||
|
||||
Glib::RefPtr<Gtk::StyleContext> style_context_;
|
||||
Glib::RefPtr<Gtk::CssProvider> css_provider_;
|
||||
std::unique_ptr<Portal> portal;
|
||||
std::list<struct waybar_output> outputs_;
|
||||
};
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
#endif
|
||||
#if defined(HAVE_CPU_LINUX) || defined(HAVE_CPU_BSD)
|
||||
#include "modules/cpu.hpp"
|
||||
#include "modules/cpu_frequency.hpp"
|
||||
#include "modules/cpu_usage.hpp"
|
||||
#include "modules/load.hpp"
|
||||
#endif
|
||||
#include "modules/idle_inhibitor.hpp"
|
||||
#if defined(HAVE_MEMORY_LINUX) || defined(HAVE_MEMORY_BSD)
|
||||
|
||||
@@ -5,18 +5,31 @@
|
||||
#include <json/json.h>
|
||||
|
||||
#include "AModule.hpp"
|
||||
#include "bar.hpp"
|
||||
#include "factory.hpp"
|
||||
#include "gtkmm/revealer.h"
|
||||
|
||||
namespace waybar {
|
||||
|
||||
class Group : public AModule {
|
||||
public:
|
||||
Group(const std::string&, const std::string&, const Json::Value&, bool);
|
||||
~Group() = default;
|
||||
virtual ~Group() = default;
|
||||
auto update() -> void override;
|
||||
operator Gtk::Widget&() override;
|
||||
|
||||
virtual Gtk::Box& getBox();
|
||||
void addWidget(Gtk::Widget& widget);
|
||||
|
||||
bool handleMouseHover(GdkEventCrossing* const& e);
|
||||
|
||||
protected:
|
||||
Gtk::Box box;
|
||||
Gtk::Box revealer_box;
|
||||
Gtk::Revealer revealer;
|
||||
bool is_first_widget = true;
|
||||
bool is_drawer = false;
|
||||
std::string add_class_to_drawer_children;
|
||||
|
||||
void addHoverHandlerTo(Gtk::Widget& widget);
|
||||
};
|
||||
|
||||
} // namespace waybar
|
||||
|
||||
@@ -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();
|
||||
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;
|
||||
|
||||
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
include/modules/backlight_slider.hpp
Normal file
24
include/modules/backlight_slider.hpp
Normal 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
|
||||
@@ -59,7 +59,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 +69,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_;
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
#include "ALabel.hpp"
|
||||
#include "util/sleeper_thread.hpp"
|
||||
|
||||
namespace cava {
|
||||
extern "C" {
|
||||
#include <cava/common.h>
|
||||
}
|
||||
} // namespace cava
|
||||
|
||||
namespace waybar::modules {
|
||||
using namespace std::literals::chrono_literals;
|
||||
@@ -21,13 +23,13 @@ class Cava final : public ALabel {
|
||||
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{}};
|
||||
struct cava::error_s error_ {}; // cava errors
|
||||
struct cava::config_params prm_ {}; // cava parameters
|
||||
struct cava::audio_raw audio_raw_ {}; // cava handled raw audio data(is based on audio_data)
|
||||
struct cava::audio_data audio_data_ {}; // cava audio data
|
||||
struct cava::cava_plan* plan_; //{new cava_plan{}};
|
||||
// Cava API to read audio source
|
||||
ptr input_source_;
|
||||
cava::ptr input_source_;
|
||||
// Delay to handle audio source
|
||||
std::chrono::milliseconds frame_time_milsec_{1s};
|
||||
// Text to display
|
||||
@@ -36,6 +38,7 @@ class Cava final : public ALabel {
|
||||
std::chrono::seconds fetch_input_delay_{4};
|
||||
std::chrono::seconds suspend_silence_delay_{0};
|
||||
bool silence_{false};
|
||||
bool hide_on_silence_{false};
|
||||
int sleep_counter_{0};
|
||||
// Cava method
|
||||
void pause_resume();
|
||||
|
||||
@@ -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
include/modules/cpu_frequency.hpp
Normal file
32
include/modules/cpu_frequency.hpp
Normal 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
include/modules/cpu_usage.hpp
Normal file
35
include/modules/cpu_usage.hpp
Normal 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
|
||||
@@ -22,6 +22,7 @@ class Custom : public ALabel {
|
||||
private:
|
||||
void delayWorker();
|
||||
void continuousWorker();
|
||||
void waitingWorker();
|
||||
void parseOutputRaw();
|
||||
void parseOutputJson();
|
||||
void handleEvent();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include "util/json.hpp"
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ALabel.hpp"
|
||||
#include "bar.hpp"
|
||||
#include "modules/hyprland/backend.hpp"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ALabel.hpp"
|
||||
#include "bar.hpp"
|
||||
#include "modules/hyprland/backend.hpp"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "AAppIconLabel.hpp"
|
||||
#include "bar.hpp"
|
||||
#include "modules/hyprland/backend.hpp"
|
||||
@@ -10,7 +14,7 @@ namespace waybar::modules::hyprland {
|
||||
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;
|
||||
|
||||
|
||||
@@ -1,17 +1,67 @@
|
||||
#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;
|
||||
|
||||
class WindowCreationPayload {
|
||||
public:
|
||||
WindowCreationPayload(std::string workspace_name, WindowAddress window_address,
|
||||
std::string window_repr);
|
||||
WindowCreationPayload(std::string workspace_name, WindowAddress window_address,
|
||||
std::string window_class, std::string window_title);
|
||||
WindowCreationPayload(Json::Value const& client_data);
|
||||
|
||||
int increment_time_spent_uncreated();
|
||||
bool is_empty(Workspaces& workspace_manager);
|
||||
bool repr_is_ready() const { return std::holds_alternative<Repr>(window_); }
|
||||
std::string repr(Workspaces& workspace_manager);
|
||||
|
||||
std::string workspace_name() const { return workspace_name_; }
|
||||
WindowAddress addr() const { return window_address_; }
|
||||
|
||||
void move_to_worksace(std::string& new_workspace_name);
|
||||
|
||||
private:
|
||||
void clear_addr();
|
||||
void clear_workspace_name();
|
||||
|
||||
using Repr = std::string;
|
||||
using ClassAndTitle = std::pair<std::string, std::string>;
|
||||
std::variant<Repr, ClassAndTitle> window_;
|
||||
|
||||
WindowAddress window_address_;
|
||||
std::string workspace_name_;
|
||||
|
||||
int time_spent_uncreated_ = 0;
|
||||
};
|
||||
|
||||
class Workspace {
|
||||
public:
|
||||
Workspace(const Json::Value& workspace_data);
|
||||
explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager,
|
||||
const Json::Value& clients_data = Json::Value::nullRef);
|
||||
std::string& select_icon(std::map<std::string, std::string>& icons_map);
|
||||
Gtk::Button& button() { return button_; };
|
||||
|
||||
@@ -21,16 +71,30 @@ class Workspace {
|
||||
bool active() const { return active_; };
|
||||
bool is_special() const { return is_special_; };
|
||||
bool is_persistent() const { return is_persistent_; };
|
||||
bool is_visible() const { return is_visible_; };
|
||||
bool is_empty() const { return windows_ == 0; };
|
||||
bool is_urgent() const { return is_urgent_; };
|
||||
|
||||
auto handle_clicked(GdkEventButton* bt) -> bool;
|
||||
bool handle_clicked(GdkEventButton* bt) const;
|
||||
void set_active(bool value = true) { active_ = value; };
|
||||
void set_persistent(bool value = true) { is_persistent_ = value; };
|
||||
void set_urgent(bool value = true) { is_urgent_ = value; };
|
||||
void set_visible(bool value = true) { is_visible_ = value; };
|
||||
void set_windows(uint value) { windows_ = value; };
|
||||
void set_name(std::string const& value) { name_ = value; };
|
||||
bool contains_window(WindowAddress const& addr) const { return window_map_.contains(addr); }
|
||||
void insert_window(WindowCreationPayload create_window_paylod);
|
||||
std::string remove_window(WindowAddress const& addr);
|
||||
void initialize_window_map(const Json::Value& clients_data);
|
||||
|
||||
bool on_window_opened(WindowCreationPayload const& create_window_paylod);
|
||||
std::optional<std::string> close_window(WindowAddress const& addr);
|
||||
|
||||
void update(const std::string& format, const std::string& icon);
|
||||
|
||||
private:
|
||||
Workspaces& workspace_manager_;
|
||||
|
||||
int id_;
|
||||
std::string name_;
|
||||
std::string output_;
|
||||
@@ -38,6 +102,10 @@ class Workspace {
|
||||
bool active_ = false;
|
||||
bool is_special_ = false;
|
||||
bool is_persistent_ = false;
|
||||
bool is_urgent_ = false;
|
||||
bool is_visible_ = false;
|
||||
|
||||
std::map<WindowAddress, std::string> window_map_;
|
||||
|
||||
Gtk::Button button_;
|
||||
Gtk::Box content_;
|
||||
@@ -53,18 +121,57 @@ class Workspaces : public AModule, public EventHandler {
|
||||
|
||||
auto all_outputs() const -> bool { return all_outputs_; }
|
||||
auto show_special() const -> bool { return show_special_; }
|
||||
auto active_only() const -> bool { return active_only_; }
|
||||
|
||||
auto get_bar_output() const -> std::string { return bar_.output->name; }
|
||||
|
||||
std::string get_rewrite(std::string window_class, std::string window_title);
|
||||
std::string& get_window_separator() { return format_window_separator_; }
|
||||
bool is_workspace_ignored(std::string const& workspace_name);
|
||||
|
||||
bool window_rewrite_config_uses_title() const { return any_window_rewrite_rule_uses_title_; }
|
||||
|
||||
private:
|
||||
void onEvent(const std::string&) override;
|
||||
void onEvent(const std::string& e) override;
|
||||
void update_window_count();
|
||||
void sort_workspaces();
|
||||
void create_workspace(Json::Value& value);
|
||||
void remove_workspace(std::string name);
|
||||
void create_workspace(Json::Value const& workspace_data,
|
||||
Json::Value const& clients_data = Json::Value::nullRef);
|
||||
void remove_workspace(std::string const& name);
|
||||
void set_urgent_workspace(std::string const& windowaddress);
|
||||
void parse_config(const Json::Value& config);
|
||||
void register_ipc();
|
||||
|
||||
// workspace events
|
||||
void on_workspace_activated(std::string const& payload);
|
||||
void on_workspace_destroyed(std::string const& payload);
|
||||
void on_workspace_created(std::string const& payload);
|
||||
void on_workspace_moved(std::string const& payload);
|
||||
void on_workspace_renamed(std::string const& payload);
|
||||
|
||||
// monitor events
|
||||
void on_monitor_focused(std::string const& payload);
|
||||
|
||||
// window events
|
||||
void on_window_opened(std::string const& payload);
|
||||
void on_window_closed(std::string const& payload);
|
||||
void on_window_moved(std::string const& payload);
|
||||
|
||||
void on_window_title_event(std::string const& payload);
|
||||
|
||||
int window_rewrite_priority_function(std::string const& window_rule);
|
||||
|
||||
bool all_outputs_ = false;
|
||||
bool show_special_ = false;
|
||||
bool active_only_ = false;
|
||||
|
||||
enum class SORT_METHOD { ID, NAME, NUMBER, DEFAULT };
|
||||
util::EnumParser<SORT_METHOD> enum_parser_;
|
||||
SORT_METHOD sort_by_ = SORT_METHOD::DEFAULT;
|
||||
std::map<std::string, SORT_METHOD> sort_map_ = {{"ID", SORT_METHOD::ID},
|
||||
{"NAME", SORT_METHOD::NAME},
|
||||
{"NUMBER", SORT_METHOD::NUMBER},
|
||||
{"DEFAULT", SORT_METHOD::DEFAULT}};
|
||||
|
||||
void fill_persistent_workspaces();
|
||||
void create_persistent_workspaces();
|
||||
@@ -72,13 +179,22 @@ class Workspaces : public AModule, public EventHandler {
|
||||
bool persistent_created_ = false;
|
||||
|
||||
std::string format_;
|
||||
|
||||
std::map<std::string, std::string> icons_map_;
|
||||
util::RegexCollection window_rewrite_rules_;
|
||||
bool any_window_rewrite_rule_uses_title_ = false;
|
||||
std::string format_window_separator_;
|
||||
|
||||
bool with_icon_;
|
||||
uint64_t monitor_id_;
|
||||
std::string active_workspace_name_;
|
||||
std::vector<std::unique_ptr<Workspace>> workspaces_;
|
||||
std::vector<Json::Value> workspaces_to_create_;
|
||||
std::vector<std::string> workspaces_to_remove_;
|
||||
std::vector<WindowCreationPayload> windows_to_create_;
|
||||
|
||||
std::vector<std::regex> ignore_workspaces_;
|
||||
|
||||
std::mutex mutex_;
|
||||
const Bar& bar_;
|
||||
Gtk::Box box_;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <fmt/chrono.h>
|
||||
#include <gtkmm/label.h>
|
||||
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "AModule.hpp"
|
||||
@@ -40,6 +41,7 @@ class KeyboardState : public AModule {
|
||||
|
||||
struct libinput* libinput_;
|
||||
std::unordered_map<std::string, struct libinput_device*> libinput_devices_;
|
||||
std::set<int> binding_keys;
|
||||
|
||||
util::SleeperThread libinput_thread_, hotplug_thread_;
|
||||
};
|
||||
|
||||
30
include/modules/load.hpp
Normal file
30
include/modules/load.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
27
include/modules/pulseaudio_slider.hpp
Normal file
27
include/modules/pulseaudio_slider.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ASlider.hpp"
|
||||
#include "util/audio_backend.hpp"
|
||||
namespace waybar::modules {
|
||||
|
||||
enum class PulseaudioSliderTarget {
|
||||
Sink,
|
||||
Source,
|
||||
};
|
||||
|
||||
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;
|
||||
PulseaudioSliderTarget target = PulseaudioSliderTarget::Sink;
|
||||
};
|
||||
|
||||
} // namespace waybar::modules
|
||||
@@ -84,6 +84,8 @@ class Item : public sigc::trackable {
|
||||
// visibility of items with Status == Passive
|
||||
bool show_passive_ = false;
|
||||
|
||||
const Bar& bar_;
|
||||
|
||||
Glib::RefPtr<Gio::DBus::Proxy> proxy_;
|
||||
Glib::RefPtr<Gio::Cancellable> cancellable_;
|
||||
std::set<std::string_view> update_pending_;
|
||||
|
||||
@@ -69,7 +69,7 @@ class UPower : public AModule {
|
||||
UpDevice *displayDevice;
|
||||
guint login1_id;
|
||||
GDBusConnection *login1_connection;
|
||||
UPowerTooltip *upower_tooltip;
|
||||
std::unique_ptr<UPowerTooltip> upower_tooltip;
|
||||
std::string lastStatus;
|
||||
bool showAltText;
|
||||
bool upowerRunning;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <libupower-glib/upower.h>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "gtkmm/box.h"
|
||||
@@ -16,7 +17,7 @@ class UPowerTooltip : public Gtk::Window {
|
||||
|
||||
const std::string getDeviceIcon(UpDeviceKind& kind);
|
||||
|
||||
Gtk::Box* contentBox;
|
||||
std::unique_ptr<Gtk::Box> contentBox;
|
||||
|
||||
uint iconSize;
|
||||
uint tooltipSpacing;
|
||||
|
||||
95
include/util/audio_backend.hpp
Normal file
95
include/util/audio_backend.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
#include <json/value.h>
|
||||
#include <pulse/context.h>
|
||||
#include <pulse/introspect.h>
|
||||
#include <pulse/thread-mainloop.h>
|
||||
#include <pulse/volume.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "util/backend_common.hpp"
|
||||
|
||||
namespace waybar::util {
|
||||
|
||||
class AudioBackend {
|
||||
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*);
|
||||
|
||||
pa_threaded_mainloop* mainloop_;
|
||||
pa_mainloop_api* mainloop_api_;
|
||||
pa_context* context_;
|
||||
pa_cvolume pa_volume_;
|
||||
|
||||
// SINK
|
||||
uint32_t sink_idx_{0};
|
||||
uint16_t 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::vector<std::string> ignored_sinks_;
|
||||
|
||||
std::function<void()> on_updated_cb_ = NOOP;
|
||||
|
||||
/* Hack to keep constructor inaccessible but still public.
|
||||
* This is required to be able to use std::make_shared.
|
||||
* It is important to keep this class only accessible via a reference-counted
|
||||
* pointer because the destructor will manually free memory, and this could be
|
||||
* a problem with C++20's copy and move semantics.
|
||||
*/
|
||||
struct private_constructor_tag {};
|
||||
|
||||
public:
|
||||
static std::shared_ptr<AudioBackend> getInstance(std::function<void()> on_updated_cb = NOOP);
|
||||
|
||||
AudioBackend(std::function<void()> on_updated_cb, private_constructor_tag tag);
|
||||
~AudioBackend();
|
||||
|
||||
void changeVolume(uint16_t volume, uint16_t min_volume = 0, uint16_t max_volume = 100);
|
||||
void changeVolume(ChangeType change_type, double step = 1, uint16_t max_volume = 100);
|
||||
|
||||
void setIgnoredSinks(const Json::Value& config);
|
||||
|
||||
std::string getSinkPortName() const { return port_name_; }
|
||||
std::string getFormFactor() const { return form_factor_; }
|
||||
std::string getSinkDesc() const { return desc_; }
|
||||
std::string getMonitor() const { return monitor_; }
|
||||
std::string getCurrentSinkName() const { return current_sink_name_; }
|
||||
bool getCurrentSinkRunning() const { return current_sink_running_; }
|
||||
uint16_t getSinkVolume() const { return volume_; }
|
||||
bool getSinkMuted() const { return muted_; }
|
||||
uint16_t getSourceVolume() const { return source_volume_; }
|
||||
bool getSourceMuted() const { return source_muted_; }
|
||||
std::string getSourcePortName() const { return source_port_name_; }
|
||||
std::string getSourceDesc() const { return source_desc_; }
|
||||
std::string getDefaultSourceName() const { return default_source_name_; }
|
||||
|
||||
void toggleSinkMute();
|
||||
void toggleSinkMute(bool);
|
||||
|
||||
void toggleSourceMute();
|
||||
void toggleSourceMute(bool);
|
||||
|
||||
bool isBluetooth();
|
||||
};
|
||||
|
||||
} // namespace waybar::util
|
||||
10
include/util/backend_common.hpp
Normal file
10
include/util/backend_common.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "AModule.hpp"
|
||||
|
||||
namespace waybar::util {
|
||||
|
||||
const static auto NOOP = []() {};
|
||||
enum class ChangeType : char { Increase, Decrease };
|
||||
|
||||
} // namespace waybar::util
|
||||
93
include/util/backlight_backend.hpp
Normal file
93
include/util/backlight_backend.hpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
|
||||
#include <libudev.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "giomm/dbusproxy.h"
|
||||
#include "util/backend_common.hpp"
|
||||
#include "util/sleeper_thread.hpp"
|
||||
|
||||
#define GET_BEST_DEVICE(varname, backend, preferred_device) \
|
||||
decltype((backend).devices_) __devices; \
|
||||
{ \
|
||||
std::scoped_lock<std::mutex> lock((backend).udev_thread_mutex_); \
|
||||
__devices = (backend).devices_; \
|
||||
} \
|
||||
auto varname = (backend).best_device(__devices.cbegin(), __devices.cend(), preferred_device);
|
||||
|
||||
namespace waybar::util {
|
||||
|
||||
class BacklightDevice {
|
||||
public:
|
||||
BacklightDevice() = default;
|
||||
BacklightDevice(std::string name, int actual, int max, bool powered);
|
||||
|
||||
std::string 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 BacklightDevice &lhs, const BacklightDevice &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;
|
||||
};
|
||||
|
||||
class BacklightBackend {
|
||||
public:
|
||||
BacklightBackend(std::chrono::milliseconds interval, std::function<void()> on_updated_cb = NOOP);
|
||||
|
||||
// const inline BacklightDevice *get_best_device(std::string_view preferred_device);
|
||||
const BacklightDevice *get_previous_best_device();
|
||||
|
||||
void set_previous_best_device(const BacklightDevice *device);
|
||||
|
||||
void set_brightness(std::string preferred_device, ChangeType change_type, double step);
|
||||
|
||||
void set_scaled_brightness(std::string preferred_device, int brightness);
|
||||
int get_scaled_brightness(std::string preferred_device);
|
||||
|
||||
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 is_login_proxy_initialized() const { return static_cast<bool>(login_proxy_); }
|
||||
|
||||
template <class ForwardIt>
|
||||
static const BacklightDevice *best_device(ForwardIt first, ForwardIt last, std::string_view);
|
||||
|
||||
std::vector<BacklightDevice> devices_;
|
||||
std::mutex udev_thread_mutex_;
|
||||
|
||||
private:
|
||||
void set_brightness_internal(std::string device_name, int brightness, int max_brightness);
|
||||
|
||||
std::function<void()> on_updated_cb_;
|
||||
std::chrono::milliseconds polling_interval_;
|
||||
|
||||
std::optional<BacklightDevice> previous_best_;
|
||||
// thread must destruct before shared data
|
||||
util::SleeperThread udev_thread_;
|
||||
|
||||
Glib::RefPtr<Gio::DBus::Proxy> login_proxy_;
|
||||
|
||||
static constexpr int EPOLL_MAX_EVENTS = 16;
|
||||
};
|
||||
|
||||
} // namespace waybar::util
|
||||
@@ -112,6 +112,10 @@ inline FILE* open(const std::string& cmd, int& pid) {
|
||||
execlp("/bin/sh", "sh", "-c", cmd.c_str(), (char*)0);
|
||||
exit(0);
|
||||
} else {
|
||||
reap_mtx.lock();
|
||||
reap.push_back(child_pid);
|
||||
reap_mtx.unlock();
|
||||
|
||||
::close(fd[1]);
|
||||
}
|
||||
pid = child_pid;
|
||||
|
||||
19
include/util/enum.hpp
Normal file
19
include/util/enum.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace waybar::util {
|
||||
|
||||
template <typename EnumType>
|
||||
struct EnumParser {
|
||||
public:
|
||||
EnumParser();
|
||||
~EnumParser();
|
||||
|
||||
EnumType parseStringToEnum(const std::string& str,
|
||||
const std::map<std::string, EnumType>& enumMap);
|
||||
};
|
||||
|
||||
} // namespace waybar::util
|
||||
@@ -93,7 +93,7 @@ template <>
|
||||
struct formatter<Glib::ustring> : formatter<std::string> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Glib::ustring& value, FormatContext& ctx) {
|
||||
return formatter<std::string>::format(value, ctx);
|
||||
return formatter<std::string>::format(static_cast<std::string>(value), ctx);
|
||||
}
|
||||
};
|
||||
} // namespace fmt
|
||||
|
||||
38
include/util/portal.hpp
Normal file
38
include/util/portal.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <giomm/dbusproxy.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
namespace waybar {
|
||||
|
||||
using namespace Gio;
|
||||
|
||||
enum class Appearance {
|
||||
UNKNOWN = 0,
|
||||
DARK = 1,
|
||||
LIGHT = 2,
|
||||
};
|
||||
class Portal : private DBus::Proxy {
|
||||
public:
|
||||
Portal();
|
||||
void refreshAppearance();
|
||||
Appearance getAppearance();
|
||||
|
||||
typedef sigc::signal<void, Appearance> type_signal_appearance_changed;
|
||||
type_signal_appearance_changed signal_appearance_changed() { return m_signal_appearance_changed; }
|
||||
|
||||
private:
|
||||
type_signal_appearance_changed m_signal_appearance_changed;
|
||||
Appearance currentMode;
|
||||
void on_signal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
|
||||
const Glib::VariantContainerBase& parameters);
|
||||
};
|
||||
|
||||
} // namespace waybar
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<waybar::Appearance> : formatter<fmt::string_view> {
|
||||
// parse is inherited from formatter<string_view>.
|
||||
auto format(waybar::Appearance c, format_context& ctx) const;
|
||||
};
|
||||
51
include/util/regex_collection.hpp
Normal file
51
include/util/regex_collection.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <json/json.h>
|
||||
|
||||
#include <functional>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
namespace waybar::util {
|
||||
|
||||
struct Rule {
|
||||
std::regex rule;
|
||||
std::string repr;
|
||||
int priority;
|
||||
|
||||
// Fix for Clang < 16
|
||||
// See https://en.cppreference.com/w/cpp/compiler_support/20 "Parenthesized initialization of
|
||||
// aggregates"
|
||||
Rule(std::regex rule, std::string repr, int priority)
|
||||
: rule(rule), repr(repr), priority(priority) {}
|
||||
};
|
||||
|
||||
int default_priority_function(std::string& key);
|
||||
|
||||
/* A collection of regexes and strings, with a default string to return if no regexes.
|
||||
* When a regex is matched, the corresponding string is returned.
|
||||
* All regexes that are matched are cached, so that the regexes are only
|
||||
* evaluated once against a given string.
|
||||
* Regexes may be given a higher priority than others, so that they are matched
|
||||
* first. The priority function is given the regex string, and should return a
|
||||
* higher number for higher priority regexes.
|
||||
*/
|
||||
class RegexCollection {
|
||||
private:
|
||||
std::vector<Rule> rules;
|
||||
std::map<std::string, std::string> regex_cache;
|
||||
std::string default_repr;
|
||||
|
||||
std::string& find_match(std::string& value, bool& matched_any);
|
||||
|
||||
public:
|
||||
RegexCollection() = default;
|
||||
RegexCollection(const Json::Value& map, std::string default_repr = "",
|
||||
std::function<int(std::string&)> priority_function = default_priority_function);
|
||||
~RegexCollection() = default;
|
||||
|
||||
std::string& get(std::string& value, bool& matched_any);
|
||||
std::string& get(std::string& value);
|
||||
};
|
||||
|
||||
} // namespace waybar::util
|
||||
@@ -5,4 +5,6 @@
|
||||
|
||||
namespace waybar::util {
|
||||
std::string rewriteString(const std::string&, const Json::Value&);
|
||||
}
|
||||
std::string rewriteStringOnce(const std::string& value, const Json::Value& rules,
|
||||
bool& matched_any);
|
||||
} // namespace waybar::util
|
||||
|
||||
21
include/util/scope_guard.hpp
Normal file
21
include/util/scope_guard.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace waybar::util {
|
||||
|
||||
template <typename Func>
|
||||
class ScopeGuard {
|
||||
public:
|
||||
explicit ScopeGuard(Func&& exit_function) : f{std::forward<Func>(exit_function)} {}
|
||||
ScopeGuard(const ScopeGuard&) = delete;
|
||||
ScopeGuard(ScopeGuard&&) = default;
|
||||
ScopeGuard& operator=(const ScopeGuard&) = delete;
|
||||
ScopeGuard& operator=(ScopeGuard&&) = default;
|
||||
~ScopeGuard() { f(); }
|
||||
|
||||
private:
|
||||
Func f;
|
||||
};
|
||||
|
||||
} // namespace waybar::util
|
||||
@@ -58,10 +58,22 @@ class SleeperThread {
|
||||
|
||||
bool isRunning() const { return do_run_; }
|
||||
|
||||
auto sleep() {
|
||||
std::unique_lock lk(mutex_);
|
||||
CancellationGuard cancel_lock;
|
||||
return condvar_.wait(lk, [this] { return signal_ || !do_run_; });
|
||||
}
|
||||
|
||||
auto sleep_for(std::chrono::system_clock::duration dur) {
|
||||
std::unique_lock lk(mutex_);
|
||||
CancellationGuard cancel_lock;
|
||||
return condvar_.wait_for(lk, dur, [this] { return signal_ || !do_run_; });
|
||||
constexpr auto max_time_point = std::chrono::steady_clock::time_point::max();
|
||||
auto wait_end = max_time_point;
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
if (now < max_time_point - dur) {
|
||||
wait_end = now + dur;
|
||||
}
|
||||
return condvar_.wait_until(lk, wait_end, [this] { return signal_ || !do_run_; });
|
||||
}
|
||||
|
||||
auto sleep_until(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
const std::string WHITESPACE = " \n\r\t\f\v";
|
||||
@@ -15,3 +16,10 @@ inline std::string rtrim(const std::string& s) {
|
||||
}
|
||||
|
||||
inline std::string trim(const std::string& s) { return rtrim(ltrim(s)); }
|
||||
|
||||
inline std::string capitalize(const std::string& str) {
|
||||
std::string result = str;
|
||||
std::transform(result.begin(), result.end(), result.begin(),
|
||||
[](unsigned char c) { return std::toupper(c); });
|
||||
return result;
|
||||
}
|
||||
|
||||
88
man/waybar-backlight-slider.5.scd
Normal file
88
man/waybar-backlight-slider.5.scd
Normal file
@@ -0,0 +1,88 @@
|
||||
waybar-backlight-slider(5)
|
||||
|
||||
# NAME
|
||||
|
||||
waybar - backlight slider module
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
The *backlight slider* module displays and controls the current brightness of the default or preferred device.
|
||||
|
||||
The brightness can be controlled by dragging the slider across the bar or clicking on a specific position.
|
||||
|
||||
# CONFIGURATION
|
||||
|
||||
*min*: ++
|
||||
typeof: int ++
|
||||
default: 0 ++
|
||||
The minimum volume value the slider should display and set.
|
||||
|
||||
*max*: ++
|
||||
typeof: int ++
|
||||
default: 100 ++
|
||||
The maximum volume value the slider should display and set.
|
||||
|
||||
*orientation*: ++
|
||||
typeof: string ++
|
||||
default: horizontal ++
|
||||
The orientation of the slider. Can be either `horizontal` or `vertical`.
|
||||
|
||||
*device*: ++
|
||||
typeof: string ++
|
||||
The name of the preferred device to control. If left empty, a device will be chosen automatically.
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
```
|
||||
"modules-right": [
|
||||
"backlight-slider",
|
||||
],
|
||||
"backlight/slider": {
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"orientation": "horizontal",
|
||||
"device": "intel_backlight"
|
||||
}
|
||||
```
|
||||
|
||||
# STYLE
|
||||
|
||||
The slider is a component with multiple CSS Nodes, of which the following are exposed:
|
||||
|
||||
*#backlight-slider*: ++
|
||||
Controls the style of the box *around* the slider and bar.
|
||||
|
||||
*#backlight-slider slider*: ++
|
||||
Controls the style of the slider handle.
|
||||
|
||||
*#backlight-slider trough*: ++
|
||||
Controls the style of the part of the bar that has not been filled.
|
||||
|
||||
*#backlight-slider highlight*: ++
|
||||
Controls the style of the part of the bar that has been filled.
|
||||
|
||||
## STYLE EXAMPLE
|
||||
|
||||
```
|
||||
#backlight-slider slider {
|
||||
min-height: 0px;
|
||||
min-width: 0px;
|
||||
opacity: 0;
|
||||
background-image: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#backlight-slider trough {
|
||||
min-height: 80px;
|
||||
min-width: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
#backlight-slider highlight {
|
||||
min-width: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: red;
|
||||
}
|
||||
```
|
||||
@@ -26,7 +26,7 @@ The *backlight* module displays the current backlight level.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -46,11 +46,11 @@ The *backlight* module displays the current backlight level.
|
||||
|
||||
*on-click-middle*: ++
|
||||
typeof: string ++
|
||||
Command to execute when middle-clicked on the module using mousewheel.
|
||||
Command to execute when middle-clicked on the module using mouse scroll wheel.
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when the module is right clicked.
|
||||
Command to execute when the module is right-clicked.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
@@ -75,7 +75,7 @@ The *backlight* module displays the current backlight level.
|
||||
*scroll-step*: ++
|
||||
typeof: float ++
|
||||
default: 1.0 ++
|
||||
The speed in which to change the brightness when scrolling.
|
||||
The speed at which to change the brightness when scrolling.
|
||||
|
||||
# EXAMPLE:
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
||||
*design-capacity*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
Option to use the battery design capacity instead of it's current maximal capacity.
|
||||
Option to use the battery design capacity instead of its current maximal capacity.
|
||||
|
||||
*interval*: ++
|
||||
typeof: integer ++
|
||||
@@ -57,7 +57,7 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -77,7 +77,7 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
@@ -100,6 +100,11 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
||||
default: true ++
|
||||
Option to disable tooltip on hover.
|
||||
|
||||
*bat-compatibility*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
Option to enable battery compatibility if not detected.
|
||||
|
||||
# FORMAT REPLACEMENTS
|
||||
|
||||
*{capacity}*: Capacity in percentage
|
||||
@@ -121,7 +126,7 @@ The three arguments are:
|
||||
|
||||
# CUSTOM FORMATS
|
||||
|
||||
The *battery* module allows one to define custom formats based on up to two factors. The best fitting format will be selected.
|
||||
The *battery* module allows one to define custom formats based on up to two factors. The best-fitting format will be selected.
|
||||
|
||||
*format-<state>*: With *states*, a custom format can be set depending on the capacity of your battery.
|
||||
|
||||
@@ -132,8 +137,8 @@ The *battery* module allows one to define custom formats based on up to two fact
|
||||
# STATES
|
||||
|
||||
- Every entry (*state*) consists of a *<name>* (typeof: *string*) and a *<value>* (typeof: *integer*).
|
||||
- The state can be addressed as a CSS class in the *style.css*. The name of the CSS class is the *<name>* of the state. Each class gets activated when the current capacity is equal or below the configured *<value>*.
|
||||
- Also each state can have its own *format*. Those con be configured via *format-<name>*. Or if you want to differentiate a bit more even as *format-<status>-<state>*. For more information see *custom-formats*.
|
||||
- The state can be addressed as a CSS class in the *style.css*. The name of the CSS class is the *<name>* of the state. Each class gets activated when the current capacity is equal to or below the configured *<value>*.
|
||||
- Also each state can have its own *format*. Those can be configured via *format-<name>*. Or if you want to differentiate a bit more even as *format-<status>-<state>*. For more information see *custom-formats*.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Addressed by *bluetooth*
|
||||
|
||||
*controller*: ++
|
||||
typeof: string ++
|
||||
Use the controller with the defined alias. Otherwise a random controller is used. Recommended to define when there is more than 1 controller available to the system.
|
||||
Use the controller with the defined alias. Otherwise, a random controller is used. Recommended to define when there is more than 1 controller available to the system.
|
||||
|
||||
*format-device-preference*: ++
|
||||
typeof: array ++
|
||||
@@ -42,6 +42,10 @@ Addressed by *bluetooth*
|
||||
typeof: string ++
|
||||
This format is used when the displayed controller is connected to at least 1 device.
|
||||
|
||||
*format-no-controller*: ++
|
||||
typeof: string ++
|
||||
This format is used when no bluetooth controller can be found
|
||||
|
||||
*format-icons*: ++
|
||||
typeof: array/object ++
|
||||
Based on the current battery percentage (see section *EXPERIMENTAL BATTERY PERCENTAGE FEATURE*), the corresponding icon gets selected. ++
|
||||
@@ -58,7 +62,7 @@ Addressed by *bluetooth*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -74,7 +78,7 @@ Addressed by *bluetooth*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-scroll-up*: ++
|
||||
typeof: string ++
|
||||
@@ -113,6 +117,10 @@ Addressed by *bluetooth*
|
||||
typeof: string ++
|
||||
This format is used when the displayed controller is connected to at least 1 device.
|
||||
|
||||
*tooltip-format-no-controller*: ++
|
||||
typeof: string ++
|
||||
This format is used when no bluetooth controller can be found
|
||||
|
||||
*tooltip-format-enumerate-connected*: ++
|
||||
typeof: string ++
|
||||
This format is used to define how each connected device should be displayed within the *device_enumerate* format replacement in the tooltip menu.
|
||||
@@ -138,7 +146,7 @@ Addressed by *bluetooth*
|
||||
*{device_alias}*: Alias of the displayed device.
|
||||
|
||||
*{device_enumerate}*: Show a list of all connected devices, each on a separate line. Define the format of each device with the *tooltip-format-enumerate-connected* ++
|
||||
and/or *tooltip-format-enumerate-connected-battery* config options. Can only be used in the tooltip related format options.
|
||||
and/or *tooltip-format-enumerate-connected-battery* config options. Can only be used in the tooltip-related format options.
|
||||
|
||||
# EXPERIMENTAL BATTERY PERCENTAGE FEATURE
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ libcava lives in:
|
||||
|[ *framerate*
|
||||
:[ integer
|
||||
:[ 30
|
||||
:[ rames per second. Is used as a replacement for *interval*
|
||||
:[ Frames per second. Is used as a replacement for *interval*
|
||||
|[ *autosens*
|
||||
:[ integer
|
||||
:[ 1
|
||||
@@ -60,6 +60,10 @@ libcava lives in:
|
||||
:[ integer
|
||||
:[ 5
|
||||
:[ Seconds with no input before cava main thread goes to sleep mode
|
||||
|[ *hide_on_silence*
|
||||
:[ bool
|
||||
:[ false
|
||||
:[ Hides the widget if no input (after sleep_timer elapsed)
|
||||
|[ *method*
|
||||
:[ string
|
||||
:[ pulse
|
||||
@@ -91,19 +95,19 @@ libcava lives in:
|
||||
|[ *monstercat*
|
||||
:[ bool
|
||||
:[ false
|
||||
:[ Disables or enables the so-called "Monstercat smoothing" with of without "waves"
|
||||
:[ Disables or enables the so-called "Monstercat smoothing" with or without "waves"
|
||||
|[ *waves*
|
||||
:[ bool
|
||||
:[ false
|
||||
:[ Disables or enables the so-called "Monstercat smoothing" with of without "waves"
|
||||
:[ Disables or enables the so-called "Monstercat smoothing" with or without "waves"
|
||||
|[ *noise_reduction*
|
||||
:[ double
|
||||
:[ 0.77
|
||||
:[ Range between 0 - 1. The raw visualization is very noisy, this factor adjust the integral and gravity filters to keep the signal smooth. 1 - will be very slow and smooth, 0 - will be fast but noisy
|
||||
:[ Range between 0 - 1. The raw visualization is very noisy, this factor adjusts the integral and gravity filters to keep the signal smooth. 1 - will be very slow and smooth, 0 - will be fast but noisy
|
||||
|[ *input_delay*
|
||||
:[ integer
|
||||
:[ 2
|
||||
:[ Sets the delay before fetching audio source thread start working. On author machine Waybar starts much faster then pipewire audio server, and without a little delay cava module fails due to pipewire is not ready
|
||||
:[ Sets the delay before fetching audio source thread start working. On author's machine, Waybar starts much faster than pipewire audio server, and without a little delay cava module fails because pipewire is not ready
|
||||
|[ *ascii_max_range*
|
||||
:[ integer
|
||||
:[ 7
|
||||
@@ -120,14 +124,14 @@ libcava lives in:
|
||||
Configuration can be provided as:
|
||||
- The only cava configuration file which is provided through *cava_config*. The rest configuration can be skipped
|
||||
- Without cava configuration file. In such case cava should be configured through provided list of the configuration option
|
||||
- Mix. When provided both And cava configuration file And configuration options. In such case waybar applies configuration file first then overrides particular options by the provided list of configuration options
|
||||
- Mix. When provided both And cava configuration file And configuration options. In such case, waybar applies configuration file first and then overrides particular options by the provided list of configuration options
|
||||
|
||||
# ACTIONS
|
||||
|
||||
[- *String*
|
||||
:- *Action*
|
||||
|[ *mode*
|
||||
:< Switch main cava thread and fetching audio source thread from/to pause/resume
|
||||
:< Switch main cava thread and fetch audio source thread from/to pause/resume
|
||||
|
||||
# DEPENDENCIES
|
||||
|
||||
@@ -138,16 +142,16 @@ Configuration can be provided as:
|
||||
|
||||
. On start Waybar throws an exception "error while loading shared libraries: libcava.so: cannot open shared object file: No such file or directory".
|
||||
It might happen when libcava for some reason hasn't been registered in the system. sudo ldconfig should help
|
||||
. Waybar is starting but cava module doesn't react on the music
|
||||
1. In such case for at first need to make sure usual cava application is working as well
|
||||
. Waybar is starting but cava module doesn't react to the music
|
||||
1. In such cases at first need to make sure usual cava application is working as well
|
||||
2. If so, need to comment all configuration options. Uncomment cava_config and provide the path to the working cava config
|
||||
3. You might set too huge or too small input_delay. Try to setup to 4 seconds, restart waybar and check again 4 seconds past. Usual even on weak machines it should be enough
|
||||
4. You might accidentally switched action mode to pause mode
|
||||
3. You might set too huge or too small input_delay. Try to setup to 4 seconds, restart waybar, and check again 4 seconds past. Usual even on weak machines it should be enough
|
||||
4. You might accidentally switch action mode to pause mode
|
||||
|
||||
# RISING ISSUES
|
||||
|
||||
For clear understanding: this module is a cava API's consumer. So for any bugs related to cava engine you should contact to Cava upstream(https://github.com/karlstav/cava) ++
|
||||
with the one Exception. Cava upstream doesn't provide cava as a shared library. For that this module author made a fork libcava(https://github.com/LukashonakV/cava). ++
|
||||
For clear understanding: this module is a cava API's consumer. So for any bugs related to cava engine you should contact Cava upstream(https://github.com/karlstav/cava) ++
|
||||
with the one Exception. Cava upstream doesn't provide cava as a shared library. For that, this module author made a fork libcava(https://github.com/LukashonakV/cava). ++
|
||||
So the order is:
|
||||
. cava upstream
|
||||
. libcava upstream.
|
||||
|
||||
@@ -63,7 +63,7 @@ $XDG_CONFIG_HOME/waybar/config ++
|
||||
|[ *on-click-right*
|
||||
:[ string
|
||||
:[
|
||||
:[ Command to execute when you right clicked on the module
|
||||
:[ Command to execute when you right-click on the module
|
||||
|[ *on-scroll-up*
|
||||
:[ string
|
||||
:[
|
||||
@@ -147,7 +147,7 @@ View all valid format options in *strftime(3)* or have a look <https://fmt.dev/l
|
||||
|[ *tz_up*
|
||||
:[ Switch to the next provided time zone
|
||||
|[ *tz_down*
|
||||
:[ Switch to the previous provided time zone
|
||||
:[ Switch to the previously provided time zone
|
||||
|[ *shift_up*
|
||||
:[ Switch to the next calendar month/year
|
||||
|[ *shift_down*
|
||||
@@ -219,7 +219,7 @@ View all valid format options in *strftime(3)* or have a look <https://fmt.dev/l
|
||||
# Troubleshooting
|
||||
|
||||
If clock module is disabled at startup with locale::facet::\_S\_create\_c\_locale ++
|
||||
name not valid error message try one of the followings:
|
||||
name not valid error message try one of the following:
|
||||
|
||||
- check if LC_TIME is set properly (glibc)
|
||||
- set locale to C in the config file (musl)
|
||||
|
||||
@@ -6,7 +6,7 @@ waybar - cpu module
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
The *cpu* module displays the current cpu utilization.
|
||||
The *cpu* module displays the current CPU utilization.
|
||||
|
||||
# CONFIGURATION
|
||||
|
||||
@@ -31,7 +31,7 @@ The *cpu* module displays the current cpu utilization.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -43,7 +43,7 @@ The *cpu* module displays the current cpu utilization.
|
||||
|
||||
*states*: ++
|
||||
typeof: object ++
|
||||
A number of cpu usage states which get activated on certain usage levels. See *waybar-states(5)*.
|
||||
A number of CPU usage states which get activated on certain usage levels. See *waybar-states(5)*.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
@@ -55,7 +55,7 @@ The *cpu* module displays the current cpu utilization.
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
@@ -80,21 +80,21 @@ The *cpu* module displays the current cpu utilization.
|
||||
|
||||
# FORMAT REPLACEMENTS
|
||||
|
||||
*{load}*: Current cpu load.
|
||||
*{load}*: Current CPU load.
|
||||
|
||||
*{usage}*: Current overall cpu usage.
|
||||
*{usage}*: Current overall CPU usage.
|
||||
|
||||
*{usage*{n}*}*: Current cpu core n usage. Cores are numbered from zero, so first core will be {usage0} and 4th will be {usage3}.
|
||||
*{usage*{n}*}*: Current CPU core n usage. Cores are numbered from zero, so first core will be {usage0} and 4th will be {usage3}.
|
||||
|
||||
*{avg_frequency}*: Current cpu average frequency (based on all cores) in GHz.
|
||||
*{avg_frequency}*: Current CPU average frequency (based on all cores) in GHz.
|
||||
|
||||
*{max_frequency}*: Current cpu max frequency (based on the core with the highest frequency) in GHz.
|
||||
*{max_frequency}*: Current CPU max frequency (based on the core with the highest frequency) in GHz.
|
||||
|
||||
*{min_frequency}*: Current cpu min frequency (based on the core with the lowest frequency) in GHz.
|
||||
*{min_frequency}*: Current CPU min frequency (based on the core with the lowest frequency) in GHz.
|
||||
|
||||
*{icon}*: Icon for overall cpu usage.
|
||||
*{icon}*: Icon for overall CPU usage.
|
||||
|
||||
*{icon*{n}*}*: Icon for cpu core n usage. Use like {icon0}.
|
||||
*{icon*{n}*}*: Icon for CPU core n usage. Use like {icon0}.
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
@@ -108,7 +108,7 @@ Basic configuration:
|
||||
}
|
||||
```
|
||||
|
||||
Cpu usage per core rendered as icons:
|
||||
CPU usage per core rendered as icons:
|
||||
|
||||
```
|
||||
"cpu": {
|
||||
|
||||
@@ -34,18 +34,20 @@ Addressed by *custom/<name>*
|
||||
typeof: integer ++
|
||||
The interval (in seconds) in which the information gets polled. ++
|
||||
Use *once* if you want to execute the module only on startup. ++
|
||||
You can update it manually with a signal. If no *interval* is defined, it is assumed that the out script loops it self.
|
||||
You can update it manually with a signal. If no *interval* or *signal* is defined, it is assumed that the out script loops itself. ++
|
||||
If a *signal* is defined then the script will run once on startup and will only update with a signal.
|
||||
|
||||
*restart-interval*: ++
|
||||
typeof: integer ++
|
||||
The restart interval (in seconds). ++
|
||||
Can't be used with the *interval* option, so only with continuous scripts. ++
|
||||
Once the script exit, it'll be re-executed after the *restart-interval*.
|
||||
Once the script exits, it'll be re-executed after the *restart-interval*.
|
||||
|
||||
*signal*: ++
|
||||
typeof: integer ++
|
||||
The signal number used to update the module. ++
|
||||
The number is valid between 1 and N, where *SIGRTMIN+N* = *SIGRTMAX*.
|
||||
The number is valid between 1 and N, where *SIGRTMIN+N* = *SIGRTMAX*. ++
|
||||
If no interval is defined then a signal will be the only way to update the module.
|
||||
|
||||
*format*: ++
|
||||
typeof: string ++
|
||||
@@ -66,7 +68,7 @@ Addressed by *custom/<name>*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -82,7 +84,7 @@ Addressed by *custom/<name>*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
@@ -134,7 +136,7 @@ $text\\n$tooltip\\n$class*
|
||||
|
||||
*{}*: Output of the script.
|
||||
|
||||
*{percentage}* Percentage which can be set via a json return-type.
|
||||
*{percentage}* Percentage which can be set via a json return type.
|
||||
|
||||
*{icon}*: An icon from 'format-icons' according to percentage.
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ Addressed by *disk*
|
||||
|
||||
*states*: ++
|
||||
typeof: object ++
|
||||
A number of disk utilization states which get activated on certain percentage thresholds (percentage_used). See *waybar-states(5)*.
|
||||
A number of disk utilization states that get activated on certain percentage thresholds (percentage_used). See *waybar-states(5)*.
|
||||
|
||||
*max-length*: ++
|
||||
typeof: integer ++
|
||||
@@ -41,7 +41,7 @@ Addressed by *disk*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -57,7 +57,7 @@ Addressed by *disk*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
@@ -85,20 +85,30 @@ Addressed by *disk*
|
||||
default: "{used} out of {total} used ({percentage_used}%)" ++
|
||||
The format of the information displayed in the tooltip.
|
||||
|
||||
*unit*: ++
|
||||
typeof: string ++
|
||||
Use with specific_free, specific_used, and specific_total to force calculation to always be in a certain unit. Accepts kB, kiB, MB, Mib, GB, GiB, TB, TiB.
|
||||
|
||||
# FORMAT REPLACEMENTS
|
||||
|
||||
*{percentage_used}*: Percentage of disk in use.
|
||||
|
||||
*{percentage_free}*: Percentage of free disk space
|
||||
|
||||
*{total}*: Total amount of space on the disk, partition or mountpoint.
|
||||
*{total}*: Total amount of space on the disk, partition, or mountpoint. Automatically selects unit based on size remaining.
|
||||
|
||||
*{used}*: Amount of used disk space.
|
||||
*{used}*: Amount of used disk space. Automatically selects unit based on size remaining.
|
||||
|
||||
*{free}*: Amount of available disk space for normal users.
|
||||
*{free}*: Amount of available disk space for normal users. Automatically selects unit based on size remaining.
|
||||
|
||||
*{path}*: The path specified in the configuration.
|
||||
|
||||
*{specific_total}*: Total amount of space on the disk, partition, or mountpoint in a specific unit. Defaults to bytes.
|
||||
|
||||
*{specific_used}*: Amount of used disk space in a specific unit. Defaults to bytes.
|
||||
|
||||
*{specific_free}*: Amount of available disk space for normal users in a specific unit. Defaults to bytes.
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
```
|
||||
@@ -108,6 +118,15 @@ Addressed by *disk*
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
"disk": {
|
||||
"interval": 30,
|
||||
"format": "{specific_free:0.2f} GB out of {specific_total:0.2f} GB available. Alternatively {free} out of {total} available",
|
||||
"unit": "GB"
|
||||
// 1434.25 GB out of 2000.00 GB available. Alternatively 1.4TiB out of 1.9TiB available.
|
||||
}
|
||||
```
|
||||
|
||||
# STYLE
|
||||
|
||||
- *#disk*
|
||||
|
||||
@@ -24,7 +24,7 @@ Addressed by *dwl/tags*
|
||||
*disable-click*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
If set to false, you can left click to set focused tag. Right click to toggle tag focus. If set to true this behaviour is disabled.
|
||||
If set to false, you can left-click to set focused tag. Right-click to toggle tag focus. If set to true this behaviour is disabled.
|
||||
|
||||
# EXAMPLE
|
||||
|
||||
|
||||
@@ -65,11 +65,11 @@ Feral Gamemode optimizations.
|
||||
|
||||
*{glyph}*: The string icon glyph to use instead.
|
||||
|
||||
*{count}*: The amount of games running with gamemode optimizations.
|
||||
*{count}*: The number of games running with gamemode optimizations.
|
||||
|
||||
# TOOLTIP FORMAT REPLACEMENTS
|
||||
|
||||
*{count}*: The amount of games running with gamemode optimizations.
|
||||
*{count}*: The number of games running with gamemode optimizations.
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ Addressed by *hyprland/submap*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -43,7 +43,7 @@ Addressed by *hyprland/submap*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
|
||||
@@ -19,17 +19,51 @@ Addressed by *hyprland/workspaces*
|
||||
|
||||
*format-icons*: ++
|
||||
typeof: array ++
|
||||
Based on the workspace id and state, the corresponding icon gets selected. See *icons*.
|
||||
Based on the workspace ID and state, the corresponding icon gets selected. See *icons*.
|
||||
|
||||
*window-rewrite*: ++
|
||||
typeof: object ++
|
||||
Regex rules to map window class to an icon or preferred method of representation for a workspace's window.
|
||||
Keys are the rules, while the values are the methods of representation.
|
||||
Rules may specify `class<...>`, `title<...>`, or both in order to fine-tune the matching.
|
||||
|
||||
*window-rewrite-default*:
|
||||
typeof: string ++
|
||||
default: "?" ++
|
||||
The default method of representation for a workspace's window. This will be used for windows whose classes do not match any of the rules in *window-rewrite*.
|
||||
|
||||
*format-window-separator*: ++
|
||||
typeof: string ++
|
||||
default: " " ++
|
||||
The separator to be used between windows in a workspace.
|
||||
|
||||
*show-special*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
If set to true special workspaces will be shown.
|
||||
If set to true, special workspaces will be shown.
|
||||
|
||||
*all-outputs*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
If set to false workspaces group will be shown only in assigned output. Otherwise all workspace groups are shown.
|
||||
If set to false workspaces group will be shown only in assigned output. Otherwise, all workspace groups are shown.
|
||||
|
||||
*active-only*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
If set to true, only the active workspace will be shown.
|
||||
|
||||
*ignore-workspaces*: ++
|
||||
typeof: array ++
|
||||
default: [] ++
|
||||
Regexes to match against workspaces names. If there's a match, the workspace will not be shown. This takes precedence over *show-special*, *all-outputs*, and *active-only*.
|
||||
|
||||
*sort-by*: ++
|
||||
typeof: string ++
|
||||
default: "default" ++
|
||||
If set to number, workspaces will sort by number.
|
||||
If set to name, workspaces will sort by name.
|
||||
If set to id, workspaces will sort by id.
|
||||
If none of those, workspaces will sort with default behavior.
|
||||
|
||||
# FORMAT REPLACEMENTS
|
||||
|
||||
@@ -43,10 +77,12 @@ Addressed by *hyprland/workspaces*
|
||||
|
||||
Additional to workspace name matching, the following *format-icons* can be set.
|
||||
|
||||
- *default*: Will be shown, when no string match is found.
|
||||
- *default*: Will be shown, when no string match is found and none of the below conditions have defined icons.
|
||||
- *active*: Will be shown, when workspace is active
|
||||
- *special*: Will be shown on non-active special workspaces
|
||||
- *persistent*: Will be shown on non-active persistent workspaces
|
||||
- *empty*: Will be shown on non-active, non-special empty persistent workspaces
|
||||
- *visible*: Will be shown on workspaces that are visible but not active. For example: this is useful if you want your visible workspaces on other monitors to have the same look as active.
|
||||
- *persistent*: Will be shown on non-empty persistent workspaces
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
@@ -62,17 +98,62 @@ Additional to workspace name matching, the following *format-icons* can be set.
|
||||
"active": "",
|
||||
"default": ""
|
||||
},
|
||||
"persistent_workspaces": {
|
||||
"persistent-workspaces": {
|
||||
"*": 5, // 5 workspaces by default on every monitor
|
||||
"HDMI-A-1": 3 // but only three on HDMI-A-1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
"hyprland/workspaces": {
|
||||
"format": "{name}: {icon}",
|
||||
"format-icons": {
|
||||
"1": "",
|
||||
"2": "",
|
||||
"3": "",
|
||||
"4": "",
|
||||
"5": "",
|
||||
"active": "",
|
||||
"default": ""
|
||||
},
|
||||
"persistent-workspaces": {
|
||||
"*": [ 2,3,4,5 ], // 2-5 on every monitor
|
||||
"HDMI-A-1": [ 1 ] // but only workspace 1 on HDMI-A-1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
"hyprland/workspaces": {
|
||||
"format": "{name}\n{windows}",
|
||||
"format-window-separator": "\n",
|
||||
"window-rewrite-default": "",
|
||||
"window-rewrite": {
|
||||
"title<.*youtube.*>": "", // Windows whose titles contain "youtube"
|
||||
"class<firefox>": "", // Windows whose classes are "firefox"
|
||||
"class<firefox> title<.*github.*>": "", // Windows whose class is "firefox" and title contains "github". Note that "class" always comes first.
|
||||
"foot": "", // Windows that contain "foot" in either class or title. For optimization reasons, it will only match against a title if at least one other window explicitly matches against a title.
|
||||
"code": "",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
"hyprland/workspaces": {
|
||||
// Formatting omitted for brevity
|
||||
"ignore-workspaces": [
|
||||
"(special:)?chrome-sharing-indicator"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
# Style
|
||||
|
||||
- *#workspaces*
|
||||
- *#workspaces button*
|
||||
- *#workspaces button.active*
|
||||
- *#workspaces button.empty*
|
||||
- *#workspaces button.visible*
|
||||
- *#workspaces button.persistent*
|
||||
- *#workspaces button.special*
|
||||
- *#workspaces button.urgent*
|
||||
|
||||
@@ -6,8 +6,8 @@ waybar - idle_inhibitor module
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
The *idle_inhibitor* module can inhibiting the idle behavior such as screen blanking, locking, and
|
||||
screensaving, also known as "presentation mode".
|
||||
The *idle_inhibitor* module can inhibit the idle behavior such as screen blanking, locking, and
|
||||
screensaver, also known as "presentation mode".
|
||||
|
||||
# CONFIGURATION
|
||||
|
||||
@@ -29,7 +29,7 @@ screensaving, also known as "presentation mode".
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -45,7 +45,7 @@ screensaving, also known as "presentation mode".
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
@@ -70,7 +70,7 @@ screensaving, also known as "presentation mode".
|
||||
|
||||
*timeout*: ++
|
||||
typeof: double ++
|
||||
The number of minutes the inhibit should last.
|
||||
The number of minutes the inhibition should last.
|
||||
|
||||
*tooltip*: ++
|
||||
typeof: bool ++
|
||||
|
||||
@@ -66,7 +66,7 @@ The *image* module displays an image from a path.
|
||||
|
||||
# SCRIPT OUTPUT
|
||||
|
||||
Similar to the *custom* module, output values of the script is *newline* separated.
|
||||
Similar to the *custom* module, output values of the script are *newline* separated.
|
||||
The following is the output format:
|
||||
|
||||
```
|
||||
|
||||
@@ -33,7 +33,7 @@ See *systemd-inhibit*(1) for more information.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -49,7 +49,7 @@ See *systemd-inhibit*(1) for more information.
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
|
||||
@@ -27,7 +27,7 @@ Addressed by *jack*
|
||||
|
||||
*format-xrun*: ++
|
||||
typeof: string ++
|
||||
This format is used for one polling interval, when the JACK server reports an xrun.
|
||||
This format is used for one polling interval when the JACK server reports an xrun.
|
||||
|
||||
*realtime*: ++
|
||||
typeof: bool ++
|
||||
@@ -59,7 +59,7 @@ Addressed by *jack*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -75,7 +75,7 @@ Addressed by *jack*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
@@ -87,7 +87,7 @@ Addressed by *jack*
|
||||
|
||||
*{bufsize}*: The size of the JACK buffer.
|
||||
|
||||
*{samplerate}*: The samplerate at which the JACK server is running.
|
||||
*{samplerate}*: The sample rate at which the JACK server is running.
|
||||
|
||||
*{latency}*: The duration, in ms, of the current buffer size.
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ You must be a member of the input group to use this module.
|
||||
# CONFIGURATION
|
||||
|
||||
*interval*: ++
|
||||
Deprecated, this module use event loop now, the interval has no effect.
|
||||
Deprecated, this module uses event loop now, the interval has no effect.
|
||||
typeof: integer ++
|
||||
default: 1 ++
|
||||
The interval, in seconds, to poll the keyboard state.
|
||||
@@ -48,6 +48,11 @@ You must be a member of the input group to use this module.
|
||||
default: chooses first valid input device ++
|
||||
Which libevdev input device to show the state of. Libevdev devices can be found in /dev/input. The device should support number lock, caps lock, and scroll lock events.
|
||||
|
||||
*binding-keys*: ++
|
||||
typeof: array ++
|
||||
default: [58, 69, 70] ++
|
||||
Customize the key to trigger this module, the key number can be found in /usr/include/linux/input-event-codes.h or running sudo libinput debug-events --show-keycodes.
|
||||
|
||||
# FORMAT REPLACEMENTS
|
||||
|
||||
*{name}*: Caps, Num, or Scroll.
|
||||
|
||||
@@ -41,7 +41,7 @@ Addressed by *memory*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -57,7 +57,7 @@ Addressed by *memory*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
|
||||
@@ -99,7 +99,7 @@ Addressed by *mpd*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -115,7 +115,7 @@ Addressed by *mpd*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
@@ -182,7 +182,7 @@ Addressed by *mpd*
|
||||
|
||||
*{queueLength}*: The length of the current queue.
|
||||
|
||||
*{stateIcon}*: The icon corresponding the playing or paused status of the player (see *state-icons* option)
|
||||
*{stateIcon}*: The icon corresponding to the playing or paused status of the player (see *state-icons* option)
|
||||
|
||||
*{consumeIcon}*: The icon corresponding the "consume" option (see *consume-icons* option)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ The *mpris* module displays currently playing media via libplayerctl.
|
||||
*player*: ++
|
||||
typeof: string ++
|
||||
default: playerctld ++
|
||||
Name of the MPRIS player to attach to. Using the default value always follows the currenly active player.
|
||||
Name of the MPRIS player to attach to. Using the default value always follows the currently active player.
|
||||
|
||||
*ignored-players*: ++
|
||||
typeof: []string ++
|
||||
@@ -21,6 +21,7 @@ The *mpris* module displays currently playing media via libplayerctl.
|
||||
|
||||
*interval*: ++
|
||||
typeof: integer ++
|
||||
default: 0 ++
|
||||
Refresh MPRIS information on a timer.
|
||||
|
||||
*format*: ++
|
||||
@@ -97,7 +98,7 @@ The *mpris* module displays currently playing media via libplayerctl.
|
||||
*enable-tooltip-len-limits*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
Option to enable the length limits for the tooltip as well. By default the tooltip ignores all length limits.
|
||||
Option to enable the length limits for the tooltip as well. By default, the tooltip ignores all length limits.
|
||||
|
||||
*ellipsis*: ++
|
||||
typeof: string ++
|
||||
@@ -114,7 +115,7 @@ The *mpris* module displays currently playing media via libplayerctl.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -126,12 +127,12 @@ The *mpris* module displays currently playing media via libplayerctl.
|
||||
default: play-pause ++
|
||||
Overwrite default action toggles.
|
||||
|
||||
*on-middle-click*: ++
|
||||
*on-click-middle*: ++
|
||||
typeof: string ++
|
||||
default: previous track ++
|
||||
Overwrite default action toggles.
|
||||
|
||||
*on-right-click*: ++
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
default: next track ++
|
||||
Overwrite default action toggles.
|
||||
|
||||
@@ -14,7 +14,7 @@ Addressed by *network*
|
||||
|
||||
*interface*: ++
|
||||
typeof: string ++
|
||||
Use the defined interface instead of auto detection. Accepts wildcard.
|
||||
Use the defined interface instead of auto-detection. Accepts wildcard.
|
||||
|
||||
*interval*: ++
|
||||
typeof: integer ++
|
||||
@@ -41,7 +41,7 @@ Addressed by *network*
|
||||
|
||||
*format-linked*: ++
|
||||
typeof: string ++
|
||||
This format is used when a linked interface with no ip address is displayed.
|
||||
This format is used when a linked interface with no IP address is displayed.
|
||||
|
||||
*format-disconnected*: ++
|
||||
typeof: string ++
|
||||
@@ -66,7 +66,7 @@ Addressed by *network*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -82,7 +82,7 @@ Addressed by *network*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
|
||||
83
man/waybar-pulseaudio-slider.5.scd
Normal file
83
man/waybar-pulseaudio-slider.5.scd
Normal file
@@ -0,0 +1,83 @@
|
||||
waybar-pulseaudio-slider(5)
|
||||
|
||||
# NAME
|
||||
|
||||
waybar - pulseaudio slider module
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
The *pulseaudio slider* module displays and controls the current volume of the default sink or source as a bar.
|
||||
|
||||
The volume can be controlled by dragging the slider across the bar or clicking on a specific position.
|
||||
|
||||
# CONFIGURATION
|
||||
|
||||
*min*: ++
|
||||
typeof: int ++
|
||||
default: 0 ++
|
||||
The minimum volume value the slider should display and set.
|
||||
|
||||
*max*: ++
|
||||
typeof: int ++
|
||||
default: 100 ++
|
||||
The maximum volume value the slider should display and set.
|
||||
|
||||
*orientation*: ++
|
||||
typeof: string ++
|
||||
default: horizontal ++
|
||||
The orientation of the slider. Can be either `horizontal` or `vertical`.
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
```
|
||||
"modules-right": [
|
||||
"pulseaudio-slider",
|
||||
],
|
||||
"pulseaudio/slider": {
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"orientation": "horizontal"
|
||||
}
|
||||
```
|
||||
|
||||
# STYLE
|
||||
|
||||
The slider is a component with multiple CSS Nodes, of which the following are exposed:
|
||||
|
||||
*#pulseaudio-slider*: ++
|
||||
Controls the style of the box *around* the slider and bar.
|
||||
|
||||
*#pulseaudio-slider slider*: ++
|
||||
Controls the style of the slider handle.
|
||||
|
||||
*#pulseaudio-slider trough*: ++
|
||||
Controls the style of the part of the bar that has not been filled.
|
||||
|
||||
*#pulseaudio-slider highlight*: ++
|
||||
Controls the style of the part of the bar that has been filled.
|
||||
|
||||
## STYLE EXAMPLE
|
||||
|
||||
```
|
||||
#pulseaudio-slider slider {
|
||||
min-height: 0px;
|
||||
min-width: 0px;
|
||||
opacity: 0;
|
||||
background-image: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#pulseaudio-slider trough {
|
||||
min-height: 80px;
|
||||
min-width: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
#pulseaudio-slider highlight {
|
||||
min-width: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: green;
|
||||
}
|
||||
```
|
||||
@@ -8,7 +8,7 @@ waybar - pulseaudio module
|
||||
|
||||
The *pulseaudio* module displays the current volume reported by PulseAudio.
|
||||
|
||||
Additionally you can control the volume by scrolling *up* or *down* while the cursor is over the module.
|
||||
Additionally, you can control the volume by scrolling *up* or *down* while the cursor is over the module.
|
||||
|
||||
# CONFIGURATION
|
||||
|
||||
@@ -36,7 +36,7 @@ Additionally you can control the volume by scrolling *up* or *down* while the cu
|
||||
|
||||
*format-icons*: ++
|
||||
typeof: array ++
|
||||
Based on the current port-name and volume, the corresponding icon gets selected. The order is *low* to *high*. See *Icons*.
|
||||
Based on the current port name and volume, the corresponding icon gets selected. The order is *low* to *high*. See *Icons*.
|
||||
|
||||
*rotate*: ++
|
||||
typeof: integer ++
|
||||
@@ -52,7 +52,7 @@ Additionally you can control the volume by scrolling *up* or *down* while the cu
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -61,7 +61,7 @@ Additionally you can control the volume by scrolling *up* or *down* while the cu
|
||||
*scroll-step*: ++
|
||||
typeof: float ++
|
||||
default: 1.0 ++
|
||||
The speed in which to change the volume when scrolling.
|
||||
The speed at which to change the volume when scrolling.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
@@ -73,7 +73,7 @@ Additionally you can control the volume by scrolling *up* or *down* while the cu
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
@@ -107,7 +107,7 @@ Additionally you can control the volume by scrolling *up* or *down* while the cu
|
||||
|
||||
*ignored-sinks*: ++
|
||||
typeof: array ++
|
||||
Sinks in this list will not be shown as the active sink by Waybar. Entries should be the sink's description field.
|
||||
Sinks in this list will not be shown as active sink by Waybar. Entries should be the sink's description field.
|
||||
|
||||
# FORMAT REPLACEMENTS
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ Addressed by *river/layout*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -45,7 +45,7 @@ Addressed by *river/layout*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
# EXAMPLE
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ Addressed by *river/mode*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -43,7 +43,7 @@ Addressed by *river/mode*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
|
||||
@@ -24,7 +24,7 @@ Addressed by *river/tags*
|
||||
*disable-click*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
If set to false, you can left click to set focused tag. Right click to toggle tag focus. If set to true this behaviour is disabled.
|
||||
If set to false, you can left-click to set focused tag. Right-click to toggle tag focus. If set to true this behaviour is disabled.
|
||||
|
||||
# EXAMPLE
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ Addressed by *river/window*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -43,7 +43,7 @@ Addressed by *river/window*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ cursor is over the module, and clicking on the module toggles mute.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -37,7 +37,7 @@ cursor is over the module, and clicking on the module toggles mute.
|
||||
*scroll-step*: ++
|
||||
typeof: int ++
|
||||
default: 5 ++
|
||||
The speed in which to change the volume when scrolling.
|
||||
The speed at which to change the volume when scrolling.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
@@ -50,7 +50,7 @@ cursor is over the module, and clicking on the module toggles mute.
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
|
||||
@@ -27,7 +27,7 @@ Addressed by *sway/mode*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -43,7 +43,7 @@ Addressed by *sway/mode*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
|
||||
@@ -27,7 +27,7 @@ Addressed by *sway/window*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -43,7 +43,7 @@ Addressed by *sway/window*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
@@ -78,7 +78,7 @@ Addressed by *sway/window*
|
||||
|
||||
*offscreen-css-text*: ++
|
||||
typeof: string ++
|
||||
Only effective when both all-outputs and offscreen-style are true. On screens currently not focused, show the given text along with that workspaces styles.
|
||||
Only effective when both all-outputs and offscreen-style are true. On screens currently not focused, show the given text along with that workspace styles.
|
||||
|
||||
*show-focused-workspace-name*: ++
|
||||
typeof: bool ++
|
||||
@@ -106,7 +106,7 @@ Addressed by *sway/window*
|
||||
*{app_id}*: The app_id of the focused window.
|
||||
|
||||
*{shell}*: The shell of the focused window. It's 'xwayland' when the window is
|
||||
running through xwayland, otherwise it's 'xdg-shell'.
|
||||
running through xwayland, otherwise, it's 'xdg-shell'.
|
||||
|
||||
# REWRITE RULES
|
||||
|
||||
|
||||
@@ -60,10 +60,10 @@ Addressed by *sway/workspaces*
|
||||
default: false ++
|
||||
If set to true. Only focused workspaces will be shown.
|
||||
|
||||
*persistent_workspaces*: ++
|
||||
*persistent-workspaces*: ++
|
||||
typeof: json (see below) ++
|
||||
default: empty ++
|
||||
Lists workspaces that should always be shown, even when non existent
|
||||
Lists workspaces that should always be shown, even when non-existent
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
@@ -98,11 +98,11 @@ warp-on-scroll: ++
|
||||
|
||||
Additional to workspace name matching, the following *format-icons* can be set.
|
||||
|
||||
- *default*: Will be shown, when no string matches is found.
|
||||
- *default*: Will be shown, when no string matches are found.
|
||||
- *urgent*: Will be shown, when workspace is flagged as urgent
|
||||
- *focused*: Will be shown, when workspace is focused
|
||||
- *persistent*: Will be shown, when workspace is persistent one.
|
||||
- *high-priority-named*: Icons by names will be shown always for that workspaces, independent by state.
|
||||
- *persistent*: Will be shown, when workspace is persistent.
|
||||
- *high-priority-named*: Icons by names will be shown always for those workspaces, independent by state.
|
||||
|
||||
# PERSISTENT WORKSPACES
|
||||
|
||||
@@ -112,10 +112,10 @@ an empty list denoting all outputs.
|
||||
|
||||
```
|
||||
"sway/workspaces": {
|
||||
"persistent_workspaces": {
|
||||
"3": [], // Always show a workspace with name '3', on all outputs if it does not exists
|
||||
"4": ["eDP-1"], // Always show a workspace with name '4', on output 'eDP-1' if it does not exists
|
||||
"5": ["eDP-1", "DP-2"] // Always show a workspace with name '5', on outputs 'eDP-1' and 'DP-2' if it does not exists
|
||||
"persistent-workspaces": {
|
||||
"3": [], // Always show a workspace with name '3', on all outputs if it does not exist
|
||||
"4": ["eDP-1"], // Always show a workspace with name '4', on output 'eDP-1' if it does not exist
|
||||
"5": ["eDP-1", "DP-2"] // Always show a workspace with name '5', on outputs 'eDP-1' and 'DP-2' if it does not exist
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -67,7 +67,7 @@ Addressed by *temperature*
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -75,7 +75,7 @@ Addressed by *temperature*
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you clicked on the module.
|
||||
Command to execute when you click on the module.
|
||||
|
||||
*on-click-middle*: ++
|
||||
typeof: string ++
|
||||
@@ -83,7 +83,7 @@ Addressed by *temperature*
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
|
||||
@@ -43,7 +43,7 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
|
||||
|
||||
*min-length*: ++
|
||||
typeof: integer ++
|
||||
The minimum length in characters the module should take up.
|
||||
The minimum length in characters the module should accept.
|
||||
|
||||
*align*: ++
|
||||
typeof: float ++
|
||||
@@ -52,7 +52,7 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
|
||||
*scroll-step*: ++
|
||||
typeof: float ++
|
||||
default: 1.0 ++
|
||||
The speed in which to change the volume when scrolling.
|
||||
The speed at which to change the volume when scrolling.
|
||||
|
||||
*on-click*: ++
|
||||
typeof: string ++
|
||||
@@ -64,7 +64,7 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
|
||||
|
||||
*on-click-right*: ++
|
||||
typeof: string ++
|
||||
Command to execute when you right clicked on the module.
|
||||
Command to execute when you right-click on the module.
|
||||
|
||||
*on-update*: ++
|
||||
typeof: string ++
|
||||
|
||||
@@ -16,7 +16,7 @@ Addressed by *wlr/taskbar*
|
||||
*all-outputs*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
If set to false applications on the waybar's current output will be shown. Otherwise all applications are shown.
|
||||
If set to false applications on the waybar's current output will be shown. Otherwise, all applications are shown.
|
||||
|
||||
*format*: ++
|
||||
typeof: string ++
|
||||
@@ -89,7 +89,7 @@ Addressed by *wlr/taskbar*
|
||||
|
||||
*{icon}*: The icon of the application.
|
||||
|
||||
*{name}*: The application name as in desktop file if appropriate desktop fils found, otherwise same as {app_id}
|
||||
*{name}*: The application name as in desktop file if appropriate desktop files are found, otherwise same as {app_id}
|
||||
|
||||
*{title}*: The title of the application.
|
||||
|
||||
|
||||
@@ -30,17 +30,17 @@ Addressed by *wlr/workspaces*
|
||||
typeof: bool ++
|
||||
default: true ++
|
||||
Should workspaces be sorted by coordinates. ++
|
||||
Note that if both *sort-by-name* and *sort-by-coordinates* are true sort by name will be first. If both are false - sort by id will be performed.
|
||||
Note that if both *sort-by-name* and *sort-by-coordinates* are true sort-by name will be first. If both are false - sort by id will be performed.
|
||||
|
||||
*sort-by-number*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
If set to true, workspace names will be sorted numerically. Takes presedence over any other sort-by option.
|
||||
If set to true, workspace names will be sorted numerically. Takes precedence over any other sort-by option.
|
||||
|
||||
*all-outputs*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
If set to false workspaces group will be shown only in assigned output. Otherwise all workspace groups are shown.
|
||||
If set to false workspaces group will be shown only in assigned output. Otherwise, all workspace groups are shown.
|
||||
|
||||
*active-only*: ++
|
||||
typeof: bool ++
|
||||
@@ -61,7 +61,7 @@ Addressed by *wlr/workspaces*
|
||||
|
||||
# ICONS
|
||||
|
||||
Additional to workspace name matching, the following *format-icons* can be set.
|
||||
In addition to workspace name matching, the following *format-icons* can be set.
|
||||
|
||||
- *default*: Will be shown, when no string match is found.
|
||||
- *active*: Will be shown, when workspace is active
|
||||
|
||||
@@ -17,7 +17,7 @@ Valid locations for this file are:
|
||||
- *@sysconfdir@/xdg/waybar/config*
|
||||
|
||||
A good starting point is the default configuration found at https://github.com/Alexays/Waybar/blob/master/resources/config
|
||||
Also a minimal example configuration can be found on the at the bottom of this man page.
|
||||
Also, a minimal example configuration can be found at the bottom of this man page.
|
||||
|
||||
# BAR CONFIGURATION
|
||||
|
||||
@@ -30,7 +30,7 @@ Also a minimal example configuration can be found on the at the bottom of this m
|
||||
*output* ++
|
||||
typeof: string|array ++
|
||||
Specifies on which screen this bar will be displayed. Exclamation mark(*!*) can be used to exclude specific output.
|
||||
Output specification follows sway's and can either be the output port such as "HDMI-A-1" or a string consisting of the make, model and serial such as "Some Company ABC123 0x00000000". See *sway-output(5)* for details.
|
||||
Output specification follows sway's and can either be the output port such as "HDMI-A-1" or a string consisting of the make, model, and serial such as "Some Company ABC123 0x00000000". See *sway-output(5)* for details.
|
||||
In an array, star '*\**' can be used at the end to accept all outputs, in case all previous entries are exclusions.
|
||||
|
||||
*position* ++
|
||||
@@ -68,7 +68,7 @@ Also a minimal example configuration can be found on the at the bottom of this m
|
||||
|
||||
*spacing* ++
|
||||
typeof: integer ++
|
||||
Size of gaps in between of the different modules.
|
||||
Size of gaps in between the different modules.
|
||||
|
||||
*name* ++
|
||||
typeof: string ++
|
||||
@@ -89,7 +89,7 @@ Also a minimal example configuration can be found on the at the bottom of this m
|
||||
default: *press*
|
||||
Defines the timing of modifier key to reset the bar visibility.
|
||||
To reset the visibility of the bar with the press of the modifier key use *press*.
|
||||
Use *release* to reset the visibility upon the release of the modifier key and only if no other action happened while the key was pressed. This prevents hiding the bar when the modifier is used to switch a workspace, change binding mode or start a keybinding.
|
||||
Use *release* to reset the visibility upon the release of the modifier key and only if no other action happened while the key was pressed. This prevents hiding the bar when the modifier is used to switch a workspace, change binding mode, or start a keybinding.
|
||||
|
||||
*exclusive* ++
|
||||
typeof: bool ++
|
||||
@@ -118,11 +118,11 @@ Also a minimal example configuration can be found on the at the bottom of this m
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
Option to subscribe to the Sway IPC bar configuration and visibility events and control waybar with *swaymsg bar* commands. ++
|
||||
Requires *bar_id* value from sway configuration to be either passed with the *-b* commandline argument or specified with the *id* option.
|
||||
Requires *bar_id* value from sway configuration to be either passed with the *-b* command line argument or specified with the *id* option.
|
||||
|
||||
*id* ++
|
||||
typeof: string ++
|
||||
*bar_id* for the Sway IPC. Use this if you need to override the value passed with the *-b bar_id* commandline argument for the specific bar instance.
|
||||
*bar_id* for the Sway IPC. Use this if you need to override the value passed with the *-b bar_id* command line argument for the specific bar instance.
|
||||
|
||||
*include* ++
|
||||
typeof: string|array ++
|
||||
@@ -142,7 +142,7 @@ e.g.
|
||||
# MULTIPLE INSTANCES OF A MODULE
|
||||
|
||||
If you want to have a second instance of a module, you can suffix it by a '#' and a custom name.
|
||||
For example if you want a second battery module, you can add *"battery#bat2"* to your modules.
|
||||
For example, if you want a second battery module, you can add *"battery#bat2"* to your modules.
|
||||
To configure the newly added module, you then also add a module configuration with the same name.
|
||||
|
||||
This could then look something like this *(this is an incomplete example)*:
|
||||
@@ -236,11 +236,11 @@ When positioning Waybar on the left or right side of the screen, sometimes it's
|
||||
}
|
||||
```
|
||||
|
||||
Valid options for the "rotate" property are: 0, 90, 180 and 270.
|
||||
Valid options for the "rotate" property are: 0, 90, 180, and 270.
|
||||
|
||||
## Grouping modules
|
||||
|
||||
Module groups allow stacking modules in the direction orthogonal to the bar direction. When the bar is positioned on the top or bottom of the screen, modules in a group are stacked vertically. Likewise, when positioned on the left or right, modules in a group are stacked horizontally.
|
||||
Module groups allow stacking modules in any direction. By default, when the bar is positioned on the top or bottom of the screen, modules in a group are stacked vertically. Likewise, when positioned on the left or right, modules in a group are stacked horizontally. This can be changed with the "orientation" property.
|
||||
|
||||
A module group is defined by specifying a module named "group/some-group-name". The group must also be configured with a list of contained modules. Example:
|
||||
|
||||
@@ -263,6 +263,43 @@ A module group is defined by specifying a module named "group/some-group-name".
|
||||
|
||||
Valid options for the (optional) "orientation" property are: "horizontal", "vertical", "inherit", and "orthogonal" (default).
|
||||
|
||||
## Group Drawers
|
||||
|
||||
A group may hide all but one element, showing them only on mouse hover. In order to configure this, you can use the `drawer` property, whose value is an object with the following properties:
|
||||
|
||||
*transition-duration*: ++
|
||||
typeof: integer ++
|
||||
default: 500 ++
|
||||
Defines the duration of the transition animation in milliseconds.
|
||||
|
||||
*children-class*: ++
|
||||
typeof: string ++
|
||||
default: "hidden" ++
|
||||
Defines the CSS class to be applied to the hidden elements.
|
||||
|
||||
*transition-left-to-right*: ++
|
||||
typeof: bool ++
|
||||
default: true ++
|
||||
Defines the direction of the transition animation. If true, the hidden elements will slide from left to right. If false, they will slide from right to left.
|
||||
When the bar is vertical, it reads as top-to-bottom.
|
||||
|
||||
```
|
||||
"group/power": {
|
||||
"orientation": "inherit",
|
||||
"drawer": {
|
||||
"transition-duration": 500,
|
||||
"children-class": "not-power",
|
||||
"transition-left-to-right": false,
|
||||
},
|
||||
"modules": [
|
||||
"custom/power", // First element is the "group leader" and won't ever be hidden
|
||||
"custom/quit",
|
||||
"custom/lock",
|
||||
"custom/reboot",
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
# SUPPORTED MODULES
|
||||
|
||||
- *waybar-backlight(5)*
|
||||
@@ -273,28 +310,39 @@ Valid options for the (optional) "orientation" property are: "horizontal", "vert
|
||||
- *waybar-cpu(5)*
|
||||
- *waybar-custom(5)*
|
||||
- *waybar-disk(5)*
|
||||
- *waybar-dwl-tags(5)*
|
||||
- *waybar-gamemode(5)*
|
||||
- *waybar-hyprland-language(5)*
|
||||
- *waybar-hyprland-submap(5)*
|
||||
- *waybar-hyprland-window(5)*
|
||||
- *waybar-hyprland-workspaces(5)*
|
||||
- *waybar-idle-inhibitor(5)*
|
||||
- *waybar-image(5)*
|
||||
- *waybar-inhibitor(5)*
|
||||
- *waybar-jack(5)*
|
||||
- *waybar-keyboard-state(5)*
|
||||
- *waybar-memory(5)*
|
||||
- *waybar-mpd(5)*
|
||||
- *waybar-mpris(5)*
|
||||
- *waybar-network(5)*
|
||||
- *waybar-pulseaudio(5)*
|
||||
- *waybar-river-layout(5)*
|
||||
- *waybar-river-mode(5)*
|
||||
- *waybar-river-tags(5)*
|
||||
- *waybar-river-window(5)*
|
||||
- *waybar-river-layout(5)*
|
||||
- *waybar-sndio(5)*
|
||||
- *waybar-states(5)*
|
||||
- *waybar-sway-language(5)*
|
||||
- *waybar-sway-mode(5)*
|
||||
- *waybar-sway-scratchpad(5)*
|
||||
- *waybar-sway-window(5)*
|
||||
- *waybar-sway-workspaces(5)*
|
||||
- *waybar-temperature(5)*
|
||||
- *waybar-tray(5)*
|
||||
- *waybar-upower(5)*
|
||||
- *waybar-wireplumber(5)*
|
||||
- *waybar-wlr-taskbar(5)*
|
||||
- *waybar-wlr-workspaces(5)*
|
||||
- *waybar-temperature(5)*
|
||||
- *waybar-tray(5)*
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
|
||||
31
meson.build
31
meson.build
@@ -1,6 +1,6 @@
|
||||
project(
|
||||
'waybar', 'cpp', 'c',
|
||||
version: '0.9.21',
|
||||
version: '0.9.23',
|
||||
license: 'MIT',
|
||||
meson_version: '>= 0.50.0',
|
||||
default_options : [
|
||||
@@ -164,18 +164,23 @@ src_files = files(
|
||||
'src/modules/disk.cpp',
|
||||
'src/modules/idle_inhibitor.cpp',
|
||||
'src/modules/image.cpp',
|
||||
'src/modules/load.cpp',
|
||||
'src/modules/temperature.cpp',
|
||||
'src/modules/user.cpp',
|
||||
'src/ASlider.cpp',
|
||||
'src/main.cpp',
|
||||
'src/bar.cpp',
|
||||
'src/client.cpp',
|
||||
'src/config.cpp',
|
||||
'src/group.cpp',
|
||||
'src/util/portal.cpp',
|
||||
'src/util/enum.cpp',
|
||||
'src/util/prepare_for_sleep.cpp',
|
||||
'src/util/ustring_clen.cpp',
|
||||
'src/util/sanitize_str.cpp',
|
||||
'src/util/rewrite_string.cpp',
|
||||
'src/util/gtk_icon.cpp'
|
||||
'src/util/gtk_icon.cpp',
|
||||
'src/util/regex_collection.cpp'
|
||||
)
|
||||
|
||||
inc_dirs = ['include']
|
||||
@@ -185,8 +190,11 @@ if is_linux
|
||||
add_project_arguments('-DHAVE_MEMORY_LINUX', language: 'cpp')
|
||||
src_files += files(
|
||||
'src/modules/battery.cpp',
|
||||
'src/modules/cpu/common.cpp',
|
||||
'src/modules/cpu/linux.cpp',
|
||||
'src/modules/cpu.cpp',
|
||||
'src/modules/cpu_frequency/common.cpp',
|
||||
'src/modules/cpu_frequency/linux.cpp',
|
||||
'src/modules/cpu_usage/common.cpp',
|
||||
'src/modules/cpu_usage/linux.cpp',
|
||||
'src/modules/memory/common.cpp',
|
||||
'src/modules/memory/linux.cpp',
|
||||
)
|
||||
@@ -194,8 +202,11 @@ elif is_dragonfly or is_freebsd or is_netbsd or is_openbsd
|
||||
add_project_arguments('-DHAVE_CPU_BSD', language: 'cpp')
|
||||
add_project_arguments('-DHAVE_MEMORY_BSD', language: 'cpp')
|
||||
src_files += files(
|
||||
'src/modules/cpu/bsd.cpp',
|
||||
'src/modules/cpu/common.cpp',
|
||||
'src/modules/cpu.cpp',
|
||||
'src/modules/cpu_frequency/bsd.cpp',
|
||||
'src/modules/cpu_frequency/common.cpp',
|
||||
'src/modules/cpu_usage/bsd.cpp',
|
||||
'src/modules/cpu_usage/common.cpp',
|
||||
'src/modules/memory/bsd.cpp',
|
||||
'src/modules/memory/common.cpp',
|
||||
)
|
||||
@@ -270,6 +281,8 @@ endif
|
||||
if libpulse.found()
|
||||
add_project_arguments('-DHAVE_LIBPULSE', language: 'cpp')
|
||||
src_files += 'src/modules/pulseaudio.cpp'
|
||||
src_files += 'src/modules/pulseaudio_slider.cpp'
|
||||
src_files += 'src/util/audio_backend.cpp'
|
||||
endif
|
||||
|
||||
if libjack.found()
|
||||
@@ -295,6 +308,8 @@ endif
|
||||
if libudev.found() and (is_linux or libepoll.found())
|
||||
add_project_arguments('-DHAVE_LIBUDEV', language: 'cpp')
|
||||
src_files += 'src/modules/backlight.cpp'
|
||||
src_files += 'src/modules/backlight_slider.cpp'
|
||||
src_files += 'src/util/backlight_backend.cpp'
|
||||
endif
|
||||
|
||||
if libevdev.found() and (is_linux or libepoll.found()) and libinput.found() and (is_linux or libinotify.found())
|
||||
@@ -346,7 +361,7 @@ if get_option('experimental')
|
||||
endif
|
||||
|
||||
cava = dependency('cava',
|
||||
version : '>=0.8.5',
|
||||
version : '>=0.9.1',
|
||||
required: get_option('cava'),
|
||||
fallback : ['cava', 'cava_dep'],
|
||||
not_found_message: 'cava is not found. Building waybar without cava')
|
||||
@@ -422,6 +437,7 @@ if scdoc.found()
|
||||
man_files = [
|
||||
main_manpage_path,
|
||||
'waybar-backlight.5.scd',
|
||||
'waybar-backlight-slider.5.scd',
|
||||
'waybar-battery.5.scd',
|
||||
'waybar-cava.5.scd',
|
||||
'waybar-clock.5.scd',
|
||||
@@ -437,6 +453,7 @@ if scdoc.found()
|
||||
'waybar-mpris.5.scd',
|
||||
'waybar-network.5.scd',
|
||||
'waybar-pulseaudio.5.scd',
|
||||
'waybar-pulseaudio-slider.5.scd',
|
||||
'waybar-river-mode.5.scd',
|
||||
'waybar-river-tags.5.scd',
|
||||
'waybar-river-window.5.scd',
|
||||
|
||||
@@ -12,7 +12,7 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
|
||||
: AModule(config, name, id, config["format-alt"].isString() || enable_click, enable_scroll),
|
||||
format_(config_["format"].isString() ? config_["format"].asString() : format),
|
||||
interval_(config_["interval"] == "once"
|
||||
? std::chrono::seconds(100000000)
|
||||
? std::chrono::seconds::max()
|
||||
: std::chrono::seconds(
|
||||
config_["interval"].isUInt() ? config_["interval"].asUInt() : interval)),
|
||||
default_format_(format_) {
|
||||
|
||||
@@ -27,18 +27,28 @@ AModule::AModule(const Json::Value& config, const std::string& name, const std::
|
||||
}
|
||||
|
||||
// configure events' user commands
|
||||
|
||||
bool hasEvent =
|
||||
// hasUserEvent is true if any element from eventMap_ is satisfying the condition in the lambda
|
||||
bool hasUserEvent =
|
||||
std::find_if(eventMap_.cbegin(), eventMap_.cend(), [&config](const auto& eventEntry) {
|
||||
return config[eventEntry.second].isString();
|
||||
// True if there is any non-release type event
|
||||
return eventEntry.first.second != GdkEventType::GDK_BUTTON_RELEASE &&
|
||||
config[eventEntry.second].isString();
|
||||
}) != eventMap_.cend();
|
||||
|
||||
if (enable_click || hasEvent) {
|
||||
if (enable_click || hasUserEvent) {
|
||||
event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
|
||||
event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &AModule::handleToggle));
|
||||
// register key release
|
||||
}
|
||||
|
||||
bool hasReleaseEvent =
|
||||
std::find_if(eventMap_.cbegin(), eventMap_.cend(), [&config](const auto& eventEntry) {
|
||||
// True if there is any non-release type event
|
||||
return eventEntry.first.second == GdkEventType::GDK_BUTTON_RELEASE &&
|
||||
config[eventEntry.second].isString();
|
||||
}) != eventMap_.cend();
|
||||
if (hasReleaseEvent) {
|
||||
event_box_.add_events(Gdk::BUTTON_RELEASE_MASK);
|
||||
event_box_.signal_button_release_event().connect(sigc::mem_fun(*this, &AModule::handleToggle));
|
||||
event_box_.signal_button_release_event().connect(sigc::mem_fun(*this, &AModule::handleRelease));
|
||||
}
|
||||
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString() || enable_scroll) {
|
||||
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
||||
@@ -70,7 +80,11 @@ auto AModule::doAction(const std::string& name) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
bool AModule::handleToggle(GdkEventButton* const& e) {
|
||||
bool AModule::handleToggle(GdkEventButton* const& e) { return handleUserEvent(e); }
|
||||
|
||||
bool AModule::handleRelease(GdkEventButton* const& e) { return handleUserEvent(e); }
|
||||
|
||||
bool AModule::handleUserEvent(GdkEventButton* const& e) {
|
||||
std::string format{};
|
||||
const std::map<std::pair<uint, GdkEventType>, std::string>::const_iterator& rec{
|
||||
eventMap_.find(std::pair(e->button, e->type))};
|
||||
|
||||
34
src/ASlider.cpp
Normal file
34
src/ASlider.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "ASlider.hpp"
|
||||
|
||||
#include "gtkmm/adjustment.h"
|
||||
#include "gtkmm/enums.h"
|
||||
|
||||
namespace waybar {
|
||||
|
||||
ASlider::ASlider(const Json::Value& config, const std::string& name, const std::string& id)
|
||||
: AModule(config, name, id, false, false),
|
||||
vertical_(config_["orientation"].asString() == "vertical"),
|
||||
scale_(vertical_ ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL) {
|
||||
scale_.set_name(name);
|
||||
if (!id.empty()) {
|
||||
scale_.get_style_context()->add_class(id);
|
||||
}
|
||||
event_box_.add(scale_);
|
||||
scale_.signal_value_changed().connect(sigc::mem_fun(*this, &ASlider::onValueChanged));
|
||||
|
||||
if (config_["min"].isUInt()) {
|
||||
min_ = config_["min"].asUInt();
|
||||
}
|
||||
|
||||
if (config_["max"].isUInt()) {
|
||||
max_ = config_["max"].asUInt();
|
||||
}
|
||||
|
||||
scale_.set_inverted(vertical_);
|
||||
scale_.set_draw_value(false);
|
||||
scale_.set_adjustment(Gtk::Adjustment::create(curr_, min_, max_ + 1, 1, 1, 1));
|
||||
}
|
||||
|
||||
void ASlider::onValueChanged() {}
|
||||
|
||||
} // namespace waybar
|
||||
65
src/bar.cpp
65
src/bar.cpp
@@ -481,6 +481,9 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
||||
: output(w_output),
|
||||
config(w_config),
|
||||
window{Gtk::WindowType::WINDOW_TOPLEVEL},
|
||||
x_global(0),
|
||||
y_global(0),
|
||||
margins_{.top = 0, .right = 0, .bottom = 0, .left = 0},
|
||||
left_(Gtk::ORIENTATION_HORIZONTAL, 0),
|
||||
center_(Gtk::ORIENTATION_HORIZONTAL, 0),
|
||||
right_(Gtk::ORIENTATION_HORIZONTAL, 0),
|
||||
@@ -516,8 +519,6 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
||||
uint32_t height = config["height"].isUInt() ? config["height"].asUInt() : 0;
|
||||
uint32_t width = config["width"].isUInt() ? config["width"].asUInt() : 0;
|
||||
|
||||
struct bar_margins margins_;
|
||||
|
||||
if (config["margin-top"].isInt() || config["margin-right"].isInt() ||
|
||||
config["margin-bottom"].isInt() || config["margin-left"].isInt()) {
|
||||
margins_ = {
|
||||
@@ -563,6 +564,10 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
||||
margins_ = {.top = gaps, .right = gaps, .bottom = gaps, .left = gaps};
|
||||
}
|
||||
|
||||
window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure));
|
||||
output->monitor->property_geometry().signal_changed().connect(
|
||||
sigc::mem_fun(*this, &Bar::onOutputGeometryChanged));
|
||||
|
||||
#ifdef HAVE_GTK_LAYER_SHELL
|
||||
bool use_gls = config["gtk-layer-shell"].isBool() ? config["gtk-layer-shell"].asBool() : true;
|
||||
if (use_gls) {
|
||||
@@ -674,6 +679,7 @@ void waybar::Bar::onMap(GdkEventAny*) {
|
||||
*/
|
||||
auto gdk_window = window.get_window()->gobj();
|
||||
surface = gdk_wayland_window_get_wl_surface(gdk_window);
|
||||
configureGlobalOffset(gdk_window_get_width(gdk_window), gdk_window_get_height(gdk_window));
|
||||
}
|
||||
|
||||
void waybar::Bar::setVisible(bool value) {
|
||||
@@ -734,7 +740,7 @@ void waybar::Bar::handleSignal(int signal) {
|
||||
}
|
||||
|
||||
void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
||||
Gtk::Box* group = nullptr) {
|
||||
waybar::Group* group = nullptr) {
|
||||
auto module_list = group ? config[pos]["modules"] : config[pos];
|
||||
if (module_list.isArray()) {
|
||||
for (const auto& name : module_list) {
|
||||
@@ -747,10 +753,11 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
||||
auto id_name = ref.substr(6, hash_pos - 6);
|
||||
auto class_name = hash_pos != std::string::npos ? ref.substr(hash_pos + 1) : "";
|
||||
|
||||
auto parent = group ? group : &this->box_;
|
||||
auto vertical = parent->get_orientation() == Gtk::ORIENTATION_VERTICAL;
|
||||
auto vertical = (group ? group->getBox().get_orientation() : box_.get_orientation()) ==
|
||||
Gtk::ORIENTATION_VERTICAL;
|
||||
|
||||
auto group_module = new waybar::Group(id_name, class_name, config[ref], vertical);
|
||||
getModules(factory, ref, &group_module->box);
|
||||
getModules(factory, ref, group_module);
|
||||
module = group_module;
|
||||
} else {
|
||||
module = factory.makeModule(ref);
|
||||
@@ -759,7 +766,7 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
||||
std::shared_ptr<AModule> module_sp(module);
|
||||
modules_all_.emplace_back(module_sp);
|
||||
if (group) {
|
||||
group->pack_start(*module, false, false);
|
||||
group->addWidget(*module);
|
||||
} else {
|
||||
if (pos == "modules-left") {
|
||||
modules_left_.emplace_back(module_sp);
|
||||
@@ -815,3 +822,47 @@ auto waybar::Bar::setupWidgets() -> void {
|
||||
right_.pack_end(*module, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
void waybar::Bar::onConfigure(GdkEventConfigure* ev) {
|
||||
configureGlobalOffset(ev->width, ev->height);
|
||||
}
|
||||
|
||||
void waybar::Bar::configureGlobalOffset(int width, int height) {
|
||||
auto monitor_geometry = *output->monitor->property_geometry().get_value().gobj();
|
||||
auto position = config["position"].asString();
|
||||
int x;
|
||||
int y;
|
||||
if (position == "bottom") {
|
||||
if (width + margins_.left + margins_.right >= monitor_geometry.width)
|
||||
x = margins_.left;
|
||||
else
|
||||
x = (monitor_geometry.width - width) / 2;
|
||||
y = monitor_geometry.height - height - margins_.bottom;
|
||||
} else if (position == "left") {
|
||||
x = margins_.left;
|
||||
if (height + margins_.top + margins_.bottom >= monitor_geometry.height)
|
||||
y = margins_.top;
|
||||
else
|
||||
y = (monitor_geometry.height - height) / 2;
|
||||
} else if (position == "right") {
|
||||
x = monitor_geometry.width - width - margins_.right;
|
||||
if (height + margins_.top + margins_.bottom >= monitor_geometry.height)
|
||||
y = margins_.top;
|
||||
else
|
||||
y = (monitor_geometry.height - height) / 2;
|
||||
} else {
|
||||
// position is top
|
||||
if (width + margins_.left + margins_.right >= monitor_geometry.width)
|
||||
x = margins_.left;
|
||||
else
|
||||
x = (monitor_geometry.width - width) / 2;
|
||||
y = margins_.top;
|
||||
}
|
||||
|
||||
x_global = x + monitor_geometry.x;
|
||||
y_global = y + monitor_geometry.y;
|
||||
}
|
||||
|
||||
void waybar::Bar::onOutputGeometryChanged() {
|
||||
configureGlobalOffset(window.get_width(), window.get_height());
|
||||
}
|
||||
|
||||
@@ -151,8 +151,26 @@ void waybar::Client::handleDeferredMonitorRemoval(Glib::RefPtr<Gdk::Monitor> mon
|
||||
outputs_.remove_if([&monitor](const auto &output) { return output.monitor == monitor; });
|
||||
}
|
||||
|
||||
const std::string waybar::Client::getStyle(const std::string &style) {
|
||||
auto css_file = style.empty() ? Config::findConfigPath({"style.css"}) : style;
|
||||
const std::string waybar::Client::getStyle(const std::string &style,
|
||||
std::optional<Appearance> appearance = std::nullopt) {
|
||||
std::optional<std::string> css_file;
|
||||
if (style.empty()) {
|
||||
std::vector<std::string> search_files;
|
||||
switch (appearance.value_or(portal->getAppearance())) {
|
||||
case waybar::Appearance::LIGHT:
|
||||
search_files.push_back("style-light.css");
|
||||
break;
|
||||
case waybar::Appearance::DARK:
|
||||
search_files.push_back("style-dark.css");
|
||||
break;
|
||||
case waybar::Appearance::UNKNOWN:
|
||||
break;
|
||||
}
|
||||
search_files.push_back("style.css");
|
||||
css_file = Config::findConfigPath(search_files);
|
||||
} else {
|
||||
css_file = style;
|
||||
}
|
||||
if (!css_file) {
|
||||
throw std::runtime_error("Missing required resource files");
|
||||
}
|
||||
@@ -235,8 +253,15 @@ int waybar::Client::main(int argc, char *argv[]) {
|
||||
}
|
||||
wl_display = gdk_wayland_display_get_wl_display(gdk_display->gobj());
|
||||
config.load(config_opt);
|
||||
if (!portal) {
|
||||
portal = std::make_unique<waybar::Portal>();
|
||||
}
|
||||
auto css_file = getStyle(style_opt);
|
||||
setupCss(css_file);
|
||||
portal->signal_appearance_changed().connect([&](waybar::Appearance appearance) {
|
||||
auto css_file = getStyle(style_opt, appearance);
|
||||
setupCss(css_file);
|
||||
});
|
||||
bindInterfaces();
|
||||
gtk_app->hold();
|
||||
gtk_app->run();
|
||||
@@ -244,4 +269,8 @@ int waybar::Client::main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void waybar::Client::reset() { gtk_app->quit(); }
|
||||
void waybar::Client::reset() {
|
||||
gtk_app->quit();
|
||||
// delete signal handler for css changes
|
||||
portal->signal_appearance_changed().clear();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
#include "factory.hpp"
|
||||
|
||||
#ifdef HAVE_LIBPULSE
|
||||
#include "modules/pulseaudio_slider.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBUDEV
|
||||
#include "modules/backlight_slider.hpp"
|
||||
#endif
|
||||
|
||||
waybar::Factory::Factory(const Bar& bar, const Json::Value& config) : bar_(bar), config_(config) {}
|
||||
|
||||
waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||
@@ -99,6 +107,17 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||
if (ref == "cpu") {
|
||||
return new waybar::modules::Cpu(id, config_[name]);
|
||||
}
|
||||
#if defined(HAVE_CPU_LINUX)
|
||||
if (ref == "cpu_frequency") {
|
||||
return new waybar::modules::CpuFrequency(id, config_[name]);
|
||||
}
|
||||
#endif
|
||||
if (ref == "cpu_usage") {
|
||||
return new waybar::modules::CpuUsage(id, config_[name]);
|
||||
}
|
||||
if (ref == "load") {
|
||||
return new waybar::modules::Load(id, config_[name]);
|
||||
}
|
||||
#endif
|
||||
if (ref == "clock") {
|
||||
return new waybar::modules::Clock(id, config_[name]);
|
||||
@@ -126,6 +145,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||
if (ref == "backlight") {
|
||||
return new waybar::modules::Backlight(id, config_[name]);
|
||||
}
|
||||
if (ref == "backlight/slider") {
|
||||
return new waybar::modules::BacklightSlider(id, config_[name]);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
if (ref == "keyboard-state") {
|
||||
@@ -136,6 +158,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||
if (ref == "pulseaudio") {
|
||||
return new waybar::modules::Pulseaudio(id, config_[name]);
|
||||
}
|
||||
if (ref == "pulseaudio/slider") {
|
||||
return new waybar::modules::PulseaudioSlider(id, config_[name]);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_LIBMPDCLIENT
|
||||
if (ref == "mpd") {
|
||||
|
||||
@@ -4,12 +4,32 @@
|
||||
|
||||
#include <util/command.hpp>
|
||||
|
||||
#include "gdkmm/device.h"
|
||||
#include "gtkmm/widget.h"
|
||||
|
||||
namespace waybar {
|
||||
|
||||
const Gtk::RevealerTransitionType getPreferredTransitionType(bool is_vertical, bool left_to_right) {
|
||||
if (is_vertical) {
|
||||
if (left_to_right) {
|
||||
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_DOWN;
|
||||
} else {
|
||||
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_UP;
|
||||
}
|
||||
} else {
|
||||
if (left_to_right) {
|
||||
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_RIGHT;
|
||||
} else {
|
||||
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_LEFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Group::Group(const std::string& name, const std::string& id, const Json::Value& config,
|
||||
bool vertical)
|
||||
: AModule(config, name, id, false, false),
|
||||
box{vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0} {
|
||||
: AModule(config, name, id, true, true),
|
||||
box{vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0},
|
||||
revealer_box{vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0} {
|
||||
box.set_name(name_);
|
||||
if (!id.empty()) {
|
||||
box.get_style_context()->add_class(id);
|
||||
@@ -29,12 +49,77 @@ Group::Group(const std::string& name, const std::string& id, const Json::Value&
|
||||
} else {
|
||||
throw std::runtime_error("Invalid orientation value: " + orientation);
|
||||
}
|
||||
|
||||
if (config_["drawer"].isObject()) {
|
||||
is_drawer = true;
|
||||
|
||||
const auto& drawer_config = config_["drawer"];
|
||||
const int transition_duration =
|
||||
(drawer_config["transition-duration"].isInt() ? drawer_config["transition-duration"].asInt()
|
||||
: 500);
|
||||
add_class_to_drawer_children =
|
||||
(drawer_config["children-class"].isString() ? drawer_config["children-class"].asString()
|
||||
: "drawer-child");
|
||||
const bool left_to_right = (drawer_config["transition-left-to-right"].isBool()
|
||||
? drawer_config["transition-left-to-right"].asBool()
|
||||
: true);
|
||||
|
||||
auto transition_type = getPreferredTransitionType(vertical, left_to_right);
|
||||
|
||||
revealer.set_transition_type(transition_type);
|
||||
revealer.set_transition_duration(transition_duration);
|
||||
revealer.set_reveal_child(false);
|
||||
|
||||
revealer.get_style_context()->add_class("drawer");
|
||||
|
||||
revealer.add(revealer_box);
|
||||
box.pack_start(revealer);
|
||||
|
||||
addHoverHandlerTo(revealer);
|
||||
}
|
||||
}
|
||||
|
||||
bool Group::handleMouseHover(GdkEventCrossing* const& e) {
|
||||
switch (e->type) {
|
||||
case GDK_ENTER_NOTIFY:
|
||||
revealer.set_reveal_child(true);
|
||||
break;
|
||||
case GDK_LEAVE_NOTIFY:
|
||||
revealer.set_reveal_child(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Group::addHoverHandlerTo(Gtk::Widget& widget) {
|
||||
widget.add_events(Gdk::EventMask::ENTER_NOTIFY_MASK | Gdk::EventMask::LEAVE_NOTIFY_MASK);
|
||||
widget.signal_enter_notify_event().connect(sigc::mem_fun(*this, &Group::handleMouseHover));
|
||||
widget.signal_leave_notify_event().connect(sigc::mem_fun(*this, &Group::handleMouseHover));
|
||||
}
|
||||
|
||||
auto Group::update() -> void {
|
||||
// noop
|
||||
}
|
||||
|
||||
Gtk::Box& Group::getBox() { return is_drawer ? (is_first_widget ? box : revealer_box) : box; }
|
||||
|
||||
void Group::addWidget(Gtk::Widget& widget) {
|
||||
getBox().pack_start(widget, false, false);
|
||||
|
||||
if (is_drawer) {
|
||||
// Necessary because of GTK's hitbox detection
|
||||
addHoverHandlerTo(widget);
|
||||
if (!is_first_widget) {
|
||||
widget.get_style_context()->add_class(add_class_to_drawer_children);
|
||||
}
|
||||
}
|
||||
|
||||
is_first_widget = false;
|
||||
}
|
||||
|
||||
Group::operator Gtk::Widget&() { return box; }
|
||||
|
||||
} // namespace waybar
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <libudev.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -9,179 +10,26 @@
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
namespace {
|
||||
class FileDescriptor {
|
||||
public:
|
||||
explicit FileDescriptor(int fd) : fd_(fd) {}
|
||||
FileDescriptor(const FileDescriptor &other) = delete;
|
||||
FileDescriptor(FileDescriptor &&other) noexcept = delete;
|
||||
FileDescriptor &operator=(const FileDescriptor &other) = delete;
|
||||
FileDescriptor &operator=(FileDescriptor &&other) noexcept = delete;
|
||||
~FileDescriptor() {
|
||||
if (fd_ != -1) {
|
||||
if (close(fd_) != 0) {
|
||||
fmt::print(stderr, "Failed to close fd: {}\n", errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
int get() const { return fd_; }
|
||||
|
||||
private:
|
||||
int fd_;
|
||||
};
|
||||
|
||||
struct UdevDeleter {
|
||||
void operator()(udev *ptr) { udev_unref(ptr); }
|
||||
};
|
||||
|
||||
struct UdevDeviceDeleter {
|
||||
void operator()(udev_device *ptr) { udev_device_unref(ptr); }
|
||||
};
|
||||
|
||||
struct UdevEnumerateDeleter {
|
||||
void operator()(udev_enumerate *ptr) { udev_enumerate_unref(ptr); }
|
||||
};
|
||||
|
||||
struct UdevMonitorDeleter {
|
||||
void operator()(udev_monitor *ptr) { udev_monitor_unref(ptr); }
|
||||
};
|
||||
|
||||
void check_eq(int rc, int expected, const char *message = "eq, rc was: ") {
|
||||
if (rc != expected) {
|
||||
throw std::runtime_error(fmt::format(fmt::runtime(message), rc));
|
||||
}
|
||||
}
|
||||
|
||||
void check_neq(int rc, int bad_rc, const char *message = "neq, rc was: ") {
|
||||
if (rc == bad_rc) {
|
||||
throw std::runtime_error(fmt::format(fmt::runtime(message), rc));
|
||||
}
|
||||
}
|
||||
|
||||
void check0(int rc, const char *message = "rc wasn't 0") { check_eq(rc, 0, message); }
|
||||
|
||||
void check_gte(int rc, int gte, const char *message = "rc was: ") {
|
||||
if (rc < gte) {
|
||||
throw std::runtime_error(fmt::format(fmt::runtime(message), rc));
|
||||
}
|
||||
}
|
||||
|
||||
void check_nn(const void *ptr, const char *message = "ptr was null") {
|
||||
if (ptr == nullptr) {
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
waybar::modules::Backlight::BacklightDev::BacklightDev(std::string name, int actual, int max,
|
||||
bool powered)
|
||||
: name_(std::move(name)), actual_(actual), max_(max), powered_(powered) {}
|
||||
|
||||
std::string_view waybar::modules::Backlight::BacklightDev::name() const { return name_; }
|
||||
|
||||
int waybar::modules::Backlight::BacklightDev::get_actual() const { return actual_; }
|
||||
|
||||
void waybar::modules::Backlight::BacklightDev::set_actual(int actual) { actual_ = actual; }
|
||||
|
||||
int waybar::modules::Backlight::BacklightDev::get_max() const { return max_; }
|
||||
|
||||
void waybar::modules::Backlight::BacklightDev::set_max(int max) { max_ = max; }
|
||||
|
||||
bool waybar::modules::Backlight::BacklightDev::get_powered() const { return powered_; }
|
||||
|
||||
void waybar::modules::Backlight::BacklightDev::set_powered(bool powered) { powered_ = powered; }
|
||||
#include "util/backend_common.hpp"
|
||||
#include "util/backlight_backend.hpp"
|
||||
|
||||
waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value &config)
|
||||
: ALabel(config, "backlight", id, "{percent}%", 2),
|
||||
preferred_device_(config["device"].isString() ? config["device"].asString() : "") {
|
||||
// Get initial state
|
||||
{
|
||||
std::unique_ptr<udev, UdevDeleter> udev_check{udev_new()};
|
||||
check_nn(udev_check.get(), "Udev check new failed");
|
||||
enumerate_devices(devices_.begin(), devices_.end(), std::back_inserter(devices_),
|
||||
udev_check.get());
|
||||
if (devices_.empty()) {
|
||||
throw std::runtime_error("No backlight found");
|
||||
}
|
||||
dp.emit();
|
||||
}
|
||||
preferred_device_(config["device"].isString() ? config["device"].asString() : ""),
|
||||
backend(interval_, [this] { dp.emit(); }) {
|
||||
dp.emit();
|
||||
|
||||
// Set up scroll handler
|
||||
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
||||
event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &Backlight::handleScroll));
|
||||
|
||||
// Connect to the login interface
|
||||
login_proxy_ = Gio::DBus::Proxy::create_for_bus_sync(
|
||||
Gio::DBus::BusType::BUS_TYPE_SYSTEM, "org.freedesktop.login1",
|
||||
"/org/freedesktop/login1/session/self", "org.freedesktop.login1.Session");
|
||||
|
||||
udev_thread_ = [this] {
|
||||
std::unique_ptr<udev, UdevDeleter> udev{udev_new()};
|
||||
check_nn(udev.get(), "Udev new failed");
|
||||
|
||||
std::unique_ptr<udev_monitor, UdevMonitorDeleter> mon{
|
||||
udev_monitor_new_from_netlink(udev.get(), "udev")};
|
||||
check_nn(mon.get(), "udev monitor new failed");
|
||||
check_gte(udev_monitor_filter_add_match_subsystem_devtype(mon.get(), "backlight", nullptr), 0,
|
||||
"udev failed to add monitor filter: ");
|
||||
udev_monitor_enable_receiving(mon.get());
|
||||
|
||||
auto udev_fd = udev_monitor_get_fd(mon.get());
|
||||
|
||||
auto epoll_fd = FileDescriptor{epoll_create1(EPOLL_CLOEXEC)};
|
||||
check_neq(epoll_fd.get(), -1, "epoll init failed: ");
|
||||
epoll_event ctl_event{};
|
||||
ctl_event.events = EPOLLIN;
|
||||
ctl_event.data.fd = udev_fd;
|
||||
|
||||
check0(epoll_ctl(epoll_fd.get(), EPOLL_CTL_ADD, ctl_event.data.fd, &ctl_event),
|
||||
"epoll_ctl failed: {}");
|
||||
epoll_event events[EPOLL_MAX_EVENTS];
|
||||
|
||||
while (udev_thread_.isRunning()) {
|
||||
const int event_count = epoll_wait(epoll_fd.get(), events, EPOLL_MAX_EVENTS,
|
||||
std::chrono::milliseconds{interval_}.count());
|
||||
if (!udev_thread_.isRunning()) {
|
||||
break;
|
||||
}
|
||||
decltype(devices_) devices;
|
||||
{
|
||||
std::scoped_lock<std::mutex> lock(udev_thread_mutex_);
|
||||
devices = devices_;
|
||||
}
|
||||
for (int i = 0; i < event_count; ++i) {
|
||||
const auto &event = events[i];
|
||||
check_eq(event.data.fd, udev_fd, "unexpected udev fd");
|
||||
std::unique_ptr<udev_device, UdevDeviceDeleter> dev{udev_monitor_receive_device(mon.get())};
|
||||
check_nn(dev.get(), "epoll dev was null");
|
||||
upsert_device(devices.begin(), devices.end(), std::back_inserter(devices), dev.get());
|
||||
}
|
||||
|
||||
// Refresh state if timed out
|
||||
if (event_count == 0) {
|
||||
enumerate_devices(devices.begin(), devices.end(), std::back_inserter(devices), udev.get());
|
||||
}
|
||||
{
|
||||
std::scoped_lock<std::mutex> lock(udev_thread_mutex_);
|
||||
devices_ = devices;
|
||||
}
|
||||
dp.emit();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
waybar::modules::Backlight::~Backlight() = default;
|
||||
|
||||
auto waybar::modules::Backlight::update() -> void {
|
||||
decltype(devices_) devices;
|
||||
{
|
||||
std::scoped_lock<std::mutex> lock(udev_thread_mutex_);
|
||||
devices = devices_;
|
||||
}
|
||||
GET_BEST_DEVICE(best, backend, preferred_device_);
|
||||
|
||||
const auto best = best_device(devices.cbegin(), devices.cend(), preferred_device_);
|
||||
const auto previous_best_device = backend.get_previous_best_device();
|
||||
if (best != nullptr) {
|
||||
if (previous_best_.has_value() && previous_best_.value() == *best &&
|
||||
if (previous_best_device != nullptr && *previous_best_device == *best &&
|
||||
!previous_format_.empty() && previous_format_ == format_) {
|
||||
return;
|
||||
}
|
||||
@@ -211,82 +59,16 @@ auto waybar::modules::Backlight::update() -> void {
|
||||
event_box_.hide();
|
||||
}
|
||||
} else {
|
||||
if (!previous_best_.has_value()) {
|
||||
if (previous_best_device == nullptr) {
|
||||
return;
|
||||
}
|
||||
label_.set_markup("");
|
||||
}
|
||||
previous_best_ = best == nullptr ? std::nullopt : std::optional{*best};
|
||||
backend.set_previous_best_device(best);
|
||||
previous_format_ = format_;
|
||||
// Call parent update
|
||||
ALabel::update();
|
||||
}
|
||||
|
||||
template <class ForwardIt>
|
||||
const waybar::modules::Backlight::BacklightDev *waybar::modules::Backlight::best_device(
|
||||
ForwardIt first, ForwardIt last, std::string_view preferred_device) {
|
||||
const auto found = std::find_if(
|
||||
first, last, [preferred_device](const auto &dev) { return dev.name() == preferred_device; });
|
||||
if (found != last) {
|
||||
return &(*found);
|
||||
}
|
||||
|
||||
const auto max = std::max_element(
|
||||
first, last, [](const auto &l, const auto &r) { return l.get_max() < r.get_max(); });
|
||||
|
||||
return max == last ? nullptr : &(*max);
|
||||
}
|
||||
|
||||
template <class ForwardIt, class Inserter>
|
||||
void waybar::modules::Backlight::upsert_device(ForwardIt first, ForwardIt last, Inserter inserter,
|
||||
udev_device *dev) {
|
||||
const char *name = udev_device_get_sysname(dev);
|
||||
check_nn(name);
|
||||
|
||||
const char *actual_brightness_attr =
|
||||
strncmp(name, "amdgpu_bl", 9) == 0 ? "brightness" : "actual_brightness";
|
||||
|
||||
const char *actual = udev_device_get_sysattr_value(dev, actual_brightness_attr);
|
||||
const char *max = udev_device_get_sysattr_value(dev, "max_brightness");
|
||||
const char *power = udev_device_get_sysattr_value(dev, "bl_power");
|
||||
|
||||
auto found =
|
||||
std::find_if(first, last, [name](const auto &device) { return device.name() == name; });
|
||||
if (found != last) {
|
||||
if (actual != nullptr) {
|
||||
found->set_actual(std::stoi(actual));
|
||||
}
|
||||
if (max != nullptr) {
|
||||
found->set_max(std::stoi(max));
|
||||
}
|
||||
if (power != nullptr) {
|
||||
found->set_powered(std::stoi(power) == 0);
|
||||
}
|
||||
} else {
|
||||
const int actual_int = actual == nullptr ? 0 : std::stoi(actual);
|
||||
const int max_int = max == nullptr ? 0 : std::stoi(max);
|
||||
const bool power_bool = power == nullptr ? true : std::stoi(power) == 0;
|
||||
*inserter = BacklightDev{name, actual_int, max_int, power_bool};
|
||||
++inserter;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ForwardIt, class Inserter>
|
||||
void waybar::modules::Backlight::enumerate_devices(ForwardIt first, ForwardIt last,
|
||||
Inserter inserter, udev *udev) {
|
||||
std::unique_ptr<udev_enumerate, UdevEnumerateDeleter> enumerate{udev_enumerate_new(udev)};
|
||||
udev_enumerate_add_match_subsystem(enumerate.get(), "backlight");
|
||||
udev_enumerate_scan_devices(enumerate.get());
|
||||
udev_list_entry *enum_devices = udev_enumerate_get_list_entry(enumerate.get());
|
||||
udev_list_entry *dev_list_entry;
|
||||
udev_list_entry_foreach(dev_list_entry, enum_devices) {
|
||||
const char *path = udev_list_entry_get_name(dev_list_entry);
|
||||
std::unique_ptr<udev_device, UdevDeviceDeleter> dev{udev_device_new_from_syspath(udev, path)};
|
||||
check_nn(dev.get(), "dev new failed");
|
||||
upsert_device(first, last, inserter, dev.get());
|
||||
}
|
||||
}
|
||||
|
||||
bool waybar::modules::Backlight::handleScroll(GdkEventScroll *e) {
|
||||
// Check if the user has set a custom command for scrolling
|
||||
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) {
|
||||
@@ -294,14 +76,33 @@ bool waybar::modules::Backlight::handleScroll(GdkEventScroll *e) {
|
||||
}
|
||||
|
||||
// Fail fast if the proxy could not be initialized
|
||||
if (!login_proxy_) {
|
||||
if (!backend.is_login_proxy_initialized()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check scroll direction
|
||||
auto dir = AModule::getScrollDir(e);
|
||||
if (dir == SCROLL_DIR::NONE) {
|
||||
return true;
|
||||
|
||||
// No worries, it will always be set because of the switch below. This is purely to suppress a
|
||||
// warning
|
||||
util::ChangeType ct = util::ChangeType::Increase;
|
||||
|
||||
switch (dir) {
|
||||
case SCROLL_DIR::UP:
|
||||
[[fallthrough]];
|
||||
case SCROLL_DIR::RIGHT:
|
||||
ct = util::ChangeType::Increase;
|
||||
break;
|
||||
|
||||
case SCROLL_DIR::DOWN:
|
||||
[[fallthrough]];
|
||||
case SCROLL_DIR::LEFT:
|
||||
ct = util::ChangeType::Decrease;
|
||||
break;
|
||||
|
||||
case SCROLL_DIR::NONE:
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Get scroll step
|
||||
@@ -311,38 +112,7 @@ bool waybar::modules::Backlight::handleScroll(GdkEventScroll *e) {
|
||||
step = config_["scroll-step"].asDouble();
|
||||
}
|
||||
|
||||
// Get the best device
|
||||
decltype(devices_) devices;
|
||||
{
|
||||
std::scoped_lock<std::mutex> lock(udev_thread_mutex_);
|
||||
devices = devices_;
|
||||
}
|
||||
const auto best = best_device(devices.cbegin(), devices.cend(), preferred_device_);
|
||||
|
||||
if (best == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compute the absolute step
|
||||
const auto abs_step = static_cast<int>(round(step * best->get_max() / 100.0f));
|
||||
|
||||
// Compute the new value
|
||||
int new_value = best->get_actual();
|
||||
|
||||
if (dir == SCROLL_DIR::UP) {
|
||||
new_value += abs_step;
|
||||
} else if (dir == SCROLL_DIR::DOWN) {
|
||||
new_value -= abs_step;
|
||||
}
|
||||
|
||||
// Clamp the value
|
||||
new_value = std::clamp(new_value, 0, best->get_max());
|
||||
|
||||
// Set the new value
|
||||
auto call_args = Glib::VariantContainerBase(
|
||||
g_variant_new("(ssu)", "backlight", std::string(best->name()).c_str(), new_value));
|
||||
|
||||
login_proxy_->call_sync("SetBrightness", call_args);
|
||||
backend.set_brightness(preferred_device_, ct, step);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
23
src/modules/backlight_slider.cpp
Normal file
23
src/modules/backlight_slider.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "modules/backlight_slider.hpp"
|
||||
|
||||
#include "ASlider.hpp"
|
||||
|
||||
namespace waybar::modules {
|
||||
|
||||
BacklightSlider::BacklightSlider(const std::string& id, const Json::Value& config)
|
||||
: ASlider(config, "backlight-slider", id),
|
||||
interval_(config_["interval"].isUInt() ? config_["interval"].asUInt() : 1000),
|
||||
preferred_device_(config["device"].isString() ? config["device"].asString() : ""),
|
||||
backend(interval_, [this] { this->dp.emit(); }) {}
|
||||
|
||||
void BacklightSlider::update() {
|
||||
uint16_t brightness = backend.get_scaled_brightness(preferred_device_);
|
||||
scale_.set_value(brightness);
|
||||
}
|
||||
|
||||
void BacklightSlider::onValueChanged() {
|
||||
auto brightness = scale_.get_value();
|
||||
backend.set_scaled_brightness(preferred_device_, brightness);
|
||||
}
|
||||
|
||||
} // namespace waybar::modules
|
||||
@@ -100,9 +100,11 @@ void waybar::modules::Battery::refreshBatteries() {
|
||||
}
|
||||
auto dir_name = node.path().filename();
|
||||
auto bat_defined = config_["bat"].isString();
|
||||
bool bat_compatibility = config_["bat-compatibility"].asBool();
|
||||
if (((bat_defined && dir_name == config_["bat"].asString()) || !bat_defined) &&
|
||||
(fs::exists(node.path() / "capacity") || fs::exists(node.path() / "charge_now")) &&
|
||||
fs::exists(node.path() / "uevent") && fs::exists(node.path() / "status") &&
|
||||
fs::exists(node.path() / "uevent") &&
|
||||
(fs::exists(node.path() / "status") || bat_compatibility) &&
|
||||
fs::exists(node.path() / "type")) {
|
||||
std::string type;
|
||||
std::ifstream(node.path() / "type") >> type;
|
||||
@@ -252,7 +254,13 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
|
||||
for (auto const& item : batteries_) {
|
||||
auto bat = item.first;
|
||||
std::string _status;
|
||||
std::getline(std::ifstream(bat / "status"), _status);
|
||||
|
||||
/* Check for adapter status if battery is not available */
|
||||
if (!std::ifstream(bat / "status")) {
|
||||
std::getline(std::ifstream(adapter_ / "status"), _status);
|
||||
} else {
|
||||
std::getline(std::ifstream(bat / "status"), _status);
|
||||
}
|
||||
|
||||
// Some battery will report current and charge in μA/μAh.
|
||||
// Scale these by the voltage to get μW/μWh.
|
||||
@@ -534,6 +542,13 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
|
||||
}
|
||||
}
|
||||
|
||||
// Handle weighted-average
|
||||
if ((config_["weighted-average"].isBool() ? config_["weighted-average"].asBool() : false) &&
|
||||
total_energy_exists && total_energy_full_exists) {
|
||||
if (total_energy_full > 0.0f)
|
||||
calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full);
|
||||
}
|
||||
|
||||
// Handle design-capacity
|
||||
if ((config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) &&
|
||||
total_energy_exists && total_energy_full_design_exists) {
|
||||
|
||||
@@ -6,12 +6,19 @@
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "util/scope_guard.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
using GDBusManager = std::unique_ptr<GDBusObjectManager, void (*)(GDBusObjectManager*)>;
|
||||
|
||||
auto generateManager() -> GDBusManager {
|
||||
GError* error = nullptr;
|
||||
waybar::util::ScopeGuard error_deleter([error]() {
|
||||
if (error) {
|
||||
g_error_free(error);
|
||||
}
|
||||
});
|
||||
GDBusObjectManager* manager = g_dbus_object_manager_client_new_for_bus_sync(
|
||||
G_BUS_TYPE_SYSTEM,
|
||||
GDBusObjectManagerClientFlags::G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START,
|
||||
@@ -19,7 +26,6 @@ auto generateManager() -> GDBusManager {
|
||||
|
||||
if (error) {
|
||||
spdlog::error("g_dbus_object_manager_client_new_for_bus_sync() failed: {}", error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
|
||||
auto destructor = [](GDBusObjectManager* manager) {
|
||||
@@ -92,28 +98,30 @@ waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value&
|
||||
std::back_inserter(device_preference_), [](auto x) { return x.asString(); });
|
||||
}
|
||||
|
||||
// NOTE: assumption made that the controller that is selcected stays unchanged
|
||||
// NOTE: assumption made that the controller that is selected stays unchanged
|
||||
// for duration of the module
|
||||
if (!findCurController(cur_controller_)) {
|
||||
if (cur_controller_ = findCurController(); !cur_controller_) {
|
||||
if (config_["controller-alias"].isString()) {
|
||||
spdlog::error("findCurController() failed: no bluetooth controller found with alias '{}'",
|
||||
config_["controller-alias"].asString());
|
||||
} else {
|
||||
spdlog::error("findCurController() failed: no bluetooth controller found");
|
||||
}
|
||||
event_box_.hide();
|
||||
return;
|
||||
}
|
||||
findConnectedDevices(cur_controller_.path, connected_devices_);
|
||||
update();
|
||||
} else {
|
||||
// These calls only make sense if a controller could be found
|
||||
findConnectedDevices(cur_controller_->path, connected_devices_);
|
||||
g_signal_connect(manager_.get(), "interface-proxy-properties-changed",
|
||||
G_CALLBACK(onInterfaceProxyPropertiesChanged), this);
|
||||
g_signal_connect(manager_.get(), "interface-added", G_CALLBACK(onInterfaceAddedOrRemoved),
|
||||
this);
|
||||
g_signal_connect(manager_.get(), "interface-removed", G_CALLBACK(onInterfaceAddedOrRemoved),
|
||||
this);
|
||||
|
||||
g_signal_connect(manager_.get(), "interface-proxy-properties-changed",
|
||||
G_CALLBACK(onInterfaceProxyPropertiesChanged), this);
|
||||
g_signal_connect(manager_.get(), "interface-added", G_CALLBACK(onInterfaceAddedOrRemoved), this);
|
||||
g_signal_connect(manager_.get(), "interface-removed", G_CALLBACK(onInterfaceAddedOrRemoved),
|
||||
this);
|
||||
#ifdef WANT_RFKILL
|
||||
rfkill_.on_update.connect(sigc::hide(sigc::mem_fun(*this, &Bluetooth::update)));
|
||||
rfkill_.on_update.connect(sigc::hide(sigc::mem_fun(*this, &Bluetooth::update)));
|
||||
#endif
|
||||
}
|
||||
|
||||
dp.emit();
|
||||
}
|
||||
@@ -144,12 +152,16 @@ auto waybar::modules::Bluetooth::update() -> void {
|
||||
|
||||
std::string state;
|
||||
std::string tooltip_format;
|
||||
if (!cur_controller_.powered)
|
||||
state = "off";
|
||||
else if (!connected_devices_.empty())
|
||||
state = "connected";
|
||||
else
|
||||
state = "on";
|
||||
if (cur_controller_) {
|
||||
if (!cur_controller_->powered)
|
||||
state = "off";
|
||||
else if (!connected_devices_.empty())
|
||||
state = "connected";
|
||||
else
|
||||
state = "on";
|
||||
} else {
|
||||
state = "no-controller";
|
||||
}
|
||||
#ifdef WANT_RFKILL
|
||||
if (rfkill_.getState()) state = "disabled";
|
||||
#endif
|
||||
@@ -187,8 +199,6 @@ auto waybar::modules::Bluetooth::update() -> void {
|
||||
tooltip_format = config_["tooltip-format"].asString();
|
||||
}
|
||||
|
||||
format_.empty() ? event_box_.hide() : event_box_.show();
|
||||
|
||||
auto update_style_context = [this](const std::string& style_class, bool in_next_state) {
|
||||
if (in_next_state && !label_.get_style_context()->has_class(style_class)) {
|
||||
label_.get_style_context()->add_class(style_class);
|
||||
@@ -196,25 +206,32 @@ auto waybar::modules::Bluetooth::update() -> void {
|
||||
label_.get_style_context()->remove_class(style_class);
|
||||
}
|
||||
};
|
||||
update_style_context("discoverable", cur_controller_.discoverable);
|
||||
update_style_context("discovering", cur_controller_.discovering);
|
||||
update_style_context("pairable", cur_controller_.pairable);
|
||||
update_style_context("discoverable", cur_controller_ ? cur_controller_->discoverable : false);
|
||||
update_style_context("discovering", cur_controller_ ? cur_controller_->discovering : false);
|
||||
update_style_context("pairable", cur_controller_ ? cur_controller_->pairable : false);
|
||||
if (!state_.empty()) {
|
||||
update_style_context(state_, false);
|
||||
}
|
||||
update_style_context(state, true);
|
||||
state_ = state;
|
||||
|
||||
label_.set_markup(fmt::format(
|
||||
fmt::runtime(format_), fmt::arg("status", state_),
|
||||
fmt::arg("num_connections", connected_devices_.size()),
|
||||
fmt::arg("controller_address", cur_controller_.address),
|
||||
fmt::arg("controller_address_type", cur_controller_.address_type),
|
||||
fmt::arg("controller_alias", cur_controller_.alias),
|
||||
fmt::arg("device_address", cur_focussed_device_.address),
|
||||
fmt::arg("device_address_type", cur_focussed_device_.address_type),
|
||||
fmt::arg("device_alias", cur_focussed_device_.alias), fmt::arg("icon", icon_label),
|
||||
fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0))));
|
||||
if (format_.empty()) {
|
||||
event_box_.hide();
|
||||
} else {
|
||||
event_box_.show();
|
||||
label_.set_markup(fmt::format(
|
||||
fmt::runtime(format_), fmt::arg("status", state_),
|
||||
fmt::arg("num_connections", connected_devices_.size()),
|
||||
fmt::arg("controller_address", cur_controller_ ? cur_controller_->address : "null"),
|
||||
fmt::arg("controller_address_type",
|
||||
cur_controller_ ? cur_controller_->address_type : "null"),
|
||||
fmt::arg("controller_alias", cur_controller_ ? cur_controller_->alias : "null"),
|
||||
fmt::arg("device_address", cur_focussed_device_.address),
|
||||
fmt::arg("device_address_type", cur_focussed_device_.address_type),
|
||||
fmt::arg("device_alias", cur_focussed_device_.alias), fmt::arg("icon", icon_label),
|
||||
fmt::arg("device_battery_percentage",
|
||||
cur_focussed_device_.battery_percentage.value_or(0))));
|
||||
}
|
||||
|
||||
if (tooltipEnabled()) {
|
||||
bool tooltip_enumerate_connections_ = config_["tooltip-format-enumerate-connected"].isString();
|
||||
@@ -250,9 +267,10 @@ auto waybar::modules::Bluetooth::update() -> void {
|
||||
label_.set_tooltip_text(fmt::format(
|
||||
fmt::runtime(tooltip_format), fmt::arg("status", state_),
|
||||
fmt::arg("num_connections", connected_devices_.size()),
|
||||
fmt::arg("controller_address", cur_controller_.address),
|
||||
fmt::arg("controller_address_type", cur_controller_.address_type),
|
||||
fmt::arg("controller_alias", cur_controller_.alias),
|
||||
fmt::arg("controller_address", cur_controller_ ? cur_controller_->address : "null"),
|
||||
fmt::arg("controller_address_type",
|
||||
cur_controller_ ? cur_controller_->address_type : "null"),
|
||||
fmt::arg("controller_alias", cur_controller_ ? cur_controller_->alias : "null"),
|
||||
fmt::arg("device_address", cur_focussed_device_.address),
|
||||
fmt::arg("device_address_type", cur_focussed_device_.address_type),
|
||||
fmt::arg("device_alias", cur_focussed_device_.alias), fmt::arg("icon", icon_tooltip),
|
||||
@@ -292,8 +310,8 @@ auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(
|
||||
|
||||
Bluetooth* bt = static_cast<Bluetooth*>(user_data);
|
||||
if (interface_name == "org.bluez.Adapter1") {
|
||||
if (object_path == bt->cur_controller_.path) {
|
||||
bt->getControllerProperties(G_DBUS_OBJECT(object_proxy), bt->cur_controller_);
|
||||
if (object_path == bt->cur_controller_->path) {
|
||||
bt->getControllerProperties(G_DBUS_OBJECT(object_proxy), *bt->cur_controller_);
|
||||
bt->dp.emit();
|
||||
}
|
||||
} else if (interface_name == "org.bluez.Device1" || interface_name == "org.bluez.Battery1") {
|
||||
@@ -378,22 +396,23 @@ auto waybar::modules::Bluetooth::getControllerProperties(GDBusObject* object,
|
||||
return false;
|
||||
}
|
||||
|
||||
auto waybar::modules::Bluetooth::findCurController(ControllerInfo& controller_info) -> bool {
|
||||
bool found_controller = false;
|
||||
auto waybar::modules::Bluetooth::findCurController() -> std::optional<ControllerInfo> {
|
||||
std::optional<ControllerInfo> controller_info;
|
||||
|
||||
GList* objects = g_dbus_object_manager_get_objects(manager_.get());
|
||||
for (GList* l = objects; l != NULL; l = l->next) {
|
||||
GDBusObject* object = G_DBUS_OBJECT(l->data);
|
||||
if (getControllerProperties(object, controller_info) &&
|
||||
ControllerInfo info;
|
||||
if (getControllerProperties(object, info) &&
|
||||
(!config_["controller-alias"].isString() ||
|
||||
config_["controller-alias"].asString() == controller_info.alias)) {
|
||||
found_controller = true;
|
||||
config_["controller-alias"].asString() == info.alias)) {
|
||||
controller_info = std::move(info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_list_free_full(objects, g_object_unref);
|
||||
|
||||
return found_controller;
|
||||
return controller_info;
|
||||
}
|
||||
|
||||
auto waybar::modules::Bluetooth::findConnectedDevices(const std::string& cur_controller_path,
|
||||
@@ -404,7 +423,7 @@ auto waybar::modules::Bluetooth::findConnectedDevices(const std::string& cur_con
|
||||
GDBusObject* object = G_DBUS_OBJECT(l->data);
|
||||
DeviceInfo device;
|
||||
if (getDeviceProperties(object, device) && device.connected &&
|
||||
device.paired_controller == cur_controller_.path) {
|
||||
device.paired_controller == cur_controller_->path) {
|
||||
connected_devices.push_back(device);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ waybar::modules::Cava::Cava(const std::string& id, const Json::Value& config)
|
||||
|
||||
// Override cava parameters by the user config
|
||||
prm_.inAtty = 0;
|
||||
prm_.output = output_method::OUTPUT_RAW;
|
||||
prm_.output = cava::output_method::OUTPUT_RAW;
|
||||
strcpy(prm_.data_format, "ascii");
|
||||
strcpy(prm_.raw_target, "/dev/stdout");
|
||||
prm_.ascii_range = config_["format-icons"].size() - 1;
|
||||
@@ -34,9 +34,9 @@ waybar::modules::Cava::Cava(const std::string& id, const Json::Value& config)
|
||||
prm_.bar_spacing = 0;
|
||||
prm_.bar_height = 32;
|
||||
prm_.bar_width = 1;
|
||||
prm_.orientation = ORIENT_TOP;
|
||||
prm_.xaxis = xaxis_scale::NONE;
|
||||
prm_.mono_opt = AVERAGE;
|
||||
prm_.orientation = cava::ORIENT_TOP;
|
||||
prm_.xaxis = cava::xaxis_scale::NONE;
|
||||
prm_.mono_opt = cava::AVERAGE;
|
||||
prm_.autobars = 0;
|
||||
prm_.gravity = 0;
|
||||
prm_.integral = 1;
|
||||
@@ -51,7 +51,7 @@ waybar::modules::Cava::Cava(const std::string& id, const Json::Value& config)
|
||||
prm_.upper_cut_off = config_["higher_cutoff_freq"].asLargestInt();
|
||||
if (config_["sleep_timer"].isInt()) prm_.sleep_timer = config_["sleep_timer"].asInt();
|
||||
if (config_["method"].isString())
|
||||
prm_.input = input_method_by_name(config_["method"].asString().c_str());
|
||||
prm_.input = cava::input_method_by_name(config_["method"].asString().c_str());
|
||||
if (config_["source"].isString()) prm_.audio_source = config_["source"].asString().data();
|
||||
if (config_["sample_rate"].isNumeric()) prm_.fifoSample = config_["sample_rate"].asLargestInt();
|
||||
if (config_["sample_bits"].isInt()) prm_.fifoSampleBits = config_["sample_bits"].asInt();
|
||||
@@ -64,8 +64,9 @@ waybar::modules::Cava::Cava(const std::string& id, const Json::Value& config)
|
||||
prm_.noise_reduction = config_["noise_reduction"].asDouble();
|
||||
if (config_["input_delay"].isInt())
|
||||
fetch_input_delay_ = std::chrono::seconds(config_["input_delay"].asInt());
|
||||
if (config_["hide_on_silence"].isBool()) hide_on_silence_ = config_["hide_on_silence"].asBool();
|
||||
// Make cava parameters configuration
|
||||
plan_ = new cava_plan{};
|
||||
plan_ = new cava::cava_plan{};
|
||||
|
||||
audio_raw_.height = prm_.ascii_range;
|
||||
audio_data_.format = -1;
|
||||
@@ -155,12 +156,13 @@ auto waybar::modules::Cava::update() -> void {
|
||||
downThreadDelay(frame_time_milsec_, suspend_silence_delay_);
|
||||
// Process: execute cava
|
||||
pthread_mutex_lock(&audio_data_.lock);
|
||||
cava_execute(audio_data_.cava_in, audio_data_.samples_counter, audio_raw_.cava_out, plan_);
|
||||
cava::cava_execute(audio_data_.cava_in, audio_data_.samples_counter, audio_raw_.cava_out,
|
||||
plan_);
|
||||
if (audio_data_.samples_counter > 0) audio_data_.samples_counter = 0;
|
||||
pthread_mutex_unlock(&audio_data_.lock);
|
||||
|
||||
// Do transformation under raw data
|
||||
audio_raw_fetch(&audio_raw_, &prm_, &rePaint_);
|
||||
audio_raw_fetch(&audio_raw_, &prm_, &rePaint_, plan_);
|
||||
|
||||
if (rePaint_ == 1) {
|
||||
text_.clear();
|
||||
@@ -174,10 +176,13 @@ auto waybar::modules::Cava::update() -> void {
|
||||
}
|
||||
|
||||
label_.set_markup(text_);
|
||||
label_.show();
|
||||
ALabel::update();
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
upThreadDelay(frame_time_milsec_, suspend_silence_delay_);
|
||||
if (hide_on_silence_) label_.hide();
|
||||
}
|
||||
}
|
||||
|
||||
auto waybar::modules::Cava::doAction(const std::string& name) -> void {
|
||||
|
||||
63
src/modules/cpu.cpp
Normal file
63
src/modules/cpu.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "modules/cpu.hpp"
|
||||
|
||||
#include "modules/cpu_frequency.hpp"
|
||||
#include "modules/cpu_usage.hpp"
|
||||
#include "modules/load.hpp"
|
||||
|
||||
// In the 80000 version of fmt library authors decided to optimize imports
|
||||
// and moved declarations required for fmt::dynamic_format_arg_store in new
|
||||
// header fmt/args.h
|
||||
#if (FMT_VERSION >= 80000)
|
||||
#include <fmt/args.h>
|
||||
#else
|
||||
#include <fmt/core.h>
|
||||
#endif
|
||||
|
||||
waybar::modules::Cpu::Cpu(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "cpu", id, "{usage}%", 10) {
|
||||
thread_ = [this] {
|
||||
dp.emit();
|
||||
thread_.sleep_for(interval_);
|
||||
};
|
||||
}
|
||||
|
||||
auto waybar::modules::Cpu::update() -> void {
|
||||
// TODO: as creating dynamic fmt::arg arrays is buggy we have to calc both
|
||||
auto [load1, load5, load15] = Load::getLoad();
|
||||
auto [cpu_usage, tooltip] = CpuUsage::getCpuUsage(prev_times_);
|
||||
auto [max_frequency, min_frequency, avg_frequency] = CpuFrequency::getCpuFrequency();
|
||||
if (tooltipEnabled()) {
|
||||
label_.set_tooltip_text(tooltip);
|
||||
}
|
||||
auto format = format_;
|
||||
auto total_usage = cpu_usage.empty() ? 0 : cpu_usage[0];
|
||||
auto state = getState(total_usage);
|
||||
if (!state.empty() && config_["format-" + state].isString()) {
|
||||
format = config_["format-" + state].asString();
|
||||
}
|
||||
|
||||
if (format.empty()) {
|
||||
event_box_.hide();
|
||||
} else {
|
||||
event_box_.show();
|
||||
auto icons = std::vector<std::string>{state};
|
||||
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
||||
store.push_back(fmt::arg("load", load1));
|
||||
store.push_back(fmt::arg("usage", total_usage));
|
||||
store.push_back(fmt::arg("icon", getIcon(total_usage, icons)));
|
||||
store.push_back(fmt::arg("max_frequency", max_frequency));
|
||||
store.push_back(fmt::arg("min_frequency", min_frequency));
|
||||
store.push_back(fmt::arg("avg_frequency", avg_frequency));
|
||||
for (size_t i = 1; i < cpu_usage.size(); ++i) {
|
||||
auto core_i = i - 1;
|
||||
auto core_format = fmt::format("usage{}", core_i);
|
||||
store.push_back(fmt::arg(core_format.c_str(), cpu_usage[i]));
|
||||
auto icon_format = fmt::format("icon{}", core_i);
|
||||
store.push_back(fmt::arg(icon_format.c_str(), getIcon(cpu_usage[i], icons)));
|
||||
}
|
||||
label_.set_markup(fmt::vformat(format, store));
|
||||
}
|
||||
|
||||
// Call parent update
|
||||
ALabel::update();
|
||||
}
|
||||
15
src/modules/cpu_frequency/bsd.cpp
Normal file
15
src/modules/cpu_frequency/bsd.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <cmath> // NAN
|
||||
|
||||
#include "modules/cpu_frequency.hpp"
|
||||
|
||||
std::vector<float> waybar::modules::CpuFrequency::parseCpuFrequencies() {
|
||||
static std::vector<float> frequencies;
|
||||
if (frequencies.empty()) {
|
||||
spdlog::warn(
|
||||
"cpu/bsd: parseCpuFrequencies is not implemented, expect garbage in {*_frequency}");
|
||||
frequencies.push_back(NAN);
|
||||
}
|
||||
return frequencies;
|
||||
}
|
||||
67
src/modules/cpu_frequency/common.cpp
Normal file
67
src/modules/cpu_frequency/common.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "modules/cpu_frequency.hpp"
|
||||
|
||||
// In the 80000 version of fmt library authors decided to optimize imports
|
||||
// and moved declarations required for fmt::dynamic_format_arg_store in new
|
||||
// header fmt/args.h
|
||||
#if (FMT_VERSION >= 80000)
|
||||
#include <fmt/args.h>
|
||||
#else
|
||||
#include <fmt/core.h>
|
||||
#endif
|
||||
|
||||
waybar::modules::CpuFrequency::CpuFrequency(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "cpu_frequency", id, "{avg_frequency}", 10) {
|
||||
thread_ = [this] {
|
||||
dp.emit();
|
||||
thread_.sleep_for(interval_);
|
||||
};
|
||||
}
|
||||
|
||||
auto waybar::modules::CpuFrequency::update() -> void {
|
||||
// TODO: as creating dynamic fmt::arg arrays is buggy we have to calc both
|
||||
auto [max_frequency, min_frequency, avg_frequency] = CpuFrequency::getCpuFrequency();
|
||||
if (tooltipEnabled()) {
|
||||
auto tooltip =
|
||||
fmt::format("Minimum frequency: {}\nAverage frequency: {}\nMaximum frequency: {}\n",
|
||||
min_frequency, avg_frequency, max_frequency);
|
||||
label_.set_tooltip_text(tooltip);
|
||||
}
|
||||
auto format = format_;
|
||||
auto state = getState(avg_frequency);
|
||||
if (!state.empty() && config_["format-" + state].isString()) {
|
||||
format = config_["format-" + state].asString();
|
||||
}
|
||||
|
||||
if (format.empty()) {
|
||||
event_box_.hide();
|
||||
} else {
|
||||
event_box_.show();
|
||||
auto icons = std::vector<std::string>{state};
|
||||
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
||||
store.push_back(fmt::arg("icon", getIcon(avg_frequency, icons)));
|
||||
store.push_back(fmt::arg("max_frequency", max_frequency));
|
||||
store.push_back(fmt::arg("min_frequency", min_frequency));
|
||||
store.push_back(fmt::arg("avg_frequency", avg_frequency));
|
||||
label_.set_markup(fmt::vformat(format, store));
|
||||
}
|
||||
|
||||
// Call parent update
|
||||
ALabel::update();
|
||||
}
|
||||
|
||||
std::tuple<float, float, float> waybar::modules::CpuFrequency::getCpuFrequency() {
|
||||
std::vector<float> frequencies = CpuFrequency::parseCpuFrequencies();
|
||||
if (frequencies.empty()) {
|
||||
return {0.f, 0.f, 0.f};
|
||||
}
|
||||
auto [min, max] = std::minmax_element(std::begin(frequencies), std::end(frequencies));
|
||||
float avg_frequency =
|
||||
std::accumulate(std::begin(frequencies), std::end(frequencies), 0.0) / frequencies.size();
|
||||
|
||||
// Round frequencies with double decimal precision to get GHz
|
||||
float max_frequency = std::ceil(*max / 10.0) / 100.0;
|
||||
float min_frequency = std::ceil(*min / 10.0) / 100.0;
|
||||
avg_frequency = std::ceil(avg_frequency / 10.0) / 100.0;
|
||||
|
||||
return {max_frequency, min_frequency, avg_frequency};
|
||||
}
|
||||
@@ -1,36 +1,8 @@
|
||||
#include <filesystem>
|
||||
|
||||
#include "modules/cpu.hpp"
|
||||
#include "modules/cpu_frequency.hpp"
|
||||
|
||||
std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
|
||||
const std::string data_dir_ = "/proc/stat";
|
||||
std::ifstream info(data_dir_);
|
||||
if (!info.is_open()) {
|
||||
throw std::runtime_error("Can't open " + data_dir_);
|
||||
}
|
||||
std::vector<std::tuple<size_t, size_t>> cpuinfo;
|
||||
std::string line;
|
||||
while (getline(info, line)) {
|
||||
if (line.substr(0, 3).compare("cpu") != 0) {
|
||||
break;
|
||||
}
|
||||
std::stringstream sline(line.substr(5));
|
||||
std::vector<size_t> times;
|
||||
for (size_t time = 0; sline >> time; times.push_back(time))
|
||||
;
|
||||
|
||||
size_t idle_time = 0;
|
||||
size_t total_time = 0;
|
||||
if (times.size() >= 4) {
|
||||
idle_time = times[3];
|
||||
total_time = std::accumulate(times.begin(), times.end(), 0);
|
||||
}
|
||||
cpuinfo.emplace_back(idle_time, total_time);
|
||||
}
|
||||
return cpuinfo;
|
||||
}
|
||||
|
||||
std::vector<float> waybar::modules::Cpu::parseCpuFrequencies() {
|
||||
std::vector<float> waybar::modules::CpuFrequency::parseCpuFrequencies() {
|
||||
const std::string file_path_ = "/proc/cpuinfo";
|
||||
std::ifstream info(file_path_);
|
||||
if (!info.is_open()) {
|
||||
@@ -8,7 +8,8 @@
|
||||
#include <cmath> // NAN
|
||||
#include <cstdlib> // malloc
|
||||
|
||||
#include "modules/cpu.hpp"
|
||||
#include "modules/cpu_usage.hpp"
|
||||
#include "util/scope_guard.hpp"
|
||||
|
||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#include <sys/sched.h>
|
||||
@@ -27,12 +28,17 @@ typedef uint64_t pcp_time_t;
|
||||
typedef long pcp_time_t;
|
||||
#endif
|
||||
|
||||
std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
|
||||
std::vector<std::tuple<size_t, size_t>> waybar::modules::CpuUsage::parseCpuinfo() {
|
||||
cp_time_t sum_cp_time[CPUSTATES];
|
||||
size_t sum_sz = sizeof(sum_cp_time);
|
||||
int ncpu = sysconf(_SC_NPROCESSORS_CONF);
|
||||
size_t sz = CPUSTATES * (ncpu + 1) * sizeof(pcp_time_t);
|
||||
pcp_time_t *cp_time = static_cast<pcp_time_t *>(malloc(sz)), *pcp_time = cp_time;
|
||||
waybar::util::ScopeGuard cp_time_deleter([cp_time]() {
|
||||
if (cp_time) {
|
||||
free(cp_time);
|
||||
}
|
||||
});
|
||||
#if defined(__NetBSD__)
|
||||
int mib[] = {
|
||||
CTL_KERN,
|
||||
@@ -97,16 +103,5 @@ std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
|
||||
}
|
||||
cpuinfo.emplace_back(single_cp_time[CP_IDLE], total);
|
||||
}
|
||||
free(cp_time);
|
||||
return cpuinfo;
|
||||
}
|
||||
|
||||
std::vector<float> waybar::modules::Cpu::parseCpuFrequencies() {
|
||||
static std::vector<float> frequencies;
|
||||
if (frequencies.empty()) {
|
||||
spdlog::warn(
|
||||
"cpu/bsd: parseCpuFrequencies is not implemented, expect garbage in {*_frequency}");
|
||||
frequencies.push_back(NAN);
|
||||
}
|
||||
return frequencies;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "modules/cpu.hpp"
|
||||
#include "modules/cpu_usage.hpp"
|
||||
|
||||
// In the 80000 version of fmt library authors decided to optimize imports
|
||||
// and moved declarations required for fmt::dynamic_format_arg_store in new
|
||||
@@ -9,19 +9,17 @@
|
||||
#include <fmt/core.h>
|
||||
#endif
|
||||
|
||||
waybar::modules::Cpu::Cpu(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "cpu", id, "{usage}%", 10) {
|
||||
waybar::modules::CpuUsage::CpuUsage(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "cpu_usage", id, "{usage}%", 10) {
|
||||
thread_ = [this] {
|
||||
dp.emit();
|
||||
thread_.sleep_for(interval_);
|
||||
};
|
||||
}
|
||||
|
||||
auto waybar::modules::Cpu::update() -> void {
|
||||
auto waybar::modules::CpuUsage::update() -> void {
|
||||
// TODO: as creating dynamic fmt::arg arrays is buggy we have to calc both
|
||||
auto cpu_load = getCpuLoad();
|
||||
auto [cpu_usage, tooltip] = getCpuUsage();
|
||||
auto [max_frequency, min_frequency, avg_frequency] = getCpuFrequency();
|
||||
auto [cpu_usage, tooltip] = CpuUsage::getCpuUsage(prev_times_);
|
||||
if (tooltipEnabled()) {
|
||||
label_.set_tooltip_text(tooltip);
|
||||
}
|
||||
@@ -38,12 +36,8 @@ auto waybar::modules::Cpu::update() -> void {
|
||||
event_box_.show();
|
||||
auto icons = std::vector<std::string>{state};
|
||||
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
||||
store.push_back(fmt::arg("load", cpu_load));
|
||||
store.push_back(fmt::arg("usage", total_usage));
|
||||
store.push_back(fmt::arg("icon", getIcon(total_usage, icons)));
|
||||
store.push_back(fmt::arg("max_frequency", max_frequency));
|
||||
store.push_back(fmt::arg("min_frequency", min_frequency));
|
||||
store.push_back(fmt::arg("avg_frequency", avg_frequency));
|
||||
for (size_t i = 1; i < cpu_usage.size(); ++i) {
|
||||
auto core_i = i - 1;
|
||||
auto core_format = fmt::format("usage{}", core_i);
|
||||
@@ -58,25 +52,18 @@ auto waybar::modules::Cpu::update() -> void {
|
||||
ALabel::update();
|
||||
}
|
||||
|
||||
double waybar::modules::Cpu::getCpuLoad() {
|
||||
double load[1];
|
||||
if (getloadavg(load, 1) != -1) {
|
||||
return std::ceil(load[0] * 100.0) / 100.0;
|
||||
}
|
||||
throw std::runtime_error("Can't get Cpu load");
|
||||
}
|
||||
|
||||
std::tuple<std::vector<uint16_t>, std::string> waybar::modules::Cpu::getCpuUsage() {
|
||||
if (prev_times_.empty()) {
|
||||
prev_times_ = parseCpuinfo();
|
||||
std::tuple<std::vector<uint16_t>, std::string> waybar::modules::CpuUsage::getCpuUsage(
|
||||
std::vector<std::tuple<size_t, size_t>>& prev_times) {
|
||||
if (prev_times.empty()) {
|
||||
prev_times = CpuUsage::parseCpuinfo();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
std::vector<std::tuple<size_t, size_t>> curr_times = parseCpuinfo();
|
||||
std::vector<std::tuple<size_t, size_t>> curr_times = CpuUsage::parseCpuinfo();
|
||||
std::string tooltip;
|
||||
std::vector<uint16_t> usage;
|
||||
for (size_t i = 0; i < curr_times.size(); ++i) {
|
||||
auto [curr_idle, curr_total] = curr_times[i];
|
||||
auto [prev_idle, prev_total] = prev_times_[i];
|
||||
auto [prev_idle, prev_total] = prev_times[i];
|
||||
const float delta_idle = curr_idle - prev_idle;
|
||||
const float delta_total = curr_total - prev_total;
|
||||
uint16_t tmp = 100 * (1 - delta_idle / delta_total);
|
||||
@@ -87,23 +74,6 @@ std::tuple<std::vector<uint16_t>, std::string> waybar::modules::Cpu::getCpuUsage
|
||||
}
|
||||
usage.push_back(tmp);
|
||||
}
|
||||
prev_times_ = curr_times;
|
||||
prev_times = curr_times;
|
||||
return {usage, tooltip};
|
||||
}
|
||||
|
||||
std::tuple<float, float, float> waybar::modules::Cpu::getCpuFrequency() {
|
||||
std::vector<float> frequencies = parseCpuFrequencies();
|
||||
if (frequencies.empty()) {
|
||||
return {0.f, 0.f, 0.f};
|
||||
}
|
||||
auto [min, max] = std::minmax_element(std::begin(frequencies), std::end(frequencies));
|
||||
float avg_frequency =
|
||||
std::accumulate(std::begin(frequencies), std::end(frequencies), 0.0) / frequencies.size();
|
||||
|
||||
// Round frequencies with double decimal precision to get GHz
|
||||
float max_frequency = std::ceil(*max / 10.0) / 100.0;
|
||||
float min_frequency = std::ceil(*min / 10.0) / 100.0;
|
||||
avg_frequency = std::ceil(avg_frequency / 10.0) / 100.0;
|
||||
|
||||
return {max_frequency, min_frequency, avg_frequency};
|
||||
}
|
||||
31
src/modules/cpu_usage/linux.cpp
Normal file
31
src/modules/cpu_usage/linux.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <filesystem>
|
||||
|
||||
#include "modules/cpu_usage.hpp"
|
||||
|
||||
std::vector<std::tuple<size_t, size_t>> waybar::modules::CpuUsage::parseCpuinfo() {
|
||||
const std::string data_dir_ = "/proc/stat";
|
||||
std::ifstream info(data_dir_);
|
||||
if (!info.is_open()) {
|
||||
throw std::runtime_error("Can't open " + data_dir_);
|
||||
}
|
||||
std::vector<std::tuple<size_t, size_t>> cpuinfo;
|
||||
std::string line;
|
||||
while (getline(info, line)) {
|
||||
if (line.substr(0, 3).compare("cpu") != 0) {
|
||||
break;
|
||||
}
|
||||
std::stringstream sline(line.substr(5));
|
||||
std::vector<size_t> times;
|
||||
for (size_t time = 0; sline >> time; times.push_back(time))
|
||||
;
|
||||
|
||||
size_t idle_time = 0;
|
||||
size_t total_time = 0;
|
||||
if (times.size() >= 4) {
|
||||
idle_time = times[3];
|
||||
total_time = std::accumulate(times.begin(), times.end(), 0);
|
||||
}
|
||||
cpuinfo.emplace_back(idle_time, total_time);
|
||||
}
|
||||
return cpuinfo;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user