diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index a8c110b..3a0ca11 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,3 +1,4 @@
# These are supported funding model platforms
+github: Alexays
custom: https://paypal.me/ARouillard
diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml
new file mode 100644
index 0000000..03e5d70
--- /dev/null
+++ b/.github/workflows/freebsd.yml
@@ -0,0 +1,27 @@
+name: freebsd
+
+on: [ push, pull_request ]
+
+jobs:
+ clang:
+ # Run actions in a FreeBSD vm on the macos-10.15 runner
+ # https://github.com/actions/runner/issues/385 - for FreeBSD runner support
+ # https://github.com/actions/virtual-environments/issues/4060 - for lack of VirtualBox on MacOS 11 runners
+ runs-on: macos-10.15
+ steps:
+ - uses: actions/checkout@v2
+ - name: Test in FreeBSD VM
+ uses: vmactions/freebsd-vm@v0.1.5 # aka FreeBSD 13.0
+ with:
+ usesh: true
+ prepare: |
+ export CPPFLAGS=-isystem/usr/local/include LDFLAGS=-L/usr/local/lib # sndio
+ sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
+ pkg install -y git # subprojects/date
+ pkg install -y catch evdev-proto gtk-layer-shell gtkmm30 jsoncpp \
+ libdbusmenu libevdev libfmt libmpdclient libudev-devd meson \
+ pkgconf pulseaudio scdoc sndio spdlog
+ run: |
+ meson build -Dman-pages=enabled
+ ninja -C build
+ meson test -C build --no-rebuild --print-errorlogs --suite waybar
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
new file mode 100644
index 0000000..d4efbf8
--- /dev/null
+++ b/.github/workflows/linux.yml
@@ -0,0 +1,27 @@
+name: linux
+
+on: [push, pull_request]
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ distro:
+ - alpine
+ - archlinux
+ - debian
+ - fedora
+ - opensuse
+
+ runs-on: ubuntu-latest
+ container:
+ image: alexays/waybar:${{ matrix.distro }}
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: configure
+ run: meson -Dman-pages=enabled build
+ - name: build
+ run: ninja -C build
+ - name: test
+ run: meson test -C build --no-rebuild --print-errorlogs --suite waybar
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 54c148f..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-language: cpp
-
-services:
- - docker
-
-git:
- submodules: false
-
-env:
- - distro: debian
- - distro: archlinux
- - distro: fedora
- - distro: alpine
- - distro: opensuse
-
-before_install:
- - docker pull alexays/waybar:${distro}
- - find . -type f \( -name '*.cpp' -o -name '*.h' \) -print0 | xargs -r0 clang-format -i
-
-script:
- - echo FROM alexays/waybar:${distro} > Dockerfile
- - echo ADD . /root >> Dockerfile
- - docker build -t waybar .
- - docker run waybar /bin/sh -c "cd /root && meson build -Dman-pages=enabled && ninja -C build"
-
-jobs:
- include:
- - os: freebsd
- compiler: clang
- env:
- before_install:
- - sudo sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
- - sudo pkg install -y date gtk-layer-shell gtkmm30 jsoncpp libdbusmenu
- libfmt libmpdclient libudev-devd meson pulseaudio scdoc spdlog
- script:
- - meson build -Dman-pages=enabled
- - ninja -C build
diff --git a/Dockerfiles/alpine b/Dockerfiles/alpine
index 7b71837..c0e032f 100644
--- a/Dockerfiles/alpine
+++ b/Dockerfiles/alpine
@@ -2,4 +2,4 @@
FROM alpine:latest
-RUN apk add --no-cache git meson alpine-sdk libinput-dev wayland-dev wayland-protocols mesa-dev libxkbcommon-dev eudev-dev pixman-dev gtkmm3-dev jsoncpp-dev pugixml-dev libnl3-dev pulseaudio-dev libmpdclient-dev scdoc
+RUN apk add --no-cache git meson alpine-sdk libinput-dev wayland-dev wayland-protocols mesa-dev libxkbcommon-dev eudev-dev pixman-dev gtkmm3-dev jsoncpp-dev pugixml-dev libnl3-dev pulseaudio-dev libmpdclient-dev sndio-dev scdoc libxkbcommon
diff --git a/Dockerfiles/archlinux b/Dockerfiles/archlinux
index d8ae16f..40a1b2e 100644
--- a/Dockerfiles/archlinux
+++ b/Dockerfiles/archlinux
@@ -1,6 +1,6 @@
# vim: ft=Dockerfile
-FROM archlinux/base:latest
+FROM archlinux:base-devel
RUN pacman -Syu --noconfirm && \
- pacman -S git meson base-devel libinput wayland wayland-protocols pixman libxkbcommon mesa gtkmm3 jsoncpp pugixml scdoc libpulse libdbusmenu-gtk3 libmpdclient --noconfirm
+ pacman -S git meson base-devel libinput wayland wayland-protocols pixman libxkbcommon mesa gtkmm3 jsoncpp pugixml scdoc libpulse libdbusmenu-gtk3 libmpdclient gobject-introspection --noconfirm libxkbcommon
diff --git a/Dockerfiles/debian b/Dockerfiles/debian
index 077aca8..026d8fd 100644
--- a/Dockerfiles/debian
+++ b/Dockerfiles/debian
@@ -3,5 +3,5 @@
FROM debian:sid
RUN apt-get update && \
- apt-get install -y build-essential meson ninja-build git pkg-config libinput10 libpugixml-dev libinput-dev wayland-protocols libwayland-client0 libwayland-cursor0 libwayland-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev libxkbcommon-dev libudev-dev libpixman-1-dev libgtkmm-3.0-dev libjsoncpp-dev scdoc libdbusmenu-gtk3-dev libnl-3-dev libnl-genl-3-dev libpulse-dev libmpdclient-dev gobject-introspection && \
+ apt-get install -y build-essential meson ninja-build git pkg-config libinput10 libpugixml-dev libinput-dev wayland-protocols libwayland-client0 libwayland-cursor0 libwayland-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev libxkbcommon-dev libudev-dev libpixman-1-dev libgtkmm-3.0-dev libjsoncpp-dev scdoc libdbusmenu-gtk3-dev libnl-3-dev libnl-genl-3-dev libpulse-dev libmpdclient-dev gobject-introspection libgirepository1.0-dev libxkbcommon-dev libxkbregistry-dev libxkbregistry0 && \
apt-get clean
diff --git a/Dockerfiles/fedora b/Dockerfiles/fedora
index d75083c..a61dcd3 100644
--- a/Dockerfiles/fedora
+++ b/Dockerfiles/fedora
@@ -1,7 +1,12 @@
# vim: ft=Dockerfile
-FROM fedora:32
+FROM fedora:latest
-RUN dnf install sway meson git libinput-devel wayland-devel wayland-protocols-devel pugixml-devel egl-wayland-devel mesa-libEGL-devel mesa-libGLES-devel mesa-libgbm-devel libxkbcommon-devel libudev-devel pixman-devel gtkmm30-devel jsoncpp-devel scdoc -y && \
- dnf group install "C Development Tools and Libraries" -y && \
+RUN dnf install -y @c-development git-core meson scdoc 'pkgconfig(date)' \
+ 'pkgconfig(dbusmenu-gtk3-0.4)' 'pkgconfig(fmt)' 'pkgconfig(gdk-pixbuf-2.0)' \
+ 'pkgconfig(gio-unix-2.0)' 'pkgconfig(gtk-layer-shell-0)' 'pkgconfig(gtkmm-3.0)' \
+ 'pkgconfig(jsoncpp)' 'pkgconfig(libinput)' 'pkgconfig(libmpdclient)' \
+ 'pkgconfig(libnl-3.0)' 'pkgconfig(libnl-genl-3.0)' 'pkgconfig(libpulse)' \
+ 'pkgconfig(libudev)' 'pkgconfig(pugixml)' 'pkgconfig(sigc++-2.0)' 'pkgconfig(spdlog)' \
+ 'pkgconfig(wayland-client)' 'pkgconfig(wayland-cursor)' 'pkgconfig(wayland-protocols)' 'pkgconfig(xkbregistry)' && \
dnf clean all -y
diff --git a/Dockerfiles/opensuse b/Dockerfiles/opensuse
index 5b664fb..49dea27 100644
--- a/Dockerfiles/opensuse
+++ b/Dockerfiles/opensuse
@@ -3,5 +3,7 @@
FROM opensuse/tumbleweed:latest
RUN zypper -n up && \
+ zypper addrepo https://download.opensuse.org/repositories/X11:Wayland/openSUSE_Tumbleweed/X11:Wayland.repo | echo 'a' && \
+ zypper -n refresh && \
zypper -n install -t pattern devel_C_C++ && \
- zypper -n install git meson clang libinput10 libinput-devel pugixml-devel libwayland-client0 libwayland-cursor0 wayland-protocols-devel wayland-devel Mesa-libEGL-devel Mesa-libGLESv2-devel libgbm-devel libxkbcommon-devel libudev-devel libpixman-1-0-devel gtkmm3-devel jsoncpp-devel scdoc
+ zypper -n install git meson clang libinput10 libinput-devel pugixml-devel libwayland-client0 libwayland-cursor0 wayland-protocols-devel wayland-devel Mesa-libEGL-devel Mesa-libGLESv2-devel libgbm-devel libxkbcommon-devel libudev-devel libpixman-1-0-devel gtkmm3-devel jsoncpp-devel libxkbregistry-devel scdoc
diff --git a/Makefile b/Makefile
index d7182c1..94f8ee6 100644
--- a/Makefile
+++ b/Makefile
@@ -16,5 +16,8 @@ install: build
run: build
./build/waybar
+debug-run: build-debug
+ ./build/waybar --log-level debug
+
clean:
rm -rf build
diff --git a/README.md b/README.md
index f7bc4c8..98b99a2 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
-# Waybar [![Travis](https://travis-ci.org/Alexays/Waybar.svg?branch=master)](https://travis-ci.org/Alexays/Waybar) [![Licence](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Paypal Donate](https://img.shields.io/badge/Donate-Paypal-2244dd.svg)](https://paypal.me/ARouillard)
![Waybar](https://raw.githubusercontent.com/alexays/waybar/master/preview-2.png)
+# Waybar [![Licence](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Paypal Donate](https://img.shields.io/badge/Donate-Paypal-2244dd.svg)](https://paypal.me/ARouillard)
![Waybar](https://raw.githubusercontent.com/alexays/waybar/master/preview-2.png)
> Highly customizable Wayland bar for Sway and Wlroots based compositors.
> Available in Arch [community](https://www.archlinux.org/packages/community/x86_64/waybar/) or
[AUR](https://aur.archlinux.org/packages/waybar-git/), [openSUSE](https://build.opensuse.org/package/show/X11:Wayland/waybar), and [Alpine Linux](https://pkgs.alpinelinux.org/packages?name=waybar)
> *Waybar [examples](https://github.com/Alexays/Waybar/wiki/Examples)*
-**Current features**
+#### Current features
- Sway (Workspaces, Binding mode, Focused window name)
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
- Local time
@@ -22,11 +22,21 @@
- Multiple output configuration
- And much more customizations
-**Configuration and Styling**
+#### Configuration and Styling
[See the wiki for more details](https://github.com/Alexays/Waybar/wiki).
-**How to build**
+### Installation
+
+Waybar is available from a number of Linux distributions:
+
+[![Packaging status](https://repology.org/badge/vertical-allrepos/waybar.svg)](https://repology.org/project/waybar/versions)
+
+An Ubuntu PPA with more recent versions is available
+[here](https://launchpad.net/~nschloe/+archive/ubuntu/waybar).
+
+
+#### Building from source
```bash
$ git clone https://github.com/Alexays/Waybar
@@ -57,6 +67,8 @@ libnl [Network module]
libappindicator-gtk3 [Tray module]
libdbusmenu-gtk3 [Tray module]
libmpdclient [MPD module]
+libsndio [sndio module]
+libevdev [KeyboardState module]
```
**Build dependencies**
@@ -75,6 +87,7 @@ sudo apt install \
clang-tidy \
gobject-introspection \
libdbusmenu-gtk3-dev \
+ libevdev-dev \
libfmt-dev \
libgirepository1.0-dev \
libgtk-3-dev \
diff --git a/include/ALabel.hpp b/include/ALabel.hpp
index d4ad94d..d8a5b50 100644
--- a/include/ALabel.hpp
+++ b/include/ALabel.hpp
@@ -10,16 +10,15 @@ namespace waybar {
class ALabel : public AModule {
public:
ALabel(const Json::Value &, const std::string &, const std::string &, const std::string &format,
- uint16_t interval = 0, bool ellipsize = false);
+ uint16_t interval = 0, bool ellipsize = false, bool enable_click = false, bool enable_scroll = false);
virtual ~ALabel() = default;
virtual auto update() -> void;
virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0);
- virtual std::string getIcon(uint16_t, std::vector &alts, uint16_t max = 0);
+ virtual std::string getIcon(uint16_t, const std::vector &alts, uint16_t max = 0);
protected:
Gtk::Label label_;
std::string format_;
- std::string click_param;
const std::chrono::seconds interval_;
bool alt_ = false;
std::string default_format_;
diff --git a/include/AModule.hpp b/include/AModule.hpp
index f7cc484..c9f1ae2 100644
--- a/include/AModule.hpp
+++ b/include/AModule.hpp
@@ -4,14 +4,15 @@
#include
#include
#include
+
#include "IModule.hpp"
namespace waybar {
class AModule : public IModule {
public:
- AModule(const Json::Value &, const std::string &, const std::string &,
- bool enable_click = false, bool enable_scroll = false);
+ AModule(const Json::Value &, const std::string &, const std::string &, bool enable_click = false,
+ bool enable_scroll = false);
virtual ~AModule();
virtual auto update() -> void;
virtual operator Gtk::Widget &();
@@ -24,6 +25,7 @@ class AModule : public IModule {
SCROLL_DIR getScrollDir(GdkEventScroll *e);
bool tooltipEnabled();
+ const std::string name_;
const Json::Value &config_;
Gtk::EventBox event_box_;
diff --git a/include/bar.hpp b/include/bar.hpp
index fb0cd59..6f3dfcf 100644
--- a/include/bar.hpp
+++ b/include/bar.hpp
@@ -7,9 +7,8 @@
#include
#include
#include
+
#include "AModule.hpp"
-#include "idle-inhibit-unstable-v1-client-protocol.h"
-#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
namespace waybar {
@@ -18,65 +17,68 @@ class Factory;
struct waybar_output {
Glib::RefPtr monitor;
std::string name;
+ std::string identifier;
std::unique_ptr xdg_output = {
nullptr, &zxdg_output_v1_destroy};
};
+enum class bar_layer : uint8_t {
+ BOTTOM,
+ TOP,
+ OVERLAY,
+};
+
+struct bar_margins {
+ int top = 0;
+ int right = 0;
+ int bottom = 0;
+ int left = 0;
+};
+
+class BarSurface {
+ protected:
+ BarSurface() = default;
+
+ public:
+ virtual void setExclusiveZone(bool enable) = 0;
+ virtual void setLayer(bar_layer layer) = 0;
+ virtual void setMargins(const struct bar_margins &margins) = 0;
+ virtual void setPassThrough(bool enable) = 0;
+ virtual void setPosition(const std::string_view &position) = 0;
+ virtual void setSize(uint32_t width, uint32_t height) = 0;
+ virtual void commit(){};
+
+ virtual ~BarSurface() = default;
+};
+
class Bar {
public:
Bar(struct waybar_output *w_output, const Json::Value &);
Bar(const Bar &) = delete;
~Bar() = default;
- auto toggle() -> void;
+ void setVisible(bool visible);
+ void toggle();
void handleSignal(int);
struct waybar_output *output;
Json::Value config;
- Gtk::Window window;
struct wl_surface * surface;
+ bool exclusive = true;
bool visible = true;
bool vertical = false;
+ Gtk::Window window;
private:
- static constexpr const char *MIN_HEIGHT_MSG =
- "Requested height: {} exceeds the minimum height: {} required by the modules";
- static constexpr const char *MIN_WIDTH_MSG =
- "Requested width: {} exceeds the minimum width: {} required by the modules";
- static constexpr const char *BAR_SIZE_MSG =
- "Bar configured (width: {}, height: {}) for output: {}";
- static constexpr const char *SIZE_DEFINED =
- "{} size is defined in the config file so it will stay like that";
- static void layerSurfaceHandleConfigure(void *, struct zwlr_layer_surface_v1 *, uint32_t,
- uint32_t, uint32_t);
- static void layerSurfaceHandleClosed(void *, struct zwlr_layer_surface_v1 *);
-
-#ifdef HAVE_GTK_LAYER_SHELL
- void initGtkLayerShell();
-#endif
- void onConfigure(GdkEventConfigure *ev);
- void onRealize();
- void onMap(GdkEventAny *ev);
- void setExclusiveZone(uint32_t width, uint32_t height);
- void setSurfaceSize(uint32_t width, uint32_t height);
+ void onMap(GdkEventAny *);
auto setupWidgets() -> void;
void getModules(const Factory &, const std::string &);
void setupAltFormatKeyForModule(const std::string &module_name);
void setupAltFormatKeyForModuleList(const char *module_list_name);
- struct margins {
- int top = 0;
- int right = 0;
- int bottom = 0;
- int left = 0;
- } margins_;
- struct zwlr_layer_surface_v1 *layer_surface_;
- // use gtk-layer-shell instead of handling layer surfaces directly
- bool use_gls_ = false;
- uint32_t width_ = 0;
- uint32_t height_ = 1;
- uint8_t anchor_;
+ std::unique_ptr surface_impl_;
+ bar_layer layer_;
Gtk::Box left_;
Gtk::Box center_;
Gtk::Box right_;
diff --git a/include/client.hpp b/include/client.hpp
index 39b6ae3..bd80d0b 100644
--- a/include/client.hpp
+++ b/include/client.hpp
@@ -3,10 +3,14 @@
#include
#include
#include
-#include
#include
-#include
+
#include "bar.hpp"
+#include "config.hpp"
+
+struct zwlr_layer_shell_v1;
+struct zwp_idle_inhibitor_v1;
+struct zwp_idle_inhibit_manager_v1;
namespace waybar {
@@ -14,6 +18,7 @@ class Client {
public:
static Client *inst();
int main(int argc, char *argv[]);
+ void reset();
Glib::RefPtr gtk_app;
Glib::RefPtr gdk_display;
@@ -23,28 +28,27 @@ class Client {
struct zxdg_output_manager_v1 * xdg_output_manager = nullptr;
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager = nullptr;
std::vector> bars;
+ Config config;
private:
Client() = default;
- std::tuple getConfigs(const std::string &config,
- const std::string &style) const;
- void bindInterfaces();
- const std::string getValidPath(const std::vector &paths) const;
- void handleOutput(struct waybar_output &output);
- bool isValidOutput(const Json::Value &config, struct waybar_output &output);
- auto setupConfig(const std::string &config_file) -> void;
- auto setupCss(const std::string &css_file) -> void;
- struct waybar_output &getOutput(void *);
+ const std::string getStyle(const std::string &style);
+ void bindInterfaces();
+ void handleOutput(struct waybar_output &output);
+ auto setupCss(const std::string &css_file) -> void;
+ struct waybar_output & getOutput(void *);
std::vector getOutputConfigs(struct waybar_output &output);
static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name,
const char *interface, uint32_t version);
static void handleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name);
+ static void handleOutputDone(void *, struct zxdg_output_v1 *);
static void handleOutputName(void *, struct zxdg_output_v1 *, const char *);
+ static void handleOutputDescription(void *, struct zxdg_output_v1 *, const char *);
void handleMonitorAdded(Glib::RefPtr monitor);
void handleMonitorRemoved(Glib::RefPtr monitor);
+ void handleDeferredMonitorRemoval(Glib::RefPtr monitor);
- Json::Value config_;
Glib::RefPtr style_context_;
Glib::RefPtr css_provider_;
std::list outputs_;
diff --git a/include/config.hpp b/include/config.hpp
new file mode 100644
index 0000000..82d5599
--- /dev/null
+++ b/include/config.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include
+
+#include
+#include
+
+#ifndef SYSCONFDIR
+#define SYSCONFDIR "/etc"
+#endif
+
+namespace waybar {
+
+class Config {
+ public:
+ static const std::vector CONFIG_DIRS;
+
+ /* Try to find any of provided names in the supported set of config directories */
+ static std::optional findConfigPath(
+ const std::vector &names, const std::vector &dirs = CONFIG_DIRS);
+
+ Config() = default;
+
+ void load(const std::string &config);
+
+ Json::Value &getConfig() { return config_; }
+
+ std::vector getOutputConfigs(const std::string &name, const std::string &identifier);
+
+ private:
+ void setupConfig(Json::Value &dst, const std::string &config_file, int depth);
+ void resolveConfigIncludes(Json::Value &config, int depth);
+ void mergeConfig(Json::Value &a_config_, Json::Value &b_config_);
+
+ std::string config_file_;
+
+ Json::Value config_;
+};
+} // namespace waybar
diff --git a/include/factory.hpp b/include/factory.hpp
index c698aa3..43dd2cf 100644
--- a/include/factory.hpp
+++ b/include/factory.hpp
@@ -1,11 +1,23 @@
#pragma once
#include
+#ifdef HAVE_LIBDATE
#include "modules/clock.hpp"
+#else
+#include "modules/simpleclock.hpp"
+#endif
#ifdef HAVE_SWAY
#include "modules/sway/mode.hpp"
#include "modules/sway/window.hpp"
#include "modules/sway/workspaces.hpp"
+#include "modules/sway/language.hpp"
+#endif
+#ifdef HAVE_WLR
+#include "modules/wlr/taskbar.hpp"
+#include "modules/wlr/workspace_manager.hpp"
+#endif
+#ifdef HAVE_RIVER
+#include "modules/river/tags.hpp"
#endif
#if defined(__linux__) && !defined(NO_FILESYSTEM)
#include "modules/battery.hpp"
@@ -27,17 +39,25 @@
#ifdef HAVE_LIBUDEV
#include "modules/backlight.hpp"
#endif
+#ifdef HAVE_LIBEVDEV
+#include "modules/keyboard_state.hpp"
+#endif
#ifdef HAVE_LIBPULSE
#include "modules/pulseaudio.hpp"
#endif
#ifdef HAVE_LIBMPDCLIENT
-#include "modules/mpd.hpp"
+#include "modules/mpd/mpd.hpp"
+#endif
+#ifdef HAVE_LIBSNDIO
+#include "modules/sndio.hpp"
#endif
#include "bar.hpp"
#include "modules/custom.hpp"
#include "modules/temperature.hpp"
#if defined(__linux__)
-#include "modules/bluetooth.hpp"
+# ifdef WANT_RFKILL
+# include "modules/bluetooth.hpp"
+# endif
#endif
namespace waybar {
diff --git a/include/modules/battery.hpp b/include/modules/battery.hpp
index d4d20d1..41bc0ad 100644
--- a/include/modules/battery.hpp
+++ b/include/modules/battery.hpp
@@ -31,19 +31,22 @@ class Battery : public ALabel {
private:
static inline const fs::path data_dir_ = "/sys/class/power_supply/";
- void getBatteries();
- void worker();
- const std::string getAdapterStatus(uint8_t capacity) const;
- const std::tuple getInfos() const;
- const std::string formatTimeRemaining(float hoursRemaining);
+ void refreshBatteries();
+ void worker();
+ const std::string getAdapterStatus(uint8_t capacity) const;
+ const std::tuple getInfos();
+ const std::string formatTimeRemaining(float hoursRemaining);
- std::vector batteries_;
+ int global_watch;
+ std::map batteries_;
fs::path adapter_;
- int fd_;
- std::vector wds_;
+ int battery_watch_fd_;
+ int global_watch_fd_;
+ std::mutex battery_list_mutex_;
std::string old_status_;
util::SleeperThread thread_;
+ util::SleeperThread thread_battery_update_;
util::SleeperThread thread_timer_;
};
diff --git a/include/modules/bluetooth.hpp b/include/modules/bluetooth.hpp
index 04c213d..87845c9 100644
--- a/include/modules/bluetooth.hpp
+++ b/include/modules/bluetooth.hpp
@@ -1,10 +1,6 @@
#pragma once
-#include
#include "ALabel.hpp"
-
-#include
-#include "util/sleeper_thread.hpp"
#include "util/rfkill.hpp"
namespace waybar::modules {
@@ -16,10 +12,6 @@ class Bluetooth : public ALabel {
auto update() -> void;
private:
- std::string status_;
- util::SleeperThread thread_;
- util::SleeperThread intervall_thread_;
-
util::Rfkill rfkill_;
};
diff --git a/include/modules/clock.hpp b/include/modules/clock.hpp
index e3873a6..17752e4 100644
--- a/include/modules/clock.hpp
+++ b/include/modules/clock.hpp
@@ -28,12 +28,16 @@ class Clock : public ALabel {
std::locale locale_;
const date::time_zone* time_zone_;
bool fixed_time_zone_;
- date::year_month_day cached_calendar_ymd_;
+ int time_zone_idx_;
+ date::year_month_day cached_calendar_ymd_ = date::January/1/0;
std::string cached_calendar_text_;
+ bool handleScroll(GdkEventScroll* e);
+
auto calendar_text(const waybar_time& wtime) -> std::string;
auto weekdays_header(const date::weekday& first_dow, std::ostream& os) -> void;
auto first_day_of_week() -> date::weekday;
+ bool setTimeZone(Json::Value zone_name);
};
} // namespace waybar::modules
diff --git a/include/modules/cpu.hpp b/include/modules/cpu.hpp
index 7a70336..7e32a43 100644
--- a/include/modules/cpu.hpp
+++ b/include/modules/cpu.hpp
@@ -1,7 +1,6 @@
#pragma once
#include
-#include
#include
#include
#include
@@ -20,9 +19,11 @@ class Cpu : public ALabel {
auto update() -> void;
private:
- uint16_t getCpuLoad();
- std::tuple getCpuUsage();
- std::vector> parseCpuinfo();
+ double getCpuLoad();
+ std::tuple, std::string> getCpuUsage();
+ std::tuple getCpuFrequency();
+ std::vector> parseCpuinfo();
+ std::vector parseCpuFrequencies();
std::vector> prev_times_;
diff --git a/include/modules/custom.hpp b/include/modules/custom.hpp
index b8dad9d..7c77145 100644
--- a/include/modules/custom.hpp
+++ b/include/modules/custom.hpp
@@ -22,6 +22,7 @@ class Custom : public ALabel {
void continuousWorker();
void parseOutputRaw();
void parseOutputJson();
+ void handleEvent();
bool handleScroll(GdkEventScroll* e);
bool handleToggle(GdkEventButton* const& e);
diff --git a/include/modules/idle_inhibitor.hpp b/include/modules/idle_inhibitor.hpp
index 5ce324d..4b6c097 100644
--- a/include/modules/idle_inhibitor.hpp
+++ b/include/modules/idle_inhibitor.hpp
@@ -12,12 +12,13 @@ class IdleInhibitor : public ALabel {
IdleInhibitor(const std::string&, const waybar::Bar&, const Json::Value&);
~IdleInhibitor();
auto update() -> void;
+ static std::list modules;
+ static bool status;
private:
bool handleToggle(GdkEventButton* const& e);
const Bar& bar_;
- std::string status_;
struct zwp_idle_inhibitor_v1* idle_inhibitor_;
int pid_;
};
diff --git a/include/modules/keyboard_state.hpp b/include/modules/keyboard_state.hpp
new file mode 100644
index 0000000..1793bfe
--- /dev/null
+++ b/include/modules/keyboard_state.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include
+#if FMT_VERSION < 60000
+#include
+#else
+#include
+#endif
+#include "AModule.hpp"
+#include "bar.hpp"
+#include "util/sleeper_thread.hpp"
+#include
+
+extern "C" {
+#include
+}
+
+namespace waybar::modules {
+
+class KeyboardState : public AModule {
+ public:
+ KeyboardState(const std::string&, const waybar::Bar&, const Json::Value&);
+ ~KeyboardState();
+ auto update() -> void;
+
+ private:
+ static auto openDevice(const std::string&) -> std::pair;
+
+ Gtk::Box box_;
+ Gtk::Label numlock_label_;
+ Gtk::Label capslock_label_;
+ Gtk::Label scrolllock_label_;
+
+ std::string numlock_format_;
+ std::string capslock_format_;
+ std::string scrolllock_format_;
+ const std::chrono::seconds interval_;
+ std::string icon_locked_;
+ std::string icon_unlocked_;
+
+ int fd_;
+ libevdev* dev_;
+
+ util::SleeperThread thread_;
+};
+
+} // namespace waybar::modules
diff --git a/include/modules/mpd.hpp b/include/modules/mpd.hpp
deleted file mode 100644
index d08b28b..0000000
--- a/include/modules/mpd.hpp
+++ /dev/null
@@ -1,74 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-#include "ALabel.hpp"
-
-namespace waybar::modules {
-
-class MPD : public ALabel {
- public:
- MPD(const std::string&, const Json::Value&);
- auto update() -> void;
-
- private:
- std::thread periodic_updater();
- std::string getTag(mpd_tag_type type, unsigned idx = 0);
- void setLabel();
- std::string getStateIcon();
- std::string getOptionIcon(std::string optionName, bool activated);
-
- std::thread event_listener();
-
- // Assumes `connection_lock_` is locked
- void tryConnect();
- // If checking errors on the main connection, make sure to lock it using
- // `connection_lock_` before calling checkErrors
- void checkErrors(mpd_connection* conn);
-
- // Assumes `connection_lock_` is locked
- void fetchState();
- void waitForEvent();
-
- bool handlePlayPause(GdkEventButton* const&);
-
- bool stopped();
- bool playing();
- bool paused();
-
- const std::string module_name_;
-
- using unique_connection = std::unique_ptr;
- using unique_status = std::unique_ptr;
- using unique_song = std::unique_ptr;
-
- // Not using unique_ptr since we don't manage the pointer
- // (It's either nullptr, or from the config)
- const char* server_;
- const unsigned port_;
-
- unsigned timeout_;
-
- // We need a mutex here because we can trigger updates from multiple thread:
- // the event based updates, the periodic updates needed for the elapsed time,
- // and the click play/pause feature
- std::mutex connection_lock_;
- unique_connection connection_;
- // The alternate connection will be used to wait for events: since it will
- // be blocking (idle) we can't send commands via this connection
- //
- // No lock since only used in the event listener thread
- unique_connection alternate_connection_;
-
- // Protect them using the `connection_lock_`
- unique_status status_;
- mpd_state state_;
- unique_song song_;
-
- // To make sure the previous periodic_updater stops before creating a new one
- std::mutex periodic_lock_;
-};
-
-} // namespace waybar::modules
diff --git a/include/modules/mpd/mpd.hpp b/include/modules/mpd/mpd.hpp
new file mode 100644
index 0000000..0fc1ce9
--- /dev/null
+++ b/include/modules/mpd/mpd.hpp
@@ -0,0 +1,67 @@
+#pragma once
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include "ALabel.hpp"
+#include "modules/mpd/state.hpp"
+
+namespace waybar::modules {
+
+class MPD : public ALabel {
+ friend class detail::Context;
+
+ // State machine
+ detail::Context context_{this};
+
+ const std::string module_name_;
+
+ // Not using unique_ptr since we don't manage the pointer
+ // (It's either nullptr, or from the config)
+ const char* server_;
+ const unsigned port_;
+ const std::string password_;
+
+ unsigned timeout_;
+
+ detail::unique_connection connection_;
+
+ detail::unique_status status_;
+ mpd_state state_;
+ detail::unique_song song_;
+
+ public:
+ MPD(const std::string&, const Json::Value&);
+ virtual ~MPD() noexcept = default;
+ auto update() -> void;
+
+ private:
+ std::string getTag(mpd_tag_type type, unsigned idx = 0) const;
+ void setLabel();
+ std::string getStateIcon() const;
+ std::string getOptionIcon(std::string optionName, bool activated) const;
+
+ // GUI-side methods
+ bool handlePlayPause(GdkEventButton* const&);
+ void emit() { dp.emit(); }
+
+ // MPD-side, Non-GUI methods.
+ void tryConnect();
+ void checkErrors(mpd_connection* conn);
+ void fetchState();
+ void queryMPD();
+
+ inline bool stopped() const { return connection_ && state_ == MPD_STATE_STOP; }
+ inline bool playing() const { return connection_ && state_ == MPD_STATE_PLAY; }
+ inline bool paused() const { return connection_ && state_ == MPD_STATE_PAUSE; }
+};
+
+#if !defined(MPD_NOINLINE)
+#include "modules/mpd/state.inl.hpp"
+#endif
+
+} // namespace waybar::modules
diff --git a/include/modules/mpd/state.hpp b/include/modules/mpd/state.hpp
new file mode 100644
index 0000000..3b18159
--- /dev/null
+++ b/include/modules/mpd/state.hpp
@@ -0,0 +1,217 @@
+#pragma once
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include "ALabel.hpp"
+
+namespace waybar::modules {
+class MPD;
+} // namespace waybar::modules
+
+namespace waybar::modules::detail {
+
+using unique_connection = std::unique_ptr;
+using unique_status = std::unique_ptr;
+using unique_song = std::unique_ptr;
+
+class Context;
+
+/// This state machine loosely follows a non-hierarchical, statechart
+/// pattern, and includes ENTRY and EXIT actions.
+///
+/// The State class is the base class for all other states. The
+/// entry and exit methods are automatically called when entering
+/// into a new state and exiting from the current state. This
+/// includes initially entering (Disconnected class) and exiting
+/// Waybar.
+///
+/// The following nested "top-level" states are represented:
+/// 1. Idle - await notification of MPD activity.
+/// 2. All Non-Idle states:
+/// 1. Playing - An active song is producing audio output.
+/// 2. Paused - The current song is paused.
+/// 3. Stopped - No song is actively playing.
+/// 3. Disconnected - periodically attempt MPD (re-)connection.
+///
+/// NOTE: Since this statechart is non-hierarchical, the above
+/// states are flattened into a set.
+
+class State {
+ public:
+ virtual ~State() noexcept = default;
+
+ virtual void entry() noexcept { spdlog::debug("mpd: ignore entry action"); }
+ virtual void exit() noexcept { spdlog::debug("mpd: ignore exit action"); }
+
+ virtual void play() { spdlog::debug("mpd: ignore play state transition"); }
+ virtual void stop() { spdlog::debug("mpd: ignore stop state transition"); }
+ virtual void pause() { spdlog::debug("mpd: ignore pause state transition"); }
+
+ /// Request state update the GUI.
+ virtual void update() noexcept { spdlog::debug("mpd: ignoring update method request"); }
+};
+
+class Idle : public State {
+ Context* const ctx_;
+ sigc::connection idle_connection_;
+
+ public:
+ Idle(Context* const ctx) : ctx_{ctx} {}
+ virtual ~Idle() noexcept { this->exit(); };
+
+ void entry() noexcept override;
+ void exit() noexcept override;
+
+ void play() override;
+ void stop() override;
+ void pause() override;
+ void update() noexcept override;
+
+ private:
+ Idle(const Idle&) = delete;
+ Idle& operator=(const Idle&) = delete;
+
+ bool on_io(Glib::IOCondition const&);
+};
+
+class Playing : public State {
+ Context* const ctx_;
+ sigc::connection timer_connection_;
+
+ public:
+ Playing(Context* const ctx) : ctx_{ctx} {}
+ virtual ~Playing() noexcept { this->exit(); }
+
+ void entry() noexcept override;
+ void exit() noexcept override;
+
+ void pause() override;
+ void stop() override;
+ void update() noexcept override;
+
+ private:
+ Playing(Playing const&) = delete;
+ Playing& operator=(Playing const&) = delete;
+
+ bool on_timer();
+};
+
+class Paused : public State {
+ Context* const ctx_;
+ sigc::connection timer_connection_;
+
+ public:
+ Paused(Context* const ctx) : ctx_{ctx} {}
+ virtual ~Paused() noexcept { this->exit(); }
+
+ void entry() noexcept override;
+ void exit() noexcept override;
+
+ void play() override;
+ void stop() override;
+ void update() noexcept override;
+
+ private:
+ Paused(Paused const&) = delete;
+ Paused& operator=(Paused const&) = delete;
+
+ bool on_timer();
+};
+
+class Stopped : public State {
+ Context* const ctx_;
+ sigc::connection timer_connection_;
+
+ public:
+ Stopped(Context* const ctx) : ctx_{ctx} {}
+ virtual ~Stopped() noexcept { this->exit(); }
+
+ void entry() noexcept override;
+ void exit() noexcept override;
+
+ void play() override;
+ void pause() override;
+ void update() noexcept override;
+
+ private:
+ Stopped(Stopped const&) = delete;
+ Stopped& operator=(Stopped const&) = delete;
+
+ bool on_timer();
+};
+
+class Disconnected : public State {
+ Context* const ctx_;
+ sigc::connection timer_connection_;
+
+ public:
+ Disconnected(Context* const ctx) : ctx_{ctx} {}
+ virtual ~Disconnected() noexcept { this->exit(); }
+
+ void entry() noexcept override;
+ void exit() noexcept override;
+
+ void update() noexcept override;
+
+ private:
+ Disconnected(Disconnected const&) = delete;
+ Disconnected& operator=(Disconnected const&) = delete;
+
+ void arm_timer(int interval) noexcept;
+ void disarm_timer() noexcept;
+
+ bool on_timer();
+};
+
+class Context {
+ std::unique_ptr state_;
+ waybar::modules::MPD* mpd_module_;
+
+ friend class State;
+ friend class Playing;
+ friend class Paused;
+ friend class Stopped;
+ friend class Disconnected;
+ friend class Idle;
+
+ protected:
+ void setState(std::unique_ptr&& new_state) noexcept {
+ if (state_.get() != nullptr) {
+ state_->exit();
+ }
+ state_ = std::move(new_state);
+ state_->entry();
+ }
+
+ bool is_connected() const;
+ bool is_playing() const;
+ bool is_paused() const;
+ bool is_stopped() const;
+ constexpr std::size_t interval() const;
+ void tryConnect() const;
+ void checkErrors(mpd_connection*) const;
+ void do_update();
+ void queryMPD() const;
+ void fetchState() const;
+ constexpr mpd_state state() const;
+ void emit() const;
+ [[nodiscard]] unique_connection& connection();
+
+ public:
+ explicit Context(waybar::modules::MPD* const mpd_module)
+ : state_{std::make_unique(this)}, mpd_module_{mpd_module} {
+ state_->entry();
+ }
+
+ void play() { state_->play(); }
+ void stop() { state_->stop(); }
+ void pause() { state_->pause(); }
+ void update() noexcept { state_->update(); }
+};
+
+} // namespace waybar::modules::detail
diff --git a/include/modules/mpd/state.inl.hpp b/include/modules/mpd/state.inl.hpp
new file mode 100644
index 0000000..0d83b0b
--- /dev/null
+++ b/include/modules/mpd/state.inl.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+namespace detail {
+
+inline bool Context::is_connected() const { return mpd_module_->connection_ != nullptr; }
+inline bool Context::is_playing() const { return mpd_module_->playing(); }
+inline bool Context::is_paused() const { return mpd_module_->paused(); }
+inline bool Context::is_stopped() const { return mpd_module_->stopped(); }
+
+constexpr inline std::size_t Context::interval() const { return mpd_module_->interval_.count(); }
+inline void Context::tryConnect() const { mpd_module_->tryConnect(); }
+inline unique_connection& Context::connection() { return mpd_module_->connection_; }
+constexpr inline mpd_state Context::state() const { return mpd_module_->state_; }
+
+inline void Context::do_update() {
+ mpd_module_->setLabel();
+}
+
+inline void Context::checkErrors(mpd_connection* conn) const { mpd_module_->checkErrors(conn); }
+inline void Context::queryMPD() const { mpd_module_->queryMPD(); }
+inline void Context::fetchState() const { mpd_module_->fetchState(); }
+inline void Context::emit() const { mpd_module_->emit(); }
+
+} // namespace detail
diff --git a/include/modules/network.hpp b/include/modules/network.hpp
index edb5aa6..c91b598 100644
--- a/include/modules/network.hpp
+++ b/include/modules/network.hpp
@@ -2,16 +2,16 @@
#include
#include
-#include
#include
-#include
#include
#include
#include
#include
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
+#ifdef WANT_RFKILL
#include "util/rfkill.hpp"
+#endif
namespace waybar::modules {
@@ -26,26 +26,24 @@ class Network : public ALabel {
static const uint8_t EPOLL_MAX = 200;
static int handleEvents(struct nl_msg*, void*);
+ static int handleEventsDone(struct nl_msg*, void*);
static int handleScan(struct nl_msg*, void*);
+ void askForStateDump(void);
+
void worker();
void createInfoSocket();
void createEventSocket();
- int getExternalInterface(int skip_idx = -1) const;
- void getInterfaceAddress();
- int netlinkRequest(void*, uint32_t, uint32_t groups = 0) const;
- int netlinkResponse(void*, uint32_t, uint32_t groups = 0) const;
void parseEssid(struct nlattr**);
void parseSignal(struct nlattr**);
void parseFreq(struct nlattr**);
bool associatedOrJoined(struct nlattr**);
- bool checkInterface(struct ifinfomsg* rtif, std::string name);
- int getPreferredIface(int skip_idx = -1, bool wait = true) const;
+ bool checkInterface(std::string name);
auto getInfo() -> void;
- void checkNewInterface(struct ifinfomsg* rtif);
const std::string getNetworkState() const;
void clearIface();
bool wildcardMatch(const std::string& pattern, const std::string& text) const;
+ std::optional> readBandwidthUsage();
int ifid_;
sa_family_t family_;
@@ -57,24 +55,32 @@ class Network : public ALabel {
int nl80211_id_;
std::mutex mutex_;
+ bool want_route_dump_;
+ bool want_link_dump_;
+ bool want_addr_dump_;
+ bool dump_in_progress_;
+
unsigned long long bandwidth_down_total_;
unsigned long long bandwidth_up_total_;
std::string state_;
std::string essid_;
+ bool carrier_;
std::string ifname_;
std::string ipaddr_;
+ std::string gwaddr_;
std::string netmask_;
int cidr_;
int32_t signal_strength_dbm_;
uint8_t signal_strength_;
uint32_t frequency_;
+ uint32_t route_priority;
util::SleeperThread thread_;
util::SleeperThread thread_timer_;
- util::SleeperThread thread_rfkill_;
-
+#ifdef WANT_RFKILL
util::Rfkill rfkill_;
+#endif
};
} // namespace waybar::modules
diff --git a/include/modules/pulseaudio.hpp b/include/modules/pulseaudio.hpp
index 5f17620..99511b3 100644
--- a/include/modules/pulseaudio.hpp
+++ b/include/modules/pulseaudio.hpp
@@ -24,7 +24,7 @@ class Pulseaudio : public ALabel {
static void volumeModifyCb(pa_context*, int, void*);
bool handleScroll(GdkEventScroll* e);
- const std::string getPortIcon() const;
+ const std::vector getPulseIcon() const;
pa_threaded_mainloop* mainloop_;
pa_mainloop_api* mainloop_api_;
@@ -38,7 +38,8 @@ class Pulseaudio : public ALabel {
std::string form_factor_;
std::string desc_;
std::string monitor_;
- std::string default_sink_name_;
+ std::string current_sink_name_;
+ bool current_sink_running_;
// SOURCE
uint32_t source_idx_{0};
uint16_t source_volume_;
diff --git a/include/modules/river/tags.hpp b/include/modules/river/tags.hpp
new file mode 100644
index 0000000..c49ec60
--- /dev/null
+++ b/include/modules/river/tags.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include
+#include
+
+#include "AModule.hpp"
+#include "bar.hpp"
+#include "river-status-unstable-v1-client-protocol.h"
+#include "river-control-unstable-v1-client-protocol.h"
+#include "xdg-output-unstable-v1-client-protocol.h"
+
+namespace waybar::modules::river {
+
+class Tags : public waybar::AModule {
+ public:
+ Tags(const std::string &, const waybar::Bar &, const Json::Value &);
+ ~Tags();
+
+ // Handlers for wayland events
+ void handle_focused_tags(uint32_t tags);
+ void handle_view_tags(struct wl_array *tags);
+ void handle_urgent_tags(uint32_t tags);
+
+ void handle_primary_clicked(uint32_t tag);
+ bool handle_button_press(GdkEventButton *event_button, uint32_t tag);
+
+ struct zriver_status_manager_v1 *status_manager_;
+ struct zriver_control_v1 *control_;
+ struct wl_seat *seat_;
+
+ private:
+ const waybar::Bar & bar_;
+ Gtk::Box box_;
+ std::vector buttons_;
+ struct zriver_output_status_v1 *output_status_;
+};
+
+} /* namespace waybar::modules::river */
diff --git a/include/modules/simpleclock.hpp b/include/modules/simpleclock.hpp
new file mode 100644
index 0000000..aa9a0a2
--- /dev/null
+++ b/include/modules/simpleclock.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include
+#if FMT_VERSION < 60000
+#include
+#else
+#include
+#endif
+#include "ALabel.hpp"
+#include "util/sleeper_thread.hpp"
+
+namespace waybar::modules {
+
+class Clock : public ALabel {
+ public:
+ Clock(const std::string&, const Json::Value&);
+ ~Clock() = default;
+ auto update() -> void;
+
+ private:
+ util::SleeperThread thread_;
+};
+
+} // namespace waybar::modules
diff --git a/include/modules/sndio.hpp b/include/modules/sndio.hpp
new file mode 100644
index 0000000..32ed706
--- /dev/null
+++ b/include/modules/sndio.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include
+#include
+#include "ALabel.hpp"
+#include "util/sleeper_thread.hpp"
+
+namespace waybar::modules {
+
+class Sndio : public ALabel {
+ public:
+ Sndio(const std::string&, const Json::Value&);
+ ~Sndio();
+ auto update() -> void;
+ auto set_desc(struct sioctl_desc *, unsigned int) -> void;
+ auto put_val(unsigned int, unsigned int) -> void;
+ bool handleScroll(GdkEventScroll *);
+ bool handleToggle(GdkEventButton* const&);
+
+ private:
+ auto connect_to_sndio() -> void;
+ util::SleeperThread thread_;
+ struct sioctl_hdl *hdl_;
+ std::vector pfds_;
+ unsigned int addr_;
+ unsigned int volume_, old_volume_, maxval_;
+ bool muted_;
+};
+
+} // namespace waybar::modules
diff --git a/include/modules/sni/host.hpp b/include/modules/sni/host.hpp
index f97900f..8d32103 100644
--- a/include/modules/sni/host.hpp
+++ b/include/modules/sni/host.hpp
@@ -5,13 +5,15 @@
#include
#include
#include
+#include "bar.hpp"
#include "modules/sni/item.hpp"
namespace waybar::modules::SNI {
class Host {
public:
- Host(const std::size_t id, const Json::Value&, const std::function&)>&,
+ Host(const std::size_t id, const Json::Value&, const Bar&,
+ const std::function&)>&,
const std::function&)>&);
~Host();
@@ -36,6 +38,7 @@ class Host {
GCancellable* cancellable_ = nullptr;
SnWatcher* watcher_ = nullptr;
const Json::Value& config_;
+ const Bar& bar_;
const std::function&)> on_add_;
const std::function&)> on_remove_;
};
diff --git a/include/modules/sni/item.hpp b/include/modules/sni/item.hpp
index 3cbd0b7..430c351 100644
--- a/include/modules/sni/item.hpp
+++ b/include/modules/sni/item.hpp
@@ -11,11 +11,21 @@
#include
#include
+#include
+#include
+
+#include "bar.hpp"
+
namespace waybar::modules::SNI {
+struct ToolTip {
+ Glib::ustring icon_name;
+ Glib::ustring text;
+};
+
class Item : public sigc::trackable {
public:
- Item(const std::string&, const std::string&, const Json::Value&);
+ Item(const std::string&, const std::string&, const Json::Value&, const Bar&);
~Item() = default;
std::string bus_name;
@@ -27,10 +37,8 @@ class Item : public sigc::trackable {
Gtk::EventBox event_box;
std::string category;
std::string id;
- std::string status;
std::string title;
- int32_t window_id;
std::string icon_name;
Glib::RefPtr icon_pixmap;
Glib::RefPtr icon_theme;
@@ -39,6 +47,7 @@ class Item : public sigc::trackable {
std::string attention_movie_name;
std::string icon_theme_path;
std::string menu;
+ ToolTip tooltip;
DbusmenuGtkMenu* dbus_menu = nullptr;
Gtk::Menu* gtk_menu = nullptr;
/**
@@ -49,8 +58,10 @@ class Item : public sigc::trackable {
bool item_is_menu = true;
private:
+ void onConfigure(GdkEventConfigure* ev);
void proxyReady(Glib::RefPtr& result);
void setProperty(const Glib::ustring& name, Glib::VariantBase& value);
+ void setStatus(const Glib::ustring& value);
void getUpdatedProperties();
void processUpdatedProperties(Glib::RefPtr& result);
void onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
@@ -58,14 +69,24 @@ class Item : public sigc::trackable {
void updateImage();
Glib::RefPtr extractPixBuf(GVariant* variant);
+ Glib::RefPtr getIconPixbuf();
Glib::RefPtr getIconByName(const std::string& name, int size);
+ double getScaledIconSize();
static void onMenuDestroyed(Item* self, GObject* old_menu_pointer);
void makeMenu();
bool handleClick(GdkEventButton* const& /*ev*/);
+ bool handleScroll(GdkEventScroll* const&);
+
+ // smooth scrolling threshold
+ gdouble scroll_threshold_ = 0;
+ gdouble distance_scrolled_x_ = 0;
+ gdouble distance_scrolled_y_ = 0;
+ // visibility of items with Status == Passive
+ bool show_passive_ = false;
Glib::RefPtr proxy_;
Glib::RefPtr cancellable_;
- bool update_pending_;
+ std::set update_pending_;
};
} // namespace waybar::modules::SNI
diff --git a/include/modules/sway/ipc/ipc.hpp b/include/modules/sway/ipc/ipc.hpp
index 2c5a7a6..5f23d17 100644
--- a/include/modules/sway/ipc/ipc.hpp
+++ b/include/modules/sway/ipc/ipc.hpp
@@ -29,4 +29,8 @@ enum ipc_command_type {
IPC_EVENT_BINDING = ((1 << 31) | 5),
IPC_EVENT_SHUTDOWN = ((1 << 31) | 6),
IPC_EVENT_TICK = ((1 << 31) | 7),
+
+ // sway-specific event types
+ IPC_EVENT_BAR_STATE_UPDATE = ((1<<31) | 20),
+ IPC_EVENT_INPUT = ((1<<31) | 21),
};
diff --git a/include/modules/sway/language.hpp b/include/modules/sway/language.hpp
new file mode 100644
index 0000000..1faf52b
--- /dev/null
+++ b/include/modules/sway/language.hpp
@@ -0,0 +1,69 @@
+#pragma once
+
+#include
+#include
+
+#include