Merge branch 'master' into hyprland-window_no_title_from_special

This commit is contained in:
Alexis Rouillard
2024-07-02 23:19:39 +02:00
committed by GitHub
155 changed files with 4825 additions and 2445 deletions
+12 -12
View File
@@ -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 }
+32
View File
@@ -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 }}
+10 -7
View File
@@ -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
+2 -1
View File
@@ -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
+17
View File
@@ -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
+2
View File
@@ -48,3 +48,5 @@ packagecache
# Nix # Nix
result result
result-* result-*
.ccls-cache
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -6,4 +6,4 @@ RUN zypper -n up && \
zypper addrepo https://download.opensuse.org/repositories/X11:Wayland/openSUSE_Tumbleweed/X11:Wayland.repo | echo 'a' && \ zypper 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
+2 -2
View File
@@ -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
+3 -2
View File
@@ -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:
[![Packaging status](https://repology.org/badge/vertical-allrepos/waybar.svg)](https://repology.org/project/waybar/versions) [![Packaging status](https://repology.org/badge/vertical-allrepos/waybar.svg?columns=3&header=Waybar%20Downstream%20Packaging)](https://repology.org/project/waybar/versions)
An Ubuntu PPA with more recent versions is available 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
View File
@@ -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": {
+14 -6
View File
@@ -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,8 +51,11 @@
}; };
}); });
overlays.default = final: prev: { overlays = {
default = self.overlays.waybar;
waybar = final: prev: {
waybar = final.callPackage ./nix/default.nix { waybar = final.callPackage ./nix/default.nix {
waybar = prev.waybar;
# take the first "version: '...'" from meson.build # take the first "version: '...'" from meson.build
version = version =
(builtins.head (builtins.split "'" (builtins.head (builtins.split "'"
@@ -57,11 +65,11 @@
+ "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty"); + "+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;
}); });
}; };
} }
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+2 -4
View File
@@ -19,8 +19,6 @@ class Group : public AModule {
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;
Gtk::Box revealer_box; Gtk::Box revealer_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
+1 -1
View File
@@ -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&);
+3
View File
@@ -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*,
+11 -3
View File
@@ -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}};
}; };
+1
View File
@@ -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_;
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include <fmt/format.h>
#include <string>
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "dwl-ipc-unstable-v2-client-protocol.h"
#include "util/json.hpp"
namespace waybar::modules::dwl {
class Window : public AAppIconLabel, public sigc::trackable {
public:
Window(const std::string &, const waybar::Bar &, const Json::Value &);
~Window();
void handle_layout(const uint32_t layout);
void handle_title(const char *title);
void handle_appid(const char *ppid);
void handle_layout_symbol(const char *layout_symbol);
void handle_frame();
struct zdwl_ipc_manager_v2 *status_manager_;
private:
const Bar &bar_;
std::string title_;
std::string appid_;
std::string layout_symbol_;
uint32_t layout_;
struct zdwl_ipc_output_v2 *output_status_;
};
} // namespace waybar::modules::dwl
+10 -5
View File
@@ -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;
+1 -1
View File
@@ -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_;
+5 -2
View File
@@ -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
+10 -8
View File
@@ -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
+88
View File
@@ -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
+27 -91
View File
@@ -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.
+2 -1
View File
@@ -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();
+48
View File
@@ -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
-3
View File
@@ -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"
-3
View File
@@ -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"
+2
View File
@@ -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;
+1
View File
@@ -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);
+94
View File
@@ -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 &parameters);
// 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
-81
View File
@@ -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
-33
View File
@@ -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
+4 -1
View File
@@ -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);
+7 -13
View File
@@ -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_;
+12 -7
View File
@@ -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
+6 -23
View File
@@ -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
+6 -4
View File
@@ -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);
+18 -1
View File
@@ -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:
``` ```
+22 -1
View File
@@ -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*.
+18 -1
View File
@@ -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.
+12
View File
@@ -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
+12
View File
@@ -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
+5 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+118
View File
@@ -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]"
}
}
```
+13
View File
@@ -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
+28 -1
View File
@@ -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
+14
View File
@@ -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)
+18 -1
View File
@@ -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*)
+18 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+153
View File
@@ -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
View File
@@ -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
+7 -4
View File
@@ -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
+18 -1
View File
@@ -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.
+72
View File
@@ -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": ""
}
}
```
+1 -1
View File
@@ -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,
+22 -1
View File
@@ -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": ["", ""]
+18 -1
View File
@@ -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
``` ```
+18 -1
View File
@@ -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
``` ```
+18 -1
View File
@@ -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
View File
@@ -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.
+44
View File
@@ -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)*
+18
View File
@@ -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 {}.
+18 -1
View File
@@ -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
``` ```
+13
View File
@@ -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*.
+5 -1
View File
@@ -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 ++
+2
View File
@@ -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}*
+13
View File
@@ -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.
+19 -1
View File
@@ -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.
+19
View File
@@ -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
+18 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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}
+52 -5
View File
@@ -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"
}
} }
} }
+5
View File
@@ -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("&", "&amp;")
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:
+28
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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_; }
+30 -21
View File
@@ -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 {
@@ -448,10 +447,20 @@ void waybar::Bar::setupAltFormatKeyForModuleList(const char* module_list_name) {
if (config.isMember(module_list_name)) { if (config.isMember(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()) {
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()) { if (module_name.isString()) {
setupAltFormatKeyForModule(module_name.asString()); 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
View File
@@ -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, &registry_listener, this); wl_registry_add_listener(registry, &registry_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
View File
@@ -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
View File
@@ -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") {
+16 -29
View File
@@ -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) { event_box_.add(box);
switch (e->type) { }
case GDK_ENTER_NOTIFY:
bool Group::handleMouseEnter(GdkEventCrossing* const& e) {
box.set_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
revealer.set_reveal_child(true); revealer.set_reveal_child(true);
break; return false;
case GDK_LEAVE_NOTIFY: }
bool Group::handleMouseLeave(GdkEventCrossing* const& e) {
box.unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
revealer.set_reveal_child(false); revealer.set_reveal_child(false);
break; return false;
default:
break;
}
return true;
}
void Group::addHoverHandlerTo(Gtk::Widget& widget) {
widget.add_events(Gdk::EventMask::ENTER_NOTIFY_MASK | Gdk::EventMask::LEAVE_NOTIFY_MASK);
widget.signal_enter_notify_event().connect(sigc::mem_fun(*this, &Group::handleMouseHover));
widget.signal_leave_notify_event().connect(sigc::mem_fun(*this, &Group::handleMouseHover));
} }
auto Group::update() -> void { 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
addHoverHandlerTo(widget);
if (!is_first_widget) {
widget.get_style_context()->add_class(add_class_to_drawer_children); 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
View File
@@ -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