Compare commits

..

No commits in common. "master" and "0.0.5" have entirely different histories.

256 changed files with 1571 additions and 29371 deletions

View File

@ -1,5 +0,0 @@
---
BasedOnStyle: Google
AlignConsecutiveDeclarations: false
ColumnLimit: 100
...

View File

@ -1,19 +0,0 @@
# EditorConfig configuration for Waybar
# http://EditorConfig.org
# Top-most EditorConfig file
root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
[*.{build,css}]
indent_style = space
indent_size = 4
[*.{hpp,cpp}]
indent_style = space
indent_size = 2

View File

@ -1 +0,0 @@
use flake

4
.github/FUNDING.yml vendored
View File

@ -1,4 +0,0 @@
# These are supported funding model platforms
github: Alexays
custom: https://paypal.me/ARouillard

View File

@ -1,29 +0,0 @@
name: freebsd
on: [ push, pull_request ]
jobs:
clang:
# Run actions in a FreeBSD VM on the macos-12 runner
# https://github.com/actions/runner/issues/385 - for FreeBSD runner support
# https://github.com/actions/virtual-environments/issues/4060 - for lack of VirtualBox on MacOS 11 runners
runs-on: macos-12
steps:
- uses: actions/checkout@v3
- name: Test in FreeBSD VM
uses: vmactions/freebsd-vm@v0
with:
mem: 2048
usesh: true
prepare: |
export CPPFLAGS=-isystem/usr/local/include LDFLAGS=-L/usr/local/lib # sndio
sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
pkg install -y git # subprojects/date
pkg install -y catch evdev-proto gtk-layer-shell gtkmm30 jsoncpp \
libdbusmenu libevdev libfmt libmpdclient libudev-devd meson \
pkgconf pulseaudio scdoc sndio spdlog wayland-protocols upower \
libinotify
run: |
meson build -Dman-pages=enabled
ninja -C build
meson test -C build --no-rebuild --print-errorlogs --suite waybar

View File

@ -1,14 +0,0 @@
name: Linter
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: DoozyX/clang-format-lint-action@v0.13
with:
source: '.'
extensions: 'h,cpp,c'
clangFormatVersion: 12

View File

@ -1,32 +0,0 @@
name: linux
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
distro:
- alpine
- archlinux
- debian
- fedora
- opensuse
- gentoo
cpp_std: [c++20]
include:
- distro: fedora
cpp_std: c++20
runs-on: ubuntu-latest
container:
image: alexays/waybar:${{ matrix.distro }}
steps:
- uses: actions/checkout@v3
- name: configure
run: meson -Dman-pages=enabled -Dcpp_std=${{matrix.cpp_std}} build
- name: build
run: ninja -C build
- name: test
run: make test

7
.gitignore vendored
View File

@ -2,12 +2,10 @@
*~
vgcore.*
/.vscode
/.idea
/.cache
*.swp
packagecache
/subprojects/**/
/build*
/subprojects/fmt-4.1.0
/build
/dist
/meson.egg-info
@ -43,4 +41,3 @@ packagecache
*.exe
*.out
*.app
/.direnv/

View File

@ -1,5 +0,0 @@
# vim: ft=Dockerfile
FROM alpine:latest
RUN apk add --no-cache git meson alpine-sdk libinput-dev wayland-dev wayland-protocols mesa-dev libxkbcommon-dev eudev-dev pixman-dev gtkmm3-dev jsoncpp-dev pugixml-dev libnl3-dev pulseaudio-dev libmpdclient-dev sndio-dev scdoc libxkbcommon tzdata playerctl-dev

View File

@ -1,7 +0,0 @@
# vim: ft=Dockerfile
FROM archlinux:base-devel
RUN pacman -Syu --noconfirm && \
pacman -S --noconfirm git meson base-devel libinput wayland wayland-protocols pixman libxkbcommon mesa gtkmm3 jsoncpp pugixml scdoc libpulse libdbusmenu-gtk3 libmpdclient gobject-introspection libxkbcommon playerctl iniparser fftw && \
sed -Ei 's/#(en_(US|GB)\.UTF)/\1/' /etc/locale.gen && locale-gen

View File

@ -1,7 +0,0 @@
# vim: ft=Dockerfile
FROM debian:sid
RUN apt-get update && \
apt-get install -y build-essential meson ninja-build git pkg-config libinput10 libpugixml-dev libinput-dev wayland-protocols libwayland-client0 libwayland-cursor0 libwayland-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev libxkbcommon-dev libudev-dev libpixman-1-dev libgtkmm-3.0-dev libjsoncpp-dev scdoc libdbusmenu-gtk3-dev libnl-3-dev libnl-genl-3-dev libpulse-dev libmpdclient-dev gobject-introspection libgirepository1.0-dev libxkbcommon-dev libxkbregistry-dev libxkbregistry0 libplayerctl-dev && \
apt-get clean

View File

@ -1,34 +0,0 @@
# vim: ft=Dockerfile
FROM fedora:latest
RUN dnf install -y @c-development \
git-core glibc-langpack-en meson scdoc \
'pkgconfig(catch2)' \
'pkgconfig(date)' \
'pkgconfig(dbusmenu-gtk3-0.4)' \
'pkgconfig(fmt)' \
'pkgconfig(gdk-pixbuf-2.0)' \
'pkgconfig(gio-unix-2.0)' \
'pkgconfig(gtk-layer-shell-0)' \
'pkgconfig(gtkmm-3.0)' \
'pkgconfig(jack)' \
'pkgconfig(jsoncpp)' \
'pkgconfig(libevdev)' \
'pkgconfig(libinput)' \
'pkgconfig(libmpdclient)' \
'pkgconfig(libnl-3.0)' \
'pkgconfig(libnl-genl-3.0)' \
'pkgconfig(libpulse)' \
'pkgconfig(libudev)' \
'pkgconfig(playerctl)' \
'pkgconfig(pugixml)' \
'pkgconfig(sigc++-2.0)' \
'pkgconfig(spdlog)' \
'pkgconfig(upower-glib)' \
'pkgconfig(wayland-client)' \
'pkgconfig(wayland-cursor)' \
'pkgconfig(wayland-protocols)' \
'pkgconfig(wireplumber-0.4)' \
'pkgconfig(xkbregistry)' && \
dnf clean all -y

View File

@ -1,11 +0,0 @@
# vim: ft=Dockerfile
FROM gentoo/stage3:latest
RUN export FEATURES="-ipc-sandbox -network-sandbox -pid-sandbox -sandbox -usersandbox" && \
emerge --sync && \
eselect news read --quiet new 1>/dev/null 2>&1 && \
emerge --verbose --update --deep --with-bdeps=y --backtrack=30 --newuse @world && \
USE="wayland gtk3 gtk -doc X pulseaudio minimal" emerge dev-vcs/git dev-libs/wayland dev-libs/wayland-protocols =dev-cpp/gtkmm-3.24.6 x11-libs/libxkbcommon \
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

View File

@ -1,9 +0,0 @@
# vim: ft=Dockerfile
FROM opensuse/tumbleweed:latest
RUN zypper -n up && \
zypper addrepo https://download.opensuse.org/repositories/X11:Wayland/openSUSE_Tumbleweed/X11:Wayland.repo | echo 'a' && \
zypper -n refresh && \
zypper -n install -t pattern devel_C_C++ && \
zypper -n install git meson clang libinput10 libinput-devel pugixml-devel libwayland-client0 libwayland-cursor0 wayland-protocols-devel wayland-devel Mesa-libEGL-devel Mesa-libGLESv2-devel libgbm-devel libxkbcommon-devel libudev-devel libpixman-1-0-devel gtkmm3-devel jsoncpp-devel libxkbregistry-devel scdoc playerctl-devel

View File

@ -1,27 +0,0 @@
.PHONY: build build-debug run clean default install
default: build
build:
meson build
ninja -C build
build-debug:
meson build --buildtype=debug
ninja -C build
install: build
ninja -C build install
run: build
./build/waybar
debug-run: build-debug
./build/waybar --log-level debug
test:
meson test -C build --no-rebuild --verbose --suite waybar
.PHONY: test
clean:
rm -rf build

109
README.md
View File

@ -1,123 +1,36 @@
# Waybar [![Licence](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Paypal Donate](https://img.shields.io/badge/Donate-Paypal-2244dd.svg)](https://paypal.me/ARouillard)<br>![Waybar](https://raw.githubusercontent.com/alexays/waybar/master/preview-2.png)
# Waybar [![Licence](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)<br>![Waybar](https://raw.githubusercontent.com/alexays/waybar/master/preview-2.png)
**Proof of concept**
> Highly customizable Wayland bar for Sway and Wlroots based compositors.<br>
> Available in Arch [extra](https://www.archlinux.org/packages/extra/x86_64/waybar/) or
[AUR](https://aur.archlinux.org/packages/waybar-git/), [Gentoo](https://packages.gentoo.org/packages/gui-apps/waybar), [openSUSE](https://build.opensuse.org/package/show/X11:Wayland/waybar), and [Alpine Linux](https://pkgs.alpinelinux.org/packages?name=waybar).<br>
> *Waybar [examples](https://github.com/Alexays/Waybar/wiki/Examples)*
> Available on [AUR](https://aur.archlinux.org/packages/waybar-git/)
#### Current features
- Sway (Workspaces, Binding mode, Focused window name)
- River (Mapping mode, Tags, Focused window name)
- Hyprland (Focused window name)
- DWL (Tags) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc)
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
**Current features**
- Sway Workspaces
- Sway focused window name
- Local time
- Battery
- UPower
- Network
- Bluetooth
- Pulseaudio
- Wireplumber
- Disk
- Memory
- Cpu load average
- Temperature
- MPD
- Custom scripts
- Custom image
- Multiple output configuration
- And many more customizations
- And much more customizations
#### Configuration and Styling
**Configuration and Customization**
[See the wiki for more details](https://github.com/Alexays/Waybar/wiki).
### Installation
Waybar is available from a number of Linux distributions:
[![Packaging status](https://repology.org/badge/vertical-allrepos/waybar.svg)](https://repology.org/project/waybar/versions)
An Ubuntu PPA with more recent versions is available
[here](https://launchpad.net/~nschloe/+archive/ubuntu/waybar).
#### Building from source
**How to build**
```bash
$ git clone https://github.com/Alexays/Waybar
$ cd Waybar
$ meson build
$ ninja -C build
$ ./build/waybar
# If you want to install it
$ ninja -C build install
$ waybar
```
**Dependencies**
```
gtkmm3
jsoncpp
libsigc++
fmt
wayland
chrono-date
spdlog
libgtk-3-dev [gtk-layer-shell]
gobject-introspection [gtk-layer-shell]
libgirepository1.0-dev [gtk-layer-shell]
libpulse [Pulseaudio module]
libnl [Network module]
libappindicator-gtk3 [Tray module]
libdbusmenu-gtk3 [Tray module]
libmpdclient [MPD module]
libsndio [sndio module]
libevdev [KeyboardState module]
xkbregistry
upower [UPower battery module]
```
**Build dependencies**
```
cmake
meson
scdoc
wayland-protocols
```
On Ubuntu, you can install all the relevant dependencies using this command (tested with 19.10 and 20.04):
```
sudo apt install \
clang-tidy \
gobject-introspection \
libdbusmenu-gtk3-dev \
libevdev-dev \
libfmt-dev \
libgirepository1.0-dev \
libgtk-3-dev \
libgtkmm-3.0-dev \
libinput-dev \
libjsoncpp-dev \
libmpdclient-dev \
libnl-3-dev \
libnl-genl-3-dev \
libpulse-dev \
libsigc++-2.0-dev \
libspdlog-dev \
libwayland-dev \
scdoc \
upower \
libxkbregistry-dev
```
Contributions welcome!<br>
Have fun :)<br>
The style guidelines are [Google's](https://google.github.io/styleguide/cppguide.html)
Contributions welcome! - have fun :)<br>
The style guidelines is [Google's](https://google.github.io/styleguide/cppguide.html)
## License

View File

@ -1,10 +0,0 @@
(import
(
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{ src = ./.; }
).defaultNix

129
flake.lock generated
View File

@ -1,129 +0,0 @@
{
"nodes": {
"devshell": {
"inputs": {
"nixpkgs": "nixpkgs",
"systems": "systems"
},
"locked": {
"lastModified": 1692523566,
"narHash": "sha256-VDJDihK6jNebVw9y3qKCVD6+6QaC/x8kxZzL4MaIPPY=",
"owner": "numtide",
"repo": "devshell",
"rev": "d208c58e2f7afef838add5f18a9936b12a71d695",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1677383253,
"narHash": "sha256-UfpzWfSxkfXHnb4boXZNaKsAcUrZT9Hw+tao1oZxd08=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9952d6bc395f5841262b006fbace8dd7e143b634",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1692638711,
"narHash": "sha256-J0LgSFgJVGCC1+j5R2QndadWI1oumusg6hCtYAzLID4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "91a22f76cd1716f9d0149e8a5c68424bb691de15",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"devshell": "devshell",
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs_2"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View File

@ -1,89 +0,0 @@
{
description = "Highly customizable Wayland bar for Sway and Wlroots based compositors.";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
devshell.url = "github:numtide/devshell";
flake-utils.url = "github:numtide/flake-utils";
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
};
outputs = { self, flake-utils, devshell, nixpkgs, flake-compat }:
let
inherit (nixpkgs) lib;
genSystems = lib.genAttrs [
"x86_64-linux"
];
pkgsFor = genSystems (system:
import nixpkgs {
inherit system;
});
mkDate = longDate: (lib.concatStringsSep "-" [
(builtins.substring 0 4 longDate)
(builtins.substring 4 2 longDate)
(builtins.substring 6 2 longDate)
]);
in
{
overlays.default = final: prev: {
waybar = final.callPackage ./nix/default.nix {
version = prev.waybar.version + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
};
};
packages = genSystems
(system:
(self.overlays.default pkgsFor.${system} pkgsFor.${system})
// {
default = self.packages.${system}.waybar;
});
} //
flake-utils.lib.eachDefaultSystem (system: {
devShell =
let pkgs = import nixpkgs {
inherit system;
overlays = [ devshell.overlays.default ];
};
in
pkgs.devshell.mkShell {
imports = [ "${pkgs.devshell.extraModulesDir}/language/c.nix" ];
devshell.packages = with pkgs; [
clang-tools
gdb
# from nativeBuildInputs
gnumake
meson
ninja
pkg-config
scdoc
] ++ (map lib.getDev [
# from buildInputs
wayland wlroots gtkmm3 libsigcxx jsoncpp spdlog gtk-layer-shell howard-hinnant-date libxkbcommon
# optional dependencies
gobject-introspection glib playerctl python3.pkgs.pygobject3
libevdev libinput libjack2 libmpdclient playerctl libnl
libpulseaudio sndio sway libdbusmenu-gtk3 udev upower wireplumber
# from propagated build inputs?
at-spi2-atk atkmm cairo cairomm catch2 fmt_8 fontconfig
gdk-pixbuf glibmm gtk3 harfbuzz pango pangomm wayland-protocols
]);
env = with pkgs; [
{ name = "CPLUS_INCLUDE_PATH"; prefix = "$DEVSHELL_DIR/include"; }
{ name = "PKG_CONFIG_PATH"; prefix = "$DEVSHELL_DIR/lib/pkgconfig"; }
{ name = "PKG_CONFIG_PATH"; prefix = "$DEVSHELL_DIR/share/pkgconfig"; }
{ name = "PATH"; prefix = "${wayland.bin}/bin"; }
{ name = "LIBRARY_PATH"; prefix = "${lib.getLib sndio}/lib"; }
{ name = "LIBRARY_PATH"; prefix = "${lib.getLib zlib}/lib"; }
{ name = "LIBRARY_PATH"; prefix = "${lib.getLib howard-hinnant-date}/lib"; }
];
};
});
}

View File

@ -1,27 +0,0 @@
#pragma once
#include <gtkmm/box.h>
#include <gtkmm/image.h>
#include "AIconLabel.hpp"
namespace waybar {
class AAppIconLabel : public AIconLabel {
public:
AAppIconLabel(const Json::Value &config, const std::string &name, const std::string &id,
const std::string &format, uint16_t interval = 0, bool ellipsize = false,
bool enable_click = false, bool enable_scroll = false);
virtual ~AAppIconLabel() = default;
auto update() -> void override;
protected:
void updateAppIconName(const std::string &app_identifier,
const std::string &alternative_app_identifier);
void updateAppIcon();
unsigned app_icon_size_{24};
bool update_app_icon_{true};
std::string app_icon_name_;
};
} // namespace waybar

View File

@ -1,25 +0,0 @@
#pragma once
#include <gtkmm/box.h>
#include <gtkmm/image.h>
#include "ALabel.hpp"
namespace waybar {
class AIconLabel : public ALabel {
public:
AIconLabel(const Json::Value &config, const std::string &name, const std::string &id,
const std::string &format, uint16_t interval = 0, bool ellipsize = false,
bool enable_click = false, bool enable_scroll = false);
virtual ~AIconLabel() = default;
auto update() -> void override;
protected:
Gtk::Image image_;
Gtk::Box box_;
bool iconEnabled() const;
};
} // namespace waybar

View File

@ -1,32 +1,19 @@
#pragma once
#include <glibmm/markup.h>
#include <gtkmm/label.h>
#include <json/json.h>
#include "AModule.hpp"
#include "IModule.hpp"
namespace waybar {
class ALabel : public AModule {
public:
ALabel(const Json::Value &, const std::string &, const std::string &, const std::string &format,
uint16_t interval = 0, bool ellipsize = false, bool enable_click = false,
bool enable_scroll = false);
virtual ~ALabel() = default;
auto update() -> void override;
virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0);
virtual std::string getIcon(uint16_t, const std::vector<std::string> &alts, uint16_t max = 0);
protected:
Gtk::Label label_;
std::string format_;
const std::chrono::seconds interval_;
bool alt_ = false;
std::string default_format_;
bool handleToggle(GdkEventButton *const &e) override;
virtual std::string getState(uint8_t value, bool lesser = false);
class ALabel : public IModule {
public:
ALabel(Json::Value);
virtual ~ALabel() = default;
virtual auto update() -> void;
virtual operator Gtk::Widget &();
protected:
Gtk::Label label_;
Json::Value config_;
};
} // namespace waybar
}

View File

@ -1,63 +0,0 @@
#pragma once
#include <glibmm/dispatcher.h>
#include <glibmm/markup.h>
#include <gtkmm/eventbox.h>
#include <json/json.h>
#include "IModule.hpp"
namespace waybar {
class AModule : public IModule {
public:
virtual ~AModule();
auto update() -> void override;
virtual auto refresh(int) -> void{};
operator Gtk::Widget &() override;
auto doAction(const std::string &name) -> void override;
Glib::Dispatcher dp;
protected:
// Don't need to make an object directly
// Derived classes are able to use it
AModule(const Json::Value &, const std::string &, const std::string &, bool enable_click = false,
bool enable_scroll = false);
enum SCROLL_DIR { NONE, UP, DOWN, LEFT, RIGHT };
SCROLL_DIR getScrollDir(GdkEventScroll *e);
bool tooltipEnabled();
const std::string name_;
const Json::Value &config_;
Gtk::EventBox event_box_;
virtual bool handleToggle(GdkEventButton *const &ev);
virtual bool handleScroll(GdkEventScroll *);
private:
std::vector<int> pid_;
gdouble distance_scrolled_y_;
gdouble distance_scrolled_x_;
std::map<std::string, std::string> eventActionMap_;
static const inline std::map<std::pair<uint, GdkEventType>, std::string> eventMap_{
{std::make_pair(1, GdkEventType::GDK_BUTTON_PRESS), "on-click"},
{std::make_pair(1, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click"},
{std::make_pair(1, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click"},
{std::make_pair(2, GdkEventType::GDK_BUTTON_PRESS), "on-click-middle"},
{std::make_pair(2, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-middle"},
{std::make_pair(2, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-middle"},
{std::make_pair(3, GdkEventType::GDK_BUTTON_PRESS), "on-click-right"},
{std::make_pair(3, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-right"},
{std::make_pair(3, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-right"},
{std::make_pair(8, GdkEventType::GDK_BUTTON_PRESS), "on-click-backward"},
{std::make_pair(8, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-backward"},
{std::make_pair(8, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-backward"},
{std::make_pair(9, GdkEventType::GDK_BUTTON_PRESS), "on-click-forward"},
{std::make_pair(9, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-forward"},
{std::make_pair(9, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-forward"}};
};
} // namespace waybar

View File

@ -1,15 +1,14 @@
#pragma once
#include <gtkmm/widget.h>
#include <gtkmm.h>
namespace waybar {
class IModule {
public:
virtual ~IModule() = default;
virtual auto update() -> void = 0;
virtual operator Gtk::Widget&() = 0;
virtual auto doAction(const std::string& name) -> void = 0;
public:
virtual ~IModule() {}
virtual auto update() -> void = 0;
virtual operator Gtk::Widget &() = 0;
};
} // namespace waybar
}

View File

@ -1,125 +1,59 @@
#pragma once
#include <gdkmm/monitor.h>
#include <glibmm/refptr.h>
#include <gtkmm/box.h>
#include <gtkmm/cssprovider.h>
#include <gtkmm/main.h>
#include <gtkmm/window.h>
#include <json/json.h>
#include <memory>
#include <vector>
#include "AModule.hpp"
#include <gtkmm.h>
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
#include "IModule.hpp"
namespace waybar {
class Client;
class Factory;
struct waybar_output {
Glib::RefPtr<Gdk::Monitor> monitor;
std::string name;
std::string identifier;
std::unique_ptr<struct zxdg_output_v1, decltype(&zxdg_output_v1_destroy)> xdg_output = {
nullptr, &zxdg_output_v1_destroy};
};
enum class bar_layer : uint8_t {
BOTTOM,
TOP,
OVERLAY,
};
struct bar_margins {
int top = 0;
int right = 0;
int bottom = 0;
int left = 0;
};
struct bar_mode {
bar_layer layer;
bool exclusive;
bool passthrough;
bool visible;
};
#ifdef HAVE_SWAY
namespace modules::sway {
class BarIpcClient;
}
#endif // HAVE_SWAY
class BarSurface {
protected:
BarSurface() = default;
public:
virtual void setExclusiveZone(bool enable) = 0;
virtual void setLayer(bar_layer layer) = 0;
virtual void setMargins(const struct bar_margins &margins) = 0;
virtual void setPassThrough(bool enable) = 0;
virtual void setPosition(const std::string_view &position) = 0;
virtual void setSize(uint32_t width, uint32_t height) = 0;
virtual void commit(){};
virtual ~BarSurface() = default;
};
class Bar {
public:
using bar_mode_map = std::map<std::string_view, struct bar_mode>;
static const bar_mode_map PRESET_MODES;
static const std::string_view MODE_DEFAULT;
static const std::string_view MODE_INVISIBLE;
public:
Bar(Client&, std::unique_ptr<struct wl_output *>&&, uint32_t wl_name);
Bar(const Bar&) = delete;
Bar(struct waybar_output *w_output, const Json::Value &);
Bar(const Bar &) = delete;
~Bar();
auto toggle() -> void;
void setMode(const std::string_view &);
void setVisible(bool visible);
void toggle();
void handleSignal(int);
Client& client;
Gtk::Window window;
struct wl_surface *surface;
struct zwlr_layer_surface_v1 *layer_surface;
std::unique_ptr<struct wl_output *> output;
std::string output_name;
uint32_t wl_name;
bool visible = true;
private:
static void handleLogicalPosition(void *, struct zxdg_output_v1 *, int32_t,
int32_t);
static void handleLogicalSize(void *, struct zxdg_output_v1 *, int32_t,
int32_t);
static void handleDone(void *, struct zxdg_output_v1 *);
static void handleName(void *, struct zxdg_output_v1 *, const char *);
static void handleDescription(void *, struct zxdg_output_v1 *,
const char *);
static void layerSurfaceHandleConfigure(void *,
struct zwlr_layer_surface_v1 *, uint32_t, uint32_t, uint32_t);
static void layerSurfaceHandleClosed(void *,
struct zwlr_layer_surface_v1 *);
struct waybar_output *output;
Json::Value config;
struct wl_surface *surface;
bool visible = true;
bool vertical = false;
Gtk::Window window;
auto setupConfig() -> void;
auto setupWidgets() -> void;
auto setupCss() -> void;
void getModules(Factory factory, const std::string& pos);
#ifdef HAVE_SWAY
std::string bar_id;
#endif
private:
void onMap(GdkEventAny *);
auto setupWidgets() -> void;
void getModules(const Factory &, const std::string &, Gtk::Box *);
void setupAltFormatKeyForModule(const std::string &module_name);
void setupAltFormatKeyForModuleList(const char *module_list_name);
void setMode(const bar_mode &);
/* Copy initial set of modes to allow customization */
bar_mode_map configured_modes = PRESET_MODES;
std::string last_mode_{MODE_DEFAULT};
std::unique_ptr<BarSurface> surface_impl_;
Gtk::Box left_;
Gtk::Box center_;
Gtk::Box right_;
Gtk::Box box_;
std::vector<std::shared_ptr<waybar::AModule>> modules_left_;
std::vector<std::shared_ptr<waybar::AModule>> modules_center_;
std::vector<std::shared_ptr<waybar::AModule>> modules_right_;
#ifdef HAVE_SWAY
using BarIpcClient = modules::sway::BarIpcClient;
std::unique_ptr<BarIpcClient> _ipc_client;
#endif
std::vector<std::shared_ptr<waybar::AModule>> modules_all_;
uint32_t width_ = 0;
uint32_t height_ = 30;
Json::Value config_;
Glib::RefPtr<Gtk::StyleContext> style_context_;
Glib::RefPtr<Gtk::CssProvider> css_provider_;
struct zxdg_output_v1 *xdg_output_;
std::vector<std::unique_ptr<waybar::IModule>> modules_left_;
std::vector<std::unique_ptr<waybar::IModule>> modules_center_;
std::vector<std::unique_ptr<waybar::IModule>> modules_right_;
};
} // namespace waybar
}

View File

@ -1,58 +1,43 @@
#pragma once
#include <unistd.h>
#include <wordexp.h>
#include <fmt/format.h>
#include <gdk/gdk.h>
#include <gdk/gdkwayland.h>
#include <wayland-client.h>
#include "bar.hpp"
#include "config.hpp"
#include <gdk/gdkwayland.h>
struct zwlr_layer_shell_v1;
struct zwp_idle_inhibitor_v1;
struct zwp_idle_inhibit_manager_v1;
#include "bar.hpp"
namespace waybar {
class Client {
public:
static Client *inst();
int main(int argc, char *argv[]);
void reset();
public:
Client(int argc, char *argv[]);
int main(int argc, char *argv[]);
Glib::RefPtr<Gtk::Application> gtk_app;
Glib::RefPtr<Gdk::Display> gdk_display;
struct wl_display *wl_display = nullptr;
struct wl_registry *registry = nullptr;
struct zwlr_layer_shell_v1 *layer_shell = nullptr;
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager = nullptr;
std::vector<std::unique_ptr<Bar>> bars;
Config config;
std::string bar_id;
Glib::RefPtr<Gtk::Application> gtk_app;
std::string css_file;
std::string config_file;
Glib::RefPtr<Gdk::Display> gdk_display;
struct wl_display *wl_display = nullptr;
struct wl_registry *registry = nullptr;
struct zwlr_layer_shell_v1 *layer_shell = nullptr;
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
struct wl_seat *seat = nullptr;
std::vector<std::unique_ptr<Bar>> bars;
private:
Client() = default;
const std::string getStyle(const std::string &style);
private:
void bindInterfaces();
void handleOutput(struct waybar_output &output);
auto setupCss(const std::string &css_file) -> void;
struct waybar_output &getOutput(void *);
std::vector<Json::Value> getOutputConfigs(struct waybar_output &output);
auto setupCss();
static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name,
const char *interface, uint32_t version);
static void handleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name);
static void handleOutputDone(void *, struct zxdg_output_v1 *);
static void handleOutputName(void *, struct zxdg_output_v1 *, const char *);
static void handleOutputDescription(void *, struct zxdg_output_v1 *, const char *);
void handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor);
void handleMonitorRemoved(Glib::RefPtr<Gdk::Monitor> monitor);
void handleDeferredMonitorRemoval(Glib::RefPtr<Gdk::Monitor> monitor);
Glib::RefPtr<Gtk::StyleContext> style_context_;
Glib::RefPtr<Gtk::CssProvider> css_provider_;
std::list<struct waybar_output> outputs_;
static void handleGlobal(void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version);
static void handleGlobalRemove(void *data,
struct wl_registry *registry, uint32_t name);
};
} // namespace waybar
}

View File

@ -1,40 +0,0 @@
#pragma once
#include <json/json.h>
#include <optional>
#include <string>
#ifndef SYSCONFDIR
#define SYSCONFDIR "/etc"
#endif
namespace waybar {
class Config {
public:
static const std::vector<std::string> CONFIG_DIRS;
static const char *CONFIG_PATH_ENV;
/* Try to find any of provided names in the supported set of config directories */
static std::optional<std::string> findConfigPath(
const std::vector<std::string> &names, const std::vector<std::string> &dirs = CONFIG_DIRS);
Config() = default;
void load(const std::string &config);
Json::Value &getConfig() { return config_; }
std::vector<Json::Value> getOutputConfigs(const std::string &name, const std::string &identifier);
private:
void setupConfig(Json::Value &dst, const std::string &config_file, int depth);
void resolveConfigIncludes(Json::Value &config, int depth);
void mergeConfig(Json::Value &a_config_, Json::Value &b_config_);
std::string config_file_;
Json::Value config_;
};
} // namespace waybar

View File

@ -1,108 +1,25 @@
#pragma once
#include <json/json.h>
#if defined(HAVE_CHRONO_TIMEZONES) || defined(HAVE_LIBDATE)
#include "modules/clock.hpp"
#else
#include "modules/simpleclock.hpp"
#endif
#ifdef HAVE_SWAY
#include "modules/sway/language.hpp"
#include "modules/sway/mode.hpp"
#include "modules/sway/scratchpad.hpp"
#include "modules/sway/window.hpp"
#include "modules/sway/workspaces.hpp"
#endif
#ifdef HAVE_WLR
#include "modules/wlr/taskbar.hpp"
#include "modules/wlr/workspace_manager.hpp"
#endif
#ifdef HAVE_RIVER
#include "modules/river/layout.hpp"
#include "modules/river/mode.hpp"
#include "modules/river/tags.hpp"
#include "modules/river/window.hpp"
#endif
#ifdef HAVE_DWL
#include "modules/dwl/tags.hpp"
#endif
#ifdef HAVE_HYPRLAND
#include "modules/hyprland/backend.hpp"
#include "modules/hyprland/language.hpp"
#include "modules/hyprland/submap.hpp"
#include "modules/hyprland/window.hpp"
#include "modules/hyprland/workspaces.hpp"
#endif
#if defined(__FreeBSD__) || (defined(__linux__) && !defined(NO_FILESYSTEM))
#include "modules/sway/window.hpp"
#include "modules/battery.hpp"
#endif
#if defined(HAVE_CPU_LINUX) || defined(HAVE_CPU_BSD)
#include "modules/cpu.hpp"
#endif
#include "modules/idle_inhibitor.hpp"
#if defined(HAVE_MEMORY_LINUX) || defined(HAVE_MEMORY_BSD)
#include "modules/memory.hpp"
#endif
#include "modules/disk.hpp"
#ifdef HAVE_DBUSMENU
#include "modules/sni/tray.hpp"
#endif
#ifdef HAVE_MPRIS
#include "modules/mpris/mpris.hpp"
#endif
#ifdef HAVE_LIBNL
#include "modules/cpu.hpp"
#include "modules/network.hpp"
#endif
#ifdef HAVE_LIBUDEV
#include "modules/backlight.hpp"
#endif
#ifdef HAVE_LIBEVDEV
#include "modules/keyboard_state.hpp"
#endif
#ifdef HAVE_GAMEMODE
#include "modules/gamemode.hpp"
#endif
#ifdef HAVE_UPOWER
#include "modules/upower/upower.hpp"
#endif
#ifdef HAVE_LIBPULSE
#include "modules/pulseaudio.hpp"
#endif
#ifdef HAVE_LIBMPDCLIENT
#include "modules/mpd/mpd.hpp"
#endif
#ifdef HAVE_LIBSNDIO
#include "modules/sndio.hpp"
#endif
#ifdef HAVE_GIO_UNIX
#include "modules/bluetooth.hpp"
#include "modules/inhibitor.hpp"
#endif
#ifdef HAVE_LIBJACK
#include "modules/jack.hpp"
#endif
#ifdef HAVE_LIBWIREPLUMBER
#include "modules/wireplumber.hpp"
#endif
#ifdef HAVE_LIBCAVA
#include "modules/cava.hpp"
#endif
#include "bar.hpp"
#include "modules/custom.hpp"
#include "modules/image.hpp"
#include "modules/temperature.hpp"
#include "modules/user.hpp"
namespace waybar {
class Factory {
public:
Factory(const Bar& bar, const Json::Value& config);
AModule* makeModule(const std::string& name) const;
private:
const Bar& bar_;
const Json::Value& config_;
public:
Factory(Bar &bar, Json::Value config);
IModule* makeModule(const std::string &name);
private:
Bar &_bar;
Json::Value _config;
};
} // namespace waybar
}

View File

@ -1,22 +0,0 @@
#pragma once
#include <gtkmm/box.h>
#include <gtkmm/widget.h>
#include <json/json.h>
#include "AModule.hpp"
#include "bar.hpp"
#include "factory.hpp"
namespace waybar {
class Group : public AModule {
public:
Group(const std::string&, const std::string&, const Json::Value&, bool);
~Group() = default;
auto update() -> void override;
operator Gtk::Widget&() override;
Gtk::Box box;
};
} // namespace waybar

View File

@ -1,69 +0,0 @@
#pragma once
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include "ALabel.hpp"
#include "giomm/dbusproxy.h"
#include "util/json.hpp"
#include "util/sleeper_thread.hpp"
struct udev;
struct udev_device;
namespace waybar::modules {
class Backlight : public ALabel {
class BacklightDev {
public:
BacklightDev() = default;
BacklightDev(std::string name, int actual, int max, bool powered);
std::string_view name() const;
int get_actual() const;
void set_actual(int actual);
int get_max() const;
void set_max(int max);
bool get_powered() const;
void set_powered(bool powered);
friend inline bool operator==(const BacklightDev &lhs, const BacklightDev &rhs) {
return lhs.name_ == rhs.name_ && lhs.actual_ == rhs.actual_ && lhs.max_ == rhs.max_;
}
private:
std::string name_;
int actual_ = 1;
int max_ = 1;
bool powered_ = true;
};
public:
Backlight(const std::string &, const Json::Value &);
virtual ~Backlight();
auto update() -> void override;
private:
template <class ForwardIt>
static const BacklightDev *best_device(ForwardIt first, ForwardIt last, std::string_view);
template <class ForwardIt, class Inserter>
static void upsert_device(ForwardIt first, ForwardIt last, Inserter inserter, udev_device *dev);
template <class ForwardIt, class Inserter>
static void enumerate_devices(ForwardIt first, ForwardIt last, Inserter inserter, udev *udev);
bool handleScroll(GdkEventScroll *e) override;
const std::string preferred_device_;
static constexpr int EPOLL_MAX_EVENTS = 16;
std::optional<BacklightDev> previous_best_;
std::string previous_format_;
std::mutex udev_thread_mutex_;
std::vector<BacklightDev> devices_;
// thread must destruct before shared data
util::SleeperThread udev_thread_;
Glib::RefPtr<Gio::DBus::Proxy> login_proxy_;
};
} // namespace waybar::modules

View File

@ -1,58 +1,31 @@
#pragma once
#ifdef FILESYSTEM_EXPERIMENTAL
#include <experimental/filesystem>
#else
#include <filesystem>
#endif
#include <fmt/format.h>
#if defined(__linux__)
#include <sys/inotify.h>
#endif
#include <algorithm>
#include <fstream>
#include <string>
#include <vector>
#include <iostream>
#include <fmt/format.h>
#include <sys/inotify.h>
#include <algorithm>
#include "util/chrono.hpp"
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
#ifdef FILESYSTEM_EXPERIMENTAL
namespace fs = std::experimental::filesystem;
#else
namespace fs = std::filesystem;
#endif
class Battery : public ALabel {
public:
Battery(const std::string&, const Json::Value&);
virtual ~Battery();
auto update() -> void override;
public:
Battery(Json::Value);
~Battery();
auto update() -> void;
private:
std::string getIcon(uint16_t percentage);
private:
static inline const fs::path data_dir_ = "/sys/class/power_supply/";
static inline const fs::path data_dir_ = "/sys/class/power_supply/";
void refreshBatteries();
void worker();
const std::string getAdapterStatus(uint8_t capacity) const;
const std::tuple<uint8_t, float, std::string, float> getInfos();
const std::string formatTimeRemaining(float hoursRemaining);
int global_watch;
std::map<fs::path, int> batteries_;
fs::path adapter_;
int battery_watch_fd_;
int global_watch_fd_;
std::mutex battery_list_mutex_;
std::string old_status_;
bool warnFirstTime_{true};
util::SleeperThread thread_;
util::SleeperThread thread_battery_update_;
util::SleeperThread thread_timer_;
util::SleeperThread thread_;
std::vector<fs::path> batteries_;
int fd_;
};
} // namespace waybar::modules
}

View File

@ -1,80 +0,0 @@
#pragma once
#include "ALabel.hpp"
#ifdef WANT_RFKILL
#include "util/rfkill.hpp"
#endif
#include <gio/gio.h>
#include <optional>
#include <string>
#include <vector>
namespace waybar::modules {
class Bluetooth : public ALabel {
struct ControllerInfo {
std::string path;
std::string address;
std::string address_type;
// std::string name; // just use alias instead
std::string alias;
bool powered;
bool discoverable;
bool pairable;
bool discovering;
};
// NOTE: there are some properties that not all devices provide
struct DeviceInfo {
std::string path;
std::string paired_controller;
std::string address;
std::string address_type;
// std::optional<std::string> name; // just use alias instead
std::string alias;
std::optional<std::string> icon;
bool paired;
bool trusted;
bool blocked;
bool connected;
bool services_resolved;
// NOTE: experimental feature in bluez
std::optional<unsigned char> battery_percentage;
};
public:
Bluetooth(const std::string&, const Json::Value&);
virtual ~Bluetooth() = default;
auto update() -> void override;
private:
static auto onInterfaceAddedOrRemoved(GDBusObjectManager*, GDBusObject*, GDBusInterface*,
gpointer) -> void;
static auto onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient*, GDBusObjectProxy*,
GDBusProxy*, GVariant*, const gchar* const*,
gpointer) -> void;
auto getDeviceBatteryPercentage(GDBusObject*) -> std::optional<unsigned char>;
auto getDeviceProperties(GDBusObject*, DeviceInfo&) -> bool;
auto getControllerProperties(GDBusObject*, ControllerInfo&) -> bool;
// Returns std::nullopt if no controller could be found
auto findCurController() -> std::optional<ControllerInfo>;
auto findConnectedDevices(const std::string&, std::vector<DeviceInfo>&) -> void;
#ifdef WANT_RFKILL
util::Rfkill rfkill_;
#endif
const std::unique_ptr<GDBusObjectManager, void (*)(GDBusObjectManager*)> manager_;
std::string state_;
std::optional<ControllerInfo> cur_controller_;
std::vector<DeviceInfo> connected_devices_;
DeviceInfo cur_focussed_device_;
std::string device_enumerate_;
std::vector<std::string> device_preference_;
};
} // namespace waybar::modules

View File

@ -1,46 +0,0 @@
#pragma once
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
extern "C" {
#include <cava/common.h>
}
namespace waybar::modules {
using namespace std::literals::chrono_literals;
class Cava final : public ALabel {
public:
Cava(const std::string&, const Json::Value&);
virtual ~Cava();
auto update() -> void override;
auto doAction(const std::string& name) -> void override;
private:
util::SleeperThread thread_;
util::SleeperThread thread_fetch_input_;
struct error_s error_ {}; // cava errors
struct config_params prm_ {}; // cava parameters
struct audio_raw audio_raw_ {}; // cava handled raw audio data(is based on audio_data)
struct audio_data audio_data_ {}; // cava audio data
struct cava_plan* plan_; //{new cava_plan{}};
// Cava API to read audio source
ptr input_source_;
// Delay to handle audio source
std::chrono::milliseconds frame_time_milsec_{1s};
// Text to display
std::string text_{""};
int rePaint_{1};
std::chrono::seconds fetch_input_delay_{4};
std::chrono::seconds suspend_silence_delay_{0};
bool silence_{false};
int sleep_counter_{0};
// Cava method
void pause_resume();
// ModuleActionMap
static inline std::map<const std::string, void (waybar::modules::Cava::*const)()> actionMap_{
{"mode", &waybar::modules::Cava::pause_resume}};
};
} // namespace waybar::modules

View File

@ -1,79 +1,18 @@
#pragma once
#include <fmt/format.h>
#include "fmt/time.h"
#include "util/chrono.hpp"
#include "ALabel.hpp"
#include "util/date.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
const std::string kCalendarPlaceholder = "calendar";
const std::string KTimezonedTimeListPlaceholder = "timezoned_time_list";
enum class WeeksSide {
LEFT,
RIGHT,
HIDDEN,
class Clock : public ALabel {
public:
Clock(Json::Value);
auto update() -> void;
private:
waybar::util::SleeperThread thread_;
};
enum class CldMode { MONTH, YEAR };
class Clock final : public ALabel {
public:
Clock(const std::string&, const Json::Value&);
virtual ~Clock() = default;
auto update() -> void override;
auto doAction(const std::string& name) -> void override;
private:
util::SleeperThread thread_;
std::locale locale_;
std::vector<const date::time_zone*> time_zones_;
int current_time_zone_idx_;
bool is_calendar_in_tooltip_;
bool is_timezoned_list_in_tooltip_;
auto first_day_of_week() -> date::weekday;
const date::time_zone* current_timezone();
auto timezones_text(std::chrono::system_clock::time_point now) -> std::string;
/*Calendar properties*/
WeeksSide cldWPos_{WeeksSide::HIDDEN};
/*
0 - calendar.format.months
1 - calendar.format.weekdays
2 - calendar.format.days
3 - calendar.format.today
4 - calendar.format.weeks
5 - tooltip-format
*/
std::map<int, std::string const> fmtMap_;
CldMode cldMode_{CldMode::MONTH};
uint cldMonCols_{3}; // Count of the month in the row
int cldMonColLen_{20}; // Length of the month column
int cldWnLen_{3}; // Length of the week number
date::year_month_day cldYearShift_;
date::year_month cldMonShift_;
date::months cldCurrShift_{0};
date::months cldShift_{0};
std::string cldYearCached_{};
std::string cldMonCached_{};
date::day cldBaseDay_{0};
/*Calendar functions*/
auto get_calendar(const date::year_month_day& today, const date::year_month_day& ymd,
const date::time_zone* tz) -> const std::string;
/*Clock actions*/
void cldModeSwitch();
void cldShift_up();
void cldShift_down();
void tz_up();
void tz_down();
// ModuleActionMap
static inline std::map<const std::string, void (waybar::modules::Clock::*const)()> actionMap_{
{"mode", &waybar::modules::Clock::cldModeSwitch},
{"shift_up", &waybar::modules::Clock::cldShift_up},
{"shift_down", &waybar::modules::Clock::cldShift_down},
{"tz_up", &waybar::modules::Clock::tz_up},
{"tz_down", &waybar::modules::Clock::tz_down}};
};
} // namespace waybar::modules
}

View File

@ -1,35 +1,18 @@
#pragma once
#include <fmt/format.h>
#include <cstdint>
#include <fstream>
#include <numeric>
#include <string>
#include <utility>
#include <vector>
#include <sys/sysinfo.h>
#include "util/chrono.hpp"
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Cpu : public ALabel {
public:
Cpu(const std::string&, const Json::Value&);
virtual ~Cpu() = default;
auto update() -> void override;
private:
double getCpuLoad();
std::tuple<std::vector<uint16_t>, std::string> getCpuUsage();
std::tuple<float, float, float> getCpuFrequency();
std::vector<std::tuple<size_t, size_t>> parseCpuinfo();
std::vector<float> parseCpuFrequencies();
std::vector<std::tuple<size_t, size_t>> prev_times_;
util::SleeperThread thread_;
public:
Cpu(Json::Value);
auto update() -> void;
private:
waybar::util::SleeperThread thread_;
};
} // namespace waybar::modules
}

View File

@ -1,48 +1,20 @@
#pragma once
#include <fmt/format.h>
#include <fmt/args.h>
#include <csignal>
#include <string>
#include "ALabel.hpp"
#include <iostream>
#include "util/chrono.hpp"
#include "util/command.hpp"
#include "util/json.hpp"
#include "util/sleeper_thread.hpp"
#include "ALabel.hpp"
namespace waybar::modules {
class Custom : public ALabel {
public:
Custom(const std::string&, const std::string&, const Json::Value&);
virtual ~Custom();
auto update() -> void override;
void refresh(int /*signal*/) override;
private:
void delayWorker();
void continuousWorker();
void parseOutputRaw();
void parseOutputJson();
void handleEvent();
bool handleScroll(GdkEventScroll* e) override;
bool handleToggle(GdkEventButton* const& e) override;
const std::string name_;
std::string text_;
std::string id_;
std::string alt_;
std::string tooltip_;
std::vector<std::string> class_;
fmt::dynamic_format_arg_store<fmt::format_context> fields_;
int percentage_;
FILE* fp_;
int pid_;
util::command::res output_;
util::JsonParser parser_;
util::SleeperThread thread_;
public:
Custom(std::string, Json::Value);
auto update() -> void;
private:
std::string name_;
waybar::util::SleeperThread thread_;
};
} // namespace waybar::modules
}

View File

@ -1,25 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <sys/statvfs.h>
#include <fstream>
#include "ALabel.hpp"
#include "util/format.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Disk : public ALabel {
public:
Disk(const std::string&, const Json::Value&);
virtual ~Disk() = default;
auto update() -> void override;
private:
util::SleeperThread thread_;
std::string path_;
};
} // namespace waybar::modules

View File

@ -1,34 +0,0 @@
#pragma once
#include <gtkmm/button.h>
#include <wayland-client.h>
#include "AModule.hpp"
#include "bar.hpp"
#include "dwl-ipc-unstable-v2-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
namespace waybar::modules::dwl {
class Tags : public waybar::AModule {
public:
Tags(const std::string &, const waybar::Bar &, const Json::Value &);
virtual ~Tags();
// Handlers for wayland events
void handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused);
void handle_primary_clicked(uint32_t tag);
bool handle_button_press(GdkEventButton *event_button, uint32_t tag);
struct zdwl_ipc_manager_v2 *status_manager_;
struct wl_seat *seat_;
private:
const waybar::Bar &bar_;
Gtk::Box box_;
std::vector<Gtk::Button> buttons_;
struct zdwl_ipc_output_v2 *output_status_;
};
} /* namespace waybar::modules::dwl */

View File

@ -1,77 +0,0 @@
#pragma once
#include <iostream>
#include <map>
#include <string>
#include "ALabel.hpp"
#include "giomm/dbusconnection.h"
#include "giomm/dbusproxy.h"
#include "glibconfig.h"
#include "gtkmm/box.h"
#include "gtkmm/image.h"
#include "gtkmm/label.h"
#include "gtkmm/overlay.h"
namespace waybar::modules {
class Gamemode : public AModule {
public:
Gamemode(const std::string &, const Json::Value &);
virtual ~Gamemode();
auto update() -> void override;
private:
const std::string DEFAULT_ICON_NAME = "input-gaming-symbolic";
const std::string DEFAULT_FORMAT = "{glyph}";
const std::string DEFAULT_FORMAT_ALT = "{glyph} {count}";
const std::string DEFAULT_TOOLTIP_FORMAT = "Games running: {count}";
const std::string DEFAULT_GLYPH = "";
void appear(const Glib::RefPtr<Gio::DBus::Connection> &connection, const Glib::ustring &name,
const Glib::ustring &name_owner);
void disappear(const Glib::RefPtr<Gio::DBus::Connection> &connection, const Glib::ustring &name);
void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection> &connection,
const Glib::ustring &sender_name, const Glib::ustring &object_path,
const Glib::ustring &interface_name, const Glib::ustring &signal_name,
const Glib::VariantContainerBase &parameters);
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name,
const Glib::VariantContainerBase &arguments);
void getData();
bool handleToggle(GdkEventButton *const &) override;
// Config
std::string format = DEFAULT_FORMAT;
std::string format_alt = DEFAULT_FORMAT_ALT;
std::string tooltip_format = DEFAULT_TOOLTIP_FORMAT;
std::string glyph = DEFAULT_GLYPH;
bool tooltip = true;
bool hideNotRunning = true;
bool useIcon = true;
uint iconSize = 20;
uint iconSpacing = 4;
std::string iconName = DEFAULT_ICON_NAME;
Gtk::Box box_;
Gtk::Image icon_;
Gtk::Label label_;
const std::string dbus_name = "com.feralinteractive.GameMode";
const std::string dbus_obj_path = "/com/feralinteractive/GameMode";
const std::string dbus_interface = "org.freedesktop.DBus.Properties";
const std::string dbus_get_interface = "com.feralinteractive.GameMode";
uint gameCount = 0;
std::string lastStatus;
bool showAltText = false;
guint login1_id;
Glib::RefPtr<Gio::DBus::Proxy> gamemode_proxy;
Glib::RefPtr<Gio::DBus::Connection> system_connection;
bool gamemodeRunning;
guint gamemodeWatcher_id;
};
} // namespace waybar::modules

View File

@ -1,40 +0,0 @@
#pragma once
#include <functional>
#include <list>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include "util/json.hpp"
namespace waybar::modules::hyprland {
class EventHandler {
public:
virtual void onEvent(const std::string& ev) = 0;
virtual ~EventHandler() = default;
};
class IPC {
public:
IPC() { startIPC(); }
void registerForIPC(const std::string&, EventHandler*);
void unregisterForIPC(EventHandler*);
std::string getSocket1Reply(const std::string& rq);
Json::Value getSocket1JsonReply(const std::string& rq);
private:
void startIPC();
void parseIPC(const std::string&);
std::mutex callbackMutex;
util::JsonParser parser_;
std::list<std::pair<std::string, EventHandler*>> callbacks;
};
inline std::unique_ptr<IPC> gIPC;
inline bool modulesReady = false;
}; // namespace waybar::modules::hyprland

View File

@ -1,38 +0,0 @@
#include <fmt/format.h>
#include "ALabel.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
#include "util/json.hpp"
namespace waybar::modules::hyprland {
class Language : public waybar::ALabel, public EventHandler {
public:
Language(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Language();
auto update() -> void override;
private:
void onEvent(const std::string&) override;
void initLanguage();
struct Layout {
std::string full_name;
std::string short_name;
std::string variant;
std::string short_description;
};
auto getLayout(const std::string&) -> Layout;
std::mutex mutex_;
const Bar& bar_;
util::JsonParser parser_;
Layout layout_;
};
} // namespace waybar::modules::hyprland

View File

@ -1,26 +0,0 @@
#include <fmt/format.h>
#include "ALabel.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
#include "util/json.hpp"
namespace waybar::modules::hyprland {
class Submap : public waybar::ALabel, public EventHandler {
public:
Submap(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Submap();
auto update() -> void override;
private:
void onEvent(const std::string&) override;
std::mutex mutex_;
const Bar& bar_;
util::JsonParser parser_;
std::string submap_;
};
} // namespace waybar::modules::hyprland

View File

@ -1,60 +0,0 @@
#include <fmt/format.h>
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
#include "util/json.hpp"
namespace waybar::modules::hyprland {
class Window : public waybar::AAppIconLabel, public EventHandler {
public:
Window(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Window();
auto update() -> void override;
private:
struct Workspace {
int id;
int windows;
std::string last_window;
std::string last_window_title;
static auto parse(const Json::Value&) -> Workspace;
};
struct WindowData {
bool floating;
int monitor = -1;
std::string class_name;
std::string initial_class_name;
std::string title;
std::string initial_title;
bool fullscreen;
bool grouped;
static auto parse(const Json::Value&) -> WindowData;
};
auto getActiveWorkspace(const std::string&) -> Workspace;
auto getActiveWorkspace() -> Workspace;
void onEvent(const std::string&) override;
void queryActiveWorkspace();
void setClass(const std::string&, bool enable);
bool separate_outputs;
std::mutex mutex_;
const Bar& bar_;
util::JsonParser parser_;
WindowData window_data_;
Workspace workspace_;
std::string solo_class_;
std::string last_solo_class_;
bool solo_;
bool all_floating_;
bool swallowing_;
bool fullscreen_;
};
} // namespace waybar::modules::hyprland

View File

@ -1,91 +0,0 @@
#include <gtkmm/button.h>
#include <gtkmm/label.h>
#include <memory>
#include "AModule.hpp"
#include "bar.hpp"
#include "modules/hyprland/backend.hpp"
namespace waybar::modules::hyprland {
class Workspace {
public:
Workspace(const Json::Value& workspace_data);
std::string& select_icon(std::map<std::string, std::string>& icons_map);
Gtk::Button& button() { return button_; };
int id() const { return id_; };
std::string name() const { return name_; };
std::string output() const { return output_; };
bool active() const { return active_; };
bool is_special() const { return is_special_; };
bool is_persistent() const { return is_persistent_; };
bool is_empty() const { return windows_ == 0; };
bool is_urgent() const { return is_urgent_; };
auto handle_clicked(GdkEventButton* bt) -> bool;
void set_active(bool value = true) { active_ = value; };
void set_persistent(bool value = true) { is_persistent_ = value; };
void set_urgent(bool value = true) { is_urgent_ = value; };
void set_windows(uint value) { windows_ = value; };
void update(const std::string& format, const std::string& icon);
private:
int id_;
std::string name_;
std::string output_;
uint windows_;
bool active_ = false;
bool is_special_ = false;
bool is_persistent_ = false;
bool is_urgent_ = false;
Gtk::Button button_;
Gtk::Box content_;
Gtk::Label label_;
};
class Workspaces : public AModule, public EventHandler {
public:
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
~Workspaces() override;
void update() override;
void init();
auto all_outputs() const -> bool { return all_outputs_; }
auto show_special() const -> bool { return show_special_; }
auto get_bar_output() const -> std::string { return bar_.output->name; }
private:
void onEvent(const std::string&) override;
void update_window_count();
void sort_workspaces();
void create_workspace(Json::Value& value);
void remove_workspace(std::string name);
void set_urgent_workspace(std::string windowaddress);
bool all_outputs_ = false;
bool show_special_ = false;
void fill_persistent_workspaces();
void create_persistent_workspaces();
std::vector<std::string> persistent_workspaces_to_create_;
bool persistent_created_ = false;
std::string format_;
std::map<std::string, std::string> icons_map_;
bool with_icon_;
uint64_t monitor_id_;
std::string active_workspace_name_;
std::vector<std::unique_ptr<Workspace>> workspaces_;
std::vector<Json::Value> workspaces_to_create_;
std::vector<std::string> workspaces_to_remove_;
std::mutex mutex_;
const Bar& bar_;
Gtk::Box box_;
};
} // namespace waybar::modules::hyprland

View File

@ -1,30 +0,0 @@
#pragma once
#include <fmt/format.h>
#include "ALabel.hpp"
#include "bar.hpp"
#include "client.hpp"
namespace waybar::modules {
class IdleInhibitor : public ALabel {
sigc::connection timeout_;
public:
IdleInhibitor(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~IdleInhibitor();
auto update() -> void override;
static std::list<waybar::AModule*> modules;
static bool status;
private:
bool handleToggle(GdkEventButton* const& e) override;
void toggleStatus();
const Bar& bar_;
struct zwp_idle_inhibitor_v1* idle_inhibitor_;
int pid_;
};
} // namespace waybar::modules

View File

@ -1,40 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <gtkmm/image.h>
#include <csignal>
#include <string>
#include "ALabel.hpp"
#include "gtkmm/box.h"
#include "util/command.hpp"
#include "util/json.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Image : public AModule {
public:
Image(const std::string&, const Json::Value&);
virtual ~Image() = default;
auto update() -> void override;
void refresh(int /*signal*/) override;
private:
void delayWorker();
void handleEvent();
void parseOutputRaw();
Gtk::Box box_;
Gtk::Image image_;
std::string path_;
std::string tooltip_;
int size_;
int interval_;
util::command::res output_;
util::SleeperThread thread_;
};
} // namespace waybar::modules

View File

@ -1,27 +0,0 @@
#pragma once
#include <gio/gio.h>
#include <memory>
#include "ALabel.hpp"
#include "bar.hpp"
namespace waybar::modules {
class Inhibitor : public ALabel {
public:
Inhibitor(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Inhibitor();
auto update() -> void override;
auto activated() -> bool;
private:
auto handleToggle(::GdkEventButton* const& e) -> bool override;
const std::unique_ptr<::GDBusConnection, void (*)(::GDBusConnection*)> dbus_;
const std::string inhibitors_;
int handle_ = -1;
};
} // namespace waybar::modules

View File

@ -1,44 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <jack/jack.h>
#include <jack/thread.h>
#include <fstream>
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class JACK : public ALabel {
public:
JACK(const std::string &, const Json::Value &);
virtual ~JACK() = default;
auto update() -> void override;
int bufSize(jack_nframes_t size);
int sampleRate(jack_nframes_t rate);
int xrun();
void shutdown();
private:
std::string JACKState();
jack_client_t *client_;
jack_nframes_t bufsize_;
jack_nframes_t samplerate_;
unsigned int xruns_;
float load_;
bool running_;
std::mutex mutex_;
std::string state_;
util::SleeperThread thread_;
};
} // namespace waybar::modules
int bufSizeCallback(jack_nframes_t size, void *obj);
int sampleRateCallback(jack_nframes_t rate, void *obj);
int xrunCallback(void *obj);
void shutdownCallback(void *obj);

View File

@ -1,49 +0,0 @@
#pragma once
#include <fmt/chrono.h>
#include <gtkmm/label.h>
#include <set>
#include <unordered_map>
#include "AModule.hpp"
#include "bar.hpp"
#include "util/sleeper_thread.hpp"
extern "C" {
#include <libevdev/libevdev.h>
#include <libinput.h>
}
namespace waybar::modules {
class KeyboardState : public AModule {
public:
KeyboardState(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~KeyboardState();
auto update() -> void override;
private:
auto tryAddDevice(const std::string&) -> void;
Gtk::Box box_;
Gtk::Label numlock_label_;
Gtk::Label capslock_label_;
Gtk::Label scrolllock_label_;
std::string numlock_format_;
std::string capslock_format_;
std::string scrolllock_format_;
const std::chrono::seconds interval_;
std::string icon_locked_;
std::string icon_unlocked_;
std::string devices_path_;
struct libinput* libinput_;
std::unordered_map<std::string, struct libinput_device*> libinput_devices_;
std::set<int> binding_keys;
util::SleeperThread libinput_thread_, hotplug_thread_;
};
} // namespace waybar::modules

View File

@ -1,27 +1,18 @@
#pragma once
#include <fmt/format.h>
#include <fstream>
#include <unordered_map>
#include <sys/sysinfo.h>
#include "util/chrono.hpp"
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Memory : public ALabel {
public:
Memory(const std::string&, const Json::Value&);
virtual ~Memory() = default;
auto update() -> void override;
private:
void parseMeminfo();
std::unordered_map<std::string, unsigned long> meminfo_;
util::SleeperThread thread_;
public:
Memory(Json::Value);
auto update() -> void;
private:
waybar::util::SleeperThread thread_;
};
} // namespace waybar::modules
}

View File

@ -1,68 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <mpd/client.h>
#include <spdlog/spdlog.h>
#include <condition_variable>
#include <thread>
#include "ALabel.hpp"
#include "modules/mpd/state.hpp"
namespace waybar::modules {
class MPD : public ALabel {
friend class detail::Context;
// State machine
detail::Context context_{this};
const std::string module_name_;
// Not using unique_ptr since we don't manage the pointer
// (It's either nullptr, or from the config)
const char* server_;
const unsigned port_;
const std::string password_;
unsigned timeout_;
detail::unique_connection connection_;
detail::unique_status status_;
mpd_state state_;
detail::unique_song song_;
public:
MPD(const std::string&, const Json::Value&);
virtual ~MPD() noexcept = default;
auto update() -> void override;
private:
std::string getTag(mpd_tag_type type, unsigned idx = 0) const;
std::string getFilename() const;
void setLabel();
std::string getStateIcon() const;
std::string getOptionIcon(std::string optionName, bool activated) const;
// GUI-side methods
bool handlePlayPause(GdkEventButton* const&);
void emit() { dp.emit(); }
// MPD-side, Non-GUI methods.
void tryConnect();
void checkErrors(mpd_connection* conn);
void fetchState();
void queryMPD();
inline bool stopped() const { return connection_ && state_ == MPD_STATE_STOP; }
inline bool playing() const { return connection_ && state_ == MPD_STATE_PLAY; }
inline bool paused() const { return connection_ && state_ == MPD_STATE_PAUSE; }
};
#if !defined(MPD_NOINLINE)
#include "modules/mpd/state.inl.hpp"
#endif
} // namespace waybar::modules

View File

@ -1,217 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <mpd/client.h>
#include <spdlog/spdlog.h>
#include <condition_variable>
#include <thread>
#include "ALabel.hpp"
namespace waybar::modules {
class MPD;
} // namespace waybar::modules
namespace waybar::modules::detail {
using unique_connection = std::unique_ptr<mpd_connection, decltype(&mpd_connection_free)>;
using unique_status = std::unique_ptr<mpd_status, decltype(&mpd_status_free)>;
using unique_song = std::unique_ptr<mpd_song, decltype(&mpd_song_free)>;
class Context;
/// This state machine loosely follows a non-hierarchical, statechart
/// pattern, and includes ENTRY and EXIT actions.
///
/// The State class is the base class for all other states. The
/// entry and exit methods are automatically called when entering
/// into a new state and exiting from the current state. This
/// includes initially entering (Disconnected class) and exiting
/// Waybar.
///
/// The following nested "top-level" states are represented:
/// 1. Idle - await notification of MPD activity.
/// 2. All Non-Idle states:
/// 1. Playing - An active song is producing audio output.
/// 2. Paused - The current song is paused.
/// 3. Stopped - No song is actively playing.
/// 3. Disconnected - periodically attempt MPD (re-)connection.
///
/// NOTE: Since this statechart is non-hierarchical, the above
/// states are flattened into a set.
class State {
public:
virtual ~State() noexcept = default;
virtual void entry() noexcept { spdlog::debug("mpd: ignore entry action"); }
virtual void exit() noexcept { spdlog::debug("mpd: ignore exit action"); }
virtual void play() { spdlog::debug("mpd: ignore play state transition"); }
virtual void stop() { spdlog::debug("mpd: ignore stop state transition"); }
virtual void pause() { spdlog::debug("mpd: ignore pause state transition"); }
/// Request state update the GUI.
virtual void update() noexcept { spdlog::debug("mpd: ignoring update method request"); }
};
class Idle : public State {
Context* const ctx_;
sigc::connection idle_connection_;
public:
Idle(Context* const ctx) : ctx_{ctx} {}
virtual ~Idle() noexcept { this->exit(); };
void entry() noexcept override;
void exit() noexcept override;
void play() override;
void stop() override;
void pause() override;
void update() noexcept override;
private:
Idle(const Idle&) = delete;
Idle& operator=(const Idle&) = delete;
bool on_io(Glib::IOCondition const&);
};
class Playing : public State {
Context* const ctx_;
sigc::connection timer_connection_;
public:
Playing(Context* const ctx) : ctx_{ctx} {}
virtual ~Playing() noexcept { this->exit(); }
void entry() noexcept override;
void exit() noexcept override;
void pause() override;
void stop() override;
void update() noexcept override;
private:
Playing(Playing const&) = delete;
Playing& operator=(Playing const&) = delete;
bool on_timer();
};
class Paused : public State {
Context* const ctx_;
sigc::connection timer_connection_;
public:
Paused(Context* const ctx) : ctx_{ctx} {}
virtual ~Paused() noexcept { this->exit(); }
void entry() noexcept override;
void exit() noexcept override;
void play() override;
void stop() override;
void update() noexcept override;
private:
Paused(Paused const&) = delete;
Paused& operator=(Paused const&) = delete;
bool on_timer();
};
class Stopped : public State {
Context* const ctx_;
sigc::connection timer_connection_;
public:
Stopped(Context* const ctx) : ctx_{ctx} {}
virtual ~Stopped() noexcept { this->exit(); }
void entry() noexcept override;
void exit() noexcept override;
void play() override;
void pause() override;
void update() noexcept override;
private:
Stopped(Stopped const&) = delete;
Stopped& operator=(Stopped const&) = delete;
bool on_timer();
};
class Disconnected : public State {
Context* const ctx_;
sigc::connection timer_connection_;
public:
Disconnected(Context* const ctx) : ctx_{ctx} {}
virtual ~Disconnected() noexcept { this->exit(); }
void entry() noexcept override;
void exit() noexcept override;
void update() noexcept override;
private:
Disconnected(Disconnected const&) = delete;
Disconnected& operator=(Disconnected const&) = delete;
void arm_timer(int interval) noexcept;
void disarm_timer() noexcept;
bool on_timer();
};
class Context {
std::unique_ptr<State> state_;
waybar::modules::MPD* mpd_module_;
friend class State;
friend class Playing;
friend class Paused;
friend class Stopped;
friend class Disconnected;
friend class Idle;
protected:
void setState(std::unique_ptr<State>&& new_state) noexcept {
if (state_.get() != nullptr) {
state_->exit();
}
state_ = std::move(new_state);
state_->entry();
}
bool is_connected() const;
bool is_playing() const;
bool is_paused() const;
bool is_stopped() const;
constexpr std::size_t interval() const;
void tryConnect() const;
void checkErrors(mpd_connection*) const;
void do_update();
void queryMPD() const;
void fetchState() const;
constexpr mpd_state state() const;
void emit() const;
[[nodiscard]] unique_connection& connection();
public:
explicit Context(waybar::modules::MPD* const mpd_module)
: state_{std::make_unique<Disconnected>(this)}, mpd_module_{mpd_module} {
state_->entry();
}
void play() { state_->play(); }
void stop() { state_->stop(); }
void pause() { state_->pause(); }
void update() noexcept { state_->update(); }
};
} // namespace waybar::modules::detail

View File

@ -1,22 +0,0 @@
#pragma once
namespace detail {
inline bool Context::is_connected() const { return mpd_module_->connection_ != nullptr; }
inline bool Context::is_playing() const { return mpd_module_->playing(); }
inline bool Context::is_paused() const { return mpd_module_->paused(); }
inline bool Context::is_stopped() const { return mpd_module_->stopped(); }
constexpr inline std::size_t Context::interval() const { return mpd_module_->interval_.count(); }
inline void Context::tryConnect() const { mpd_module_->tryConnect(); }
inline unique_connection& Context::connection() { return mpd_module_->connection_; }
constexpr inline mpd_state Context::state() const { return mpd_module_->state_; }
inline void Context::do_update() { mpd_module_->setLabel(); }
inline void Context::checkErrors(mpd_connection* conn) const { mpd_module_->checkErrors(conn); }
inline void Context::queryMPD() const { mpd_module_->queryMPD(); }
inline void Context::fetchState() const { mpd_module_->fetchState(); }
inline void Context::emit() const { mpd_module_->emit(); }
} // namespace detail

View File

@ -1,88 +0,0 @@
#pragma once
#include <iostream>
#include <optional>
#include <string>
#include "gtkmm/box.h"
#include "gtkmm/label.h"
extern "C" {
#include <playerctl/playerctl.h>
}
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules::mpris {
class Mpris : public ALabel {
public:
Mpris(const std::string&, const Json::Value&);
virtual ~Mpris();
auto update() -> void override;
bool handleToggle(GdkEventButton* const&) override;
private:
static auto onPlayerNameAppeared(PlayerctlPlayerManager*, PlayerctlPlayerName*, gpointer) -> void;
static auto onPlayerNameVanished(PlayerctlPlayerManager*, PlayerctlPlayerName*, gpointer) -> void;
static auto onPlayerPlay(PlayerctlPlayer*, gpointer) -> void;
static auto onPlayerPause(PlayerctlPlayer*, gpointer) -> void;
static auto onPlayerStop(PlayerctlPlayer*, gpointer) -> void;
static auto onPlayerMetadata(PlayerctlPlayer*, GVariant*, gpointer) -> void;
struct PlayerInfo {
std::string name;
PlayerctlPlaybackStatus status;
std::string status_string;
std::optional<std::string> artist;
std::optional<std::string> album;
std::optional<std::string> title;
std::optional<std::string> length; // as HH:MM:SS
std::optional<std::string> position; // same format
};
auto getPlayerInfo() -> std::optional<PlayerInfo>;
auto getIconFromJson(const Json::Value&, const std::string&) -> std::string;
auto getArtistStr(const PlayerInfo&, bool) -> std::string;
auto getAlbumStr(const PlayerInfo&, bool) -> std::string;
auto getTitleStr(const PlayerInfo&, bool) -> std::string;
auto getLengthStr(const PlayerInfo&, bool) -> std::string;
auto getPositionStr(const PlayerInfo&, bool) -> std::string;
auto getDynamicStr(const PlayerInfo&, bool, bool) -> std::string;
// config
std::string format_playing_;
std::string format_paused_;
std::string format_stopped_;
std::string tooltip_;
std::string tooltip_playing_;
std::string tooltip_paused_;
std::string tooltip_stopped_;
int artist_len_;
int album_len_;
int title_len_;
int dynamic_len_;
std::vector<std::string> dynamic_prio_;
std::vector<std::string> dynamic_order_;
std::string dynamic_separator_;
bool truncate_hours_;
bool tooltip_len_limits_;
std::string ellipsis_;
std::string player_;
std::vector<std::string> ignored_players_;
PlayerctlPlayerManager* manager;
PlayerctlPlayer* player;
std::string lastStatus;
std::string lastPlayer;
util::SleeperThread thread_;
std::chrono::time_point<std::chrono::system_clock> last_update_;
};
} // namespace waybar::modules::mpris

View File

@ -1,91 +1,43 @@
#pragma once
#include <arpa/inet.h>
#include <fmt/format.h>
#include <linux/nl80211.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>
#include <net/if.h>
#include <netlink/netlink.h>
#include <sys/epoll.h>
#include <optional>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <linux/nl80211.h>
#include <fmt/format.h>
#include "util/chrono.hpp"
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
#ifdef WANT_RFKILL
#include "util/rfkill.hpp"
#endif
namespace waybar::modules {
class Network : public ALabel {
public:
Network(const std::string&, const Json::Value&);
virtual ~Network();
auto update() -> void override;
public:
Network(Json::Value);
~Network();
auto update() -> void;
private:
static uint64_t netlinkRequest(int, void*, uint32_t, uint32_t groups = 0);
static uint64_t netlinkResponse(int, void*, uint32_t, uint32_t groups = 0);
static int scanCb(struct nl_msg*, void*);
private:
static const uint8_t MAX_RETRY = 5;
static const uint8_t EPOLL_MAX = 200;
void disconnected();
int getExternalInterface();
void parseEssid(struct nlattr**);
void parseSignal(struct nlattr**);
bool associatedOrJoined(struct nlattr**);
auto getInfo() -> void;
static int handleEvents(struct nl_msg*, void*);
static int handleEventsDone(struct nl_msg*, void*);
static int handleScan(struct nl_msg*, void*);
waybar::util::SleeperThread thread_;
int ifid_;
sa_family_t family_;
int sock_fd_;
struct sockaddr_nl nladdr_ = {0};
void askForStateDump(void);
void worker();
void createInfoSocket();
void createEventSocket();
void parseEssid(struct nlattr**);
void parseSignal(struct nlattr**);
void parseFreq(struct nlattr**);
bool associatedOrJoined(struct nlattr**);
bool checkInterface(std::string name);
auto getInfo() -> void;
const std::string getNetworkState() const;
void clearIface();
bool wildcardMatch(const std::string& pattern, const std::string& text) const;
std::optional<std::pair<unsigned long long, unsigned long long>> readBandwidthUsage();
int ifid_;
sa_family_t family_;
struct sockaddr_nl nladdr_ = {0};
struct nl_sock* sock_ = nullptr;
struct nl_sock* ev_sock_ = nullptr;
int efd_;
int ev_fd_;
int nl80211_id_;
std::mutex mutex_;
bool want_route_dump_;
bool want_link_dump_;
bool want_addr_dump_;
bool dump_in_progress_;
bool is_p2p_;
unsigned long long bandwidth_down_total_;
unsigned long long bandwidth_up_total_;
std::string state_;
std::string essid_;
bool carrier_;
std::string ifname_;
std::string ipaddr_;
std::string gwaddr_;
std::string netmask_;
int cidr_;
int32_t signal_strength_dbm_;
uint8_t signal_strength_;
std::string signal_strength_app_;
uint32_t route_priority;
util::SleeperThread thread_;
util::SleeperThread thread_timer_;
#ifdef WANT_RFKILL
util::Rfkill rfkill_;
#endif
float frequency_;
std::string essid_;
std::string ifname_;
int signal_strength_dbm_;
uint16_t signal_strength_;
};
} // namespace waybar::modules
}

View File

@ -1,54 +1,33 @@
#pragma once
#include <fmt/format.h>
#include <pulse/pulseaudio.h>
#include <pulse/volume.h>
#include <fmt/format.h>
#include <algorithm>
#include <array>
#include "ALabel.hpp"
namespace waybar::modules {
class Pulseaudio : public ALabel {
public:
Pulseaudio(const std::string&, const Json::Value&);
virtual ~Pulseaudio();
auto update() -> void override;
public:
Pulseaudio(Json::Value);
~Pulseaudio();
auto update() -> void;
private:
static void subscribeCb(pa_context*, pa_subscription_event_type_t,
uint32_t, void*);
static void contextStateCb(pa_context*, void*);
static void sinkInfoCb(pa_context*, const pa_sink_info*, int, void*);
static void serverInfoCb(pa_context*, const pa_server_info*, void*);
private:
static void subscribeCb(pa_context*, pa_subscription_event_type_t, uint32_t, void*);
static void contextStateCb(pa_context*, void*);
static void sinkInfoCb(pa_context*, const pa_sink_info*, int, void*);
static void sourceInfoCb(pa_context*, const pa_source_info* i, int, void* data);
static void serverInfoCb(pa_context*, const pa_server_info*, void*);
static void volumeModifyCb(pa_context*, int, void*);
std::string getIcon(uint16_t);
bool handleScroll(GdkEventScroll* e) override;
const std::vector<std::string> getPulseIcon() const;
pa_threaded_mainloop* mainloop_;
pa_mainloop_api* mainloop_api_;
pa_context* context_;
// SINK
uint32_t sink_idx_{0};
uint16_t volume_;
pa_cvolume pa_volume_;
bool muted_;
std::string port_name_;
std::string form_factor_;
std::string desc_;
std::string monitor_;
std::string current_sink_name_;
bool current_sink_running_;
// SOURCE
uint32_t source_idx_{0};
uint16_t source_volume_;
bool source_muted_;
std::string source_port_name_;
std::string source_desc_;
std::string default_source_name_;
pa_threaded_mainloop* mainloop_;
pa_mainloop_api* mainloop_api_;
pa_context* context_;
uint32_t sink_idx_{0};
uint16_t volume_;
bool muted_;
std::string desc_;
};
} // namespace waybar::modules
}

View File

@ -1,33 +0,0 @@
#pragma once
#include <wayland-client.h>
#include "ALabel.hpp"
#include "bar.hpp"
#include "river-status-unstable-v1-client-protocol.h"
namespace waybar::modules::river {
class Layout : public waybar::ALabel {
public:
Layout(const std::string &, const waybar::Bar &, const Json::Value &);
virtual ~Layout();
// Handlers for wayland events
void handle_name(const char *name);
void handle_clear();
void handle_focused_output(struct wl_output *output);
void handle_unfocused_output(struct wl_output *output);
struct zriver_status_manager_v1 *status_manager_;
struct wl_seat *seat_;
private:
const waybar::Bar &bar_;
struct wl_output *output_; // stores the output this module belongs to
struct wl_output *focused_output_; // stores the currently focused output
struct zriver_output_status_v1 *output_status_;
struct zriver_seat_status_v1 *seat_status_;
};
} /* namespace waybar::modules::river */

View File

@ -1,28 +0,0 @@
#pragma once
#include <wayland-client.h>
#include "ALabel.hpp"
#include "bar.hpp"
#include "river-status-unstable-v1-client-protocol.h"
namespace waybar::modules::river {
class Mode : public waybar::ALabel {
public:
Mode(const std::string &, const waybar::Bar &, const Json::Value &);
virtual ~Mode();
// Handlers for wayland events
void handle_mode(const char *mode);
struct zriver_status_manager_v1 *status_manager_;
struct wl_seat *seat_;
private:
const waybar::Bar &bar_;
std::string mode_;
struct zriver_seat_status_v1 *seat_status_;
};
} /* namespace waybar::modules::river */

View File

@ -1,38 +0,0 @@
#pragma once
#include <gtkmm/button.h>
#include <wayland-client.h>
#include "AModule.hpp"
#include "bar.hpp"
#include "river-control-unstable-v1-client-protocol.h"
#include "river-status-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
namespace waybar::modules::river {
class Tags : public waybar::AModule {
public:
Tags(const std::string &, const waybar::Bar &, const Json::Value &);
virtual ~Tags();
// Handlers for wayland events
void handle_focused_tags(uint32_t tags);
void handle_view_tags(struct wl_array *tags);
void handle_urgent_tags(uint32_t tags);
void handle_primary_clicked(uint32_t tag);
bool handle_button_press(GdkEventButton *event_button, uint32_t tag);
struct zriver_status_manager_v1 *status_manager_;
struct zriver_control_v1 *control_;
struct wl_seat *seat_;
private:
const waybar::Bar &bar_;
Gtk::Box box_;
std::vector<Gtk::Button> buttons_;
struct zriver_output_status_v1 *output_status_;
};
} /* namespace waybar::modules::river */

View File

@ -1,33 +0,0 @@
#pragma once
#include <gtkmm/button.h>
#include <wayland-client.h>
#include "ALabel.hpp"
#include "bar.hpp"
#include "river-status-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
namespace waybar::modules::river {
class Window : public waybar::ALabel {
public:
Window(const std::string &, const waybar::Bar &, const Json::Value &);
virtual ~Window();
// Handlers for wayland events
void handle_focused_view(const char *title);
void handle_focused_output(struct wl_output *output);
void handle_unfocused_output(struct wl_output *output);
struct zriver_status_manager_v1 *status_manager_;
struct wl_seat *seat_;
private:
const waybar::Bar &bar_;
struct wl_output *output_; // stores the output this module belongs to
struct wl_output *focused_output_; // stores the currently focused output
struct zriver_seat_status_v1 *seat_status_;
};
} /* namespace waybar::modules::river */

View File

@ -1,20 +0,0 @@
#pragma once
#include <fmt/chrono.h>
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Clock : public ALabel {
public:
Clock(const std::string&, const Json::Value&);
virtual ~Clock() = default;
auto update() -> void override;
private:
util::SleeperThread thread_;
};
} // namespace waybar::modules

View File

@ -1,32 +0,0 @@
#pragma once
#include <sndio.h>
#include <vector>
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Sndio : public ALabel {
public:
Sndio(const std::string &, const Json::Value &);
virtual ~Sndio();
auto update() -> void override;
auto set_desc(struct sioctl_desc *, unsigned int) -> void;
auto put_val(unsigned int, unsigned int) -> void;
bool handleScroll(GdkEventScroll *) override;
bool handleToggle(GdkEventButton *const &) override;
private:
auto connect_to_sndio() -> void;
util::SleeperThread thread_;
struct sioctl_hdl *hdl_;
std::vector<struct pollfd> pfds_;
unsigned int addr_;
unsigned int volume_, old_volume_, maxval_;
bool muted_;
};
} // namespace waybar::modules

View File

@ -1,48 +0,0 @@
#pragma once
#include <dbus-status-notifier-watcher.h>
#include <giomm.h>
#include <glibmm/refptr.h>
#include <json/json.h>
#include <tuple>
#include "bar.hpp"
#include "modules/sni/item.hpp"
namespace waybar::modules::SNI {
class Host {
public:
Host(const std::size_t id, const Json::Value&, const Bar&,
const std::function<void(std::unique_ptr<Item>&)>&,
const std::function<void(std::unique_ptr<Item>&)>&);
~Host();
private:
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
void nameAppeared(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring,
const Glib::ustring&);
void nameVanished(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
static void proxyReady(GObject*, GAsyncResult*, gpointer);
static void registerHost(GObject*, GAsyncResult*, gpointer);
static void itemRegistered(SnWatcher*, const gchar*, gpointer);
static void itemUnregistered(SnWatcher*, const gchar*, gpointer);
std::tuple<std::string, std::string> getBusNameAndObjectPath(const std::string);
void addRegisteredItem(std::string service);
std::vector<std::unique_ptr<Item>> items_;
const std::string bus_name_;
const std::string object_path_;
std::size_t bus_name_id_;
std::size_t watcher_id_;
GCancellable* cancellable_ = nullptr;
SnWatcher* watcher_ = nullptr;
const Json::Value& config_;
const Bar& bar_;
const std::function<void(std::unique_ptr<Item>&)> on_add_;
const std::function<void(std::unique_ptr<Item>&)> on_remove_;
};
} // namespace waybar::modules::SNI

View File

@ -1,92 +0,0 @@
#pragma once
#include <dbus-status-notifier-item.h>
#include <giomm/dbusproxy.h>
#include <glibmm/refptr.h>
#include <gtkmm/eventbox.h>
#include <gtkmm/icontheme.h>
#include <gtkmm/image.h>
#include <gtkmm/menu.h>
#include <json/json.h>
#include <libdbusmenu-gtk/dbusmenu-gtk.h>
#include <sigc++/trackable.h>
#include <set>
#include <string_view>
#include "bar.hpp"
namespace waybar::modules::SNI {
struct ToolTip {
Glib::ustring icon_name;
Glib::ustring text;
};
class Item : public sigc::trackable {
public:
Item(const std::string&, const std::string&, const Json::Value&, const Bar&);
~Item() = default;
std::string bus_name;
std::string object_path;
int icon_size;
int effective_icon_size;
Gtk::Image image;
Gtk::EventBox event_box;
std::string category;
std::string id;
std::string title;
std::string icon_name;
Glib::RefPtr<Gdk::Pixbuf> icon_pixmap;
Glib::RefPtr<Gtk::IconTheme> icon_theme;
std::string overlay_icon_name;
std::string attention_icon_name;
std::string attention_movie_name;
std::string icon_theme_path;
std::string menu;
ToolTip tooltip;
DbusmenuGtkMenu* dbus_menu = nullptr;
Gtk::Menu* gtk_menu = nullptr;
/**
* ItemIsMenu flag means that the item only supports the context menu.
* Default value is true because libappindicator supports neither ItemIsMenu nor Activate method
* while compliant SNI implementation would always reset the flag to desired value.
*/
bool item_is_menu = true;
private:
void onConfigure(GdkEventConfigure* ev);
void proxyReady(Glib::RefPtr<Gio::AsyncResult>& result);
void setProperty(const Glib::ustring& name, Glib::VariantBase& value);
void setStatus(const Glib::ustring& value);
void getUpdatedProperties();
void processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& result);
void onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
const Glib::VariantContainerBase& arguments);
void updateImage();
Glib::RefPtr<Gdk::Pixbuf> extractPixBuf(GVariant* variant);
Glib::RefPtr<Gdk::Pixbuf> getIconPixbuf();
Glib::RefPtr<Gdk::Pixbuf> getIconByName(const std::string& name, int size);
double getScaledIconSize();
static void onMenuDestroyed(Item* self, GObject* old_menu_pointer);
void makeMenu();
bool handleClick(GdkEventButton* const& /*ev*/);
bool handleScroll(GdkEventScroll* const&);
// smooth scrolling threshold
gdouble scroll_threshold_ = 0;
gdouble distance_scrolled_x_ = 0;
gdouble distance_scrolled_y_ = 0;
// visibility of items with Status == Passive
bool show_passive_ = false;
Glib::RefPtr<Gio::DBus::Proxy> proxy_;
Glib::RefPtr<Gio::Cancellable> cancellable_;
std::set<std::string_view> update_pending_;
};
} // namespace waybar::modules::SNI

View File

@ -1,29 +0,0 @@
#pragma once
#include <fmt/format.h>
#include "AModule.hpp"
#include "bar.hpp"
#include "modules/sni/host.hpp"
#include "modules/sni/watcher.hpp"
#include "util/json.hpp"
namespace waybar::modules::SNI {
class Tray : public AModule {
public:
Tray(const std::string&, const Bar&, const Json::Value&);
virtual ~Tray() = default;
auto update() -> void override;
private:
void onAdd(std::unique_ptr<Item>& item);
void onRemove(std::unique_ptr<Item>& item);
static inline std::size_t nb_hosts_ = 0;
Gtk::Box box_;
SNI::Watcher::singleton watcher_;
SNI::Host host_;
};
} // namespace waybar::modules::SNI

View File

@ -1,56 +0,0 @@
#pragma once
#include <dbus-status-notifier-watcher.h>
#include <giomm.h>
#include <glibmm/refptr.h>
namespace waybar::modules::SNI {
class Watcher {
private:
Watcher();
public:
~Watcher();
using singleton = std::shared_ptr<Watcher>;
static singleton getInstance() {
static std::weak_ptr<Watcher> weak;
std::shared_ptr<Watcher> strong = weak.lock();
if (!strong) {
strong = std::shared_ptr<Watcher>(new Watcher());
weak = strong;
}
return strong;
}
private:
typedef enum { GF_WATCH_TYPE_HOST, GF_WATCH_TYPE_ITEM } GfWatchType;
typedef struct {
GfWatchType type;
Watcher *watcher;
gchar *service;
gchar *bus_name;
gchar *object_path;
guint watch_id;
} GfWatch;
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection> &, Glib::ustring);
static gboolean handleRegisterHost(Watcher *, GDBusMethodInvocation *, const gchar *);
static gboolean handleRegisterItem(Watcher *, GDBusMethodInvocation *, const gchar *);
static GfWatch *gfWatchFind(GSList *list, const gchar *bus_name, const gchar *object_path);
static GfWatch *gfWatchNew(GfWatchType, const gchar *, const gchar *, const gchar *, Watcher *);
static void nameVanished(GDBusConnection *connection, const char *name, gpointer data);
static void gfWatchFree(gpointer data);
void updateRegisteredItems(SnWatcher *obj);
uint32_t bus_name_id_;
GSList *hosts_ = nullptr;
GSList *items_ = nullptr;
SnWatcher *watcher_ = nullptr;
};
} // namespace waybar::modules::SNI

View File

@ -1,60 +0,0 @@
#pragma once
#include <atomic>
#include <string>
#include "modules/sway/ipc/client.hpp"
#include "util/SafeSignal.hpp"
#include "util/json.hpp"
namespace waybar {
class Bar;
namespace modules::sway {
/*
* Supported subset of i3/sway IPC barconfig object
*/
struct swaybar_config {
std::string id;
std::string mode;
std::string hidden_state;
};
/**
* swaybar IPC client
*/
class BarIpcClient {
public:
BarIpcClient(waybar::Bar& bar);
private:
void onInitialConfig(const struct Ipc::ipc_response& res);
void onIpcEvent(const struct Ipc::ipc_response&);
void onCmd(const struct Ipc::ipc_response&);
void onConfigUpdate(const swaybar_config& config);
void onVisibilityUpdate(bool visible_by_modifier);
void onModeUpdate(bool visible_by_modifier);
void onUrgencyUpdate(bool visible_by_urgency);
void update();
bool isModuleEnabled(std::string name);
Bar& bar_;
util::JsonParser parser_;
Ipc ipc_;
swaybar_config bar_config_;
std::string modifier_reset_;
bool visible_by_mode_ = false;
bool visible_by_modifier_ = false;
bool visible_by_urgency_ = false;
std::atomic<bool> modifier_no_action_ = false;
SafeSignal<bool> signal_mode_;
SafeSignal<bool> signal_visible_;
SafeSignal<bool> signal_urgency_;
SafeSignal<swaybar_config> signal_config_;
};
} // namespace modules::sway
} // namespace waybar

View File

@ -1,53 +1,33 @@
#pragma once
#include <sigc++/sigc++.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <cstring>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <string>
#include <iostream>
#include "ipc.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules::sway {
class Ipc {
public:
Ipc();
~Ipc();
struct ipc_response {
uint32_t size;
uint32_t type;
std::string payload;
};
sigc::signal<void, const struct ipc_response &> signal_event;
sigc::signal<void, const struct ipc_response &> signal_cmd;
void sendCmd(uint32_t type, const std::string &payload = "");
void subscribe(const std::string &payload);
void handleEvent();
void setWorker(std::function<void()> &&func);
protected:
static inline const std::string ipc_magic_ = "i3-ipc";
static inline const size_t ipc_header_size_ = ipc_magic_.size() + 8;
const std::string getSocketPath() const;
int open(const std::string &) const;
struct ipc_response send(int fd, uint32_t type, const std::string &payload = "");
struct ipc_response recv(int fd);
int fd_;
int fd_event_;
std::mutex mutex_;
util::SleeperThread thread_;
/**
* IPC response including type of IPC response, size of payload and the json
* encoded payload string.
*/
struct ipc_response {
uint32_t size;
uint32_t type;
std::string payload;
};
} // namespace waybar::modules::sway
/**
* Gets the path to the IPC socket from sway.
*/
std::string getSocketPath(void);
/**
* Opens the sway socket.
*/
int ipcOpenSocket(const std::string &socketPath);
/**
* Issues a single IPC command and returns the buffer. len will be updated with
* the length of the buffer returned from sway.
*/
struct ipc_response ipcSingleCommand(int socketfd, uint32_t type,
const std::string& payload);
/**
* Receives a single IPC response and returns an ipc_response.
*/
struct ipc_response ipcRecvResponse(int socketfd);

View File

@ -1,38 +1,32 @@
#pragma once
#include <cstdint>
#define event_mask(ev) (1 << (ev & 0x7F))
#define event_mask(ev) (1u << (ev & 0x7F))
enum ipc_command_type {
// i3 command types - see i3's I3_REPLY_TYPE constants
IPC_COMMAND = 0,
IPC_GET_WORKSPACES = 1,
IPC_SUBSCRIBE = 2,
IPC_GET_OUTPUTS = 3,
IPC_GET_TREE = 4,
IPC_GET_MARKS = 5,
IPC_GET_BAR_CONFIG = 6,
IPC_GET_VERSION = 7,
IPC_GET_BINDING_MODES = 8,
IPC_GET_CONFIG = 9,
IPC_SEND_TICK = 10,
enum ipc_command_type : uint32_t {
// i3 command types - see i3's I3_REPLY_TYPE constants
IPC_COMMAND = 0,
IPC_GET_WORKSPACES = 1,
IPC_SUBSCRIBE = 2,
IPC_GET_OUTPUTS = 3,
IPC_GET_TREE = 4,
IPC_GET_MARKS = 5,
IPC_GET_BAR_CONFIG = 6,
IPC_GET_VERSION = 7,
IPC_GET_BINDING_MODES = 8,
IPC_GET_CONFIG = 9,
IPC_SEND_TICK = 10,
// sway-specific command types
IPC_GET_INPUTS = 100,
IPC_GET_SEATS = 101,
// sway-specific command types
IPC_GET_INPUTS = 100,
IPC_GET_SEATS = 101,
// Events sent from sway to clients. Events have the highest bits set.
IPC_EVENT_WORKSPACE = ((1U << 31) | 0),
IPC_EVENT_OUTPUT = ((1U << 31) | 1),
IPC_EVENT_MODE = ((1U << 31) | 2),
IPC_EVENT_WINDOW = ((1U << 31) | 3),
IPC_EVENT_BARCONFIG_UPDATE = ((1U << 31) | 4),
IPC_EVENT_BINDING = ((1U << 31) | 5),
IPC_EVENT_SHUTDOWN = ((1U << 31) | 6),
IPC_EVENT_TICK = ((1U << 31) | 7),
// sway-specific event types
IPC_EVENT_BAR_STATE_UPDATE = ((1U << 31) | 20),
IPC_EVENT_INPUT = ((1U << 31) | 21),
// Events sent from sway to clients. Events have the highest bits set.
IPC_EVENT_WORKSPACE = ((1<<31) | 0),
IPC_EVENT_OUTPUT = ((1<<31) | 1),
IPC_EVENT_MODE = ((1<<31) | 2),
IPC_EVENT_WINDOW = ((1<<31) | 3),
IPC_EVENT_BARCONFIG_UPDATE = ((1<<31) | 4),
IPC_EVENT_BINDING = ((1<<31) | 5),
IPC_EVENT_SHUTDOWN = ((1<<31) | 6),
IPC_EVENT_TICK = ((1<<31) | 7),
};

View File

@ -1,67 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <xkbcommon/xkbregistry.h>
#include <map>
#include <string>
#include "ALabel.hpp"
#include "bar.hpp"
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
#include "util/json.hpp"
namespace waybar::modules::sway {
class Language : public ALabel, public sigc::trackable {
public:
Language(const std::string& id, const Json::Value& config);
virtual ~Language() = default;
auto update() -> void override;
private:
enum class DispayedShortFlag { None = 0, ShortName = 1, ShortDescription = 1 << 1 };
struct Layout {
std::string full_name;
std::string short_name;
std::string variant;
std::string short_description;
std::string country_flag() const;
};
class XKBContext {
public:
XKBContext();
~XKBContext();
auto next_layout() -> Layout*;
private:
rxkb_context* context_ = nullptr;
rxkb_layout* xkb_layout_ = nullptr;
Layout* layout_ = nullptr;
std::map<std::string, rxkb_layout*> base_layouts_by_name_;
};
void onEvent(const struct Ipc::ipc_response&);
void onCmd(const struct Ipc::ipc_response&);
auto set_current_layout(std::string current_layout) -> void;
auto init_layouts_map(const std::vector<std::string>& used_layouts) -> void;
const static std::string XKB_LAYOUT_NAMES_KEY;
const static std::string XKB_ACTIVE_LAYOUT_NAME_KEY;
Layout layout_;
std::string tooltip_format_ = "";
std::map<std::string, Layout> layouts_map_;
bool is_variant_displayed;
std::byte displayed_short_flag = static_cast<std::byte>(DispayedShortFlag::None);
util::JsonParser parser_;
std::mutex mutex_;
Ipc ipc_;
};
} // namespace waybar::modules::sway

View File

@ -1,28 +0,0 @@
#pragma once
#include <fmt/format.h>
#include "ALabel.hpp"
#include "bar.hpp"
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
#include "util/json.hpp"
namespace waybar::modules::sway {
class Mode : public ALabel, public sigc::trackable {
public:
Mode(const std::string&, const Json::Value&);
virtual ~Mode() = default;
auto update() -> void override;
private:
void onEvent(const struct Ipc::ipc_response&);
std::string mode_;
util::JsonParser parser_;
std::mutex mutex_;
Ipc ipc_;
};
} // namespace waybar::modules::sway

View File

@ -1,35 +0,0 @@
#pragma once
#include <gtkmm/label.h>
#include <mutex>
#include <string>
#include "ALabel.hpp"
#include "bar.hpp"
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
#include "util/json.hpp"
namespace waybar::modules::sway {
class Scratchpad : public ALabel {
public:
Scratchpad(const std::string&, const Json::Value&);
virtual ~Scratchpad() = default;
auto update() -> void override;
private:
auto getTree() -> void;
auto onCmd(const struct Ipc::ipc_response&) -> void;
auto onEvent(const struct Ipc::ipc_response&) -> void;
std::string tooltip_format_;
bool show_empty_;
bool tooltip_enabled_;
std::string tooltip_text_;
int count_;
std::mutex mutex_;
Ipc ipc_;
util::JsonParser parser_;
};
} // namespace waybar::modules::sway

View File

@ -1,44 +1,29 @@
#pragma once
#include <fmt/format.h>
#include <tuple>
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
#include "util/chrono.hpp"
#include "util/json.hpp"
#include "ALabel.hpp"
namespace waybar::modules::sway {
class Window : public AAppIconLabel, public sigc::trackable {
public:
Window(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Window() = default;
auto update() -> void override;
class Window : public ALabel {
public:
Window(waybar::Bar&, Json::Value);
~Window();
auto update() -> void;
private:
std::string getFocusedNode(Json::Value nodes);
void getFocusedWindow();
private:
void setClass(std::string classname, bool enable);
void onEvent(const struct Ipc::ipc_response&);
void onCmd(const struct Ipc::ipc_response&);
std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string>
getFocusedNode(const Json::Value& nodes, std::string& output);
void getTree();
const Bar& bar_;
std::string window_;
int windowId_;
std::string app_id_;
std::string app_class_;
std::string layout_;
std::string old_app_id_;
std::size_t app_nb_;
std::string shell_;
int floating_count_;
util::JsonParser parser_;
std::mutex mutex_;
Ipc ipc_;
Bar& bar_;
waybar::util::SleeperThread thread_;
util::JsonParser parser_;
int ipcfd_;
int ipc_eventfd_;
std::string window_;
};
} // namespace waybar::modules::sway
}

View File

@ -1,53 +1,38 @@
#pragma once
#include <fmt/format.h>
#include <gtkmm/button.h>
#include <gtkmm/label.h>
#include <string_view>
#include <unordered_map>
#include "AModule.hpp"
#include "bar.hpp"
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
#include "util/chrono.hpp"
#include "util/json.hpp"
#include "IModule.hpp"
namespace waybar::modules::sway {
class Workspaces : public AModule, public sigc::trackable {
public:
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Workspaces() = default;
auto update() -> void override;
class Workspaces : public IModule {
public:
Workspaces(waybar::Bar&, Json::Value);
~Workspaces();
auto update() -> void;
operator Gtk::Widget &();
private:
void addWorkspace(Json::Value);
std::string getIcon(std::string);
bool handleScroll(GdkEventScroll*);
int getPrevWorkspace();
int getNextWorkspace();
private:
static constexpr std::string_view workspace_switch_cmd_ = "workspace {} \"{}\"";
static constexpr std::string_view persistent_workspace_switch_cmd_ =
R"(workspace {} "{}"; move workspace to output "{}"; workspace {} "{}")";
static int convertWorkspaceNameToNum(std::string name);
void onCmd(const struct Ipc::ipc_response&);
void onEvent(const struct Ipc::ipc_response&);
bool filterButtons();
Gtk::Button& addButton(const Json::Value&);
void onButtonReady(const Json::Value&, Gtk::Button&);
std::string getIcon(const std::string&, const Json::Value&);
const std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const;
uint16_t getWorkspaceIndex(const std::string& name) const;
std::string trimWorkspaceName(std::string);
bool handleScroll(GdkEventScroll*) override;
const Bar& bar_;
std::vector<Json::Value> workspaces_;
std::vector<std::string> high_priority_named_;
std::vector<std::string> workspaces_order_;
Gtk::Box box_;
util::JsonParser parser_;
std::unordered_map<std::string, Gtk::Button> buttons_;
std::mutex mutex_;
Ipc ipc_;
Bar& bar_;
Json::Value config_;
waybar::util::SleeperThread thread_;
Gtk::Box box_;
util::JsonParser parser_;
std::mutex mutex_;
bool scrolling_;
std::unordered_map<int, Gtk::Button> buttons_;
Json::Value workspaces_;
int ipcfd_;
int ipc_eventfd_;
};
} // namespace waybar::modules::sway
}

View File

@ -1,26 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <fstream>
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Temperature : public ALabel {
public:
Temperature(const std::string&, const Json::Value&);
virtual ~Temperature() = default;
auto update() -> void override;
private:
float getTemperature();
bool isCritical(uint16_t);
std::string file_path_;
util::SleeperThread thread_;
};
} // namespace waybar::modules

View File

@ -1,80 +0,0 @@
#pragma once
#include <libupower-glib/upower.h>
#include <iostream>
#include <map>
#include <string>
#include <unordered_map>
#include "ALabel.hpp"
#include "glibconfig.h"
#include "gtkmm/box.h"
#include "gtkmm/image.h"
#include "gtkmm/label.h"
#include "modules/upower/upower_tooltip.hpp"
namespace waybar::modules::upower {
class UPower : public AModule {
public:
UPower(const std::string &, const Json::Value &);
virtual ~UPower();
auto update() -> void override;
private:
typedef std::unordered_map<std::string, UpDevice *> Devices;
const std::string DEFAULT_FORMAT = "{percentage}";
const std::string DEFAULT_FORMAT_ALT = "{percentage} {time}";
static void deviceAdded_cb(UpClient *client, UpDevice *device, gpointer data);
static void deviceRemoved_cb(UpClient *client, const gchar *objectPath, gpointer data);
static void deviceNotify_cb(UpDevice *device, GParamSpec *pspec, gpointer user_data);
static void prepareForSleep_cb(GDBusConnection *system_bus, const gchar *sender_name,
const gchar *object_path, const gchar *interface_name,
const gchar *signal_name, GVariant *parameters,
gpointer user_data);
static void upowerAppear(GDBusConnection *conn, const gchar *name, const gchar *name_owner,
gpointer data);
static void upowerDisappear(GDBusConnection *connection, const gchar *name, gpointer user_data);
void removeDevice(const gchar *objectPath);
void addDevice(UpDevice *device);
void setDisplayDevice();
void resetDevices();
void removeDevices();
bool show_tooltip_callback(int, int, bool, const Glib::RefPtr<Gtk::Tooltip> &tooltip);
bool handleToggle(GdkEventButton *const &) override;
std::string timeToString(gint64 time);
const std::string getDeviceStatus(UpDeviceState &state);
Gtk::Box box_;
Gtk::Image icon_;
Gtk::Label label_;
// Config
bool hideIfEmpty = true;
bool tooltip_enabled = true;
uint tooltip_spacing = 4;
uint tooltip_padding = 4;
uint iconSize = 20;
std::string format = DEFAULT_FORMAT;
std::string format_alt = DEFAULT_FORMAT_ALT;
Devices devices;
std::mutex m_Mutex;
UpClient *client;
UpDevice *displayDevice;
guint login1_id;
GDBusConnection *login1_connection;
UPowerTooltip *upower_tooltip;
std::string lastStatus;
bool showAltText;
bool upowerRunning;
guint upowerWatcher_id;
std::string nativePath_;
};
} // namespace waybar::modules::upower

View File

@ -1,32 +0,0 @@
#pragma once
#include <libupower-glib/upower.h>
#include <unordered_map>
#include "gtkmm/box.h"
#include "gtkmm/label.h"
#include "gtkmm/window.h"
namespace waybar::modules::upower {
class UPowerTooltip : public Gtk::Window {
private:
typedef std::unordered_map<std::string, UpDevice*> Devices;
const std::string getDeviceIcon(UpDeviceKind& kind);
Gtk::Box* contentBox;
uint iconSize;
uint tooltipSpacing;
uint tooltipPadding;
public:
UPowerTooltip(uint iconSize, uint tooltipSpacing, uint tooltipPadding);
virtual ~UPowerTooltip();
uint updateTooltip(Devices& devices);
};
} // namespace waybar::modules::upower

View File

@ -1,34 +0,0 @@
#pragma once
#include <fmt/chrono.h>
#include <gdkmm/pixbuf.h>
#include <glibmm/refptr.h>
#include "AIconLabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class User : public AIconLabel {
public:
User(const std::string&, const Json::Value&);
virtual ~User() = default;
auto update() -> void override;
bool handleToggle(GdkEventButton* const& e) override;
private:
util::SleeperThread thread_;
static constexpr inline int defaultUserImageWidth_ = 20;
static constexpr inline int defaultUserImageHeight_ = 20;
long uptime_as_seconds();
std::string get_user_login() const;
std::string get_user_home_dir() const;
std::string get_default_user_avatar_path() const;
void init_default_user_avatar(int width, int height);
void init_user_avatar(const std::string& path, int width, int height);
void init_avatar(const Json::Value& config);
void init_update_worker();
};
} // namespace waybar::modules

View File

@ -1,46 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <wp/wp.h>
#include <algorithm>
#include <array>
#include "ALabel.hpp"
namespace waybar::modules {
class Wireplumber : public ALabel {
public:
Wireplumber(const std::string&, const Json::Value&);
virtual ~Wireplumber();
auto update() -> void override;
private:
void loadRequiredApiModules();
void prepare();
void activatePlugins();
static void updateVolume(waybar::modules::Wireplumber* self, uint32_t id);
static void updateNodeName(waybar::modules::Wireplumber* self, uint32_t id);
static void onPluginActivated(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
static void onObjectManagerInstalled(waybar::modules::Wireplumber* self);
static void onMixerChanged(waybar::modules::Wireplumber* self, uint32_t id);
static void onDefaultNodesApiChanged(waybar::modules::Wireplumber* self);
bool handleScroll(GdkEventScroll* e) override;
WpCore* wp_core_;
GPtrArray* apis_;
WpObjectManager* om_;
WpPlugin* mixer_api_;
WpPlugin* def_nodes_api_;
gchar* default_node_name_;
uint32_t pending_plugins_;
bool muted_;
double volume_;
double min_step_;
uint32_t node_id_{0};
std::string node_name_;
};
} // namespace waybar::modules

View File

@ -1,179 +0,0 @@
#pragma once
#include <gdk/gdk.h>
#include <glibmm/refptr.h>
#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/icontheme.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>
#include <wayland-client.h>
#include <map>
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
#include "AModule.hpp"
#include "bar.hpp"
#include "client.hpp"
#include "giomm/desktopappinfo.h"
#include "util/json.hpp"
#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
namespace waybar::modules::wlr {
class Taskbar;
class Task {
public:
Task(const waybar::Bar &, const Json::Value &, Taskbar *,
struct zwlr_foreign_toplevel_handle_v1 *, struct wl_seat *);
~Task();
public:
enum State {
MAXIMIZED = (1 << 0),
MINIMIZED = (1 << 1),
ACTIVE = (1 << 2),
FULLSCREEN = (1 << 3),
INVALID = (1 << 4)
};
// made public so TaskBar can reorder based on configuration.
Gtk::Button button;
private:
static uint32_t global_id;
private:
const waybar::Bar &bar_;
const Json::Value &config_;
Taskbar *tbar_;
struct zwlr_foreign_toplevel_handle_v1 *handle_;
struct wl_seat *seat_;
uint32_t id_;
Gtk::Box content_;
Gtk::Image icon_;
Gtk::Label text_before_;
Gtk::Label text_after_;
Glib::RefPtr<Gio::DesktopAppInfo> app_info_;
bool button_visible_ = false;
bool ignored_ = false;
bool with_icon_ = false;
bool with_name_ = false;
std::string format_before_;
std::string format_after_;
std::string format_tooltip_;
std::string name_;
std::string title_;
std::string app_id_;
uint32_t state_ = 0;
int32_t drag_start_x;
int32_t drag_start_y;
int32_t drag_start_button = -1;
private:
std::string repr() const;
std::string state_string(bool = false) const;
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();
public:
/* Getter functions */
uint32_t id() const { return id_; }
std::string title() const { return title_; }
std::string app_id() const { return app_id_; }
uint32_t state() const { return state_; }
bool maximized() const { return state_ & MAXIMIZED; }
bool minimized() const { return state_ & MINIMIZED; }
bool active() const { return state_ & ACTIVE; }
bool fullscreen() const { return state_ & FULLSCREEN; }
public:
/* Callbacks for the wlr protocol */
void handle_title(const char *);
void handle_app_id(const char *);
void handle_output_enter(struct wl_output *);
void handle_output_leave(struct wl_output *);
void handle_state(struct wl_array *);
void handle_done();
void handle_closed();
/* Callbacks for Gtk events */
bool handle_clicked(GdkEventButton *);
bool handle_button_release(GdkEventButton *);
bool handle_motion_notify(GdkEventMotion *);
void handle_drag_data_get(const Glib::RefPtr<Gdk::DragContext> &context,
Gtk::SelectionData &selection_data, guint info, guint time);
void handle_drag_data_received(const Glib::RefPtr<Gdk::DragContext> &context, int x, int y,
Gtk::SelectionData selection_data, guint info, guint time);
public:
bool operator==(const Task &) const;
bool operator!=(const Task &) const;
public:
void update();
public:
/* Interaction with the tasks */
void maximize(bool);
void minimize(bool);
void activate();
void fullscreen(bool);
void close();
};
using TaskPtr = std::unique_ptr<Task>;
class Taskbar : public waybar::AModule {
public:
Taskbar(const std::string &, const waybar::Bar &, const Json::Value &);
~Taskbar();
void update();
private:
const waybar::Bar &bar_;
Gtk::Box box_;
std::vector<TaskPtr> tasks_;
std::vector<Glib::RefPtr<Gtk::IconTheme>> icon_themes_;
std::unordered_set<std::string> ignore_list_;
std::map<std::string, std::string> app_ids_replace_map_;
struct zwlr_foreign_toplevel_manager_v1 *manager_;
struct wl_seat *seat_;
public:
/* Callbacks for global registration */
void register_manager(struct wl_registry *, uint32_t name, uint32_t version);
void register_seat(struct wl_registry *, uint32_t name, uint32_t version);
/* Callbacks for the wlr protocol */
void handle_toplevel_create(struct zwlr_foreign_toplevel_handle_v1 *);
void handle_finished();
public:
void add_button(Gtk::Button &);
void move_button(Gtk::Button &, int);
void remove_button(Gtk::Button &);
void remove_task(uint32_t);
bool show_output(struct wl_output *) const;
bool all_outputs() const;
const std::vector<Glib::RefPtr<Gtk::IconTheme>> &icon_themes() const;
const std::unordered_set<std::string> &ignore_list() const;
const std::map<std::string, std::string> &app_ids_replace_map() const;
};
} /* namespace waybar::modules::wlr */

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

View File

@ -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

View File

@ -1,75 +0,0 @@
#pragma once
#include <glibmm/dispatcher.h>
#include <sigc++/signal.h>
#include <functional>
#include <mutex>
#include <queue>
#include <thread>
#include <tuple>
#include <type_traits>
#include <utility>
namespace waybar {
/**
* Thread-safe signal wrapper.
* Uses Glib::Dispatcher to pass events to another thread and locked queue to pass the arguments.
*/
template <typename... Args>
struct SafeSignal : sigc::signal<void(std::decay_t<Args>...)> {
public:
SafeSignal() { dp_.connect(sigc::mem_fun(*this, &SafeSignal::handle_event)); }
template <typename... EmitArgs>
void emit(EmitArgs&&... args) {
if (main_tid_ == std::this_thread::get_id()) {
/*
* Bypass the queue if the method is called the main thread.
* Ensures that events emitted from the main thread are processed synchronously and saves a
* few CPU cycles on locking/queuing.
* As a downside, this makes main thread events prioritized over the other threads and
* disrupts chronological order.
*/
signal_t::emit(std::forward<EmitArgs>(args)...);
} else {
{
std::unique_lock lock(mutex_);
queue_.emplace(std::forward<EmitArgs>(args)...);
}
dp_.emit();
}
}
template <typename... EmitArgs>
inline void operator()(EmitArgs&&... args) {
emit(std::forward<EmitArgs>(args)...);
}
protected:
using signal_t = sigc::signal<void(std::decay_t<Args>...)>;
using slot_t = decltype(std::declval<signal_t>().make_slot());
using arg_tuple_t = std::tuple<std::decay_t<Args>...>;
// ensure that unwrapped methods are not accessible
using signal_t::emit_reverse;
using signal_t::make_slot;
void handle_event() {
for (std::unique_lock lock(mutex_); !queue_.empty(); lock.lock()) {
auto args = queue_.front();
queue_.pop();
lock.unlock();
std::apply(cached_fn_, args);
}
}
Glib::Dispatcher dp_;
std::mutex mutex_;
std::queue<arg_tuple_t> queue_;
const std::thread::id main_tid_ = std::this_thread::get_id();
// cache functor for signal emission to avoid recreating it on each event
const slot_t cached_fn_ = make_slot();
};
} // namespace waybar

93
include/util/chrono.hpp Normal file
View File

@ -0,0 +1,93 @@
#pragma once
#include <chrono>
#include <ctime>
#include <functional>
#include <condition_variable>
#include <thread>
#include <gtkmm.h>
namespace waybar::chrono {
using namespace std::chrono;
using clock = std::chrono::system_clock;
using duration = clock::duration;
using time_point = std::chrono::time_point<clock, duration>;
}
namespace waybar::util {
struct SleeperThread {
SleeperThread() = default;
SleeperThread(std::function<void()> func)
: thread_{[this, func] {
while(true) {
{
std::lock_guard<std::mutex> lock(mutex_);
if (!do_run_) {
break;
}
}
func();
}
}}
{}
SleeperThread& operator=(std::function<void()> func)
{
thread_ = std::thread([this, func] {
while(true) {
{
std::lock_guard<std::mutex> lock(mutex_);
if (!do_run_) {
break;
}
}
func();
}
});
return *this;
}
auto sleep_for(chrono::duration dur)
{
auto lock = std::unique_lock(mutex_);
return condvar_.wait_for(lock, dur);
}
auto sleep_until(chrono::time_point time)
{
auto lock = std::unique_lock(mutex_);
return condvar_.wait_until(lock, time);
}
auto wake_up()
{
condvar_.notify_all();
}
~SleeperThread()
{
do_run_ = false;
condvar_.notify_all();
auto native_handle = thread_.native_handle();
pthread_cancel(native_handle);
if (thread_.joinable()) {
thread_.join();
}
}
sigc::signal<void> sig_update;
private:
std::thread thread_;
std::condition_variable condvar_;
std::mutex mutex_;
bool do_run_ = true;
};
}

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +1,21 @@
#pragma once
#include <fcntl.h>
#include <giomm.h>
#include <spdlog/spdlog.h>
#include <sys/wait.h>
#include <unistd.h>
#ifdef __linux__
#include <sys/prctl.h>
#endif
#ifdef __FreeBSD__
#include <sys/procctl.h>
#endif
#include <array>
extern std::mutex reap_mtx;
extern std::list<pid_t> reap;
namespace waybar::util::command {
struct res {
struct cmd_res {
int exit_code;
std::string out;
};
inline std::string read(FILE* fp) {
inline struct cmd_res exec(const std::string cmd)
{
FILE* fp(popen(cmd.c_str(), "r"));
if (!fp) {
return { -1, "" };
}
std::array<char, 128> buffer = {0};
std::string output;
while (feof(fp) == 0) {
@ -35,135 +25,11 @@ inline std::string read(FILE* fp) {
}
// Remove last newline
if (!output.empty() && output[output.length() - 1] == '\n') {
output.erase(output.length() - 1);
if (!output.empty() && output[output.length()-1] == '\n') {
output.erase(output.length()-1);
}
return output;
int exit_code = WEXITSTATUS(pclose(fp));
return { exit_code, output };
}
inline int close(FILE* fp, pid_t pid) {
int stat = -1;
pid_t ret;
fclose(fp);
do {
ret = waitpid(pid, &stat, WCONTINUED | WUNTRACED);
if (WIFEXITED(stat)) {
spdlog::debug("Cmd exited with code {}", WEXITSTATUS(stat));
} else if (WIFSIGNALED(stat)) {
spdlog::debug("Cmd killed by {}", WTERMSIG(stat));
} else if (WIFSTOPPED(stat)) {
spdlog::debug("Cmd stopped by {}", WSTOPSIG(stat));
} else if (WIFCONTINUED(stat)) {
spdlog::debug("Cmd continued");
} else if (ret == -1) {
spdlog::debug("waitpid failed: {}", strerror(errno));
} else {
break;
}
} while (!WIFEXITED(stat) && !WIFSIGNALED(stat));
return stat;
}
inline FILE* open(const std::string& cmd, int& pid) {
if (cmd == "") return nullptr;
int fd[2];
// Open the pipe with the close-on-exec flag set, so it will not be inherited
// by any other subprocesses launched by other threads (which could result in
// the pipe staying open after this child dies, causing us to hang when trying
// to read from it)
if (pipe2(fd, O_CLOEXEC) != 0) {
spdlog::error("Unable to pipe fd");
return nullptr;
}
pid_t child_pid = fork();
if (child_pid < 0) {
spdlog::error("Unable to exec cmd {}, error {}", cmd.c_str(), strerror(errno));
::close(fd[0]);
::close(fd[1]);
return nullptr;
}
if (!child_pid) {
int err;
sigset_t mask;
sigfillset(&mask);
// Reset sigmask
err = pthread_sigmask(SIG_UNBLOCK, &mask, nullptr);
if (err != 0) spdlog::error("pthread_sigmask in open failed: {}", strerror(err));
// Kill child if Waybar exits
int deathsig = SIGTERM;
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, deathsig) != 0) {
spdlog::error("prctl(PR_SET_PDEATHSIG) in open failed: {}", strerror(errno));
}
#endif
#ifdef __FreeBSD__
if (procctl(P_PID, 0, PROC_PDEATHSIG_CTL, reinterpret_cast<void*>(&deathsig)) == -1) {
spdlog::error("procctl(PROC_PDEATHSIG_CTL) in open failed: {}", strerror(errno));
}
#endif
::close(fd[0]);
dup2(fd[1], 1);
setpgid(child_pid, child_pid);
execlp("/bin/sh", "sh", "-c", cmd.c_str(), (char*)0);
exit(0);
} else {
::close(fd[1]);
}
pid = child_pid;
return fdopen(fd[0], "r");
}
inline struct res exec(const std::string& cmd) {
int pid;
auto fp = command::open(cmd, pid);
if (!fp) return {-1, ""};
auto output = command::read(fp);
auto stat = command::close(fp, pid);
return {WEXITSTATUS(stat), output};
}
inline struct res execNoRead(const std::string& cmd) {
int pid;
auto fp = command::open(cmd, pid);
if (!fp) return {-1, ""};
auto stat = command::close(fp, pid);
return {WEXITSTATUS(stat), ""};
}
inline int32_t forkExec(const std::string& cmd) {
if (cmd == "") return -1;
pid_t pid = fork();
if (pid < 0) {
spdlog::error("Unable to exec cmd {}, error {}", cmd.c_str(), strerror(errno));
return pid;
}
// Child executes the command
if (!pid) {
int err;
sigset_t mask;
sigfillset(&mask);
// Reset sigmask
err = pthread_sigmask(SIG_UNBLOCK, &mask, nullptr);
if (err != 0) spdlog::error("pthread_sigmask in forkExec failed: {}", strerror(err));
setpgid(pid, pid);
execl("/bin/sh", "sh", "-c", cmd.c_str(), (char*)0);
exit(0);
} else {
reap_mtx.lock();
reap.push_back(pid);
reap_mtx.unlock();
spdlog::debug("Added child to reap list: {}", pid);
}
return pid;
}
} // namespace waybar::util::command

View File

@ -1,60 +0,0 @@
#pragma once
#include <fmt/format.h>
#if HAVE_CHRONO_TIMEZONES
#include <chrono>
#include <format>
/* Compatibility layer for <date/tz.h> on top of C++20 <chrono> */
namespace date {
using namespace std::chrono;
namespace literals {
using std::chrono::last;
}
inline auto format(const std::string& spec, const auto& ztime) {
return spec.empty() ? "" : std::vformat("{:L" + spec + "}", std::make_format_args(ztime));
}
inline auto format(const std::locale& loc, const std::string& spec, const auto& ztime) {
return spec.empty() ? "" : std::vformat(loc, "{:L" + spec + "}", std::make_format_args(ztime));
}
} // namespace date
#else
#include <date/tz.h>
#endif
template <typename Duration, typename TimeZonePtr>
struct fmt::formatter<date::zoned_time<Duration, TimeZonePtr>> {
std::string_view specs;
template <typename ParseContext>
constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
auto it = ctx.begin();
if (it != ctx.end() && *it == ':') {
++it;
}
auto end = it;
while (end != ctx.end() && *end != '}') {
++end;
}
if (end != it) {
specs = {it, std::string_view::size_type(end - it)};
}
return end;
}
template <typename FormatContext>
auto format(const date::zoned_time<Duration, TimeZonePtr>& ztime, FormatContext& ctx) {
if (ctx.locale()) {
const auto loc = ctx.locale().template get<std::locale>();
return fmt::format_to(ctx.out(), "{}", date::format(loc, fmt::to_string(specs), ztime));
}
return fmt::format_to(ctx.out(), "{}", date::format(fmt::to_string(specs), ztime));
}
};

View File

@ -1,99 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <glibmm/ustring.h>
class pow_format {
public:
pow_format(long long val, std::string&& unit, bool binary = false)
: val_(val), unit_(unit), binary_(binary){};
long long val_;
std::string unit_;
bool binary_;
};
namespace fmt {
template <>
struct formatter<pow_format> {
char spec = 0;
int width = 0;
template <typename ParseContext>
constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
auto it = ctx.begin(), end = ctx.end();
if (it != end && *it == ':') ++it;
if (it && (*it == '>' || *it == '<' || *it == '=')) {
spec = *it;
++it;
}
if (it == end || *it == '}') return it;
if ('0' <= *it && *it <= '9') {
// We ignore it for now, but keep it for compatibility with
// existing configs where the format for pow_format'ed numbers was
// 'string' and specifications such as {:>9} were valid.
// The rationale for ignoring it is that the only reason to specify
// an alignment and a with is to get a fixed width bar, and ">" is
// sufficient in this implementation.
#if FMT_VERSION < 80000
width = parse_nonnegative_int(it, end, ctx);
#else
width = detail::parse_nonnegative_int(it, end, -1);
#endif
}
return it;
}
template <class FormatContext>
auto format(const pow_format& s, FormatContext& ctx) -> decltype(ctx.out()) {
const char* units[] = {"", "k", "M", "G", "T", "P", nullptr};
auto base = s.binary_ ? 1024ull : 1000ll;
auto fraction = (double)s.val_;
int pow;
for (pow = 0; units[pow + 1] != nullptr && fraction / base >= 1; ++pow) {
fraction /= base;
}
auto number_width = 5 // coeff in {:.1f} format
+ s.binary_; // potential 4th digit before the decimal point
auto max_width = number_width + 1 // prefix from units array
+ s.binary_ // for the 'i' in GiB.
+ s.unit_.length();
const char* format;
std::string string;
switch (spec) {
case '>':
return fmt::format_to(ctx.out(), "{:>{}}", fmt::format("{}", s), max_width);
case '<':
return fmt::format_to(ctx.out(), "{:<{}}", fmt::format("{}", s), max_width);
case '=':
format = "{coefficient:<{number_width}.1f}{padding}{prefix}{unit}";
break;
case 0:
default:
format = "{coefficient:.1f}{prefix}{unit}";
break;
}
return fmt::format_to(
ctx.out(), fmt::runtime(format), fmt::arg("coefficient", fraction),
fmt::arg("number_width", number_width),
fmt::arg("prefix", std::string() + units[pow] + ((s.binary_ && pow) ? "i" : "")),
fmt::arg("unit", s.unit_),
fmt::arg("padding", pow ? ""
: s.binary_ ? " "
: " "));
}
};
// Glib ustirng support
template <>
struct formatter<Glib::ustring> : formatter<std::string> {
template <typename FormatContext>
auto format(const Glib::ustring& value, FormatContext& ctx) {
return formatter<std::string>::format(static_cast<std::string>(value), ctx);
}
};
} // namespace fmt

View File

@ -1,14 +0,0 @@
#pragma once
#include <gtkmm/icontheme.h>
#include <mutex>
#include <string>
class DefaultGtkIconThemeWrapper {
private:
static std::mutex default_theme_mutex;
public:
static bool has_icon(const std::string&);
static Glib::RefPtr<Gdk::Pixbuf> load_icon(const char*, int, Gtk::IconLookupFlags);
};

View File

@ -1,36 +1,38 @@
#pragma once
#include <fmt/ostream.h>
#include <json/json.h>
#if (FMT_VERSION >= 90000)
template <>
struct fmt::formatter<Json::Value> : ostream_formatter {};
#endif
namespace waybar::util {
struct JsonParser {
JsonParser() {}
const Json::Value parse(const std::string& data) const {
Json::Value root(Json::objectValue);
if (data.empty()) {
return root;
}
std::unique_ptr<Json::CharReader> const reader(builder_.newCharReader());
JsonParser()
: _reader(_builder.newCharReader())
{}
Json::Value parse(const std::string data)
{
Json::Value root;
std::string err;
bool res = reader->parse(data.c_str(), data.c_str() + data.size(), &root, &err);
if (!res) throw std::runtime_error(err);
if (_reader == nullptr) {
throw std::runtime_error("Unable to parse");
}
bool res =
_reader->parse(data.c_str(), data.c_str() + data.size(), &root, &err);
if (!res)
throw std::runtime_error(err);
return root;
}
~JsonParser() = default;
~JsonParser()
{
delete _reader;
_reader = nullptr;
}
private:
Json::CharReaderBuilder builder_;
private:
Json::CharReaderBuilder _builder;
Json::CharReader *_reader;
};
} // namespace waybar::util
}

View File

@ -1,9 +0,0 @@
#pragma once
#include "SafeSignal.hpp"
namespace waybar::util {
// Get a signal emited with value true when entering sleep, and false when exiting
SafeSignal<bool>& prepare_for_sleep();
} // namespace waybar::util

View File

@ -1,8 +0,0 @@
#pragma once
#include <json/json.h>
#include <string>
namespace waybar::util {
std::string rewriteString(const std::string&, const Json::Value&);
}

View File

@ -1,26 +0,0 @@
#pragma once
#include <glibmm/iochannel.h>
#include <linux/rfkill.h>
#include <sigc++/signal.h>
#include <sigc++/trackable.h>
namespace waybar::util {
class Rfkill : public sigc::trackable {
public:
Rfkill(enum rfkill_type rfkill_type);
~Rfkill();
bool getState() const;
sigc::signal<void(struct rfkill_event&)> on_update;
private:
enum rfkill_type rfkill_type_;
bool state_ = false;
int fd_ = -1;
bool on_event(Glib::IOCondition cond);
};
} // namespace waybar::util

View File

@ -1,6 +0,0 @@
#pragma once
#include <string>
namespace waybar::util {
std::string sanitize_string(std::string str);
} // namespace waybar::util

View File

@ -1,114 +0,0 @@
#pragma once
#include <chrono>
#include <condition_variable>
#include <ctime>
#include <functional>
#include <thread>
#include "prepare_for_sleep.h"
namespace waybar::util {
/**
* Defer pthread_cancel until the end of a current scope.
*
* Required to protect a scope where it's unsafe to raise `__forced_unwind` exception.
* An example of these is a call of a method marked as `noexcept`; an attempt to cancel within such
* a method may result in a `std::terminate` call.
*/
class CancellationGuard {
int oldstate;
public:
CancellationGuard() { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); }
~CancellationGuard() { pthread_setcancelstate(oldstate, &oldstate); }
};
class SleeperThread {
public:
SleeperThread() = default;
SleeperThread(std::function<void()> func)
: thread_{[this, func] {
while (do_run_) {
signal_ = false;
func();
}
}} {
connection_ = prepare_for_sleep().connect([this](bool sleep) {
if (not sleep) wake_up();
});
}
SleeperThread& operator=(std::function<void()> func) {
thread_ = std::thread([this, func] {
while (do_run_) {
signal_ = false;
func();
}
});
if (connection_.empty()) {
connection_ = prepare_for_sleep().connect([this](bool sleep) {
if (not sleep) wake_up();
});
}
return *this;
}
bool isRunning() const { return do_run_; }
auto sleep_for(std::chrono::system_clock::duration dur) {
std::unique_lock lk(mutex_);
CancellationGuard cancel_lock;
return condvar_.wait_for(lk, dur, [this] { return signal_ || !do_run_; });
}
auto sleep_until(
std::chrono::time_point<std::chrono::system_clock, std::chrono::system_clock::duration>
time_point) {
std::unique_lock lk(mutex_);
CancellationGuard cancel_lock;
return condvar_.wait_until(lk, time_point, [this] { return signal_ || !do_run_; });
}
void wake_up() {
{
std::lock_guard<std::mutex> lck(mutex_);
signal_ = true;
}
condvar_.notify_all();
}
auto stop() {
{
std::lock_guard<std::mutex> lck(mutex_);
signal_ = true;
do_run_ = false;
}
condvar_.notify_all();
auto handle = thread_.native_handle();
if (handle != 0) {
// TODO: find a proper way to terminate thread...
pthread_cancel(handle);
}
}
~SleeperThread() {
connection_.disconnect();
stop();
if (thread_.joinable()) {
thread_.join();
}
}
private:
std::thread thread_;
std::condition_variable condvar_;
std::mutex mutex_;
bool do_run_ = true;
bool signal_ = false;
sigc::connection connection_;
};
} // namespace waybar::util

View File

@ -1,17 +0,0 @@
#pragma once
#include <string>
const std::string WHITESPACE = " \n\r\t\f\v";
inline std::string ltrim(const std::string& s) {
size_t begin = s.find_first_not_of(WHITESPACE);
return (begin == std::string::npos) ? "" : s.substr(begin);
}
inline std::string rtrim(const std::string& s) {
size_t end = s.find_last_not_of(WHITESPACE);
return (end == std::string::npos) ? "" : s.substr(0, end + 1);
}
inline std::string trim(const std::string& s) { return rtrim(ltrim(s)); }

View File

@ -1,5 +0,0 @@
#pragma once
#include <glibmm/ustring.h>
// calculate column width of ustring
int ustring_clen(const Glib::ustring &str);

View File

@ -1,92 +0,0 @@
waybar-backlight(5)
# NAME
waybar - backlight module
# DESCRIPTION
The *backlight* module displays the current backlight level.
# CONFIGURATION
*interval*: ++
typeof: integer ++
default: 2 ++
The interval in which information gets polled.
*format*: ++
typeof: string ++
default: {percent}% ++
The format, how information should be displayed. On {} data gets inserted.
*max-length*: ++
typeof: integer ++
The maximum length in characters the module should display.
*min-length*: ++
typeof: integer ++
The minimum length in characters the module should take up.
*align*: ++
typeof: float ++
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*rotate*: ++
typeof: integer ++
Positive value to rotate the text label.
*states*: ++
typeof: object ++
A number of backlight states which get activated on certain brightness levels. See *waybar-states(5)*.
*on-click*: ++
typeof: string ++
Command to execute when the module is clicked.
*on-click-middle*: ++
typeof: string ++
Command to execute when middle-clicked on the module using mousewheel.
*on-click-right*: ++
typeof: string ++
Command to execute when the module is right clicked.
*on-update*: ++
typeof: string ++
Command to execute when the module is updated.
*on-scroll-up*: ++
typeof: string ++
Command to execute when performing a scroll up on the module. This replaces the default behaviour of brightness control.
*on-scroll-down*: ++
typeof: string
Command to execute when performing a scroll down on the module. This replaces the default behaviour of brightness control.
*smooth-scrolling-threshold*: ++
typeof: double
Threshold to be used when scrolling.
*reverse-scrolling*: ++
typeof: bool ++
Option to reverse the scroll direction.
*scroll-step*: ++
typeof: float ++
default: 1.0 ++
The speed in which to change the brightness when scrolling.
# EXAMPLE:
```
"backlight": {
"device": "intel_backlight",
"format": "{percent}% {icon}",
"format-icons": ["", ""]
}
```
# STYLE
- *#backlight*

View File

@ -1,164 +0,0 @@
waybar-battery(5)
# NAME
waybar - battery module
# DESCRIPTION
The *battery* module displays the current capacity and state (eg. charging) of your battery.
# CONFIGURATION
*bat*: ++
typeof: string ++
The battery to monitor, as in /sys/class/power_supply/ instead of auto detect.
*adapter*: ++
typeof: string ++
The adapter to monitor, as in /sys/class/power_supply/ instead of auto detect.
*full-at*: ++
typeof: integer ++
Define the max percentage of the battery, for when you've set the battery to stop charging at a lower level to save it. For example, if you've set the battery to stop at 80% that will become the new 100%.
*design-capacity*: ++
typeof: bool ++
default: false ++
Option to use the battery design capacity instead of it's current maximal capacity.
*interval*: ++
typeof: integer ++
default: 60 ++
The interval in which the information gets polled.
*states*: ++
typeof: object ++
A number of battery states which get activated on certain capacity levels. See *waybar-states(5)*.
*format*: ++
typeof: string ++
default: {capacity}% ++
The format, how information should be displayed.
*format-time*: ++
typeof: string ++
default: {H} h {M} min ++
The format, how the time should be displayed.
*format-icons*: ++
typeof: array/object ++
Based on the current capacity, the corresponding icon gets selected. ++
The order is *low* to *high*. Or by the state if it is an object.
*max-length*: ++
typeof: integer++
The maximum length in character the module should display.
*min-length*: ++
typeof: integer ++
The minimum length in characters the module should take up.
*align*: ++
typeof: float ++
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*rotate*: ++
typeof: integer++
Positive value to rotate the text label.
*on-click*: ++
typeof: string ++
Command to execute when clicked on the module.
*on-click-middle*: ++
typeof: string ++
Command to execute when middle-clicked on the module using mousewheel.
*on-click-right*: ++
typeof: string ++
Command to execute when you right clicked on the module.
*on-update*: ++
typeof: string ++
Command to execute when the module is updated.
*on-scroll-up*: ++
typeof: string ++
Command to execute when scrolling up on the module.
*on-scroll-down*: ++
typeof: string ++
Command to execute when scrolling down on the module.
*smooth-scrolling-threshold*: ++
typeof: double ++
Threshold to be used when scrolling.
*tooltip*: ++
typeof: bool ++
default: true ++
Option to disable tooltip on hover.
# FORMAT REPLACEMENTS
*{capacity}*: Capacity in percentage
*{power}*: Power in watts
*{icon}*: Icon, as defined in *format-icons*.
*{time}*: Estimate of time until full or empty. Note that this is based on the power draw at the last refresh time, not an average.
# TIME FORMAT
The *battery* module allows you to define how time should be formatted via *format-time*.
The three arguments are:
*{H}*: Hours
*{M}*: Minutes
*{m}*: Zero-padded minutes
# CUSTOM FORMATS
The *battery* module allows one to define custom formats based on up to two factors. The best fitting format will be selected.
*format-<state>*: With *states*, a custom format can be set depending on the capacity of your battery.
*format-<status>*: With the status, a custom format can be set depending on the status in /sys/class/power_supply/<bat>/status (in lowercase).
*format-<status>-<state>*: You can also set a custom format depending on both values.
# STATES
- Every entry (*state*) consists of a *<name>* (typeof: *string*) and a *<value>* (typeof: *integer*).
- The state can be addressed as a CSS class in the *style.css*. The name of the CSS class is the *<name>* of the state. Each class gets activated when the current capacity is equal or below the configured *<value>*.
- Also each state can have its own *format*. Those con be configured via *format-<name>*. Or if you want to differentiate a bit more even as *format-<status>-<state>*. For more information see *custom-formats*.
# EXAMPLES
```
"battery": {
"bat": "BAT2",
"interval": 60,
"states": {
"warning": 30,
"critical": 15
},
"format": "{capacity}% {icon}",
"format-icons": ["", "", "", "", ""],
"max-length": 25
}
```
# STYLE
- *#battery*
- *#battery.<status>*
- *<status>* is the value of /sys/class/power_supply/<bat>/status in lowercase.
- *#battery.<state>*
- *<state>* can be defined in the *config*. For more information see *states*.
- *#battery.<status>.<state>*
- Combination of both *<status>* and *<state>*.

View File

@ -1,210 +0,0 @@
waybar-bluetooth(5)
# NAME
waybar - bluetooth module
# DESCRIPTION
The *bluetooth* module displays information about a bluetooth controller and its connections.
# CONFIGURATION
Addressed by *bluetooth*
*controller*: ++
typeof: string ++
Use the controller with the defined alias. Otherwise a random controller is used. Recommended to define when there is more than 1 controller available to the system.
*format-device-preference*: ++
typeof: array ++
A ranking of bluetooth devices, addressed by their alias. The order is from *first displayed* to *last displayed*. ++
If this config option is not defined or none of the devices in the list are connected, it will fall back to showing the last connected device.
*format*: ++
typeof: string ++
default: * {status}* ++
The format, how information should be displayed. This format is used when other formats aren't specified.
*format-disabled*: ++
typeof: string ++
This format is used when the displayed controller is disabled.
*format-off*: ++
typeof: string ++
This format is used when the displayed controller is turned off.
*format-on*: ++
typeof: string ++
This format is used when the displayed controller is turned on with no devices connected.
*format-connected*: ++
typeof: string ++
This format is used when the displayed controller is connected to at least 1 device.
*format-no-controller*: ++
typeof: string ++
This format is used when no bluetooth controller could be found
*format-icons*: ++
typeof: array/object ++
Based on the current battery percentage (see section *EXPERIMENTAL BATTERY PERCENTAGE FEATURE*), the corresponding icon gets selected. ++
The order is *low* to *high*. Will only show the current battery percentage icon in the *\*-connected-battery* config options. ++
Or by the state if it is an object. It will fall back to the enabled state if its derivatives are not defined (on, off, connected).
*rotate*: ++
typeof: integer ++
Positive value to rotate the text label.
*max-length*: ++
typeof: integer ++
The maximum length in character the module should display.
*min-length*: ++
typeof: integer ++
The minimum length in characters the module should take up.
*align*: ++
typeof: float ++
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*on-click*: ++
typeof: string ++
Command to execute when clicked on the module.
*on-click-middle*: ++
typeof: string ++
Command to execute when middle-clicked on the module using mousewheel.
*on-click-right*: ++
typeof: string ++
Command to execute when you right clicked on the module.
*on-scroll-up*: ++
typeof: string ++
Command to execute when scrolling up on the module.
*on-scroll-down*: ++
typeof: string ++
Command to execute when scrolling down on the module.
*smooth-scrolling-threshold*: ++
typeof: double ++
Threshold to be used when scrolling.
*tooltip*: ++
typeof: bool ++
default: *true* ++
Option to disable tooltip on hover.
*tooltip-format*: ++
typeof: string ++
The format, how information should be displayed in the tooltip. This format is used when other formats aren't specified.
*tooltip-format-disabled*: ++
typeof: string ++
This format is used when the displayed controller is disabled.
*tooltip-format-off*: ++
typeof: string ++
This format is used when the displayed controller is turned off.
*tooltip-format-on*: ++
typeof: string ++
This format is used when the displayed controller is turned on with no devices connected.
*tooltip-format-connected*: ++
typeof: string ++
This format is used when the displayed controller is connected to at least 1 device.
*tooltip-format-no-controller*: ++
typeof: string ++
This format is used when no bluetooth controller could be found
*tooltip-format-enumerate-connected*: ++
typeof: string ++
This format is used to define how each connected device should be displayed within the *device_enumerate* format replacement in the tooltip menu.
# FORMAT REPLACEMENTS
*{status}*: Status of the bluetooth device.
*{icon}*: Icon, as defined in *format-icons*.
*{num_connections}*: Number of connections the displayed controller has.
*{controller_address}*: Address of the displayed controller.
*{controller_address_type}*: Address type of the displayed controller.
*{controller_alias}*: Alias of the displayed controller.
*{device_address}*: Address of the displayed device.
*{device_address_type}*: Address type of the displayed device.
*{device_alias}*: Alias of the displayed device.
*{device_enumerate}*: Show a list of all connected devices, each on a separate line. Define the format of each device with the *tooltip-format-enumerate-connected* ++
and/or *tooltip-format-enumerate-connected-battery* config options. Can only be used in the tooltip related format options.
# EXPERIMENTAL BATTERY PERCENTAGE FEATURE
At the time of writing, the experimental features of BlueZ need to be turned on, for the battery percentage options listed below to work.
## FORMAT REPLACEMENT
*{device_battery_percentage}*: Battery percentage of the displayed device if available. Use only in the config options defined below.
## CONFIGURATION
*format-connected-battery*: ++
typeof: string ++
This format is used when the displayed device provides its battery percentage.
*tooltip-format-connected-battery*: ++
typeof: string ++
This format is used when the displayed device provides its battery percentage.
*tooltip-format-enumerate-connected-battery*: ++
typeof: string ++
This format is used to define how each connected device with a battery should be displayed within the *device_enumerate* format replacement option. ++
When this config option is not defined, it will fall back on the *tooltip-format-enumerate-connected* config option.
# EXAMPLES
```
"bluetooth": {
// "controller": "controller1", // specify the alias of the controller if there are more than 1 on the system
"format": " {status}",
"format-disabled": "", // an empty format will hide the module
"format-connected": " {num_connections} connected",
"tooltip-format": "{controller_alias}\\t{controller_address}",
"tooltip-format-connected": "{controller_alias}\\t{controller_address}\\n\\n{device_enumerate}",
"tooltip-format-enumerate-connected": "{device_alias}\\t{device_address}"
}
```
```
"bluetooth": {
"format": " {status}",
"format-connected": " {device_alias}",
"format-connected-battery": " {device_alias} {device_battery_percentage}%",
// "format-device-preference": [ "device1", "device2" ], // preference list deciding the displayed device
"tooltip-format": "{controller_alias}\\t{controller_address}\\n\\n{num_connections} connected",
"tooltip-format-connected": "{controller_alias}\\t{controller_address}\\n\\n{num_connections} connected\\n\\n{device_enumerate}",
"tooltip-format-enumerate-connected": "{device_alias}\\t{device_address}",
"tooltip-format-enumerate-connected-battery": "{device_alias}\\t{device_address}\\t{device_battery_percentage}%"
}
```
# STYLE
- *#bluetooth*
- *#bluetooth.disabled*
- *#bluetooth.off*
- *#bluetooth.on*
- *#bluetooth.connected*
- *#bluetooth.discoverable*
- *#bluetooth.discovering*
- *#bluetooth.pairable*

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