Compare commits

..

15 Commits
0.10.2 ... gtk4

Author SHA1 Message Date
Alexis Rouillard
75d7b2f812 Merge pull request #4696 from luoqing510/gtk4
fix: add const qualifier to Glib::ustring formatter to fix compile error
2025-12-18 18:57:22 +01:00
luoQ
dd0f8a0ecf fix: add const qualifier to Glib::ustring formatter to fix compile error 2025-12-13 21:51:58 +08:00
Alexis Rouillard
b54e2c16f3 Merge pull request #2927 from LukashonakV/gtk4
Gtk4. Pick up PR#2836
2024-02-19 22:42:00 +01:00
Aleksei Bavshin
b32abf9966 refactor: merge BarSurface into Bar
With only one implementation left, the abstraction is no longer
necessary.
2024-02-19 23:02:47 +03:00
Aleksei Bavshin
2469851865 fix(bar): use std::string for mode names
`string_view` leads to UAF when reading custom mode definitions from the
configuration.
2024-02-19 22:47:25 +03:00
Aleksei Bavshin
a6d33db20f feat: add module class to the root elements of the modules
Previously, the only way to select all the module labels was with the
following kind of selector:
```css
.modules-left > widget > label,
.modules-center > widget > label,
.modules-right > widget > label {
    /* ... */
}
```
(and a matching block for the `box` containers).

Now, this can be expressed as
```css
label.module, box.module {
    /* ... */
}
```
2024-02-19 22:26:05 +03:00
Aleksei Bavshin
5a4a1a5595 refactor(bar): use Gtk enums for position and orientation
Ensure that the position and the corresponding CSS class on window are
always set.
2024-02-19 22:24:08 +03:00
Aleksei Bavshin
d6d164a27d feat!: drop RawSurfaceImpl with direct use of wlr-layer-shell
BREAKING CHANGE: gtk-layer-shell is now required and unconditionally
used. The corresponding config option is removed.

As a part of preparation for future versions of GTK, remove an ability
to use wlr-layer-shell directly. The APIs it required were dropped in
GTK4, and with the menus/tooltips positioning issue being practically
unsolvable it doesn't make sense to keep maintaining the code.
2024-02-17 22:00:38 +03:00
Aleksei Bavshin
8e33333c0b chore: update gtk-layer-shell subproject to 0.8.2 2024-02-17 21:52:03 +03:00
Alex
f1abc186b2 fix: merge 🥲 2024-01-12 10:08:20 +01:00
Alex
d5bc2f3335 Merge remote-tracking branch 'luka/gtk4' into gtk4 2024-01-12 10:06:47 +01:00
Viktar Lukashonak
f8eb01def2 Clean code
Signed-off-by: Viktar Lukashonak <myxabeer@gmail.com>
2024-01-08 22:48:57 +03:00
Viktar Lukashonak
158767b5b4 Drop break point
Signed-off-by: Viktar Lukashonak <myxabeer@gmail.com>
2024-01-08 22:26:13 +03:00
Viktar Lukashonak
aa95c04842 Gtk4. Stylecontext
Signed-off-by: Viktar Lukashonak <myxabeer@gmail.com>
2024-01-08 22:20:23 +03:00
Viktar Lukashonak
4a88cb693a GTK4 base compilation
Signed-off-by: Viktar Lukashonak <myxabeer@gmail.com>
2024-01-08 19:03:42 +03:00
135 changed files with 1182 additions and 3767 deletions

View File

@@ -22,7 +22,7 @@ CheckOptions:
- { key: readability-identifier-naming.FunctionCase, value: camelBack }
- { key: readability-identifier-naming.VariableCase, value: camelBack }
- { key: readability-identifier-naming.PrivateMemberCase, value: camelBack }
- { key: readability-identifier-naming.PrivateMemberSuffix, value: _ }
- { key: readability-identifier-naming.PrivateMemberPrefix, value: m_ }
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
- { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE }
- { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }

65
.github/labeler.yml vendored
View File

@@ -1,65 +0,0 @@
bug:
- "(crash|bug|error|coredump|freeze|segfault|issue|problem)"
enhancement:
- "(feature|enhancement|improvement|request|suggestion)"
hyprland:
- "(hyprland)"
network:
- "(network|wifi|ethernet)"
bluetooth:
- "(bluetooth|bluez)"
sway:
- "(sway)"
cpu:
- "(cpu)"
memory:
- "(memory|ram)"
disk:
- "(disk|storage)"
battery:
- "(upower|battery)"
sni:
- "(sni|tray)"
dwl:
- "(dwl)"
custom:
- "(custom|module|extension|plugin|script)"
mpd:
- "(mpd|music)"
audio:
- "(pulseaudio|alsa|jack|audio|pirewire|wireplumber)"
temperature:
- "(temperature|thermal|hwmon)"
clock:
- "(clock|time|date)"
gamemode:
- "(gamemode|game|gaming)"
inhibitor:
- "(inhibitor|idle|lock|suspend|hibernate|logout)"
cava:
- "(cava|audio-visualizer)"
backlight:
- "(backlight|brightness)"
keyboard:
- "(keyboard|keymap|layout|shortcut)"

View File

@@ -2,18 +2,14 @@ name: clang-format
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-format-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: DoozyX/clang-format-lint-action@v0.16.2
name: clang-format
with:
source: "."
extensions: "hpp,h,cpp,c"
clangFormatVersion: 16
- uses: actions/checkout@v3
- uses: DoozyX/clang-format-lint-action@v0.16.2
name: clang-format
with:
source: '.'
extensions: 'hpp,h,cpp,c'
clangFormatVersion: 16

View File

@@ -2,10 +2,6 @@ name: clang-tidy
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-tidy-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
@@ -17,11 +13,7 @@ jobs:
run: |
meson -Dcpp_std=c++20 build # necessary to generate compile_commands.json
ninja -C build # necessary to find certain .h files (xdg, wayland, etc.)
- uses: actions/setup-python@v5
with:
python-version: '3.10' # to be kept in sync with cpp-linter-action
update-environment: true # the python dist installed by the action needs LD_LIBRARY_PATH to work
- uses: cpp-linter/cpp-linter-action@v2.9.1
- uses: cpp-linter/cpp-linter-action@v2.7.5
name: clang-tidy
id: clang-tidy-check
env:

View File

@@ -2,28 +2,21 @@ name: freebsd
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-freebsd-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
clang:
# Run actions in a FreeBSD VM on the ubuntu runner
# Run actions in a FreeBSD VM on the macos-12 runner
# https://github.com/actions/runner/issues/385 - for FreeBSD runner support
runs-on: ubuntu-latest
# 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: cross-platform-actions/action@v0.23.0
uses: cross-platform-actions/action@v0.21.1
timeout-minutes: 180
env:
CPPFLAGS: '-isystem/usr/local/include'
LDFLAGS: '-L/usr/local/lib'
with:
operating_system: freebsd
version: "13.2"
environment_variables: CPPFLAGS LDFLAGS
sync_files: runner-to-vm
environment_variables: CPPFLAGS=-isystem/usr/local/include LDFLAGS=-L/usr/local/lib
run: |
sudo sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
sudo pkg install -y git # subprojects/date

View File

@@ -1,19 +0,0 @@
name: "Issue Labeler"
on:
issues:
types: [opened, edited]
permissions:
issues: write
contents: read
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: github/issue-labeler@v3.4
with:
configuration-path: .github/labeler.yml
enable-versioned-regex: 0
include-title: 1
repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -2,10 +2,6 @@ name: linux
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-linux-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
@@ -18,6 +14,9 @@ jobs:
- opensuse
- gentoo
cpp_std: [c++20]
include:
- distro: fedora
cpp_std: c++20
runs-on: ubuntu-latest
container:

View File

@@ -3,47 +3,11 @@
FROM debian:sid
RUN apt update && \
apt install --no-install-recommends --no-install-suggests -y \
build-essential \
catch2 \
cmake \
git \
gobject-introspection \
libdbusmenu-gtk3-dev \
libegl1-mesa-dev \
libfmt-dev \
libgbm-dev \
libgirepository1.0-dev \
libgles2-mesa-dev \
libgtk-layer-shell-dev \
libgtkmm-3.0-dev \
libhowardhinnant-date-dev \
libiniparser-dev \
libinput-dev \
libjack-jackd2-dev \
libjsoncpp-dev \
libmpdclient-dev \
libnl-3-dev \
libnl-genl-3-dev \
libpixman-1-dev \
libplayerctl-dev \
libpugixml-dev \
libpulse-dev \
libsndio-dev \
libspdlog-dev \
libudev-dev \
libupower-glib-dev \
libwayland-dev \
libwireplumber-0.4-dev \
libxkbcommon-dev \
libxkbregistry-dev \
locales \
meson \
ninja-build \
pkg-config \
python3-pip \
python3-venv \
scdoc \
sudo \
wayland-protocols \
&& apt clean
apt 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 sudo python3-venv python3-pip && \
apt clean

View File

@@ -8,12 +8,11 @@
- Sway (Workspaces, Binding mode, Focused window name)
- River (Mapping mode, Tags, Focused window name)
- Hyprland (Window Icons, Workspaces, Focused window name)
- DWL (Tags, Focused window name) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc)
- DWL (Tags) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc)
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
- Local time
- Battery
- UPower
- Power profiles daemon
- Network
- Bluetooth
- Pulseaudio
@@ -37,7 +36,7 @@
Waybar is available from a number of Linux distributions:
[![Packaging status](https://repology.org/badge/vertical-allrepos/waybar.svg?columns=3&header=Waybar%20Downstream%20Packaging)](https://repology.org/project/waybar/versions)
[![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).

6
flake.lock generated
View File

@@ -18,11 +18,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1711163522,
"narHash": "sha256-YN/Ciidm+A0fmJPWlHBGvVkcarYWSC+s3NTPk/P+q3c=",
"lastModified": 1704538339,
"narHash": "sha256-1734d3mQuux9ySvwf6axRWZRBhtcZA9Q8eftD6EZg6U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "44d0940ea560dee511026a53f0e2e2cde489b4d4",
"rev": "46ae0210ce163b3cba6c7da08840c1d63de9c701",
"type": "github"
},
"original": {

View File

@@ -25,7 +25,7 @@ class ALabel : public AModule {
bool alt_ = false;
std::string default_format_;
bool handleToggle(GdkEventButton *const &e) override;
//todo bool handleToggle(GdkEventButton *const &e) override;
virtual std::string getState(uint8_t value, bool lesser = false);
};

View File

@@ -2,7 +2,7 @@
#include <glibmm/dispatcher.h>
#include <glibmm/markup.h>
#include <gtkmm/eventbox.h>
//#include <gtkmm/eventbox.h>
#include <json/json.h>
#include "IModule.hpp"
@@ -30,27 +30,25 @@ class AModule : public IModule {
enum SCROLL_DIR { NONE, UP, DOWN, LEFT, RIGHT };
SCROLL_DIR getScrollDir(GdkEventScroll *e);
// SCROLL_DIR getScrollDir(GdkEventScroll *e);
bool tooltipEnabled();
const std::string name_;
const Json::Value &config_;
Gtk::EventBox event_box_;
// Gtk::EventBox event_box_;
virtual bool handleToggle(GdkEventButton *const &ev);
virtual bool handleMouseEnter(GdkEventCrossing *const &ev);
virtual bool handleMouseLeave(GdkEventCrossing *const &ev);
virtual bool handleScroll(GdkEventScroll *);
virtual bool handleRelease(GdkEventButton *const &ev);
// virtual bool handleToggle(GdkEventButton *const &ev);
// virtual bool handleScroll(GdkEventScroll *);
// virtual bool handleRelease(GdkEventButton *const &ev);
private:
bool handleUserEvent(GdkEventButton *const &ev);
// bool handleUserEvent(GdkEventButton *const &ev);
const bool isTooltip;
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_{
/* 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_BUTTON_RELEASE), "on-click-release"},
{std::make_pair(1, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click"},
@@ -70,7 +68,7 @@ class AModule : public IModule {
{std::make_pair(9, GdkEventType::GDK_BUTTON_PRESS), "on-click-forward"},
{std::make_pair(9, GdkEventType::GDK_BUTTON_RELEASE), "on-click-forward-release"},
{std::make_pair(9, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-forward"},
{std::make_pair(9, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-forward"}};
{std::make_pair(9, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-forward"}};*/
};
} // namespace waybar

View File

@@ -1,18 +1,13 @@
#pragma once
#include <gdkmm/monitor.h>
#include <glibmm/refptr.h>
#include <gtkmm/box.h>
#include <gtkmm/centerbox.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 "group.hpp"
//#include "group.hpp"
#include "xdg-output-unstable-v1-client-protocol.h"
namespace waybar {
@@ -74,8 +69,9 @@ class Bar {
struct wl_surface *surface;
bool visible = true;
Gtk::Window window;
Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL;
Gtk::PositionType position = Gtk::POS_TOP;
Glib::RefPtr<Gdk::Surface> gdk_surface_;
Gtk::Orientation orientation = Gtk::Orientation::HORIZONTAL;
Gtk::PositionType position = Gtk::PositionType::TOP;
int x_global;
int y_global;
@@ -85,15 +81,15 @@ class Bar {
#endif
private:
void onMap(GdkEventAny *);
void onMap();
auto setupWidgets() -> void;
void getModules(const Factory &, const std::string &, waybar::Group *);
// void getModules(const Factory &, const std::string &, waybar::Group *);
void setupAltFormatKeyForModule(const std::string &module_name);
void setupAltFormatKeyForModuleList(const char *module_list_name);
void setMode(const bar_mode &);
void setPassThrough(bool passthrough);
void setPosition(Gtk::PositionType position);
void onConfigure(GdkEventConfigure *ev);
void onConfigure(int width, int height);
void configureGlobalOffset(int width, int height);
void onOutputGeometryChanged();
@@ -108,7 +104,7 @@ class Bar {
Gtk::Box left_;
Gtk::Box center_;
Gtk::Box right_;
Gtk::Box box_;
Gtk::CenterBox 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_;

View File

@@ -1,13 +1,9 @@
#pragma once
#include <fmt/format.h>
#include <gdk/gdk.h>
#include <gdk/gdkwayland.h>
#include <wayland-client.h>
#include <gdk/wayland/gdkwayland.h>
#include "bar.hpp"
#include "config.hpp"
#include "util/css_reload_helper.hpp"
#include "util/portal.hpp"
struct zwp_idle_inhibitor_v1;
@@ -33,6 +29,7 @@ class Client {
private:
Client() = default;
Glib::RefPtr<Gio::ListModel> monitors_;
const std::string getStyle(const std::string &style, std::optional<Appearance> appearance);
void bindInterfaces();
void handleOutput(struct waybar_output &output);
@@ -50,12 +47,9 @@ class Client {
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::unique_ptr<Portal> portal;
std::list<struct waybar_output> outputs_;
std::unique_ptr<CssReloadHelper> m_cssReloadHelper;
std::string m_cssFile;
};
} // namespace waybar

View File

@@ -1,13 +1,110 @@
#pragma once
#include <json/json.h>
#include <AModule.hpp>
#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/battery.hpp"
#endif
#if defined(HAVE_CPU_LINUX) || defined(HAVE_CPU_BSD)
#include "modules/cpu.hpp"
#include "modules/cpu_frequency.hpp"
#include "modules/cpu_usage.hpp"
#include "modules/load.hpp"
#endif
#include "modules/idle_inhibitor.hpp"
#if defined(HAVE_MEMORY_LINUX) || defined(HAVE_MEMORY_BSD)
#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/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_PIPEWIRE
#include "modules/privacy/privacy.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
#ifdef HAVE_SYSTEMD_MONITOR
#include "modules/systemd_failed_units.hpp"
#endif
#include "bar.hpp"
#include "modules/cffi.hpp"
#include "modules/custom.hpp"
#include "modules/image.hpp"
#include "modules/temperature.hpp"
#include "modules/user.hpp"
namespace waybar {
class Bar;
class Factory {
public:
Factory(const Bar& bar, const Json::Value& config);

View File

@@ -19,7 +19,7 @@ class Group : public AModule {
virtual Gtk::Box& getBox();
void addWidget(Gtk::Widget& widget);
bool handleMouseHover(GdkEventCrossing* const& e);
// bool handleMouseHover(GdkEventCrossing* const& e);
protected:
Gtk::Box box;

View File

@@ -1,8 +1,11 @@
#pragma once
#include <fmt/format.h>
#ifdef FILESYSTEM_EXPERIMENTAL
#include <experimental/filesystem>
#else
#include <filesystem>
#endif
#include <fmt/format.h>
#if defined(__linux__)
#include <sys/inotify.h>
#endif
@@ -13,16 +16,19 @@
#include <vector>
#include "ALabel.hpp"
#include "bar.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 waybar::Bar&, const Json::Value&);
Battery(const std::string&, const Json::Value&);
virtual ~Battery();
auto update() -> void override;
@@ -32,9 +38,8 @@ class Battery : public ALabel {
void refreshBatteries();
void worker();
const std::string getAdapterStatus(uint8_t capacity) const;
std::tuple<uint8_t, float, std::string, float, uint16_t, float> getInfos();
const std::tuple<uint8_t, float, std::string, float> getInfos();
const std::string formatTimeRemaining(float hoursRemaining);
void setBarClass(std::string&);
int global_watch;
std::map<fs::path, int> batteries_;
@@ -44,7 +49,6 @@ class Battery : public ALabel {
std::mutex battery_list_mutex_;
std::string old_status_;
bool warnFirstTime_{true};
const Bar& bar_;
util::SleeperThread thread_;
util::SleeperThread thread_battery_update_;

View File

@@ -16,7 +16,7 @@ typedef struct wbcffi_module wbcffi_module;
typedef struct {
wbcffi_module* obj;
const char* waybar_version;
GtkContainer* (*get_root_widget)(wbcffi_module*);
//todo GtkContainer* (*get_root_widget)(wbcffi_module*);
void (*queue_update)(wbcffi_module*);
} wbcffi_init_info;

View File

@@ -8,7 +8,6 @@ namespace waybar::modules {
const std::string kCldPlaceholder{"calendar"};
const std::string kTZPlaceholder{"tz_list"};
const std::string kOrdPlaceholder{"ordinal_date"};
enum class CldMode { MONTH, YEAR };
enum class WS { LEFT, RIGHT, HIDDEN };
@@ -41,7 +40,6 @@ class Clock final : public ALabel {
const int cldMonColLen_{20}; // calendar month column length
WS cldWPos_{WS::HIDDEN}; // calendar week side to print
months cldCurrShift_{0}; // calendar months shift
int cldShift_{1}; // calendar months shift factor
year_month_day cldYearShift_; // calendar Year mode. Cached ymd
std::string cldYearCached_; // calendar Year mode. Cached calendar
year_month cldMonShift_; // calendar Month mode. Cached ym
@@ -52,9 +50,6 @@ class Clock final : public ALabel {
auto get_calendar(const year_month_day& today, const year_month_day& ymd, const time_zone* tz)
-> const std::string;
// get local time zone
auto local_zone() -> const time_zone*;
// time zoned time in tooltip
const bool tzInTooltip_; // if need to print time zones text
std::vector<const time_zone*> tzList_; // time zones list
@@ -62,18 +57,12 @@ class Clock final : public ALabel {
std::string tzText_{""}; // time zones text to print
util::SleeperThread thread_;
// ordinal date in tooltip
const bool ordInTooltip_;
std::string ordText_{""};
auto get_ordinal_date(const year_month_day& today) -> std::string;
auto getTZtext(sys_seconds now) -> std::string;
auto first_day_of_week() -> weekday;
// Module actions
void cldModeSwitch();
void cldShift_up();
void cldShift_down();
void cldShift_reset();
void tz_up();
void tz_down();
// Module Action Map
@@ -81,7 +70,6 @@ class Clock final : public ALabel {
{"mode", &waybar::modules::Clock::cldModeSwitch},
{"shift_up", &waybar::modules::Clock::cldShift_up},
{"shift_down", &waybar::modules::Clock::cldShift_down},
{"shift_reset", &waybar::modules::Clock::cldShift_reset},
{"tz_up", &waybar::modules::Clock::tz_up},
{"tz_down", &waybar::modules::Clock::tz_down}};
};

View File

@@ -26,8 +26,8 @@ class Custom : public ALabel {
void parseOutputRaw();
void parseOutputJson();
void handleEvent();
bool handleScroll(GdkEventScroll* e) override;
bool handleToggle(GdkEventButton* const& e) override;
//todo bool handleScroll(GdkEventScroll* e) override;
//todo bool handleToggle(GdkEventButton* const& e) override;
const std::string name_;
const std::string output_name_;

View File

@@ -1,38 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <string>
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "dwl-ipc-unstable-v2-client-protocol.h"
#include "util/json.hpp"
namespace waybar::modules::dwl {
class Window : public AAppIconLabel, public sigc::trackable {
public:
Window(const std::string &, const waybar::Bar &, const Json::Value &);
virtual ~Window() = default;
void handle_layout(const uint32_t layout);
void handle_title(const char *title);
void handle_appid(const char *ppid);
void handle_layout_symbol(const char *layout_symbol);
void handle_frame();
struct zdwl_ipc_manager_v2 *status_manager_;
private:
const Bar &bar_;
std::string title_;
std::string appid_;
std::string layout_symbol_;
uint32_t layout_;
struct zdwl_ipc_output_v2 *output_status_;
};
} // namespace waybar::modules::dwl

View File

@@ -20,8 +20,8 @@ class IPC {
public:
IPC() { startIPC(); }
void registerForIPC(const std::string& ev, EventHandler* ev_handler);
void unregisterForIPC(EventHandler* handler);
void registerForIPC(const std::string&, EventHandler*);
void unregisterForIPC(EventHandler*);
static std::string getSocket1Reply(const std::string& rq);
Json::Value getSocket1JsonReply(const std::string& rq);
@@ -30,9 +30,9 @@ class IPC {
void startIPC();
void parseIPC(const std::string&);
std::mutex callbackMutex_;
util::JsonParser parser_;
std::list<std::pair<std::string, EventHandler*>> callbacks_;
std::mutex m_callbackMutex;
util::JsonParser m_parser;
std::list<std::pair<std::string, EventHandler*>> m_callbacks;
};
inline std::unique_ptr<IPC> gIPC;

View File

@@ -30,7 +30,7 @@ class Language : public waybar::ALabel, public EventHandler {
std::string short_description;
};
static auto getLayout(const std::string&) -> Layout;
auto getLayout(const std::string&) -> Layout;
std::mutex mutex_;
const Bar& bar_;

View File

@@ -14,20 +14,17 @@ namespace waybar::modules::hyprland {
class Submap : public waybar::ALabel, public EventHandler {
public:
Submap(const std::string&, const waybar::Bar&, const Json::Value&);
~Submap() override;
virtual ~Submap();
auto update() -> void override;
private:
auto parseConfig(const Json::Value&) -> void;
void onEvent(const std::string& ev) override;
void onEvent(const std::string&) override;
std::mutex mutex_;
const Bar& bar_;
util::JsonParser parser_;
std::string submap_;
bool always_on_ = false;
std::string default_submap_ = "Default";
};
} // namespace waybar::modules::hyprland

View File

@@ -25,7 +25,7 @@ class Window : public waybar::AAppIconLabel, public EventHandler {
std::string last_window;
std::string last_window_title;
static auto parse(const Json::Value& value) -> Workspace;
static auto parse(const Json::Value&) -> Workspace;
};
struct WindowData {
@@ -41,25 +41,24 @@ class Window : public waybar::AAppIconLabel, public EventHandler {
static auto parse(const Json::Value&) -> WindowData;
};
static auto getActiveWorkspace(const std::string&) -> Workspace;
static auto getActiveWorkspace() -> Workspace;
void onEvent(const std::string& ev) override;
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 separateOutputs_;
bool separate_outputs;
std::mutex mutex_;
const Bar& bar_;
util::JsonParser parser_;
WindowData windowData_;
WindowData window_data_;
Workspace workspace_;
std::string soloClass_;
std::string lastSoloClass_;
std::string solo_class_;
std::string last_solo_class_;
bool solo_;
bool allFloating_;
bool all_floating_;
bool swallowing_;
bool fullscreen_;
bool focused_;
};
} // namespace waybar::modules::hyprland

View File

@@ -68,24 +68,20 @@ class Workspace {
int id() const { return m_id; };
std::string name() const { return m_name; };
std::string output() const { return m_output; };
bool isActive() const { return m_isActive; };
bool isActive() const { return m_active; };
bool isSpecial() const { return m_isSpecial; };
bool isPersistent() const { return m_isPersistentRule || m_isPersistentConfig; };
bool isPersistentConfig() const { return m_isPersistentConfig; };
bool isPersistentRule() const { return m_isPersistentRule; };
bool isPersistent() const { return m_isPersistent; };
bool isVisible() const { return m_isVisible; };
bool isEmpty() const { return m_windows == 0; };
bool isUrgent() const { return m_isUrgent; };
bool handleClicked(GdkEventButton* bt) const;
void setActive(bool value = true) { m_isActive = value; };
void setPersistentRule(bool value = true) { m_isPersistentRule = value; };
void setPersistentConfig(bool value = true) { m_isPersistentConfig = value; };
void setActive(bool value = true) { m_active = value; };
void setPersistent(bool value = true) { m_isPersistent = value; };
void setUrgent(bool value = true) { m_isUrgent = value; };
void setVisible(bool value = true) { m_isVisible = value; };
void setWindows(uint value) { m_windows = value; };
void setName(std::string const& value) { m_name = value; };
void setOutput(std::string const& value) { m_output = value; };
bool containsWindow(WindowAddress const& addr) const { return m_windowMap.contains(addr); }
void insertWindow(WindowCreationPayload create_window_paylod);
std::string removeWindow(WindowAddress const& addr);
@@ -103,10 +99,9 @@ class Workspace {
std::string m_name;
std::string m_output;
uint m_windows;
bool m_isActive = false;
bool m_active = false;
bool m_isSpecial = false;
bool m_isPersistentRule = false; // represents the persistent state in hyprland
bool m_isPersistentConfig = false; // represents the persistent state in the Waybar config
bool m_isPersistent = false;
bool m_isUrgent = false;
bool m_isVisible = false;
@@ -127,7 +122,6 @@ class Workspaces : public AModule, public EventHandler {
auto allOutputs() const -> bool { return m_allOutputs; }
auto showSpecial() const -> bool { return m_showSpecial; }
auto activeOnly() const -> bool { return m_activeOnly; }
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
auto getBarOutput() const -> std::string { return m_bar.output->name; }
@@ -141,8 +135,8 @@ class Workspaces : public AModule, public EventHandler {
void onEvent(const std::string& e) override;
void updateWindowCount();
void sortWorkspaces();
void createWorkspace(Json::Value const& workspaceData,
Json::Value const& clientsData = Json::Value::nullRef);
void createWorkspace(Json::Value const& workspace_data,
Json::Value const& clients_data = Json::Value::nullRef);
void removeWorkspace(std::string const& name);
void setUrgentWorkspace(std::string const& windowaddress);
void parseConfig(const Json::Value& config);
@@ -150,7 +144,6 @@ class Workspaces : public AModule, public EventHandler {
// workspace events
void onWorkspaceActivated(std::string const& payload);
void onSpecialWorkspaceActivated(std::string const& payload);
void onWorkspaceDestroyed(std::string const& payload);
void onWorkspaceCreated(std::string const& workspaceName,
Json::Value const& clientsData = Json::Value::nullRef);
@@ -167,25 +160,16 @@ class Workspaces : public AModule, public EventHandler {
void onWindowTitleEvent(std::string const& payload);
void onConfigReloaded();
int windowRewritePriorityFunction(std::string const& window_rule);
void doUpdate();
void extendOrphans(int workspaceId, Json::Value const& clientsJson);
void registerOrphanWindow(WindowCreationPayload create_window_payload);
void initializeWorkspaces();
void setCurrentMonitorId();
void loadPersistentWorkspacesFromConfig(Json::Value const& clientsJson);
void loadPersistentWorkspacesFromWorkspaceRules(const Json::Value& clientsJson);
void registerOrphanWindow(WindowCreationPayload create_window_paylod);
bool m_allOutputs = false;
bool m_showSpecial = false;
bool m_activeOnly = false;
bool m_moveToMonitor = false;
Json::Value m_persistentWorkspaceConfig;
// Map for windows stored in workspaces not present in the current bar.
// This happens when the user has multiple monitors (hence, multiple bars)
@@ -200,6 +184,11 @@ class Workspaces : public AModule, public EventHandler {
{"NUMBER", SortMethod::NUMBER},
{"DEFAULT", SortMethod::DEFAULT}};
void fillPersistentWorkspaces();
void createPersistentWorkspaces();
std::vector<std::string> m_persistentWorkspacesToCreate;
bool m_persistentCreated = false;
std::string m_format;
std::map<std::string, std::string> m_iconsMap;
@@ -210,7 +199,6 @@ class Workspaces : public AModule, public EventHandler {
bool m_withIcon;
uint64_t m_monitorId;
std::string m_activeWorkspaceName;
std::string m_activeSpecialWorkspaceName;
std::vector<std::unique_ptr<Workspace>> m_workspaces;
std::vector<std::pair<Json::Value, Json::Value>> m_workspacesToCreate;
std::vector<std::string> m_workspacesToRemove;

View File

@@ -19,7 +19,7 @@ class IdleInhibitor : public ALabel {
static bool status;
private:
bool handleToggle(GdkEventButton* const& e) override;
//todo bool handleToggle(GdkEventButton* const& e) override;
void toggleStatus();
const Bar& bar_;

View File

@@ -148,7 +148,6 @@ class Stopped : public State {
class Disconnected : public State {
Context* const ctx_;
sigc::connection timer_connection_;
int last_interval_;
public:
Disconnected(Context* const ctx) : ctx_{ctx} {}
@@ -163,7 +162,7 @@ class Disconnected : public State {
Disconnected(Disconnected const&) = delete;
Disconnected& operator=(Disconnected const&) = delete;
bool arm_timer(int interval) noexcept;
void arm_timer(int interval) noexcept;
void disarm_timer() noexcept;
bool on_timer();

View File

@@ -1,46 +0,0 @@
#pragma once
#include <fmt/format.h>
#include "ALabel.hpp"
#include "giomm/dbusproxy.h"
namespace waybar::modules {
struct Profile {
std::string name;
std::string driver;
};
class PowerProfilesDaemon : public ALabel {
public:
PowerProfilesDaemon(const std::string &, const Json::Value &);
auto update() -> void override;
void profileChangedCb(const Gio::DBus::Proxy::MapChangedProperties &,
const std::vector<Glib::ustring> &);
void busConnectedCb(Glib::RefPtr<Gio::AsyncResult> &r);
void getAllPropsCb(Glib::RefPtr<Gio::AsyncResult> &r);
void setPropCb(Glib::RefPtr<Gio::AsyncResult> &r);
void populateInitState();
bool handleToggle(GdkEventButton *const &e) override;
private:
// True if we're connected to the dbug interface. False if we're
// not.
bool connected_;
// Look for a profile name in the list of available profiles and
// switch activeProfile_ to it.
void switchToProfile(std::string const &);
// Used to toggle/display the profiles
std::vector<Profile> availableProfiles_;
// Points to the active profile in the profiles list
std::vector<Profile>::iterator activeProfile_;
// Current CSS class applied to the label
std::string currentStyle_;
// Format string
std::string tooltipFormat_;
// DBus Proxy used to track the current active profile
Glib::RefPtr<Gio::DBus::Proxy> powerProfilesProxy_;
};
} // namespace waybar::modules

View File

@@ -56,7 +56,6 @@ class Language : public ALabel, public sigc::trackable {
Layout layout_;
std::string tooltip_format_ = "";
std::map<std::string, Layout> layouts_map_;
bool hide_single_;
bool is_variant_displayed;
std::byte displayed_short_flag = static_cast<std::byte>(DispayedShortFlag::None);

View File

@@ -12,7 +12,6 @@
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
#include "util/json.hpp"
#include "util/regex_collection.hpp"
namespace waybar::modules::sway {
@@ -28,13 +27,10 @@ class Workspaces : public AModule, public sigc::trackable {
R"(workspace {} "{}"; move workspace to output "{}"; workspace {} "{}")";
static int convertWorkspaceNameToNum(std::string name);
static int windowRewritePriorityFunction(std::string const& window_rule);
void onCmd(const struct Ipc::ipc_response&);
void onEvent(const struct Ipc::ipc_response&);
bool filterButtons();
static bool hasFlag(const Json::Value&, const std::string&);
void updateWindows(const Json::Value&, std::string&);
Gtk::Button& addButton(const Json::Value&);
void onButtonReady(const Json::Value&, Gtk::Button&);
std::string getIcon(const std::string&, const Json::Value&);
@@ -48,9 +44,6 @@ class Workspaces : public AModule, public sigc::trackable {
std::vector<std::string> high_priority_named_;
std::vector<std::string> workspaces_order_;
Gtk::Box box_;
std::string m_formatWindowSeperator;
std::string m_windowRewriteDefault;
util::RegexCollection m_windowRewriteRules;
util::JsonParser parser_;
std::unordered_map<std::string, Gtk::Button> buttons_;
std::mutex mutex_;

View File

@@ -1,8 +1,7 @@
#pragma once
#include <giomm/dbusproxy.h>
#include <string>
#include <giomm/dbusproxy.h>
#include "ALabel.hpp"
@@ -10,7 +9,7 @@ namespace waybar::modules {
class SystemdFailedUnits : public ALabel {
public:
SystemdFailedUnits(const std::string &, const Json::Value &);
SystemdFailedUnits(const std::string&, const Json::Value&);
virtual ~SystemdFailedUnits();
auto update() -> void override;
@@ -19,8 +18,8 @@ class SystemdFailedUnits : public ALabel {
std::string format_ok;
bool update_pending;
uint32_t nr_failed_system, nr_failed_user;
std::string last_status;
uint32_t nr_failed_system, nr_failed_user;
Glib::RefPtr<Gio::DBus::Proxy> system_proxy, user_proxy;
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name,

View File

@@ -66,12 +66,11 @@ class UPower : public AModule {
Devices devices;
std::mutex m_Mutex;
UpClient *client;
UpDevice *displayDevice = nullptr;
UpDevice *displayDevice;
guint login1_id;
GDBusConnection *login1_connection;
std::unique_ptr<UPowerTooltip> upower_tooltip;
std::string lastStatus;
const char *lastWarningLevel;
bool showAltText;
bool showIcon = true;
bool upowerRunning;

View File

@@ -14,7 +14,7 @@ class User : public AIconLabel {
virtual ~User() = default;
auto update() -> void override;
bool handleToggle(GdkEventButton* const& e) override;
//todo bool handleToggle(GdkEventButton* const& e) override;
private:
util::SleeperThread thread_;

View File

@@ -17,15 +17,12 @@ class Wireplumber : public ALabel {
auto update() -> void override;
private:
void asyncLoadRequiredApiModules();
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 onDefaultNodesApiLoaded(WpObject* p, GAsyncResult* res,
waybar::modules::Wireplumber* self);
static void onMixerApiLoaded(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
static void onObjectManagerInstalled(waybar::modules::Wireplumber* self);
static void onMixerChanged(waybar::modules::Wireplumber* self, uint32_t id);
static void onDefaultNodesApiChanged(waybar::modules::Wireplumber* self);

View File

@@ -52,7 +52,7 @@ struct SafeSignal : 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::emit;
using signal_t::make_slot;
void handle_event() {

View File

@@ -22,7 +22,6 @@ class AudioBackend {
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*);
void connectContext();
pa_threaded_mainloop* mainloop_;
pa_mainloop_api* mainloop_api_;

View File

@@ -20,7 +20,7 @@
std::scoped_lock<std::mutex> lock((backend).udev_thread_mutex_); \
__devices = (backend).devices_; \
} \
auto varname = (backend).best_device(__devices, preferred_device);
auto varname = (backend).best_device(__devices.cbegin(), __devices.cend(), preferred_device);
namespace waybar::util {
@@ -61,10 +61,16 @@ class BacklightBackend {
void set_scaled_brightness(std::string preferred_device, int brightness);
int get_scaled_brightness(std::string preferred_device);
template <class ForwardIt, class Inserter>
static void upsert_device(ForwardIt first, ForwardIt last, Inserter inserter, udev_device *dev);
template <class ForwardIt, class Inserter>
static void enumerate_devices(ForwardIt first, ForwardIt last, Inserter inserter, udev *udev);
bool is_login_proxy_initialized() const { return static_cast<bool>(login_proxy_); }
static const BacklightDevice *best_device(const std::vector<BacklightDevice> &devices,
std::string_view);
template <class ForwardIt>
static const BacklightDevice *best_device(ForwardIt first, ForwardIt last, std::string_view);
std::vector<BacklightDevice> devices_;
std::mutex udev_thread_mutex_;
@@ -84,4 +90,4 @@ class BacklightBackend {
static constexpr int EPOLL_MAX_EVENTS = 16;
};
} // namespace waybar::util
} // namespace waybar::util

View File

@@ -1,49 +0,0 @@
#pragma once
#include <functional>
#include <string>
#include <unordered_map>
#include <vector>
#include "giomm/file.h"
#include "giomm/filemonitor.h"
#include "glibmm/refptr.h"
struct pollfd;
namespace waybar {
class CssReloadHelper {
public:
CssReloadHelper(std::string cssFile, std::function<void()> callback);
virtual ~CssReloadHelper() = default;
virtual void monitorChanges();
protected:
std::vector<std::string> parseImports(const std::string& cssFile);
void parseImports(const std::string& cssFile, std::unordered_map<std::string, bool>& imports);
void watchFiles(const std::vector<std::string>& files);
bool handleInotifyEvents(int fd);
bool watch(int inotifyFd, pollfd* pollFd);
virtual std::string getFileContents(const std::string& filename);
virtual std::string findPath(const std::string& filename);
void handleFileChange(Glib::RefPtr<Gio::File> const& file,
Glib::RefPtr<Gio::File> const& other_type,
Gio::FileMonitorEvent event_type);
private:
std::string m_cssFile;
std::function<void()> m_callback;
std::vector<std::tuple<Glib::RefPtr<Gio::FileMonitor>>> m_fileMonitors;
};
} // namespace waybar

View File

@@ -30,6 +30,10 @@ template <typename T>
inline auto format(const std::locale& loc, const char* spec, const T& arg) {
return date::format(loc, std::regex_replace(spec, std::regex("\\{:L|\\}"), ""), arg);
}
constexpr decltype(auto) operator""d(unsigned long long d) noexcept {
return date::operator""_d(d); // very verbose, but it works
}
#endif
} // namespace date

View File

@@ -92,7 +92,7 @@ struct formatter<pow_format> {
template <>
struct formatter<Glib::ustring> : formatter<std::string> {
template <typename FormatContext>
auto format(const Glib::ustring& value, FormatContext& ctx) {
auto format(const Glib::ustring& value, FormatContext& ctx) const {
return formatter<std::string>::format(static_cast<std::string>(value), ctx);
}
};

View File

@@ -3,12 +3,6 @@
#include <fmt/ostream.h>
#include <json/json.h>
#include <algorithm>
#include <codecvt>
#include <iostream>
#include <locale>
#include <regex>
#if (FMT_VERSION >= 90000)
template <>
@@ -18,30 +12,25 @@ struct fmt::formatter<Json::Value> : ostream_formatter {};
namespace waybar::util {
class JsonParser {
public:
JsonParser() = default;
struct JsonParser {
JsonParser() {}
Json::Value parse(const std::string& jsonStr) {
Json::Value root;
// replace all occurrences of "\x" with "\u00", because JSON doesn't allow "\x" escape sequences
std::string modifiedJsonStr = replaceHexadecimalEscape(jsonStr);
std::istringstream jsonStream(modifiedJsonStr);
std::string errs;
if (!Json::parseFromStream(m_readerBuilder, jsonStream, &root, &errs)) {
throw std::runtime_error("Error parsing JSON: " + errs);
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());
std::string err;
bool res = reader->parse(data.c_str(), data.c_str() + data.size(), &root, &err);
if (!res) throw std::runtime_error(err);
return root;
}
private:
Json::CharReaderBuilder m_readerBuilder;
~JsonParser() = default;
static std::string replaceHexadecimalEscape(const std::string& str) {
static std::regex re("\\\\x");
return std::regex_replace(str, re, "\\u00");
}
private:
Json::CharReaderBuilder builder_;
};
} // namespace waybar::util

View File

@@ -13,8 +13,7 @@ class PipewireBackend {
pw_context* context_;
pw_core* core_;
pw_registry* registry_;
spa_hook registryListener_;
spa_hook registry_listener;
/* Hack to keep constructor inaccessible but still public.
* This is required to be able to use std::make_shared.
@@ -22,22 +21,20 @@ class PipewireBackend {
* pointer because the destructor will manually free memory, and this could be
* a problem with C++20's copy and move semantics.
*/
struct PrivateConstructorTag {};
struct private_constructor_tag {};
public:
std::mutex mutex_;
pw_registry* registry;
sigc::signal<void> privacy_nodes_changed_signal_event;
std::unordered_map<uint32_t, PrivacyNodeInfo*> privacy_nodes;
std::mutex mutex_;
static std::shared_ptr<PipewireBackend> getInstance();
// Handlers for PipeWire events
void handleRegistryEventGlobal(uint32_t id, uint32_t permissions, const char* type,
uint32_t version, const struct spa_dict* props);
void handleRegistryEventGlobalRemove(uint32_t id);
PipewireBackend(PrivateConstructorTag tag);
PipewireBackend(private_constructor_tag tag);
~PipewireBackend();
};
} // namespace waybar::util::PipewireBackend

View File

@@ -34,12 +34,29 @@ class PrivacyNodeInfo {
void *data;
std::string getName();
std::string getIconName();
std::string get_name() {
const std::vector<std::string *> names{&application_name, &node_name};
std::string name = "Unknown Application";
for (auto &name_ : names) {
if (name_ != nullptr && name_->length() > 0) {
name = *name_;
name[0] = toupper(name[0]);
break;
}
}
return name;
}
// Handlers for PipeWire events
void handleProxyEventDestroy();
void handleNodeEventInfo(const struct pw_node_info *info);
std::string get_icon_name() {
const std::vector<std::string *> names{&application_icon_name, &pipewire_access_portal_app_id,
&application_name, &node_name};
const std::string name = "application-x-executable-symbolic";
for (auto &name_ : names) {
if (name_ != nullptr && name_->length() > 0 && DefaultGtkIconThemeWrapper::has_icon(*name_)) {
return *name_;
}
}
return name;
}
};
} // namespace waybar::util::PipewireBackend

View File

@@ -19,7 +19,7 @@ class Portal : private DBus::Proxy {
void refreshAppearance();
Appearance getAppearance();
typedef sigc::signal<void, Appearance> type_signal_appearance_changed;
typedef sigc::signal<void(Appearance)> type_signal_appearance_changed;
type_signal_appearance_changed signal_appearance_changed() { return m_signal_appearance_changed; }
private:

View File

@@ -30,11 +30,7 @@ The *backlight* module displays the current backlight level.
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -61,11 +61,7 @@ The *battery* module displays the current capacity and state (eg. charging) of y
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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++
@@ -119,10 +115,6 @@ The *battery* module displays the current capacity and state (eg. charging) of y
*{time}*: Estimate of time until full or empty. Note that this is based on the power draw at the last refresh time, not an average.
*{cycles}*: Amount of charge cycles the highest-capacity battery has seen. *(Linux only)*
*{health}*: The percentage of the highest-capacity battery's original maximum charge it can still hold.
# TIME FORMAT
The *battery* module allows you to define how time should be formatted via *format-time*.
@@ -175,10 +167,3 @@ The *battery* module allows one to define custom formats based on up to two fact
- *<state>* can be defined in the *config*. For more information see *states*.
- *#battery.<status>.<state>*
- Combination of both *<status>* and *<state>*.
The following classes are applied to the entire Waybar rather than just the
battery widget:
- *window#waybar.battery-<state>*
- *<state>* can be defined in the *config*, as previously mentioned.

View File

@@ -66,11 +66,7 @@ Addressed by *bluetooth*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -157,7 +157,6 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe
- *{calendar}*: Current month calendar
- *{tz_list}*: List of time in the rest timezones, if more than one timezone is set in the config
- *{ordinal_date}*: The current day in (English) ordinal form, e.g. 21st
# EXAMPLES

View File

@@ -35,11 +35,7 @@ The *cpu* module displays the current CPU utilization.
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -72,11 +72,7 @@ Addressed by *custom/<name>*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++
@@ -111,11 +107,6 @@ Addressed by *custom/<name>*
default: true ++
Option to disable tooltip on hover.
*tooltip-format*: ++
typeof: string ++
The tooltip format. If specified, overrides any tooltip output from the script in *exec*. ++
Uses the same format replacements as *format*.
*escape*: ++
typeof: bool ++
default: false ++

View File

@@ -45,11 +45,7 @@ Addressed by *disk*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -1,118 +0,0 @@
waybar-dwl-window(5)
# NAME
waybar - dwl window module
# DESCRIPTION
The *window* module displays the title of the currently focused window in DWL
# CONFIGURATION
Addressed by *dwl/window*
*format*: ++
typeof: string ++
default: {title} ++
The format, how information should be displayed.
*rotate*: ++
typeof: integer ++
Positive value to rotate the text label.
*max-length*: ++
typeof: integer ++
The maximum length in character the module should display.
*min-length*: ++
typeof: integer ++
The minimum length in characters the module should accept.
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
*on-click*: ++
typeof: string ++
Command to execute when clicked on the module.
*on-click-middle*: ++
typeof: string ++
Command to execute when middle-clicked on the module using mousewheel.
*on-click-right*: ++
typeof: string ++
Command to execute when you right-click on the module.
*on-update*: ++
typeof: string ++
Command to execute when the module is updated.
*on-scroll-up*: ++
typeof: string ++
Command to execute when scrolling up on the module.
*on-scroll-down*: ++
typeof: string ++
Command to execute when scrolling down on the module.
*smooth-scrolling-threshold*: ++
typeof: double ++
Threshold to be used when scrolling.
*tooltip*: ++
typeof: bool ++
default: true ++
Option to disable tooltip on hover.
*rewrite*: ++
typeof: object ++
Rules to rewrite the module format output. See *rewrite rules*.
*icon*: ++
typeof: bool ++
default: false ++
Option to hide the application icon.
*icon-size*: ++
typeof: integer ++
default: 24 ++
Option to change the size of the application icon.
# FORMAT REPLACEMENTS
*{title}*: The title of the focused window.
*{app_id}*: The app_id of the focused window.
*{layout}*: The layout of the focused window.
# REWRITE RULES
*rewrite* is an object where keys are regular expressions and values are
rewrite rules if the expression matches. Rules may contain references to
captures of the expression.
Regular expression and replacement follow ECMA-script rules.
If no expression matches, the format output is left unchanged.
Invalid expressions (e.g., mismatched parentheses) are skipped.
# EXAMPLES
```
"dwl/window": {
"format": "{}",
"max-length": 50,
"rewrite": {
"(.*) - Mozilla Firefox": "🌎 $1",
"(.*) - zsh": "> [$1]"
}
}
```

View File

@@ -31,11 +31,7 @@ Addressed by *hyprland/submap*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++
@@ -70,16 +66,6 @@ Addressed by *hyprland/submap*
default: true ++
Option to disable tooltip on hover.
*always-on*: ++
typeof: bool ++
default: false ++
Option to display the widget even when there's no active submap.
*default-submap* ++
typeof: string ++
default: Default ++
Option to set the submap name to display when not in an active submap.
# EXAMPLES
@@ -94,4 +80,3 @@ Addressed by *hyprland/submap*
# STYLE
- *#submap*
- *#submap.<name>*

View File

@@ -52,13 +52,6 @@ Addressed by *hyprland/workspaces*
default: false ++
If set to true, only the active workspace will be shown.
*move-to-monitor*: ++
typeof: bool ++
default: false ++
If set to true, open the workspace on the current monitor when clicking on a workspace button.
Otherwise, the workspace will open on the monitor where it was previously assigned.
Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland.
*ignore-workspaces*: ++
typeof: array ++
default: [] ++
@@ -146,7 +139,6 @@ Additional to workspace name matching, the following *format-icons* can be set.
}
```
```
"hyprland/workspaces": {
// Formatting omitted for brevity
"ignore-workspaces": [
@@ -165,4 +157,3 @@ Additional to workspace name matching, the following *format-icons* can be set.
- *#workspaces button.persistent*
- *#workspaces button.special*
- *#workspaces button.urgent*
- *#workspaces button.hosting-monitor* (gets applied if workspace-monitor == waybar-monitor)

View File

@@ -33,11 +33,7 @@ screensaver, also known as "presentation mode".
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -87,4 +87,3 @@ $path\\n$tooltip
# STYLE
- *#image*
- *#image.empty*

View File

@@ -37,11 +37,7 @@ See *systemd-inhibit*(1) for more information.
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -63,11 +63,7 @@ Addressed by *jack*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -45,11 +45,7 @@ Addressed by *memory*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -103,11 +103,7 @@ Addressed by *mpd*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -119,11 +119,8 @@ The *mpris* module displays currently playing media via libplayerctl.
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -70,11 +70,7 @@ Addressed by *network*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -1,72 +0,0 @@
waybar-power-profiles-daemon(5)
# NAME
waybar - power-profiles-daemon module
# DESCRIPTION
The *power-profiles-daemon* module displays the active power-profiles-daemon profile and cycle through the available profiles on click.
# FILES
$XDG_CONFIG_HOME/waybar/config
# CONFIGURATION
[- *Option*
:- *Typeof*
:- *Default*
:= *Description*
|[ *format*
:[ string
:[ "{icon}"
:[ Message displayed on the bar. {icon} and {profile} are respectively substituted with the icon representing the active profile and its full name.
|[ *tooltip-format*
:[ string
:[ "Power profile: {profile}\\nDriver: {driver}"
:[ Messaged displayed in the module tooltip. {icon} and {profile} are respectively substituted with the icon representing the active profile and its full name.
|[ *tooltip*
:[ bool
:[ true
:[ Display the tooltip.
|[ *format-icons*
:[ object
:[ See default value in the example below.
:[ Icons used to represent the various power-profile. *Note*: the default configuration uses the font-awesome icons. You may want to override it if you don't have this font installed on your system.
# CONFIGURATION EXAMPLES
Compact display (default config):
```
"power-profiles-daemon": {
"format": "{icon}",
"tooltip-format": "Power profile: {profile}\nDriver: {driver}",
"tooltip": true,
"format-icons": {
"default": "",
"performance": "",
"balanced": "",
"power-saver": ""
}
}
```
Display the full profile name:
```
"power-profiles-daemon": {
"format": "{icon} {profile}",
"tooltip-format": "Power profile: {profile}\nDriver: {driver}",
"tooltip": true,
"format-icons": {
"default": "",
"performance": "",
"balanced": "",
"power-saver": ""
}
}
```

View File

@@ -56,11 +56,7 @@ Additionally, you can control the volume by scrolling *up* or *down* while the c
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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.
*scroll-step*: ++
typeof: float ++

View File

@@ -33,11 +33,7 @@ Addressed by *river/layout*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -31,11 +31,7 @@ Addressed by *river/mode*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -31,11 +31,7 @@ Addressed by *river/window*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -32,11 +32,7 @@ cursor is over the module, and clicking on the module toggles mute.
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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.
*scroll-step*: ++
typeof: int ++

View File

@@ -1,44 +0,0 @@
waybar-styles(5)
# NAME
waybar-styles - using stylesheets for waybar
# DESCRIPTION
Waybar uses Cascading Style Sheets (CSS) to configure its appearance.
It uses the first file found in this search order:
- *$XDG_CONFIG_HOME/waybar/style.css*
- *~/.config/waybar/style.css*
- *~/waybar/style.css*
- */etc/xdg/waybar/style.css*
- *@sysconfdir@/xdg/waybar/style.css*
# EXAMPLE
An example user-controlled stylesheet that just changes the color of the clock to be green on black, while keeping the rest of the system config the same would be:
```
@import url("file:///etc/xdg/waybar/style.css")
#clock {
background: #000000;
color: #00ff00;
}
```
## Hover-effect
You can apply special styling to any module for when the cursor hovers it.
```
#clock:hover {
background-color: #ffffff;
}
```
# SEE ALSO
- *waybar(5)*

View File

@@ -17,11 +17,6 @@ Addressed by *sway/language*
default: {} ++
The format, how layout should be displayed.
*hide-single-layout*: ++
typeof: bool ++
default: false ++
Defines visibility of the module if a single layout is configured
*tooltip-format*: ++
typeof: string ++
default: {} ++

View File

@@ -31,11 +31,7 @@ Addressed by *sway/mode*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -31,11 +31,7 @@ Addressed by *sway/window*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -82,23 +82,6 @@ warp-on-scroll: ++
default: true ++
If set to false, you can scroll to cycle through workspaces without mouse warping being enabled. If set to true this behaviour is disabled.
*window-rewrite*: ++
typeof: object ++
Regex rules to map window class to an icon or preferred method of representation for a workspace's window.
Keys are the rules, while the values are the methods of representation.
Rules may specify `class<...>`, `title<...>`, or both in order to fine-tune the matching.
*window-rewrite-default*:
typeof: string ++
default: "?" ++
The default method of representation for a workspace's window. This will be used for windows whose classes do not match any of the rules in *window-rewrite*.
*format-window-separator*: ++
typeof: string ++
default: " " ++
The separator to be used between windows in a workspace.
# FORMAT REPLACEMENTS
*{value}*: Name of the workspace, as defined by sway.
@@ -111,8 +94,6 @@ warp-on-scroll: ++
*{output}*: Output where the workspace is located.
*{windows}*: Result from window-rewrite
# ICONS
Additional to workspace name matching, the following *format-icons* can be set.
@@ -162,19 +143,6 @@ n.b.: the list of outputs can be obtained from command line using *swaymsg -t ge
}
```
```
"sway/workspaces": {
"format": "<span size='larger'>{name}</span> {windows}",
"format-window-separator": " | ",
"window-rewrite-default": "{name}",
"window-format": "<span color='#e0e0e0'>{name}</span>",
"window-rewrite": {
"class<firefox>": "",
"class<kitty>": "k",
}
}
```
# Style
- *#workspaces button*
@@ -182,6 +150,5 @@ n.b.: the list of outputs can be obtained from command line using *swaymsg -t ge
- *#workspaces button.focused*
- *#workspaces button.urgent*
- *#workspaces button.persistent*
- *#workspaces button.empty*
- *#workspaces button.current_output*
- *#workspaces button#sway-workspace-${name}*

View File

@@ -71,11 +71,7 @@ Addressed by *temperature*
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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 ++

View File

@@ -47,11 +47,7 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
*align*: ++
typeof: float ++
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*justify*: ++
typeof: string ++
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
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.
*scroll-step*: ++
typeof: float ++

View File

@@ -16,11 +16,9 @@ Valid locations for this file are:
- */etc/xdg/waybar/*
- *@sysconfdir@/xdg/waybar/*
A good starting point is the default configuration found at https://github.com/Alexays/Waybar/blob/master/resources/config.jsonc
A good starting point is the default configuration found at https://github.com/Alexays/Waybar/blob/master/resources/config
Also, a minimal example configuration can be found at the bottom of this man page.
The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(5)* for details.
# BAR CONFIGURATION
*layer* ++
@@ -126,11 +124,6 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(
Each file can contain a single object with any of the bar configuration options. In case of duplicate options, the first defined value takes precedence, i.e. including file -> first included file -> etc. Nested includes are permitted, but make sure to avoid circular imports.
For a multi-bar config, the include directive affects only current bar configuration object.
*reload_style_on_change* ++
typeof: bool ++
default: *false* ++
Option to enable reloading the css style if a modification is detected on the style sheet file or any imported css files.
# MODULE FORMAT
You can use PangoMarkupFormat (See https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat).
@@ -312,7 +305,6 @@ A group may hide all but one element, showing them only on mouse hover. In order
- *waybar-custom(5)*
- *waybar-disk(5)*
- *waybar-dwl-tags(5)*
- *waybar-dwl-window(5)*
- *waybar-gamemode(5)*
- *waybar-hyprland-language(5)*
- *waybar-hyprland-submap(5)*
@@ -349,4 +341,3 @@ A group may hide all but one element, showing them only on mouse hover. In order
# SEE ALSO
*sway-output(5)*
*waybar-styles(5)"

View File

@@ -1,10 +1,10 @@
project(
'waybar', 'cpp', 'c',
version: '0.10.2',
version: '4.1.0',
license: 'MIT',
meson_version: '>= 0.59.0',
meson_version: '>= 1.3.0',
default_options : [
'cpp_std=c++20',
'cpp_std=c++23',
'buildtype=release',
'default_library=static'
],
@@ -22,6 +22,8 @@ endif
if compiler.has_link_argument('-lc++fs')
cpp_link_args += ['-lc++fs']
elif compiler.has_link_argument('-lc++experimental')
cpp_link_args += ['-lc++experimental']
elif compiler.has_link_argument('-lstdc++fs')
cpp_link_args += ['-lstdc++fs']
endif
@@ -31,10 +33,10 @@ git = find_program('git', native: true, required: false)
if not git.found()
add_project_arguments('-DVERSION="@0@"'.format(meson.project_version()), language: 'cpp')
else
git_path = run_command(git, 'rev-parse', '--show-toplevel', check: false).stdout().strip()
if meson.project_source_root() == git_path
git_commit_hash = run_command(git, 'describe', '--always', '--tags', check: false).stdout().strip()
git_branch = run_command(git, 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip()
git_path = run_command([git.path(), 'rev-parse', '--show-toplevel']).stdout().strip()
if meson.source_root() == git_path
git_commit_hash = run_command([git.path(), 'describe', '--always', '--tags']).stdout().strip()
git_branch = run_command([git.path(), 'rev-parse', '--abbrev-ref', 'HEAD']).stdout().strip()
version = '"@0@ (branch \'@1@\')"'.format(git_commit_hash, git_branch)
add_project_arguments('-DVERSION=@0@'.format(version), language: 'cpp')
else
@@ -42,6 +44,15 @@ else
endif
endif
if not compiler.has_header('filesystem')
if compiler.has_header('experimental/filesystem')
add_project_arguments('-DFILESYSTEM_EXPERIMENTAL', language: 'cpp')
else
add_project_arguments('-DNO_FILESYSTEM', language: 'cpp')
warning('No filesystem header found, some modules may not work')
endif
endif
code = '''
#include <langinfo.h>
#include <locale.h>
@@ -67,526 +78,60 @@ is_freebsd = host_machine.system() == 'freebsd'
is_netbsd = host_machine.system() == 'netbsd'
is_openbsd = host_machine.system() == 'openbsd'
thread_dep = dependency('threads')
fmt = dependency('fmt', version : ['>=8.1.1'], fallback : ['fmt', 'fmt_dep'])
spdlog = dependency('spdlog', version : ['>=1.10.0'], fallback : ['spdlog', 'spdlog_dep'], default_options : ['external_fmt=enabled'])
jsoncpp = dependency('jsoncpp', version : ['>=1.9.4'], fallback : ['jsoncpp', 'jsoncpp_dep'])
wayland_client = dependency('wayland-client')
wayland_cursor = dependency('wayland-cursor')
wayland_protos = dependency('wayland-protocols')
gtkmm = dependency('gtkmm-3.0', version : ['>=3.22.0'])
dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4', required: get_option('dbusmenu-gtk'))
giounix = dependency('gio-unix-2.0')
jsoncpp = dependency('jsoncpp', version : ['>=1.9.2'], fallback : ['jsoncpp', 'jsoncpp_dep'])
sigcpp = dependency('sigc++-2.0')
libinotify = dependency('libinotify', required: false)
libepoll = dependency('epoll-shim', required: false)
libinput = dependency('libinput', required: get_option('libinput'))
libnl = dependency('libnl-3.0', required: get_option('libnl'))
libnlgen = dependency('libnl-genl-3.0', required: get_option('libnl'))
upower_glib = dependency('upower-glib', required: get_option('upower_glib'))
pipewire = dependency('libpipewire-0.3', required: get_option('pipewire'))
playerctl = dependency('playerctl', version : ['>=2.0.0'], required: get_option('mpris'))
libpulse = dependency('libpulse', required: get_option('pulseaudio'))
libudev = dependency('libudev', required: get_option('libudev'))
libevdev = dependency('libevdev', required: get_option('libevdev'))
libmpdclient = dependency('libmpdclient', required: get_option('mpd'))
xkbregistry = dependency('xkbregistry')
libjack = dependency('jack', required: get_option('jack'))
libwireplumber = dependency('wireplumber-0.5', required: get_option('wireplumber'))
sigcpp = dependency('sigc++-3.0', version: ['>=3.4.0'])
gtkmm = dependency('gtkmm-4.0', version : ['>=4.12.0'])
giounix = dependency('gio-unix-2.0', version: ['>=2.76.4'])
spdlog = dependency('spdlog', version : ['>=1.10.0'], fallback : ['spdlog', 'spdlog_dep'], default_options : ['external_fmt=enabled'])
libsndio = compiler.find_library('sndio', required: get_option('sndio'))
if libsndio.found()
if not compiler.has_function('sioctl_open', prefix: '#include <sndio.h>', dependencies: libsndio)
if get_option('sndio').enabled()
error('libsndio is too old, required >=1.7.0')
else
warning('libsndio is too old, required >=1.7.0')
libsndio = dependency('', required: false)
endif
endif
endif
gtk_layer_shell = dependency('gtk-layer-shell-0', version: ['>=0.6.0'],
default_options: ['introspection=false', 'vapi=false'],
fallback: ['gtk-layer-shell', 'gtk_layer_shell'])
systemd = dependency('systemd', required: get_option('systemd'))
cpp_lib_chrono = compiler.compute_int('__cpp_lib_chrono', prefix : '#include <chrono>')
have_chrono_timezones = cpp_lib_chrono >= 201611
if have_chrono_timezones
code = '''
#include <chrono>
using namespace std::chrono;
int main(int argc, char** argv) {
const time_zone* tz;
return 0;
}
'''
if not compiler.links(code)
have_chrono_timezones = false
endif
endif
if have_chrono_timezones
tz_dep = declare_dependency()
else
tz_dep = dependency('date',
required: false,
default_options : [ 'use_system_tzdb=true' ],
modules : [ 'date::date', 'date::date-tz' ],
fallback: [ 'date', 'tz_dep' ])
endif
gtk_layer_shell = dependency('gtk4-layer-shell-0',
version : ['>=1.0.2'],
fallback : ['gtk4-layer-shell', 'gtk_layer_shell'],
default_options : ['introspection=false', 'vapi=false'])
prefix = get_option('prefix')
sysconfdir = get_option('sysconfdir')
conf_data = configuration_data()
conf_data.set('prefix', prefix)
add_project_arguments('-DSYSCONFDIR="@0@"'.format(prefix / sysconfdir), language : 'cpp')
if systemd.found()
user_units_dir = systemd.get_variable(pkgconfig: 'systemduserunitdir')
configure_file(
configuration: conf_data,
input: './resources/waybar.service.in',
output: '@BASENAME@',
install_dir: user_units_dir
)
endif
add_project_arguments('-DSYSCONFDIR="/@0@"'.format(join_paths(prefix, sysconfdir)), language : 'cpp')
src_files = files(
'src/factory.cpp',
'src/AModule.cpp',
'src/ALabel.cpp',
'src/AIconLabel.cpp',
'src/AAppIconLabel.cpp',
'src/modules/custom.cpp',
'src/modules/disk.cpp',
'src/modules/idle_inhibitor.cpp',
'src/modules/image.cpp',
'src/modules/load.cpp',
'src/modules/temperature.cpp',
'src/modules/user.cpp',
'src/ASlider.cpp',
'src/main.cpp',
'src/bar.cpp',
'src/client.cpp',
'src/config.cpp',
'src/group.cpp',
'src/util/portal.cpp',
'src/util/enum.cpp',
'src/util/prepare_for_sleep.cpp',
'src/util/ustring_clen.cpp',
'src/util/sanitize_str.cpp',
'src/util/rewrite_string.cpp',
'src/util/gtk_icon.cpp',
'src/util/regex_collection.cpp',
'src/util/css_reload_helper.cpp'
)
man_files = files(
'man/waybar-custom.5.scd',
'man/waybar-disk.5.scd',
'man/waybar-idle-inhibitor.5.scd',
'man/waybar-image.5.scd',
'man/waybar-states.5.scd',
'man/waybar-temperature.5.scd',
'src/main.cpp',
'src/client.cpp',
'src/bar.cpp',
'src/config.cpp',
'src/util/portal.cpp',
'src/util/prepare_for_sleep.cpp',
# 'src/AModule.cpp',
)
inc_dirs = ['include']
if is_linux
add_project_arguments('-DHAVE_CPU_LINUX', language: 'cpp')
add_project_arguments('-DHAVE_MEMORY_LINUX', language: 'cpp')
add_project_arguments('-DHAVE_SYSTEMD_MONITOR', language: 'cpp')
src_files += files(
'src/modules/battery.cpp',
'src/modules/bluetooth.cpp',
'src/modules/cffi.cpp',
'src/modules/cpu.cpp',
'src/modules/cpu_frequency/common.cpp',
'src/modules/cpu_frequency/linux.cpp',
'src/modules/cpu_usage/common.cpp',
'src/modules/cpu_usage/linux.cpp',
'src/modules/memory/common.cpp',
'src/modules/memory/linux.cpp',
'src/modules/power_profiles_daemon.cpp',
'src/modules/systemd_failed_units.cpp',
)
man_files += files(
'man/waybar-battery.5.scd',
'man/waybar-bluetooth.5.scd',
'man/waybar-cffi.5.scd',
'man/waybar-cpu.5.scd',
'man/waybar-memory.5.scd',
'man/waybar-systemd-failed-units.5.scd',
'man/waybar-power-profiles-daemon.5.scd',
)
elif is_dragonfly or is_freebsd or is_netbsd or is_openbsd
add_project_arguments('-DHAVE_CPU_BSD', language: 'cpp')
add_project_arguments('-DHAVE_MEMORY_BSD', language: 'cpp')
src_files += files(
'src/modules/cffi.cpp',
'src/modules/cpu.cpp',
'src/modules/cpu_frequency/bsd.cpp',
'src/modules/cpu_frequency/common.cpp',
'src/modules/cpu_usage/bsd.cpp',
'src/modules/cpu_usage/common.cpp',
'src/modules/memory/bsd.cpp',
'src/modules/memory/common.cpp',
)
man_files += files(
'man/waybar-cffi.5.scd',
'man/waybar-cpu.5.scd',
'man/waybar-memory.5.scd',
)
if is_freebsd
src_files += files('src/modules/battery.cpp')
man_files += files('man/waybar-battery.5.scd')
endif
endif
if true
add_project_arguments('-DHAVE_SWAY', language: 'cpp')
src_files += files(
'src/modules/sway/ipc/client.cpp',
'src/modules/sway/bar.cpp',
'src/modules/sway/mode.cpp',
'src/modules/sway/language.cpp',
'src/modules/sway/window.cpp',
'src/modules/sway/workspaces.cpp',
'src/modules/sway/scratchpad.cpp'
)
man_files += files(
'man/waybar-sway-language.5.scd',
'man/waybar-sway-mode.5.scd',
'man/waybar-sway-scratchpad.5.scd',
'man/waybar-sway-window.5.scd',
'man/waybar-sway-workspaces.5.scd',
)
endif
if true
add_project_arguments('-DHAVE_WLR_TASKBAR', language: 'cpp')
src_files += files('src/modules/wlr/taskbar.cpp')
man_files += files('man/waybar-wlr-taskbar.5.scd')
endif
if true
add_project_arguments('-DHAVE_RIVER', language: 'cpp')
src_files += files(
'src/modules/river/layout.cpp',
'src/modules/river/mode.cpp',
'src/modules/river/tags.cpp',
'src/modules/river/window.cpp',
)
man_files += files(
'man/waybar-river-layout.5.scd',
'man/waybar-river-mode.5.scd',
'man/waybar-river-tags.5.scd',
'man/waybar-river-window.5.scd',
)
endif
if true
add_project_arguments('-DHAVE_DWL', language: 'cpp')
src_files += files('src/modules/dwl/tags.cpp')
src_files += files('src/modules/dwl/window.cpp')
man_files += files('man/waybar-dwl-tags.5.scd')
man_files += files('man/waybar-dwl-window.5.scd')
endif
if true
add_project_arguments('-DHAVE_HYPRLAND', language: 'cpp')
src_files += files(
'src/modules/hyprland/backend.cpp',
'src/modules/hyprland/language.cpp',
'src/modules/hyprland/submap.cpp',
'src/modules/hyprland/window.cpp',
'src/modules/hyprland/workspaces.cpp',
)
man_files += files(
'man/waybar-hyprland-language.5.scd',
'man/waybar-hyprland-submap.5.scd',
'man/waybar-hyprland-window.5.scd',
'man/waybar-hyprland-workspaces.5.scd',
)
endif
if libnl.found() and libnlgen.found()
add_project_arguments('-DHAVE_LIBNL', language: 'cpp')
src_files += files('src/modules/network.cpp')
man_files += files('man/waybar-network.5.scd')
endif
if not get_option('logind').disabled()
add_project_arguments('-DHAVE_GAMEMODE', '-DHAVE_LOGIND_INHIBITOR', language: 'cpp')
src_files += files(
'src/modules/gamemode.cpp',
'src/modules/inhibitor.cpp',
)
man_files += files(
'man/waybar-gamemode.5.scd',
'man/waybar-inhibitor.5.scd',
)
endif
if (upower_glib.found() and not get_option('logind').disabled())
add_project_arguments('-DHAVE_UPOWER', language: 'cpp')
src_files += files(
'src/modules/upower/upower.cpp',
'src/modules/upower/upower_tooltip.cpp',
)
man_files += files('man/waybar-upower.5.scd')
endif
if pipewire.found()
add_project_arguments('-DHAVE_PIPEWIRE', language: 'cpp')
src_files += files(
'src/modules/privacy/privacy.cpp',
'src/modules/privacy/privacy_item.cpp',
'src/util/pipewire/pipewire_backend.cpp',
'src/util/pipewire/privacy_node_info.cpp',
)
man_files += files('man/waybar-privacy.5.scd')
endif
if playerctl.found()
add_project_arguments('-DHAVE_MPRIS', language: 'cpp')
src_files += files('src/modules/mpris/mpris.cpp')
man_files += files('man/waybar-mpris.5.scd')
endif
if libpulse.found()
add_project_arguments('-DHAVE_LIBPULSE', language: 'cpp')
src_files += files(
'src/modules/pulseaudio.cpp',
'src/modules/pulseaudio_slider.cpp',
'src/util/audio_backend.cpp',
)
man_files += files(
'man/waybar-pulseaudio.5.scd',
'man/waybar-pulseaudio-slider.5.scd',
)
endif
if libjack.found()
add_project_arguments('-DHAVE_LIBJACK', language: 'cpp')
src_files += files('src/modules/jack.cpp')
man_files += files('man/waybar-jack.5.scd')
endif
if libwireplumber.found()
add_project_arguments('-DHAVE_LIBWIREPLUMBER', language: 'cpp')
src_files += files('src/modules/wireplumber.cpp')
man_files += files('man/waybar-wireplumber.5.scd')
endif
if dbusmenu_gtk.found()
add_project_arguments('-DHAVE_DBUSMENU', language: 'cpp')
src_files += files(
'src/modules/sni/tray.cpp',
'src/modules/sni/watcher.cpp',
'src/modules/sni/host.cpp',
'src/modules/sni/item.cpp'
)
man_files += files(
'man/waybar-tray.5.scd',
)
endif
if libudev.found() and (is_linux or libepoll.found())
add_project_arguments('-DHAVE_LIBUDEV', language: 'cpp')
src_files += files(
'src/modules/backlight.cpp',
'src/modules/backlight_slider.cpp',
'src/util/backlight_backend.cpp',
)
man_files += files(
'man/waybar-backlight.5.scd',
'man/waybar-backlight-slider.5.scd',
)
endif
if libevdev.found() and (is_linux or libepoll.found()) and libinput.found() and (is_linux or libinotify.found())
add_project_arguments('-DHAVE_LIBEVDEV', language: 'cpp')
add_project_arguments('-DHAVE_LIBINPUT', language: 'cpp')
src_files += files('src/modules/keyboard_state.cpp')
man_files += files('man/waybar-keyboard-state.5.scd')
endif
if libmpdclient.found()
add_project_arguments('-DHAVE_LIBMPDCLIENT', language: 'cpp')
src_files += files(
'src/modules/mpd/mpd.cpp',
'src/modules/mpd/state.cpp',
)
man_files += files(
'man/waybar-mpd.5.scd',
)
endif
if libsndio.found()
add_project_arguments('-DHAVE_LIBSNDIO', language: 'cpp')
src_files += files('src/modules/sndio.cpp')
man_files += files('man/waybar-sndio.5.scd')
endif
if get_option('rfkill').enabled() and is_linux
add_project_arguments('-DWANT_RFKILL', language: 'cpp')
src_files += files(
'src/util/rfkill.cpp'
)
endif
if have_chrono_timezones
add_project_arguments('-DHAVE_CHRONO_TIMEZONES', language: 'cpp')
src_files += files('src/modules/clock.cpp')
man_files += files('man/waybar-clock.5.scd')
elif tz_dep.found()
add_project_arguments('-DHAVE_LIBDATE', language: 'cpp')
src_files += files('src/modules/clock.cpp')
man_files += files('man/waybar-clock.5.scd')
else
src_files += files('src/modules/simpleclock.cpp')
man_files += files('man/waybar-clock.5.scd')
endif
if get_option('experimental')
add_project_arguments('-DHAVE_WLR_WORKSPACES', language: 'cpp')
src_files += files(
'src/modules/wlr/workspace_manager.cpp',
'src/modules/wlr/workspace_manager_binding.cpp',
)
man_files += files(
'man/waybar-wlr-workspaces.5.scd',
)
endif
cava = dependency('cava',
version : '>=0.10.1',
required: get_option('cava'),
fallback : ['cava', 'cava_dep'],
not_found_message: 'cava is not found. Building waybar without cava')
if cava.found()
add_project_arguments('-DHAVE_LIBCAVA', language: 'cpp')
src_files += files('src/modules/cava.cpp')
man_files += files('man/waybar-cava.5.scd')
endif
subdir('protocol')
app_resources = []
subdir('resources/icons')
executable(
'waybar',
[src_files, app_resources],
[src_files],
dependencies: [
thread_dep,
client_protos,
wayland_client,
fmt,
spdlog,
gtk_layer_shell,
gtkmm,
giounix,
sigcpp,
jsoncpp,
wayland_client,
wayland_cursor,
gtkmm,
dbusmenu_gtk,
giounix,
libinput,
libnl,
libnlgen,
upower_glib,
pipewire,
playerctl,
libpulse,
libjack,
libwireplumber,
libudev,
libinotify,
libepoll,
libmpdclient,
libevdev,
gtk_layer_shell,
libsndio,
tz_dep,
xkbregistry,
cava
client_protos,
spdlog
],
include_directories: inc_dirs,
install: true,
)
install_data(
'resources/config.jsonc',
'resources/style.css',
install_dir: sysconfdir / 'xdg/waybar'
'./resources/config',
'./resources/style.css',
install_dir: sysconfdir + '/xdg/waybar'
)
scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages'))
if scdoc.found()
man_files += configure_file(
input: 'man/waybar.5.scd.in',
output: 'waybar.5.scd',
configuration: {
'sysconfdir': prefix / sysconfdir
}
)
man_files += configure_file(
input: 'man/waybar-styles.5.scd.in',
output: 'waybar-styles.5.scd',
configuration: {
'sysconfdir': prefix / sysconfdir
}
)
fs = import('fs')
mandir = get_option('mandir')
foreach file : man_files
basename = fs.name(file)
topic = basename.split('.')[-3]
section = basename.split('.')[-2]
output = '@0@.@1@'.format(topic, section)
custom_target(
output,
input: file,
output: output,
command: scdoc.get_variable('scdoc'),
feed: true,
capture: true,
install: true,
install_dir: '@0@/man@1@'.format(mandir, section)
)
endforeach
endif
catch2 = dependency(
'catch2',
default_options: [ 'tests=false' ],
fallback: ['catch2', 'catch2_dep'],
required: get_option('tests'),
)
if catch2.found()
subdir('test')
endif
clangtidy = find_program('clang-tidy', required: false)
if clangtidy.found()
run_target(
'tidy',
command: [
clangtidy,
'-checks=*,-fuchsia-default-arguments',
'-p', meson.project_build_root()
] + src_files)
endif

View File

@@ -4,36 +4,27 @@
, version
}:
let
libcava = rec {
version = "0.10.1";
src = pkgs.fetchFromGitHub {
owner = "LukashonakV";
repo = "cava";
rev = version;
hash = "sha256-iIYKvpOWafPJB5XhDOSIW9Mb4I3A4pcgIIPQdQYEqUw=";
};
catch2_3 = {
src = pkgs.fetchFromGitHub
{
owner = "catchorg";
repo = "Catch2";
rev = "v3.5.1";
hash = "sha256-OyYNUfnu6h1+MfCF8O+awQ4Usad0qrdCtdZhYgOY+Vw=";
};
};
in
(waybar.overrideAttrs (
oldAttrs: {
inherit version;
(waybar.overrideAttrs (oldAttrs: rec {
inherit version;
src = lib.cleanSourceWith {
filter = name: type: type != "regular" || !lib.hasSuffix ".nix" name;
src = lib.cleanSource ../.;
};
mesonFlags = lib.remove "-Dgtk-layer-shell=enabled" oldAttrs.mesonFlags;
buildInputs = (builtins.filter (p: p.pname != "wireplumber") oldAttrs.buildInputs) ++ [
pkgs.wireplumber
];
postUnpack = ''
pushd "$sourceRoot"
cp -R --no-preserve=mode,ownership ${libcava.src} subprojects/cava-${libcava.version}
patchShebangs .
popd
'';
}
))
src = lib.cleanSourceWith {
filter = name: type: type != "regular" || !lib.hasSuffix ".nix" name;
src = lib.cleanSource ../.;
};
})
).override {
catch2_3 = pkgs.catch2_3.overrideAttrs (oldAttrs: {
version = "3.5.1";
src = catch2_3.src;
});
}

View File

@@ -1,4 +1,4 @@
wl_protocol_dir = wayland_protos.get_variable(pkgconfig: 'pkgdatadir')
wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir')
wayland_scanner = find_program('wayland-scanner')
@@ -43,7 +43,7 @@ endforeach
gdbus_codegen = find_program('gdbus-codegen')
r = run_command(gdbus_codegen, '--body', '--output', '/dev/null', check: false)
r = run_command(gdbus_codegen, '--body', '--output', '/dev/null')
if r.returncode() != 0
gdbus_code_dsnw = custom_target(
'dbus-status-notifier-watcher.[ch]',

View File

@@ -1,4 +1,3 @@
// -*- mode: jsonc -*-
{
// "layer": "top", // Waybar at top layer
// "position": "bottom", // Waybar position (top|bottom|left|right)
@@ -6,32 +5,9 @@
// "width": 1280, // Waybar width
"spacing": 4, // Gaps between modules (4px)
// Choose the order of the modules
"modules-left": [
"sway/workspaces",
"sway/mode",
"sway/scratchpad",
"custom/media"
],
"modules-center": [
"sway/window"
],
"modules-right": [
"mpd",
"idle_inhibitor",
"pulseaudio",
"network",
"power-profiles-daemon",
"cpu",
"memory",
"temperature",
"backlight",
"keyboard-state",
"sway/language",
"battery",
"battery#bat2",
"clock",
"tray"
],
"modules-left": ["sway/workspaces", "sway/mode", "sway/scratchpad", "custom/media"],
"modules-center": ["sway/window"],
"modules-right": ["mpd", "idle_inhibitor", "pulseaudio", "network", "cpu", "memory", "temperature", "backlight", "keyboard-state", "sway/language", "battery", "battery#bat2", "clock", "tray"],
// Modules configuration
// "sway/workspaces": {
// "disable-scroll": true,
@@ -73,7 +49,7 @@
"format-disconnected": "Disconnected ",
"format-stopped": "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ",
"unknown-tag": "N/A",
"interval": 5,
"interval": 2,
"consume-icons": {
"on": " "
},
@@ -137,7 +113,6 @@
"critical": 15
},
"format": "{capacity}% {icon}",
"format-full": "{capacity}% {icon}",
"format-charging": "{capacity}% ",
"format-plugged": "{capacity}% ",
"format-alt": "{time} {icon}",
@@ -148,17 +123,6 @@
"battery#bat2": {
"bat": "BAT2"
},
"power-profiles-daemon": {
"format": "{icon}",
"tooltip-format": "Power profile: {profile}\nDriver: {driver}",
"tooltip": true,
"format-icons": {
"default": "",
"performance": "",
"balanced": "",
"power-saver": ""
}
},
"network": {
// "interface": "wlp2*", // (Optional) To force the use of this interface
"format-wifi": "{essid} ({signalStrength}%) ",
@@ -200,3 +164,4 @@
// "exec": "$HOME/.config/waybar/mediaplayer.py --player spotify 2> /dev/null" // Filter player based on name
}
}

View File

@@ -23,7 +23,7 @@ def signal_handler(sig, frame):
class PlayerManager:
def __init__(self, selected_player=None, excluded_player=[]):
def __init__(self, selected_player=None):
self.manager = Playerctl.PlayerManager()
self.loop = GLib.MainLoop()
self.manager.connect(
@@ -35,14 +35,11 @@ class PlayerManager:
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
self.selected_player = selected_player
self.excluded_player = excluded_player.split(',') if excluded_player else []
self.init_players()
def init_players(self):
for player in self.manager.props.player_names:
if player.name in self.excluded_player:
continue
if self.selected_player is not None and self.selected_player != player.name:
logger.debug(f"{player.name} is not the filtered player, skipping it")
continue
@@ -152,8 +149,6 @@ def parse_arguments():
# Increase verbosity with every occurrence of -v
parser.add_argument("-v", "--verbose", action="count", default=0)
parser.add_argument("-x", "--exclude", "- Comma-separated list of excluded player")
# Define for which player we"re listening
parser.add_argument("--player")
@@ -179,10 +174,7 @@ def main():
logger.info("Creating player manager")
if arguments.player:
logger.info(f"Filtering for player: {arguments.player}")
if arguments.exclude:
logger.info(f"Exclude player {arguments.exclude}")
player = PlayerManager(arguments.player, arguments.exclude)
player = PlayerManager(arguments.player)
player.run()

View File

@@ -48,11 +48,6 @@ button:hover {
box-shadow: inset 0 -3px #ffffff;
}
/* you can set a style on hover for any module like this */
#pulseaudio:hover {
background-color: #a37800;
}
#workspaces button {
padding: 0 5px;
background-color: transparent;
@@ -74,7 +69,7 @@ button:hover {
#mode {
background-color: #64727D;
box-shadow: inset 0 -3px #ffffff;
border-bottom: 3px solid #ffffff;
}
#clock,
@@ -92,7 +87,6 @@ button:hover {
#mode,
#idle_inhibitor,
#scratchpad,
#power-profiles-daemon,
#mpd {
padding: 0 10px;
color: #ffffff;
@@ -134,36 +128,16 @@ button:hover {
}
}
/* Using steps() instead of linear as a timing function to limit cpu usage */
#battery.critical:not(.charging) {
background-color: #f53c3c;
color: #ffffff;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: steps(12);
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#power-profiles-daemon {
padding-right: 15px;
}
#power-profiles-daemon.performance {
background-color: #f53c3c;
color: #ffffff;
}
#power-profiles-daemon.balanced {
background-color: #2980b9;
color: #ffffff;
}
#power-profiles-daemon.power-saver {
background-color: #2ecc71;
color: #000000;
}
label:focus {
background-color: #000000;
}

View File

@@ -24,61 +24,18 @@ AAppIconLabel::AAppIconLabel(const Json::Value& config, const std::string& name,
image_.set_pixel_size(app_icon_size_);
}
std::string toLowerCase(const std::string& input) {
std::string result = input;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::tolower(c); });
return result;
}
std::optional<std::string> getFileBySuffix(const std::string& dir, const std::string& suffix,
bool check_lower_case) {
if (!std::filesystem::exists(dir)) {
return {};
}
for (const auto& entry : std::filesystem::recursive_directory_iterator(dir)) {
if (entry.is_regular_file()) {
std::string filename = entry.path().filename().string();
if (filename.size() < suffix.size()) {
continue;
}
if ((filename.compare(filename.size() - suffix.size(), suffix.size(), suffix) == 0) ||
(check_lower_case && filename.compare(filename.size() - suffix.size(), suffix.size(),
toLowerCase(suffix)) == 0)) {
return entry.path().string();
}
}
}
return {};
}
std::optional<std::string> getFileBySuffix(const std::string& dir, const std::string& suffix) {
return getFileBySuffix(dir, suffix, false);
}
std::optional<std::string> getDesktopFilePath(const std::string& app_identifier,
const std::string& alternative_app_identifier) {
if (app_identifier.empty()) {
return {};
}
const auto data_dirs = Glib::get_system_data_dirs();
for (const auto& data_dir : data_dirs) {
const auto data_app_dir = data_dir + "/applications/";
auto desktop_file_suffix = app_identifier + ".desktop";
// searching for file by suffix catches cases like terminal emulator "foot" where class is
// "footclient" and desktop file is named "org.codeberg.dnkl.footclient.desktop"
auto desktop_file_path = getFileBySuffix(data_app_dir, desktop_file_suffix, true);
// "true" argument allows checking for lowercase - this catches cases where class name is
// "LibreWolf" and desktop file is named "librewolf.desktop"
if (desktop_file_path.has_value()) {
const auto data_app_dir = data_dir + "applications/";
auto desktop_file_path = data_app_dir + app_identifier + ".desktop";
if (std::filesystem::exists(desktop_file_path)) {
return desktop_file_path;
}
if (!alternative_app_identifier.empty()) {
desktop_file_suffix = alternative_app_identifier + ".desktop";
desktop_file_path = getFileBySuffix(data_app_dir, desktop_file_suffix, true);
if (desktop_file_path.has_value()) {
desktop_file_path = data_app_dir + alternative_app_identifier + ".desktop";
if (std::filesystem::exists(desktop_file_path)) {
return desktop_file_path;
}
}
@@ -101,9 +58,16 @@ std::optional<Glib::ustring> getIconName(const std::string& app_identifier,
return app_identifier_desktop;
}
const auto to_lower = [](const std::string& str) {
auto str_cpy = str;
std::transform(str_cpy.begin(), str_cpy.end(), str_cpy.begin(),
[](unsigned char c) { return std::tolower(c); });
return str;
};
const auto first_space = app_identifier.find_first_of(' ');
if (first_space != std::string::npos) {
const auto first_word = toLowerCase(app_identifier.substr(0, first_space));
const auto first_word = to_lower(app_identifier.substr(0, first_space));
if (DefaultGtkIconThemeWrapper::has_icon(first_word)) {
return first_word;
}
@@ -111,7 +75,7 @@ std::optional<Glib::ustring> getIconName(const std::string& app_identifier,
const auto first_dash = app_identifier.find_first_of('-');
if (first_dash != std::string::npos) {
const auto first_word = toLowerCase(app_identifier.substr(0, first_dash));
const auto first_word = to_lower(app_identifier.substr(0, first_dash));
if (DefaultGtkIconThemeWrapper::has_icon(first_word)) {
return first_word;
}

View File

@@ -9,23 +9,10 @@ AIconLabel::AIconLabel(const Json::Value &config, const std::string &name, const
bool enable_click, bool enable_scroll)
: ALabel(config, name, id, format, interval, ellipsize, enable_click, enable_scroll) {
event_box_.remove();
label_.unset_name();
label_.get_style_context()->remove_class(MODULE_CLASS);
box_.get_style_context()->add_class(MODULE_CLASS);
if (!id.empty()) {
label_.get_style_context()->remove_class(id);
box_.get_style_context()->add_class(id);
}
box_.set_orientation(Gtk::Orientation::ORIENTATION_HORIZONTAL);
box_.set_name(name);
int spacing = config_["icon-spacing"].isInt() ? config_["icon-spacing"].asInt() : 8;
box_.set_spacing(spacing);
box_.set_spacing(8);
box_.add(image_);
box_.add(label_);
event_box_.add(box_);
}

View File

@@ -50,17 +50,6 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
label_.set_xalign(align);
}
}
if (config_["justify"].isString()) {
auto justify_str = config_["justify"].asString();
if (justify_str == "left") {
label_.set_justify(Gtk::Justification::JUSTIFY_LEFT);
} else if (justify_str == "right") {
label_.set_justify(Gtk::Justification::JUSTIFY_RIGHT);
} else if (justify_str == "center") {
label_.set_justify(Gtk::Justification::JUSTIFY_CENTER);
}
}
}
auto ALabel::update() -> void { AModule::update(); }

View File

@@ -27,9 +27,6 @@ AModule::AModule(const Json::Value& config, const std::string& name, const std::
spdlog::warn("Wrong actions section configuration. See config by index: {}", it.index());
}
event_box_.signal_enter_notify_event().connect(sigc::mem_fun(*this, &AModule::handleMouseEnter));
event_box_.signal_leave_notify_event().connect(sigc::mem_fun(*this, &AModule::handleMouseLeave));
// configure events' user commands
// hasUserEvent is true if any element from eventMap_ is satisfying the condition in the lambda
bool hasUserEvent =
@@ -54,9 +51,7 @@ AModule::AModule(const Json::Value& config, const std::string& name, const std::
event_box_.add_events(Gdk::BUTTON_RELEASE_MASK);
event_box_.signal_button_release_event().connect(sigc::mem_fun(*this, &AModule::handleRelease));
}
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString() ||
config_["on-scroll-left"].isString() || config_["on-scroll-right"].isString() ||
enable_scroll) {
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString() || enable_scroll) {
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &AModule::handleScroll));
}
@@ -86,20 +81,6 @@ auto AModule::doAction(const std::string& name) -> void {
}
}
bool AModule::handleMouseEnter(GdkEventCrossing* const& e) {
if (auto* module = event_box_.get_child(); module != nullptr) {
module->set_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
}
return false;
}
bool AModule::handleMouseLeave(GdkEventCrossing* const& e) {
if (auto* module = event_box_.get_child(); module != nullptr) {
module->unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
}
return false;
}
bool AModule::handleToggle(GdkEventButton* const& e) { return handleUserEvent(e); }
bool AModule::handleRelease(GdkEventButton* const& e) { return handleUserEvent(e); }
@@ -198,10 +179,6 @@ bool AModule::handleScroll(GdkEventScroll* e) {
eventName = "on-scroll-up";
else if (dir == SCROLL_DIR::DOWN)
eventName = "on-scroll-down";
else if (dir == SCROLL_DIR::LEFT)
eventName = "on-scroll-left";
else if (dir == SCROLL_DIR::RIGHT)
eventName = "on-scroll-right";
// First call module actions
this->AModule::doAction(eventName);

View File

@@ -1,13 +1,11 @@
#include "bar.hpp"
#include <gtk-layer-shell.h>
#include <gtk4-layer-shell.h>
#include <spdlog/spdlog.h>
#include <type_traits>
#include "client.hpp"
#include "factory.hpp"
#include "group.hpp"
//#include "factory.hpp"
//#include "group.hpp"
#ifdef HAVE_SWAY
#include "modules/sway/bar.hpp"
@@ -90,28 +88,27 @@ void from_json(const Json::Value& j, bar_mode& m) {
/* Deserializer for enum Gtk::PositionType */
void from_json(const Json::Value& j, Gtk::PositionType& pos) {
if (j == "left") {
pos = Gtk::POS_LEFT;
pos = Gtk::PositionType::LEFT;
} else if (j == "right") {
pos = Gtk::POS_RIGHT;
pos = Gtk::PositionType::RIGHT;
} else if (j == "top") {
pos = Gtk::POS_TOP;
pos = Gtk::PositionType::TOP;
} else if (j == "bottom") {
pos = Gtk::POS_BOTTOM;
pos = Gtk::PositionType::BOTTOM;
}
}
Glib::ustring to_string(Gtk::PositionType pos) {
switch (pos) {
case Gtk::POS_LEFT:
case Gtk::PositionType::LEFT:
return "left";
case Gtk::POS_RIGHT:
case Gtk::PositionType::RIGHT:
return "right";
case Gtk::POS_TOP:
case Gtk::PositionType::TOP:
return "top";
case Gtk::POS_BOTTOM:
case Gtk::PositionType::BOTTOM:
return "bottom";
}
throw std::runtime_error("Invalid Gtk::PositionType");
}
/* Deserializer for JSON Object -> map<string compatible type, Value>
@@ -132,31 +129,32 @@ void from_json(const Json::Value& j, std::map<Key, Value>& m) {
waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
: output(w_output),
config(w_config),
window{Gtk::WindowType::WINDOW_TOPLEVEL},
window{Gtk::Window()},
x_global(0),
y_global(0),
margins_{.top = 0, .right = 0, .bottom = 0, .left = 0},
left_(Gtk::ORIENTATION_HORIZONTAL, 0),
center_(Gtk::ORIENTATION_HORIZONTAL, 0),
right_(Gtk::ORIENTATION_HORIZONTAL, 0),
box_(Gtk::ORIENTATION_HORIZONTAL, 0) {
left_(Gtk::Orientation::HORIZONTAL, 0),
center_(Gtk::Orientation::HORIZONTAL, 0),
right_(Gtk::Orientation::HORIZONTAL, 0),
box_{} {
window.set_title("waybar");
window.set_name("waybar");
window.set_decorated(false);
window.set_child(box_);
window.get_style_context()->add_class(output->name);
window.get_style_context()->add_class(config["name"].asString());
from_json(config["position"], position);
orientation = (position == Gtk::POS_LEFT || position == Gtk::POS_RIGHT)
? Gtk::ORIENTATION_VERTICAL
: Gtk::ORIENTATION_HORIZONTAL;
orientation = (position == Gtk::PositionType::LEFT || position == Gtk::PositionType::RIGHT)
? Gtk::Orientation::VERTICAL
: Gtk::Orientation::HORIZONTAL;
window.get_style_context()->add_class(to_string(position));
left_ = Gtk::Box(orientation, 0);
center_ = Gtk::Box(orientation, 0);
right_ = Gtk::Box(orientation, 0);
box_ = Gtk::Box(orientation, 0);
left_.set_orientation(orientation);
center_.set_orientation(orientation);
right_.set_orientation(orientation);
box_.set_orientation(orientation);
left_.get_style_context()->add_class("modules-left");
center_.get_style_context()->add_class("modules-center");
@@ -217,7 +215,6 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
margins_ = {.top = gaps, .right = gaps, .bottom = gaps, .left = gaps};
}
window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure));
output->monitor->property_geometry().signal_changed().connect(
sigc::mem_fun(*this, &Bar::onOutputGeometryChanged));
@@ -257,7 +254,7 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
setVisible(false);
}
window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap));
window.signal_map().connect(sigc::mem_fun(*this, &Bar::onMap));
#if HAVE_SWAY
if (auto ipc = config["ipc"]; ipc.isBool() && ipc.asBool()) {
@@ -277,7 +274,7 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
#endif
setupWidgets();
window.show_all();
window.show();
if (spdlog::should_log(spdlog::level::debug)) {
// Unfortunately, this function isn't in the C++ bindings, so we have to call the C version.
@@ -342,13 +339,12 @@ void waybar::Bar::setMode(const struct bar_mode& mode) {
}
void waybar::Bar::setPassThrough(bool passthrough) {
auto gdk_window = window.get_window();
if (gdk_window) {
if (gdk_surface_) {
Cairo::RefPtr<Cairo::Region> region;
if (passthrough) {
region = Cairo::Region::create();
}
gdk_window->input_shape_combine_region(region, 0, 0);
gdk_surface_->set_input_region(region);
}
}
@@ -356,18 +352,18 @@ void waybar::Bar::setPosition(Gtk::PositionType position) {
std::array<gboolean, GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER> anchors;
anchors.fill(TRUE);
auto orientation = (position == Gtk::POS_LEFT || position == Gtk::POS_RIGHT)
? Gtk::ORIENTATION_VERTICAL
: Gtk::ORIENTATION_HORIZONTAL;
auto orientation = (position == Gtk::PositionType::LEFT || position == Gtk::PositionType::RIGHT)
? Gtk::Orientation::VERTICAL
: Gtk::Orientation::HORIZONTAL;
switch (position) {
case Gtk::POS_LEFT:
case Gtk::PositionType::LEFT:
anchors[GTK_LAYER_SHELL_EDGE_RIGHT] = FALSE;
break;
case Gtk::POS_RIGHT:
case Gtk::PositionType::RIGHT:
anchors[GTK_LAYER_SHELL_EDGE_LEFT] = FALSE;
break;
case Gtk::POS_BOTTOM:
case Gtk::PositionType::BOTTOM:
anchors[GTK_LAYER_SHELL_EDGE_TOP] = FALSE;
break;
default: /* Gtk::POS_TOP */
@@ -379,10 +375,10 @@ void waybar::Bar::setPosition(Gtk::PositionType position) {
// otherwise the bar will use all space
uint32_t configured_width = config["width"].isUInt() ? config["width"].asUInt() : 0;
uint32_t configured_height = config["height"].isUInt() ? config["height"].asUInt() : 0;
if (orientation == Gtk::ORIENTATION_VERTICAL && configured_height > 1) {
if (orientation == Gtk::Orientation::VERTICAL && configured_height > 1) {
anchors[GTK_LAYER_SHELL_EDGE_TOP] = FALSE;
anchors[GTK_LAYER_SHELL_EDGE_BOTTOM] = FALSE;
} else if (orientation == Gtk::ORIENTATION_HORIZONTAL && configured_width > 1) {
} else if (orientation == Gtk::Orientation::HORIZONTAL && configured_width > 1) {
anchors[GTK_LAYER_SHELL_EDGE_LEFT] = FALSE;
anchors[GTK_LAYER_SHELL_EDGE_RIGHT] = FALSE;
}
@@ -393,13 +389,14 @@ void waybar::Bar::setPosition(Gtk::PositionType position) {
}
}
void waybar::Bar::onMap(GdkEventAny*) {
void waybar::Bar::onMap() {
/*
* Obtain a pointer to the custom layer surface for modules that require it (idle_inhibitor).
*/
auto gdk_window = window.get_window()->gobj();
surface = gdk_wayland_window_get_wl_surface(gdk_window);
configureGlobalOffset(gdk_window_get_width(gdk_window), gdk_window_get_height(gdk_window));
gdk_surface_ = window.get_surface();
surface = gdk_wayland_surface_get_wl_surface(gdk_surface_->gobj());
configureGlobalOffset(gdk_surface_->get_width(), gdk_surface_->get_height());
gdk_surface_->signal_layout().connect(sigc::mem_fun(*this, &Bar::onConfigure));
setPassThrough(passthrough_);
}
@@ -449,17 +446,7 @@ void waybar::Bar::setupAltFormatKeyForModuleList(const char* module_list_name) {
Json::Value& modules = config[module_list_name];
for (const Json::Value& module_name : modules) {
if (module_name.isString()) {
auto ref = module_name.asString();
if (ref.compare(0, 6, "group/") == 0 && ref.size() > 6) {
Json::Value& group_modules = config[ref]["modules"];
for (const Json::Value& module_name : group_modules) {
if (module_name.isString()) {
setupAltFormatKeyForModule(module_name.asString());
}
}
} else {
setupAltFormatKeyForModule(ref);
}
setupAltFormatKeyForModule(module_name.asString());
}
}
}
@@ -471,6 +458,8 @@ void waybar::Bar::handleSignal(int signal) {
}
}
// todo gtkmm4
/*
void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
waybar::Group* group = nullptr) {
auto module_list = group ? config[pos]["modules"] : config[pos];
@@ -486,7 +475,7 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
auto class_name = hash_pos != std::string::npos ? ref.substr(hash_pos + 1) : "";
auto vertical = (group ? group->getBox().get_orientation() : box_.get_orientation()) ==
Gtk::ORIENTATION_VERTICAL;
Gtk::Orientation::VERTICAL;
auto group_module = new waybar::Group(id_name, class_name, config[ref], vertical);
getModules(factory, ref, group_module);
@@ -523,39 +512,38 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
}
}
}
*/
auto waybar::Bar::setupWidgets() -> void {
window.add(box_);
box_.pack_start(left_, false, false);
box_.set_start_widget(left_);
if (config["fixed-center"].isBool() ? config["fixed-center"].asBool() : true) {
box_.set_center_widget(center_);
} else {
box_.pack_start(center_, true, false);
box_.set_start_widget(center_);
}
box_.pack_end(right_, false, false);
box_.set_end_widget(right_);
// Convert to button code for every module that is used.
setupAltFormatKeyForModuleList("modules-left");
setupAltFormatKeyForModuleList("modules-right");
setupAltFormatKeyForModuleList("modules-center");
Factory factory(*this, config);
getModules(factory, "modules-left");
getModules(factory, "modules-center");
getModules(factory, "modules-right");
// todo gtkmm4
// Factory factory(*this, config);
// getModules(factory, "modules-left");
// getModules(factory, "modules-center");
// getModules(factory, "modules-right");
for (auto const& module : modules_left_) {
left_.pack_start(*module, false, false);
left_.prepend(*module);
}
for (auto const& module : modules_center_) {
center_.pack_start(*module, false, false);
center_.prepend(*module);
}
std::reverse(modules_right_.begin(), modules_right_.end());
for (auto const& module : modules_right_) {
right_.pack_end(*module, false, false);
right_.append(*module);
}
}
void waybar::Bar::onConfigure(GdkEventConfigure* ev) {
void waybar::Bar::onConfigure(int width, int height) {
/*
* GTK wants new size for the window.
* Actual resizing and management of the exclusve zone is handled within the gtk-layer-shell
@@ -564,20 +552,20 @@ void waybar::Bar::onConfigure(GdkEventConfigure* ev) {
* Note: forced resizing to a window smaller than required by GTK would not work with
* gtk-layer-shell.
*/
if (orientation == Gtk::ORIENTATION_VERTICAL) {
if (width_ > 1 && ev->width > static_cast<int>(width_)) {
spdlog::warn(MIN_WIDTH_MSG, width_, ev->width);
if (orientation == Gtk::Orientation::VERTICAL) {
if (width_ > 1 && width > static_cast<int>(width_)) {
spdlog::warn(MIN_WIDTH_MSG, width_, width);
}
} else {
if (height_ > 1 && ev->height > static_cast<int>(height_)) {
spdlog::warn(MIN_HEIGHT_MSG, height_, ev->height);
if (height_ > 1 && height > static_cast<int>(height_)) {
spdlog::warn(MIN_HEIGHT_MSG, height_, height);
}
}
width_ = ev->width;
height_ = ev->height;
width_ = width;
height_ = height;
configureGlobalOffset(ev->width, ev->height);
spdlog::info(BAR_SIZE_MSG, ev->width, ev->height, output->name);
configureGlobalOffset(width, height);
spdlog::info(BAR_SIZE_MSG, width, height, output->name);
}
void waybar::Bar::configureGlobalOffset(int width, int height) {
@@ -585,28 +573,28 @@ void waybar::Bar::configureGlobalOffset(int width, int height) {
int x;
int y;
switch (position) {
case Gtk::POS_BOTTOM:
case Gtk::PositionType::BOTTOM:
if (width + margins_.left + margins_.right >= monitor_geometry.width)
x = margins_.left;
else
x = (monitor_geometry.width - width) / 2;
y = monitor_geometry.height - height - margins_.bottom;
break;
case Gtk::POS_LEFT:
case Gtk::PositionType::LEFT:
x = margins_.left;
if (height + margins_.top + margins_.bottom >= monitor_geometry.height)
y = margins_.top;
else
y = (monitor_geometry.height - height) / 2;
break;
case Gtk::POS_RIGHT:
case Gtk::PositionType::RIGHT:
x = monitor_geometry.width - width - margins_.right;
if (height + margins_.top + margins_.bottom >= monitor_geometry.height)
y = margins_.top;
else
y = (monitor_geometry.height - height) / 2;
break;
default: /* Gtk::POS_TOP */
default: /* Gtk::PositionType::TOP */
if (width + margins_.left + margins_.right >= monitor_geometry.width)
x = margins_.left;
else

View File

@@ -1,11 +1,12 @@
#include "client.hpp"
#include <gtk-layer-shell.h>
#include <gtk4-layer-shell.h>
#include <spdlog/spdlog.h>
#include <iostream>
#include "gtkmm/icontheme.h"
#include "gtkmm/application.h"
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "util/clara.hpp"
#include "util/format.hpp"
@@ -176,14 +177,15 @@ const std::string waybar::Client::getStyle(const std::string &style,
auto waybar::Client::setupCss(const std::string &css_file) -> void {
css_provider_ = Gtk::CssProvider::create();
style_context_ = Gtk::StyleContext::create();
// Load our css file, wherever that may be hiding
if (!css_provider_->load_from_path(css_file)) {
throw std::runtime_error("Can't open style file");
try {
css_provider_->load_from_path(css_file);
} catch (const Glib::Error& e) {
spdlog::error("{}", e.what());
}
// there's always only one screen
style_context_->add_provider_for_screen(Gdk::Screen::get_default(), css_provider_,
Gtk::StyleContext::add_provider_for_display(Gdk::Display::get_default(), css_provider_,
GTK_STYLE_PROVIDER_PRIORITY_USER);
}
@@ -204,13 +206,20 @@ void waybar::Client::bindInterfaces() {
throw std::runtime_error("Failed to acquire required resources.");
}
// add existing outputs and subscribe to updates
for (auto i = 0; i < gdk_display->get_n_monitors(); ++i) {
auto monitor = gdk_display->get_monitor(i);
handleMonitorAdded(monitor);
// auto monitors{gdk_display->get_monitors()};
for (guint i{0}; i < monitors_->get_n_items(); ++i) {
handleMonitorAdded(std::dynamic_pointer_cast<Gdk::Monitor>(monitors_->get_object(i)));
}
gdk_display->signal_monitor_added().connect(sigc::mem_fun(*this, &Client::handleMonitorAdded));
gdk_display->signal_monitor_removed().connect(
sigc::mem_fun(*this, &Client::handleMonitorRemoved));
monitors_->signal_items_changed().connect([=, this](const guint& position, const guint& removed, const guint& added){
for (auto i{removed}; i > 0; --i) {
handleMonitorRemoved(std::dynamic_pointer_cast<Gdk::Monitor>(monitors_->get_object(position + i)));
}
for (auto i{added}; i > 0; --i) {
handleMonitorAdded(std::dynamic_pointer_cast<Gdk::Monitor>(monitors_->get_object(position + i)));
}
});
}
int waybar::Client::main(int argc, char *argv[]) {
@@ -243,13 +252,8 @@ int waybar::Client::main(int argc, char *argv[]) {
if (!log_level.empty()) {
spdlog::set_level(spdlog::level::from_str(log_level));
}
gtk_app = Gtk::Application::create(argc, argv, "fr.arouillard.waybar",
Gio::APPLICATION_HANDLES_COMMAND_LINE);
// Initialize Waybars GTK resources with our custom icons
auto theme = Gtk::IconTheme::get_default();
theme->add_resource_path("/fr/arouillard/waybar/icons");
gtk_app = Gtk::Application::create("fr.arouillard.waybar",
Gio::Application::Flags::HANDLES_COMMAND_LINE);
gdk_display = Gdk::Display::get_default();
if (!gdk_display) {
throw std::runtime_error("Can't find display");
@@ -257,36 +261,28 @@ int waybar::Client::main(int argc, char *argv[]) {
if (!GDK_IS_WAYLAND_DISPLAY(gdk_display->gobj())) {
throw std::runtime_error("Bar need to run under Wayland");
}
// Initialize Waybars GTK resources with our custom icons
auto theme{Gtk::IconTheme::get_for_display(gdk_display)};
theme->add_resource_path("/fr/arouillard/waybar/icons");
wl_display = gdk_wayland_display_get_wl_display(gdk_display->gobj());
monitors_ = gdk_display->get_monitors();
config.load(config_opt);
if (!portal) {
portal = std::make_unique<waybar::Portal>();
}
m_cssFile = getStyle(style_opt);
setupCss(m_cssFile);
m_cssReloadHelper = std::make_unique<CssReloadHelper>(m_cssFile, [&]() { setupCss(m_cssFile); });
auto css_file = getStyle(style_opt);
setupCss(css_file);
portal->signal_appearance_changed().connect([&](waybar::Appearance appearance) {
auto css_file = getStyle(style_opt, appearance);
setupCss(css_file);
});
auto m_config = config.getConfig();
if (m_config.isObject() && m_config["reload_style_on_change"].asBool()) {
m_cssReloadHelper->monitorChanges();
} else if (m_config.isArray()) {
for (const auto &conf : m_config) {
if (conf["reload_style_on_change"].asBool()) {
m_cssReloadHelper->monitorChanges();
break;
}
}
}
bindInterfaces();
gtk_app->hold();
gtk_app->run();
m_cssReloadHelper.reset(); // stop watching css file
bars.clear();
return 0;
}

View File

@@ -162,7 +162,6 @@ void Config::load(const std::string &config) {
}
config_file_ = file.value();
spdlog::info("Using configuration file {}", config_file_);
config_ = Json::Value();
setupConfig(config_, config_file_, 0);
}

View File

@@ -1,114 +1,12 @@
#include "factory.hpp"
#include "bar.hpp"
#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_TASKBAR
#include "modules/wlr/taskbar.hpp"
#endif
#ifdef HAVE_WLR_WORKSPACES
#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"
#include "modules/dwl/window.hpp"
#endif
#ifdef HAVE_HYPRLAND
#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__)
#include "modules/battery.hpp"
#endif
#if defined(HAVE_CPU_LINUX) || defined(HAVE_CPU_BSD)
#include "modules/cpu.hpp"
#include "modules/cpu_frequency.hpp"
#include "modules/cpu_usage.hpp"
#include "modules/load.hpp"
#endif
#include "modules/idle_inhibitor.hpp"
#if defined(HAVE_MEMORY_LINUX) || defined(HAVE_MEMORY_BSD)
#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/network.hpp"
#endif
#ifdef HAVE_LIBUDEV
#include "modules/backlight.hpp"
#include "modules/backlight_slider.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_PIPEWIRE
#include "modules/privacy/privacy.hpp"
#endif
#ifdef HAVE_LIBPULSE
#include "modules/pulseaudio.hpp"
#include "modules/pulseaudio_slider.hpp"
#endif
#ifdef HAVE_LIBMPDCLIENT
#include "modules/mpd/mpd.hpp"
#ifdef HAVE_LIBUDEV
#include "modules/backlight_slider.hpp"
#endif
#ifdef HAVE_LIBSNDIO
#include "modules/sndio.hpp"
#endif
#if defined(__linux__)
#include "modules/bluetooth.hpp"
#include "modules/power_profiles_daemon.hpp"
#endif
#ifdef HAVE_LOGIND_INHIBITOR
#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
#ifdef HAVE_SYSTEMD_MONITOR
#include "modules/systemd_failed_units.hpp"
#endif
#include "modules/cffi.hpp"
#include "modules/custom.hpp"
#include "modules/image.hpp"
#include "modules/temperature.hpp"
#include "modules/user.hpp"
waybar::Factory::Factory(const Bar& bar, const Json::Value& config) : bar_(bar), config_(config) {}
@@ -118,9 +16,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
auto hash_pos = name.find('#');
auto ref = name.substr(0, hash_pos);
auto id = hash_pos != std::string::npos ? name.substr(hash_pos + 1) : "";
#if defined(__FreeBSD__) || defined(__linux__)
#if defined(__FreeBSD__) || (defined(__linux__) && !defined(NO_FILESYSTEM))
if (ref == "battery") {
return new waybar::modules::Battery(id, bar_, config_[name]);
return new waybar::modules::Battery(id, config_[name]);
}
#endif
#ifdef HAVE_GAMEMODE
@@ -160,16 +58,16 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
return new waybar::modules::sway::Scratchpad(id, config_[name]);
}
#endif
#ifdef HAVE_WLR_TASKBAR
#ifdef HAVE_WLR
if (ref == "wlr/taskbar") {
return new waybar::modules::wlr::Taskbar(id, bar_, config_[name]);
}
#endif
#ifdef HAVE_WLR_WORKSPACES
#ifdef USE_EXPERIMENTAL
if (ref == "wlr/workspaces") {
return new waybar::modules::wlr::WorkspaceManager(id, bar_, config_[name]);
}
#endif
#endif
#ifdef HAVE_RIVER
if (ref == "river/mode") {
return new waybar::modules::river::Mode(id, bar_, config_[name]);
@@ -188,9 +86,6 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
if (ref == "dwl/tags") {
return new waybar::modules::dwl::Tags(id, bar_, config_[name]);
}
if (ref == "dwl/window") {
return new waybar::modules::dwl::Window(id, bar_, config_[name]);
}
#endif
#ifdef HAVE_HYPRLAND
if (ref == "hyprland/window") {
@@ -283,15 +178,10 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
return new waybar::modules::Sndio(id, config_[name]);
}
#endif
#if defined(__linux__)
#ifdef HAVE_GIO_UNIX
if (ref == "bluetooth") {
return new waybar::modules::Bluetooth(id, config_[name]);
}
if (ref == "power-profiles-daemon") {
return new waybar::modules::PowerProfilesDaemon(id, config_[name]);
}
#endif
#ifdef HAVE_LOGIND_INHIBITOR
if (ref == "inhibitor") {
return new waybar::modules::Inhibitor(id, bar_, config_[name]);
}

View File

@@ -9,18 +9,19 @@
namespace waybar {
const Gtk::RevealerTransitionType getPreferredTransitionType(bool is_vertical) {
/* The transition direction of a drawer is not actually determined by the transition type,
* but rather by the order of 'box' and 'revealer_box':
* 'REVEALER_TRANSITION_TYPE_SLIDE_LEFT' and 'REVEALER_TRANSITION_TYPE_SLIDE_RIGHT'
* will result in the same thing.
* However: we still need to differentiate between vertical and horizontal transition types.
*/
const Gtk::RevealerTransitionType getPreferredTransitionType(bool is_vertical, bool left_to_right) {
if (is_vertical) {
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_UP;
if (left_to_right) {
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_DOWN;
} else {
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_UP;
}
} else {
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_LEFT;
if (left_to_right) {
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_RIGHT;
} else {
return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_LEFT;
}
}
}
@@ -63,7 +64,7 @@ Group::Group(const std::string& name, const std::string& id, const Json::Value&
? drawer_config["transition-left-to-right"].asBool()
: true);
auto transition_type = getPreferredTransitionType(vertical);
auto transition_type = getPreferredTransitionType(vertical, left_to_right);
revealer.set_transition_type(transition_type);
revealer.set_transition_duration(transition_duration);
@@ -72,12 +73,7 @@ Group::Group(const std::string& name, const std::string& id, const Json::Value&
revealer.get_style_context()->add_class("drawer");
revealer.add(revealer_box);
if (left_to_right) {
box.pack_end(revealer);
} else {
box.pack_start(revealer);
}
box.pack_start(revealer);
addHoverHandlerTo(revealer);
}

View File

@@ -108,11 +108,11 @@ int main(int argc, char* argv[]) {
delete client;
return ret;
} catch (const Glib::Error& e) {
spdlog::error("{}", static_cast<std::string>(e.what()));
return 1;
} catch (const std::exception& e) {
spdlog::error("{}", e.what());
return 1;
} catch (const Glib::Exception& e) {
spdlog::error("{}", static_cast<std::string>(e.what()));
return 1;
}
}

View File

@@ -1,14 +1,12 @@
#include "modules/battery.hpp"
#include <algorithm>
#if defined(__FreeBSD__)
#include <sys/sysctl.h>
#endif
#include <spdlog/spdlog.h>
#include <iostream>
waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const Json::Value& config)
: ALabel(config, "battery", id, "{capacity}%", 60), bar_(bar) {
waybar::modules::Battery::Battery(const std::string& id, const Json::Value& config)
: ALabel(config, "battery", id, "{capacity}%", 60) {
#if defined(__linux__)
battery_watch_fd_ = inotify_init1(IN_CLOEXEC);
if (battery_watch_fd_ == -1) {
@@ -181,8 +179,7 @@ static bool status_gt(const std::string& a, const std::string& b) {
return false;
}
std::tuple<uint8_t, float, std::string, float, uint16_t, float>
waybar::modules::Battery::getInfos() {
const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::getInfos() {
std::lock_guard<std::mutex> guard(battery_list_mutex_);
try {
@@ -235,7 +232,7 @@ waybar::modules::Battery::getInfos() {
}
// spdlog::info("{} {} {} {}", capacity,time,status,rate);
return {capacity, time / 60.0, status, rate, 0, 0.0F};
return {capacity, time / 60.0, status, rate};
#elif defined(__linux__)
uint32_t total_power = 0; // μW
@@ -253,10 +250,6 @@ waybar::modules::Battery::getInfos() {
uint32_t time_to_full_now = 0;
bool time_to_full_now_exists = false;
uint32_t largestDesignCapacity = 0;
uint16_t mainBatCycleCount = 0;
float mainBatHealthPercent = 0.0F;
std::string status = "Unknown";
for (auto const& item : batteries_) {
auto bat = item.first;
@@ -358,25 +351,6 @@ waybar::modules::Battery::getInfos() {
std::ifstream(bat / "energy_full_design") >> energy_full_design;
}
uint16_t cycleCount = 0;
if (fs::exists(bat / "cycle_count")) {
std::ifstream(bat / "cycle_count") >> cycleCount;
}
if (charge_full_design >= largestDesignCapacity) {
largestDesignCapacity = charge_full_design;
if (cycleCount > mainBatCycleCount) {
mainBatCycleCount = cycleCount;
}
if (charge_full_exists && charge_full_design_exists) {
float batHealthPercent = ((float)charge_full / charge_full_design) * 100;
if (mainBatHealthPercent == 0.0f || batHealthPercent < mainBatHealthPercent) {
mainBatHealthPercent = batHealthPercent;
}
}
}
if (!voltage_now_exists) {
if (power_now_exists && current_now_exists && current_now != 0) {
voltage_now_exists = true;
@@ -597,12 +571,11 @@ waybar::modules::Battery::getInfos() {
// still charging but not yet done
if (cap == 100 && status == "Charging") status = "Full";
return {
cap, time_remaining, status, total_power / 1e6, mainBatCycleCount, mainBatHealthPercent};
return {cap, time_remaining, status, total_power / 1e6};
#endif
} catch (const std::exception& e) {
spdlog::error("Battery: {}", e.what());
return {0, 0, "Unknown", 0, 0, 0.0f};
return {0, 0, "Unknown", 0};
}
}
@@ -658,7 +631,7 @@ auto waybar::modules::Battery::update() -> void {
return;
}
#endif
auto [capacity, time_remaining, status, power, cycles, health] = getInfos();
auto [capacity, time_remaining, status, power] = getInfos();
if (status == "Unknown") {
status = getAdapterStatus(capacity);
}
@@ -668,7 +641,6 @@ auto waybar::modules::Battery::update() -> void {
[](char ch) { return ch == ' ' ? '-' : std::tolower(ch); });
auto format = format_;
auto state = getState(capacity, true);
setBarClass(state);
auto time_remaining_formatted = formatTimeRemaining(time_remaining);
if (tooltipEnabled()) {
std::string tooltip_text_default;
@@ -688,11 +660,10 @@ auto waybar::modules::Battery::update() -> void {
} else if (config_["tooltip-format"].isString()) {
tooltip_format = config_["tooltip-format"].asString();
}
label_.set_tooltip_text(
fmt::format(fmt::runtime(tooltip_format), fmt::arg("timeTo", tooltip_text_default),
fmt::arg("power", power), fmt::arg("capacity", capacity),
fmt::arg("time", time_remaining_formatted), fmt::arg("cycles", cycles),
fmt::arg("health", fmt::format("{:.3}", health))));
label_.set_tooltip_text(fmt::format(fmt::runtime(tooltip_format),
fmt::arg("timeTo", tooltip_text_default),
fmt::arg("power", power), fmt::arg("capacity", capacity),
fmt::arg("time", time_remaining_formatted)));
}
if (!old_status_.empty()) {
label_.get_style_context()->remove_class(old_status_);
@@ -711,46 +682,10 @@ auto waybar::modules::Battery::update() -> void {
} else {
event_box_.show();
auto icons = std::vector<std::string>{status + "-" + state, status, state};
label_.set_markup(
fmt::format(fmt::runtime(format), fmt::arg("capacity", capacity), fmt::arg("power", power),
fmt::arg("icon", getIcon(capacity, icons)),
fmt::arg("time", time_remaining_formatted), fmt::arg("cycles", cycles)));
label_.set_markup(fmt::format(
fmt::runtime(format), fmt::arg("capacity", capacity), fmt::arg("power", power),
fmt::arg("icon", getIcon(capacity, icons)), fmt::arg("time", time_remaining_formatted)));
}
// Call parent update
ALabel::update();
}
void waybar::modules::Battery::setBarClass(std::string& state) {
auto classes = bar_.window.get_style_context()->list_classes();
const std::string prefix = "battery-";
auto old_class_it = std::find_if(classes.begin(), classes.end(), [&prefix](auto classname) {
return classname.rfind(prefix, 0) == 0;
});
auto new_class = prefix + state;
// If the bar doesn't have any `battery-` class
if (old_class_it == classes.end()) {
if (!state.empty()) {
bar_.window.get_style_context()->add_class(new_class);
}
return;
}
auto old_class = *old_class_it;
// If the bar has a `battery-` class,
// but `state` is empty
if (state.empty()) {
bar_.window.get_style_context()->remove_class(old_class);
return;
}
// If the bar has a `battery-` class,
// and `state` is NOT empty
if (old_class != new_class) {
bar_.window.get_style_context()->remove_class(old_class);
bar_.window.get_style_context()->add_class(new_class);
}
}

View File

@@ -53,8 +53,8 @@ waybar::modules::Cava::Cava(const std::string& id, const Json::Value& config)
if (config_["method"].isString())
prm_.input = cava::input_method_by_name(config_["method"].asString().c_str());
if (config_["source"].isString()) prm_.audio_source = config_["source"].asString().data();
if (config_["sample_rate"].isNumeric()) prm_.samplerate = config_["sample_rate"].asLargestInt();
if (config_["sample_bits"].isInt()) prm_.samplebits = config_["sample_bits"].asInt();
if (config_["sample_rate"].isNumeric()) prm_.fifoSample = config_["sample_rate"].asLargestInt();
if (config_["sample_bits"].isInt()) prm_.fifoSampleBits = config_["sample_bits"].asInt();
if (config_["stereo"].isBool()) prm_.stereo = config_["stereo"].asBool();
if (config_["reverse"].isBool()) prm_.reverse = config_["reverse"].asBool();
if (config_["bar_delimiter"].isInt()) prm_.bar_delim = config_["bar_delimiter"].asInt();

View File

@@ -2,10 +2,8 @@
#include <spdlog/spdlog.h>
#include <chrono>
#include <iomanip>
#include <regex>
#include <sstream>
#include "util/ustring_clen.hpp"
@@ -22,8 +20,7 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
tlpFmt_{(config_["tooltip-format"].isString()) ? config_["tooltip-format"].asString() : ""},
cldInTooltip_{tlpFmt_.find("{" + kCldPlaceholder + "}") != std::string::npos},
tzInTooltip_{tlpFmt_.find("{" + kTZPlaceholder + "}") != std::string::npos},
tzCurrIdx_{0},
ordInTooltip_{tlpFmt_.find("{" + kOrdPlaceholder + "}") != std::string::npos} {
tzCurrIdx_{0} {
tlpText_ = tlpFmt_;
if (config_["timezones"].isArray() && !config_["timezones"].empty()) {
@@ -31,7 +28,7 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
if (!zone_name.isString()) continue;
if (zone_name.asString().empty())
// local time should be shown
tzList_.push_back(nullptr);
tzList_.push_back(current_zone());
else
try {
tzList_.push_back(locate_zone(zone_name.asString()));
@@ -42,7 +39,7 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
} else if (config_["timezone"].isString()) {
if (config_["timezone"].asString().empty())
// local time should be shown
tzList_.push_back(nullptr);
tzList_.push_back(current_zone());
else
try {
tzList_.push_back(locate_zone(config_["timezone"].asString()));
@@ -50,7 +47,7 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
spdlog::warn("Timezone: {0}. {1}", config_["timezone"].asString(), e.what());
}
}
if (!tzList_.size()) tzList_.push_back(nullptr);
if (!tzList_.size()) tzList_.push_back(current_zone());
// Calendar properties
if (cldInTooltip_) {
@@ -87,7 +84,7 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
fmtMap_.insert({3, config_[kCldPlaceholder]["format"]["today"].asString()});
cldBaseDay_ =
year_month_day{
floor<days>(zoned_time{local_zone(), system_clock::now()}.get_local_time())}
floor<days>(zoned_time{current_zone(), system_clock::now()}.get_local_time())}
.day();
} else
fmtMap_.insert({3, "{}"});
@@ -115,7 +112,6 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
} else
cldMonCols_ = 1;
if (config_[kCldPlaceholder]["on-scroll"].isInt()) {
cldShift_ = config_[kCldPlaceholder]["on-scroll"].asInt();
event_box_.add_events(Gdk::LEAVE_NOTIFY_MASK);
event_box_.signal_leave_notify_event().connect([this](GdkEventCrossing*) {
cldCurrShift_ = months{0};
@@ -131,7 +127,7 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
}
auto waybar::modules::Clock::update() -> void {
const auto* tz = tzList_[tzCurrIdx_] != nullptr ? tzList_[tzCurrIdx_] : local_zone();
auto tz{tzList_[tzCurrIdx_]};
const zoned_time now{tz, floor<seconds>(system_clock::now())};
label_.set_markup(fmt_lib::vformat(locale_, format_, fmt_lib::make_format_args(now)));
@@ -144,16 +140,11 @@ auto waybar::modules::Clock::update() -> void {
if (tzInTooltip_) tzText_ = getTZtext(now.get_sys_time());
if (cldInTooltip_) cldText_ = get_calendar(today, shiftedDay, tz);
if (ordInTooltip_) ordText_ = get_ordinal_date(shiftedDay);
if (tzInTooltip_ || cldInTooltip_ || ordInTooltip_) {
if (tzInTooltip_ || cldInTooltip_) {
// std::vformat doesn't support named arguments.
tlpText_ = std::regex_replace(tlpFmt_, std::regex("\\{" + kTZPlaceholder + "\\}"), tzText_);
tlpText_ =
std::regex_replace(tlpText_, std::regex("\\{" + kCldPlaceholder + "\\}"), cldText_);
tlpText_ =
std::regex_replace(tlpText_, std::regex("\\{" + kOrdPlaceholder + "\\}"), ordText_);
} else {
tlpText_ = tlpFmt_;
}
tlpText_ = fmt_lib::vformat(locale_, tlpText_, fmt_lib::make_format_args(shiftedNow));
@@ -170,8 +161,7 @@ auto waybar::modules::Clock::getTZtext(sys_seconds now) -> std::string {
std::stringstream os;
for (size_t tz_idx{0}; tz_idx < tzList_.size(); ++tz_idx) {
if (static_cast<int>(tz_idx) == tzCurrIdx_) continue;
const auto* tz = tzList_[tz_idx] != nullptr ? tzList_[tz_idx] : local_zone();
auto zt{zoned_time{tz, now}};
auto zt{zoned_time{tzList_[tz_idx], now}};
os << fmt_lib::vformat(locale_, format_, fmt_lib::make_format_args(zt)) << '\n';
}
@@ -224,22 +214,22 @@ auto getCalendarLine(const year_month_day& currDate, const year_month ym, const
}
// Print first week prefixed with spaces if necessary
case 2: {
auto d{day{1}};
auto wd{weekday{ym / 1}};
os << std::string((wd - firstdow).count() * 3, ' ');
if (currDate != ym / d)
os << date::format(*locale_, "{:L%e}", d);
if (currDate != ym / 1d)
os << date::format(*locale_, "{:L%e}", 1d);
else
os << "{today}";
auto d{2d};
while (++wd != firstdow) {
++d;
if (currDate != ym / d)
os << date::format(*locale_, " {:L%e}", d);
else
os << " {today}";
++d;
}
break;
}
@@ -395,18 +385,6 @@ auto waybar::modules::Clock::get_calendar(const year_month_day& today, const yea
return os.str();
}
auto waybar::modules::Clock::local_zone() -> const time_zone* {
const char* tz_name = getenv("TZ");
if (tz_name) {
try {
return locate_zone(tz_name);
} catch (const std::runtime_error& e) {
spdlog::warn("Timezone: {0}. {1}", tz_name, e.what());
}
}
return current_zone();
}
// Actions handler
auto waybar::modules::Clock::doAction(const std::string& name) -> void {
if (actionMap_[name]) {
@@ -420,12 +398,11 @@ void waybar::modules::Clock::cldModeSwitch() {
cldMode_ = (cldMode_ == CldMode::YEAR) ? CldMode::MONTH : CldMode::YEAR;
}
void waybar::modules::Clock::cldShift_up() {
cldCurrShift_ += (months)((cldMode_ == CldMode::YEAR) ? 12 : 1) * cldShift_;
cldCurrShift_ += (months)((cldMode_ == CldMode::YEAR) ? 12 : 1);
}
void waybar::modules::Clock::cldShift_down() {
cldCurrShift_ -= (months)((cldMode_ == CldMode::YEAR) ? 12 : 1) * cldShift_;
cldCurrShift_ -= (months)((cldMode_ == CldMode::YEAR) ? 12 : 1);
}
void waybar::modules::Clock::cldShift_reset() { cldCurrShift_ = (months)0; }
void waybar::modules::Clock::tz_up() {
const auto tzSize{tzList_.size()};
if (tzSize == 1) return;
@@ -460,28 +437,3 @@ auto waybar::modules::Clock::first_day_of_week() -> weekday {
#endif
return Sunday;
}
auto waybar::modules::Clock::get_ordinal_date(const year_month_day& today) -> std::string {
auto day = static_cast<unsigned int>(today.day());
std::stringstream res;
res << day;
if (day >= 11 && day <= 13) {
res << "th";
return res.str();
}
switch (day % 10) {
case 1:
res << "st";
break;
case 2:
res << "nd";
break;
case 3:
res << "rd";
break;
default:
res << "th";
}
return res.str();
}

View File

@@ -1,27 +1,15 @@
#include <spdlog/spdlog.h>
#include <sys/sysctl.h>
#include <cmath> // NAN
#include "modules/cpu_frequency.hpp"
std::vector<float> waybar::modules::CpuFrequency::parseCpuFrequencies() {
std::vector<float> frequencies;
char buffer[256];
size_t len;
int32_t freq;
uint32_t i = 0;
while (true) {
len = 4;
snprintf(buffer, 256, "dev.cpu.%u.freq", i);
if (sysctlbyname(buffer, &freq, &len, NULL, 0) == -1 || len <= 0) break;
frequencies.push_back(freq);
++i;
}
static std::vector<float> frequencies;
if (frequencies.empty()) {
spdlog::warn("cpu/bsd: parseCpuFrequencies failed, not found in sysctl");
spdlog::warn(
"cpu/bsd: parseCpuFrequencies is not implemented, expect garbage in {*_frequency}");
frequencies.push_back(NAN);
}
return frequencies;
}

View File

@@ -170,12 +170,6 @@ auto waybar::modules::Custom::update() -> void {
if (label_.get_tooltip_markup() != str) {
label_.set_tooltip_markup(str);
}
} else if (config_["tooltip-format"].isString()) {
auto tooltip = config_["tooltip-format"].asString();
tooltip = fmt::format(fmt::runtime(tooltip), text_, fmt::arg("alt", alt_),
fmt::arg("icon", getIcon(percentage_, alt_)),
fmt::arg("percentage", percentage_));
label_.set_tooltip_markup(tooltip);
} else {
if (label_.get_tooltip_markup() != tooltip_) {
label_.set_tooltip_markup(tooltip_);
@@ -214,19 +208,13 @@ void waybar::modules::Custom::parseOutputRaw() {
if (i == 0) {
if (config_["escape"].isBool() && config_["escape"].asBool()) {
text_ = Glib::Markup::escape_text(validated_line);
tooltip_ = Glib::Markup::escape_text(validated_line);
} else {
text_ = validated_line;
tooltip_ = validated_line;
}
tooltip_ = validated_line;
class_.clear();
} else if (i == 1) {
if (config_["escape"].isBool() && config_["escape"].asBool()) {
tooltip_ = Glib::Markup::escape_text(validated_line);
} else {
tooltip_ = validated_line;
}
tooltip_ = validated_line;
} else if (i == 2) {
class_.push_back(validated_line);
} else {
@@ -252,11 +240,7 @@ void waybar::modules::Custom::parseOutputJson() {
} else {
alt_ = parsed["alt"].asString();
}
if (config_["escape"].isBool() && config_["escape"].asBool()) {
tooltip_ = Glib::Markup::escape_text(parsed["tooltip"].asString());
} else {
tooltip_ = parsed["tooltip"].asString();
}
tooltip_ = parsed["tooltip"].asString();
if (parsed["class"].isString()) {
class_.push_back(parsed["class"].asString());
} else if (parsed["class"].isArray()) {

View File

@@ -21,11 +21,11 @@ wl_array tags, layouts;
static uint num_tags = 0;
static void toggle_visibility(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
void toggle_visibility(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
// Intentionally empty
}
static void active(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t active) {
void active(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t active) {
// Intentionally empty
}
@@ -37,15 +37,15 @@ static void set_tag(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t tag
: num_tags & ~(1 << tag);
}
static void set_layout_symbol(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *layout) {
void set_layout_symbol(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *layout) {
// Intentionally empty
}
static void title(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *title) {
void title(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *title) {
// Intentionally empty
}
static void dwl_frame(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
void dwl_frame(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
// Intentionally empty
}
@@ -97,7 +97,6 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
output_status_{nullptr} {
struct wl_display *display = Client::inst()->wl_display;
struct wl_registry *registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_listener_impl, this);
wl_display_roundtrip(display);
@@ -156,9 +155,6 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
}
Tags::~Tags() {
if (output_status_) {
zdwl_ipc_output_v2_destroy(output_status_);
}
if (status_manager_) {
zdwl_ipc_manager_v2_destroy(status_manager_);
}

View File

@@ -1,114 +0,0 @@
#include "modules/dwl/window.hpp"
#include <gdkmm/pixbuf.h>
#include <glibmm/fileutils.h>
#include <glibmm/keyfile.h>
#include <glibmm/miscutils.h>
#include <gtkmm/enums.h>
#include <spdlog/spdlog.h>
#include "client.hpp"
#include "dwl-ipc-unstable-v2-client-protocol.h"
#include "util/rewrite_string.hpp"
namespace waybar::modules::dwl {
static void toggle_visibility(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
// Intentionally empty
}
static void active(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t active) {
// Intentionally empty
}
static void set_tag(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t tag, uint32_t state,
uint32_t clients, uint32_t focused) {
// Intentionally empty
}
static void set_layout_symbol(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *layout) {
static_cast<Window *>(data)->handle_layout_symbol(layout);
}
static void title(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *title) {
static_cast<Window *>(data)->handle_title(title);
}
static void dwl_frame(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
static_cast<Window *>(data)->handle_frame();
}
static void set_layout(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t layout) {
static_cast<Window *>(data)->handle_layout(layout);
}
static void appid(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *appid) {
static_cast<Window *>(data)->handle_appid(appid);
};
static const zdwl_ipc_output_v2_listener output_status_listener_impl{
.toggle_visibility = toggle_visibility,
.active = active,
.tag = set_tag,
.layout = set_layout,
.title = title,
.appid = appid,
.layout_symbol = set_layout_symbol,
.frame = dwl_frame,
};
static void handle_global(void *data, struct wl_registry *registry, uint32_t name,
const char *interface, uint32_t version) {
if (std::strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) {
static_cast<Window *>(data)->status_manager_ = static_cast<struct zdwl_ipc_manager_v2 *>(
(zdwl_ipc_manager_v2 *)wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 1));
}
}
static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
/* Ignore event */
}
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
.global_remove = handle_global_remove};
Window::Window(const std::string &id, const Bar &bar, const Json::Value &config)
: AAppIconLabel(config, "window", id, "{}", 0, true), bar_(bar) {
struct wl_display *display = Client::inst()->wl_display;
struct wl_registry *registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_listener_impl, this);
wl_display_roundtrip(display);
if (!status_manager_) {
spdlog::error("dwl_status_manager_v2 not advertised");
return;
}
struct wl_output *output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
output_status_ = zdwl_ipc_manager_v2_get_output(status_manager_, output);
zdwl_ipc_output_v2_add_listener(output_status_, &output_status_listener_impl, this);
zdwl_ipc_manager_v2_destroy(status_manager_);
}
void Window::handle_title(const char *title) { title_ = title; }
void Window::handle_appid(const char *appid) { appid_ = appid; }
void Window::handle_layout_symbol(const char *layout_symbol) { layout_symbol_ = layout_symbol; }
void Window::handle_layout(const uint32_t layout) { layout_ = layout; }
void Window::handle_frame() {
label_.set_markup(waybar::util::rewriteString(
fmt::format(fmt::runtime(format_), fmt::arg("title", title_),
fmt::arg("layout", layout_symbol_), fmt::arg("app_id", appid_)),
config_["rewrite"]));
updateAppIconName(appid_, "");
updateAppIcon();
if (tooltipEnabled()) {
label_.set_tooltip_text(title_);
}
}
} // namespace waybar::modules::dwl

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