Merge branch 'master' into hyprland-window_no_title_from_special
This commit is contained in:
+12
-12
@@ -15,15 +15,15 @@ Checks: >
|
|||||||
-readability-redundant-member-init,
|
-readability-redundant-member-init,
|
||||||
-readability-redundant-string-init,
|
-readability-redundant-string-init,
|
||||||
-readability-identifier-length
|
-readability-identifier-length
|
||||||
CheckOptions:
|
# CheckOptions:
|
||||||
- { key: readability-identifier-naming.NamespaceCase, value: lower_case }
|
# - { key: readability-identifier-naming.NamespaceCase, value: lower_case }
|
||||||
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
|
# - { key: readability-identifier-naming.ClassCase, value: CamelCase }
|
||||||
- { key: readability-identifier-naming.StructCase, value: CamelCase }
|
# - { key: readability-identifier-naming.StructCase, value: CamelCase }
|
||||||
- { key: readability-identifier-naming.FunctionCase, value: camelBack }
|
# - { key: readability-identifier-naming.FunctionCase, value: camelBack }
|
||||||
- { key: readability-identifier-naming.VariableCase, value: camelBack }
|
# - { key: readability-identifier-naming.VariableCase, value: camelBack }
|
||||||
- { key: readability-identifier-naming.PrivateMemberCase, value: camelBack }
|
# - { key: readability-identifier-naming.PrivateMemberCase, value: camelBack }
|
||||||
- { key: readability-identifier-naming.PrivateMemberPrefix, value: m_ }
|
# - { key: readability-identifier-naming.PrivateMemberSuffix, value: _ }
|
||||||
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
|
# - { key: readability-identifier-naming.EnumCase, value: CamelCase }
|
||||||
- { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE }
|
# - { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE }
|
||||||
- { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }
|
# - { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }
|
||||||
- { key: readability-identifier-naming.StaticConstantCase, value: UPPER_CASE }
|
# - { key: readability-identifier-naming.StaticConstantCase, value: UPPER_CASE }
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
name: Build and Push Docker Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# run every night at midnight
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false # don't fail the other jobs if one of the images fails to build
|
||||||
|
matrix:
|
||||||
|
os: [ 'alpine', 'archlinux', 'debian', 'fedora', 'gentoo', 'opensuse' ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: Dockerfiles/${{ matrix.os }}
|
||||||
|
push: true
|
||||||
|
tags: alexays/waybar:${{ matrix.os }}
|
||||||
@@ -8,26 +8,29 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
clang:
|
clang:
|
||||||
# Run actions in a FreeBSD VM on the macos-12 runner
|
# Run actions in a FreeBSD VM on the ubuntu runner
|
||||||
# https://github.com/actions/runner/issues/385 - for FreeBSD runner support
|
# https://github.com/actions/runner/issues/385 - for FreeBSD runner support
|
||||||
# https://github.com/actions/virtual-environments/issues/4060 - for lack of VirtualBox on MacOS 11 runners
|
runs-on: ubuntu-latest
|
||||||
runs-on: macos-12
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Test in FreeBSD VM
|
- name: Test in FreeBSD VM
|
||||||
uses: cross-platform-actions/action@v0.21.1
|
uses: cross-platform-actions/action@v0.23.0
|
||||||
timeout-minutes: 180
|
timeout-minutes: 180
|
||||||
|
env:
|
||||||
|
CPPFLAGS: '-isystem/usr/local/include'
|
||||||
|
LDFLAGS: '-L/usr/local/lib'
|
||||||
with:
|
with:
|
||||||
operating_system: freebsd
|
operating_system: freebsd
|
||||||
version: "13.2"
|
version: "13.2"
|
||||||
environment_variables: CPPFLAGS=-isystem/usr/local/include LDFLAGS=-L/usr/local/lib
|
environment_variables: CPPFLAGS LDFLAGS
|
||||||
|
sync_files: runner-to-vm
|
||||||
run: |
|
run: |
|
||||||
sudo sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
|
sudo sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
|
||||||
sudo pkg install -y git # subprojects/date
|
sudo pkg install -y git # subprojects/date
|
||||||
sudo pkg install -y catch evdev-proto gtk-layer-shell gtkmm30 jsoncpp \
|
sudo pkg install -y catch evdev-proto gtk-layer-shell gtkmm30 jsoncpp \
|
||||||
libdbusmenu libevdev libfmt libmpdclient libudev-devd meson \
|
libdbusmenu libevdev libfmt libmpdclient libudev-devd meson \
|
||||||
pkgconf pulseaudio scdoc sndio spdlog wayland-protocols upower \
|
pkgconf pipewire pulseaudio scdoc sndio spdlog wayland-protocols upower \
|
||||||
libinotify
|
libinotify
|
||||||
meson build -Dman-pages=enabled
|
meson setup build -Dman-pages=enabled
|
||||||
ninja -C build
|
ninja -C build
|
||||||
meson test -C build --no-rebuild --print-errorlogs --suite waybar
|
meson test -C build --no-rebuild --print-errorlogs --suite waybar
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
distro:
|
distro:
|
||||||
- alpine
|
- alpine
|
||||||
@@ -26,7 +27,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: configure
|
- name: configure
|
||||||
run: meson -Dman-pages=enabled -Dcpp_std=${{matrix.cpp_std}} build
|
run: meson setup -Dman-pages=enabled -Dcpp_std=${{matrix.cpp_std}} build
|
||||||
- name: build
|
- name: build
|
||||||
run: ninja -C build
|
run: ninja -C build
|
||||||
- name: test
|
- name: test
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
name: "Nix-Tests"
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
jobs:
|
||||||
|
nix-flake-check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: cachix/install-nix-action@v27
|
||||||
|
with:
|
||||||
|
extra_nix_config: |
|
||||||
|
experimental-features = nix-command flakes
|
||||||
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- run: nix flake show
|
||||||
|
- run: nix flake check --print-build-logs
|
||||||
|
- run: nix build --print-build-logs
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
name: update-flake-lock
|
||||||
|
on:
|
||||||
|
workflow_dispatch: # allows manual triggering
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 1 * *' # Run monthly
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'flake.nix'
|
||||||
|
jobs:
|
||||||
|
lockfile:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Install Nix
|
||||||
|
uses: cachix/install-nix-action@v27
|
||||||
|
with:
|
||||||
|
extra_nix_config: |
|
||||||
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Update flake.lock
|
||||||
|
uses: DeterminateSystems/update-flake-lock@v21
|
||||||
@@ -48,3 +48,5 @@ packagecache
|
|||||||
# Nix
|
# Nix
|
||||||
result
|
result
|
||||||
result-*
|
result-*
|
||||||
|
|
||||||
|
.ccls-cache
|
||||||
|
|||||||
@@ -3,5 +3,5 @@
|
|||||||
FROM archlinux:base-devel
|
FROM archlinux:base-devel
|
||||||
|
|
||||||
RUN pacman -Syu --noconfirm && \
|
RUN pacman -Syu --noconfirm && \
|
||||||
pacman -S --noconfirm git meson base-devel libinput wayland wayland-protocols pixman libxkbcommon mesa gtkmm3 jsoncpp pugixml scdoc libpulse libdbusmenu-gtk3 libmpdclient gobject-introspection libxkbcommon playerctl iniparser fftw && \
|
pacman -S --noconfirm git meson base-devel libinput wayland wayland-protocols glib2-devel pixman libxkbcommon mesa gtkmm3 jsoncpp pugixml scdoc libpulse libdbusmenu-gtk3 libmpdclient gobject-introspection libxkbcommon playerctl iniparser fftw && \
|
||||||
sed -Ei 's/#(en_(US|GB)\.UTF)/\1/' /etc/locale.gen && locale-gen
|
sed -Ei 's/#(en_(US|GB)\.UTF)/\1/' /etc/locale.gen && locale-gen
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ RUN apt update && \
|
|||||||
libudev-dev \
|
libudev-dev \
|
||||||
libupower-glib-dev \
|
libupower-glib-dev \
|
||||||
libwayland-dev \
|
libwayland-dev \
|
||||||
libwireplumber-0.4-dev \
|
libwireplumber-0.5-dev \
|
||||||
libxkbcommon-dev \
|
libxkbcommon-dev \
|
||||||
libxkbregistry-dev \
|
libxkbregistry-dev \
|
||||||
locales \
|
locales \
|
||||||
|
|||||||
+1
-1
@@ -29,6 +29,6 @@ RUN dnf install -y @c-development \
|
|||||||
'pkgconfig(wayland-client)' \
|
'pkgconfig(wayland-client)' \
|
||||||
'pkgconfig(wayland-cursor)' \
|
'pkgconfig(wayland-cursor)' \
|
||||||
'pkgconfig(wayland-protocols)' \
|
'pkgconfig(wayland-protocols)' \
|
||||||
'pkgconfig(wireplumber-0.4)' \
|
'pkgconfig(wireplumber-0.5)' \
|
||||||
'pkgconfig(xkbregistry)' && \
|
'pkgconfig(xkbregistry)' && \
|
||||||
dnf clean all -y
|
dnf clean all -y
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ RUN zypper -n up && \
|
|||||||
zypper addrepo https://download.opensuse.org/repositories/X11:Wayland/openSUSE_Tumbleweed/X11:Wayland.repo | echo 'a' && \
|
zypper addrepo https://download.opensuse.org/repositories/X11:Wayland/openSUSE_Tumbleweed/X11:Wayland.repo | echo 'a' && \
|
||||||
zypper -n refresh && \
|
zypper -n refresh && \
|
||||||
zypper -n install -t pattern devel_C_C++ && \
|
zypper -n install -t pattern devel_C_C++ && \
|
||||||
zypper -n install git meson clang libinput10 libinput-devel pugixml-devel libwayland-client0 libwayland-cursor0 wayland-protocols-devel wayland-devel Mesa-libEGL-devel Mesa-libGLESv2-devel libgbm-devel libxkbcommon-devel libudev-devel libpixman-1-0-devel gtkmm3-devel jsoncpp-devel libxkbregistry-devel scdoc playerctl-devel
|
zypper -n install git meson clang libinput10 libinput-devel pugixml-devel libwayland-client0 libwayland-cursor0 wayland-protocols-devel wayland-devel Mesa-libEGL-devel Mesa-libGLESv2-devel libgbm-devel libxkbcommon-devel libudev-devel libpixman-1-0-devel gtkmm3-devel jsoncpp-devel libxkbregistry-devel scdoc playerctl-devel python3-packaging
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
default: build
|
default: build
|
||||||
|
|
||||||
build:
|
build:
|
||||||
meson build
|
meson setup build
|
||||||
ninja -C build
|
ninja -C build
|
||||||
|
|
||||||
build-debug:
|
build-debug:
|
||||||
meson build --buildtype=debug
|
meson setup build --buildtype=debug
|
||||||
ninja -C build
|
ninja -C build
|
||||||
|
|
||||||
install: build
|
install: build
|
||||||
|
|||||||
@@ -8,11 +8,12 @@
|
|||||||
- Sway (Workspaces, Binding mode, Focused window name)
|
- Sway (Workspaces, Binding mode, Focused window name)
|
||||||
- River (Mapping mode, Tags, Focused window name)
|
- River (Mapping mode, Tags, Focused window name)
|
||||||
- Hyprland (Window Icons, Workspaces, Focused window name)
|
- Hyprland (Window Icons, Workspaces, Focused window name)
|
||||||
- DWL (Tags) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc)
|
- DWL (Tags, Focused window name) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc)
|
||||||
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
|
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
|
||||||
- Local time
|
- Local time
|
||||||
- Battery
|
- Battery
|
||||||
- UPower
|
- UPower
|
||||||
|
- Power profiles daemon
|
||||||
- Network
|
- Network
|
||||||
- Bluetooth
|
- Bluetooth
|
||||||
- Pulseaudio
|
- Pulseaudio
|
||||||
@@ -36,7 +37,7 @@
|
|||||||
|
|
||||||
Waybar is available from a number of Linux distributions:
|
Waybar is available from a number of Linux distributions:
|
||||||
|
|
||||||
[](https://repology.org/project/waybar/versions)
|
[](https://repology.org/project/waybar/versions)
|
||||||
|
|
||||||
An Ubuntu PPA with more recent versions is available
|
An Ubuntu PPA with more recent versions is available
|
||||||
[here](https://launchpad.net/~nschloe/+archive/ubuntu/waybar).
|
[here](https://launchpad.net/~nschloe/+archive/ubuntu/waybar).
|
||||||
|
|||||||
Generated
+3
-3
@@ -18,11 +18,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1704538339,
|
"lastModified": 1719506693,
|
||||||
"narHash": "sha256-1734d3mQuux9ySvwf6axRWZRBhtcZA9Q8eftD6EZg6U=",
|
"narHash": "sha256-C8e9S7RzshSdHB7L+v9I51af1gDM5unhJ2xO1ywxNH8=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "46ae0210ce163b3cba6c7da08840c1d63de9c701",
|
"rev": "b2852eb9365c6de48ffb0dc2c9562591f652242a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -16,7 +16,12 @@
|
|||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
"aarch64-linux"
|
"aarch64-linux"
|
||||||
]
|
]
|
||||||
(system: func (import nixpkgs { inherit system; }));
|
(system: func (import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
overlays = with self.overlays; [
|
||||||
|
waybar
|
||||||
|
];
|
||||||
|
}));
|
||||||
|
|
||||||
mkDate = longDate: (lib.concatStringsSep "-" [
|
mkDate = longDate: (lib.concatStringsSep "-" [
|
||||||
(builtins.substring 0 4 longDate)
|
(builtins.substring 0 4 longDate)
|
||||||
@@ -46,22 +51,25 @@
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
overlays.default = final: prev: {
|
overlays = {
|
||||||
waybar = final.callPackage ./nix/default.nix {
|
default = self.overlays.waybar;
|
||||||
# take the first "version: '...'" from meson.build
|
waybar = final: prev: {
|
||||||
version =
|
waybar = final.callPackage ./nix/default.nix {
|
||||||
(builtins.head (builtins.split "'"
|
waybar = prev.waybar;
|
||||||
(builtins.elemAt
|
# take the first "version: '...'" from meson.build
|
||||||
(builtins.split " version: '" (builtins.readFile ./meson.build))
|
version =
|
||||||
2)))
|
(builtins.head (builtins.split "'"
|
||||||
+ "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
|
(builtins.elemAt
|
||||||
|
(builtins.split " version: '" (builtins.readFile ./meson.build))
|
||||||
|
2)))
|
||||||
|
+ "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = genSystems (pkgs:
|
packages = genSystems (pkgs: {
|
||||||
let packages = self.overlays.default pkgs pkgs;
|
default = self.packages.${pkgs.stdenv.hostPlatform.system}.waybar;
|
||||||
in packages // {
|
inherit (pkgs) waybar;
|
||||||
default = packages.waybar;
|
});
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ class ALabel : public AModule {
|
|||||||
|
|
||||||
bool handleToggle(GdkEventButton *const &e) override;
|
bool handleToggle(GdkEventButton *const &e) override;
|
||||||
virtual std::string getState(uint8_t value, bool lesser = false);
|
virtual std::string getState(uint8_t value, bool lesser = false);
|
||||||
|
|
||||||
|
std::map<std::string, GtkMenuItem *> submenus_;
|
||||||
|
std::map<std::string, std::string> menuActionsMap_;
|
||||||
|
static void handleGtkMenuEvent(GtkMenuItem *menuitem, gpointer data);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar
|
} // namespace waybar
|
||||||
|
|||||||
+10
-3
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <glibmm/dispatcher.h>
|
#include <glibmm/dispatcher.h>
|
||||||
#include <glibmm/markup.h>
|
#include <glibmm/markup.h>
|
||||||
|
#include <gtkmm.h>
|
||||||
#include <gtkmm/eventbox.h>
|
#include <gtkmm/eventbox.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
|
|
||||||
@@ -13,9 +14,9 @@ class AModule : public IModule {
|
|||||||
public:
|
public:
|
||||||
static constexpr const char *MODULE_CLASS = "module";
|
static constexpr const char *MODULE_CLASS = "module";
|
||||||
|
|
||||||
virtual ~AModule();
|
~AModule() override;
|
||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
virtual auto refresh(int) -> void{};
|
virtual auto refresh(int shouldRefresh) -> void{};
|
||||||
operator Gtk::Widget &() override;
|
operator Gtk::Widget &() override;
|
||||||
auto doAction(const std::string &name) -> void override;
|
auto doAction(const std::string &name) -> void override;
|
||||||
|
|
||||||
@@ -31,19 +32,25 @@ class AModule : public IModule {
|
|||||||
enum SCROLL_DIR { NONE, UP, DOWN, LEFT, RIGHT };
|
enum SCROLL_DIR { NONE, UP, DOWN, LEFT, RIGHT };
|
||||||
|
|
||||||
SCROLL_DIR getScrollDir(GdkEventScroll *e);
|
SCROLL_DIR getScrollDir(GdkEventScroll *e);
|
||||||
bool tooltipEnabled();
|
bool tooltipEnabled() const;
|
||||||
|
|
||||||
const std::string name_;
|
const std::string name_;
|
||||||
const Json::Value &config_;
|
const Json::Value &config_;
|
||||||
Gtk::EventBox event_box_;
|
Gtk::EventBox event_box_;
|
||||||
|
|
||||||
|
virtual void setCursor(Gdk::CursorType const &c);
|
||||||
|
|
||||||
virtual bool handleToggle(GdkEventButton *const &ev);
|
virtual bool handleToggle(GdkEventButton *const &ev);
|
||||||
|
virtual bool handleMouseEnter(GdkEventCrossing *const &ev);
|
||||||
|
virtual bool handleMouseLeave(GdkEventCrossing *const &ev);
|
||||||
virtual bool handleScroll(GdkEventScroll *);
|
virtual bool handleScroll(GdkEventScroll *);
|
||||||
virtual bool handleRelease(GdkEventButton *const &ev);
|
virtual bool handleRelease(GdkEventButton *const &ev);
|
||||||
|
GObject *menu_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool handleUserEvent(GdkEventButton *const &ev);
|
bool handleUserEvent(GdkEventButton *const &ev);
|
||||||
const bool isTooltip;
|
const bool isTooltip;
|
||||||
|
bool hasUserEvents_;
|
||||||
std::vector<int> pid_;
|
std::vector<int> pid_;
|
||||||
gdouble distance_scrolled_y_;
|
gdouble distance_scrolled_y_;
|
||||||
gdouble distance_scrolled_x_;
|
gdouble distance_scrolled_x_;
|
||||||
|
|||||||
+2
-1
@@ -9,6 +9,7 @@
|
|||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
@@ -41,7 +42,7 @@ struct bar_margins {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct bar_mode {
|
struct bar_mode {
|
||||||
bar_layer layer;
|
std::optional<bar_layer> layer;
|
||||||
bool exclusive;
|
bool exclusive;
|
||||||
bool passthrough;
|
bool passthrough;
|
||||||
bool visible;
|
bool visible;
|
||||||
|
|||||||
+6
-8
@@ -11,15 +11,13 @@ namespace waybar {
|
|||||||
|
|
||||||
class Group : public AModule {
|
class Group : public AModule {
|
||||||
public:
|
public:
|
||||||
Group(const std::string&, const std::string&, const Json::Value&, bool);
|
Group(const std::string &, const std::string &, const Json::Value &, bool);
|
||||||
virtual ~Group() = default;
|
virtual ~Group() = default;
|
||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
operator Gtk::Widget&() override;
|
operator Gtk::Widget &() override;
|
||||||
|
|
||||||
virtual Gtk::Box& getBox();
|
virtual Gtk::Box &getBox();
|
||||||
void addWidget(Gtk::Widget& widget);
|
void addWidget(Gtk::Widget &widget);
|
||||||
|
|
||||||
bool handleMouseHover(GdkEventCrossing* const& e);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Gtk::Box box;
|
Gtk::Box box;
|
||||||
@@ -28,8 +26,8 @@ class Group : public AModule {
|
|||||||
bool is_first_widget = true;
|
bool is_first_widget = true;
|
||||||
bool is_drawer = false;
|
bool is_drawer = false;
|
||||||
std::string add_class_to_drawer_children;
|
std::string add_class_to_drawer_children;
|
||||||
|
bool handleMouseEnter(GdkEventCrossing *const &ev) override;
|
||||||
void addHoverHandlerTo(Gtk::Widget& widget);
|
bool handleMouseLeave(GdkEventCrossing *const &ev) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar
|
} // namespace waybar
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class Battery : public ALabel {
|
|||||||
void refreshBatteries();
|
void refreshBatteries();
|
||||||
void worker();
|
void worker();
|
||||||
const std::string getAdapterStatus(uint8_t capacity) const;
|
const std::string getAdapterStatus(uint8_t capacity) const;
|
||||||
const std::tuple<uint8_t, float, std::string, float> getInfos();
|
std::tuple<uint8_t, float, std::string, float, uint16_t, float> getInfos();
|
||||||
const std::string formatTimeRemaining(float hoursRemaining);
|
const std::string formatTimeRemaining(float hoursRemaining);
|
||||||
void setBarClass(std::string&);
|
void setBarClass(std::string&);
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ class Bluetooth : public ALabel {
|
|||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static auto onObjectAdded(GDBusObjectManager*, GDBusObject*, gpointer) -> void;
|
||||||
|
static auto onObjectRemoved(GDBusObjectManager*, GDBusObject*, gpointer) -> void;
|
||||||
|
|
||||||
static auto onInterfaceAddedOrRemoved(GDBusObjectManager*, GDBusObject*, GDBusInterface*,
|
static auto onInterfaceAddedOrRemoved(GDBusObjectManager*, GDBusObject*, GDBusInterface*,
|
||||||
gpointer) -> void;
|
gpointer) -> void;
|
||||||
static auto onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient*, GDBusObjectProxy*,
|
static auto onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient*, GDBusObjectProxy*,
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ class Clock final : public ALabel {
|
|||||||
auto doAction(const std::string&) -> void override;
|
auto doAction(const std::string&) -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::locale locale_;
|
const std::locale m_locale_;
|
||||||
// tooltip
|
// tooltip
|
||||||
const std::string tlpFmt_;
|
const std::string m_tlpFmt_;
|
||||||
std::string tlpText_{""}; // tooltip text to print
|
std::string m_tlpText_{""}; // tooltip text to print
|
||||||
|
const Glib::RefPtr<Gtk::Label> m_tooltip_; // tooltip as a separate Gtk::Label
|
||||||
|
bool query_tlp_cb(int, int, bool, const Glib::RefPtr<Gtk::Tooltip>& tooltip);
|
||||||
// Calendar
|
// Calendar
|
||||||
const bool cldInTooltip_; // calendar in tooltip
|
const bool cldInTooltip_; // calendar in tooltip
|
||||||
/*
|
/*
|
||||||
@@ -41,6 +43,7 @@ class Clock final : public ALabel {
|
|||||||
const int cldMonColLen_{20}; // calendar month column length
|
const int cldMonColLen_{20}; // calendar month column length
|
||||||
WS cldWPos_{WS::HIDDEN}; // calendar week side to print
|
WS cldWPos_{WS::HIDDEN}; // calendar week side to print
|
||||||
months cldCurrShift_{0}; // calendar months shift
|
months cldCurrShift_{0}; // calendar months shift
|
||||||
|
int cldShift_{1}; // calendar months shift factor
|
||||||
year_month_day cldYearShift_; // calendar Year mode. Cached ymd
|
year_month_day cldYearShift_; // calendar Year mode. Cached ymd
|
||||||
std::string cldYearCached_; // calendar Year mode. Cached calendar
|
std::string cldYearCached_; // calendar Year mode. Cached calendar
|
||||||
year_month cldMonShift_; // calendar Month mode. Cached ym
|
year_month cldMonShift_; // calendar Month mode. Cached ym
|
||||||
@@ -51,6 +54,9 @@ class Clock final : public ALabel {
|
|||||||
auto get_calendar(const year_month_day& today, const year_month_day& ymd, const time_zone* tz)
|
auto get_calendar(const year_month_day& today, const year_month_day& ymd, const time_zone* tz)
|
||||||
-> const std::string;
|
-> const std::string;
|
||||||
|
|
||||||
|
// get local time zone
|
||||||
|
auto local_zone() -> const time_zone*;
|
||||||
|
|
||||||
// time zoned time in tooltip
|
// time zoned time in tooltip
|
||||||
const bool tzInTooltip_; // if need to print time zones text
|
const bool tzInTooltip_; // if need to print time zones text
|
||||||
std::vector<const time_zone*> tzList_; // time zones list
|
std::vector<const time_zone*> tzList_; // time zones list
|
||||||
@@ -69,6 +75,7 @@ class Clock final : public ALabel {
|
|||||||
void cldModeSwitch();
|
void cldModeSwitch();
|
||||||
void cldShift_up();
|
void cldShift_up();
|
||||||
void cldShift_down();
|
void cldShift_down();
|
||||||
|
void cldShift_reset();
|
||||||
void tz_up();
|
void tz_up();
|
||||||
void tz_down();
|
void tz_down();
|
||||||
// Module Action Map
|
// Module Action Map
|
||||||
@@ -76,6 +83,7 @@ class Clock final : public ALabel {
|
|||||||
{"mode", &waybar::modules::Clock::cldModeSwitch},
|
{"mode", &waybar::modules::Clock::cldModeSwitch},
|
||||||
{"shift_up", &waybar::modules::Clock::cldShift_up},
|
{"shift_up", &waybar::modules::Clock::cldShift_up},
|
||||||
{"shift_down", &waybar::modules::Clock::cldShift_down},
|
{"shift_down", &waybar::modules::Clock::cldShift_down},
|
||||||
|
{"shift_reset", &waybar::modules::Clock::cldShift_reset},
|
||||||
{"tz_up", &waybar::modules::Clock::tz_up},
|
{"tz_up", &waybar::modules::Clock::tz_up},
|
||||||
{"tz_down", &waybar::modules::Clock::tz_down}};
|
{"tz_down", &waybar::modules::Clock::tz_down}};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class Custom : public ALabel {
|
|||||||
std::string id_;
|
std::string id_;
|
||||||
std::string alt_;
|
std::string alt_;
|
||||||
std::string tooltip_;
|
std::string tooltip_;
|
||||||
|
const bool tooltip_format_enabled_;
|
||||||
std::vector<std::string> class_;
|
std::vector<std::string> class_;
|
||||||
int percentage_;
|
int percentage_;
|
||||||
FILE* fp_;
|
FILE* fp_;
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "AAppIconLabel.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "dwl-ipc-unstable-v2-client-protocol.h"
|
||||||
|
#include "util/json.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::dwl {
|
||||||
|
|
||||||
|
class Window : public AAppIconLabel, public sigc::trackable {
|
||||||
|
public:
|
||||||
|
Window(const std::string &, const waybar::Bar &, const Json::Value &);
|
||||||
|
~Window();
|
||||||
|
|
||||||
|
void handle_layout(const uint32_t layout);
|
||||||
|
void handle_title(const char *title);
|
||||||
|
void handle_appid(const char *ppid);
|
||||||
|
void handle_layout_symbol(const char *layout_symbol);
|
||||||
|
void handle_frame();
|
||||||
|
|
||||||
|
struct zdwl_ipc_manager_v2 *status_manager_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Bar &bar_;
|
||||||
|
|
||||||
|
std::string title_;
|
||||||
|
std::string appid_;
|
||||||
|
std::string layout_symbol_;
|
||||||
|
uint32_t layout_;
|
||||||
|
|
||||||
|
struct zdwl_ipc_output_v2 *output_status_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::dwl
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -20,19 +21,23 @@ class IPC {
|
|||||||
public:
|
public:
|
||||||
IPC() { startIPC(); }
|
IPC() { startIPC(); }
|
||||||
|
|
||||||
void registerForIPC(const std::string&, EventHandler*);
|
void registerForIPC(const std::string& ev, EventHandler* ev_handler);
|
||||||
void unregisterForIPC(EventHandler*);
|
void unregisterForIPC(EventHandler* handler);
|
||||||
|
|
||||||
static std::string getSocket1Reply(const std::string& rq);
|
static std::string getSocket1Reply(const std::string& rq);
|
||||||
Json::Value getSocket1JsonReply(const std::string& rq);
|
Json::Value getSocket1JsonReply(const std::string& rq);
|
||||||
|
static std::filesystem::path getSocketFolder(const char* instanceSig);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static std::filesystem::path socketFolder_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startIPC();
|
void startIPC();
|
||||||
void parseIPC(const std::string&);
|
void parseIPC(const std::string&);
|
||||||
|
|
||||||
std::mutex m_callbackMutex;
|
std::mutex callbackMutex_;
|
||||||
util::JsonParser m_parser;
|
util::JsonParser parser_;
|
||||||
std::list<std::pair<std::string, EventHandler*>> m_callbacks;
|
std::list<std::pair<std::string, EventHandler*>> callbacks_;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<IPC> gIPC;
|
inline std::unique_ptr<IPC> gIPC;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class Language : public waybar::ALabel, public EventHandler {
|
|||||||
std::string short_description;
|
std::string short_description;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto getLayout(const std::string&) -> Layout;
|
static auto getLayout(const std::string&) -> Layout;
|
||||||
|
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
|
|||||||
@@ -14,17 +14,20 @@ namespace waybar::modules::hyprland {
|
|||||||
class Submap : public waybar::ALabel, public EventHandler {
|
class Submap : public waybar::ALabel, public EventHandler {
|
||||||
public:
|
public:
|
||||||
Submap(const std::string&, const waybar::Bar&, const Json::Value&);
|
Submap(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
virtual ~Submap();
|
~Submap() override;
|
||||||
|
|
||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onEvent(const std::string&) override;
|
auto parseConfig(const Json::Value&) -> void;
|
||||||
|
void onEvent(const std::string& ev) override;
|
||||||
|
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
std::string submap_;
|
std::string submap_;
|
||||||
|
bool always_on_ = false;
|
||||||
|
std::string default_submap_ = "Default";
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::hyprland
|
} // namespace waybar::modules::hyprland
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class Window : public waybar::AAppIconLabel, public EventHandler {
|
|||||||
std::string last_window;
|
std::string last_window;
|
||||||
std::string last_window_title;
|
std::string last_window_title;
|
||||||
|
|
||||||
static auto parse(const Json::Value&) -> Workspace;
|
static auto parse(const Json::Value& value) -> Workspace;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WindowData {
|
struct WindowData {
|
||||||
@@ -41,23 +41,25 @@ class Window : public waybar::AAppIconLabel, public EventHandler {
|
|||||||
static auto parse(const Json::Value&) -> WindowData;
|
static auto parse(const Json::Value&) -> WindowData;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto getActiveWorkspace(const std::string&) -> Workspace;
|
static auto getActiveWorkspace(const std::string&) -> Workspace;
|
||||||
void onEvent(const std::string&) override;
|
static auto getActiveWorkspace() -> Workspace;
|
||||||
|
void onEvent(const std::string& ev) override;
|
||||||
void queryActiveWorkspace();
|
void queryActiveWorkspace();
|
||||||
void setClass(const std::string&, bool enable);
|
void setClass(const std::string&, bool enable);
|
||||||
|
|
||||||
bool separate_outputs;
|
bool separateOutputs_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
WindowData window_data_;
|
WindowData windowData_;
|
||||||
Workspace workspace_;
|
Workspace workspace_;
|
||||||
std::string solo_class_;
|
std::string soloClass_;
|
||||||
std::string last_solo_class_;
|
std::string lastSoloClass_;
|
||||||
bool solo_;
|
bool solo_;
|
||||||
bool all_floating_;
|
bool allFloating_;
|
||||||
bool swallowing_;
|
bool swallowing_;
|
||||||
bool fullscreen_;
|
bool fullscreen_;
|
||||||
|
bool focused_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::hyprland
|
} // namespace waybar::modules::hyprland
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#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 incrementTimeSpentUncreated();
|
||||||
|
bool isEmpty(Workspaces& workspace_manager);
|
||||||
|
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
|
||||||
|
std::string repr(Workspaces& workspace_manager);
|
||||||
|
|
||||||
|
std::string getWorkspaceName() const { return m_workspaceName; }
|
||||||
|
WindowAddress getAddress() const { return m_windowAddress; }
|
||||||
|
|
||||||
|
void moveToWorksace(std::string& new_workspace_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void clearAddr();
|
||||||
|
void clearWorkspaceName();
|
||||||
|
|
||||||
|
using Repr = std::string;
|
||||||
|
using ClassAndTitle = std::pair<std::string, std::string>;
|
||||||
|
std::variant<Repr, ClassAndTitle> m_window;
|
||||||
|
|
||||||
|
WindowAddress m_windowAddress;
|
||||||
|
std::string m_workspaceName;
|
||||||
|
|
||||||
|
int m_timeSpentUncreated = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::hyprland
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <gtkmm/label.h>
|
||||||
|
#include <json/value.h>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <regex>
|
||||||
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "AModule.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "modules/hyprland/backend.hpp"
|
||||||
|
#include "modules/hyprland/windowcreationpayload.hpp"
|
||||||
|
#include "util/enum.hpp"
|
||||||
|
#include "util/regex_collection.hpp"
|
||||||
|
|
||||||
|
using WindowAddress = std::string;
|
||||||
|
|
||||||
|
namespace waybar::modules::hyprland {
|
||||||
|
|
||||||
|
class Workspaces;
|
||||||
|
class Workspace {
|
||||||
|
public:
|
||||||
|
explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager,
|
||||||
|
const Json::Value& clients_data = Json::Value::nullRef);
|
||||||
|
std::string& selectIcon(std::map<std::string, std::string>& icons_map);
|
||||||
|
Gtk::Button& button() { return m_button; };
|
||||||
|
|
||||||
|
int id() const { return m_id; };
|
||||||
|
std::string name() const { return m_name; };
|
||||||
|
std::string output() const { return m_output; };
|
||||||
|
bool isActive() const { return m_isActive; };
|
||||||
|
bool isSpecial() const { return m_isSpecial; };
|
||||||
|
bool isPersistent() const { return m_isPersistentRule || m_isPersistentConfig; };
|
||||||
|
bool isPersistentConfig() const { return m_isPersistentConfig; };
|
||||||
|
bool isPersistentRule() const { return m_isPersistentRule; };
|
||||||
|
bool isVisible() const { return m_isVisible; };
|
||||||
|
bool isEmpty() const { return m_windows == 0; };
|
||||||
|
bool isUrgent() const { return m_isUrgent; };
|
||||||
|
|
||||||
|
bool handleClicked(GdkEventButton* bt) const;
|
||||||
|
void setActive(bool value = true) { m_isActive = value; };
|
||||||
|
void setPersistentRule(bool value = true) { m_isPersistentRule = value; };
|
||||||
|
void setPersistentConfig(bool value = true) { m_isPersistentConfig = value; };
|
||||||
|
void setUrgent(bool value = true) { m_isUrgent = value; };
|
||||||
|
void setVisible(bool value = true) { m_isVisible = value; };
|
||||||
|
void setWindows(uint value) { m_windows = value; };
|
||||||
|
void setName(std::string const& value) { m_name = value; };
|
||||||
|
void setOutput(std::string const& value) { m_output = value; };
|
||||||
|
bool containsWindow(WindowAddress const& addr) const { return m_windowMap.contains(addr); }
|
||||||
|
void insertWindow(WindowCreationPayload create_window_paylod);
|
||||||
|
std::string removeWindow(WindowAddress const& addr);
|
||||||
|
void initializeWindowMap(const Json::Value& clients_data);
|
||||||
|
|
||||||
|
bool onWindowOpened(WindowCreationPayload const& create_window_paylod);
|
||||||
|
std::optional<std::string> closeWindow(WindowAddress const& addr);
|
||||||
|
|
||||||
|
void update(const std::string& format, const std::string& icon);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Workspaces& m_workspaceManager;
|
||||||
|
|
||||||
|
int m_id;
|
||||||
|
std::string m_name;
|
||||||
|
std::string m_output;
|
||||||
|
uint m_windows;
|
||||||
|
bool m_isActive = false;
|
||||||
|
bool m_isSpecial = false;
|
||||||
|
bool m_isPersistentRule = false; // represents the persistent state in hyprland
|
||||||
|
bool m_isPersistentConfig = false; // represents the persistent state in the Waybar config
|
||||||
|
bool m_isUrgent = false;
|
||||||
|
bool m_isVisible = false;
|
||||||
|
|
||||||
|
std::map<WindowAddress, std::string> m_windowMap;
|
||||||
|
|
||||||
|
Gtk::Button m_button;
|
||||||
|
Gtk::Box m_content;
|
||||||
|
Gtk::Label m_label;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::hyprland
|
||||||
@@ -4,19 +4,18 @@
|
|||||||
#include <gtkmm/label.h>
|
#include <gtkmm/label.h>
|
||||||
#include <json/value.h>
|
#include <json/value.h>
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "modules/hyprland/backend.hpp"
|
#include "modules/hyprland/backend.hpp"
|
||||||
|
#include "modules/hyprland/windowcreationpayload.hpp"
|
||||||
|
#include "modules/hyprland/workspace.hpp"
|
||||||
#include "util/enum.hpp"
|
#include "util/enum.hpp"
|
||||||
#include "util/regex_collection.hpp"
|
#include "util/regex_collection.hpp"
|
||||||
|
|
||||||
@@ -26,92 +25,6 @@ namespace waybar::modules::hyprland {
|
|||||||
|
|
||||||
class Workspaces;
|
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 incrementTimeSpentUncreated();
|
|
||||||
bool isEmpty(Workspaces& workspace_manager);
|
|
||||||
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
|
|
||||||
std::string repr(Workspaces& workspace_manager);
|
|
||||||
|
|
||||||
std::string getWorkspaceName() const { return m_workspaceName; }
|
|
||||||
WindowAddress getAddress() const { return m_windowAddress; }
|
|
||||||
|
|
||||||
void moveToWorksace(std::string& new_workspace_name);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void clearAddr();
|
|
||||||
void clearWorkspaceName();
|
|
||||||
|
|
||||||
using Repr = std::string;
|
|
||||||
using ClassAndTitle = std::pair<std::string, std::string>;
|
|
||||||
std::variant<Repr, ClassAndTitle> m_window;
|
|
||||||
|
|
||||||
WindowAddress m_windowAddress;
|
|
||||||
std::string m_workspaceName;
|
|
||||||
|
|
||||||
int m_timeSpentUncreated = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Workspace {
|
|
||||||
public:
|
|
||||||
explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager,
|
|
||||||
const Json::Value& clients_data = Json::Value::nullRef);
|
|
||||||
std::string& selectIcon(std::map<std::string, std::string>& icons_map);
|
|
||||||
Gtk::Button& button() { return m_button; };
|
|
||||||
|
|
||||||
int id() const { return m_id; };
|
|
||||||
std::string name() const { return m_name; };
|
|
||||||
std::string output() const { return m_output; };
|
|
||||||
bool isActive() const { return m_isActive; };
|
|
||||||
bool isSpecial() const { return m_isSpecial; };
|
|
||||||
bool isPersistent() const { return m_isPersistent; };
|
|
||||||
bool isVisible() const { return m_isVisible; };
|
|
||||||
bool isEmpty() const { return m_windows == 0; };
|
|
||||||
bool isUrgent() const { return m_isUrgent; };
|
|
||||||
|
|
||||||
bool handleClicked(GdkEventButton* bt) const;
|
|
||||||
void setActive(bool value = true) { m_isActive = value; };
|
|
||||||
void setPersistent(bool value = true) { m_isPersistent = value; };
|
|
||||||
void setUrgent(bool value = true) { m_isUrgent = value; };
|
|
||||||
void setVisible(bool value = true) { m_isVisible = value; };
|
|
||||||
void setWindows(uint value) { m_windows = value; };
|
|
||||||
void setName(std::string const& value) { m_name = value; };
|
|
||||||
bool containsWindow(WindowAddress const& addr) const { return m_windowMap.contains(addr); }
|
|
||||||
void insertWindow(WindowCreationPayload create_window_paylod);
|
|
||||||
std::string removeWindow(WindowAddress const& addr);
|
|
||||||
void initializeWindowMap(const Json::Value& clients_data);
|
|
||||||
|
|
||||||
bool onWindowOpened(WindowCreationPayload const& create_window_paylod);
|
|
||||||
std::optional<std::string> closeWindow(WindowAddress const& addr);
|
|
||||||
|
|
||||||
void update(const std::string& format, const std::string& icon);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Workspaces& m_workspaceManager;
|
|
||||||
|
|
||||||
int m_id;
|
|
||||||
std::string m_name;
|
|
||||||
std::string m_output;
|
|
||||||
uint m_windows;
|
|
||||||
bool m_isActive = false;
|
|
||||||
bool m_isSpecial = false;
|
|
||||||
bool m_isPersistent = false;
|
|
||||||
bool m_isUrgent = false;
|
|
||||||
bool m_isVisible = false;
|
|
||||||
|
|
||||||
std::map<WindowAddress, std::string> m_windowMap;
|
|
||||||
|
|
||||||
Gtk::Button m_button;
|
|
||||||
Gtk::Box m_content;
|
|
||||||
Gtk::Label m_label;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Workspaces : public AModule, public EventHandler {
|
class Workspaces : public AModule, public EventHandler {
|
||||||
public:
|
public:
|
||||||
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
|
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
@@ -122,6 +35,8 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
auto allOutputs() const -> bool { return m_allOutputs; }
|
auto allOutputs() const -> bool { return m_allOutputs; }
|
||||||
auto showSpecial() const -> bool { return m_showSpecial; }
|
auto showSpecial() const -> bool { return m_showSpecial; }
|
||||||
auto activeOnly() const -> bool { return m_activeOnly; }
|
auto activeOnly() const -> bool { return m_activeOnly; }
|
||||||
|
auto specialVisibleOnly() const -> bool { return m_specialVisibleOnly; }
|
||||||
|
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
|
||||||
|
|
||||||
auto getBarOutput() const -> std::string { return m_bar.output->name; }
|
auto getBarOutput() const -> std::string { return m_bar.output->name; }
|
||||||
|
|
||||||
@@ -135,11 +50,24 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
void onEvent(const std::string& e) override;
|
void onEvent(const std::string& e) override;
|
||||||
void updateWindowCount();
|
void updateWindowCount();
|
||||||
void sortWorkspaces();
|
void sortWorkspaces();
|
||||||
void createWorkspace(Json::Value const& workspaceData,
|
void createWorkspace(Json::Value const& workspace_data,
|
||||||
Json::Value const& clientsData = Json::Value::nullRef);
|
Json::Value const& clients_data = Json::Value::nullRef);
|
||||||
|
|
||||||
|
static Json::Value createMonitorWorkspaceData(std::string const& name,
|
||||||
|
std::string const& monitor);
|
||||||
void removeWorkspace(std::string const& name);
|
void removeWorkspace(std::string const& name);
|
||||||
void setUrgentWorkspace(std::string const& windowaddress);
|
void setUrgentWorkspace(std::string const& windowaddress);
|
||||||
|
|
||||||
|
// Config
|
||||||
void parseConfig(const Json::Value& config);
|
void parseConfig(const Json::Value& config);
|
||||||
|
auto populateIconsMap(const Json::Value& formatIcons) -> void;
|
||||||
|
static auto populateBoolConfig(const Json::Value& config, const std::string& key, bool& member)
|
||||||
|
-> void;
|
||||||
|
auto populateSortByConfig(const Json::Value& config) -> void;
|
||||||
|
auto populateIgnoreWorkspacesConfig(const Json::Value& config) -> void;
|
||||||
|
auto populateFormatWindowSeparatorConfig(const Json::Value& config) -> void;
|
||||||
|
auto populateWindowRewriteConfig(const Json::Value& config) -> void;
|
||||||
|
|
||||||
void registerIpc();
|
void registerIpc();
|
||||||
|
|
||||||
// workspace events
|
// workspace events
|
||||||
@@ -165,7 +93,13 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
|
|
||||||
int windowRewritePriorityFunction(std::string const& window_rule);
|
int windowRewritePriorityFunction(std::string const& window_rule);
|
||||||
|
|
||||||
|
// Update methods
|
||||||
void doUpdate();
|
void doUpdate();
|
||||||
|
void removeWorkspacesToRemove();
|
||||||
|
void createWorkspacesToCreate();
|
||||||
|
static std::vector<std::string> getVisibleWorkspaces();
|
||||||
|
void updateWorkspaceStates();
|
||||||
|
bool updateWindowsToCreate();
|
||||||
|
|
||||||
void extendOrphans(int workspaceId, Json::Value const& clientsJson);
|
void extendOrphans(int workspaceId, Json::Value const& clientsJson);
|
||||||
void registerOrphanWindow(WindowCreationPayload create_window_payload);
|
void registerOrphanWindow(WindowCreationPayload create_window_payload);
|
||||||
@@ -178,6 +112,8 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
bool m_allOutputs = false;
|
bool m_allOutputs = false;
|
||||||
bool m_showSpecial = false;
|
bool m_showSpecial = false;
|
||||||
bool m_activeOnly = false;
|
bool m_activeOnly = false;
|
||||||
|
bool m_specialVisibleOnly = false;
|
||||||
|
bool m_moveToMonitor = false;
|
||||||
Json::Value m_persistentWorkspaceConfig;
|
Json::Value m_persistentWorkspaceConfig;
|
||||||
|
|
||||||
// Map for windows stored in workspaces not present in the current bar.
|
// Map for windows stored in workspaces not present in the current bar.
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ class Stopped : public State {
|
|||||||
class Disconnected : public State {
|
class Disconnected : public State {
|
||||||
Context* const ctx_;
|
Context* const ctx_;
|
||||||
sigc::connection timer_connection_;
|
sigc::connection timer_connection_;
|
||||||
|
int last_interval_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Disconnected(Context* const ctx) : ctx_{ctx} {}
|
Disconnected(Context* const ctx) : ctx_{ctx} {}
|
||||||
@@ -162,7 +163,7 @@ class Disconnected : public State {
|
|||||||
Disconnected(Disconnected const&) = delete;
|
Disconnected(Disconnected const&) = delete;
|
||||||
Disconnected& operator=(Disconnected const&) = delete;
|
Disconnected& operator=(Disconnected const&) = delete;
|
||||||
|
|
||||||
void arm_timer(int interval) noexcept;
|
bool arm_timer(int interval) noexcept;
|
||||||
void disarm_timer() noexcept;
|
void disarm_timer() noexcept;
|
||||||
|
|
||||||
bool on_timer();
|
bool on_timer();
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "ALabel.hpp"
|
||||||
|
#include "giomm/dbusproxy.h"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
struct Profile {
|
||||||
|
std::string name;
|
||||||
|
std::string driver;
|
||||||
|
|
||||||
|
Profile(std::string n, std::string d) : name(std::move(n)), driver(std::move(d)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PowerProfilesDaemon : public ALabel {
|
||||||
|
public:
|
||||||
|
PowerProfilesDaemon(const std::string &, const Json::Value &);
|
||||||
|
auto update() -> void override;
|
||||||
|
void profileChangedCb(const Gio::DBus::Proxy::MapChangedProperties &,
|
||||||
|
const std::vector<Glib::ustring> &);
|
||||||
|
void busConnectedCb(Glib::RefPtr<Gio::AsyncResult> &r);
|
||||||
|
void getAllPropsCb(Glib::RefPtr<Gio::AsyncResult> &r);
|
||||||
|
void setPropCb(Glib::RefPtr<Gio::AsyncResult> &r);
|
||||||
|
void populateInitState();
|
||||||
|
bool handleToggle(GdkEventButton *const &e) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// True if we're connected to the dbug interface. False if we're
|
||||||
|
// not.
|
||||||
|
bool connected_;
|
||||||
|
// Look for a profile name in the list of available profiles and
|
||||||
|
// switch activeProfile_ to it.
|
||||||
|
void switchToProfile(std::string const &);
|
||||||
|
// Used to toggle/display the profiles
|
||||||
|
std::vector<Profile> availableProfiles_;
|
||||||
|
// Points to the active profile in the profiles list
|
||||||
|
std::vector<Profile>::iterator activeProfile_;
|
||||||
|
// Current CSS class applied to the label
|
||||||
|
std::string currentStyle_;
|
||||||
|
// Format string
|
||||||
|
std::string tooltipFormat_;
|
||||||
|
// DBus Proxy used to track the current active profile
|
||||||
|
Glib::RefPtr<Gio::DBus::Proxy> powerProfilesProxy_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
|
||||||
#include "gtkmm/box.h"
|
#include "gtkmm/box.h"
|
||||||
#include "modules/privacy/privacy_item.hpp"
|
#include "modules/privacy/privacy_item.hpp"
|
||||||
#include "util/pipewire/pipewire_backend.hpp"
|
#include "util/pipewire/pipewire_backend.hpp"
|
||||||
|
|||||||
@@ -2,9 +2,6 @@
|
|||||||
|
|
||||||
#include <json/value.h>
|
#include <json/value.h>
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <map>
|
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "gtkmm/box.h"
|
#include "gtkmm/box.h"
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ class Item : public sigc::trackable {
|
|||||||
void makeMenu();
|
void makeMenu();
|
||||||
bool handleClick(GdkEventButton* const& /*ev*/);
|
bool handleClick(GdkEventButton* const& /*ev*/);
|
||||||
bool handleScroll(GdkEventScroll* const&);
|
bool handleScroll(GdkEventScroll* const&);
|
||||||
|
bool handleMouseEnter(GdkEventCrossing* const&);
|
||||||
|
bool handleMouseLeave(GdkEventCrossing* const&);
|
||||||
|
|
||||||
// smooth scrolling threshold
|
// smooth scrolling threshold
|
||||||
gdouble scroll_threshold_ = 0;
|
gdouble scroll_threshold_ = 0;
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ class Language : public ALabel, public sigc::trackable {
|
|||||||
Layout layout_;
|
Layout layout_;
|
||||||
std::string tooltip_format_ = "";
|
std::string tooltip_format_ = "";
|
||||||
std::map<std::string, Layout> layouts_map_;
|
std::map<std::string, Layout> layouts_map_;
|
||||||
|
bool hide_single_;
|
||||||
bool is_variant_displayed;
|
bool is_variant_displayed;
|
||||||
std::byte displayed_short_flag = static_cast<std::byte>(DispayedShortFlag::None);
|
std::byte displayed_short_flag = static_cast<std::byte>(DispayedShortFlag::None);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <giomm/dbusconnection.h>
|
||||||
|
#include <gtkmm/icontheme.h>
|
||||||
|
#include <libupower-glib/upower.h>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "AIconLabel.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
class UPower final : public AIconLabel {
|
||||||
|
public:
|
||||||
|
UPower(const std::string &, const Json::Value &);
|
||||||
|
virtual ~UPower();
|
||||||
|
auto update() -> void override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string NO_BATTERY{"battery-missing-symbolic"};
|
||||||
|
|
||||||
|
// Config
|
||||||
|
bool showIcon_{true};
|
||||||
|
bool hideIfEmpty_{true};
|
||||||
|
int iconSize_{20};
|
||||||
|
int tooltip_spacing_{4};
|
||||||
|
int tooltip_padding_{4};
|
||||||
|
Gtk::Box contentBox_; // tooltip box
|
||||||
|
std::string tooltipFormat_;
|
||||||
|
|
||||||
|
// UPower device info
|
||||||
|
struct upDevice_output {
|
||||||
|
UpDevice *upDevice{NULL};
|
||||||
|
double percentage{0.0};
|
||||||
|
double temperature{0.0};
|
||||||
|
guint64 time_full{0u};
|
||||||
|
guint64 time_empty{0u};
|
||||||
|
gchar *icon_name{(char *)'\0'};
|
||||||
|
bool upDeviceValid{false};
|
||||||
|
UpDeviceState state;
|
||||||
|
UpDeviceKind kind;
|
||||||
|
char *nativePath{(char *)'\0'};
|
||||||
|
char *model{(char *)'\0'};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Technical variables
|
||||||
|
std::string nativePath_;
|
||||||
|
std::string model_;
|
||||||
|
std::string lastStatus_;
|
||||||
|
Glib::ustring label_markup_;
|
||||||
|
std::mutex mutex_;
|
||||||
|
Glib::RefPtr<Gtk::IconTheme> gtkTheme_;
|
||||||
|
bool sleeping_;
|
||||||
|
|
||||||
|
// Technical functions
|
||||||
|
void addDevice(UpDevice *);
|
||||||
|
void removeDevice(const gchar *);
|
||||||
|
void removeDevices();
|
||||||
|
void resetDevices();
|
||||||
|
void setDisplayDevice();
|
||||||
|
const Glib::ustring getText(const upDevice_output &upDevice_, const std::string &format);
|
||||||
|
bool queryTooltipCb(int, int, bool, const Glib::RefPtr<Gtk::Tooltip> &);
|
||||||
|
|
||||||
|
// DBUS variables
|
||||||
|
guint watcherID_;
|
||||||
|
Glib::RefPtr<Gio::DBus::Connection> conn_;
|
||||||
|
guint subscrID_{0u};
|
||||||
|
|
||||||
|
// UPower variables
|
||||||
|
UpClient *upClient_;
|
||||||
|
upDevice_output upDevice_; // Device to display
|
||||||
|
typedef std::unordered_map<std::string, upDevice_output> Devices;
|
||||||
|
Devices devices_;
|
||||||
|
bool upRunning_{true};
|
||||||
|
|
||||||
|
// DBus callbacks
|
||||||
|
void getConn_cb(Glib::RefPtr<Gio::AsyncResult> &result);
|
||||||
|
void onAppear(const Glib::RefPtr<Gio::DBus::Connection> &, const Glib::ustring &,
|
||||||
|
const Glib::ustring &);
|
||||||
|
void onVanished(const Glib::RefPtr<Gio::DBus::Connection> &, const Glib::ustring &);
|
||||||
|
void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection> &connection,
|
||||||
|
const Glib::ustring &sender_name, const Glib::ustring &object_path,
|
||||||
|
const Glib::ustring &interface_name, const Glib::ustring &signal_name,
|
||||||
|
const Glib::VariantContainerBase ¶meters);
|
||||||
|
|
||||||
|
// UPower callbacks
|
||||||
|
static void deviceAdded_cb(UpClient *client, UpDevice *device, gpointer data);
|
||||||
|
static void deviceRemoved_cb(UpClient *client, const gchar *objectPath, gpointer data);
|
||||||
|
static void deviceNotify_cb(UpDevice *device, GParamSpec *pspec, gpointer user_data);
|
||||||
|
// UPower secondary functions
|
||||||
|
void getUpDeviceInfo(upDevice_output &upDevice_);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <libupower-glib/upower.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
|
||||||
#include "glibconfig.h"
|
|
||||||
#include "gtkmm/box.h"
|
|
||||||
#include "gtkmm/image.h"
|
|
||||||
#include "gtkmm/label.h"
|
|
||||||
#include "modules/upower/upower_tooltip.hpp"
|
|
||||||
|
|
||||||
namespace waybar::modules::upower {
|
|
||||||
|
|
||||||
class UPower : public AModule {
|
|
||||||
public:
|
|
||||||
UPower(const std::string &, const Json::Value &);
|
|
||||||
virtual ~UPower();
|
|
||||||
auto update() -> void override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::unordered_map<std::string, UpDevice *> Devices;
|
|
||||||
|
|
||||||
const std::string DEFAULT_FORMAT = "{percentage}";
|
|
||||||
const std::string DEFAULT_FORMAT_ALT = "{percentage} {time}";
|
|
||||||
|
|
||||||
static void deviceAdded_cb(UpClient *client, UpDevice *device, gpointer data);
|
|
||||||
static void deviceRemoved_cb(UpClient *client, const gchar *objectPath, gpointer data);
|
|
||||||
static void deviceNotify_cb(UpDevice *device, GParamSpec *pspec, gpointer user_data);
|
|
||||||
static void prepareForSleep_cb(GDBusConnection *system_bus, const gchar *sender_name,
|
|
||||||
const gchar *object_path, const gchar *interface_name,
|
|
||||||
const gchar *signal_name, GVariant *parameters,
|
|
||||||
gpointer user_data);
|
|
||||||
static void upowerAppear(GDBusConnection *conn, const gchar *name, const gchar *name_owner,
|
|
||||||
gpointer data);
|
|
||||||
static void upowerDisappear(GDBusConnection *connection, const gchar *name, gpointer user_data);
|
|
||||||
|
|
||||||
void removeDevice(const gchar *objectPath);
|
|
||||||
void addDevice(UpDevice *device);
|
|
||||||
void setDisplayDevice();
|
|
||||||
void resetDevices();
|
|
||||||
void removeDevices();
|
|
||||||
bool show_tooltip_callback(int, int, bool, const Glib::RefPtr<Gtk::Tooltip> &tooltip);
|
|
||||||
bool handleToggle(GdkEventButton *const &) override;
|
|
||||||
std::string timeToString(gint64 time);
|
|
||||||
|
|
||||||
const std::string getDeviceStatus(UpDeviceState &state);
|
|
||||||
|
|
||||||
Gtk::Box box_;
|
|
||||||
Gtk::Image icon_;
|
|
||||||
Gtk::Label label_;
|
|
||||||
|
|
||||||
// Config
|
|
||||||
bool hideIfEmpty = true;
|
|
||||||
bool tooltip_enabled = true;
|
|
||||||
uint tooltip_spacing = 4;
|
|
||||||
uint tooltip_padding = 4;
|
|
||||||
uint iconSize = 20;
|
|
||||||
std::string format = DEFAULT_FORMAT;
|
|
||||||
std::string format_alt = DEFAULT_FORMAT_ALT;
|
|
||||||
|
|
||||||
Devices devices;
|
|
||||||
std::mutex m_Mutex;
|
|
||||||
UpClient *client;
|
|
||||||
UpDevice *displayDevice = nullptr;
|
|
||||||
guint login1_id;
|
|
||||||
GDBusConnection *login1_connection;
|
|
||||||
std::unique_ptr<UPowerTooltip> upower_tooltip;
|
|
||||||
std::string lastStatus;
|
|
||||||
bool showAltText;
|
|
||||||
bool showIcon = true;
|
|
||||||
bool upowerRunning;
|
|
||||||
guint upowerWatcher_id;
|
|
||||||
std::string nativePath_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace waybar::modules::upower
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <libupower-glib/upower.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "gtkmm/box.h"
|
|
||||||
#include "gtkmm/label.h"
|
|
||||||
#include "gtkmm/window.h"
|
|
||||||
|
|
||||||
namespace waybar::modules::upower {
|
|
||||||
|
|
||||||
class UPowerTooltip : public Gtk::Window {
|
|
||||||
private:
|
|
||||||
typedef std::unordered_map<std::string, UpDevice*> Devices;
|
|
||||||
|
|
||||||
const std::string getDeviceIcon(UpDeviceKind& kind);
|
|
||||||
|
|
||||||
std::unique_ptr<Gtk::Box> contentBox;
|
|
||||||
|
|
||||||
uint iconSize;
|
|
||||||
uint tooltipSpacing;
|
|
||||||
uint tooltipPadding;
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPowerTooltip(uint iconSize, uint tooltipSpacing, uint tooltipPadding);
|
|
||||||
virtual ~UPowerTooltip();
|
|
||||||
|
|
||||||
uint updateTooltip(Devices& devices);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace waybar::modules::upower
|
|
||||||
@@ -17,12 +17,15 @@ class Wireplumber : public ALabel {
|
|||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadRequiredApiModules();
|
void asyncLoadRequiredApiModules();
|
||||||
void prepare();
|
void prepare();
|
||||||
void activatePlugins();
|
void activatePlugins();
|
||||||
static void updateVolume(waybar::modules::Wireplumber* self, uint32_t id);
|
static void updateVolume(waybar::modules::Wireplumber* self, uint32_t id);
|
||||||
static void updateNodeName(waybar::modules::Wireplumber* self, uint32_t id);
|
static void updateNodeName(waybar::modules::Wireplumber* self, uint32_t id);
|
||||||
static void onPluginActivated(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
|
static void onPluginActivated(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
|
||||||
|
static void onDefaultNodesApiLoaded(WpObject* p, GAsyncResult* res,
|
||||||
|
waybar::modules::Wireplumber* self);
|
||||||
|
static void onMixerApiLoaded(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
|
||||||
static void onObjectManagerInstalled(waybar::modules::Wireplumber* self);
|
static void onObjectManagerInstalled(waybar::modules::Wireplumber* self);
|
||||||
static void onMixerChanged(waybar::modules::Wireplumber* self, uint32_t id);
|
static void onMixerChanged(waybar::modules::Wireplumber* self, uint32_t id);
|
||||||
static void onDefaultNodesApiChanged(waybar::modules::Wireplumber* self);
|
static void onDefaultNodesApiChanged(waybar::modules::Wireplumber* self);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
std::scoped_lock<std::mutex> lock((backend).udev_thread_mutex_); \
|
std::scoped_lock<std::mutex> lock((backend).udev_thread_mutex_); \
|
||||||
__devices = (backend).devices_; \
|
__devices = (backend).devices_; \
|
||||||
} \
|
} \
|
||||||
auto varname = (backend).best_device(__devices.cbegin(), __devices.cend(), preferred_device);
|
auto varname = (backend).best_device(__devices, preferred_device);
|
||||||
|
|
||||||
namespace waybar::util {
|
namespace waybar::util {
|
||||||
|
|
||||||
@@ -56,27 +56,21 @@ class BacklightBackend {
|
|||||||
|
|
||||||
void set_previous_best_device(const BacklightDevice *device);
|
void set_previous_best_device(const BacklightDevice *device);
|
||||||
|
|
||||||
void set_brightness(std::string preferred_device, ChangeType change_type, double step);
|
void set_brightness(const std::string &preferred_device, ChangeType change_type, double step);
|
||||||
|
|
||||||
void set_scaled_brightness(std::string preferred_device, int brightness);
|
void set_scaled_brightness(const std::string &preferred_device, int brightness);
|
||||||
int get_scaled_brightness(std::string preferred_device);
|
int get_scaled_brightness(const 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_); }
|
bool is_login_proxy_initialized() const { return static_cast<bool>(login_proxy_); }
|
||||||
|
|
||||||
template <class ForwardIt>
|
static const BacklightDevice *best_device(const std::vector<BacklightDevice> &devices,
|
||||||
static const BacklightDevice *best_device(ForwardIt first, ForwardIt last, std::string_view);
|
std::string_view);
|
||||||
|
|
||||||
std::vector<BacklightDevice> devices_;
|
std::vector<BacklightDevice> devices_;
|
||||||
std::mutex udev_thread_mutex_;
|
std::mutex udev_thread_mutex_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void set_brightness_internal(std::string device_name, int brightness, int max_brightness);
|
void set_brightness_internal(const std::string &device_name, int brightness, int max_brightness);
|
||||||
|
|
||||||
std::function<void()> on_updated_cb_;
|
std::function<void()> on_updated_cb_;
|
||||||
std::chrono::milliseconds polling_interval_;
|
std::chrono::milliseconds polling_interval_;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <pipewire/pipewire.h>
|
#include <pipewire/pipewire.h>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "util/backend_common.hpp"
|
#include "util/backend_common.hpp"
|
||||||
#include "util/pipewire/privacy_node_info.hpp"
|
#include "util/pipewire/privacy_node_info.hpp"
|
||||||
|
|
||||||
@@ -13,7 +15,8 @@ class PipewireBackend {
|
|||||||
pw_context* context_;
|
pw_context* context_;
|
||||||
pw_core* core_;
|
pw_core* core_;
|
||||||
|
|
||||||
spa_hook registry_listener;
|
pw_registry* registry_;
|
||||||
|
spa_hook registryListener_;
|
||||||
|
|
||||||
/* Hack to keep constructor inaccessible but still public.
|
/* Hack to keep constructor inaccessible but still public.
|
||||||
* This is required to be able to use std::make_shared.
|
* This is required to be able to use std::make_shared.
|
||||||
@@ -21,20 +24,22 @@ class PipewireBackend {
|
|||||||
* pointer because the destructor will manually free memory, and this could be
|
* pointer because the destructor will manually free memory, and this could be
|
||||||
* a problem with C++20's copy and move semantics.
|
* a problem with C++20's copy and move semantics.
|
||||||
*/
|
*/
|
||||||
struct private_constructor_tag {};
|
struct PrivateConstructorTag {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::mutex mutex_;
|
|
||||||
|
|
||||||
pw_registry* registry;
|
|
||||||
|
|
||||||
sigc::signal<void> privacy_nodes_changed_signal_event;
|
sigc::signal<void> privacy_nodes_changed_signal_event;
|
||||||
|
|
||||||
std::unordered_map<uint32_t, PrivacyNodeInfo*> privacy_nodes;
|
std::unordered_map<uint32_t, PrivacyNodeInfo*> privacy_nodes;
|
||||||
|
std::mutex mutex_;
|
||||||
|
|
||||||
static std::shared_ptr<PipewireBackend> getInstance();
|
static std::shared_ptr<PipewireBackend> getInstance();
|
||||||
|
|
||||||
PipewireBackend(private_constructor_tag tag);
|
// Handlers for PipeWire events
|
||||||
|
void handleRegistryEventGlobal(uint32_t id, uint32_t permissions, const char* type,
|
||||||
|
uint32_t version, const struct spa_dict* props);
|
||||||
|
void handleRegistryEventGlobalRemove(uint32_t id);
|
||||||
|
|
||||||
|
PipewireBackend(PrivateConstructorTag tag);
|
||||||
~PipewireBackend();
|
~PipewireBackend();
|
||||||
};
|
};
|
||||||
} // namespace waybar::util::PipewireBackend
|
} // namespace waybar::util::PipewireBackend
|
||||||
|
|||||||
@@ -34,29 +34,12 @@ class PrivacyNodeInfo {
|
|||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
std::string get_name() {
|
std::string getName();
|
||||||
const std::vector<std::string *> names{&application_name, &node_name};
|
std::string getIconName();
|
||||||
std::string name = "Unknown Application";
|
|
||||||
for (auto &name_ : names) {
|
|
||||||
if (name_ != nullptr && name_->length() > 0) {
|
|
||||||
name = *name_;
|
|
||||||
name[0] = toupper(name[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string get_icon_name() {
|
// Handlers for PipeWire events
|
||||||
const std::vector<std::string *> names{&application_icon_name, &pipewire_access_portal_app_id,
|
void handleProxyEventDestroy();
|
||||||
&application_name, &node_name};
|
void handleNodeEventInfo(const struct pw_node_info *info);
|
||||||
const std::string name = "application-x-executable-symbolic";
|
|
||||||
for (auto &name_ : names) {
|
|
||||||
if (name_ != nullptr && name_->length() > 0 && DefaultGtkIconThemeWrapper::has_icon(*name_)) {
|
|
||||||
return *name_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::util::PipewireBackend
|
} // namespace waybar::util::PipewireBackend
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace waybar::util {
|
namespace waybar::util {
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ struct Rule {
|
|||||||
// See https://en.cppreference.com/w/cpp/compiler_support/20 "Parenthesized initialization of
|
// See https://en.cppreference.com/w/cpp/compiler_support/20 "Parenthesized initialization of
|
||||||
// aggregates"
|
// aggregates"
|
||||||
Rule(std::regex rule, std::string repr, int priority)
|
Rule(std::regex rule, std::string repr, int priority)
|
||||||
: rule(rule), repr(repr), priority(priority) {}
|
: rule(std::move(rule)), repr(std::move(repr)), priority(priority) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
int default_priority_function(std::string& key);
|
int default_priority_function(std::string& key);
|
||||||
@@ -36,12 +37,13 @@ class RegexCollection {
|
|||||||
std::map<std::string, std::string> regex_cache;
|
std::map<std::string, std::string> regex_cache;
|
||||||
std::string default_repr;
|
std::string default_repr;
|
||||||
|
|
||||||
std::string& find_match(std::string& value, bool& matched_any);
|
std::string find_match(std::string& value, bool& matched_any);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RegexCollection() = default;
|
RegexCollection() = default;
|
||||||
RegexCollection(const Json::Value& map, std::string default_repr = "",
|
RegexCollection(
|
||||||
std::function<int(std::string&)> priority_function = default_priority_function);
|
const Json::Value& map, std::string default_repr = "",
|
||||||
|
const std::function<int(std::string&)>& priority_function = default_priority_function);
|
||||||
~RegexCollection() = default;
|
~RegexCollection() = default;
|
||||||
|
|
||||||
std::string& get(std::string& value, bool& matched_any);
|
std::string& get(std::string& value, bool& matched_any);
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ The *backlight* module displays the current backlight level.
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
@@ -77,6 +81,19 @@ The *backlight* module displays the current backlight level.
|
|||||||
default: 1.0 ++
|
default: 1.0 ++
|
||||||
The speed at which to change the brightness when scrolling.
|
The speed at which to change the brightness when scrolling.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# EXAMPLE:
|
# EXAMPLE:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -61,7 +61,11 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer++
|
typeof: integer++
|
||||||
@@ -105,6 +109,19 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
|||||||
default: false ++
|
default: false ++
|
||||||
Option to enable battery compatibility if not detected.
|
Option to enable battery compatibility if not detected.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{capacity}*: Capacity in percentage
|
*{capacity}*: Capacity in percentage
|
||||||
@@ -115,6 +132,10 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
|||||||
|
|
||||||
*{time}*: Estimate of time until full or empty. Note that this is based on the power draw at the last refresh time, not an average.
|
*{time}*: Estimate of time until full or empty. Note that this is based on the power draw at the last refresh time, not an average.
|
||||||
|
|
||||||
|
*{cycles}*: Amount of charge cycles the highest-capacity battery has seen. *(Linux only)*
|
||||||
|
|
||||||
|
*{health}*: The percentage of the highest-capacity battery's original maximum charge it can still hold.
|
||||||
|
|
||||||
# TIME FORMAT
|
# TIME FORMAT
|
||||||
|
|
||||||
The *battery* module allows you to define how time should be formatted via *format-time*.
|
The *battery* module allows you to define how time should be formatted via *format-time*.
|
||||||
|
|||||||
@@ -66,7 +66,11 @@ Addressed by *bluetooth*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -125,6 +129,19 @@ Addressed by *bluetooth*
|
|||||||
typeof: string ++
|
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.
|
This format is used to define how each connected device should be displayed within the *device_enumerate* format replacement in the tooltip menu.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{status}*: Status of the bluetooth device.
|
*{status}*: Status of the bluetooth device.
|
||||||
|
|||||||
@@ -120,6 +120,18 @@ libcava lives in:
|
|||||||
:[ string
|
:[ string
|
||||||
:[ /dev/stdout
|
:[ /dev/stdout
|
||||||
:[ It's impossible to set it. Waybar sets it to = /dev/stdout for internal needs
|
:[ It's impossible to set it. Waybar sets it to = /dev/stdout for internal needs
|
||||||
|
|[ *menu*
|
||||||
|
:[ string
|
||||||
|
:[
|
||||||
|
:[ Action that popups the menu.
|
||||||
|
|[ *menu-file*
|
||||||
|
:[ string
|
||||||
|
:[
|
||||||
|
:[ Location of the menu descriptor file. There need to be an element of type GtkMenu with id *menu*
|
||||||
|
|[ *menu-actions*
|
||||||
|
:[ array
|
||||||
|
:[
|
||||||
|
:[ The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
Configuration can be provided as:
|
Configuration can be provided as:
|
||||||
- The only cava configuration file which is provided through *cava_config*. The rest configuration can be skipped
|
- The only cava configuration file which is provided through *cava_config*. The rest configuration can be skipped
|
||||||
|
|||||||
@@ -84,6 +84,18 @@ $XDG_CONFIG_HOME/waybar/config ++
|
|||||||
:[ string
|
:[ string
|
||||||
:[ same as format
|
:[ same as format
|
||||||
:[ Tooltip on hover
|
:[ Tooltip on hover
|
||||||
|
|[ *menu*
|
||||||
|
:[ string
|
||||||
|
:[
|
||||||
|
:[ Action that popups the menu.
|
||||||
|
|[ *menu-file*
|
||||||
|
:[ string
|
||||||
|
:[
|
||||||
|
:[ Location of the menu descriptor file. There need to be an element of type GtkMenu with id *menu*
|
||||||
|
|[ *menu-actions*
|
||||||
|
:[ array
|
||||||
|
:[
|
||||||
|
:[ The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
View all valid format options in *strftime(3)* or have a look https://en.cppreference.com/w/cpp/chrono/duration/formatter
|
View all valid format options in *strftime(3)* or have a look https://en.cppreference.com/w/cpp/chrono/duration/formatter
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,11 @@ The *cpu* module displays the current CPU utilization.
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|||||||
+22
-1
@@ -21,6 +21,10 @@ Addressed by *custom/<name>*
|
|||||||
The path to a script, which determines if the script in *exec* should be executed. ++
|
The path to a script, which determines if the script in *exec* should be executed. ++
|
||||||
*exec* will be executed if the exit code of *exec-if* equals 0.
|
*exec* will be executed if the exit code of *exec-if* equals 0.
|
||||||
|
|
||||||
|
*hide-empty-text*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
Disables the module when output is empty, but format might contain additional static content.
|
||||||
|
|
||||||
*exec-on-event*: ++
|
*exec-on-event*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: true ++
|
default: true ++
|
||||||
@@ -72,7 +76,11 @@ Addressed by *custom/<name>*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -117,6 +125,19 @@ Addressed by *custom/<name>*
|
|||||||
default: false ++
|
default: false ++
|
||||||
Option to enable escaping of script output.
|
Option to enable escaping of script output.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# RETURN-TYPE
|
# RETURN-TYPE
|
||||||
|
|
||||||
When *return-type* is set to *json*, Waybar expects the *exec*-script to output its data in JSON format.
|
When *return-type* is set to *json*, Waybar expects the *exec*-script to output its data in JSON format.
|
||||||
|
|||||||
+18
-1
@@ -45,7 +45,11 @@ Addressed by *disk*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -89,6 +93,19 @@ Addressed by *disk*
|
|||||||
typeof: string ++
|
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.
|
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.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{percentage_used}*: Percentage of disk in use.
|
*{percentage_used}*: Percentage of disk in use.
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
waybar-dwl-window(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - dwl window module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *window* module displays the title of the currently focused window in DWL
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
Addressed by *dwl/window*
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {title} ++
|
||||||
|
The format, how information should be displayed.
|
||||||
|
|
||||||
|
*rotate*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
Positive value to rotate the text label.
|
||||||
|
|
||||||
|
*max-length*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
The maximum length in character the module should display.
|
||||||
|
|
||||||
|
*min-length*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
The minimum length in characters the module should accept.
|
||||||
|
|
||||||
|
*align*: ++
|
||||||
|
typeof: float ++
|
||||||
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
|
*on-click*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when clicked on the module.
|
||||||
|
|
||||||
|
*on-click-middle*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when middle-clicked on the module using mousewheel.
|
||||||
|
|
||||||
|
*on-click-right*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when you right-click on the module.
|
||||||
|
|
||||||
|
*on-update*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when the module is updated.
|
||||||
|
|
||||||
|
*on-scroll-up*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when scrolling up on the module.
|
||||||
|
|
||||||
|
*on-scroll-down*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when scrolling down on the module.
|
||||||
|
|
||||||
|
*smooth-scrolling-threshold*: ++
|
||||||
|
typeof: double ++
|
||||||
|
Threshold to be used when scrolling.
|
||||||
|
|
||||||
|
*tooltip*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*rewrite*: ++
|
||||||
|
typeof: object ++
|
||||||
|
Rules to rewrite the module format output. See *rewrite rules*.
|
||||||
|
|
||||||
|
*icon*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
Option to hide the application icon.
|
||||||
|
|
||||||
|
*icon-size*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
default: 24 ++
|
||||||
|
Option to change the size of the application icon.
|
||||||
|
|
||||||
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
*{title}*: The title of the focused window.
|
||||||
|
|
||||||
|
*{app_id}*: The app_id of the focused window.
|
||||||
|
|
||||||
|
*{layout}*: The layout of the focused window.
|
||||||
|
|
||||||
|
# REWRITE RULES
|
||||||
|
|
||||||
|
*rewrite* is an object where keys are regular expressions and values are
|
||||||
|
rewrite rules if the expression matches. Rules may contain references to
|
||||||
|
captures of the expression.
|
||||||
|
|
||||||
|
Regular expression and replacement follow ECMA-script rules.
|
||||||
|
|
||||||
|
If no expression matches, the format output is left unchanged.
|
||||||
|
|
||||||
|
Invalid expressions (e.g., mismatched parentheses) are skipped.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"dwl/window": {
|
||||||
|
"format": "{}",
|
||||||
|
"max-length": 50,
|
||||||
|
"rewrite": {
|
||||||
|
"(.*) - Mozilla Firefox": "🌎 $1",
|
||||||
|
"(.*) - zsh": "> [$1]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -25,6 +25,19 @@ Addressed by *hyprland/language*
|
|||||||
typeof: string ++
|
typeof: string ++
|
||||||
Specifies which keyboard to use from hyprctl devices output. Using the option that begins with "at-translated-set..." is recommended.
|
Specifies which keyboard to use from hyprctl devices output. Using the option that begins with "at-translated-set..." is recommended.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,11 @@ Addressed by *hyprland/submap*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -66,6 +70,29 @@ Addressed by *hyprland/submap*
|
|||||||
default: true ++
|
default: true ++
|
||||||
Option to disable tooltip on hover.
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*always-on*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
Option to display the widget even when there's no active submap.
|
||||||
|
|
||||||
|
*default-submap* ++
|
||||||
|
typeof: string ++
|
||||||
|
default: Default ++
|
||||||
|
Option to set the submap name to display when not in an active submap.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ Addressed by *hyprland/workspaces*
|
|||||||
default: false ++
|
default: false ++
|
||||||
If set to true, special workspaces will be shown.
|
If set to true, special workspaces will be shown.
|
||||||
|
|
||||||
|
*special-visible-only*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If this and show-special are to true, special workspaces will be shown only if visible.
|
||||||
|
|
||||||
*all-outputs*: ++
|
*all-outputs*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: false ++
|
default: false ++
|
||||||
@@ -52,6 +57,13 @@ Addressed by *hyprland/workspaces*
|
|||||||
default: false ++
|
default: false ++
|
||||||
If set to true, only the active workspace will be shown.
|
If set to true, only the active workspace will be shown.
|
||||||
|
|
||||||
|
*move-to-monitor*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If set to true, open the workspace on the current monitor when clicking on a workspace button.
|
||||||
|
Otherwise, the workspace will open on the monitor where it was previously assigned.
|
||||||
|
Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland.
|
||||||
|
|
||||||
*ignore-workspaces*: ++
|
*ignore-workspaces*: ++
|
||||||
typeof: array ++
|
typeof: array ++
|
||||||
default: [] ++
|
default: [] ++
|
||||||
@@ -135,6 +147,7 @@ Additional to workspace name matching, the following *format-icons* can be set.
|
|||||||
"class<firefox> title<.*github.*>": "", // Windows whose class is "firefox" and title contains "github". Note that "class" always comes first.
|
"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.
|
"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": "",
|
"code": "",
|
||||||
|
"title<.* - (.*) - VSCodium>": "codium $1" // captures part of the window title and formats it into output
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -158,3 +171,4 @@ Additional to workspace name matching, the following *format-icons* can be set.
|
|||||||
- *#workspaces button.persistent*
|
- *#workspaces button.persistent*
|
||||||
- *#workspaces button.special*
|
- *#workspaces button.special*
|
||||||
- *#workspaces button.urgent*
|
- *#workspaces button.urgent*
|
||||||
|
- *#workspaces button.hosting-monitor* (gets applied if workspace-monitor == waybar-monitor)
|
||||||
|
|||||||
@@ -33,7 +33,11 @@ screensaver, also known as "presentation mode".
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -85,6 +89,19 @@ screensaver, also known as "presentation mode".
|
|||||||
typeof: string ++
|
typeof: string ++
|
||||||
This format is used when the inhibit is deactivated.
|
This format is used when the inhibit is deactivated.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu. Cannot be "on-click".
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{status}*: status (*activated* or *deactivated*)
|
*{status}*: status (*activated* or *deactivated*)
|
||||||
|
|||||||
@@ -37,7 +37,11 @@ See *systemd-inhibit*(1) for more information.
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -72,6 +76,19 @@ See *systemd-inhibit*(1) for more information.
|
|||||||
default: true ++
|
default: true ++
|
||||||
Option to disable tooltip on hover.
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu. Cannot be "on-click".
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{status}*: status (*activated* or *deactivated*)
|
*{status}*: status (*activated* or *deactivated*)
|
||||||
|
|||||||
+18
-1
@@ -63,7 +63,11 @@ Addressed by *jack*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -81,6 +85,19 @@ Addressed by *jack*
|
|||||||
typeof: string ++
|
typeof: string ++
|
||||||
Command to execute when the module is updated.
|
Command to execute when the module is updated.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{load}*: The current CPU load estimated by JACK.
|
*{load}*: The current CPU load estimated by JACK.
|
||||||
|
|||||||
+18
-1
@@ -45,7 +45,11 @@ Addressed by *memory*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -80,6 +84,19 @@ Addressed by *memory*
|
|||||||
default: true ++
|
default: true ++
|
||||||
Option to disable tooltip on hover.
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{percentage}*: Percentage of memory in use.
|
*{percentage}*: Percentage of memory in use.
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
waybar-menu(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - menu property
|
||||||
|
|
||||||
|
# OVERVIEW
|
||||||
|
|
||||||
|
|
||||||
|
Some modules support a 'menu', which allows to have a popup menu whan a defined
|
||||||
|
click is done over the module.
|
||||||
|
|
||||||
|
# PROPERTIES
|
||||||
|
|
||||||
|
A module that implements a 'menu' needs 3 properties defined in its config :
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu. The possibles actions are :
|
||||||
|
|
||||||
|
[- *Option*
|
||||||
|
:- *Description*
|
||||||
|
|[ *on-click*
|
||||||
|
:< When you left-click on the module
|
||||||
|
|[ *on-click-release*
|
||||||
|
:< When you release left button on the module
|
||||||
|
|[ *on-double-click*
|
||||||
|
:< When you double left click on the module
|
||||||
|
|[ *on-triple-click*
|
||||||
|
:< When you triple left click on the module
|
||||||
|
|[ *on-click-middle*
|
||||||
|
:< When you middle click on the module using mousewheel
|
||||||
|
|[ *on-click-middle-release*
|
||||||
|
:< When you release mousewheel button on the module
|
||||||
|
|[ *on-double-click-middle*
|
||||||
|
:< When you double middle click on the module
|
||||||
|
|[ *on-triple-click-middle*
|
||||||
|
:< When you triple middle click on the module
|
||||||
|
|[ *on-click-right*
|
||||||
|
:< When you right click on the module using
|
||||||
|
|[ *on-click-right-release*
|
||||||
|
:< When you release right button on the module
|
||||||
|
|[ *on-double-click-right*
|
||||||
|
:< When you double right click on the module
|
||||||
|
|[ *on-triple-click-right*
|
||||||
|
:< When you triple middle click on the module
|
||||||
|
|[ *on-click-backward*
|
||||||
|
:< When you click on the module using mouse backward button
|
||||||
|
|[ *on-click-backward-release*
|
||||||
|
:< When you release mouse backward button on the module
|
||||||
|
|[ *on-double-click-backward*
|
||||||
|
:< When you double click on the module using mouse backward button
|
||||||
|
|[ *on-triple-click-backward*
|
||||||
|
:< When you triple click on the module using mouse backawrd button
|
||||||
|
|[ *on-click-forward*
|
||||||
|
:< When you click on the module using mouse forward button
|
||||||
|
|[ *on-click-forward-release*
|
||||||
|
:< When you release mouse forward button on the module
|
||||||
|
|[ *on-double-click-forward*
|
||||||
|
:< When you double click on the module using mouse forward button
|
||||||
|
|[ *on-triple-click-forward*
|
||||||
|
:< When you triple click on the module using mouse forward button
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*.
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu. The identifiers of
|
||||||
|
each actions needs to exists as an id in the 'menu-file' for it to be linked
|
||||||
|
properly.
|
||||||
|
|
||||||
|
# MENU-FILE
|
||||||
|
|
||||||
|
The menu-file is an `.xml` file representing a GtkBuilder. Documentation for it
|
||||||
|
can be found here : https://docs.gtk.org/gtk4/class.Builder.html
|
||||||
|
|
||||||
|
Here, it needs to have an element of type GtkMenu with id "menu". Eeach actions
|
||||||
|
in *menu-actions* are linked to elements in the *menu-file* file by the id of
|
||||||
|
the elements.
|
||||||
|
|
||||||
|
# EXAMPLE
|
||||||
|
|
||||||
|
Module config :
|
||||||
|
```
|
||||||
|
"custom/power": {
|
||||||
|
"format" : "⏻ ",
|
||||||
|
"tooltip": false,
|
||||||
|
"menu": "on-click",
|
||||||
|
"menu-file": "~/.config/waybar/power_menu.xml",
|
||||||
|
"menu-actions": {
|
||||||
|
"shutdown": "shutdown",
|
||||||
|
"reboot": "reboot",
|
||||||
|
"suspend": "systemctl suspend",
|
||||||
|
"hibernate": "systemctl hibernate",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
~/.config/waybar/power_menu.xml :
|
||||||
|
```
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<object class="GtkMenu" id="menu">
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="suspend">
|
||||||
|
<property name="label">Suspend</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="hibernat">
|
||||||
|
<property name="label">Hibernate</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="shutdown">
|
||||||
|
<property name="label">Shutdown</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSeparatorMenuItem" id="delimiter1"/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="reboot">
|
||||||
|
<property name="label">Reboot</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
||||||
|
```
|
||||||
|
|
||||||
|
# STYLING MENUS
|
||||||
|
|
||||||
|
- *menu*
|
||||||
|
Style for the menu
|
||||||
|
|
||||||
|
- *menuitem*
|
||||||
|
Style for items in the menu
|
||||||
|
|
||||||
|
# EXAMPLE:
|
||||||
|
|
||||||
|
```
|
||||||
|
menu {
|
||||||
|
border-radius: 15px;
|
||||||
|
background: #161320;
|
||||||
|
color: #B5E8E0;
|
||||||
|
}
|
||||||
|
menuitem {
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
```
|
||||||
+18
-1
@@ -103,7 +103,11 @@ Addressed by *mpd*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -158,6 +162,19 @@ Addressed by *mpd*
|
|||||||
default: {} ++
|
default: {} ++
|
||||||
Icon to show depending on the "single" option (*{ "on": "...", "off": "..." }*)
|
Icon to show depending on the "single" option (*{ "on": "...", "off": "..." }*)
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
## WHEN PLAYING/PAUSED
|
## WHEN PLAYING/PAUSED
|
||||||
|
|||||||
@@ -119,8 +119,11 @@ The *mpris* module displays currently playing media via libplayerctl.
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. ++
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
If the module is rotated, it will follow the flow of the text.
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -139,11 +142,11 @@ The *mpris* module displays currently playing media via libplayerctl.
|
|||||||
|
|
||||||
*player-icons*: ++
|
*player-icons*: ++
|
||||||
typeof: map[string]string ++
|
typeof: map[string]string ++
|
||||||
Allows setting _{player-icon}_ based on player-name property.
|
Allows setting _{player_icon}_ based on player-name property.
|
||||||
|
|
||||||
*status-icons*: ++
|
*status-icons*: ++
|
||||||
typeof: map[string]string ++
|
typeof: map[string]string ++
|
||||||
Allows setting _{status-icon}_ based on player status (playing, paused, stopped).
|
Allows setting _{status_icon}_ based on player status (playing, paused, stopped).
|
||||||
|
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|||||||
@@ -70,7 +70,11 @@ Addressed by *network*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -125,6 +129,19 @@ Addressed by *network*
|
|||||||
typeof: string ++
|
typeof: string ++
|
||||||
This format is used when the displayed interface is disabled.
|
This format is used when the displayed interface is disabled.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{ifname}*: Name of the network interface.
|
*{ifname}*: Name of the network interface.
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
waybar-power-profiles-daemon(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - power-profiles-daemon module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *power-profiles-daemon* module displays the active power-profiles-daemon profile and cycle through the available profiles on click.
|
||||||
|
|
||||||
|
# FILES
|
||||||
|
|
||||||
|
$XDG_CONFIG_HOME/waybar/config
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
|
||||||
|
[- *Option*
|
||||||
|
:- *Typeof*
|
||||||
|
:- *Default*
|
||||||
|
:= *Description*
|
||||||
|
|[ *format*
|
||||||
|
:[ string
|
||||||
|
:[ "{icon}"
|
||||||
|
:[ Message displayed on the bar. {icon} and {profile} are respectively substituted with the icon representing the active profile and its full name.
|
||||||
|
|[ *tooltip-format*
|
||||||
|
:[ string
|
||||||
|
:[ "Power profile: {profile}\\nDriver: {driver}"
|
||||||
|
:[ Messaged displayed in the module tooltip. {icon} and {profile} are respectively substituted with the icon representing the active profile and its full name.
|
||||||
|
|[ *tooltip*
|
||||||
|
:[ bool
|
||||||
|
:[ true
|
||||||
|
:[ Display the tooltip.
|
||||||
|
|[ *format-icons*
|
||||||
|
:[ object
|
||||||
|
:[ See default value in the example below.
|
||||||
|
:[ Icons used to represent the various power-profile. *Note*: the default configuration uses the font-awesome icons. You may want to override it if you don't have this font installed on your system.
|
||||||
|
|
||||||
|
|
||||||
|
# CONFIGURATION EXAMPLES
|
||||||
|
|
||||||
|
Compact display (default config):
|
||||||
|
|
||||||
|
```
|
||||||
|
"power-profiles-daemon": {
|
||||||
|
"format": "{icon}",
|
||||||
|
"tooltip-format": "Power profile: {profile}\nDriver: {driver}",
|
||||||
|
"tooltip": true,
|
||||||
|
"format-icons": {
|
||||||
|
"default": "",
|
||||||
|
"performance": "",
|
||||||
|
"balanced": "",
|
||||||
|
"power-saver": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Display the full profile name:
|
||||||
|
|
||||||
|
```
|
||||||
|
"power-profiles-daemon": {
|
||||||
|
"format": "{icon} {profile}",
|
||||||
|
"tooltip-format": "Power profile: {profile}\nDriver: {driver}",
|
||||||
|
"tooltip": true,
|
||||||
|
"format-icons": {
|
||||||
|
"default": "",
|
||||||
|
"performance": "",
|
||||||
|
"balanced": "",
|
||||||
|
"power-saver": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -31,7 +31,7 @@ The volume can be controlled by dragging the slider across the bar or clicking o
|
|||||||
|
|
||||||
```
|
```
|
||||||
"modules-right": [
|
"modules-right": [
|
||||||
"pulseaudio-slider",
|
"pulseaudio/slider",
|
||||||
],
|
],
|
||||||
"pulseaudio/slider": {
|
"pulseaudio/slider": {
|
||||||
"min": 0,
|
"min": 0,
|
||||||
|
|||||||
@@ -56,7 +56,11 @@ Additionally, you can control the volume by scrolling *up* or *down* while the c
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*scroll-step*: ++
|
*scroll-step*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
@@ -109,6 +113,19 @@ Additionally, you can control the volume by scrolling *up* or *down* while the c
|
|||||||
typeof: array ++
|
typeof: array ++
|
||||||
Sinks in this list will not be shown as 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.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{desc}*: Pulseaudio port's description, for bluetooth it'll be the device name.
|
*{desc}*: Pulseaudio port's description, for bluetooth it'll be the device name.
|
||||||
@@ -138,6 +155,8 @@ If they are found in the current PulseAudio port name, the corresponding icons w
|
|||||||
- *hifi*
|
- *hifi*
|
||||||
- *phone*
|
- *phone*
|
||||||
|
|
||||||
|
Additionally, suffixing a device name or port with *-muted* will cause the icon
|
||||||
|
to be selected when the corresponding audio device is muted. This applies to *default* as well.
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
@@ -148,10 +167,12 @@ If they are found in the current PulseAudio port name, the corresponding icons w
|
|||||||
"format-muted": "",
|
"format-muted": "",
|
||||||
"format-icons": {
|
"format-icons": {
|
||||||
"alsa_output.pci-0000_00_1f.3.analog-stereo": "",
|
"alsa_output.pci-0000_00_1f.3.analog-stereo": "",
|
||||||
|
"alsa_output.pci-0000_00_1f.3.analog-stereo-muted": "",
|
||||||
"headphones": "",
|
"headphones": "",
|
||||||
"handsfree": "",
|
"handsfree": "",
|
||||||
"headset": "",
|
"headset": "",
|
||||||
"phone": "",
|
"phone": "",
|
||||||
|
"phone-muted": "",
|
||||||
"portable": "",
|
"portable": "",
|
||||||
"car": "",
|
"car": "",
|
||||||
"default": ["", ""]
|
"default": ["", ""]
|
||||||
|
|||||||
@@ -33,7 +33,11 @@ Addressed by *river/layout*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -47,6 +51,19 @@ Addressed by *river/layout*
|
|||||||
typeof: string ++
|
typeof: string ++
|
||||||
Command to execute when you right-click on the module.
|
Command to execute when you right-click on the module.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# EXAMPLE
|
# EXAMPLE
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -31,7 +31,11 @@ Addressed by *river/mode*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -61,6 +65,19 @@ Addressed by *river/mode*
|
|||||||
typeof: double ++
|
typeof: double ++
|
||||||
Threshold to be used when scrolling.
|
Threshold to be used when scrolling.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -31,7 +31,11 @@ Addressed by *river/window*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -45,6 +49,19 @@ Addressed by *river/window*
|
|||||||
typeof: string ++
|
typeof: string ++
|
||||||
Command to execute when you right-click on the module.
|
Command to execute when you right-click on the module.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
+18
-1
@@ -32,7 +32,11 @@ cursor is over the module, and clicking on the module toggles mute.
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*scroll-step*: ++
|
*scroll-step*: ++
|
||||||
typeof: int ++
|
typeof: int ++
|
||||||
@@ -70,6 +74,19 @@ cursor is over the module, and clicking on the module toggles mute.
|
|||||||
typeof: double ++
|
typeof: double ++
|
||||||
Threshold to be used when scrolling.
|
Threshold to be used when scrolling.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{volume}*: Volume in percentage.
|
*{volume}*: Volume in percentage.
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
waybar-styles(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar-styles - using stylesheets for waybar
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
Waybar uses Cascading Style Sheets (CSS) to configure its appearance.
|
||||||
|
|
||||||
|
It uses the first file found in this search order:
|
||||||
|
|
||||||
|
- *$XDG_CONFIG_HOME/waybar/style.css*
|
||||||
|
- *~/.config/waybar/style.css*
|
||||||
|
- *~/waybar/style.css*
|
||||||
|
- */etc/xdg/waybar/style.css*
|
||||||
|
- *@sysconfdir@/xdg/waybar/style.css*
|
||||||
|
|
||||||
|
# EXAMPLE
|
||||||
|
|
||||||
|
An example user-controlled stylesheet that just changes the color of the clock to be green on black, while keeping the rest of the system config the same would be:
|
||||||
|
|
||||||
|
```
|
||||||
|
@import url("file:///etc/xdg/waybar/style.css")
|
||||||
|
|
||||||
|
#clock {
|
||||||
|
background: #000000;
|
||||||
|
color: #00ff00;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hover-effect
|
||||||
|
|
||||||
|
You can apply special styling to any module for when the cursor hovers it.
|
||||||
|
|
||||||
|
```
|
||||||
|
#clock:hover {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# SEE ALSO
|
||||||
|
|
||||||
|
- *waybar(5)*
|
||||||
@@ -17,6 +17,11 @@ Addressed by *sway/language*
|
|||||||
default: {} ++
|
default: {} ++
|
||||||
The format, how layout should be displayed.
|
The format, how layout should be displayed.
|
||||||
|
|
||||||
|
*hide-single-layout*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
Defines visibility of the module if a single layout is configured
|
||||||
|
|
||||||
*tooltip-format*: ++
|
*tooltip-format*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
default: {} ++
|
default: {} ++
|
||||||
@@ -27,6 +32,19 @@ Addressed by *sway/language*
|
|||||||
default: true ++
|
default: true ++
|
||||||
Option to disable tooltip on hover.
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{short}*: Short name of layout (e.g. "us"). Equals to {}.
|
*{short}*: Short name of layout (e.g. "us"). Equals to {}.
|
||||||
|
|||||||
@@ -31,7 +31,11 @@ Addressed by *sway/mode*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -66,6 +70,19 @@ Addressed by *sway/mode*
|
|||||||
default: true ++
|
default: true ++
|
||||||
Option to disable tooltip on hover.
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -36,6 +36,19 @@ Addressed by *sway/scratchpad*
|
|||||||
default: {app}: {title} ++
|
default: {app}: {title} ++
|
||||||
The format, how information in the tooltip should be displayed.
|
The format, how information in the tooltip should be displayed.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{icon}*: Icon, as defined in *format-icons*.
|
*{icon}*: Icon, as defined in *format-icons*.
|
||||||
|
|||||||
@@ -31,7 +31,11 @@ Addressed by *sway/window*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ n.b.: the list of outputs can be obtained from command line using *swaymsg -t ge
|
|||||||
"window-rewrite": {
|
"window-rewrite": {
|
||||||
"class<firefox>": "",
|
"class<firefox>": "",
|
||||||
"class<kitty>": "k",
|
"class<kitty>": "k",
|
||||||
|
"title<.* - (.*) - VSCodium>": "codium $1" // captures part of the window title and formats it into output
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -182,5 +183,6 @@ n.b.: the list of outputs can be obtained from command line using *swaymsg -t ge
|
|||||||
- *#workspaces button.focused*
|
- *#workspaces button.focused*
|
||||||
- *#workspaces button.urgent*
|
- *#workspaces button.urgent*
|
||||||
- *#workspaces button.persistent*
|
- *#workspaces button.persistent*
|
||||||
|
- *#workspaces button.empty*
|
||||||
- *#workspaces button.current_output*
|
- *#workspaces button.current_output*
|
||||||
- *#workspaces button#sway-workspace-${name}*
|
- *#workspaces button#sway-workspace-${name}*
|
||||||
|
|||||||
@@ -36,6 +36,19 @@ Addressed by *systemd-failed-units*
|
|||||||
default: *true* ++
|
default: *true* ++
|
||||||
Option to hide this module when there is no failing units.
|
Option to hide this module when there is no failing units.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{nr_failed_system}*: Number of failed units from systemwide (PID=1) systemd.
|
*{nr_failed_system}*: Number of failed units from systemwide (PID=1) systemd.
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ Addressed by *temperature*
|
|||||||
*hwmon-path-abs*: ++
|
*hwmon-path-abs*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
The path of the hwmon-directory of the device, e.g. */sys/devices/pci0000:00/0000:00:18.3/hwmon*. (Note that the subdirectory *hwmon/hwmon#*, where *#* is a number is not part of the path!) Has to be used together with *input-filename*.
|
The path of the hwmon-directory of the device, e.g. */sys/devices/pci0000:00/0000:00:18.3/hwmon*. (Note that the subdirectory *hwmon/hwmon#*, where *#* is a number is not part of the path!) Has to be used together with *input-filename*.
|
||||||
|
This can also be an array of strings, for which, it just works like *hwmon-path*.
|
||||||
|
|
||||||
*input-filename*: ++
|
*input-filename*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -71,7 +72,11 @@ Addressed by *temperature*
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -106,6 +111,19 @@ Addressed by *temperature*
|
|||||||
default: true ++
|
default: true ++
|
||||||
Option to disable tooltip on hover.
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{temperatureC}*: Temperature in Celsius.
|
*{temperatureC}*: Temperature in Celsius.
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ compatible devices in the tooltip.
|
|||||||
The battery to monitor. Refer to the https://upower.freedesktop.org/docs/UpDevice.html#UpDevice--native-path ++
|
The battery to monitor. Refer to the https://upower.freedesktop.org/docs/UpDevice.html#UpDevice--native-path ++
|
||||||
Can be obtained using `upower --dump`
|
Can be obtained using `upower --dump`
|
||||||
|
|
||||||
|
*model*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: ++
|
||||||
|
The battery to monitor, based on the model. (this option is ignored if *native-path* is given). ++
|
||||||
|
Can be obtained using `upower --dump`
|
||||||
|
|
||||||
*icon-size*: ++
|
*icon-size*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
default: 20 ++
|
default: 20 ++
|
||||||
@@ -62,6 +68,19 @@ compatible devices in the tooltip.
|
|||||||
default: true ++
|
default: true ++
|
||||||
Option to disable battery icon.
|
Option to disable battery icon.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{percentage}*: The battery capacity in percentage
|
*{percentage}*: The battery capacity in percentage
|
||||||
|
|||||||
@@ -47,7 +47,11 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
|
|||||||
|
|
||||||
*align*: ++
|
*align*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
*scroll-step*: ++
|
*scroll-step*: ++
|
||||||
typeof: float ++
|
typeof: float ++
|
||||||
@@ -83,6 +87,19 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
|
|||||||
default: 100 ++
|
default: 100 ++
|
||||||
The maximum volume that can be set, in percentage.
|
The maximum volume that can be set, in percentage.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
|
GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{volume}*: Volume in percentage.
|
*{volume}*: Volume in percentage.
|
||||||
|
|||||||
+5
-1
@@ -16,9 +16,11 @@ Valid locations for this file are:
|
|||||||
- */etc/xdg/waybar/*
|
- */etc/xdg/waybar/*
|
||||||
- *@sysconfdir@/xdg/waybar/*
|
- *@sysconfdir@/xdg/waybar/*
|
||||||
|
|
||||||
A good starting point is the default configuration found at https://github.com/Alexays/Waybar/blob/master/resources/config
|
A good starting point is the default configuration found at https://github.com/Alexays/Waybar/blob/master/resources/config.jsonc
|
||||||
Also, a minimal example configuration can be found at the bottom of this man page.
|
Also, a minimal example configuration can be found at the bottom of this man page.
|
||||||
|
|
||||||
|
The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(5)* for details.
|
||||||
|
|
||||||
# BAR CONFIGURATION
|
# BAR CONFIGURATION
|
||||||
|
|
||||||
*layer* ++
|
*layer* ++
|
||||||
@@ -310,6 +312,7 @@ A group may hide all but one element, showing them only on mouse hover. In order
|
|||||||
- *waybar-custom(5)*
|
- *waybar-custom(5)*
|
||||||
- *waybar-disk(5)*
|
- *waybar-disk(5)*
|
||||||
- *waybar-dwl-tags(5)*
|
- *waybar-dwl-tags(5)*
|
||||||
|
- *waybar-dwl-window(5)*
|
||||||
- *waybar-gamemode(5)*
|
- *waybar-gamemode(5)*
|
||||||
- *waybar-hyprland-language(5)*
|
- *waybar-hyprland-language(5)*
|
||||||
- *waybar-hyprland-submap(5)*
|
- *waybar-hyprland-submap(5)*
|
||||||
@@ -346,3 +349,4 @@ A group may hide all but one element, showing them only on mouse hover. In order
|
|||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
*sway-output(5)*
|
*sway-output(5)*
|
||||||
|
*waybar-styles(5)"
|
||||||
|
|||||||
+23
-11
@@ -1,6 +1,6 @@
|
|||||||
project(
|
project(
|
||||||
'waybar', 'cpp', 'c',
|
'waybar', 'cpp', 'c',
|
||||||
version: '0.9.24',
|
version: '0.10.3',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>= 0.59.0',
|
meson_version: '>= 0.59.0',
|
||||||
default_options : [
|
default_options : [
|
||||||
@@ -92,7 +92,7 @@ libevdev = dependency('libevdev', required: get_option('libevdev'))
|
|||||||
libmpdclient = dependency('libmpdclient', required: get_option('mpd'))
|
libmpdclient = dependency('libmpdclient', required: get_option('mpd'))
|
||||||
xkbregistry = dependency('xkbregistry')
|
xkbregistry = dependency('xkbregistry')
|
||||||
libjack = dependency('jack', required: get_option('jack'))
|
libjack = dependency('jack', required: get_option('jack'))
|
||||||
libwireplumber = dependency('wireplumber-0.4', required: get_option('wireplumber'))
|
libwireplumber = dependency('wireplumber-0.5', required: get_option('wireplumber'))
|
||||||
|
|
||||||
libsndio = compiler.find_library('sndio', required: get_option('sndio'))
|
libsndio = compiler.find_library('sndio', required: get_option('sndio'))
|
||||||
if libsndio.found()
|
if libsndio.found()
|
||||||
@@ -192,6 +192,7 @@ man_files = files(
|
|||||||
'man/waybar-idle-inhibitor.5.scd',
|
'man/waybar-idle-inhibitor.5.scd',
|
||||||
'man/waybar-image.5.scd',
|
'man/waybar-image.5.scd',
|
||||||
'man/waybar-states.5.scd',
|
'man/waybar-states.5.scd',
|
||||||
|
'man/waybar-menu.5.scd',
|
||||||
'man/waybar-temperature.5.scd',
|
'man/waybar-temperature.5.scd',
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -212,6 +213,7 @@ if is_linux
|
|||||||
'src/modules/cpu_usage/linux.cpp',
|
'src/modules/cpu_usage/linux.cpp',
|
||||||
'src/modules/memory/common.cpp',
|
'src/modules/memory/common.cpp',
|
||||||
'src/modules/memory/linux.cpp',
|
'src/modules/memory/linux.cpp',
|
||||||
|
'src/modules/power_profiles_daemon.cpp',
|
||||||
'src/modules/systemd_failed_units.cpp',
|
'src/modules/systemd_failed_units.cpp',
|
||||||
)
|
)
|
||||||
man_files += files(
|
man_files += files(
|
||||||
@@ -221,6 +223,7 @@ if is_linux
|
|||||||
'man/waybar-cpu.5.scd',
|
'man/waybar-cpu.5.scd',
|
||||||
'man/waybar-memory.5.scd',
|
'man/waybar-memory.5.scd',
|
||||||
'man/waybar-systemd-failed-units.5.scd',
|
'man/waybar-systemd-failed-units.5.scd',
|
||||||
|
'man/waybar-power-profiles-daemon.5.scd',
|
||||||
)
|
)
|
||||||
elif is_dragonfly or is_freebsd or is_netbsd or is_openbsd
|
elif is_dragonfly or is_freebsd or is_netbsd or is_openbsd
|
||||||
add_project_arguments('-DHAVE_CPU_BSD', language: 'cpp')
|
add_project_arguments('-DHAVE_CPU_BSD', language: 'cpp')
|
||||||
@@ -291,7 +294,9 @@ endif
|
|||||||
if true
|
if true
|
||||||
add_project_arguments('-DHAVE_DWL', language: 'cpp')
|
add_project_arguments('-DHAVE_DWL', language: 'cpp')
|
||||||
src_files += files('src/modules/dwl/tags.cpp')
|
src_files += files('src/modules/dwl/tags.cpp')
|
||||||
|
src_files += files('src/modules/dwl/window.cpp')
|
||||||
man_files += files('man/waybar-dwl-tags.5.scd')
|
man_files += files('man/waybar-dwl-tags.5.scd')
|
||||||
|
man_files += files('man/waybar-dwl-window.5.scd')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if true
|
if true
|
||||||
@@ -301,7 +306,9 @@ if true
|
|||||||
'src/modules/hyprland/language.cpp',
|
'src/modules/hyprland/language.cpp',
|
||||||
'src/modules/hyprland/submap.cpp',
|
'src/modules/hyprland/submap.cpp',
|
||||||
'src/modules/hyprland/window.cpp',
|
'src/modules/hyprland/window.cpp',
|
||||||
|
'src/modules/hyprland/workspace.cpp',
|
||||||
'src/modules/hyprland/workspaces.cpp',
|
'src/modules/hyprland/workspaces.cpp',
|
||||||
|
'src/modules/hyprland/windowcreationpayload.cpp',
|
||||||
)
|
)
|
||||||
man_files += files(
|
man_files += files(
|
||||||
'man/waybar-hyprland-language.5.scd',
|
'man/waybar-hyprland-language.5.scd',
|
||||||
@@ -331,10 +338,7 @@ endif
|
|||||||
|
|
||||||
if (upower_glib.found() and not get_option('logind').disabled())
|
if (upower_glib.found() and not get_option('logind').disabled())
|
||||||
add_project_arguments('-DHAVE_UPOWER', language: 'cpp')
|
add_project_arguments('-DHAVE_UPOWER', language: 'cpp')
|
||||||
src_files += files(
|
src_files += files('src/modules/upower.cpp')
|
||||||
'src/modules/upower/upower.cpp',
|
|
||||||
'src/modules/upower/upower_tooltip.cpp',
|
|
||||||
)
|
|
||||||
man_files += files('man/waybar-upower.5.scd')
|
man_files += files('man/waybar-upower.5.scd')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -344,7 +348,8 @@ if pipewire.found()
|
|||||||
src_files += files(
|
src_files += files(
|
||||||
'src/modules/privacy/privacy.cpp',
|
'src/modules/privacy/privacy.cpp',
|
||||||
'src/modules/privacy/privacy_item.cpp',
|
'src/modules/privacy/privacy_item.cpp',
|
||||||
'src/util/pipewire_backend.cpp',
|
'src/util/pipewire/pipewire_backend.cpp',
|
||||||
|
'src/util/pipewire/privacy_node_info.cpp',
|
||||||
)
|
)
|
||||||
man_files += files('man/waybar-privacy.5.scd')
|
man_files += files('man/waybar-privacy.5.scd')
|
||||||
endif
|
endif
|
||||||
@@ -462,7 +467,7 @@ if get_option('experimental')
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
cava = dependency('cava',
|
cava = dependency('cava',
|
||||||
version : '>=0.10.1',
|
version : '>=0.10.2',
|
||||||
required: get_option('cava'),
|
required: get_option('cava'),
|
||||||
fallback : ['cava', 'cava_dep'],
|
fallback : ['cava', 'cava_dep'],
|
||||||
not_found_message: 'cava is not found. Building waybar without cava')
|
not_found_message: 'cava is not found. Building waybar without cava')
|
||||||
@@ -518,8 +523,8 @@ executable(
|
|||||||
)
|
)
|
||||||
|
|
||||||
install_data(
|
install_data(
|
||||||
'./resources/config',
|
'resources/config.jsonc',
|
||||||
'./resources/style.css',
|
'resources/style.css',
|
||||||
install_dir: sysconfdir / 'xdg/waybar'
|
install_dir: sysconfdir / 'xdg/waybar'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -534,6 +539,14 @@ if scdoc.found()
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
man_files += configure_file(
|
||||||
|
input: 'man/waybar-styles.5.scd.in',
|
||||||
|
output: 'waybar-styles.5.scd',
|
||||||
|
configuration: {
|
||||||
|
'sysconfdir': prefix / sysconfdir
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
fs = import('fs')
|
fs = import('fs')
|
||||||
mandir = get_option('mandir')
|
mandir = get_option('mandir')
|
||||||
foreach file : man_files
|
foreach file : man_files
|
||||||
@@ -577,4 +590,3 @@ if clangtidy.found()
|
|||||||
'-p', meson.project_build_root()
|
'-p', meson.project_build_root()
|
||||||
] + src_files)
|
] + src_files)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -5,12 +5,12 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
libcava = rec {
|
libcava = rec {
|
||||||
version = "0.10.1";
|
version = "0.10.2";
|
||||||
src = pkgs.fetchFromGitHub {
|
src = pkgs.fetchFromGitHub {
|
||||||
owner = "LukashonakV";
|
owner = "LukashonakV";
|
||||||
repo = "cava";
|
repo = "cava";
|
||||||
rev = version;
|
rev = version;
|
||||||
hash = "sha256-iIYKvpOWafPJB5XhDOSIW9Mb4I3A4pcgIIPQdQYEqUw=";
|
hash = "sha256-jU7RQV2txruu/nUUl0TzjK4nai7G38J1rcTjO7UXumY=";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
@@ -25,6 +25,10 @@ in
|
|||||||
|
|
||||||
mesonFlags = lib.remove "-Dgtk-layer-shell=enabled" oldAttrs.mesonFlags;
|
mesonFlags = lib.remove "-Dgtk-layer-shell=enabled" oldAttrs.mesonFlags;
|
||||||
|
|
||||||
|
buildInputs = (builtins.filter (p: p.pname != "wireplumber") oldAttrs.buildInputs) ++ [
|
||||||
|
pkgs.wireplumber
|
||||||
|
];
|
||||||
|
|
||||||
postUnpack = ''
|
postUnpack = ''
|
||||||
pushd "$sourceRoot"
|
pushd "$sourceRoot"
|
||||||
cp -R --no-preserve=mode,ownership ${libcava.src} subprojects/cava-${libcava.version}
|
cp -R --no-preserve=mode,ownership ${libcava.src} subprojects/cava-${libcava.version}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// -*- mode: jsonc -*-
|
||||||
{
|
{
|
||||||
// "layer": "top", // Waybar at top layer
|
// "layer": "top", // Waybar at top layer
|
||||||
// "position": "bottom", // Waybar position (top|bottom|left|right)
|
// "position": "bottom", // Waybar position (top|bottom|left|right)
|
||||||
@@ -5,9 +6,33 @@
|
|||||||
// "width": 1280, // Waybar width
|
// "width": 1280, // Waybar width
|
||||||
"spacing": 4, // Gaps between modules (4px)
|
"spacing": 4, // Gaps between modules (4px)
|
||||||
// Choose the order of the modules
|
// Choose the order of the modules
|
||||||
"modules-left": ["sway/workspaces", "sway/mode", "sway/scratchpad", "custom/media"],
|
"modules-left": [
|
||||||
"modules-center": ["sway/window"],
|
"sway/workspaces",
|
||||||
"modules-right": ["mpd", "idle_inhibitor", "pulseaudio", "network", "cpu", "memory", "temperature", "backlight", "keyboard-state", "sway/language", "battery", "battery#bat2", "clock", "tray"],
|
"sway/mode",
|
||||||
|
"sway/scratchpad",
|
||||||
|
"custom/media"
|
||||||
|
],
|
||||||
|
"modules-center": [
|
||||||
|
"sway/window"
|
||||||
|
],
|
||||||
|
"modules-right": [
|
||||||
|
"mpd",
|
||||||
|
"idle_inhibitor",
|
||||||
|
"pulseaudio",
|
||||||
|
"network",
|
||||||
|
"power-profiles-daemon",
|
||||||
|
"cpu",
|
||||||
|
"memory",
|
||||||
|
"temperature",
|
||||||
|
"backlight",
|
||||||
|
"keyboard-state",
|
||||||
|
"sway/language",
|
||||||
|
"battery",
|
||||||
|
"battery#bat2",
|
||||||
|
"clock",
|
||||||
|
"tray",
|
||||||
|
"custom/power"
|
||||||
|
],
|
||||||
// Modules configuration
|
// Modules configuration
|
||||||
// "sway/workspaces": {
|
// "sway/workspaces": {
|
||||||
// "disable-scroll": true,
|
// "disable-scroll": true,
|
||||||
@@ -49,7 +74,7 @@
|
|||||||
"format-disconnected": "Disconnected ",
|
"format-disconnected": "Disconnected ",
|
||||||
"format-stopped": "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ",
|
"format-stopped": "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ",
|
||||||
"unknown-tag": "N/A",
|
"unknown-tag": "N/A",
|
||||||
"interval": 2,
|
"interval": 5,
|
||||||
"consume-icons": {
|
"consume-icons": {
|
||||||
"on": " "
|
"on": " "
|
||||||
},
|
},
|
||||||
@@ -124,6 +149,17 @@
|
|||||||
"battery#bat2": {
|
"battery#bat2": {
|
||||||
"bat": "BAT2"
|
"bat": "BAT2"
|
||||||
},
|
},
|
||||||
|
"power-profiles-daemon": {
|
||||||
|
"format": "{icon}",
|
||||||
|
"tooltip-format": "Power profile: {profile}\nDriver: {driver}",
|
||||||
|
"tooltip": true,
|
||||||
|
"format-icons": {
|
||||||
|
"default": "",
|
||||||
|
"performance": "",
|
||||||
|
"balanced": "",
|
||||||
|
"power-saver": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"network": {
|
"network": {
|
||||||
// "interface": "wlp2*", // (Optional) To force the use of this interface
|
// "interface": "wlp2*", // (Optional) To force the use of this interface
|
||||||
"format-wifi": "{essid} ({signalStrength}%) ",
|
"format-wifi": "{essid} ({signalStrength}%) ",
|
||||||
@@ -163,6 +199,17 @@
|
|||||||
"escape": true,
|
"escape": true,
|
||||||
"exec": "$HOME/.config/waybar/mediaplayer.py 2> /dev/null" // Script in resources folder
|
"exec": "$HOME/.config/waybar/mediaplayer.py 2> /dev/null" // Script in resources folder
|
||||||
// "exec": "$HOME/.config/waybar/mediaplayer.py --player spotify 2> /dev/null" // Filter player based on name
|
// "exec": "$HOME/.config/waybar/mediaplayer.py --player spotify 2> /dev/null" // Filter player based on name
|
||||||
|
},
|
||||||
|
"custom/power": {
|
||||||
|
"format" : "⏻ ",
|
||||||
|
"tooltip": false,
|
||||||
|
"menu": "on-click",
|
||||||
|
"menu-file": "$HOME/.config/waybar/power_menu.xml", // Menu file in resources folder
|
||||||
|
"menu-actions": {
|
||||||
|
"shutdown": "shutdown",
|
||||||
|
"reboot": "reboot",
|
||||||
|
"suspend": "systemctl suspend",
|
||||||
|
"hibernate": "systemctl hibernate"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +113,7 @@ class PlayerManager:
|
|||||||
player_name = player.props.player_name
|
player_name = player.props.player_name
|
||||||
artist = player.get_artist()
|
artist = player.get_artist()
|
||||||
title = player.get_title()
|
title = player.get_title()
|
||||||
|
title = title.replace("&", "&")
|
||||||
|
|
||||||
track_info = ""
|
track_info = ""
|
||||||
if player_name == "spotify" and "mpris:trackid" in metadata.keys() and ":ad:" in player.props.metadata["mpris:trackid"]:
|
if player_name == "spotify" and "mpris:trackid" in metadata.keys() and ":ad:" in player.props.metadata["mpris:trackid"]:
|
||||||
@@ -136,6 +137,10 @@ class PlayerManager:
|
|||||||
|
|
||||||
def on_player_appeared(self, _, player):
|
def on_player_appeared(self, _, player):
|
||||||
logger.info(f"Player has appeared: {player.name}")
|
logger.info(f"Player has appeared: {player.name}")
|
||||||
|
if player.name in self.excluded_player:
|
||||||
|
logger.debug(
|
||||||
|
"New player appeared, but it's in exclude player list, skipping")
|
||||||
|
return
|
||||||
if player is not None and (self.selected_player is None or player.name == self.selected_player):
|
if player is not None and (self.selected_player is None or player.name == self.selected_player):
|
||||||
self.init_player(player)
|
self.init_player(player)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<object class="GtkMenu" id="menu">
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="suspend">
|
||||||
|
<property name="label">Suspend</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="hibernate">
|
||||||
|
<property name="label">Hibernate</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="shutdown">
|
||||||
|
<property name="label">Shutdown</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSeparatorMenuItem" id="delimiter1"/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="reboot">
|
||||||
|
<property name="label">Reboot</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
||||||
+26
-1
@@ -48,6 +48,11 @@ button:hover {
|
|||||||
box-shadow: inset 0 -3px #ffffff;
|
box-shadow: inset 0 -3px #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* you can set a style on hover for any module like this */
|
||||||
|
#pulseaudio:hover {
|
||||||
|
background-color: #a37800;
|
||||||
|
}
|
||||||
|
|
||||||
#workspaces button {
|
#workspaces button {
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
@@ -69,7 +74,7 @@ button:hover {
|
|||||||
|
|
||||||
#mode {
|
#mode {
|
||||||
background-color: #64727D;
|
background-color: #64727D;
|
||||||
border-bottom: 3px solid #ffffff;
|
box-shadow: inset 0 -3px #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#clock,
|
#clock,
|
||||||
@@ -87,6 +92,7 @@ button:hover {
|
|||||||
#mode,
|
#mode,
|
||||||
#idle_inhibitor,
|
#idle_inhibitor,
|
||||||
#scratchpad,
|
#scratchpad,
|
||||||
|
#power-profiles-daemon,
|
||||||
#mpd {
|
#mpd {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
@@ -139,6 +145,25 @@ button:hover {
|
|||||||
animation-direction: alternate;
|
animation-direction: alternate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#power-profiles-daemon {
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#power-profiles-daemon.performance {
|
||||||
|
background-color: #f53c3c;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#power-profiles-daemon.balanced {
|
||||||
|
background-color: #2980b9;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#power-profiles-daemon.power-saver {
|
||||||
|
background-color: #2ecc71;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
label:focus {
|
label:focus {
|
||||||
background-color: #000000;
|
background-color: #000000;
|
||||||
}
|
}
|
||||||
|
|||||||
+52
-16
@@ -24,18 +24,61 @@ AAppIconLabel::AAppIconLabel(const Json::Value& config, const std::string& name,
|
|||||||
image_.set_pixel_size(app_icon_size_);
|
image_.set_pixel_size(app_icon_size_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string toLowerCase(const std::string& input) {
|
||||||
|
std::string result = input;
|
||||||
|
std::transform(result.begin(), result.end(), result.begin(),
|
||||||
|
[](unsigned char c) { return std::tolower(c); });
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> getFileBySuffix(const std::string& dir, const std::string& suffix,
|
||||||
|
bool check_lower_case) {
|
||||||
|
if (!std::filesystem::exists(dir)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
for (const auto& entry : std::filesystem::recursive_directory_iterator(dir)) {
|
||||||
|
if (entry.is_regular_file()) {
|
||||||
|
std::string filename = entry.path().filename().string();
|
||||||
|
if (filename.size() < suffix.size()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((filename.compare(filename.size() - suffix.size(), suffix.size(), suffix) == 0) ||
|
||||||
|
(check_lower_case && filename.compare(filename.size() - suffix.size(), suffix.size(),
|
||||||
|
toLowerCase(suffix)) == 0)) {
|
||||||
|
return entry.path().string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> getFileBySuffix(const std::string& dir, const std::string& suffix) {
|
||||||
|
return getFileBySuffix(dir, suffix, false);
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::string> getDesktopFilePath(const std::string& app_identifier,
|
std::optional<std::string> getDesktopFilePath(const std::string& app_identifier,
|
||||||
const std::string& alternative_app_identifier) {
|
const std::string& alternative_app_identifier) {
|
||||||
|
if (app_identifier.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
const auto data_dirs = Glib::get_system_data_dirs();
|
const auto data_dirs = Glib::get_system_data_dirs();
|
||||||
for (const auto& data_dir : data_dirs) {
|
for (const auto& data_dir : data_dirs) {
|
||||||
const auto data_app_dir = data_dir + "applications/";
|
const auto data_app_dir = data_dir + "/applications/";
|
||||||
auto desktop_file_path = data_app_dir + app_identifier + ".desktop";
|
auto desktop_file_suffix = app_identifier + ".desktop";
|
||||||
if (std::filesystem::exists(desktop_file_path)) {
|
// searching for file by suffix catches cases like terminal emulator "foot" where class is
|
||||||
|
// "footclient" and desktop file is named "org.codeberg.dnkl.footclient.desktop"
|
||||||
|
auto desktop_file_path = getFileBySuffix(data_app_dir, desktop_file_suffix, true);
|
||||||
|
// "true" argument allows checking for lowercase - this catches cases where class name is
|
||||||
|
// "LibreWolf" and desktop file is named "librewolf.desktop"
|
||||||
|
if (desktop_file_path.has_value()) {
|
||||||
return desktop_file_path;
|
return desktop_file_path;
|
||||||
}
|
}
|
||||||
if (!alternative_app_identifier.empty()) {
|
if (!alternative_app_identifier.empty()) {
|
||||||
desktop_file_path = data_app_dir + alternative_app_identifier + ".desktop";
|
desktop_file_suffix = alternative_app_identifier + ".desktop";
|
||||||
if (std::filesystem::exists(desktop_file_path)) {
|
desktop_file_path = getFileBySuffix(data_app_dir, desktop_file_suffix, true);
|
||||||
|
if (desktop_file_path.has_value()) {
|
||||||
return desktop_file_path;
|
return desktop_file_path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,21 +96,14 @@ std::optional<Glib::ustring> getIconName(const std::string& app_identifier,
|
|||||||
return app_identifier;
|
return app_identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto app_identifier_desktop = app_identifier + "-desktop";
|
auto app_identifier_desktop = app_identifier + "-desktop";
|
||||||
if (DefaultGtkIconThemeWrapper::has_icon(app_identifier_desktop)) {
|
if (DefaultGtkIconThemeWrapper::has_icon(app_identifier_desktop)) {
|
||||||
return app_identifier_desktop;
|
return app_identifier_desktop;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto to_lower = [](const std::string& str) {
|
auto first_space = app_identifier.find_first_of(' ');
|
||||||
auto str_cpy = str;
|
|
||||||
std::transform(str_cpy.begin(), str_cpy.end(), str_cpy.begin(),
|
|
||||||
[](unsigned char c) { return std::tolower(c); });
|
|
||||||
return str;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto first_space = app_identifier.find_first_of(' ');
|
|
||||||
if (first_space != std::string::npos) {
|
if (first_space != std::string::npos) {
|
||||||
const auto first_word = to_lower(app_identifier.substr(0, first_space));
|
auto first_word = toLowerCase(app_identifier.substr(0, first_space));
|
||||||
if (DefaultGtkIconThemeWrapper::has_icon(first_word)) {
|
if (DefaultGtkIconThemeWrapper::has_icon(first_word)) {
|
||||||
return first_word;
|
return first_word;
|
||||||
}
|
}
|
||||||
@@ -75,7 +111,7 @@ std::optional<Glib::ustring> getIconName(const std::string& app_identifier,
|
|||||||
|
|
||||||
const auto first_dash = app_identifier.find_first_of('-');
|
const auto first_dash = app_identifier.find_first_of('-');
|
||||||
if (first_dash != std::string::npos) {
|
if (first_dash != std::string::npos) {
|
||||||
const auto first_word = to_lower(app_identifier.substr(0, first_dash));
|
auto first_word = toLowerCase(app_identifier.substr(0, first_dash));
|
||||||
if (DefaultGtkIconThemeWrapper::has_icon(first_word)) {
|
if (DefaultGtkIconThemeWrapper::has_icon(first_word)) {
|
||||||
return first_word;
|
return first_word;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-1
@@ -9,10 +9,23 @@ AIconLabel::AIconLabel(const Json::Value &config, const std::string &name, const
|
|||||||
bool enable_click, bool enable_scroll)
|
bool enable_click, bool enable_scroll)
|
||||||
: ALabel(config, name, id, format, interval, ellipsize, enable_click, enable_scroll) {
|
: ALabel(config, name, id, format, interval, ellipsize, enable_click, enable_scroll) {
|
||||||
event_box_.remove();
|
event_box_.remove();
|
||||||
|
label_.unset_name();
|
||||||
|
label_.get_style_context()->remove_class(MODULE_CLASS);
|
||||||
|
box_.get_style_context()->add_class(MODULE_CLASS);
|
||||||
|
if (!id.empty()) {
|
||||||
|
label_.get_style_context()->remove_class(id);
|
||||||
|
box_.get_style_context()->add_class(id);
|
||||||
|
}
|
||||||
|
|
||||||
box_.set_orientation(Gtk::Orientation::ORIENTATION_HORIZONTAL);
|
box_.set_orientation(Gtk::Orientation::ORIENTATION_HORIZONTAL);
|
||||||
box_.set_spacing(8);
|
box_.set_name(name);
|
||||||
|
|
||||||
|
int spacing = config_["icon-spacing"].isInt() ? config_["icon-spacing"].asInt() : 8;
|
||||||
|
box_.set_spacing(spacing);
|
||||||
|
|
||||||
box_.add(image_);
|
box_.add(image_);
|
||||||
box_.add(label_);
|
box_.add(label_);
|
||||||
|
|
||||||
event_box_.add(box_);
|
event_box_.add(box_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+63
-3
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
#include <util/command.hpp>
|
#include <util/command.hpp>
|
||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
@@ -9,7 +11,9 @@ namespace waybar {
|
|||||||
ALabel::ALabel(const Json::Value& config, const std::string& name, const std::string& id,
|
ALabel::ALabel(const Json::Value& config, const std::string& name, const std::string& id,
|
||||||
const std::string& format, uint16_t interval, bool ellipsize, bool enable_click,
|
const std::string& format, uint16_t interval, bool ellipsize, bool enable_click,
|
||||||
bool enable_scroll)
|
bool enable_scroll)
|
||||||
: AModule(config, name, id, config["format-alt"].isString() || enable_click, enable_scroll),
|
: AModule(config, name, id,
|
||||||
|
config["format-alt"].isString() || config["menu"].isString() || enable_click,
|
||||||
|
enable_scroll),
|
||||||
format_(config_["format"].isString() ? config_["format"].asString() : format),
|
format_(config_["format"].isString() ? config_["format"].asString() : format),
|
||||||
interval_(config_["interval"] == "once"
|
interval_(config_["interval"] == "once"
|
||||||
? std::chrono::seconds::max()
|
? std::chrono::seconds::max()
|
||||||
@@ -50,6 +54,58 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
|
|||||||
label_.set_xalign(align);
|
label_.set_xalign(align);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a GTKMenu is requested in the config
|
||||||
|
if (config_["menu"].isString()) {
|
||||||
|
// Create the GTKMenu widget
|
||||||
|
try {
|
||||||
|
// Check that the file exists
|
||||||
|
std::string menuFile = config_["menu-file"].asString();
|
||||||
|
// Read the menu descriptor file
|
||||||
|
std::ifstream file(menuFile);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
throw std::runtime_error("Failed to open file: " + menuFile);
|
||||||
|
}
|
||||||
|
std::stringstream fileContent;
|
||||||
|
fileContent << file.rdbuf();
|
||||||
|
GtkBuilder* builder = gtk_builder_new();
|
||||||
|
|
||||||
|
// Make the GtkBuilder and check for errors in his parsing
|
||||||
|
if (gtk_builder_add_from_string(builder, fileContent.str().c_str(), -1, nullptr) == 0U) {
|
||||||
|
throw std::runtime_error("Error found in the file " + menuFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu_ = gtk_builder_get_object(builder, "menu");
|
||||||
|
if (menu_ == nullptr) {
|
||||||
|
throw std::runtime_error("Failed to get 'menu' object from GtkBuilder");
|
||||||
|
}
|
||||||
|
submenus_ = std::map<std::string, GtkMenuItem*>();
|
||||||
|
menuActionsMap_ = std::map<std::string, std::string>();
|
||||||
|
|
||||||
|
// Linking actions to the GTKMenu based on
|
||||||
|
for (Json::Value::const_iterator it = config_["menu-actions"].begin();
|
||||||
|
it != config_["menu-actions"].end(); ++it) {
|
||||||
|
std::string key = it.key().asString();
|
||||||
|
submenus_[key] = GTK_MENU_ITEM(gtk_builder_get_object(builder, key.c_str()));
|
||||||
|
menuActionsMap_[key] = it->asString();
|
||||||
|
g_signal_connect(submenus_[key], "activate", G_CALLBACK(handleGtkMenuEvent),
|
||||||
|
(gpointer)menuActionsMap_[key].c_str());
|
||||||
|
}
|
||||||
|
} catch (std::runtime_error& e) {
|
||||||
|
spdlog::warn("Error while creating the menu : {}. Menu popup not activated.", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config_["justify"].isString()) {
|
||||||
|
auto justify_str = config_["justify"].asString();
|
||||||
|
if (justify_str == "left") {
|
||||||
|
label_.set_justify(Gtk::Justification::JUSTIFY_LEFT);
|
||||||
|
} else if (justify_str == "right") {
|
||||||
|
label_.set_justify(Gtk::Justification::JUSTIFY_RIGHT);
|
||||||
|
} else if (justify_str == "center") {
|
||||||
|
label_.set_justify(Gtk::Justification::JUSTIFY_CENTER);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ALabel::update() -> void { AModule::update(); }
|
auto ALabel::update() -> void { AModule::update(); }
|
||||||
@@ -65,7 +121,7 @@ std::string ALabel::getIcon(uint16_t percentage, const std::string& alt, uint16_
|
|||||||
}
|
}
|
||||||
if (format_icons.isArray()) {
|
if (format_icons.isArray()) {
|
||||||
auto size = format_icons.size();
|
auto size = format_icons.size();
|
||||||
if (size) {
|
if (size != 0U) {
|
||||||
auto idx = std::clamp(percentage / ((max == 0 ? 100 : max) / size), 0U, size - 1);
|
auto idx = std::clamp(percentage / ((max == 0 ? 100 : max) / size), 0U, size - 1);
|
||||||
format_icons = format_icons[idx];
|
format_icons = format_icons[idx];
|
||||||
}
|
}
|
||||||
@@ -91,7 +147,7 @@ std::string ALabel::getIcon(uint16_t percentage, const std::vector<std::string>&
|
|||||||
}
|
}
|
||||||
if (format_icons.isArray()) {
|
if (format_icons.isArray()) {
|
||||||
auto size = format_icons.size();
|
auto size = format_icons.size();
|
||||||
if (size) {
|
if (size != 0U) {
|
||||||
auto idx = std::clamp(percentage / ((max == 0 ? 100 : max) / size), 0U, size - 1);
|
auto idx = std::clamp(percentage / ((max == 0 ? 100 : max) / size), 0U, size - 1);
|
||||||
format_icons = format_icons[idx];
|
format_icons = format_icons[idx];
|
||||||
}
|
}
|
||||||
@@ -114,6 +170,10 @@ bool waybar::ALabel::handleToggle(GdkEventButton* const& e) {
|
|||||||
return AModule::handleToggle(e);
|
return AModule::handleToggle(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ALabel::handleGtkMenuEvent(GtkMenuItem* menuitem, gpointer data) {
|
||||||
|
waybar::util::command::res res = waybar::util::command::exec((char*)data, "GtkMenu");
|
||||||
|
}
|
||||||
|
|
||||||
std::string ALabel::getState(uint8_t value, bool lesser) {
|
std::string ALabel::getState(uint8_t value, bool lesser) {
|
||||||
if (!config_["states"].isObject()) {
|
if (!config_["states"].isObject()) {
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
+62
-10
@@ -8,37 +8,44 @@ namespace waybar {
|
|||||||
|
|
||||||
AModule::AModule(const Json::Value& config, const std::string& name, const std::string& id,
|
AModule::AModule(const Json::Value& config, const std::string& name, const std::string& id,
|
||||||
bool enable_click, bool enable_scroll)
|
bool enable_click, bool enable_scroll)
|
||||||
: name_(std::move(name)),
|
: name_(name),
|
||||||
config_(std::move(config)),
|
config_(config),
|
||||||
isTooltip{config_["tooltip"].isBool() ? config_["tooltip"].asBool() : true},
|
isTooltip{config_["tooltip"].isBool() ? config_["tooltip"].asBool() : true},
|
||||||
distance_scrolled_y_(0.0),
|
distance_scrolled_y_(0.0),
|
||||||
distance_scrolled_x_(0.0) {
|
distance_scrolled_x_(0.0) {
|
||||||
// Configure module action Map
|
// Configure module action Map
|
||||||
const Json::Value actions{config_["actions"]};
|
const Json::Value actions{config_["actions"]};
|
||||||
|
|
||||||
for (Json::Value::const_iterator it = actions.begin(); it != actions.end(); ++it) {
|
for (Json::Value::const_iterator it = actions.begin(); it != actions.end(); ++it) {
|
||||||
if (it.key().isString() && it->isString())
|
if (it.key().isString() && it->isString())
|
||||||
if (eventActionMap_.count(it.key().asString()) == 0) {
|
if (!eventActionMap_.contains(it.key().asString())) {
|
||||||
eventActionMap_.insert({it.key().asString(), it->asString()});
|
eventActionMap_.insert({it.key().asString(), it->asString()});
|
||||||
enable_click = true;
|
enable_click = true;
|
||||||
enable_scroll = true;
|
enable_scroll = true;
|
||||||
} else
|
} else
|
||||||
spdlog::warn("Dublicate action is ignored: {0}", it.key().asString());
|
spdlog::warn("Duplicate action is ignored: {0}", it.key().asString());
|
||||||
else
|
else
|
||||||
spdlog::warn("Wrong actions section configuration. See config by index: {}", it.index());
|
spdlog::warn("Wrong actions section configuration. See config by index: {}", it.index());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event_box_.signal_enter_notify_event().connect(sigc::mem_fun(*this, &AModule::handleMouseEnter));
|
||||||
|
event_box_.signal_leave_notify_event().connect(sigc::mem_fun(*this, &AModule::handleMouseLeave));
|
||||||
|
|
||||||
// configure events' user commands
|
// configure events' user commands
|
||||||
// hasUserEvent is true if any element from eventMap_ is satisfying the condition in the lambda
|
// hasUserEvents is true if any element from eventMap_ is satisfying the condition in the lambda
|
||||||
bool hasUserEvent =
|
bool hasUserEvents =
|
||||||
std::find_if(eventMap_.cbegin(), eventMap_.cend(), [&config](const auto& eventEntry) {
|
std::find_if(eventMap_.cbegin(), eventMap_.cend(), [&config](const auto& eventEntry) {
|
||||||
// True if there is any non-release type event
|
// True if there is any non-release type event
|
||||||
return eventEntry.first.second != GdkEventType::GDK_BUTTON_RELEASE &&
|
return eventEntry.first.second != GdkEventType::GDK_BUTTON_RELEASE &&
|
||||||
config[eventEntry.second].isString();
|
config[eventEntry.second].isString();
|
||||||
}) != eventMap_.cend();
|
}) != eventMap_.cend();
|
||||||
|
|
||||||
if (enable_click || hasUserEvent) {
|
if (enable_click || hasUserEvents) {
|
||||||
|
hasUserEvents_ = true;
|
||||||
event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
|
event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
|
||||||
event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &AModule::handleToggle));
|
event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &AModule::handleToggle));
|
||||||
|
} else {
|
||||||
|
hasUserEvents_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasReleaseEvent =
|
bool hasReleaseEvent =
|
||||||
@@ -51,7 +58,9 @@ AModule::AModule(const Json::Value& config, const std::string& name, const std::
|
|||||||
event_box_.add_events(Gdk::BUTTON_RELEASE_MASK);
|
event_box_.add_events(Gdk::BUTTON_RELEASE_MASK);
|
||||||
event_box_.signal_button_release_event().connect(sigc::mem_fun(*this, &AModule::handleRelease));
|
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) {
|
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString() ||
|
||||||
|
config_["on-scroll-left"].isString() || config_["on-scroll-right"].isString() ||
|
||||||
|
enable_scroll) {
|
||||||
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
||||||
event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &AModule::handleScroll));
|
event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &AModule::handleScroll));
|
||||||
}
|
}
|
||||||
@@ -81,6 +90,34 @@ auto AModule::doAction(const std::string& name) -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AModule::setCursor(Gdk::CursorType const& c) {
|
||||||
|
auto cursor = Gdk::Cursor::create(c);
|
||||||
|
auto gdk_window = event_box_.get_window();
|
||||||
|
gdk_window->set_cursor(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AModule::handleMouseEnter(GdkEventCrossing* const& e) {
|
||||||
|
if (auto* module = event_box_.get_child(); module != nullptr) {
|
||||||
|
module->set_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasUserEvents_) {
|
||||||
|
setCursor(Gdk::HAND2);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AModule::handleMouseLeave(GdkEventCrossing* const& e) {
|
||||||
|
if (auto* module = event_box_.get_child(); module != nullptr) {
|
||||||
|
module->unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasUserEvents_) {
|
||||||
|
setCursor(Gdk::ARROW);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool AModule::handleToggle(GdkEventButton* const& e) { return handleUserEvent(e); }
|
bool AModule::handleToggle(GdkEventButton* const& e) { return handleUserEvent(e); }
|
||||||
|
|
||||||
bool AModule::handleRelease(GdkEventButton* const& e) { return handleUserEvent(e); }
|
bool AModule::handleRelease(GdkEventButton* const& e) { return handleUserEvent(e); }
|
||||||
@@ -89,12 +126,23 @@ bool AModule::handleUserEvent(GdkEventButton* const& e) {
|
|||||||
std::string format{};
|
std::string format{};
|
||||||
const std::map<std::pair<uint, GdkEventType>, std::string>::const_iterator& rec{
|
const std::map<std::pair<uint, GdkEventType>, std::string>::const_iterator& rec{
|
||||||
eventMap_.find(std::pair(e->button, e->type))};
|
eventMap_.find(std::pair(e->button, e->type))};
|
||||||
|
|
||||||
if (rec != eventMap_.cend()) {
|
if (rec != eventMap_.cend()) {
|
||||||
// First call module actions
|
// First call module actions
|
||||||
this->AModule::doAction(rec->second);
|
this->AModule::doAction(rec->second);
|
||||||
|
|
||||||
format = rec->second;
|
format = rec->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that a menu has been configured
|
||||||
|
if (config_["menu"].isString()) {
|
||||||
|
// Check if the event is the one specified for the "menu" option
|
||||||
|
if (rec->second == config_["menu"].asString()) {
|
||||||
|
// Popup the menu
|
||||||
|
gtk_widget_show_all(GTK_WIDGET(menu_));
|
||||||
|
gtk_menu_popup_at_pointer(GTK_MENU(menu_), reinterpret_cast<GdkEvent*>(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
// Second call user scripts
|
// Second call user scripts
|
||||||
if (!format.empty()) {
|
if (!format.empty()) {
|
||||||
if (config_[format].isString())
|
if (config_[format].isString())
|
||||||
@@ -116,7 +164,7 @@ AModule::SCROLL_DIR AModule::getScrollDir(GdkEventScroll* e) {
|
|||||||
|
|
||||||
// ignore reverse-scrolling if event comes from a mouse wheel
|
// ignore reverse-scrolling if event comes from a mouse wheel
|
||||||
GdkDevice* device = gdk_event_get_source_device((GdkEvent*)e);
|
GdkDevice* device = gdk_event_get_source_device((GdkEvent*)e);
|
||||||
if (device != NULL && gdk_device_get_source(device) == GDK_SOURCE_MOUSE) {
|
if (device != nullptr && gdk_device_get_source(device) == GDK_SOURCE_MOUSE) {
|
||||||
reverse = reverse_mouse;
|
reverse = reverse_mouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,6 +227,10 @@ bool AModule::handleScroll(GdkEventScroll* e) {
|
|||||||
eventName = "on-scroll-up";
|
eventName = "on-scroll-up";
|
||||||
else if (dir == SCROLL_DIR::DOWN)
|
else if (dir == SCROLL_DIR::DOWN)
|
||||||
eventName = "on-scroll-down";
|
eventName = "on-scroll-down";
|
||||||
|
else if (dir == SCROLL_DIR::LEFT)
|
||||||
|
eventName = "on-scroll-left";
|
||||||
|
else if (dir == SCROLL_DIR::RIGHT)
|
||||||
|
eventName = "on-scroll-right";
|
||||||
|
|
||||||
// First call module actions
|
// First call module actions
|
||||||
this->AModule::doAction(eventName);
|
this->AModule::doAction(eventName);
|
||||||
@@ -190,7 +242,7 @@ bool AModule::handleScroll(GdkEventScroll* e) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AModule::tooltipEnabled() { return isTooltip; }
|
bool AModule::tooltipEnabled() const { return isTooltip; }
|
||||||
|
|
||||||
AModule::operator Gtk::Widget&() { return event_box_; }
|
AModule::operator Gtk::Widget&() { return event_box_; }
|
||||||
|
|
||||||
|
|||||||
+31
-22
@@ -43,7 +43,7 @@ const Bar::bar_mode_map Bar::PRESET_MODES = { //
|
|||||||
.visible = true}},
|
.visible = true}},
|
||||||
{"invisible",
|
{"invisible",
|
||||||
{//
|
{//
|
||||||
.layer = bar_layer::BOTTOM,
|
.layer = std::nullopt,
|
||||||
.exclusive = false,
|
.exclusive = false,
|
||||||
.passthrough = true,
|
.passthrough = true,
|
||||||
.visible = false}},
|
.visible = false}},
|
||||||
@@ -59,7 +59,7 @@ const std::string Bar::MODE_INVISIBLE = "invisible";
|
|||||||
const std::string_view DEFAULT_BAR_ID = "bar-0";
|
const std::string_view DEFAULT_BAR_ID = "bar-0";
|
||||||
|
|
||||||
/* Deserializer for enum bar_layer */
|
/* Deserializer for enum bar_layer */
|
||||||
void from_json(const Json::Value& j, bar_layer& l) {
|
void from_json(const Json::Value& j, std::optional<bar_layer>& l) {
|
||||||
if (j == "bottom") {
|
if (j == "bottom") {
|
||||||
l = bar_layer::BOTTOM;
|
l = bar_layer::BOTTOM;
|
||||||
} else if (j == "top") {
|
} else if (j == "top") {
|
||||||
@@ -72,16 +72,16 @@ void from_json(const Json::Value& j, bar_layer& l) {
|
|||||||
/* Deserializer for struct bar_mode */
|
/* Deserializer for struct bar_mode */
|
||||||
void from_json(const Json::Value& j, bar_mode& m) {
|
void from_json(const Json::Value& j, bar_mode& m) {
|
||||||
if (j.isObject()) {
|
if (j.isObject()) {
|
||||||
if (auto v = j["layer"]; v.isString()) {
|
if (const auto& v = j["layer"]; v.isString()) {
|
||||||
from_json(v, m.layer);
|
from_json(v, m.layer);
|
||||||
}
|
}
|
||||||
if (auto v = j["exclusive"]; v.isBool()) {
|
if (const auto& v = j["exclusive"]; v.isBool()) {
|
||||||
m.exclusive = v.asBool();
|
m.exclusive = v.asBool();
|
||||||
}
|
}
|
||||||
if (auto v = j["passthrough"]; v.isBool()) {
|
if (const auto& v = j["passthrough"]; v.isBool()) {
|
||||||
m.passthrough = v.asBool();
|
m.passthrough = v.asBool();
|
||||||
}
|
}
|
||||||
if (auto v = j["visible"]; v.isBool()) {
|
if (const auto& v = j["visible"]; v.isBool()) {
|
||||||
m.visible = v.asBool();
|
m.visible = v.asBool();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@ Glib::ustring to_string(Gtk::PositionType pos) {
|
|||||||
* Assumes that all the values in the object are deserializable to the same type.
|
* Assumes that all the values in the object are deserializable to the same type.
|
||||||
*/
|
*/
|
||||||
template <typename Key, typename Value,
|
template <typename Key, typename Value,
|
||||||
typename = std::enable_if_t<std::is_convertible<std::string, Key>::value>>
|
typename = std::enable_if_t<std::is_convertible_v<std::string, Key>>>
|
||||||
void from_json(const Json::Value& j, std::map<Key, Value>& m) {
|
void from_json(const Json::Value& j, std::map<Key, Value>& m) {
|
||||||
if (j.isObject()) {
|
if (j.isObject()) {
|
||||||
for (auto it = j.begin(); it != j.end(); ++it) {
|
for (auto it = j.begin(); it != j.end(); ++it) {
|
||||||
@@ -316,13 +316,13 @@ void waybar::Bar::setMode(const std::string& mode) {
|
|||||||
void waybar::Bar::setMode(const struct bar_mode& mode) {
|
void waybar::Bar::setMode(const struct bar_mode& mode) {
|
||||||
auto* gtk_window = window.gobj();
|
auto* gtk_window = window.gobj();
|
||||||
|
|
||||||
auto layer = GTK_LAYER_SHELL_LAYER_BOTTOM;
|
if (mode.layer == bar_layer::BOTTOM) {
|
||||||
if (mode.layer == bar_layer::TOP) {
|
gtk_layer_set_layer(gtk_window, GTK_LAYER_SHELL_LAYER_BOTTOM);
|
||||||
layer = GTK_LAYER_SHELL_LAYER_TOP;
|
} else if (mode.layer == bar_layer::TOP) {
|
||||||
|
gtk_layer_set_layer(gtk_window, GTK_LAYER_SHELL_LAYER_TOP);
|
||||||
} else if (mode.layer == bar_layer::OVERLAY) {
|
} else if (mode.layer == bar_layer::OVERLAY) {
|
||||||
layer = GTK_LAYER_SHELL_LAYER_OVERLAY;
|
gtk_layer_set_layer(gtk_window, GTK_LAYER_SHELL_LAYER_OVERLAY);
|
||||||
}
|
}
|
||||||
gtk_layer_set_layer(gtk_window, layer);
|
|
||||||
|
|
||||||
if (mode.exclusive) {
|
if (mode.exclusive) {
|
||||||
gtk_layer_auto_exclusive_zone_enable(gtk_window);
|
gtk_layer_auto_exclusive_zone_enable(gtk_window);
|
||||||
@@ -393,19 +393,18 @@ void waybar::Bar::setPosition(Gtk::PositionType position) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Bar::onMap(GdkEventAny*) {
|
void waybar::Bar::onMap(GdkEventAny* /*unused*/) {
|
||||||
/*
|
/*
|
||||||
* Obtain a pointer to the custom layer surface for modules that require it (idle_inhibitor).
|
* Obtain a pointer to the custom layer surface for modules that require it (idle_inhibitor).
|
||||||
*/
|
*/
|
||||||
auto gdk_window = window.get_window()->gobj();
|
auto* gdk_window = window.get_window()->gobj();
|
||||||
surface = gdk_wayland_window_get_wl_surface(gdk_window);
|
surface = gdk_wayland_window_get_wl_surface(gdk_window);
|
||||||
configureGlobalOffset(gdk_window_get_width(gdk_window), gdk_window_get_height(gdk_window));
|
configureGlobalOffset(gdk_window_get_width(gdk_window), gdk_window_get_height(gdk_window));
|
||||||
|
|
||||||
setPassThrough(passthrough_);
|
setPassThrough(passthrough_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Bar::setVisible(bool value) {
|
void waybar::Bar::setVisible(bool visible) {
|
||||||
visible = value;
|
|
||||||
if (auto mode = config.get("mode", {}); mode.isString()) {
|
if (auto mode = config.get("mode", {}); mode.isString()) {
|
||||||
setMode(visible ? config["mode"].asString() : MODE_INVISIBLE);
|
setMode(visible ? config["mode"].asString() : MODE_INVISIBLE);
|
||||||
} else {
|
} else {
|
||||||
@@ -449,7 +448,17 @@ void waybar::Bar::setupAltFormatKeyForModuleList(const char* module_list_name) {
|
|||||||
Json::Value& modules = config[module_list_name];
|
Json::Value& modules = config[module_list_name];
|
||||||
for (const Json::Value& module_name : modules) {
|
for (const Json::Value& module_name : modules) {
|
||||||
if (module_name.isString()) {
|
if (module_name.isString()) {
|
||||||
setupAltFormatKeyForModule(module_name.asString());
|
auto ref = module_name.asString();
|
||||||
|
if (ref.compare(0, 6, "group/") == 0 && ref.size() > 6) {
|
||||||
|
Json::Value& group_modules = config[ref]["modules"];
|
||||||
|
for (const Json::Value& module_name : group_modules) {
|
||||||
|
if (module_name.isString()) {
|
||||||
|
setupAltFormatKeyForModule(module_name.asString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setupAltFormatKeyForModule(ref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,7 +472,7 @@ void waybar::Bar::handleSignal(int signal) {
|
|||||||
|
|
||||||
void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
||||||
waybar::Group* group = nullptr) {
|
waybar::Group* group = nullptr) {
|
||||||
auto module_list = group ? config[pos]["modules"] : config[pos];
|
auto module_list = group != nullptr ? config[pos]["modules"] : config[pos];
|
||||||
if (module_list.isArray()) {
|
if (module_list.isArray()) {
|
||||||
for (const auto& name : module_list) {
|
for (const auto& name : module_list) {
|
||||||
try {
|
try {
|
||||||
@@ -475,10 +484,10 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
|||||||
auto id_name = ref.substr(6, hash_pos - 6);
|
auto id_name = ref.substr(6, hash_pos - 6);
|
||||||
auto class_name = hash_pos != std::string::npos ? ref.substr(hash_pos + 1) : "";
|
auto class_name = hash_pos != std::string::npos ? ref.substr(hash_pos + 1) : "";
|
||||||
|
|
||||||
auto vertical = (group ? group->getBox().get_orientation() : box_.get_orientation()) ==
|
auto vertical = (group != nullptr ? group->getBox().get_orientation()
|
||||||
Gtk::ORIENTATION_VERTICAL;
|
: box_.get_orientation()) == Gtk::ORIENTATION_VERTICAL;
|
||||||
|
|
||||||
auto group_module = new waybar::Group(id_name, class_name, config[ref], vertical);
|
auto* group_module = new waybar::Group(id_name, class_name, config[ref], vertical);
|
||||||
getModules(factory, ref, group_module);
|
getModules(factory, ref, group_module);
|
||||||
module = group_module;
|
module = group_module;
|
||||||
} else {
|
} else {
|
||||||
@@ -487,7 +496,7 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
|||||||
|
|
||||||
std::shared_ptr<AModule> module_sp(module);
|
std::shared_ptr<AModule> module_sp(module);
|
||||||
modules_all_.emplace_back(module_sp);
|
modules_all_.emplace_back(module_sp);
|
||||||
if (group) {
|
if (group != nullptr) {
|
||||||
group->addWidget(*module);
|
group->addWidget(*module);
|
||||||
} else {
|
} else {
|
||||||
if (pos == "modules-left") {
|
if (pos == "modules-left") {
|
||||||
|
|||||||
+17
-16
@@ -4,6 +4,7 @@
|
|||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "gtkmm/icontheme.h"
|
#include "gtkmm/icontheme.h"
|
||||||
#include "idle-inhibit-unstable-v1-client-protocol.h"
|
#include "idle-inhibit-unstable-v1-client-protocol.h"
|
||||||
@@ -11,13 +12,13 @@
|
|||||||
#include "util/format.hpp"
|
#include "util/format.hpp"
|
||||||
|
|
||||||
waybar::Client *waybar::Client::inst() {
|
waybar::Client *waybar::Client::inst() {
|
||||||
static auto c = new Client();
|
static auto *c = new Client();
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleGlobal(void *data, struct wl_registry *registry, uint32_t name,
|
void waybar::Client::handleGlobal(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
const char *interface, uint32_t version) {
|
const char *interface, uint32_t version) {
|
||||||
auto client = static_cast<Client *>(data);
|
auto *client = static_cast<Client *>(data);
|
||||||
if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 &&
|
if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 &&
|
||||||
version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) {
|
version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) {
|
||||||
client->xdg_output_manager = static_cast<struct zxdg_output_manager_v1 *>(wl_registry_bind(
|
client->xdg_output_manager = static_cast<struct zxdg_output_manager_v1 *>(wl_registry_bind(
|
||||||
@@ -42,7 +43,7 @@ void waybar::Client::handleOutput(struct waybar_output &output) {
|
|||||||
.description = &handleOutputDescription,
|
.description = &handleOutputDescription,
|
||||||
};
|
};
|
||||||
// owned by output->monitor; no need to destroy
|
// owned by output->monitor; no need to destroy
|
||||||
auto wl_output = gdk_wayland_monitor_get_wl_output(output.monitor->gobj());
|
auto *wl_output = gdk_wayland_monitor_get_wl_output(output.monitor->gobj());
|
||||||
output.xdg_output.reset(zxdg_output_manager_v1_get_xdg_output(xdg_output_manager, wl_output));
|
output.xdg_output.reset(zxdg_output_manager_v1_get_xdg_output(xdg_output_manager, wl_output));
|
||||||
zxdg_output_v1_add_listener(output.xdg_output.get(), &xdgOutputListener, &output);
|
zxdg_output_v1_add_listener(output.xdg_output.get(), &xdgOutputListener, &output);
|
||||||
}
|
}
|
||||||
@@ -61,7 +62,7 @@ std::vector<Json::Value> waybar::Client::getOutputConfigs(struct waybar_output &
|
|||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleOutputDone(void *data, struct zxdg_output_v1 * /*xdg_output*/) {
|
void waybar::Client::handleOutputDone(void *data, struct zxdg_output_v1 * /*xdg_output*/) {
|
||||||
auto client = waybar::Client::inst();
|
auto *client = waybar::Client::inst();
|
||||||
try {
|
try {
|
||||||
auto &output = client->getOutput(data);
|
auto &output = client->getOutput(data);
|
||||||
/**
|
/**
|
||||||
@@ -85,24 +86,24 @@ void waybar::Client::handleOutputDone(void *data, struct zxdg_output_v1 * /*xdg_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleOutputName(void *data, struct zxdg_output_v1 * /*xdg_output*/,
|
void waybar::Client::handleOutputName(void *data, struct zxdg_output_v1 * /*xdg_output*/,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
auto client = waybar::Client::inst();
|
auto *client = waybar::Client::inst();
|
||||||
try {
|
try {
|
||||||
auto &output = client->getOutput(data);
|
auto &output = client->getOutput(data);
|
||||||
output.name = name;
|
output.name = name;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleOutputDescription(void *data, struct zxdg_output_v1 * /*xdg_output*/,
|
void waybar::Client::handleOutputDescription(void *data, struct zxdg_output_v1 * /*xdg_output*/,
|
||||||
const char *description) {
|
const char *description) {
|
||||||
auto client = waybar::Client::inst();
|
auto *client = waybar::Client::inst();
|
||||||
try {
|
try {
|
||||||
auto &output = client->getOutput(data);
|
auto &output = client->getOutput(data);
|
||||||
const char *open_paren = strrchr(description, '(');
|
const char *open_paren = strrchr(description, '(');
|
||||||
@@ -111,13 +112,13 @@ void waybar::Client::handleOutputDescription(void *data, struct zxdg_output_v1 *
|
|||||||
size_t identifier_length = open_paren - description;
|
size_t identifier_length = open_paren - description;
|
||||||
output.identifier = std::string(description, identifier_length - 1);
|
output.identifier = std::string(description, identifier_length - 1);
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor) {
|
void waybar::Client::handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor) {
|
||||||
auto &output = outputs_.emplace_back();
|
auto &output = outputs_.emplace_back();
|
||||||
output.monitor = monitor;
|
output.monitor = std::move(monitor);
|
||||||
handleOutput(output);
|
handleOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,15 +155,15 @@ const std::string waybar::Client::getStyle(const std::string &style,
|
|||||||
std::vector<std::string> search_files;
|
std::vector<std::string> search_files;
|
||||||
switch (appearance.value_or(portal->getAppearance())) {
|
switch (appearance.value_or(portal->getAppearance())) {
|
||||||
case waybar::Appearance::LIGHT:
|
case waybar::Appearance::LIGHT:
|
||||||
search_files.push_back("style-light.css");
|
search_files.emplace_back("style-light.css");
|
||||||
break;
|
break;
|
||||||
case waybar::Appearance::DARK:
|
case waybar::Appearance::DARK:
|
||||||
search_files.push_back("style-dark.css");
|
search_files.emplace_back("style-dark.css");
|
||||||
break;
|
break;
|
||||||
case waybar::Appearance::UNKNOWN:
|
case waybar::Appearance::UNKNOWN:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
search_files.push_back("style.css");
|
search_files.emplace_back("style.css");
|
||||||
css_file = Config::findConfigPath(search_files);
|
css_file = Config::findConfigPath(search_files);
|
||||||
} else {
|
} else {
|
||||||
css_file = style;
|
css_file = style;
|
||||||
@@ -196,7 +197,7 @@ void waybar::Client::bindInterfaces() {
|
|||||||
wl_registry_add_listener(registry, ®istry_listener, this);
|
wl_registry_add_listener(registry, ®istry_listener, this);
|
||||||
wl_display_roundtrip(wl_display);
|
wl_display_roundtrip(wl_display);
|
||||||
|
|
||||||
if (!gtk_layer_is_supported()) {
|
if (gtk_layer_is_supported() == 0) {
|
||||||
throw std::runtime_error("The Wayland compositor does not support wlr-layer-shell protocol");
|
throw std::runtime_error("The Wayland compositor does not support wlr-layer-shell protocol");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,11 +234,11 @@ int waybar::Client::main(int argc, char *argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (show_help) {
|
if (show_help) {
|
||||||
std::cout << cli << std::endl;
|
std::cout << cli << '\n';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (show_version) {
|
if (show_version) {
|
||||||
std::cout << "Waybar v" << VERSION << std::endl;
|
std::cout << "Waybar v" << VERSION << '\n';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!log_level.empty()) {
|
if (!log_level.empty()) {
|
||||||
|
|||||||
+8
-5
@@ -21,10 +21,10 @@ const std::vector<std::string> Config::CONFIG_DIRS = {
|
|||||||
|
|
||||||
const char *Config::CONFIG_PATH_ENV = "WAYBAR_CONFIG_DIR";
|
const char *Config::CONFIG_PATH_ENV = "WAYBAR_CONFIG_DIR";
|
||||||
|
|
||||||
std::optional<std::string> tryExpandPath(const std::string base, const std::string filename) {
|
std::optional<std::string> tryExpandPath(const std::string &base, const std::string &filename) {
|
||||||
fs::path path;
|
fs::path path;
|
||||||
|
|
||||||
if (filename != "") {
|
if (!filename.empty()) {
|
||||||
path = fs::path(base) / fs::path(filename);
|
path = fs::path(base) / fs::path(filename);
|
||||||
} else {
|
} else {
|
||||||
path = fs::path(base);
|
path = fs::path(base);
|
||||||
@@ -129,9 +129,9 @@ bool isValidOutput(const Json::Value &config, const std::string &name,
|
|||||||
if (config_output.substr(0, 1) == "!") {
|
if (config_output.substr(0, 1) == "!") {
|
||||||
if (config_output.substr(1) == name || config_output.substr(1) == identifier) {
|
if (config_output.substr(1) == name || config_output.substr(1) == identifier) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (config_output == name || config_output == identifier) {
|
if (config_output == name || config_output == identifier) {
|
||||||
return true;
|
return true;
|
||||||
@@ -142,7 +142,9 @@ bool isValidOutput(const Json::Value &config, const std::string &name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else if (config["output"].isString()) {
|
}
|
||||||
|
|
||||||
|
if (config["output"].isString()) {
|
||||||
auto config_output = config["output"].asString();
|
auto config_output = config["output"].asString();
|
||||||
if (!config_output.empty()) {
|
if (!config_output.empty()) {
|
||||||
if (config_output.substr(0, 1) == "!") {
|
if (config_output.substr(0, 1) == "!") {
|
||||||
@@ -162,6 +164,7 @@ void Config::load(const std::string &config) {
|
|||||||
}
|
}
|
||||||
config_file_ = file.value();
|
config_file_ = file.value();
|
||||||
spdlog::info("Using configuration file {}", config_file_);
|
spdlog::info("Using configuration file {}", config_file_);
|
||||||
|
config_ = Json::Value();
|
||||||
setupConfig(config_, config_file_, 0);
|
setupConfig(config_, config_file_, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-2
@@ -28,6 +28,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_DWL
|
#ifdef HAVE_DWL
|
||||||
#include "modules/dwl/tags.hpp"
|
#include "modules/dwl/tags.hpp"
|
||||||
|
#include "modules/dwl/window.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_HYPRLAND
|
#ifdef HAVE_HYPRLAND
|
||||||
#include "modules/hyprland/language.hpp"
|
#include "modules/hyprland/language.hpp"
|
||||||
@@ -69,7 +70,7 @@
|
|||||||
#include "modules/gamemode.hpp"
|
#include "modules/gamemode.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_UPOWER
|
#ifdef HAVE_UPOWER
|
||||||
#include "modules/upower/upower.hpp"
|
#include "modules/upower.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_PIPEWIRE
|
#ifdef HAVE_PIPEWIRE
|
||||||
#include "modules/privacy/privacy.hpp"
|
#include "modules/privacy/privacy.hpp"
|
||||||
@@ -86,6 +87,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#include "modules/bluetooth.hpp"
|
#include "modules/bluetooth.hpp"
|
||||||
|
#include "modules/power_profiles_daemon.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LOGIND_INHIBITOR
|
#ifdef HAVE_LOGIND_INHIBITOR
|
||||||
#include "modules/inhibitor.hpp"
|
#include "modules/inhibitor.hpp"
|
||||||
@@ -128,7 +130,7 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_UPOWER
|
#ifdef HAVE_UPOWER
|
||||||
if (ref == "upower") {
|
if (ref == "upower") {
|
||||||
return new waybar::modules::upower::UPower(id, config_[name]);
|
return new waybar::modules::UPower(id, config_[name]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_PIPEWIRE
|
#ifdef HAVE_PIPEWIRE
|
||||||
@@ -186,6 +188,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
|
|||||||
if (ref == "dwl/tags") {
|
if (ref == "dwl/tags") {
|
||||||
return new waybar::modules::dwl::Tags(id, bar_, config_[name]);
|
return new waybar::modules::dwl::Tags(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
|
if (ref == "dwl/window") {
|
||||||
|
return new waybar::modules::dwl::Window(id, bar_, config_[name]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_HYPRLAND
|
#ifdef HAVE_HYPRLAND
|
||||||
if (ref == "hyprland/window") {
|
if (ref == "hyprland/window") {
|
||||||
@@ -282,6 +287,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
|
|||||||
if (ref == "bluetooth") {
|
if (ref == "bluetooth") {
|
||||||
return new waybar::modules::Bluetooth(id, config_[name]);
|
return new waybar::modules::Bluetooth(id, config_[name]);
|
||||||
}
|
}
|
||||||
|
if (ref == "power-profiles-daemon") {
|
||||||
|
return new waybar::modules::PowerProfilesDaemon(id, config_[name]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LOGIND_INHIBITOR
|
#ifdef HAVE_LOGIND_INHIBITOR
|
||||||
if (ref == "inhibitor") {
|
if (ref == "inhibitor") {
|
||||||
|
|||||||
+17
-30
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <util/command.hpp>
|
#include <util/command.hpp>
|
||||||
|
|
||||||
#include "gdkmm/device.h"
|
#include "gtkmm/enums.h"
|
||||||
#include "gtkmm/widget.h"
|
#include "gtkmm/widget.h"
|
||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
@@ -19,9 +19,9 @@ const Gtk::RevealerTransitionType getPreferredTransitionType(bool is_vertical) {
|
|||||||
|
|
||||||
if (is_vertical) {
|
if (is_vertical) {
|
||||||
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_UP;
|
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_UP;
|
||||||
} else {
|
|
||||||
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_LEFT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_LEFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Group::Group(const std::string& name, const std::string& id, const Json::Value& config,
|
Group::Group(const std::string& name, const std::string& id, const Json::Value& config,
|
||||||
@@ -78,30 +78,21 @@ Group::Group(const std::string& name, const std::string& id, const Json::Value&
|
|||||||
} else {
|
} else {
|
||||||
box.pack_start(revealer);
|
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;
|
event_box_.add(box);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Group::addHoverHandlerTo(Gtk::Widget& widget) {
|
bool Group::handleMouseEnter(GdkEventCrossing* const& e) {
|
||||||
widget.add_events(Gdk::EventMask::ENTER_NOTIFY_MASK | Gdk::EventMask::LEAVE_NOTIFY_MASK);
|
box.set_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
|
||||||
widget.signal_enter_notify_event().connect(sigc::mem_fun(*this, &Group::handleMouseHover));
|
revealer.set_reveal_child(true);
|
||||||
widget.signal_leave_notify_event().connect(sigc::mem_fun(*this, &Group::handleMouseHover));
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Group::handleMouseLeave(GdkEventCrossing* const& e) {
|
||||||
|
box.unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
|
||||||
|
revealer.set_reveal_child(false);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Group::update() -> void {
|
auto Group::update() -> void {
|
||||||
@@ -113,17 +104,13 @@ Gtk::Box& Group::getBox() { return is_drawer ? (is_first_widget ? box : revealer
|
|||||||
void Group::addWidget(Gtk::Widget& widget) {
|
void Group::addWidget(Gtk::Widget& widget) {
|
||||||
getBox().pack_start(widget, false, false);
|
getBox().pack_start(widget, false, false);
|
||||||
|
|
||||||
if (is_drawer) {
|
if (is_drawer && !is_first_widget) {
|
||||||
// Necessary because of GTK's hitbox detection
|
widget.get_style_context()->add_class(add_class_to_drawer_children);
|
||||||
addHoverHandlerTo(widget);
|
|
||||||
if (!is_first_widget) {
|
|
||||||
widget.get_style_context()->add_class(add_class_to_drawer_children);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is_first_widget = false;
|
is_first_widget = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Group::operator Gtk::Widget&() { return box; }
|
Group::operator Gtk::Widget&() { return event_box_; }
|
||||||
|
|
||||||
} // namespace waybar
|
} // namespace waybar
|
||||||
|
|||||||
+4
-3
@@ -13,7 +13,8 @@ std::list<pid_t> reap;
|
|||||||
volatile bool reload;
|
volatile bool reload;
|
||||||
|
|
||||||
void* signalThread(void* args) {
|
void* signalThread(void* args) {
|
||||||
int err, signum;
|
int err;
|
||||||
|
int signum;
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
sigemptyset(&mask);
|
sigemptyset(&mask);
|
||||||
sigaddset(&mask, SIGCHLD);
|
sigaddset(&mask, SIGCHLD);
|
||||||
@@ -46,7 +47,7 @@ void* signalThread(void* args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void startSignalThread(void) {
|
void startSignalThread() {
|
||||||
int err;
|
int err;
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
sigemptyset(&mask);
|
sigemptyset(&mask);
|
||||||
@@ -71,7 +72,7 @@ void startSignalThread(void) {
|
|||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
try {
|
try {
|
||||||
auto client = waybar::Client::inst();
|
auto* client = waybar::Client::inst();
|
||||||
|
|
||||||
std::signal(SIGUSR1, [](int /*signal*/) {
|
std::signal(SIGUSR1, [](int /*signal*/) {
|
||||||
for (auto& bar : waybar::Client::inst()->bars) {
|
for (auto& bar : waybar::Client::inst()->bars) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user