Merge branch 'Alexays:master' into patch-1

This commit is contained in:
tS
2025-12-09 10:15:36 +01:00
committed by GitHub
190 changed files with 6574 additions and 2983 deletions
+5 -3
View File
@@ -7,14 +7,16 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
build: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: DoozyX/clang-format-lint-action@v0.16.2 # TODO: bump to clang 19 release
# - uses: DoozyX/clang-format-lint-action@v0.18.2
- uses: DoozyX/clang-format-lint-action@558090054b3f39e3d6af24f0cd73b319535da809
name: clang-format name: clang-format
with: with:
source: "." source: "."
extensions: "hpp,h,cpp,c" extensions: "hpp,h,cpp,c"
style: "file:.clang-format" style: "file:.clang-format"
clangFormatVersion: 18 clangFormatVersion: 19
+1 -1
View File
@@ -7,7 +7,7 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
build: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: alexays/waybar:debian image: alexays/waybar:debian
+4 -3
View File
@@ -1,14 +1,15 @@
name: Build and Push Docker Image name: Build and Push Docker Image
on: on:
workflow_dispatch:
schedule: schedule:
# run every night at midnight # run monthly
- cron: '0 0 * * *' - cron: '0 0 1 * *'
jobs: jobs:
build-and-push: build-and-push:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'Alexays/Waybar' if: github.event_name != 'schedule' || github.repository == 'Alexays/Waybar'
strategy: strategy:
fail-fast: false # don't fail the other jobs if one of the images fails to build fail-fast: false # don't fail the other jobs if one of the images fails to build
matrix: matrix:
+3 -3
View File
@@ -7,21 +7,21 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
clang: build:
# Run actions in a FreeBSD VM on the ubuntu 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
runs-on: ubuntu-latest runs-on: ubuntu-latest
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.25.0 uses: cross-platform-actions/action@v0.28.0
timeout-minutes: 180 timeout-minutes: 180
env: env:
CPPFLAGS: '-isystem/usr/local/include' CPPFLAGS: '-isystem/usr/local/include'
LDFLAGS: '-L/usr/local/lib' LDFLAGS: '-L/usr/local/lib'
with: with:
operating_system: freebsd operating_system: freebsd
version: "14.1" version: "14.2"
environment_variables: CPPFLAGS LDFLAGS environment_variables: CPPFLAGS LDFLAGS
sync_files: runner-to-vm sync_files: runner-to-vm
run: | run: |
+1 -1
View File
@@ -1,6 +1,6 @@
# vim: ft=Dockerfile # vim: ft=Dockerfile
FROM debian:sid FROM debian:sid-slim
RUN apt update && \ RUN apt update && \
apt install --no-install-recommends --no-install-suggests -y \ apt install --no-install-recommends --no-install-suggests -y \
+1 -1
View File
@@ -6,6 +6,6 @@ RUN export FEATURES="-ipc-sandbox -network-sandbox -pid-sandbox -sandbox -usersa
emerge --sync && \ emerge --sync && \
eselect news read --quiet new 1>/dev/null 2>&1 && \ eselect news read --quiet new 1>/dev/null 2>&1 && \
emerge --verbose --update --deep --with-bdeps=y --backtrack=30 --newuse @world && \ emerge --verbose --update --deep --with-bdeps=y --backtrack=30 --newuse @world && \
USE="wayland gtk3 gtk -doc X pulseaudio minimal" emerge dev-vcs/git dev-libs/wayland dev-libs/wayland-protocols =dev-cpp/gtkmm-3.24.6 x11-libs/libxkbcommon \ USE="wayland gtk3 gtk -doc X pulseaudio minimal" emerge dev-vcs/git dev-libs/wayland dev-libs/wayland-protocols dev-cpp/gtkmm:3.0 x11-libs/libxkbcommon \
x11-libs/gtk+:3 dev-libs/libdbusmenu dev-libs/libnl sys-power/upower media-libs/libpulse dev-libs/libevdev media-libs/libmpdclient \ x11-libs/gtk+:3 dev-libs/libdbusmenu dev-libs/libnl sys-power/upower media-libs/libpulse dev-libs/libevdev media-libs/libmpdclient \
media-sound/sndio gui-libs/gtk-layer-shell app-text/scdoc media-sound/playerctl dev-libs/iniparser sci-libs/fftw media-sound/sndio gui-libs/gtk-layer-shell app-text/scdoc media-sound/playerctl dev-libs/iniparser sci-libs/fftw
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2018 Alex Copyright (c) 2025 Alex
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+5 -1
View File
@@ -20,8 +20,12 @@ debug-run: build-debug
./build/waybar --log-level debug ./build/waybar --log-level debug
test: test:
meson test -C build --no-rebuild --verbose --suite waybar meson test -C build --verbose --suite waybar
.PHONY: test .PHONY: test
test-detailed:
meson test -C build --verbose --print-errorlogs --test-args='--reporter console -s'
.PHONY: test-detailed
clean: clean:
rm -rf build rm -rf build
+31 -1
View File
@@ -9,7 +9,7 @@
- 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)
- Niri (Workspaces, Focused window name, Language) - Niri (Workspaces, Focused window name, Language)
- DWL (Tags, Focused window name) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc) - DWL (Tags, Focused window name) [requires dwl ipc patch](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/ipc)
- Tray [#21](https://github.com/Alexays/Waybar/issues/21) - Tray [#21](https://github.com/Alexays/Waybar/issues/21)
- Local time - Local time
- Battery - Battery
@@ -116,6 +116,36 @@ sudo apt install \
libxkbregistry-dev libxkbregistry-dev
``` ```
On Arch, you can use this command:
```
pacman -S \
gtkmm3 \
jsoncpp \
libsigc++ \
fmt \
wayland \
chrono-date \
spdlog \
gtk3 \
gobject-introspection \
libgirepository \
libpulse \
libnl \
libappindicator-gtk3 \
libdbusmenu-gtk3 \
libmpdclient \
sndio \
libevdev \
libxkbcommon \
upower \
meson \
cmake \
scdoc \
wayland-protocols \
glib2-devel
```
Contributions welcome!<br> Contributions welcome!<br>
Have fun :)<br> Have fun :)<br>
+5
View File
@@ -0,0 +1,5 @@
# Suppress common address sanitizer issues in dependencies, these are often non-fixable or not an issue.
# Use it like this (when in repo root): ASAN_OPTIONS="suppressions=./asan.supp" ./build/waybar
leak:libpangoft2-1.0.so.0
leak:libgtk-3.so.0
leak:libfontconfig.so.1
+9 -10
View File
@@ -1,10 +1,9 @@
(import (import (
( let
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in lock = builtins.fromJSON (builtins.readFile ./flake.lock);
fetchTarball { in
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; fetchTarball {
sha256 = lock.nodes.flake-compat.locked.narHash; url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
} sha256 = lock.nodes.flake-compat.locked.narHash;
) }
{ src = ./.; } ) { src = ./.; }).defaultNix
).defaultNix
Generated
+6 -6
View File
@@ -3,11 +3,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1732722421, "lastModified": 1747046372,
"narHash": "sha256-HRJ/18p+WoXpWJkcdsk9St5ZiukCqSDgbOGFa8Okehg=", "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "9ed2ac151eada2306ca8c418ebd97807bb08f6ac", "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -18,11 +18,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1732837521, "lastModified": 1760878510,
"narHash": "sha256-jNRNr49UiuIwaarqijgdTR2qLPifxsVhlJrKzQ8XUIE=", "narHash": "sha256-K5Osef2qexezUfs0alLvZ7nQFTGS9DL2oTVsIXsqLgs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "970e93b9f82e2a0f3675757eb0bfc73297cc6370", "rev": "5e2a59a5b1a82f89f2c7e598302a9cacebb72a67",
"type": "github" "type": "github"
}, },
"original": { "original": {
+90 -39
View File
@@ -9,47 +9,94 @@
}; };
}; };
outputs = { self, nixpkgs, ... }: outputs =
{ self, nixpkgs, ... }:
let let
inherit (nixpkgs) lib; inherit (nixpkgs) lib;
genSystems = func: lib.genAttrs [ genSystems =
"x86_64-linux" func:
"aarch64-linux" lib.genAttrs
] [
(system: func (import nixpkgs { "x86_64-linux"
inherit system; "aarch64-linux"
overlays = with self.overlays; [ ]
waybar (
]; system:
})); func (
import nixpkgs {
inherit system;
overlays = with self.overlays; [
waybar
];
}
)
);
mkDate = longDate: (lib.concatStringsSep "-" [ mkDate =
(builtins.substring 0 4 longDate) longDate:
(builtins.substring 4 2 longDate) (lib.concatStringsSep "-" [
(builtins.substring 6 2 longDate) (builtins.substring 0 4 longDate)
]); (builtins.substring 4 2 longDate)
(builtins.substring 6 2 longDate)
]);
in in
{ {
devShells = genSystems devShells = genSystems (pkgs: {
(pkgs: default = pkgs.mkShell {
{ name = "waybar-shell";
default =
pkgs.mkShell
{
name = "waybar-shell";
# inherit attributes from upstream nixpkgs derivation # inherit attributes from upstream nixpkgs derivation
inherit (pkgs.waybar) buildInputs depsBuildBuild depsBuildBuildPropagated depsBuildTarget inherit (pkgs.waybar)
depsBuildTargetPropagated depsHostHost depsHostHostPropagated depsTargetTarget buildInputs
depsTargetTargetPropagated propagatedBuildInputs propagatedNativeBuildInputs strictDeps; depsBuildBuild
depsBuildBuildPropagated
depsBuildTarget
depsBuildTargetPropagated
depsHostHost
depsHostHostPropagated
depsTargetTarget
depsTargetTargetPropagated
propagatedBuildInputs
propagatedNativeBuildInputs
strictDeps
;
# overrides for local development # overrides for local development
nativeBuildInputs = pkgs.waybar.nativeBuildInputs ++ (with pkgs; [ nativeBuildInputs =
clang-tools pkgs.waybar.nativeBuildInputs
gdb ++ (with pkgs; [
]); nixfmt
}; clang-tools
}); gdb
]);
};
});
formatter = genSystems (
pkgs:
pkgs.treefmt.withConfig {
settings = {
formatter = {
clang-format = {
options = [ "-i" ];
command = lib.getExe' pkgs.clang-tools "clang-format";
excludes = [ ];
includes = [
"*.c"
"*.cpp"
"*.h"
"*.hpp"
];
};
nixfmt = {
command = lib.getExe pkgs.nixfmt;
includes = [ "*.nix" ];
};
};
tree-root-file = ".git/index";
};
}
);
overlays = { overlays = {
default = self.overlays.waybar; default = self.overlays.waybar;
@@ -58,11 +105,15 @@
waybar = prev.waybar; 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.elemAt builtins.split "'" (
(builtins.split " version: '" (builtins.readFile ./meson.build)) builtins.elemAt (builtins.split " version: '" (builtins.readFile ./meson.build)) 2
2))) )
+ "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty"); ))
+ "+date="
+ (mkDate (self.lastModifiedDate or "19700101"))
+ "_"
+ (self.shortRev or "dirty");
}; };
}; };
}; };
+1 -1
View File
@@ -21,7 +21,7 @@ class ALabel : public AModule {
protected: protected:
Gtk::Label label_; Gtk::Label label_;
std::string format_; std::string format_;
const std::chrono::seconds interval_; const std::chrono::milliseconds interval_;
bool alt_ = false; bool alt_ = false;
std::string default_format_; std::string default_format_;
+1 -1
View File
@@ -36,6 +36,7 @@ class AModule : public IModule {
SCROLL_DIR getScrollDir(GdkEventScroll *e); SCROLL_DIR getScrollDir(GdkEventScroll *e);
bool tooltipEnabled() const; bool tooltipEnabled() const;
std::vector<int> pid_children_;
const std::string name_; const std::string name_;
const Json::Value &config_; const Json::Value &config_;
Gtk::EventBox event_box_; Gtk::EventBox event_box_;
@@ -54,7 +55,6 @@ class AModule : public IModule {
const bool isTooltip; const bool isTooltip;
const bool isExpand; const bool isExpand;
bool hasUserEvents_; bool hasUserEvents_;
std::vector<int> pid_;
gdouble distance_scrolled_y_; gdouble distance_scrolled_y_;
gdouble distance_scrolled_x_; gdouble distance_scrolled_x_;
std::map<std::string, std::string> eventActionMap_; std::map<std::string, std::string> eventActionMap_;
+8
View File
@@ -14,6 +14,7 @@
#include "AModule.hpp" #include "AModule.hpp"
#include "group.hpp" #include "group.hpp"
#include "util/kill_signal.hpp"
#include "xdg-output-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h"
namespace waybar { namespace waybar {
@@ -68,7 +69,11 @@ class Bar : public sigc::trackable {
void setMode(const std::string &mode); void setMode(const std::string &mode);
void setVisible(bool value); void setVisible(bool value);
void toggle(); void toggle();
void show();
void hide();
void handleSignal(int); void handleSignal(int);
util::KillSignalAction getOnSigusr1Action();
util::KillSignalAction getOnSigusr2Action();
struct waybar_output *output; struct waybar_output *output;
Json::Value config; Json::Value config;
@@ -118,6 +123,9 @@ class Bar : public sigc::trackable {
std::unique_ptr<BarIpcClient> _ipc_client; std::unique_ptr<BarIpcClient> _ipc_client;
#endif #endif
std::vector<std::shared_ptr<waybar::AModule>> modules_all_; std::vector<std::shared_ptr<waybar::AModule>> modules_all_;
waybar::util::KillSignalAction onSigusr1 = util::SIGNALACTION_DEFAULT_SIGUSR1;
waybar::util::KillSignalAction onSigusr2 = util::SIGNALACTION_DEFAULT_SIGUSR2;
}; };
} // namespace waybar } // namespace waybar
+4 -2
View File
@@ -20,8 +20,8 @@ class Config {
static std::optional<std::string> findConfigPath( static std::optional<std::string> findConfigPath(
const std::vector<std::string> &names, const std::vector<std::string> &dirs = CONFIG_DIRS); const std::vector<std::string> &names, const std::vector<std::string> &dirs = CONFIG_DIRS);
static std::optional<std::string> tryExpandPath(const std::string &base, static std::vector<std::string> tryExpandPath(const std::string &base,
const std::string &filename); const std::string &filename);
Config() = default; Config() = default;
@@ -35,6 +35,8 @@ class Config {
void setupConfig(Json::Value &dst, const std::string &config_file, int depth); void setupConfig(Json::Value &dst, const std::string &config_file, int depth);
void resolveConfigIncludes(Json::Value &config, int depth); void resolveConfigIncludes(Json::Value &config, int depth);
void mergeConfig(Json::Value &a_config_, Json::Value &b_config_); void mergeConfig(Json::Value &a_config_, Json::Value &b_config_);
static std::vector<std::string> findIncludePath(
const std::string &name, const std::vector<std::string> &dirs = CONFIG_DIRS);
std::string config_file_; std::string config_file_;
+2
View File
@@ -35,6 +35,7 @@ class Battery : public ALabel {
std::tuple<uint8_t, float, std::string, float, uint16_t, 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&);
void processEvents(std::string& state, std::string& status, uint8_t capacity);
int global_watch; int global_watch;
std::map<fs::path, int> batteries_; std::map<fs::path, int> batteries_;
@@ -43,6 +44,7 @@ class Battery : public ALabel {
int global_watch_fd_; int global_watch_fd_;
std::mutex battery_list_mutex_; std::mutex battery_list_mutex_;
std::string old_status_; std::string old_status_;
std::string last_event_;
bool warnFirstTime_{true}; bool warnFirstTime_{true};
const Bar& bar_; const Bar& bar_;
-50
View File
@@ -1,50 +0,0 @@
#pragma once
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace cava {
extern "C" {
#include <cava/common.h>
}
} // namespace cava
namespace waybar::modules {
using namespace std::literals::chrono_literals;
class Cava final : public ALabel {
public:
Cava(const std::string&, const Json::Value&);
virtual ~Cava();
auto update() -> void override;
auto doAction(const std::string& name) -> void override;
private:
util::SleeperThread thread_;
util::SleeperThread thread_fetch_input_;
struct cava::error_s error_ {}; // cava errors
struct cava::config_params prm_ {}; // cava parameters
struct cava::audio_raw audio_raw_ {}; // cava handled raw audio data(is based on audio_data)
struct cava::audio_data audio_data_ {}; // cava audio data
struct cava::cava_plan* plan_; //{new cava_plan{}};
// Cava API to read audio source
cava::ptr input_source_;
// Delay to handle audio source
std::chrono::milliseconds frame_time_milsec_{1s};
// Text to display
std::string text_{""};
int rePaint_{1};
std::chrono::seconds fetch_input_delay_{4};
std::chrono::seconds suspend_silence_delay_{0};
bool silence_{false};
bool hide_on_silence_{false};
std::string format_silent_{""};
int sleep_counter_{0};
// Cava method
void pause_resume();
// ModuleActionMap
static inline std::map<const std::string, void (waybar::modules::Cava::*const)()> actionMap_{
{"mode", &waybar::modules::Cava::pause_resume}};
};
} // namespace waybar::modules
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include "ALabel.hpp"
#include "cava_backend.hpp"
namespace waybar::modules::cava {
class Cava final : public ALabel, public sigc::trackable {
public:
Cava(const std::string&, const Json::Value&);
~Cava() = default;
auto onUpdate(const std::string& input) -> void;
auto onSilence() -> void;
auto doAction(const std::string& name) -> void override;
private:
std::shared_ptr<CavaBackend> backend_;
// Text to display
std::string label_text_{""};
bool hide_on_silence_{false};
std::string format_silent_{""};
int ascii_range_{0};
bool silence_{false};
// Cava method
void pause_resume();
// ModuleActionMap
static inline std::map<const std::string, void (waybar::modules::cava::Cava::* const)()>
actionMap_{{"mode", &waybar::modules::cava::Cava::pause_resume}};
};
} // namespace waybar::modules::cava
+74
View File
@@ -0,0 +1,74 @@
#pragma once
#include <json/json.h>
#include <sigc++/sigc++.h>
#include "util/sleeper_thread.hpp"
namespace cava {
extern "C" {
// Need sdl_glsl output feature to be enabled on libcava
#ifndef SDL_GLSL
#define SDL_GLSL
#endif
#include <cava/common.h>
#ifdef SDL_GLSL
#undef SDL_GLSL
#endif
}
} // namespace cava
namespace waybar::modules::cava {
using namespace std::literals::chrono_literals;
class CavaBackend final {
public:
static std::shared_ptr<CavaBackend> inst(const Json::Value& config);
virtual ~CavaBackend();
// Methods
int getAsciiRange();
void doPauseResume();
void Update();
// Signal accessor
using type_signal_update = sigc::signal<void(const std::string&)>;
type_signal_update signal_update();
using type_signal_silence = sigc::signal<void()>;
type_signal_silence signal_silence();
private:
CavaBackend(const Json::Value& config);
util::SleeperThread thread_;
util::SleeperThread read_thread_;
// Cava API to read audio source
::cava::ptr input_source_{NULL};
struct ::cava::error_s error_{}; // cava errors
struct ::cava::config_params prm_{}; // cava parameters
struct ::cava::audio_raw audio_raw_{}; // cava handled raw audio data(is based on audio_data)
struct ::cava::audio_data audio_data_{}; // cava audio data
struct ::cava::cava_plan* plan_{NULL}; //{new cava_plan{}};
std::chrono::seconds fetch_input_delay_{4};
// Delay to handle audio source
std::chrono::milliseconds frame_time_milsec_{1s};
int re_paint_{0};
bool silence_{false};
bool silence_prev_{false};
std::chrono::seconds suspend_silence_delay_{0};
int sleep_counter_{0};
std::string output_{};
// Methods
void invoke();
void execute();
bool isSilence();
void doUpdate(bool force = false);
// Signal
type_signal_update m_signal_update_;
type_signal_silence m_signal_silence_;
};
} // namespace waybar::modules::cava
+24 -22
View File
@@ -38,39 +38,41 @@ class Clock final : public ALabel {
5 - tooltip-format 5 - tooltip-format
*/ */
std::map<int, std::string const> fmtMap_; std::map<int, std::string const> fmtMap_;
uint cldMonCols_{3}; // calendar count month columns uint cldMonCols_{3}; // calendar count month columns
int cldWnLen_{3}; // calendar week number length int cldWnLen_{3}; // calendar week number length
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 date::months cldCurrShift_{0}; // calendar months shift
int cldShift_{1}; // calendar months shift factor int cldShift_{1}; // calendar months shift factor
year_month_day cldYearShift_; // calendar Year mode. Cached ymd date::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 date::year_month cldMonShift_; // calendar Month mode. Cached ym
std::string cldMonCached_; // calendar Month mode. Cached calendar std::string cldMonCached_; // calendar Month mode. Cached calendar
day cldBaseDay_{0}; // calendar Cached day. Is used when today is changing(midnight) date::day cldBaseDay_{0}; // calendar Cached day. Is used when today is changing(midnight)
std::string cldText_{""}; // calendar text to print std::string cldText_{""}; // calendar text to print
bool iso8601Calendar_{false}; // whether the calendar is in ISO8601
CldMode cldMode_{CldMode::MONTH}; CldMode cldMode_{CldMode::MONTH};
auto get_calendar(const year_month_day& today, const year_month_day& ymd, auto get_calendar(const date::year_month_day& today, const date::year_month_day& ymd,
const time_zone* tz) -> const std::string; const date::time_zone* tz) -> const std::string;
// get local time zone // get local time zone
auto local_zone() -> const time_zone*; auto local_zone() -> const date::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 date::time_zone*> tzList_; // time zones list
int tzCurrIdx_; // current time zone index for tzList_ int tzCurrIdx_; // current time zone index for tzList_
std::string tzText_{""}; // time zones text to print std::string tzText_{""}; // time zones text to print
std::string tzTooltipFormat_{""}; // optional timezone tooltip format
util::SleeperThread thread_; util::SleeperThread thread_;
// ordinal date in tooltip // ordinal date in tooltip
const bool ordInTooltip_; const bool ordInTooltip_;
std::string ordText_{""}; std::string ordText_{""};
auto get_ordinal_date(const year_month_day& today) -> std::string; auto get_ordinal_date(const date::year_month_day& today) -> std::string;
auto getTZtext(sys_seconds now) -> std::string; auto getTZtext(date::sys_seconds now) -> std::string;
auto first_day_of_week() -> weekday; auto first_day_of_week() -> date::weekday;
// Module actions // Module actions
void cldModeSwitch(); void cldModeSwitch();
void cldShift_up(); void cldShift_up();
@@ -79,7 +81,7 @@ class Clock final : public ALabel {
void tz_up(); void tz_up();
void tz_down(); void tz_down();
// Module Action Map // Module Action Map
static inline std::map<const std::string, void (waybar::modules::Clock::*const)()> actionMap_{ static inline std::map<const std::string, void (waybar::modules::Clock::* const)()> actionMap_{
{"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},
+141
View File
@@ -0,0 +1,141 @@
#pragma once
#include <fmt/format.h>
#include <gtkmm/button.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>
#include <map>
#include <memory>
#include <vector>
#include "AModule.hpp"
#include "bar.hpp"
#include "ext-workspace-v1-client-protocol.h"
namespace waybar::modules::ext {
class WorkspaceGroup;
class Workspace;
class WorkspaceManager final : public AModule {
public:
WorkspaceManager(const std::string &id, const waybar::Bar &bar, const Json::Value &config);
~WorkspaceManager() override;
void register_manager(wl_registry *registry, uint32_t name, uint32_t version);
void remove_workspace_group(uint32_t id);
void remove_workspace(uint32_t id);
void set_needs_sorting() { needs_sorting_ = true; }
// wl events
void handle_workspace_group(ext_workspace_group_handle_v1 *handle);
void handle_workspace(ext_workspace_handle_v1 *handle);
void handle_done();
void handle_finished();
// wl requests
void commit() const;
private:
void update() override;
bool has_button(const Gtk::Button *button);
void sort_workspaces();
void clear_buttons();
void update_buttons();
static uint32_t group_global_id;
static uint32_t workspace_global_id;
uint32_t workspace_name = 0;
bool sort_by_id_ = false;
bool sort_by_name_ = true;
bool sort_by_coordinates_ = false;
bool all_outputs_ = false;
const waybar::Bar &bar_;
Gtk::Box box_;
ext_workspace_manager_v1 *ext_manager_ = nullptr;
std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
std::vector<std::unique_ptr<Workspace>> workspaces_;
bool needs_sorting_ = false;
};
class WorkspaceGroup {
public:
WorkspaceGroup(WorkspaceManager &manager, ext_workspace_group_handle_v1 *handle, uint32_t id);
~WorkspaceGroup();
u_int32_t id() const { return id_; }
bool has_output(const wl_output *output);
bool has_workspace(const ext_workspace_handle_v1 *workspace);
// wl events
void handle_capabilities(uint32_t capabilities);
void handle_output_enter(wl_output *output);
void handle_output_leave(wl_output *output);
void handle_workspace_enter(ext_workspace_handle_v1 *handle);
void handle_workspace_leave(ext_workspace_handle_v1 *handle);
void handle_removed();
private:
WorkspaceManager &workspaces_manager_;
ext_workspace_group_handle_v1 *ext_handle_;
uint32_t id_;
std::vector<wl_output *> outputs_;
std::vector<ext_workspace_handle_v1 *> workspaces_;
};
class Workspace {
public:
Workspace(const Json::Value &config, WorkspaceManager &manager, ext_workspace_handle_v1 *handle,
uint32_t id, const std::string &name);
~Workspace();
ext_workspace_handle_v1 *handle() const { return ext_handle_; }
u_int32_t id() const { return id_; }
std::string &workspace_id() { return workspace_id_; }
std::string &name() { return name_; }
std::vector<u_int32_t> &coordinates() { return coordinates_; }
Gtk::Button &button() { return button_; }
void update();
// wl events
void handle_id(const std::string &id);
void handle_name(const std::string &name);
void handle_coordinates(const std::vector<uint32_t> &coordinates);
void handle_state(uint32_t state);
void handle_capabilities(uint32_t capabilities);
void handle_removed();
// gdk events
bool handle_clicked(const GdkEventButton *button) const;
private:
bool has_state(uint32_t state) const { return (state_ & state) == state; }
std::string icon();
WorkspaceManager &workspace_manager_;
ext_workspace_handle_v1 *ext_handle_ = nullptr;
uint32_t id_;
uint32_t state_ = 0;
std::string workspace_id_;
std::string name_;
std::vector<uint32_t> coordinates_;
bool active_only_ = false;
bool ignore_hidden_ = true;
std::string format_;
bool with_icon_ = false;
static std::map<std::string, std::string> icon_map_;
std::string on_click_action_;
std::string on_click_middle_action_;
std::string on_click_right_action_;
Gtk::Button button_;
Gtk::Box content_;
Gtk::Label label_;
};
} // namespace waybar::modules::ext
@@ -0,0 +1,10 @@
#include "ext-workspace-v1-client-protocol.h"
namespace waybar::modules::ext {
void add_registry_listener(void *data);
void add_workspace_listener(ext_workspace_handle_v1 *workspace_handle, void *data);
void add_workspace_group_listener(ext_workspace_group_handle_v1 *workspace_group_handle,
void *data);
ext_workspace_manager_v1 *workspace_manager_bind(wl_registry *registry, uint32_t name,
uint32_t version, void *data);
} // namespace waybar::modules::ext
+40
View File
@@ -0,0 +1,40 @@
#pragma once
#include <fmt/format.h>
#include <sys/statvfs.h>
#ifdef WANT_RFKILL
#include "util/rfkill.hpp"
#endif
#include <gps.h>
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Gps : public ALabel {
public:
Gps(const std::string&, const Json::Value&);
virtual ~Gps();
auto update() -> void override;
private:
#ifdef WANT_RFKILL
util::Rfkill rfkill_;
#endif
const std::string getFixModeName() const;
const std::string getFixModeString() const;
const std::string getFixStatusString() const;
util::SleeperThread thread_, gps_thread_;
gps_data_t gps_data_;
std::string state_;
bool hideDisconnected = true;
bool hideNoFix = false;
};
} // namespace waybar::modules
+13 -6
View File
@@ -2,9 +2,9 @@
#include <filesystem> #include <filesystem>
#include <list> #include <list>
#include <memory>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <thread>
#include <utility> #include <utility>
#include "util/json.hpp" #include "util/json.hpp"
@@ -17,9 +17,15 @@ class EventHandler {
virtual ~EventHandler() = default; virtual ~EventHandler() = default;
}; };
/// If you want to use the Hyprland IPC, simply use IPC::inst() to get the singleton instance.
/// Do not create multiple instances.
class IPC { class IPC {
protected:
IPC(); // use IPC::inst() instead.
public: public:
IPC() { startIPC(); } ~IPC();
static IPC& inst();
void registerForIPC(const std::string& ev, EventHandler* ev_handler); void registerForIPC(const std::string& ev, EventHandler* ev_handler);
void unregisterForIPC(EventHandler* handler); void unregisterForIPC(EventHandler* handler);
@@ -32,14 +38,15 @@ class IPC {
static std::filesystem::path socketFolder_; static std::filesystem::path socketFolder_;
private: private:
void startIPC(); void socketListener();
void parseIPC(const std::string&); void parseIPC(const std::string&);
std::thread ipcThread_;
std::mutex callbackMutex_; std::mutex callbackMutex_;
util::JsonParser parser_; util::JsonParser parser_;
std::list<std::pair<std::string, EventHandler*>> callbacks_; std::list<std::pair<std::string, EventHandler*>> callbacks_;
int socketfd_; // the hyprland socket file descriptor
pid_t socketOwnerPid_;
bool running_ = true; // the ipcThread will stop running when this is false
}; };
inline std::unique_ptr<IPC> gIPC;
inline bool modulesReady = false;
}; // namespace waybar::modules::hyprland }; // namespace waybar::modules::hyprland
+2
View File
@@ -37,6 +37,8 @@ class Language : public waybar::ALabel, public EventHandler {
util::JsonParser parser_; util::JsonParser parser_;
Layout layout_; Layout layout_;
IPC& m_ipc;
}; };
} // namespace waybar::modules::hyprland } // namespace waybar::modules::hyprland
+2
View File
@@ -28,6 +28,8 @@ class Submap : public waybar::ALabel, public EventHandler {
std::string submap_; std::string submap_;
bool always_on_ = false; bool always_on_ = false;
std::string default_submap_ = "Default"; std::string default_submap_ = "Default";
IPC& m_ipc;
}; };
} // namespace waybar::modules::hyprland } // namespace waybar::modules::hyprland
+2
View File
@@ -60,6 +60,8 @@ class Window : public waybar::AAppIconLabel, public EventHandler {
bool swallowing_; bool swallowing_;
bool fullscreen_; bool fullscreen_;
bool focused_; bool focused_;
IPC& m_ipc;
}; };
} // namespace waybar::modules::hyprland } // namespace waybar::modules::hyprland
+41
View File
@@ -0,0 +1,41 @@
#pragma once
#include <fmt/format.h>
#include <string>
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
namespace waybar::modules::hyprland {
class WindowCount : public waybar::AAppIconLabel, public EventHandler {
public:
WindowCount(const std::string&, const waybar::Bar&, const Json::Value&);
~WindowCount() override;
auto update() -> void override;
private:
struct Workspace {
int id;
int windows;
bool hasfullscreen;
static auto parse(const Json::Value& value) -> Workspace;
};
auto getActiveWorkspace(const std::string&) -> Workspace;
auto getActiveWorkspace() -> Workspace;
void onEvent(const std::string& ev) override;
void queryActiveWorkspace();
void setClass(const std::string&, bool enable);
bool separateOutputs_;
std::mutex mutex_;
const Bar& bar_;
Workspace workspace_;
IPC& m_ipc;
};
} // namespace waybar::modules::hyprland
@@ -26,34 +26,48 @@ namespace waybar::modules::hyprland {
class Workspaces; class Workspaces;
struct WindowRepr {
std::string address;
std::string window_class;
std::string window_title;
std::string repr_rewrite;
bool isActive = false;
public:
bool empty() const { return address.empty(); }
void setActive(bool value) { isActive = value; }
};
class WindowCreationPayload { class WindowCreationPayload {
public: public:
WindowCreationPayload(std::string workspace_name, WindowAddress window_address, WindowCreationPayload(std::string workspace_name, WindowAddress window_address,
std::string window_repr); WindowRepr window_repr);
WindowCreationPayload(std::string workspace_name, WindowAddress window_address, WindowCreationPayload(std::string workspace_name, WindowAddress window_address,
std::string window_class, std::string window_title); std::string window_class, std::string window_title, bool is_active);
WindowCreationPayload(Json::Value const& client_data); WindowCreationPayload(Json::Value const& client_data);
int incrementTimeSpentUncreated(); int incrementTimeSpentUncreated();
bool isEmpty(Workspaces& workspace_manager); bool isEmpty(Workspaces& workspace_manager);
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); } bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
std::string repr(Workspaces& workspace_manager); WindowRepr repr(Workspaces& workspace_manager);
void setActive(bool value) { m_isActive = value; }
std::string getWorkspaceName() const { return m_workspaceName; } std::string getWorkspaceName() const { return m_workspaceName; }
WindowAddress getAddress() const { return m_windowAddress; } WindowAddress getAddress() const { return m_windowAddress; }
void moveToWorksace(std::string& new_workspace_name); void moveToWorkspace(std::string& new_workspace_name);
private: private:
void clearAddr(); void clearAddr();
void clearWorkspaceName(); void clearWorkspaceName();
using Repr = std::string; using Repr = WindowRepr;
using ClassAndTitle = std::pair<std::string, std::string>; using ClassAndTitle = std::pair<std::string, std::string>;
std::variant<Repr, ClassAndTitle> m_window; std::variant<Repr, ClassAndTitle> m_window;
WindowAddress m_windowAddress; WindowAddress m_windowAddress;
std::string m_workspaceName; std::string m_workspaceName;
bool m_isActive = false;
int m_timeSpentUncreated = 0; int m_timeSpentUncreated = 0;
}; };
+18 -9
View File
@@ -42,7 +42,6 @@ class Workspace {
bool isPersistentConfig() const { return m_isPersistentConfig; }; bool isPersistentConfig() const { return m_isPersistentConfig; };
bool isPersistentRule() const { return m_isPersistentRule; }; bool isPersistentRule() const { return m_isPersistentRule; };
bool isVisible() const { return m_isVisible; }; bool isVisible() const { return m_isVisible; };
bool isEmpty() const { return m_windows == 0; };
bool isUrgent() const { return m_isUrgent; }; bool isUrgent() const { return m_isUrgent; };
bool handleClicked(GdkEventButton* bt) const; bool handleClicked(GdkEventButton* bt) const;
@@ -54,15 +53,18 @@ class Workspace {
void setWindows(uint value) { m_windows = value; }; void setWindows(uint value) { m_windows = value; };
void setName(std::string const& value) { m_name = value; }; void setName(std::string const& value) { m_name = value; };
void setOutput(std::string const& value) { m_output = value; }; void setOutput(std::string const& value) { m_output = value; };
bool containsWindow(WindowAddress const& addr) const { return m_windowMap.contains(addr); } bool containsWindow(WindowAddress const& addr) const {
void insertWindow(WindowCreationPayload create_window_paylod); return std::ranges::any_of(m_windowMap,
std::string removeWindow(WindowAddress const& addr); [&addr](const auto& window) { return window.address == addr; });
};
void insertWindow(WindowCreationPayload create_window_payload);
void initializeWindowMap(const Json::Value& clients_data); void initializeWindowMap(const Json::Value& clients_data);
void setActiveWindow(WindowAddress const& addr);
bool onWindowOpened(WindowCreationPayload const& create_window_paylod); bool onWindowOpened(WindowCreationPayload const& create_window_payload);
std::optional<std::string> closeWindow(WindowAddress const& addr); std::optional<WindowRepr> closeWindow(WindowAddress const& addr);
void update(const std::string& format, const std::string& icon); void update(const std::string& workspace_icon);
private: private:
Workspaces& m_workspaceManager; Workspaces& m_workspaceManager;
@@ -78,11 +80,18 @@ class Workspace {
bool m_isUrgent = false; bool m_isUrgent = false;
bool m_isVisible = false; bool m_isVisible = false;
std::map<WindowAddress, std::string> m_windowMap; std::vector<WindowRepr> m_windowMap;
Gtk::Button m_button; Gtk::Button m_button;
Gtk::Box m_content; Gtk::Box m_content;
Gtk::Label m_label; Gtk::Label m_labelBefore;
Gtk::Label m_labelAfter;
bool isEmpty() const;
void updateTaskbar(const std::string& workspace_icon);
bool handleClick(const GdkEventButton* event_button, WindowAddress const& addr) const;
bool shouldSkipWindow(const WindowRepr& window_repr) const;
IPC& m_ipc;
}; };
} // namespace waybar::modules::hyprland } // namespace waybar::modules::hyprland
+65 -10
View File
@@ -1,12 +1,14 @@
#pragma once #pragma once
#include <gtkmm/button.h> #include <gtkmm/button.h>
#include <gtkmm/enums.h>
#include <gtkmm/label.h> #include <gtkmm/label.h>
#include <json/value.h> #include <json/value.h>
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <memory> #include <memory>
#include <optional>
#include <regex> #include <regex>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -17,6 +19,7 @@
#include "modules/hyprland/windowcreationpayload.hpp" #include "modules/hyprland/windowcreationpayload.hpp"
#include "modules/hyprland/workspace.hpp" #include "modules/hyprland/workspace.hpp"
#include "util/enum.hpp" #include "util/enum.hpp"
#include "util/icon_loader.hpp"
#include "util/regex_collection.hpp" #include "util/regex_collection.hpp"
using WindowAddress = std::string; using WindowAddress = std::string;
@@ -36,37 +39,55 @@ class Workspaces : public AModule, public EventHandler {
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 specialVisibleOnly() const -> bool { return m_specialVisibleOnly; }
auto persistentOnly() const -> bool { return m_persistentOnly; }
auto moveToMonitor() const -> bool { return m_moveToMonitor; } auto moveToMonitor() const -> bool { return m_moveToMonitor; }
auto enableTaskbar() const -> bool { return m_enableTaskbar; }
auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; }
auto getBarOutput() const -> std::string { return m_bar.output->name; } auto getBarOutput() const -> std::string { return m_bar.output->name; }
auto formatBefore() const -> std::string { return m_formatBefore; }
auto formatAfter() const -> std::string { return m_formatAfter; }
auto taskbarFormatBefore() const -> std::string { return m_taskbarFormatBefore; }
auto taskbarFormatAfter() const -> std::string { return m_taskbarFormatAfter; }
auto taskbarIconSize() const -> int { return m_taskbarIconSize; }
auto taskbarOrientation() const -> Gtk::Orientation { return m_taskbarOrientation; }
auto taskbarReverseDirection() const -> bool { return m_taskbarReverseDirection; }
auto onClickWindow() const -> std::string { return m_onClickWindow; }
auto getIgnoredWindows() const -> std::vector<std::regex> { return m_ignoreWindows; }
enum class ActiveWindowPosition { NONE, FIRST, LAST };
auto activeWindowPosition() const -> ActiveWindowPosition { return m_activeWindowPosition; }
std::string getRewrite(std::string window_class, std::string window_title); std::string getRewrite(std::string window_class, std::string window_title);
std::string& getWindowSeparator() { return m_formatWindowSeparator; } std::string& getWindowSeparator() { return m_formatWindowSeparator; }
bool isWorkspaceIgnored(std::string const& workspace_name); bool isWorkspaceIgnored(std::string const& workspace_name);
bool windowRewriteConfigUsesTitle() const { return m_anyWindowRewriteRuleUsesTitle; } bool windowRewriteConfigUsesTitle() const { return m_anyWindowRewriteRuleUsesTitle; }
const IconLoader& iconLoader() const { return m_iconLoader; }
private: private:
void onEvent(const std::string& e) override; void onEvent(const std::string& e) override;
void updateWindowCount(); void updateWindowCount();
void sortSpecialCentered();
void sortWorkspaces(); void sortWorkspaces();
void createWorkspace(Json::Value const& workspace_data, void createWorkspace(Json::Value const& workspace_data,
Json::Value const& clients_data = Json::Value::nullRef); Json::Value const& clients_data = Json::Value::nullRef);
static Json::Value createMonitorWorkspaceData(std::string const& name, static Json::Value createMonitorWorkspaceData(std::string const& name,
std::string const& monitor); std::string const& monitor);
void removeWorkspace(std::string const& name); void removeWorkspace(std::string const& workspaceString);
void setUrgentWorkspace(std::string const& windowaddress); void setUrgentWorkspace(std::string const& windowaddress);
// Config // Config
void parseConfig(const Json::Value& config); void parseConfig(const Json::Value& config);
auto populateIconsMap(const Json::Value& formatIcons) -> void; auto populateIconsMap(const Json::Value& formatIcons) -> void;
static auto populateBoolConfig(const Json::Value& config, const std::string& key, static auto populateBoolConfig(const Json::Value& config, const std::string& key, bool& member)
bool& member) -> void; -> void;
auto populateSortByConfig(const Json::Value& config) -> void; auto populateSortByConfig(const Json::Value& config) -> void;
auto populateIgnoreWorkspacesConfig(const Json::Value& config) -> void; auto populateIgnoreWorkspacesConfig(const Json::Value& config) -> void;
auto populateFormatWindowSeparatorConfig(const Json::Value& config) -> void; auto populateFormatWindowSeparatorConfig(const Json::Value& config) -> void;
auto populateWindowRewriteConfig(const Json::Value& config) -> void; auto populateWindowRewriteConfig(const Json::Value& config) -> void;
auto populateWorkspaceTaskbarConfig(const Json::Value& config) -> void;
void registerIpc(); void registerIpc();
@@ -74,10 +95,11 @@ class Workspaces : public AModule, public EventHandler {
void onWorkspaceActivated(std::string const& payload); void onWorkspaceActivated(std::string const& payload);
void onSpecialWorkspaceActivated(std::string const& payload); void onSpecialWorkspaceActivated(std::string const& payload);
void onWorkspaceDestroyed(std::string const& payload); void onWorkspaceDestroyed(std::string const& payload);
void onWorkspaceCreated(std::string const& workspaceName, void onWorkspaceCreated(std::string const& payload,
Json::Value const& clientsData = Json::Value::nullRef); Json::Value const& clientsData = Json::Value::nullRef);
void onWorkspaceMoved(std::string const& payload); void onWorkspaceMoved(std::string const& payload);
void onWorkspaceRenamed(std::string const& payload); void onWorkspaceRenamed(std::string const& payload);
static std::optional<int> parseWorkspaceId(std::string const& workspaceIdStr);
// monitor events // monitor events
void onMonitorFocused(std::string const& payload); void onMonitorFocused(std::string const& payload);
@@ -88,16 +110,24 @@ class Workspaces : public AModule, public EventHandler {
void onWindowMoved(std::string const& payload); void onWindowMoved(std::string const& payload);
void onWindowTitleEvent(std::string const& payload); void onWindowTitleEvent(std::string const& payload);
void onActiveWindowChanged(WindowAddress const& payload);
void onConfigReloaded(); void onConfigReloaded();
int windowRewritePriorityFunction(std::string const& window_rule); int windowRewritePriorityFunction(std::string const& window_rule);
// event payload management
template <typename... Args>
static std::string makePayload(Args const&... args);
static std::pair<std::string, std::string> splitDoublePayload(std::string const& payload);
static std::tuple<std::string, std::string, std::string> splitTriplePayload(
std::string const& payload);
// Update methods // Update methods
void doUpdate(); void doUpdate();
void removeWorkspacesToRemove(); void removeWorkspacesToRemove();
void createWorkspacesToCreate(); void createWorkspacesToCreate();
static std::vector<std::string> getVisibleWorkspaces(); static std::vector<int> getVisibleWorkspaces();
void updateWorkspaceStates(); void updateWorkspaceStates();
bool updateWindowsToCreate(); bool updateWindowsToCreate();
@@ -113,23 +143,26 @@ class Workspaces : public AModule, public EventHandler {
bool m_showSpecial = false; bool m_showSpecial = false;
bool m_activeOnly = false; bool m_activeOnly = false;
bool m_specialVisibleOnly = false; bool m_specialVisibleOnly = false;
bool m_persistentOnly = false;
bool m_moveToMonitor = 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.
// This happens when the user has multiple monitors (hence, multiple bars) // This happens when the user has multiple monitors (hence, multiple bars)
// and doesn't share windows accross bars (a.k.a `all-outputs` = false) // and doesn't share windows across bars (a.k.a `all-outputs` = false)
std::map<WindowAddress, std::string> m_orphanWindowMap; std::map<WindowAddress, WindowRepr, std::less<>> m_orphanWindowMap;
enum class SortMethod { ID, NAME, NUMBER, DEFAULT }; enum class SortMethod { ID, NAME, NUMBER, SPECIAL_CENTERED, DEFAULT };
util::EnumParser<SortMethod> m_enumParser; util::EnumParser<SortMethod> m_enumParser;
SortMethod m_sortBy = SortMethod::DEFAULT; SortMethod m_sortBy = SortMethod::DEFAULT;
std::map<std::string, SortMethod> m_sortMap = {{"ID", SortMethod::ID}, std::map<std::string, SortMethod> m_sortMap = {{"ID", SortMethod::ID},
{"NAME", SortMethod::NAME}, {"NAME", SortMethod::NAME},
{"NUMBER", SortMethod::NUMBER}, {"NUMBER", SortMethod::NUMBER},
{"SPECIAL-CENTERED", SortMethod::SPECIAL_CENTERED},
{"DEFAULT", SortMethod::DEFAULT}}; {"DEFAULT", SortMethod::DEFAULT}};
std::string m_format; std::string m_formatBefore;
std::string m_formatAfter;
std::map<std::string, std::string> m_iconsMap; std::map<std::string, std::string> m_iconsMap;
util::RegexCollection m_windowRewriteRules; util::RegexCollection m_windowRewriteRules;
@@ -138,18 +171,40 @@ class Workspaces : public AModule, public EventHandler {
bool m_withIcon; bool m_withIcon;
uint64_t m_monitorId; uint64_t m_monitorId;
std::string m_activeWorkspaceName; int m_activeWorkspaceId;
std::string m_activeSpecialWorkspaceName; std::string m_activeSpecialWorkspaceName;
std::vector<std::unique_ptr<Workspace>> m_workspaces; std::vector<std::unique_ptr<Workspace>> m_workspaces;
std::vector<std::pair<Json::Value, Json::Value>> m_workspacesToCreate; std::vector<std::pair<Json::Value, Json::Value>> m_workspacesToCreate;
std::vector<std::string> m_workspacesToRemove; std::vector<std::string> m_workspacesToRemove;
std::vector<WindowCreationPayload> m_windowsToCreate; std::vector<WindowCreationPayload> m_windowsToCreate;
IconLoader m_iconLoader;
bool m_enableTaskbar = false;
bool m_updateActiveWindow = false;
bool m_taskbarWithIcon = false;
bool m_taskbarWithTitle = false;
std::string m_taskbarFormatBefore;
std::string m_taskbarFormatAfter;
int m_taskbarIconSize = 16;
Gtk::Orientation m_taskbarOrientation = Gtk::ORIENTATION_HORIZONTAL;
bool m_taskbarReverseDirection = false;
util::EnumParser<ActiveWindowPosition> m_activeWindowEnumParser;
ActiveWindowPosition m_activeWindowPosition = ActiveWindowPosition::NONE;
std::map<std::string, ActiveWindowPosition> m_activeWindowPositionMap = {
{"NONE", ActiveWindowPosition::NONE},
{"FIRST", ActiveWindowPosition::FIRST},
{"LAST", ActiveWindowPosition::LAST},
};
std::string m_onClickWindow;
std::string m_currentActiveWindowAddress;
std::vector<std::regex> m_ignoreWorkspaces; std::vector<std::regex> m_ignoreWorkspaces;
std::vector<std::regex> m_ignoreWindows;
std::mutex m_mutex; std::mutex m_mutex;
const Bar& m_bar; const Bar& m_bar;
Gtk::Box m_box; Gtk::Box m_box;
IPC& m_ipc;
}; };
} // namespace waybar::modules::hyprland } // namespace waybar::modules::hyprland
+1 -1
View File
@@ -31,7 +31,7 @@ class Image : public AModule {
std::string path_; std::string path_;
std::string tooltip_; std::string tooltip_;
int size_; int size_;
int interval_; std::chrono::milliseconds interval_;
util::command::res output_; util::command::res output_;
util::SleeperThread thread_; util::SleeperThread thread_;
+29 -22
View File
@@ -9,6 +9,7 @@
#include <sys/epoll.h> #include <sys/epoll.h>
#include <optional> #include <optional>
#include <vector>
#include "ALabel.hpp" #include "ALabel.hpp"
#include "util/sleeper_thread.hpp" #include "util/sleeper_thread.hpp"
@@ -16,6 +17,8 @@
#include "util/rfkill.hpp" #include "util/rfkill.hpp"
#endif #endif
enum ip_addr_pref : uint8_t { IPV4, IPV6, IPV4_6 };
namespace waybar::modules { namespace waybar::modules {
class Network : public ALabel { class Network : public ALabel {
@@ -25,8 +28,8 @@ class Network : public ALabel {
auto update() -> void override; auto update() -> void override;
private: private:
static const uint8_t MAX_RETRY = 5; static const uint8_t MAX_RETRY{5};
static const uint8_t EPOLL_MAX = 200; static const uint8_t EPOLL_MAX{200};
static int handleEvents(struct nl_msg*, void*); static int handleEvents(struct nl_msg*, void*);
static int handleEventsDone(struct nl_msg*, void*); static int handleEventsDone(struct nl_msg*, void*);
@@ -42,40 +45,44 @@ class Network : public ALabel {
void parseFreq(struct nlattr**); void parseFreq(struct nlattr**);
void parseBssid(struct nlattr**); void parseBssid(struct nlattr**);
bool associatedOrJoined(struct nlattr**); bool associatedOrJoined(struct nlattr**);
bool checkInterface(std::string name); bool matchInterface(const std::string& ifname, const std::vector<std::string>& altnames,
std::string& matched) const;
auto getInfo() -> void; auto getInfo() -> void;
const std::string getNetworkState() const; const std::string getNetworkState() const;
void clearIface(); void clearIface();
bool wildcardMatch(const std::string& pattern, const std::string& text) const;
std::optional<std::pair<unsigned long long, unsigned long long>> readBandwidthUsage(); std::optional<std::pair<unsigned long long, unsigned long long>> readBandwidthUsage();
int ifid_; int ifid_{-1};
struct sockaddr_nl nladdr_ = {0}; ip_addr_pref addr_pref_{ip_addr_pref::IPV4};
struct nl_sock* sock_ = nullptr; struct sockaddr_nl nladdr_{0};
struct nl_sock* ev_sock_ = nullptr; struct nl_sock* sock_{nullptr};
int efd_; struct nl_sock* ev_sock_{nullptr};
int ev_fd_; int efd_{-1};
int nl80211_id_; int ev_fd_{-1};
int nl80211_id_{-1};
std::mutex mutex_; std::mutex mutex_;
bool want_route_dump_; bool want_route_dump_{false};
bool want_link_dump_; bool want_link_dump_{false};
bool want_addr_dump_; bool want_addr_dump_{false};
bool dump_in_progress_; bool dump_in_progress_{false};
bool is_p2p_; bool is_p2p_{false};
unsigned long long bandwidth_down_total_; unsigned long long bandwidth_down_total_{0};
unsigned long long bandwidth_up_total_; unsigned long long bandwidth_up_total_{0};
std::string state_; std::string state_;
std::string essid_; std::string essid_;
std::string bssid_; std::string bssid_;
bool carrier_; bool carrier_{false};
std::string ifname_; std::string ifname_;
std::string ipaddr_; std::string ipaddr_;
std::string ipaddr6_;
std::string gwaddr_; std::string gwaddr_;
std::string netmask_; std::string netmask_;
int cidr_; std::string netmask6_;
int cidr_{0};
int cidr6_{0};
int32_t signal_strength_dbm_; int32_t signal_strength_dbm_;
uint8_t signal_strength_; uint8_t signal_strength_;
std::string signal_strength_app_; std::string signal_strength_app_;
@@ -84,9 +91,9 @@ class Network : public ALabel {
util::SleeperThread thread_; util::SleeperThread thread_;
util::SleeperThread thread_timer_; util::SleeperThread thread_timer_;
#ifdef WANT_RFKILL #ifdef WANT_RFKILL
util::Rfkill rfkill_; util::Rfkill rfkill_{RFKILL_TYPE_WLAN};
#endif #endif
float frequency_; float frequency_{0};
}; };
} // namespace waybar::modules } // namespace waybar::modules
+1
View File
@@ -33,6 +33,7 @@ class Language : public ALabel, public EventHandler {
std::vector<Layout> layouts_; std::vector<Layout> layouts_;
unsigned current_idx_; unsigned current_idx_;
std::string last_short_name_;
}; };
} // namespace waybar::modules::niri } // namespace waybar::modules::niri
+3 -1
View File
@@ -13,7 +13,7 @@ namespace waybar::modules::privacy {
class Privacy : public AModule { class Privacy : public AModule {
public: public:
Privacy(const std::string &, const Json::Value &, const std::string &pos); Privacy(const std::string &, const Json::Value &, Gtk::Orientation, const std::string &pos);
auto update() -> void override; auto update() -> void override;
void onPrivacyNodesChanged(); void onPrivacyNodesChanged();
@@ -31,6 +31,8 @@ class Privacy : public AModule {
uint iconSpacing = 4; uint iconSpacing = 4;
uint iconSize = 20; uint iconSize = 20;
uint transition_duration = 250; uint transition_duration = 250;
std::set<std::pair<PrivacyNodeType, std::string>> ignore;
bool ignore_monitor = true;
std::shared_ptr<util::PipewireBackend::PipewireBackend> backend = nullptr; std::shared_ptr<util::PipewireBackend::PipewireBackend> backend = nullptr;
}; };
+2 -2
View File
@@ -17,8 +17,8 @@ namespace waybar::modules::privacy {
class PrivacyItem : public Gtk::Revealer { class PrivacyItem : public Gtk::Revealer {
public: public:
PrivacyItem(const Json::Value &config_, enum PrivacyNodeType privacy_type_, PrivacyItem(const Json::Value &config_, enum PrivacyNodeType privacy_type_,
std::list<PrivacyNodeInfo *> *nodes, const std::string &pos, const uint icon_size, std::list<PrivacyNodeInfo *> *nodes, Gtk::Orientation orientation,
const uint transition_duration); const std::string &pos, const uint icon_size, const uint transition_duration);
enum PrivacyNodeType privacy_type; enum PrivacyNodeType privacy_type;
+1
View File
@@ -24,6 +24,7 @@ class Layout : public waybar::ALabel {
private: private:
const waybar::Bar &bar_; const waybar::Bar &bar_;
std::string name_;
struct wl_output *output_; // stores the output this module belongs to struct wl_output *output_; // stores the output this module belongs to
struct wl_output *focused_output_; // stores the currently focused output struct wl_output *focused_output_; // stores the currently focused output
struct zriver_output_status_v1 *output_status_; struct zriver_output_status_v1 *output_status_;
+1
View File
@@ -21,6 +21,7 @@ class Tags : public waybar::AModule {
void handle_view_tags(struct wl_array *tags); void handle_view_tags(struct wl_array *tags);
void handle_urgent_tags(uint32_t tags); void handle_urgent_tags(uint32_t tags);
void handle_show();
void handle_primary_clicked(uint32_t tag); void handle_primary_clicked(uint32_t tag);
bool handle_button_press(GdkEventButton *event_button, uint32_t tag); bool handle_button_press(GdkEventButton *event_button, uint32_t tag);
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <json/json.h>
#include <spdlog/spdlog.h>
#include <string>
#include <unordered_map>
class IconManager {
public:
static IconManager& instance() {
static IconManager instance;
return instance;
}
void setIconsConfig(const Json::Value& icons_config) {
if (icons_config.isObject()) {
for (const auto& key : icons_config.getMemberNames()) {
std::string app_name = key;
const Json::Value& icon_value = icons_config[key];
if (icon_value.isString()) {
std::string icon_path = icon_value.asString();
icons_map_[app_name] = icon_path;
}
}
} else {
spdlog::warn("Invalid icon config format.");
}
}
std::string getIconForApp(const std::string& app_name) const {
auto it = icons_map_.find(app_name);
if (it != icons_map_.end()) {
return it->second;
}
return "";
}
private:
IconManager() = default;
std::unordered_map<std::string, std::string> icons_map_;
};
+2 -1
View File
@@ -26,7 +26,7 @@ struct ToolTip {
class Item : public sigc::trackable { class Item : public sigc::trackable {
public: public:
Item(const std::string&, const std::string&, const Json::Value&, const Bar&); Item(const std::string&, const std::string&, const Json::Value&, const Bar&);
~Item() = default; ~Item();
std::string bus_name; std::string bus_name;
std::string object_path; std::string object_path;
@@ -62,6 +62,7 @@ class Item : public sigc::trackable {
void proxyReady(Glib::RefPtr<Gio::AsyncResult>& result); void proxyReady(Glib::RefPtr<Gio::AsyncResult>& result);
void setProperty(const Glib::ustring& name, Glib::VariantBase& value); void setProperty(const Glib::ustring& name, Glib::VariantBase& value);
void setStatus(const Glib::ustring& value); void setStatus(const Glib::ustring& value);
void setCustomIcon(const std::string& id);
void getUpdatedProperties(); void getUpdatedProperties();
void processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& result); void processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& result);
void onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name, void onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
+1
View File
@@ -21,6 +21,7 @@ class Tray : public AModule {
void onRemove(std::unique_ptr<Item>& item); void onRemove(std::unique_ptr<Item>& item);
static inline std::size_t nb_hosts_ = 0; static inline std::size_t nb_hosts_ = 0;
bool show_passive_ = false;
Gtk::Box box_; Gtk::Box box_;
SNI::Watcher::singleton watcher_; SNI::Watcher::singleton watcher_;
SNI::Host host_; SNI::Host host_;
+2 -2
View File
@@ -21,7 +21,7 @@ class Language : public ALabel, public sigc::trackable {
auto update() -> void override; auto update() -> void override;
private: private:
enum class DispayedShortFlag { None = 0, ShortName = 1, ShortDescription = 1 << 1 }; enum class DisplayedShortFlag { None = 0, ShortName = 1, ShortDescription = 1 << 1 };
struct Layout { struct Layout {
std::string full_name; std::string full_name;
@@ -58,7 +58,7 @@ class Language : public ALabel, public sigc::trackable {
std::map<std::string, Layout> layouts_map_; std::map<std::string, Layout> layouts_map_;
bool hide_single_; 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>(DisplayedShortFlag::None);
util::JsonParser parser_; util::JsonParser parser_;
std::mutex mutex_; std::mutex mutex_;
+4 -2
View File
@@ -19,10 +19,11 @@ class Window : public AAppIconLabel, public sigc::trackable {
auto update() -> void override; auto update() -> void override;
private: private:
void setClass(std::string classname, bool enable); void setClass(const std::string& classname, bool enable);
void onEvent(const struct Ipc::ipc_response&); void onEvent(const struct Ipc::ipc_response&);
void onCmd(const struct Ipc::ipc_response&); void onCmd(const struct Ipc::ipc_response&);
std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string> std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string,
std::string>
getFocusedNode(const Json::Value& nodes, std::string& output); getFocusedNode(const Json::Value& nodes, std::string& output);
void getTree(); void getTree();
@@ -35,6 +36,7 @@ class Window : public AAppIconLabel, public sigc::trackable {
std::string old_app_id_; std::string old_app_id_;
std::size_t app_nb_; std::size_t app_nb_;
std::string shell_; std::string shell_;
std::string marks_;
int floating_count_; int floating_count_;
util::JsonParser parser_; util::JsonParser parser_;
std::mutex mutex_; std::mutex mutex_;
+1 -2
View File
@@ -48,8 +48,7 @@ class Workspaces : public AModule, public sigc::trackable {
std::vector<std::string> high_priority_named_; std::vector<std::string> high_priority_named_;
std::vector<std::string> workspaces_order_; std::vector<std::string> workspaces_order_;
Gtk::Box box_; Gtk::Box box_;
std::string m_formatWindowSeperator; std::string m_formatWindowSeparator;
std::string m_windowRewriteDefault;
util::RegexCollection m_windowRewriteRules; util::RegexCollection m_windowRewriteRules;
util::JsonParser parser_; util::JsonParser parser_;
std::unordered_map<std::string, Gtk::Button> buttons_; std::unordered_map<std::string, Gtk::Button> buttons_;
+4 -1
View File
@@ -19,12 +19,15 @@ class SystemdFailedUnits : public ALabel {
std::string format_ok; std::string format_ok;
bool update_pending; bool update_pending;
uint32_t nr_failed_system, nr_failed_user; std::string system_state, user_state, overall_state;
uint32_t nr_failed_system, nr_failed_user, nr_failed;
std::string last_status; std::string last_status;
Glib::RefPtr<Gio::DBus::Proxy> system_proxy, user_proxy; Glib::RefPtr<Gio::DBus::Proxy> system_proxy, user_proxy;
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name, void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name,
const Glib::VariantContainerBase &arguments); const Glib::VariantContainerBase &arguments);
void RequestFailedUnits();
void RequestSystemState();
void updateData(); void updateData();
}; };
+122
View File
@@ -0,0 +1,122 @@
#pragma once
#include <json/json.h>
#include <unistd.h>
#include <functional>
#include <list>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
namespace waybar::modules::wayfire {
using EventHandler = std::function<void(const std::string& event)>;
struct State {
/*
┌───────────┐ ┌───────────┐
│ output #1 │ │ output #2 │
└─────┬─────┘ └─────┬─────┘
└─┐ └─────┐─ ─ ─ ─ ─ ─ ─ ─ ┐
┌───────┴───────┐ ┌───────┴──────┐ ┌───────┴───────┐
│ wset #1 │ │ wset #2 │ │ wset #3 │
│┌────────────┐ │ │┌────────────┐│ │┌────────────┐ │
││ workspaces │ │ ││ workspaces ││ ││ workspaces │ │
│└─┬──────────┘ │ │└────────────┘│ │└─┬──────────┘ │
│ │ ┌─────────┐│ └──────────────┘ │ │ ┌─────────┐│
│ ├─┤ view #1 ││ │ └─┤ view #3 ││
│ │ └─────────┘│ │ └─────────┘│
│ │ ┌─────────┐│ └───────────────┘
│ └─┤ view #2 ││
│ └─────────┘│
└───────────────┘
*/
struct Output {
size_t id;
size_t w, h;
size_t wset_idx;
};
struct Workspace {
size_t num_views;
size_t num_sticky_views;
};
struct Wset {
std::optional<std::reference_wrapper<Output>> output;
std::vector<Workspace> wss;
size_t ws_w, ws_h, ws_x, ws_y;
size_t focused_view_id;
auto ws_idx() const { return ws_w * ws_y + ws_x; }
auto count_ws(const Json::Value& pos) -> Workspace&;
auto locate_ws(const Json::Value& geo) -> Workspace&;
auto locate_ws(const Json::Value& geo) const -> const Workspace&;
};
std::unordered_map<std::string, Output> outputs;
std::unordered_map<size_t, Wset> wsets;
std::unordered_map<size_t, Json::Value> views;
std::string focused_output_name;
size_t maybe_empty_focus_wset_idx = {};
size_t vswitch_sticky_view_id = {};
bool new_output_detected = {};
bool vswitching = {};
auto update_view(const Json::Value& view) -> void;
};
struct Sock {
int fd;
Sock(int fd) : fd{fd} {}
~Sock() { close(fd); }
Sock(const Sock&) = delete;
auto operator=(const Sock&) = delete;
Sock(Sock&& rhs) noexcept {
fd = rhs.fd;
rhs.fd = -1;
}
auto& operator=(Sock&& rhs) noexcept {
fd = rhs.fd;
rhs.fd = -1;
return *this;
}
};
class IPC {
static std::weak_ptr<IPC> instance;
Json::CharReaderBuilder reader_builder;
Json::StreamWriterBuilder writer_builder;
std::list<std::pair<std::string, std::reference_wrapper<const EventHandler>>> handlers;
std::mutex handlers_mutex;
State state;
std::mutex state_mutex;
IPC() { start(); }
static auto connect() -> Sock;
auto receive(Sock& sock) -> Json::Value;
auto start() -> void;
auto root_event_handler(const std::string& event, const Json::Value& data) -> void;
auto update_state_handler(const std::string& event, const Json::Value& data) -> void;
public:
static auto get_instance() -> std::shared_ptr<IPC>;
auto send(const std::string& method, Json::Value&& data) -> Json::Value;
auto register_handler(const std::string& event, const EventHandler& handler) -> void;
auto unregister_handler(EventHandler& handler) -> void;
auto lock_state() -> std::lock_guard<std::mutex> { return std::lock_guard{state_mutex}; }
auto& get_outputs() const { return state.outputs; }
auto& get_wsets() const { return state.wsets; }
auto& get_views() const { return state.views; }
auto& get_focused_output_name() const { return state.focused_output_name; }
};
} // namespace waybar::modules::wayfire
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "modules/wayfire/backend.hpp"
namespace waybar::modules::wayfire {
class Window : public AAppIconLabel {
std::shared_ptr<IPC> ipc;
EventHandler handler;
const Bar& bar_;
std::string old_app_id_;
public:
Window(const std::string& id, const Bar& bar, const Json::Value& config);
~Window() override;
auto update() -> void override;
auto update_icon_label() -> void;
};
} // namespace waybar::modules::wayfire
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <gtkmm/button.h>
#include <json/json.h>
#include <memory>
#include <vector>
#include "AModule.hpp"
#include "bar.hpp"
#include "modules/wayfire/backend.hpp"
namespace waybar::modules::wayfire {
class Workspaces : public AModule {
std::shared_ptr<IPC> ipc;
EventHandler handler;
const Bar& bar_;
Gtk::Box box_;
std::vector<Gtk::Button> buttons_;
auto handleScroll(GdkEventScroll* e) -> bool override;
auto update() -> void override;
auto update_box() -> void;
public:
Workspaces(const std::string& id, const Bar& bar, const Json::Value& config);
~Workspaces() override;
};
} // namespace waybar::modules::wayfire
+11 -1
View File
@@ -18,10 +18,12 @@ class Wireplumber : public ALabel {
private: private:
void asyncLoadRequiredApiModules(); void asyncLoadRequiredApiModules();
void prepare(); void prepare(waybar::modules::Wireplumber* self);
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 updateSourceVolume(waybar::modules::Wireplumber* self, uint32_t id);
static void updateSourceName(waybar::modules::Wireplumber* self, uint32_t id); // NEW
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, static void onDefaultNodesApiLoaded(WpObject* p, GAsyncResult* res,
waybar::modules::Wireplumber* self); waybar::modules::Wireplumber* self);
@@ -32,6 +34,8 @@ class Wireplumber : public ALabel {
bool handleScroll(GdkEventScroll* e) override; bool handleScroll(GdkEventScroll* e) override;
static std::list<waybar::modules::Wireplumber*> modules;
WpCore* wp_core_; WpCore* wp_core_;
GPtrArray* apis_; GPtrArray* apis_;
WpObjectManager* om_; WpObjectManager* om_;
@@ -44,6 +48,12 @@ class Wireplumber : public ALabel {
double min_step_; double min_step_;
uint32_t node_id_{0}; uint32_t node_id_{0};
std::string node_name_; std::string node_name_;
std::string source_name_;
gchar* type_;
uint32_t source_node_id_;
bool source_muted_;
double source_volume_;
gchar* default_source_name_;
}; };
} // namespace waybar::modules } // namespace waybar::modules
+3 -5
View File
@@ -19,6 +19,7 @@
#include "bar.hpp" #include "bar.hpp"
#include "client.hpp" #include "client.hpp"
#include "giomm/desktopappinfo.h" #include "giomm/desktopappinfo.h"
#include "util/icon_loader.hpp"
#include "util/json.hpp" #include "util/json.hpp"
#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h" #include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
@@ -89,9 +90,6 @@ class Task {
std::string state_string(bool = false) const; std::string state_string(bool = false) const;
void set_minimize_hint(); void set_minimize_hint();
void on_button_size_allocated(Gtk::Allocation &alloc); void on_button_size_allocated(Gtk::Allocation &alloc);
void set_app_info_from_app_id_list(const std::string &app_id_list);
bool image_load_icon(Gtk::Image &image, const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
void hide_if_ignored(); void hide_if_ignored();
public: public:
@@ -153,7 +151,7 @@ class Taskbar : public waybar::AModule {
Gtk::Box box_; Gtk::Box box_;
std::vector<TaskPtr> tasks_; std::vector<TaskPtr> tasks_;
std::vector<Glib::RefPtr<Gtk::IconTheme>> icon_themes_; IconLoader icon_loader_;
std::unordered_set<std::string> ignore_list_; std::unordered_set<std::string> ignore_list_;
std::map<std::string, std::string> app_ids_replace_map_; std::map<std::string, std::string> app_ids_replace_map_;
@@ -178,7 +176,7 @@ class Taskbar : public waybar::AModule {
bool show_output(struct wl_output *) const; bool show_output(struct wl_output *) const;
bool all_outputs() const; bool all_outputs() const;
const std::vector<Glib::RefPtr<Gtk::IconTheme>> &icon_themes() const; const IconLoader &icon_loader() const;
const std::unordered_set<std::string> &ignore_list() const; const std::unordered_set<std::string> &ignore_list() const;
const std::map<std::string, std::string> &app_ids_replace_map() const; const std::map<std::string, std::string> &app_ids_replace_map() const;
}; };
-172
View File
@@ -1,172 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <gtkmm/button.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>
#include <functional>
#include <map>
#include <memory>
#include <vector>
#include "AModule.hpp"
#include "bar.hpp"
#include "ext-workspace-unstable-v1-client-protocol.h"
namespace waybar::modules::wlr {
class WorkspaceManager;
class WorkspaceGroup;
class Workspace {
public:
Workspace(const waybar::Bar &bar, const Json::Value &config, WorkspaceGroup &workspace_group,
zext_workspace_handle_v1 *workspace, uint32_t id, std::string name);
~Workspace();
auto update() -> void;
auto id() const -> uint32_t { return id_; }
auto is_active() const -> bool { return state_ & static_cast<uint32_t>(State::ACTIVE); }
auto is_urgent() const -> bool { return state_ & static_cast<uint32_t>(State::URGENT); }
auto is_hidden() const -> bool { return state_ & static_cast<uint32_t>(State::HIDDEN); }
auto is_empty() const -> bool { return state_ & static_cast<uint32_t>(State::EMPTY); }
auto is_persistent() const -> bool { return persistent_; }
// wlr stuff
auto handle_name(const std::string &name) -> void;
auto handle_coordinates(const std::vector<uint32_t> &coordinates) -> void;
auto handle_state(const std::vector<uint32_t> &state) -> void;
auto handle_remove() -> void;
auto make_persistent() -> void;
auto handle_duplicate() -> void;
auto handle_done() -> void;
auto handle_clicked(GdkEventButton *bt) -> bool;
auto show() -> void;
auto hide() -> void;
auto get_button_ref() -> Gtk::Button & { return button_; }
auto get_name() -> std::string & { return name_; }
auto get_coords() -> std::vector<uint32_t> & { return coordinates_; }
enum class State {
ACTIVE = (1 << 0),
URGENT = (1 << 1),
HIDDEN = (1 << 2),
EMPTY = (1 << 3),
};
private:
auto get_icon() -> std::string;
const Bar &bar_;
const Json::Value &config_;
WorkspaceGroup &workspace_group_;
// wlr stuff
zext_workspace_handle_v1 *workspace_handle_;
uint32_t state_ = 0;
uint32_t id_;
std::string name_;
std::vector<uint32_t> coordinates_;
static std::map<std::string, std::string> icons_map_;
std::string format_;
bool with_icon_ = false;
bool persistent_ = false;
Gtk::Button button_;
Gtk::Box content_;
Gtk::Label label_;
};
class WorkspaceGroup {
public:
WorkspaceGroup(const waybar::Bar &bar, Gtk::Box &box, const Json::Value &config,
WorkspaceManager &manager, zext_workspace_group_handle_v1 *workspace_group_handle,
uint32_t id);
~WorkspaceGroup();
auto update() -> void;
auto id() const -> uint32_t { return id_; }
auto is_visible() const -> bool;
auto remove_workspace(uint32_t id_) -> void;
auto active_only() const -> bool;
auto creation_delayed() const -> bool;
auto workspaces() -> std::vector<std::unique_ptr<Workspace>> & { return workspaces_; }
auto persistent_workspaces() -> std::vector<std::string> & { return persistent_workspaces_; }
auto sort_workspaces() -> void;
auto set_need_to_sort() -> void { need_to_sort = true; }
auto add_button(Gtk::Button &button) -> void;
auto remove_button(Gtk::Button &button) -> void;
auto fill_persistent_workspaces() -> void;
auto create_persistent_workspaces() -> void;
// wlr stuff
auto handle_workspace_create(zext_workspace_handle_v1 *workspace_handle) -> void;
auto handle_remove() -> void;
auto handle_output_enter(wl_output *output) -> void;
auto handle_output_leave() -> void;
auto handle_done() -> void;
auto commit() -> void;
private:
static uint32_t workspace_global_id;
const waybar::Bar &bar_;
Gtk::Box &box_;
const Json::Value &config_;
WorkspaceManager &workspace_manager_;
// wlr stuff
zext_workspace_group_handle_v1 *workspace_group_handle_;
wl_output *output_ = nullptr;
uint32_t id_;
std::vector<std::unique_ptr<Workspace>> workspaces_;
bool need_to_sort = false;
std::vector<std::string> persistent_workspaces_;
bool persistent_created_ = false;
};
class WorkspaceManager : public AModule {
public:
WorkspaceManager(const std::string &id, const waybar::Bar &bar, const Json::Value &config);
~WorkspaceManager() override;
auto update() -> void override;
auto all_outputs() const -> bool { return all_outputs_; }
auto active_only() const -> bool { return active_only_; }
auto workspace_comparator() const
-> std::function<bool(std::unique_ptr<Workspace> &, std::unique_ptr<Workspace> &)>;
auto creation_delayed() const -> bool { return creation_delayed_; }
auto sort_workspaces() -> void;
auto remove_workspace_group(uint32_t id_) -> void;
// wlr stuff
auto register_manager(wl_registry *registry, uint32_t name, uint32_t version) -> void;
auto handle_workspace_group_create(zext_workspace_group_handle_v1 *workspace_group_handle)
-> void;
auto handle_done() -> void;
auto handle_finished() -> void;
auto commit() -> void;
private:
const waybar::Bar &bar_;
Gtk::Box box_;
std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
// wlr stuff
zext_workspace_manager_v1 *workspace_manager_ = nullptr;
static uint32_t group_global_id;
bool sort_by_name_ = true;
bool sort_by_coordinates_ = true;
bool sort_by_number_ = false;
bool all_outputs_ = false;
bool active_only_ = false;
bool creation_delayed_ = false;
};
} // namespace waybar::modules::wlr
@@ -1,10 +0,0 @@
#include "ext-workspace-unstable-v1-client-protocol.h"
namespace waybar::modules::wlr {
void add_registry_listener(void *data);
void add_workspace_listener(zext_workspace_handle_v1 *workspace_handle, void *data);
void add_workspace_group_listener(zext_workspace_group_handle_v1 *workspace_group_handle,
void *data);
zext_workspace_manager_v1 *workspace_manager_bind(wl_registry *registry, uint32_t name,
uint32_t version, void *data);
} // namespace waybar::modules::wlr
+5
View File
@@ -11,6 +11,11 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#ifdef __OpenBSD__
#define SIGRTMIN SIGUSR1 - 1
#define SIGRTMAX SIGUSR1 + 1
#endif
namespace waybar { namespace waybar {
/** /**
+6 -6
View File
@@ -622,8 +622,8 @@ inline auto convertInto(std::string const &source, bool &target) -> ParserResult
} }
#ifdef CLARA_CONFIG_OPTIONAL_TYPE #ifdef CLARA_CONFIG_OPTIONAL_TYPE
template <typename T> template <typename T>
inline auto convertInto(std::string const &source, inline auto convertInto(std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T> &target)
CLARA_CONFIG_OPTIONAL_TYPE<T> &target) -> ParserResult { -> ParserResult {
T temp; T temp;
auto result = convertInto(source, temp); auto result = convertInto(source, temp);
if (result) target = std::move(temp); if (result) target = std::move(temp);
@@ -751,8 +751,8 @@ class ParserBase {
public: public:
virtual ~ParserBase() = default; virtual ~ParserBase() = default;
virtual auto validate() const -> Result { return Result::ok(); } virtual auto validate() const -> Result { return Result::ok(); }
virtual auto parse(std::string const &exeName, virtual auto parse(std::string const &exeName, TokenStream const &tokens) const
TokenStream const &tokens) const -> InternalParseResult = 0; -> InternalParseResult = 0;
virtual auto cardinality() const -> size_t { return 1; } virtual auto cardinality() const -> size_t { return 1; }
auto parse(Args const &args) const -> InternalParseResult { auto parse(Args const &args) const -> InternalParseResult {
@@ -1098,8 +1098,8 @@ struct Parser : ParserBase {
using ParserBase::parse; using ParserBase::parse;
auto parse(std::string const &exeName, auto parse(std::string const &exeName, TokenStream const &tokens) const
TokenStream const &tokens) const -> InternalParseResult override { -> InternalParseResult override {
struct ParserInfo { struct ParserInfo {
ParserBase const *parser = nullptr; ParserBase const *parser = nullptr;
size_t count = 0; size_t count = 0;
+1 -3
View File
@@ -15,7 +15,7 @@
namespace date { namespace date {
#if HAVE_CHRONO_TIMEZONES #if HAVE_CHRONO_TIMEZONES
using namespace std::chrono; using namespace std::chrono;
using namespace std; using std::format;
#else #else
using system_clock = std::chrono::system_clock; using system_clock = std::chrono::system_clock;
@@ -73,5 +73,3 @@ struct fmt::formatter<date::zoned_time<Duration, TimeZonePtr>> {
} }
}; };
#endif #endif
using namespace date;
+3 -1
View File
@@ -10,5 +10,7 @@ class DefaultGtkIconThemeWrapper {
public: public:
static bool has_icon(const std::string&); static bool has_icon(const std::string&);
static Glib::RefPtr<Gdk::Pixbuf> load_icon(const char*, int, Gtk::IconLookupFlags); static Glib::RefPtr<Gdk::Pixbuf> load_icon(
const char*, int, Gtk::IconLookupFlags,
Glib::RefPtr<Gtk::StyleContext> style = Glib::RefPtr<Gtk::StyleContext>());
}; };
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <gdkmm/general.h>
#include <gio/gdesktopappinfo.h>
#include <giomm/desktopappinfo.h>
#include <glibmm/fileutils.h>
#include <gtkmm/image.h>
#include <spdlog/spdlog.h>
#include <string>
#include <vector>
#include "util/gtk_icon.hpp"
class IconLoader {
private:
std::vector<Glib::RefPtr<Gtk::IconTheme>> custom_icon_themes_;
Glib::RefPtr<Gtk::IconTheme> default_icon_theme_ = Gtk::IconTheme::get_default();
static std::vector<std::string> search_prefix();
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string &app_id);
static Glib::RefPtr<Gio::DesktopAppInfo> get_desktop_app_info(const std::string &app_id);
static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string const &icon_path, int size);
static std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
const std::string &app_id);
static bool image_load_icon(Gtk::Image &image, const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
public:
void add_custom_icon_theme(const std::string &theme_name);
bool image_load_icon(Gtk::Image &image, Glib::RefPtr<Gio::DesktopAppInfo> app_info,
int size) const;
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_from_app_id_list(
const std::string &app_id_list);
};
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include <json/value.h>
#include <cstdint>
namespace waybar::util {
enum class KillSignalAction : std::uint8_t {
TOGGLE,
RELOAD,
SHOW,
HIDE,
NOOP,
};
const std::map<std::string, KillSignalAction> userKillSignalActions = {
{"TOGGLE", KillSignalAction::TOGGLE},
{"RELOAD", KillSignalAction::RELOAD},
{"SHOW", KillSignalAction::SHOW},
{"HIDE", KillSignalAction::HIDE},
{"NOOP", KillSignalAction::NOOP}};
const KillSignalAction SIGNALACTION_DEFAULT_SIGUSR1 = KillSignalAction::TOGGLE;
const KillSignalAction SIGNALACTION_DEFAULT_SIGUSR2 = KillSignalAction::RELOAD;
}; // namespace waybar::util
@@ -25,6 +25,7 @@ class PrivacyNodeInfo {
std::string media_name; std::string media_name;
std::string node_name; std::string node_name;
std::string application_name; std::string application_name;
bool is_monitor = false;
std::string pipewire_access_portal_app_id; std::string pipewire_access_portal_app_id;
std::string application_icon_name; std::string application_icon_name;
+1 -3
View File
@@ -6,14 +6,12 @@
namespace waybar { namespace waybar {
using namespace Gio;
enum class Appearance { enum class Appearance {
UNKNOWN = 0, UNKNOWN = 0,
DARK = 1, DARK = 1,
LIGHT = 2, LIGHT = 2,
}; };
class Portal : private DBus::Proxy { class Portal : private Gio::DBus::Proxy {
public: public:
Portal(); Portal();
void refreshAppearance(); void refreshAppearance();
+1 -1
View File
@@ -4,6 +4,6 @@
namespace waybar::util { namespace waybar::util {
// Get a signal emited with value true when entering sleep, and false when exiting // Get a signal emitted with value true when entering sleep, and false when exiting
SafeSignal<bool>& prepare_for_sleep(); SafeSignal<bool>& prepare_for_sleep();
} // namespace waybar::util } // namespace waybar::util
+3 -1
View File
@@ -5,6 +5,8 @@
#include <sigc++/signal.h> #include <sigc++/signal.h>
#include <sigc++/trackable.h> #include <sigc++/trackable.h>
#include <atomic>
namespace waybar::util { namespace waybar::util {
class Rfkill : public sigc::trackable { class Rfkill : public sigc::trackable {
@@ -17,7 +19,7 @@ class Rfkill : public sigc::trackable {
private: private:
enum rfkill_type rfkill_type_; enum rfkill_type rfkill_type_;
bool state_ = false; std::atomic_bool state_ = false;
int fd_ = -1; int fd_ = -1;
bool on_event(Glib::IOCondition cond); bool on_event(Glib::IOCondition cond);
+23
View File
@@ -23,3 +23,26 @@ inline std::string capitalize(const std::string& str) {
[](unsigned char c) { return std::toupper(c); }); [](unsigned char c) { return std::toupper(c); });
return result; return result;
} }
inline std::string toLower(const std::string& str) {
std::string result = str;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::tolower(c); });
return result;
}
inline std::vector<std::string> split(std::string_view s, std::string_view delimiter,
int max_splits = -1) {
std::vector<std::string> result;
size_t pos = 0;
size_t next_pos = 0;
while ((next_pos = s.find(delimiter, pos)) != std::string::npos) {
result.push_back(std::string(s.substr(pos, next_pos - pos)));
pos = next_pos + delimiter.size();
if (max_splits > 0 && result.size() == static_cast<size_t>(max_splits)) {
break;
}
}
result.push_back(std::string(s.substr(pos)));
return result;
}
+1 -1
View File
@@ -40,7 +40,7 @@ The brightness can be controlled by dragging the slider across the bar or clicki
``` ```
"modules-right": [ "modules-right": [
"backlight-slider", "backlight/slider",
], ],
"backlight/slider": { "backlight/slider": {
"min": 0, "min": 0,
+23 -1
View File
@@ -116,7 +116,7 @@ The *battery* module displays the current capacity and state (eg. charging) of y
*menu-file*: ++ *menu-file*: ++
typeof: string ++ typeof: string ++
Location of the menu descriptor file. There need to be an element of type Location of the menu descriptor file. There need to be an element of type
GtkMenu with id *menu* GtkMenu with id *menu*.
*menu-actions*: ++ *menu-actions*: ++
typeof: array ++ typeof: array ++
@@ -127,6 +127,10 @@ The *battery* module displays the current capacity and state (eg. charging) of y
default: false ++ default: false ++
Enables this module to consume all left over space dynamically. Enables this module to consume all left over space dynamically.
*events*: ++
typeof: object ++
Specifies commands to be executed on specific battery states. See *EVENTS* section below.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{capacity}*: Capacity in percentage *{capacity}*: Capacity in percentage
@@ -166,6 +170,19 @@ The *battery* module allows one to define custom formats based on up to two fact
- The state can be addressed as a CSS class in the *style.css*. The name of the CSS class is the *<name>* of the state. Each class gets activated when the current capacity is equal to or below the configured *<value>*. - The state can be addressed as a CSS class in the *style.css*. The name of the CSS class is the *<name>* of the state. Each class gets activated when the current capacity is equal to or below the configured *<value>*.
- Also each state can have its own *format*. Those can be configured via *format-<name>*. Or if you want to differentiate a bit more even as *format-<status>-<state>*. For more information see *custom-formats*. - Also each state can have its own *format*. Those can be configured via *format-<name>*. Or if you want to differentiate a bit more even as *format-<status>-<state>*. For more information see *custom-formats*.
# EVENTS
Every entry in the *events* object consists of a *<event-name>* (typeof: *string*) and a *<command>* (typeof: *string*). ++
*<event-name>* can be in one of the following formats:
- *on-<status>-<state>*
- *on-<status>-<capacity>*
Where:
- *<status>* is either *charging* or *discharging*,
- *<state>* is the name of one of the states specified in the *states* object,
- *<capacity>* is a battery level value (between *0-100*).
# EXAMPLES # EXAMPLES
@@ -178,6 +195,11 @@ The *battery* module allows one to define custom formats based on up to two fact
"warning": 30, "warning": 30,
"critical": 15 "critical": 15
}, },
"events": {
"on-discharging-warning": "notify-send -u normal 'Low Battery'",
"on-discharging-critical": "notify-send -u critical 'Very Low Battery'",
"on-charging-100": "notify-send -u normal 'Battery Full!'"
},
"format": "{capacity}% {icon}", "format": "{capacity}% {icon}",
"format-icons": ["", "", "", "", ""], "format-icons": ["", "", "", "", ""],
"max-length": 25 "max-length": 25
+32 -1
View File
@@ -39,6 +39,12 @@ $XDG_CONFIG_HOME/waybar/config ++
:[ A list of timezones (as in *timezone*) to use for time display, changed using :[ A list of timezones (as in *timezone*) to use for time display, changed using
the scroll wheel. Do not specify *timezone* option when *timezones* is specified. the scroll wheel. Do not specify *timezone* option when *timezones* is specified.
"" represents the system's local timezone "" represents the system's local timezone
|[ *timezone-tooltip-format*
:[ string
:[
:[ Format to use for displaying timezones in the tooltip. When set, this allows showing
timezone information (like timezone abbreviations) in the tooltip while keeping the
main display clean. Uses the same format options as *format*
|[ *locale* |[ *locale*
:[ string :[ string
:[ :[
@@ -117,7 +123,7 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe
:[ 3 :[ 3
:[ Relevant for *mode=year*. Count of months per row :[ Relevant for *mode=year*. Count of months per row
|[ *weeks-pos* |[ *weeks-pos*
:[ integer :[ string
:[ :[
:[ The position where week numbers should be displayed. Disabled when is empty. :[ The position where week numbers should be displayed. Disabled when is empty.
Possible values: left|right Possible values: left|right
@@ -126,6 +132,12 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe
:[ 1 :[ 1
:[ Value to scroll months/years forward/backward. Can be negative. Is :[ Value to scroll months/years forward/backward. Can be negative. Is
configured under *on-scroll* option configured under *on-scroll* option
|[ *iso8601*
:[ bool
:[ false
:[ When enabled, the calendar follows the ISO 8601 standard: weeks begin on
Monday, and the first week of the year is numbered 1. The default week format is
'{:%V}'.
3. Addressed by *clock: calendar: format* 3. Addressed by *clock: calendar: format*
[- *Option* [- *Option*
@@ -229,6 +241,25 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe
} }
``` ```
4. Show timezone in tooltip only
```
"clock": {
"interval": 60,
"format": "{:%H:%M}",
"timezone-tooltip-format": "{:%H:%M %Z}",
"timezones": [
"",
"America/Chicago",
"America/Los_Angeles",
"Europe/Paris",
"UTC"
],
"tooltip": true,
"tooltip-format": "{tz_list}"
}
```
# STYLE # STYLE
- *#clock* - *#clock*
+3 -2
View File
@@ -11,9 +11,10 @@ The *cpu* module displays the current CPU utilization.
# CONFIGURATION # CONFIGURATION
*interval*: ++ *interval*: ++
typeof: integer ++ typeof: integer or float ++
default: 10 ++ default: 10 ++
The interval in which the information gets polled. The interval in which the information gets polled. ++
Minimum value is 0.001 (1ms). Values smaller than 1ms will be set to 1ms.
*format*: ++ *format*: ++
typeof: string ++ typeof: string ++
+4 -2
View File
@@ -35,15 +35,17 @@ Addressed by *custom/<name>*
See *return-type* See *return-type*
*interval*: ++ *interval*: ++
typeof: integer ++ typeof: integer or float ++
The interval (in seconds) in which the information gets polled. ++ The interval (in seconds) in which the information gets polled. ++
Minimum value is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++
Use *once* if you want to execute the module only on startup. ++ Use *once* if you want to execute the module only on startup. ++
You can update it manually with a signal. If no *interval* or *signal* is defined, it is assumed that the out script loops itself. ++ You can update it manually with a signal. If no *interval* or *signal* is defined, it is assumed that the out script loops itself. ++
If a *signal* is defined then the script will run once on startup and will only update with a signal. If a *signal* is defined then the script will run once on startup and will only update with a signal.
*restart-interval*: ++ *restart-interval*: ++
typeof: integer ++ typeof: integer or float ++
The restart interval (in seconds). ++ The restart interval (in seconds). ++
Minimum value is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++
Can't be used with the *interval* option, so only with continuous scripts. ++ Can't be used with the *interval* option, so only with continuous scripts. ++
Once the script exits, it'll be re-executed after the *restart-interval*. Once the script exits, it'll be re-executed after the *restart-interval*.
@@ -10,7 +10,7 @@ The *workspaces* module displays the currently used workspaces in wayland compos
# CONFIGURATION # CONFIGURATION
Addressed by *wlr/workspaces* Addressed by *ext/workspaces*
*format*: ++ *format*: ++
typeof: string ++ typeof: string ++
@@ -24,18 +24,18 @@ Addressed by *wlr/workspaces*
*sort-by-name*: ++ *sort-by-name*: ++
typeof: bool ++ typeof: bool ++
default: true ++ default: true ++
Should workspaces be sorted by name. Should workspaces be sorted by name. Workspace names will be sorted numerically when all names are numbers.
*sort-by-coordinates*: ++ *sort-by-coordinates*: ++
typeof: bool ++ typeof: bool ++
default: true ++ default: false ++
Should workspaces be sorted by coordinates. ++ Should workspaces be sorted by coordinates. ++
Note that if both *sort-by-name* and *sort-by-coordinates* are true sort-by name will be first. If both are false - sort by id will be performed. Note that if both *sort-by-name* and *sort-by-coordinates* are true sort-by name will be first. If both are false - sort by id will be performed.
*sort-by-number*: ++ *sort-by-id*: ++
typeof: bool ++ typeof: bool ++
default: false ++ default: false ++
If set to true, workspace names will be sorted numerically. Takes precedence over any other sort-by option. Should workspaces be sorted by ID. Workspace ID will be sorted numerically when all ID are numbers. Takes precedence over any other sort-by option.
*all-outputs*: ++ *all-outputs*: ++
typeof: bool ++ typeof: bool ++
@@ -47,9 +47,16 @@ Addressed by *wlr/workspaces*
default: false ++ default: false ++
If set to true only active or urgent workspaces will be shown. If set to true only active or urgent workspaces will be shown.
*ignore-hidden*: ++
typeof: bool ++
default: true ++
If set to false hidden workspaces will be shown.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{name}*: Name of workspace assigned by compositor *{name}*: Name of workspace assigned by compositor.
*{id}*: ID of workspace assigned by compositor.
*{icon}*: Icon, as defined in *format-icons*. *{icon}*: Icon, as defined in *format-icons*.
@@ -57,6 +64,8 @@ Addressed by *wlr/workspaces*
*activate*: Switch to workspace. *activate*: Switch to workspace.
*deactivate*: Deactivate the workspace.
*close*: Close the workspace. *close*: Close the workspace.
# ICONS # ICONS
@@ -69,18 +78,18 @@ In addition to workspace name matching, the following *format-icons* can be set.
# EXAMPLES # EXAMPLES
``` ```
"wlr/workspaces": { "ext/workspaces": {
"format": "{name}: {icon}", "format": "{name}: {icon}",
"on-click": "activate",
"format-icons": { "format-icons": {
"1": "", "Workspace 1": "",
"2": "", "Workspace 2": "",
"3": "", "Workspace 3": "",
"4": "", "Workspace 4": "",
"5": "",
"active": "", "active": "",
"default": "" "default": ""
}, },
"sort-by-number": true "sort-by-id": true
} }
``` ```
+111
View File
@@ -0,0 +1,111 @@
waybar-gps(5) "waybar-gps" "User Manual"
# NAME
waybar - gps module
# DESCRIPTION
*gps* module for gpsd.
# FILES
$XDG_CONFIG_HOME/waybar/config ++
Per user configuration file
# ADDITIONAL FILES
libgps lives in:
. /usr/lib/libgps.so or /usr/lib64/libgps.so
. /usr/lib/pkgconfig/libgps.pc or /usr/lib64/pkgconfig/libgps.pc
. /usr/include/gps
# CONFIGURATION
*format*: ++
typeof: string ++
default: {glyph} ++
The text format.
*tooltip*: ++
typeof: bool ++
default: true ++
Option to disable tooltip on hover.
*tooltip-format*: ++
typeof: string ++
default: Games running: {glyph} ++
The text format of the tooltip.
*interval*: ++
typeof: integer ++
default: 5 ++
The interval in which the GPS information gets polled (e.g. current speed).
Significant updates (e.g. the current fix mode) are updated immediately.
*hide-disconnected*: ++
typeof: bool ++
default: true ++
Defines if the module should be hidden if there is no GPS receiver.
*hide-no-fix*: ++
typeof: bool ++
default: false ++
Defines if the module should be hidden if there is no GPS fix.
# FORMAT REPLACEMENTS
*{mode}*: Fix mode
*{status}*: Technology used for GPS fix. Not all GPS receivers report this.
*{latitude}*: Latitude, decimal degrees. Can be NaN.
*{latitude_error}*: Latitude uncertainty, meters. Can be NaN.
*{longitude}*: Longitude, decimal degrees. Can be NaN.
*{longitude_error}*: Longitude uncertainty, meters. Can be NaN.
*{altitude_hae}*: Altitude, height above ellipsoid, meters. Can be NaN.
*{altitude_msl}*: Longitude, MSL, meters. Can be NaN.
*{altitude_error}*: Altitude uncertainty, meters. Can be NaN.
*{speed}*: Speed over ground, meters/sec. Can be NaN.
*{speed_error}*: Speed uncertainty, meters/sec. Can be NaN.
*{climb}*: Vertical speed, meters/sec. Can be NaN.
*{climb_error}*: Vertical speed uncertainty, meters/sec. Can be NaN.
*{satellites_visible}*: Number of satellites visible from the GPS receiver.
*{satellites_used}*: Number of satellites used for the GPS fix.
# EXAMPLES
```
"gps": {
"format": "{mode}",
"format-disabled": "", // an empty format will hide the module
"format-no-fix": "No fix",
"format-fix-3d": "{status}",
"tooltip-format": "{mode}",
"tooltip-format-no-fix": "{satellites_visible} satellites visible",
"tooltip-format-fix-2d": "{satellites_used}/{satellites_visible} satellites used",
"tooltip-format-fix-3d": "Altitude: {altitude_hae}m",
"hide-disconnected": false
}
```
# STYLE
- *#gps*
- *#gps.disabled* Applied when GPS is disabled.
- *#gps.fix-none* Applied when GPS is present, but there is no fix.
- *#gps.fix-2d* Applied when there is a 2D fix.
- *#gps.fix-3d* Applied when there is a 3D fix.
+3 -3
View File
@@ -59,9 +59,9 @@ Addressed by *hyprland/language*
``` ```
"hyprland/language": { "hyprland/language": {
"format": "Lang: {long}" "format": "Lang: {long}",
"format-en": "AMERICA, HELL YEAH!" "format-en": "AMERICA, HELL YEAH!",
"format-tr": "As bayrakları" "format-tr": "As bayrakları",
"keyboard-name": "at-translated-set-2-keyboard" "keyboard-name": "at-translated-set-2-keyboard"
} }
``` ```
+46
View File
@@ -0,0 +1,46 @@
waybar-hyprland-windowcount(5)
# NAME
waybar - hyprland window count module
# DESCRIPTION
The *windowcount* module displays the number of windows in the current Hyprland workspace.
# CONFIGURATION
Addressed by *hyprland/windowcount*
*format*: ++
typeof: string ++
default: {} ++
The format for how information should be displayed. On {} the current workspace window count is displayed.
*format-empty*: ++
typeof: string ++
Override the format when the workspace contains no windows window
*format-windowed*: ++
typeof: string ++
Override the format when the workspace contains no fullscreen windows
*format-fullscreen*: ++
typeof: string ++
Override the format when the workspace contains a fullscreen window
*separate-outputs*: ++
typeof: bool ++
default: true ++
Show the active workspace window count of the monitor the bar belongs to, instead of the focused workspace.
# STYLE
- *#windowcount*
The following classes are applied to the entire Waybar rather than just the
windowcount widget:
- *window#waybar.empty* When no windows are in the workspace
- *window#waybar.fullscreen* When there is a fullscreen window in the workspace;
useful with Hyprland's *fullscreen, 1* mode
+73 -4
View File
@@ -26,17 +26,77 @@ Addressed by *hyprland/workspaces*
Regex rules to map window class to an icon or preferred method of representation for a workspace's window. Regex rules to map window class to an icon or preferred method of representation for a workspace's window.
Keys are the rules, while the values are the methods of representation. Values may use the placeholders {class} and {title} to use the window's original class and/or title respectively. Keys are the rules, while the values are the methods of representation. Values may use the placeholders {class} and {title} to use the window's original class and/or title respectively.
Rules may specify `class<...>`, `title<...>`, or both in order to fine-tune the matching. Rules may specify `class<...>`, `title<...>`, or both in order to fine-tune the matching.
You may assign an empty value to a rule to have it ignored from generating any representation in workspaces. You may assign an empty value to a rule to have it ignored from generating any representation in workspaces. ++
This setting is ignored if *workspace-taskbar.enable* is set to true.
*window-rewrite-default*: *window-rewrite-default*: ++
typeof: string ++ typeof: string ++
default: "?" ++ default: "?" ++
The default method of representation for a workspace's window. This will be used for windows whose classes do not match any of the rules in *window-rewrite*. The default method of representation for a workspace's window. This will be used for windows whose classes do not match any of the rules in *window-rewrite*. ++
This setting is ignored if *workspace-taskbar.enable* is set to true.
*format-window-separator*: ++ *format-window-separator*: ++
typeof: string ++ typeof: string ++
default: " " ++ default: " " ++
The separator to be used between windows in a workspace. The separator to be used between windows in a workspace. ++
This setting is ignored if *workspace-taskbar.enable* is set to true.
*workspace-taskbar*: ++
typeof: object ++
Contains settings for the workspace taskbar, an alternative mode for the workspaces module which displays the window icons as images instead of text.
*enable*: ++
typeof: bool ++
default: false ++
Enables the workspace taskbar mode.
*update-active-window*: ++
typeof: bool ++
default: false ++
If true, the active/focused window will have an 'active' class. Could cause higher CPU usage due to more frequent redraws.
*reverse-direction*: ++
typeof: bool ++
default: false ++
If true, the taskbar windows will be added in reverse order (right to left if orientation is horizontal, bottom to top if vertical).
*active-window-position*: ++
typeof: "none" | "first" | "last" ++
default: "none" ++
If set to "first", the active window will be moved at the beginning of the taskbar. If set to "last", it will be moved at the end. It will only work if *update-active-window* is set to true.
*format*: ++
typeof: string ++
default: {icon} ++
Format to use for each window in the workspace taskbar. Available placeholders are {icon} and {title}.
*icon-size*: ++
typeof: int ++
default: 16 ++
Size of the icons in the workspace taskbar.
*icon-theme*: ++
typeof: string | array ++
default: [] ++
Icon theme to use for the workspace taskbar. If an array is provided, the first theme that is found for a given icon will be used. If no theme is found (or the array is empty), the default icon theme is used.
*orientation*: ++
typeof: "horizontal" | "vertical" ++
default: horizontal ++
Direction in which the workspace taskbar is displayed.
*ignore-list*: ++
typeof: array ++
default: [] ++
Regex patterns to match against window class or window title. If a window's class OR title matches any of the patterns, it will not be shown.
*on-click-window*: ++
typeof: string ++
default: "" ++
Command to run when a window is clicked. Available placeholders are: ++
- {address} Hyprland address of the clicked window. ++
- {button} Pressed button number, see https://api.gtkd.org/gdk.c.types.GdkEventButton.button.html. ++
See https://github.com/Alexays/Waybar/wiki/Module:-Hyprland#workspace-taskbars-example for a full example.
*show-special*: ++ *show-special*: ++
typeof: bool ++ typeof: bool ++
@@ -48,6 +108,11 @@ Addressed by *hyprland/workspaces*
default: false ++ default: false ++
If this and show-special are to true, special workspaces will be shown only if visible. If this and show-special are to true, special workspaces will be shown only if visible.
*persistent-only*: ++
typeof: bool ++
default: false ++
If set to true, only persistent workspaces will be shown on bar.
*all-outputs*: ++ *all-outputs*: ++
typeof: bool ++ typeof: bool ++
default: false ++ default: false ++
@@ -76,6 +141,7 @@ Addressed by *hyprland/workspaces*
If set to number, workspaces will sort by number. If set to number, workspaces will sort by number.
If set to name, workspaces will sort by name. If set to name, workspaces will sort by name.
If set to id, workspaces will sort by id. If set to id, workspaces will sort by id.
If set to special-centered, workspaces will sort by default with special workspaces in the center.
If none of those, workspaces will sort with default behavior. If none of those, workspaces will sort with default behavior.
*expand*: ++ *expand*: ++
@@ -178,3 +244,6 @@ Additional to workspace name matching, the following *format-icons* can be set.
- *#workspaces button.special* - *#workspaces button.special*
- *#workspaces button.urgent* - *#workspaces button.urgent*
- *#workspaces button.hosting-monitor* (gets applied if workspace-monitor == waybar-monitor) - *#workspaces button.hosting-monitor* (gets applied if workspace-monitor == waybar-monitor)
- *#workspaces .workspace-label*
- *#workspaces .taskbar-window* (each window in the taskbar, only if 'workspace-taskbar.enable' is true)
- *#workspaces .taskbar-window.active* (applied to the focused window, only if 'workspace-taskbar.update-active-window' is true)
+6
View File
@@ -125,3 +125,9 @@ screensaver, also known as "presentation mode".
"timeout": 30.5 "timeout": 30.5
} }
``` ```
# STYLE
- *#idle_inhibitor*
- *#idle_inhibitor.activated*
- *#idle_inhibitor.deactivated*
+2 -1
View File
@@ -24,8 +24,9 @@ The *image* module displays an image from a path.
The width/height to render the image. The width/height to render the image.
*interval*: ++ *interval*: ++
typeof: integer ++ typeof: integer or float ++
The interval (in seconds) to re-render the image. ++ The interval (in seconds) to re-render the image. ++
Minimum value is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++
This is useful if the contents of *path* changes. ++ This is useful if the contents of *path* changes. ++
If no *interval* is defined, the image will only be rendered once. If no *interval* is defined, the image will only be rendered once.
+1 -1
View File
@@ -45,7 +45,7 @@ Addressed by *jack*
The format of information displayed in the tooltip. The format of information displayed in the tooltip.
*interval*: ++ *interval*: ++
typeof: integer ++ typeof: integer or float ++
default: 1 ++ default: 1 ++
The interval in which the information gets polled. The interval in which the information gets polled.
+2
View File
@@ -120,6 +120,8 @@ Addressed by *memory*
*{swapAvail}*: Amount of available swap in GiB. *{swapAvail}*: Amount of available swap in GiB.
*{swapState}*: Signals if swap is activated or not
# EXAMPLES # EXAMPLES
``` ```
+26 -26
View File
@@ -7,7 +7,7 @@ waybar - menu property
# OVERVIEW # OVERVIEW
Some modules support a 'menu', which allows to have a popup menu whan a defined Some modules support a 'menu', which allows to have a popup menu when a defined
click is done over the module. click is done over the module.
# PROPERTIES # PROPERTIES
@@ -87,15 +87,15 @@ Module config :
``` ```
"custom/power": { "custom/power": {
"format" : "⏻ ", "format" : "⏻ ",
"tooltip": false, "tooltip": false,
"menu": "on-click", "menu": "on-click",
"menu-file": "~/.config/waybar/power_menu.xml", "menu-file": "~/.config/waybar/power_menu.xml",
"menu-actions": { "menu-actions": {
"shutdown": "shutdown", "shutdown": "shutdown",
"reboot": "reboot", "reboot": "reboot",
"suspend": "systemctl suspend", "suspend": "systemctl suspend",
"hibernate": "systemctl hibernate", "hibernate": "systemctl hibernate",
}, },
}, },
``` ```
@@ -104,28 +104,28 @@ Module config :
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<interface> <interface>
<object class="GtkMenu" id="menu"> <object class="GtkMenu" id="menu">
<child> <child>
<object class="GtkMenuItem" id="suspend"> <object class="GtkMenuItem" id="suspend">
<property name="label">Suspend</property> <property name="label">Suspend</property>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkMenuItem" id="hibernat"> <object class="GtkMenuItem" id="hibernate">
<property name="label">Hibernate</property> <property name="label">Hibernate</property>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkMenuItem" id="shutdown"> <object class="GtkMenuItem" id="shutdown">
<property name="label">Shutdown</property> <property name="label">Shutdown</property>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkSeparatorMenuItem" id="delimiter1"/> <object class="GtkSeparatorMenuItem" id="delimiter1"/>
</child> </child>
<child> <child>
<object class="GtkMenuItem" id="reboot"> <object class="GtkMenuItem" id="reboot">
<property name="label">Reboot</property> <property name="label">Reboot</property>
</object> </object>
</child> </child>
</object> </object>
</interface> </interface>
+4
View File
@@ -204,6 +204,10 @@ Addressed by *mpd*
*{queueLength}*: The length of the current queue. *{queueLength}*: The length of the current queue.
*{uri}*: The URI of the song relative to the MPD music directory.
*{filename}* The last part of the URI.
*{stateIcon}*: The icon corresponding to the playing or paused status of the player (see *state-icons* option) *{stateIcon}*: The icon corresponding to the playing or paused status of the player (see *state-icons* option)
*{consumeIcon}*: The icon corresponding the "consume" option (see *consume-icons* option) *{consumeIcon}*: The icon corresponding the "consume" option (see *consume-icons* option)
+15 -6
View File
@@ -16,6 +16,11 @@ Addressed by *network*
typeof: string ++ typeof: string ++
Use the defined interface instead of auto-detection. Accepts wildcard. Use the defined interface instead of auto-detection. Accepts wildcard.
*rfkill*: ++
typeof: bool ++
default: true ++
If enabled, the *disabled* format will be used when rfkill is blocking wlan interfaces.
*interval*: ++ *interval*: ++
typeof: integer ++ typeof: integer ++
default: 60 ++ default: 60 ++
@@ -24,7 +29,7 @@ Addressed by *network*
*family*: ++ *family*: ++
typeof: string ++ typeof: string ++
default: *ipv4* ++ default: *ipv4* ++
The address family that is used for the format replacement {ipaddr} and to determine if a network connection is present. The address family that is used for the format replacement {ipaddr} and to determine if a network connection is present. Set it to ipv4_6 to display both.
*format*: ++ *format*: ++
typeof: string ++ typeof: string ++
@@ -49,7 +54,7 @@ Addressed by *network*
*format-disabled*: ++ *format-disabled*: ++
typeof: string ++ typeof: string ++
This format is used when the displayed interface is disabled. This format is used when rfkill is blocking wlan interfaces.
*format-icons*: ++ *format-icons*: ++
typeof: array/object ++ typeof: array/object ++
@@ -127,7 +132,7 @@ Addressed by *network*
*tooltip-format-disabled*: ++ *tooltip-format-disabled*: ++
typeof: string ++ typeof: string ++
This format is used when the displayed interface is disabled. This format is used when rfkill is blocking wlan interfaces.
*menu*: ++ *menu*: ++
typeof: string ++ typeof: string ++
@@ -155,9 +160,13 @@ Addressed by *network*
*{gwaddr}*: The default gateway for the interface *{gwaddr}*: The default gateway for the interface
*{netmask}*: The subnetmask corresponding to the IP. *{netmask}*: The subnetmask corresponding to the IP(V4).
*{cidr}*: The subnetmask corresponding to the IP in CIDR notation. *{netmask6}*: The subnetmask corresponding to the IP(V6).
*{cidr}*: The subnetmask corresponding to the IP(V4) in CIDR notation.
*{cidr6}*: The subnetmask corresponding to the IP(V6) in CIDR notation.
*{essid}*: Name (SSID) of the wireless network. *{essid}*: Name (SSID) of the wireless network.
@@ -167,7 +176,7 @@ Addressed by *network*
*{signaldBm}*: Signal strength of the wireless network in dBm. *{signaldBm}*: Signal strength of the wireless network in dBm.
*{frequency}*: Frequency of the wireless network in MHz. *{frequency}*: Frequency of the wireless network in GHz.
*{bandwidthUpBits}*: Instant up speed in bits/seconds. *{bandwidthUpBits}*: Instant up speed in bits/seconds.
+11 -2
View File
@@ -52,8 +52,8 @@ Addressed by *niri/language*
``` ```
"niri/language": { "niri/language": {
"format": "Lang: {long}" "format": "Lang: {long}",
"format-en": "AMERICA, HELL YEAH!" "format-en": "AMERICA, HELL YEAH!",
"format-tr": "As bayrakları" "format-tr": "As bayrakları"
} }
``` ```
@@ -61,3 +61,12 @@ Addressed by *niri/language*
# STYLE # STYLE
- *#language* - *#language*
Additionally, a CSS class matching the current layout's short name is added to the widget. This
allows per-language styling, for example:
```
#language.us { color: #00ff00; }
#language.de { color: #ff0000; }
#language.fr { color: #0000ff; }
```
+3
View File
@@ -70,6 +70,8 @@ Additional to workspace name matching, the following *format-icons* can be set.
- *default*: Will be shown, when no string matches are found. - *default*: Will be shown, when no string matches are found.
- *focused*: Will be shown, when workspace is focused. - *focused*: Will be shown, when workspace is focused.
- *active*: Will be shown, when workspace is active on its output. - *active*: Will be shown, when workspace is active on its output.
- *urgent*: Will be shown, when workspace has urgent windows.
- *empty*: Will be shown, when workspace is empty.
# EXAMPLES # EXAMPLES
@@ -95,6 +97,7 @@ Additional to workspace name matching, the following *format-icons* can be set.
- *#workspaces button* - *#workspaces button*
- *#workspaces button.focused*: The single focused workspace. - *#workspaces button.focused*: The single focused workspace.
- *#workspaces button.active*: The workspace is active (visible) on its output. - *#workspaces button.active*: The workspace is active (visible) on its output.
- *#workspaces button.urgent*: The workspace has one or more urgent windows.
- *#workspaces button.empty*: The workspace is empty. - *#workspaces button.empty*: The workspace is empty.
- *#workspaces button.current_output*: The workspace is from the same output as - *#workspaces button.current_output*: The workspace is from the same output as
the bar that it is displayed on. the bar that it is displayed on.
+30
View File
@@ -37,6 +37,17 @@ the screen or playing audio.
default: false ++ default: false ++
Enables this module to consume all left over space dynamically. Enables this module to consume all left over space dynamically.
*ignore-monitor* ++
typeof: bool ++
default: true ++
Ignore streams with *stream.monitor* property.
*ignore* ++
typeof: array of objects ++
default: [] ++
Additional streams to be ignored. See *IGNORE CONFIGURATION* for++
more information.
# MODULES CONFIGURATION # MODULES CONFIGURATION
*type*: ++ *type*: ++
@@ -54,6 +65,14 @@ the screen or playing audio.
default: 24 ++ default: 24 ++
The size of each icon in the tooltip. The size of each icon in the tooltip.
# IGNORE CONFIGURATION
*type*: ++
typeof: string
*name*: ++
typeof: string
# EXAMPLES # EXAMPLES
``` ```
@@ -77,6 +96,17 @@ the screen or playing audio.
"tooltip": true, "tooltip": true,
"tooltip-icon-size": 24 "tooltip-icon-size": 24
} }
],
"ignore-monitor": true,
"ignore": [
{
"type": "audio-in",
"name": "cava"
},
{
"type": "screenshare",
"name": "obs"
}
] ]
}, },
``` ```
+2 -2
View File
@@ -77,12 +77,12 @@ The slider is a component with multiple CSS Nodes, of which the following are ex
min-height: 80px; min-height: 80px;
min-width: 10px; min-width: 10px;
border-radius: 5px; border-radius: 5px;
background-color: black; background: black;
} }
#pulseaudio-slider highlight { #pulseaudio-slider highlight {
min-width: 10px; min-width: 10px;
border-radius: 5px; border-radius: 5px;
background-color: green; background: green;
} }
``` ```
+1
View File
@@ -83,6 +83,7 @@ Addressed by *river/layout*
- *#layout* - *#layout*
- *#layout.focused* Applied when the output this module's bar belongs to is focused. - *#layout.focused* Applied when the output this module's bar belongs to is focused.
- *#layout.<layout>* Applied when the output this module's bar belongs uses this layout.
# SEE ALSO # SEE ALSO
+5
View File
@@ -31,6 +31,11 @@ Addressed by *river/tags*
default: false ++ default: false ++
Enables this module to consume all left over space dynamically. Enables this module to consume all left over space dynamically.
*hide-vacant*: ++
typeof: bool ++
default: false ++
Only show relevant tags: tags that are either focused or have a window on them.
# EXAMPLE # EXAMPLE
``` ```
+7
View File
@@ -89,6 +89,11 @@ Addressed by *sway/window*
default: false ++ default: false ++
If the workspace itself is focused and the workspace contains nodes or floating_nodes, show the workspace name. If not set, text remains empty but styles according to nodes in the workspace are still applied. If the workspace itself is focused and the workspace contains nodes or floating_nodes, show the workspace name. If not set, text remains empty but styles according to nodes in the workspace are still applied.
*show-hidden-marks*: ++
typeof: bool ++
default: false ++
For the *{marks}* format replacement, include hidden marks that start with an underscore.
*rewrite*: ++ *rewrite*: ++
typeof: object ++ typeof: object ++
Rules to rewrite the module format output. See *rewrite rules*. Rules to rewrite the module format output. See *rewrite rules*.
@@ -117,6 +122,8 @@ Addressed by *sway/window*
*{shell}*: The shell of the focused window. It's 'xwayland' when the window is *{shell}*: The shell of the focused window. It's 'xwayland' when the window is
running through xwayland, otherwise, it's 'xdg-shell'. running through xwayland, otherwise, it's 'xdg-shell'.
*{marks}*: Marks of the window.
# REWRITE RULES # REWRITE RULES
*rewrite* is an object where keys are regular expressions and values are *rewrite* is an object where keys are regular expressions and values are
+5
View File
@@ -31,6 +31,11 @@ Addressed by *sway/workspaces*
default: false ++ default: false ++
If set to false, you can scroll to cycle through workspaces. If set to true this behaviour is disabled. If set to false, you can scroll to cycle through workspaces. If set to true this behaviour is disabled.
*reverse-scroll*: ++
typeof: bool ++
default: false ++
If set to false, scrolling up will switch to the previous workspace and scrolling down will switch to the next workspace. If set to true, the behavior will be reversed.
*disable-click*: ++ *disable-click*: ++
typeof: bool ++ typeof: bool ++
default: false ++ default: false ++
+6
View File
@@ -62,6 +62,12 @@ Addressed by *systemd-failed-units*
*{nr_failed}*: Number of total failed units. *{nr_failed}*: Number of total failed units.
*{systemd_state}:* State of the systemd system session
*{user_state}:* State of the systemd user session
*{overall_state}:* Overall state of the systemd and user session. ("Ok" or "Degraded")
# EXAMPLES # EXAMPLES
``` ```
+2 -1
View File
@@ -40,7 +40,7 @@ Addressed by *temperature*
The threshold before it is considered critical (Celsius). The threshold before it is considered critical (Celsius).
*interval*: ++ *interval*: ++
typeof: integer ++ typeof: integer or float ++
default: 10 ++ default: 10 ++
The interval in which the information gets polled. The interval in which the information gets polled.
@@ -160,4 +160,5 @@ Addressed by *temperature*
# STYLE # STYLE
- *#temperature* - *#temperature*
- *#temperature.warning*
- *#temperature.critical* - *#temperature.critical*
+5 -1
View File
@@ -47,7 +47,11 @@ Addressed by *tray*
``` ```
"tray": { "tray": {
"icon-size": 21, "icon-size": 21,
"spacing": 10 "spacing": 10,
"icons": {
"blueman": "bluetooth",
"TelegramDesktop": "$HOME/.local/share/icons/hicolor/16x16/apps/telegram.png"
}
} }
``` ```
+82
View File
@@ -0,0 +1,82 @@
waybar-wayfire-window(5)
# NAME
waybar - wayfire window module
# DESCRIPTION
The *window* module displays the title of the currently focused window in wayfire.
# CONFIGURATION
Addressed by *wayfire/window*
*format*: ++
typeof: string ++
default: {title} ++
The format, how information should be displayed. On {} the current window title is displayed.
*rewrite*: ++
typeof: object ++
Rules to rewrite window title. 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.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS
See the output of "wayfire msg windows" for examples
*{title}*: The current title of the focused window.
*{app_id}*: The current app ID 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 title is left unchanged.
Invalid expressions (e.g., mismatched parentheses) are skipped.
# EXAMPLES
```
"wayfire/window": {
"format": "{}",
"rewrite": {
"(.*) - Mozilla Firefox": "🌎 $1",
"(.*) - zsh": "> [$1]"
}
}
```
# STYLE
- *#window*
- *window#waybar.empty #window* When no windows are on the workspace
The following classes are applied to the entire Waybar rather than just the
window widget:
- *window#waybar.empty* When no windows are in the workspace
- *window#waybar.solo* When only one window is on the workspace
- *window#waybar.<app-id>* Where *app-id* is the app ID of the only window on
the workspace
+86
View File
@@ -0,0 +1,86 @@
waybar-wayfire-workspaces(5)
# NAME
waybar - wayfire workspaces module
# DESCRIPTION
The *workspaces* module displays the currently used workspaces in wayfire.
# CONFIGURATION
Addressed by *wayfire/workspaces*
*format*: ++
typeof: string ++
default: {value} ++
The format, how information should be displayed.
*format-icons*: ++
typeof: array ++
Based on the workspace name, index and state, the corresponding icon gets selected. See *icons*.
*disable-click*: ++
typeof: bool ++
default: false ++
If set to false, you can click to change workspace. If set to true this behaviour is disabled.
*disable-markup*: ++
typeof: bool ++
default: false ++
If set to true, button label will escape pango markup.
*current-only*: ++
typeof: bool ++
default: false ++
If set to true, only the active or focused workspace will be shown.
*on-update*: ++
typeof: string ++
Command to execute when the module is updated.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS
*{icon}*: Icon, as defined in *format-icons*.
*{index}*: Index of the workspace on its output.
*{output}*: Output where the workspace is located.
# ICONS
Additional to workspace name matching, the following *format-icons* can be set.
- *default*: Will be shown, when no string matches are found.
- *focused*: Will be shown, when workspace is focused.
# EXAMPLES
```
"wayfire/workspaces": {
"format": "{icon}",
"format-icons": {
"1": "",
"2": "",
"3": "",
"4": "",
"5": "",
"focused": "",
"default": ""
}
}
```
# Style
- *#workspaces button*
- *#workspaces button.focused*: The single focused workspace.
- *#workspaces button.empty*: The workspace is empty.
- *#workspaces button.current_output*: The workspace is from the same output as
the bar that it is displayed on.
+27
View File
@@ -19,6 +19,11 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
typeof: string ++ typeof: string ++
This format is used when the sound is muted. This format is used when the sound is muted.
*node-type*: ++
typeof: string ++
default: *Audio/Sink* ++
The WirePlumber node type to attach to. Use *Audio/Source* to manage microphones etc.
*tooltip*: ++ *tooltip*: ++
typeof: bool ++ typeof: bool ++
default: *true* ++ default: *true* ++
@@ -108,6 +113,8 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
# EXAMPLES # EXAMPLES
## Basic:
``` ```
"wireplumber": { "wireplumber": {
"format": "{volume}%", "format": "{volume}%",
@@ -116,6 +123,26 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
} }
``` ```
## Separate Sink and Source Widgets
```
"wireplumber#sink": {
"format": "{volume}% {icon}",
"format-muted": "",
"format-icons": ["", "", ""],
"on-click": "helvum",
"on-click-right": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
"scroll-step": 5
},
"wireplumber#source": {
"node-type": "Audio/Source",
"format": "{volume}% ",
"format-muted": "",
"on-click-right": "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle",
"scroll-step": 5
}
```
# STYLE # STYLE
- *#wireplumber* - *#wireplumber*
+51 -4
View File
@@ -86,7 +86,7 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(
*no-center* ++ *no-center* ++
typeof: bool ++ typeof: bool ++
default: false ++ default: false ++
Option to disable the center modules fully usefull together with expand-\*. Option to disable the center modules fully useful together with expand-\*.
*spacing* ++ *spacing* ++
typeof: integer ++ typeof: integer ++
@@ -151,6 +151,20 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(
default: *false* ++ default: *false* ++
Option to enable reloading the css style if a modification is detected on the style sheet file or any imported css files. Option to enable reloading the css style if a modification is detected on the style sheet file or any imported css files.
*on-sigusr1* ++
typeof: string ++
default: *toggle* ++
Action that is performed when receiving SIGUSR1 kill signal. ++
Possible values: *show*, *hide*, *toggle*, *reload*, *noop*. ++
Default value: *toggle*.
*on-sigusr2* ++
typeof: string ++
default: *reload* ++
Action that is performed when receiving SIGUSR2 kill signal. ++
Possible values: *show*, *hide*, *toggle*, *reload*, *noop*. ++
Default value: *reload*.
# MODULE FORMAT # MODULE FORMAT
You can use PangoMarkupFormat (See https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat). You can use PangoMarkupFormat (See https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat).
@@ -206,14 +220,36 @@ A minimal *config* file could look like this:
Waybar accepts the following signals: Waybar accepts the following signals:
*SIGUSR1* *SIGUSR1*
Toggles the bar visibility (hides if shown, shows if hidden) By default toggles the bar visibility (hides if shown, shows if hidden)
*SIGUSR2* *SIGUSR2*
Reloads (resets) the bar By default reloads (resets) the bar
*SIGINT* *SIGINT*
Quits the bar Quits the bar
For example, to toggle the bar programmatically, you can invoke `killall -SIGUSR1 waybar`. For example, to toggle the bar programmatically, you can invoke `killall -SIGUSR1 waybar`.
## User signal configuration
Config parameters *on-sigusr1* and *on-sigusr2* change what happens when bars receive
*SIGUSR1* and *SIGUSR2* signals.
This means that commands `killall -SIGUSR1 waybar` and `killall -SIGUSR2 waybar`
can perform user-configured action.
It also means that if an external script has the PID of the bar then it can
perform more complex `show`/`hide`/`reload` logic for each instance of Waybar.
One can find the PID e.g. by doing `pgrep -a waybar` which could then match
by config name or other parameters.
## Kill parameter meanings
*show* Switches state to visible (per bar).
*hide* Switches state to hidden (per bar).
*toggle* Switches state between visible and hidden (per bar).
*reload* Reloads all waybars of current waybar process (basically equivalent to
restarting with updated config which sets initial visibility values).
*noop* Does nothing when the kill signal is received.
# MULTI OUTPUT CONFIGURATION # MULTI OUTPUT CONFIGURATION
## Limit a configuration to some outputs ## Limit a configuration to some outputs
@@ -272,6 +308,17 @@ When positioning Waybar on the left or right side of the screen, sometimes it's
Valid options for the "rotate" property are: 0, 90, 180, and 270. Valid options for the "rotate" property are: 0, 90, 180, and 270.
## Swapping icon and label
If a module displays both a label and an icon, it might be desirable to swap them (for instance, for panels on the left or right of the screen, or for user adopting a right-to-left script). This can be achieved with the "swap-icon-label" property, taking a boolean. Example:
```
{
"sway/window": {
"swap-icon-label": true
}
}
```
## Grouping modules ## Grouping modules
Module groups allow stacking modules in any direction. By default, when the bar is positioned on the top or bottom of the screen, modules in a group are stacked vertically. Likewise, when positioned on the left or right, modules in a group are stacked horizontally. This can be changed with the "orientation" property. Module groups allow stacking modules in any direction. By default, when the bar is positioned on the top or bottom of the screen, modules in a group are stacked vertically. Likewise, when positioned on the left or right, modules in a group are stacked horizontally. This can be changed with the "orientation" property.
@@ -390,4 +437,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)" *waybar-styles(5)*
+39 -16
View File
@@ -1,6 +1,6 @@
project( project(
'waybar', 'cpp', 'c', 'waybar', 'cpp', 'c',
version: '0.11.0', version: '0.14.0',
license: 'MIT', license: 'MIT',
meson_version: '>= 0.59.0', meson_version: '>= 0.59.0',
default_options : [ default_options : [
@@ -69,7 +69,7 @@ is_openbsd = host_machine.system() == 'openbsd'
thread_dep = dependency('threads') thread_dep = dependency('threads')
fmt = dependency('fmt', version : ['>=8.1.1'], fallback : ['fmt', 'fmt_dep']) fmt = dependency('fmt', version : ['>=8.1.1'], fallback : ['fmt', 'fmt_dep'])
spdlog = dependency('spdlog', version : ['>=1.10.0'], fallback : ['spdlog', 'spdlog_dep'], default_options : ['external_fmt=enabled', 'std_format=disabled', 'tests=disabled']) spdlog = dependency('spdlog', version : ['>=1.15.2'], fallback : ['spdlog', 'spdlog_dep'], default_options : ['std_format=disabled', 'tests=disabled'])
wayland_client = dependency('wayland-client') wayland_client = dependency('wayland-client')
wayland_cursor = dependency('wayland-cursor') wayland_cursor = dependency('wayland-cursor')
wayland_protos = dependency('wayland-protocols') wayland_protos = dependency('wayland-protocols')
@@ -93,6 +93,7 @@ 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.5', required: get_option('wireplumber')) libwireplumber = dependency('wireplumber-0.5', required: get_option('wireplumber'))
libgps = dependency('libgps', required: get_option('gps'))
libsndio = compiler.find_library('sndio', required: get_option('sndio')) libsndio = compiler.find_library('sndio', required: get_option('sndio'))
if libsndio.found() if libsndio.found()
@@ -182,6 +183,7 @@ src_files = files(
'src/util/sanitize_str.cpp', 'src/util/sanitize_str.cpp',
'src/util/rewrite_string.cpp', 'src/util/rewrite_string.cpp',
'src/util/gtk_icon.cpp', 'src/util/gtk_icon.cpp',
'src/util/icon_loader.cpp',
'src/util/regex_collection.cpp', 'src/util/regex_collection.cpp',
'src/util/css_reload_helper.cpp' 'src/util/css_reload_helper.cpp'
) )
@@ -275,6 +277,17 @@ if true
man_files += files('man/waybar-wlr-taskbar.5.scd') man_files += files('man/waybar-wlr-taskbar.5.scd')
endif endif
if wayland_protos.version().version_compare('>=1.39')
add_project_arguments('-DHAVE_EXT_WORKSPACES', language: 'cpp')
src_files += files(
'src/modules/ext/workspace_manager.cpp',
'src/modules/ext/workspace_manager_binding.cpp',
)
man_files += files(
'man/waybar-ext-workspaces.5.scd',
)
endif
if true if true
add_project_arguments('-DHAVE_RIVER', language: 'cpp') add_project_arguments('-DHAVE_RIVER', language: 'cpp')
src_files += files( src_files += files(
@@ -306,6 +319,7 @@ 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/windowcount.cpp',
'src/modules/hyprland/workspace.cpp', 'src/modules/hyprland/workspace.cpp',
'src/modules/hyprland/workspaces.cpp', 'src/modules/hyprland/workspaces.cpp',
'src/modules/hyprland/windowcreationpayload.cpp', 'src/modules/hyprland/windowcreationpayload.cpp',
@@ -333,6 +347,19 @@ if get_option('niri')
) )
endif endif
if true
add_project_arguments('-DHAVE_WAYFIRE', language: 'cpp')
src_files += files(
'src/modules/wayfire/backend.cpp',
'src/modules/wayfire/window.cpp',
'src/modules/wayfire/workspaces.cpp',
)
endif
if get_option('login-proxy')
add_project_arguments('-DHAVE_LOGIN_PROXY', language: 'cpp')
endif
if libnl.found() and libnlgen.found() if libnl.found() and libnlgen.found()
add_project_arguments('-DHAVE_LIBNL', language: 'cpp') add_project_arguments('-DHAVE_LIBNL', language: 'cpp')
src_files += files('src/modules/network.cpp') src_files += files('src/modules/network.cpp')
@@ -470,29 +497,24 @@ else
man_files += files('man/waybar-clock.5.scd') man_files += files('man/waybar-clock.5.scd')
endif endif
if get_option('experimental')
add_project_arguments('-DHAVE_WLR_WORKSPACES', language: 'cpp')
src_files += files(
'src/modules/wlr/workspace_manager.cpp',
'src/modules/wlr/workspace_manager_binding.cpp',
)
man_files += files(
'man/waybar-wlr-workspaces.5.scd',
)
endif
cava = dependency('cava', cava = dependency('cava',
version : '>=0.10.3', version : '>=0.10.6',
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')
if cava.found() if cava.found()
add_project_arguments('-DHAVE_LIBCAVA', language: 'cpp') add_project_arguments('-DHAVE_LIBCAVA', language: 'cpp')
src_files += files('src/modules/cava.cpp') src_files += files('src/modules/cava/cava.cpp', 'src/modules/cava/cava_backend.cpp')
man_files += files('man/waybar-cava.5.scd') man_files += files('man/waybar-cava.5.scd')
endif endif
if libgps.found()
add_project_arguments('-DHAVE_LIBGPS', language: 'cpp')
src_files += files('src/modules/gps.cpp')
man_files += files('man/waybar-gps.5.scd')
endif
subdir('protocol') subdir('protocol')
app_resources = [] app_resources = []
@@ -531,7 +553,8 @@ executable(
libsndio, libsndio,
tz_dep, tz_dep,
xkbregistry, xkbregistry,
cava cava,
libgps
], ],
include_directories: inc_dirs, include_directories: inc_dirs,
install: true, install: true,
+2
View File
@@ -20,3 +20,5 @@ option('jack', type: 'feature', value: 'auto', description: 'Enable support for
option('wireplumber', type: 'feature', value: 'auto', description: 'Enable support for WirePlumber') option('wireplumber', type: 'feature', value: 'auto', description: 'Enable support for WirePlumber')
option('cava', type: 'feature', value: 'auto', description: 'Enable support for Cava') option('cava', type: 'feature', value: 'auto', description: 'Enable support for Cava')
option('niri', type: 'boolean', description: 'Enable support for niri') option('niri', type: 'boolean', description: 'Enable support for niri')
option('login-proxy', type: 'boolean', description: 'Enable interfacing with dbus login interface')
option('gps', type: 'feature', value: 'auto', description: 'Enable support for gps')
+32 -28
View File
@@ -1,42 +1,46 @@
{ lib {
, pkgs lib,
, waybar pkgs,
, version waybar,
version,
}: }:
let let
libcava = rec { libcava = {
version = "0.10.3";
src = pkgs.fetchFromGitHub { src = pkgs.fetchFromGitHub {
owner = "LukashonakV"; owner = "LukashonakV";
repo = "cava"; repo = "cava";
rev = version; # NOTE: Needs to match the cava.wrap
hash = "sha256-ZDFbI69ECsUTjbhlw2kHRufZbQMu+FQSMmncCJ5pagg="; rev = "23efcced43b5a395747b18a2e5f2171fc0925d18";
hash = "sha256-CNspaoK5KuME0GfaNijpC24BfALngzNi04/VNwPqMvo=";
}; };
}; };
in in
(waybar.overrideAttrs ( waybar.overrideAttrs (oldAttrs: {
oldAttrs: { inherit version;
inherit version;
src = lib.cleanSourceWith { src = lib.cleanSourceWith {
filter = name: type: type != "regular" || !lib.hasSuffix ".nix" name; filter = name: type: type != "regular" || !lib.hasSuffix ".nix" name;
src = lib.cleanSource ../.; src = lib.cleanSource ../.;
}; };
mesonFlags = lib.remove "-Dgtk-layer-shell=enabled" oldAttrs.mesonFlags; mesonFlags = lib.remove "-Dgtk-layer-shell=enabled" oldAttrs.mesonFlags;
# downstream patch should not affect upstream # downstream patch should not affect upstream
patches = []; patches = [ ];
# nixpkgs checks version, no need when building locally
nativeInstallCheckInputs = [ ];
buildInputs = (builtins.filter (p: p.pname != "wireplumber") oldAttrs.buildInputs) ++ [ buildInputs =
pkgs.wireplumber (builtins.filter (p: p.pname != "wireplumber" && p.pname != "gps") oldAttrs.buildInputs)
++ [
pkgs.wireplumber
pkgs.gpsd
]; ];
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
patchShebangs . patchShebangs .
popd popd
''; '';
} })
))

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