mirror of
https://github.com/rad4day/Waybar.git
synced 2023-12-21 10:22:59 +01:00
Compare commits
205 Commits
Author | SHA1 | Date | |
---|---|---|---|
aa5f55bbe3 | |||
7ab9a560ae | |||
a5299af3c2 | |||
4d1aeb7eb8 | |||
38a846ae51 | |||
03bbc9df64 | |||
1e4fe0bee8 | |||
5e2067d51f | |||
7ea0a2348b | |||
fd306e184a | |||
f4f2989e85 | |||
8d4c7176f8 | |||
7abcbe80e5 | |||
165c5a861d | |||
d84c0f13e6 | |||
01ffe2c290 | |||
b900c01381 | |||
e2b676b800 | |||
7f995507fe | |||
b39a8ede6c | |||
315ea991bc | |||
bd0f6128d3 | |||
5a014305ec | |||
3411236697 | |||
e615612bf4 | |||
448b413eca | |||
7b7ee41e13 | |||
9bc821bdac | |||
bfcb936d87 | |||
3d023a0421 | |||
e235f48245 | |||
3043d42a89 | |||
733fb8c62a | |||
954bed3f5e | |||
13df878bc3 | |||
4592dd4a6c | |||
794610a1ca | |||
7bbf7c99a3 | |||
eec0a8255f | |||
638b4e6573 | |||
caee2e611f | |||
96746142d2 | |||
1af7191740 | |||
89be55b00b | |||
23369aa14c | |||
a16e54573e | |||
7231c47244 | |||
6184e43c84 | |||
3f123d9c4e | |||
6851e26450 | |||
fc6f5741b1 | |||
264e2c3983 | |||
45988b3dbb | |||
4e3f91d237 | |||
e5d05baba3 | |||
7763d50691 | |||
5a0e42cc76 | |||
1dcd36b06c | |||
93f9b3d213 | |||
54b1df69a9 | |||
73cd156a7a | |||
e3700b924e | |||
d87cf8a8f2 | |||
e8b022c096 | |||
503fe9a7ea | |||
b812596080 | |||
13fdbc13c3 | |||
1071b9f7c5 | |||
6ad1f6b853 | |||
a1129c4c87 | |||
2e12ea6a81 | |||
f2fcadbf62 | |||
168ba2ca5b | |||
46f07d24dd | |||
ed3e2ffdc3 | |||
d5b76bd8b5 | |||
1d03034fbb | |||
f4cc088d2f | |||
b086e2f995 | |||
4a457648f9 | |||
3a95f8f599 | |||
a7ed1ed570 | |||
e0f0931e2d | |||
0140606226 | |||
1d2a381b5f | |||
d1d73b5003 | |||
9dc09d2702 | |||
2ca4dcac49 | |||
2d87bcb1ab | |||
d4a07483b2 | |||
84dc82e1c1 | |||
e06316c80b | |||
7b071567ea | |||
2633ff3fb9 | |||
0764e9ad6e | |||
c4282cfacc | |||
05effad18b | |||
5f19a54deb | |||
7fac2afb85 | |||
4196e0d5d1 | |||
14a2a7027f | |||
2b2ac311d5 | |||
d7a030daf3 | |||
7345918f84 | |||
105f1cefe1 | |||
175d82858b | |||
c8d785071f | |||
8c6063d181 | |||
799125fb73 | |||
fcf93a6c45 | |||
6946288053 | |||
2a563f54e7 | |||
9f337db2d2 | |||
136b47ce0d | |||
6eb187a23e | |||
9b9e42fc5f | |||
d47073ef13 | |||
5396ffb71f | |||
5e9faeb2d0 | |||
4ee81c8dea | |||
a37ef74fb1 | |||
07034d561c | |||
37d87be3c1 | |||
8aee7492d4 | |||
5c1c07a035 | |||
caa24f0647 | |||
f4c6dfcddc | |||
2b3fc3acff | |||
25536f70a4 | |||
74ca1a42c6 | |||
8b6bc215cc | |||
3c1ba0a240 | |||
6c7acf18b5 | |||
ead1b2f0dc | |||
115c6e36e6 | |||
210f4454f0 | |||
77d8376fef | |||
0e580236ce | |||
1aa7587cac | |||
b6655e475b | |||
903fc2b6a2 | |||
50fc63b749 | |||
383d999fec | |||
56ebb09e5f | |||
35d6da3965 | |||
be1d2a02ca | |||
5e7ba0c9e3 | |||
18717d4b12 | |||
4dc1989744 | |||
54085dbde0 | |||
4635e8c5f8 | |||
adc67b6f75 | |||
ebe4424795 | |||
e3f56b8110 | |||
8f3fbebede | |||
a595b61e0f | |||
91339f6ad4 | |||
3c18c43b9a | |||
ac20428fdf | |||
ad5ea7ad2b | |||
851508df5e | |||
fc818dd794 | |||
e066e3080e | |||
1a93a6cfa5 | |||
074b559da5 | |||
7a61a00fb3 | |||
d4da04a750 | |||
f3819ee954 | |||
2697d432a4 | |||
061cb76fc4 | |||
6c188455a4 | |||
12caae8fd2 | |||
26ea6fae32 | |||
26419e45b7 | |||
6be741afc9 | |||
c80cc873af | |||
2b42872b6c | |||
895bc878f8 | |||
a0ee9e7fc1 | |||
941cf47693 | |||
32d42749f9 | |||
96caa9f094 | |||
f4f1267a71 | |||
bcadf64031 | |||
8974bbf7b4 | |||
1c08d26af0 | |||
c4cc7ae396 | |||
65dd245362 | |||
667d0a45f4 | |||
53fc750fc3 | |||
27df7a9aa7 | |||
d575646c2d | |||
3a6e5be59d | |||
81f0bcb3a3 | |||
9ae99c2621 | |||
5abdecc402 | |||
2301788a81 | |||
d22d6a4522 | |||
ece86c96d7 | |||
bb7b376fa6 | |||
e10c9dd011 | |||
b0eab5d793 | |||
17bb5643ae | |||
8d9e322507 | |||
94e53c3777 |
@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
BasedOnStyle: Google
|
BasedOnStyle: Google
|
||||||
AlignConsecutiveDeclarations: true
|
AlignConsecutiveDeclarations: false
|
||||||
BinPackArguments: false
|
|
||||||
ColumnLimit: 100
|
ColumnLimit: 100
|
||||||
...
|
...
|
||||||
|
4
.github/workflows/freebsd.yml
vendored
4
.github/workflows/freebsd.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Test in FreeBSD VM
|
- name: Test in FreeBSD VM
|
||||||
uses: vmactions/freebsd-vm@v0.1.5 # aka FreeBSD 13.0
|
uses: vmactions/freebsd-vm@v0.1.6 # aka FreeBSD 13.0
|
||||||
with:
|
with:
|
||||||
mem: 2048
|
mem: 2048
|
||||||
usesh: true
|
usesh: true
|
||||||
@ -21,7 +21,7 @@ jobs:
|
|||||||
pkg install -y git # subprojects/date
|
pkg install -y git # subprojects/date
|
||||||
pkg install -y catch evdev-proto gtk-layer-shell gtkmm30 jsoncpp \
|
pkg install -y catch evdev-proto gtk-layer-shell gtkmm30 jsoncpp \
|
||||||
libdbusmenu libevdev libfmt libmpdclient libudev-devd meson \
|
libdbusmenu libevdev libfmt libmpdclient libudev-devd meson \
|
||||||
pkgconf pulseaudio scdoc sndio spdlog
|
pkgconf pulseaudio scdoc sndio spdlog wayland-protocols
|
||||||
run: |
|
run: |
|
||||||
meson build -Dman-pages=enabled
|
meson build -Dman-pages=enabled
|
||||||
ninja -C build
|
ninja -C build
|
||||||
|
14
.github/workflows/lint.yml
vendored
Normal file
14
.github/workflows/lint.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
name: Linter
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: DoozyX/clang-format-lint-action@v0.13
|
||||||
|
with:
|
||||||
|
source: '.'
|
||||||
|
extensions: 'h,cpp,c'
|
||||||
|
clangFormatVersion: 12
|
11
README.md
11
README.md
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
> Highly customizable Wayland bar for Sway and Wlroots based compositors.<br>
|
> Highly customizable Wayland bar for Sway and Wlroots based compositors.<br>
|
||||||
> Available in Arch [community](https://www.archlinux.org/packages/community/x86_64/waybar/) or
|
> Available in Arch [community](https://www.archlinux.org/packages/community/x86_64/waybar/) or
|
||||||
[AUR](https://aur.archlinux.org/packages/waybar-git/), [Gentoo](https://packages.gentoo.org/packages/gui-apps/waybar), [openSUSE](https://build.opensuse.org/package/show/X11:Wayland/waybar), and [Alpine Linux](https://pkgs.alpinelinux.org/packages?name=waybar)<br>
|
[AUR](https://aur.archlinux.org/packages/waybar-git/), [Gentoo](https://packages.gentoo.org/packages/gui-apps/waybar), [openSUSE](https://build.opensuse.org/package/show/X11:Wayland/waybar), and [Alpine Linux](https://pkgs.alpinelinux.org/packages?name=waybar).<br>
|
||||||
> *Waybar [examples](https://github.com/Alexays/Waybar/wiki/Examples)*
|
> *Waybar [examples](https://github.com/Alexays/Waybar/wiki/Examples)*
|
||||||
|
|
||||||
#### Current features
|
#### Current features
|
||||||
@ -20,7 +20,7 @@
|
|||||||
- MPD
|
- MPD
|
||||||
- Custom scripts
|
- Custom scripts
|
||||||
- Multiple output configuration
|
- Multiple output configuration
|
||||||
- And much more customizations
|
- And many more customizations
|
||||||
|
|
||||||
#### Configuration and Styling
|
#### Configuration and Styling
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ scdoc
|
|||||||
wayland-protocols
|
wayland-protocols
|
||||||
```
|
```
|
||||||
|
|
||||||
On Ubuntu you can install all the relevant dependencies using this command (tested with 19.10 and 20.04):
|
On Ubuntu, you can install all the relevant dependencies using this command (tested with 19.10 and 20.04):
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo apt install \
|
sudo apt install \
|
||||||
@ -107,8 +107,9 @@ sudo apt install \
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Contributions welcome! - have fun :)<br>
|
Contributions welcome!<br>
|
||||||
The style guidelines is [Google's](https://google.github.io/styleguide/cppguide.html)
|
Have fun :)<br>
|
||||||
|
The style guidelines are [Google's](https://google.github.io/styleguide/cppguide.html)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
25
include/AIconLabel.hpp
Normal file
25
include/AIconLabel.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtkmm/box.h>
|
||||||
|
#include <gtkmm/image.h>
|
||||||
|
|
||||||
|
#include "ALabel.hpp"
|
||||||
|
|
||||||
|
namespace waybar {
|
||||||
|
|
||||||
|
class AIconLabel : public ALabel {
|
||||||
|
public:
|
||||||
|
AIconLabel(const Json::Value &config, const std::string &name, const std::string &id,
|
||||||
|
const std::string &format, uint16_t interval = 0, bool ellipsize = false,
|
||||||
|
bool enable_click = false, bool enable_scroll = false);
|
||||||
|
virtual ~AIconLabel() = default;
|
||||||
|
virtual auto update() -> void;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Gtk::Image image_;
|
||||||
|
Gtk::Box box_;
|
||||||
|
|
||||||
|
bool iconEnabled() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar
|
@ -3,6 +3,7 @@
|
|||||||
#include <glibmm/markup.h>
|
#include <glibmm/markup.h>
|
||||||
#include <gtkmm/label.h>
|
#include <gtkmm/label.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
|
|
||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
@ -10,20 +11,21 @@ namespace waybar {
|
|||||||
class ALabel : public AModule {
|
class ALabel : public AModule {
|
||||||
public:
|
public:
|
||||||
ALabel(const Json::Value &, const std::string &, const std::string &, const std::string &format,
|
ALabel(const Json::Value &, const std::string &, const std::string &, const std::string &format,
|
||||||
uint16_t interval = 0, bool ellipsize = false, bool enable_click = false, bool enable_scroll = false);
|
uint16_t interval = 0, bool ellipsize = false, bool enable_click = false,
|
||||||
|
bool enable_scroll = false);
|
||||||
virtual ~ALabel() = default;
|
virtual ~ALabel() = default;
|
||||||
virtual auto update() -> void;
|
virtual auto update() -> void;
|
||||||
virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0);
|
virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0);
|
||||||
virtual std::string getIcon(uint16_t, const std::vector<std::string> &alts, uint16_t max = 0);
|
virtual std::string getIcon(uint16_t, const std::vector<std::string> &alts, uint16_t max = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Gtk::Label label_;
|
Gtk::Label label_;
|
||||||
std::string format_;
|
std::string format_;
|
||||||
const std::chrono::seconds interval_;
|
const std::chrono::seconds interval_;
|
||||||
bool alt_ = false;
|
bool alt_ = false;
|
||||||
std::string default_format_;
|
std::string default_format_;
|
||||||
|
|
||||||
virtual bool handleToggle(GdkEventButton *const &e);
|
virtual bool handleToggle(GdkEventButton *const &e);
|
||||||
virtual std::string getState(uint8_t value, bool lesser = false);
|
virtual std::string getState(uint8_t value, bool lesser = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ class AModule : public IModule {
|
|||||||
bool enable_scroll = false);
|
bool enable_scroll = false);
|
||||||
virtual ~AModule();
|
virtual ~AModule();
|
||||||
virtual auto update() -> void;
|
virtual auto update() -> void;
|
||||||
virtual operator Gtk::Widget &();
|
virtual operator Gtk::Widget &();
|
||||||
|
|
||||||
Glib::Dispatcher dp;
|
Glib::Dispatcher dp;
|
||||||
|
|
||||||
@ -23,19 +23,35 @@ class AModule : public IModule {
|
|||||||
enum SCROLL_DIR { NONE, UP, DOWN, LEFT, RIGHT };
|
enum SCROLL_DIR { NONE, UP, DOWN, LEFT, RIGHT };
|
||||||
|
|
||||||
SCROLL_DIR getScrollDir(GdkEventScroll *e);
|
SCROLL_DIR getScrollDir(GdkEventScroll *e);
|
||||||
bool tooltipEnabled();
|
bool tooltipEnabled();
|
||||||
|
|
||||||
const std::string name_;
|
const std::string name_;
|
||||||
const Json::Value &config_;
|
const Json::Value &config_;
|
||||||
Gtk::EventBox event_box_;
|
Gtk::EventBox event_box_;
|
||||||
|
|
||||||
virtual bool handleToggle(GdkEventButton *const &ev);
|
virtual bool handleToggle(GdkEventButton *const &ev);
|
||||||
virtual bool handleScroll(GdkEventScroll *);
|
virtual bool handleScroll(GdkEventScroll *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<int> pid_;
|
std::vector<int> pid_;
|
||||||
gdouble distance_scrolled_y_;
|
gdouble distance_scrolled_y_;
|
||||||
gdouble distance_scrolled_x_;
|
gdouble distance_scrolled_x_;
|
||||||
|
static const inline std::map<std::pair<uint, GdkEventType>, std::string> eventMap_{
|
||||||
|
{std::make_pair(1, GdkEventType::GDK_BUTTON_PRESS), "on-click"},
|
||||||
|
{std::make_pair(1, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click"},
|
||||||
|
{std::make_pair(1, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click"},
|
||||||
|
{std::make_pair(2, GdkEventType::GDK_BUTTON_PRESS), "on-click-middle"},
|
||||||
|
{std::make_pair(2, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-middle"},
|
||||||
|
{std::make_pair(2, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-middle"},
|
||||||
|
{std::make_pair(3, GdkEventType::GDK_BUTTON_PRESS), "on-click-right"},
|
||||||
|
{std::make_pair(3, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-right"},
|
||||||
|
{std::make_pair(3, GdkEventType::GDK_3BUTTON_PRESS), "on-triple-click-right"},
|
||||||
|
{std::make_pair(8, GdkEventType::GDK_BUTTON_PRESS), "on-click-backward"},
|
||||||
|
{std::make_pair(8, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-backward"},
|
||||||
|
{std::make_pair(8, GdkEventType::GDK_2BUTTON_PRESS), "on-triple-click-backward"},
|
||||||
|
{std::make_pair(9, GdkEventType::GDK_BUTTON_PRESS), "on-click-forward"},
|
||||||
|
{std::make_pair(9, GdkEventType::GDK_2BUTTON_PRESS), "on-double-click-forward"},
|
||||||
|
{std::make_pair(9, GdkEventType::GDK_2BUTTON_PRESS), "on-triple-click-forward"}};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar
|
} // namespace waybar
|
||||||
|
@ -7,8 +7,8 @@ namespace waybar {
|
|||||||
class IModule {
|
class IModule {
|
||||||
public:
|
public:
|
||||||
virtual ~IModule() = default;
|
virtual ~IModule() = default;
|
||||||
virtual auto update() -> void = 0;
|
virtual auto update() -> void = 0;
|
||||||
virtual operator Gtk::Widget &() = 0;
|
virtual operator Gtk::Widget&() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar
|
} // namespace waybar
|
||||||
|
@ -19,8 +19,8 @@ namespace waybar {
|
|||||||
class Factory;
|
class Factory;
|
||||||
struct waybar_output {
|
struct waybar_output {
|
||||||
Glib::RefPtr<Gdk::Monitor> monitor;
|
Glib::RefPtr<Gdk::Monitor> monitor;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string identifier;
|
std::string identifier;
|
||||||
|
|
||||||
std::unique_ptr<struct zxdg_output_v1, decltype(&zxdg_output_v1_destroy)> xdg_output = {
|
std::unique_ptr<struct zxdg_output_v1, decltype(&zxdg_output_v1_destroy)> xdg_output = {
|
||||||
nullptr, &zxdg_output_v1_destroy};
|
nullptr, &zxdg_output_v1_destroy};
|
||||||
@ -41,9 +41,9 @@ struct bar_margins {
|
|||||||
|
|
||||||
struct bar_mode {
|
struct bar_mode {
|
||||||
bar_layer layer;
|
bar_layer layer;
|
||||||
bool exclusive;
|
bool exclusive;
|
||||||
bool passthrough;
|
bool passthrough;
|
||||||
bool visible;
|
bool visible;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_SWAY
|
#ifdef HAVE_SWAY
|
||||||
@ -71,7 +71,7 @@ class BarSurface {
|
|||||||
class Bar {
|
class Bar {
|
||||||
public:
|
public:
|
||||||
using bar_mode_map = std::map<std::string_view, struct bar_mode>;
|
using bar_mode_map = std::map<std::string_view, struct bar_mode>;
|
||||||
static const bar_mode_map PRESET_MODES;
|
static const bar_mode_map PRESET_MODES;
|
||||||
static const std::string_view MODE_DEFAULT;
|
static const std::string_view MODE_DEFAULT;
|
||||||
static const std::string_view MODE_INVISIBLE;
|
static const std::string_view MODE_INVISIBLE;
|
||||||
|
|
||||||
@ -85,11 +85,11 @@ class Bar {
|
|||||||
void handleSignal(int);
|
void handleSignal(int);
|
||||||
|
|
||||||
struct waybar_output *output;
|
struct waybar_output *output;
|
||||||
Json::Value config;
|
Json::Value config;
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
bool visible = true;
|
bool visible = true;
|
||||||
bool vertical = false;
|
bool vertical = false;
|
||||||
Gtk::Window window;
|
Gtk::Window window;
|
||||||
|
|
||||||
#ifdef HAVE_SWAY
|
#ifdef HAVE_SWAY
|
||||||
std::string bar_id;
|
std::string bar_id;
|
||||||
@ -98,20 +98,20 @@ class Bar {
|
|||||||
private:
|
private:
|
||||||
void onMap(GdkEventAny *);
|
void onMap(GdkEventAny *);
|
||||||
auto setupWidgets() -> void;
|
auto setupWidgets() -> void;
|
||||||
void getModules(const Factory &, const std::string &, Gtk::Box*);
|
void getModules(const Factory &, const std::string &, Gtk::Box *);
|
||||||
void setupAltFormatKeyForModule(const std::string &module_name);
|
void setupAltFormatKeyForModule(const std::string &module_name);
|
||||||
void setupAltFormatKeyForModuleList(const char *module_list_name);
|
void setupAltFormatKeyForModuleList(const char *module_list_name);
|
||||||
void setMode(const bar_mode &);
|
void setMode(const bar_mode &);
|
||||||
|
|
||||||
/* Copy initial set of modes to allow customization */
|
/* Copy initial set of modes to allow customization */
|
||||||
bar_mode_map configured_modes = PRESET_MODES;
|
bar_mode_map configured_modes = PRESET_MODES;
|
||||||
std::string last_mode_{MODE_DEFAULT};
|
std::string last_mode_{MODE_DEFAULT};
|
||||||
|
|
||||||
std::unique_ptr<BarSurface> surface_impl_;
|
std::unique_ptr<BarSurface> surface_impl_;
|
||||||
Gtk::Box left_;
|
Gtk::Box left_;
|
||||||
Gtk::Box center_;
|
Gtk::Box center_;
|
||||||
Gtk::Box right_;
|
Gtk::Box right_;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
std::vector<std::shared_ptr<waybar::AModule>> modules_left_;
|
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_center_;
|
||||||
std::vector<std::shared_ptr<waybar::AModule>> modules_right_;
|
std::vector<std::shared_ptr<waybar::AModule>> modules_right_;
|
||||||
|
@ -17,27 +17,27 @@ namespace waybar {
|
|||||||
class Client {
|
class Client {
|
||||||
public:
|
public:
|
||||||
static Client *inst();
|
static Client *inst();
|
||||||
int main(int argc, char *argv[]);
|
int main(int argc, char *argv[]);
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
Glib::RefPtr<Gtk::Application> gtk_app;
|
Glib::RefPtr<Gtk::Application> gtk_app;
|
||||||
Glib::RefPtr<Gdk::Display> gdk_display;
|
Glib::RefPtr<Gdk::Display> gdk_display;
|
||||||
struct wl_display * wl_display = nullptr;
|
struct wl_display *wl_display = nullptr;
|
||||||
struct wl_registry * registry = nullptr;
|
struct wl_registry *registry = nullptr;
|
||||||
struct zwlr_layer_shell_v1 * layer_shell = nullptr;
|
struct zwlr_layer_shell_v1 *layer_shell = nullptr;
|
||||||
struct zxdg_output_manager_v1 * xdg_output_manager = nullptr;
|
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
|
||||||
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager = nullptr;
|
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager = nullptr;
|
||||||
std::vector<std::unique_ptr<Bar>> bars;
|
std::vector<std::unique_ptr<Bar>> bars;
|
||||||
Config config;
|
Config config;
|
||||||
std::string bar_id;
|
std::string bar_id;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Client() = default;
|
Client() = default;
|
||||||
const std::string getStyle(const std::string &style);
|
const std::string getStyle(const std::string &style);
|
||||||
void bindInterfaces();
|
void bindInterfaces();
|
||||||
void handleOutput(struct waybar_output &output);
|
void handleOutput(struct waybar_output &output);
|
||||||
auto setupCss(const std::string &css_file) -> void;
|
auto setupCss(const std::string &css_file) -> void;
|
||||||
struct waybar_output & getOutput(void *);
|
struct waybar_output &getOutput(void *);
|
||||||
std::vector<Json::Value> getOutputConfigs(struct waybar_output &output);
|
std::vector<Json::Value> getOutputConfigs(struct waybar_output &output);
|
||||||
|
|
||||||
static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name,
|
static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
@ -46,12 +46,12 @@ class Client {
|
|||||||
static void handleOutputDone(void *, struct zxdg_output_v1 *);
|
static void handleOutputDone(void *, struct zxdg_output_v1 *);
|
||||||
static void handleOutputName(void *, struct zxdg_output_v1 *, const char *);
|
static void handleOutputName(void *, struct zxdg_output_v1 *, const char *);
|
||||||
static void handleOutputDescription(void *, struct zxdg_output_v1 *, const char *);
|
static void handleOutputDescription(void *, struct zxdg_output_v1 *, const char *);
|
||||||
void handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor);
|
void handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor);
|
||||||
void handleMonitorRemoved(Glib::RefPtr<Gdk::Monitor> monitor);
|
void handleMonitorRemoved(Glib::RefPtr<Gdk::Monitor> monitor);
|
||||||
void handleDeferredMonitorRemoval(Glib::RefPtr<Gdk::Monitor> monitor);
|
void handleDeferredMonitorRemoval(Glib::RefPtr<Gdk::Monitor> monitor);
|
||||||
|
|
||||||
Glib::RefPtr<Gtk::StyleContext> style_context_;
|
Glib::RefPtr<Gtk::StyleContext> style_context_;
|
||||||
Glib::RefPtr<Gtk::CssProvider> css_provider_;
|
Glib::RefPtr<Gtk::CssProvider> css_provider_;
|
||||||
std::list<struct waybar_output> outputs_;
|
std::list<struct waybar_output> outputs_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
#include "modules/simpleclock.hpp"
|
#include "modules/simpleclock.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SWAY
|
#ifdef HAVE_SWAY
|
||||||
|
#include "modules/sway/language.hpp"
|
||||||
#include "modules/sway/mode.hpp"
|
#include "modules/sway/mode.hpp"
|
||||||
#include "modules/sway/window.hpp"
|
#include "modules/sway/window.hpp"
|
||||||
#include "modules/sway/workspaces.hpp"
|
#include "modules/sway/workspaces.hpp"
|
||||||
#include "modules/sway/language.hpp"
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_WLR
|
#ifdef HAVE_WLR
|
||||||
#include "modules/wlr/taskbar.hpp"
|
#include "modules/wlr/taskbar.hpp"
|
||||||
@ -18,6 +18,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_RIVER
|
#ifdef HAVE_RIVER
|
||||||
#include "modules/river/tags.hpp"
|
#include "modules/river/tags.hpp"
|
||||||
|
#include "modules/river/window.hpp"
|
||||||
#endif
|
#endif
|
||||||
#if defined(__linux__) && !defined(NO_FILESYSTEM)
|
#if defined(__linux__) && !defined(NO_FILESYSTEM)
|
||||||
#include "modules/battery.hpp"
|
#include "modules/battery.hpp"
|
||||||
@ -42,6 +43,12 @@
|
|||||||
#ifdef HAVE_LIBEVDEV
|
#ifdef HAVE_LIBEVDEV
|
||||||
#include "modules/keyboard_state.hpp"
|
#include "modules/keyboard_state.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_GAMEMODE
|
||||||
|
#include "modules/gamemode.hpp"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UPOWER
|
||||||
|
#include "modules/upower/upower.hpp"
|
||||||
|
#endif
|
||||||
#ifdef HAVE_LIBPULSE
|
#ifdef HAVE_LIBPULSE
|
||||||
#include "modules/pulseaudio.hpp"
|
#include "modules/pulseaudio.hpp"
|
||||||
#endif
|
#endif
|
||||||
@ -52,16 +59,12 @@
|
|||||||
#include "modules/sndio.hpp"
|
#include "modules/sndio.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_GIO_UNIX
|
#ifdef HAVE_GIO_UNIX
|
||||||
|
#include "modules/bluetooth.hpp"
|
||||||
#include "modules/inhibitor.hpp"
|
#include "modules/inhibitor.hpp"
|
||||||
#endif
|
#endif
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "modules/custom.hpp"
|
#include "modules/custom.hpp"
|
||||||
#include "modules/temperature.hpp"
|
#include "modules/temperature.hpp"
|
||||||
#if defined(__linux__)
|
|
||||||
# ifdef WANT_RFKILL
|
|
||||||
# include "modules/bluetooth.hpp"
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
|
|
||||||
@ -71,7 +74,7 @@ class Factory {
|
|||||||
AModule* makeModule(const std::string& name) const;
|
AModule* makeModule(const std::string& name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
const Json::Value& config_;
|
const Json::Value& config_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <gtkmm/widget.h>
|
|
||||||
#include <gtkmm/box.h>
|
#include <gtkmm/box.h>
|
||||||
|
#include <gtkmm/widget.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
|
|
||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "factory.hpp"
|
#include "factory.hpp"
|
||||||
@ -14,7 +15,7 @@ class Group : public AModule {
|
|||||||
Group(const std::string&, const Bar&, const Json::Value&);
|
Group(const std::string&, const Bar&, const Json::Value&);
|
||||||
~Group() = default;
|
~Group() = default;
|
||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
operator Gtk::Widget &();
|
operator Gtk::Widget&();
|
||||||
Gtk::Box box;
|
Gtk::Box box;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,19 +19,19 @@ class Backlight : public ALabel {
|
|||||||
public:
|
public:
|
||||||
BacklightDev() = default;
|
BacklightDev() = default;
|
||||||
BacklightDev(std::string name, int actual, int max);
|
BacklightDev(std::string name, int actual, int max);
|
||||||
std::string_view name() const;
|
std::string_view name() const;
|
||||||
int get_actual() const;
|
int get_actual() const;
|
||||||
void set_actual(int actual);
|
void set_actual(int actual);
|
||||||
int get_max() const;
|
int get_max() const;
|
||||||
void set_max(int max);
|
void set_max(int max);
|
||||||
friend inline bool operator==(const BacklightDev &lhs, const BacklightDev &rhs) {
|
friend inline bool operator==(const BacklightDev &lhs, const BacklightDev &rhs) {
|
||||||
return lhs.name_ == rhs.name_ && lhs.actual_ == rhs.actual_ && lhs.max_ == rhs.max_;
|
return lhs.name_ == rhs.name_ && lhs.actual_ == rhs.actual_ && lhs.max_ == rhs.max_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
int actual_ = 1;
|
int actual_ = 1;
|
||||||
int max_ = 1;
|
int max_ = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -47,13 +47,13 @@ class Backlight : public ALabel {
|
|||||||
template <class ForwardIt, class Inserter>
|
template <class ForwardIt, class Inserter>
|
||||||
static void enumerate_devices(ForwardIt first, ForwardIt last, Inserter inserter, udev *udev);
|
static void enumerate_devices(ForwardIt first, ForwardIt last, Inserter inserter, udev *udev);
|
||||||
|
|
||||||
const std::string preferred_device_;
|
const std::string preferred_device_;
|
||||||
static constexpr int EPOLL_MAX_EVENTS = 16;
|
static constexpr int EPOLL_MAX_EVENTS = 16;
|
||||||
|
|
||||||
std::optional<BacklightDev> previous_best_;
|
std::optional<BacklightDev> previous_best_;
|
||||||
std::string previous_format_;
|
std::string previous_format_;
|
||||||
|
|
||||||
std::mutex udev_thread_mutex_;
|
std::mutex udev_thread_mutex_;
|
||||||
std::vector<BacklightDev> devices_;
|
std::vector<BacklightDev> devices_;
|
||||||
// thread must destruct before shared data
|
// thread must destruct before shared data
|
||||||
util::SleeperThread udev_thread_;
|
util::SleeperThread udev_thread_;
|
||||||
|
@ -7,10 +7,12 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
@ -31,23 +33,24 @@ class Battery : public ALabel {
|
|||||||
private:
|
private:
|
||||||
static inline const fs::path data_dir_ = "/sys/class/power_supply/";
|
static inline const fs::path data_dir_ = "/sys/class/power_supply/";
|
||||||
|
|
||||||
void refreshBatteries();
|
void refreshBatteries();
|
||||||
void worker();
|
void worker();
|
||||||
const std::string getAdapterStatus(uint8_t capacity) const;
|
const std::string getAdapterStatus(uint8_t capacity) const;
|
||||||
const std::tuple<uint8_t, float, std::string, float> getInfos();
|
const std::tuple<uint8_t, float, std::string, float> getInfos();
|
||||||
const std::string formatTimeRemaining(float hoursRemaining);
|
const std::string formatTimeRemaining(float hoursRemaining);
|
||||||
|
|
||||||
int global_watch;
|
int global_watch;
|
||||||
std::map<fs::path,int> batteries_;
|
std::map<fs::path, int> batteries_;
|
||||||
fs::path adapter_;
|
fs::path adapter_;
|
||||||
int battery_watch_fd_;
|
int battery_watch_fd_;
|
||||||
int global_watch_fd_;
|
int global_watch_fd_;
|
||||||
std::mutex battery_list_mutex_;
|
std::mutex battery_list_mutex_;
|
||||||
std::string old_status_;
|
std::string old_status_;
|
||||||
|
bool warnFirstTime_{true};
|
||||||
|
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
util::SleeperThread thread_battery_update_;
|
util::SleeperThread thread_battery_update_;
|
||||||
util::SleeperThread thread_timer_;
|
util::SleeperThread thread_timer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules
|
} // namespace waybar::modules
|
||||||
|
@ -1,18 +1,79 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
|
#ifdef WANT_RFKILL
|
||||||
#include "util/rfkill.hpp"
|
#include "util/rfkill.hpp"
|
||||||
|
#endif
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace waybar::modules {
|
namespace waybar::modules {
|
||||||
|
|
||||||
class Bluetooth : public ALabel {
|
class Bluetooth : public ALabel {
|
||||||
|
struct ControllerInfo {
|
||||||
|
std::string path;
|
||||||
|
std::string address;
|
||||||
|
std::string address_type;
|
||||||
|
// std::string name; // just use alias instead
|
||||||
|
std::string alias;
|
||||||
|
bool powered;
|
||||||
|
bool discoverable;
|
||||||
|
bool pairable;
|
||||||
|
bool discovering;
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOTE: there are some properties that not all devices provide
|
||||||
|
struct DeviceInfo {
|
||||||
|
std::string path;
|
||||||
|
std::string paired_controller;
|
||||||
|
std::string address;
|
||||||
|
std::string address_type;
|
||||||
|
// std::optional<std::string> name; // just use alias instead
|
||||||
|
std::string alias;
|
||||||
|
std::optional<std::string> icon;
|
||||||
|
bool paired;
|
||||||
|
bool trusted;
|
||||||
|
bool blocked;
|
||||||
|
bool connected;
|
||||||
|
bool services_resolved;
|
||||||
|
// NOTE: experimental feature in bluez
|
||||||
|
std::optional<unsigned char> battery_percentage;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Bluetooth(const std::string&, const Json::Value&);
|
Bluetooth(const std::string&, const Json::Value&);
|
||||||
~Bluetooth() = default;
|
~Bluetooth() = default;
|
||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static auto onInterfaceAddedOrRemoved(GDBusObjectManager*, GDBusObject*, GDBusInterface*,
|
||||||
|
gpointer) -> void;
|
||||||
|
static auto onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient*, GDBusObjectProxy*,
|
||||||
|
GDBusProxy*, GVariant*, const gchar* const*,
|
||||||
|
gpointer) -> void;
|
||||||
|
|
||||||
|
auto getDeviceBatteryPercentage(GDBusObject*) -> std::optional<unsigned char>;
|
||||||
|
auto getDeviceProperties(GDBusObject*, DeviceInfo&) -> bool;
|
||||||
|
auto getControllerProperties(GDBusObject*, ControllerInfo&) -> bool;
|
||||||
|
|
||||||
|
auto findCurController(ControllerInfo&) -> bool;
|
||||||
|
auto findConnectedDevices(const std::string&, std::vector<DeviceInfo>&) -> void;
|
||||||
|
|
||||||
|
#ifdef WANT_RFKILL
|
||||||
util::Rfkill rfkill_;
|
util::Rfkill rfkill_;
|
||||||
|
#endif
|
||||||
|
const std::unique_ptr<GDBusObjectManager, void (*)(GDBusObjectManager*)> manager_;
|
||||||
|
|
||||||
|
std::string state_;
|
||||||
|
ControllerInfo cur_controller_;
|
||||||
|
std::vector<DeviceInfo> connected_devices_;
|
||||||
|
DeviceInfo cur_focussed_device_;
|
||||||
|
std::string device_enumerate_;
|
||||||
|
|
||||||
|
std::vector<std::string> device_preference_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules
|
} // namespace waybar::modules
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <date/tz.h>
|
#include <date/tz.h>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ struct waybar_time;
|
|||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
const std::string kCalendarPlaceholder = "calendar";
|
const std::string kCalendarPlaceholder = "calendar";
|
||||||
|
const std::string KTimezonedTimeListPlaceholder = "timezoned_time_list";
|
||||||
|
|
||||||
class Clock : public ALabel {
|
class Clock : public ALabel {
|
||||||
public:
|
public:
|
||||||
@ -23,9 +25,10 @@ class Clock : public ALabel {
|
|||||||
std::locale locale_;
|
std::locale locale_;
|
||||||
std::vector<const date::time_zone*> time_zones_;
|
std::vector<const date::time_zone*> time_zones_;
|
||||||
int current_time_zone_idx_;
|
int current_time_zone_idx_;
|
||||||
date::year_month_day cached_calendar_ymd_ = date::January/1/0;
|
date::year_month_day cached_calendar_ymd_ = date::January / 1 / 0;
|
||||||
std::string cached_calendar_text_;
|
std::string cached_calendar_text_;
|
||||||
bool is_calendar_in_tooltip_;
|
bool is_calendar_in_tooltip_;
|
||||||
|
bool is_timezoned_list_in_tooltip_;
|
||||||
|
|
||||||
bool handleScroll(GdkEventScroll* e);
|
bool handleScroll(GdkEventScroll* e);
|
||||||
|
|
||||||
@ -33,7 +36,9 @@ class Clock : public ALabel {
|
|||||||
auto weekdays_header(const date::weekday& first_dow, std::ostream& os) -> void;
|
auto weekdays_header(const date::weekday& first_dow, std::ostream& os) -> void;
|
||||||
auto first_day_of_week() -> date::weekday;
|
auto first_day_of_week() -> date::weekday;
|
||||||
const date::time_zone* current_timezone();
|
const date::time_zone* current_timezone();
|
||||||
|
auto print_iso_weeknum(std::ostream& os, int weeknum) -> void;
|
||||||
bool is_timezone_fixed();
|
bool is_timezone_fixed();
|
||||||
|
auto timezones_text(std::chrono::system_clock::time_point* now) -> std::string;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
@ -19,11 +21,11 @@ class Cpu : public ALabel {
|
|||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double getCpuLoad();
|
double getCpuLoad();
|
||||||
std::tuple<std::vector<uint16_t>, std::string> getCpuUsage();
|
std::tuple<std::vector<uint16_t>, std::string> getCpuUsage();
|
||||||
std::tuple<float, float, float> getCpuFrequency();
|
std::tuple<float, float, float> getCpuFrequency();
|
||||||
std::vector<std::tuple<size_t, size_t>> parseCpuinfo();
|
std::vector<std::tuple<size_t, size_t>> parseCpuinfo();
|
||||||
std::vector<float> parseCpuFrequencies();
|
std::vector<float> parseCpuFrequencies();
|
||||||
|
|
||||||
std::vector<std::tuple<size_t, size_t>> prev_times_;
|
std::vector<std::tuple<size_t, size_t>> prev_times_;
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/command.hpp"
|
#include "util/command.hpp"
|
||||||
#include "util/json.hpp"
|
#include "util/json.hpp"
|
||||||
@ -26,16 +28,16 @@ class Custom : public ALabel {
|
|||||||
bool handleScroll(GdkEventScroll* e);
|
bool handleScroll(GdkEventScroll* e);
|
||||||
bool handleToggle(GdkEventButton* const& e);
|
bool handleToggle(GdkEventButton* const& e);
|
||||||
|
|
||||||
const std::string name_;
|
const std::string name_;
|
||||||
std::string text_;
|
std::string text_;
|
||||||
std::string alt_;
|
std::string alt_;
|
||||||
std::string tooltip_;
|
std::string tooltip_;
|
||||||
std::vector<std::string> class_;
|
std::vector<std::string> class_;
|
||||||
int percentage_;
|
int percentage_;
|
||||||
FILE* fp_;
|
FILE* fp_;
|
||||||
int pid_;
|
int pid_;
|
||||||
util::command::res output_;
|
util::command::res output_;
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
|
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <fstream>
|
|
||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
|
||||||
#include "util/format.hpp"
|
#include "util/format.hpp"
|
||||||
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
namespace waybar::modules {
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
77
include/modules/gamemode.hpp
Normal file
77
include/modules/gamemode.hpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "ALabel.hpp"
|
||||||
|
#include "giomm/dbusconnection.h"
|
||||||
|
#include "giomm/dbusproxy.h"
|
||||||
|
#include "glibconfig.h"
|
||||||
|
#include "gtkmm/box.h"
|
||||||
|
#include "gtkmm/image.h"
|
||||||
|
#include "gtkmm/label.h"
|
||||||
|
#include "gtkmm/overlay.h"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
class Gamemode : public AModule {
|
||||||
|
public:
|
||||||
|
Gamemode(const std::string &, const Json::Value &);
|
||||||
|
~Gamemode();
|
||||||
|
auto update() -> void;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string DEFAULT_ICON_NAME = "input-gaming-symbolic";
|
||||||
|
const std::string DEFAULT_FORMAT = "{glyph}";
|
||||||
|
const std::string DEFAULT_FORMAT_ALT = "{glyph} {count}";
|
||||||
|
const std::string DEFAULT_TOOLTIP_FORMAT = "Games running: {count}";
|
||||||
|
const std::string DEFAULT_GLYPH = "";
|
||||||
|
|
||||||
|
void appear(const Glib::RefPtr<Gio::DBus::Connection> &connection, const Glib::ustring &name,
|
||||||
|
const Glib::ustring &name_owner);
|
||||||
|
void disappear(const Glib::RefPtr<Gio::DBus::Connection> &connection, const Glib::ustring &name);
|
||||||
|
void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection> &connection,
|
||||||
|
const Glib::ustring &sender_name, const Glib::ustring &object_path,
|
||||||
|
const Glib::ustring &interface_name, const Glib::ustring &signal_name,
|
||||||
|
const Glib::VariantContainerBase ¶meters);
|
||||||
|
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name,
|
||||||
|
const Glib::VariantContainerBase &arguments);
|
||||||
|
|
||||||
|
void getData();
|
||||||
|
bool handleToggle(GdkEventButton *const &);
|
||||||
|
|
||||||
|
// Config
|
||||||
|
std::string format = DEFAULT_FORMAT;
|
||||||
|
std::string format_alt = DEFAULT_FORMAT_ALT;
|
||||||
|
std::string tooltip_format = DEFAULT_TOOLTIP_FORMAT;
|
||||||
|
std::string glyph = DEFAULT_GLYPH;
|
||||||
|
bool tooltip = true;
|
||||||
|
bool hideNotRunning = true;
|
||||||
|
bool useIcon = true;
|
||||||
|
uint iconSize = 20;
|
||||||
|
uint iconSpacing = 4;
|
||||||
|
std::string iconName = DEFAULT_ICON_NAME;
|
||||||
|
|
||||||
|
Gtk::Box box_;
|
||||||
|
Gtk::Image icon_;
|
||||||
|
Gtk::Label label_;
|
||||||
|
|
||||||
|
const std::string dbus_name = "com.feralinteractive.GameMode";
|
||||||
|
const std::string dbus_obj_path = "/com/feralinteractive/GameMode";
|
||||||
|
const std::string dbus_interface = "org.freedesktop.DBus.Properties";
|
||||||
|
const std::string dbus_get_interface = "com.feralinteractive.GameMode";
|
||||||
|
|
||||||
|
uint gameCount = 0;
|
||||||
|
|
||||||
|
std::string lastStatus;
|
||||||
|
bool showAltText = false;
|
||||||
|
|
||||||
|
guint login1_id;
|
||||||
|
Glib::RefPtr<Gio::DBus::Proxy> gamemode_proxy;
|
||||||
|
Glib::RefPtr<Gio::DBus::Connection> system_connection;
|
||||||
|
bool gamemodeRunning;
|
||||||
|
guint gamemodeWatcher_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
@ -8,19 +9,21 @@
|
|||||||
namespace waybar::modules {
|
namespace waybar::modules {
|
||||||
|
|
||||||
class IdleInhibitor : public ALabel {
|
class IdleInhibitor : public ALabel {
|
||||||
|
sigc::connection timeout_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IdleInhibitor(const std::string&, const waybar::Bar&, const Json::Value&);
|
IdleInhibitor(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
~IdleInhibitor();
|
~IdleInhibitor();
|
||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
static std::list<waybar::AModule*> modules;
|
static std::list<waybar::AModule*> modules;
|
||||||
static bool status;
|
static bool status;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool handleToggle(GdkEventButton* const& e);
|
bool handleToggle(GdkEventButton* const& e);
|
||||||
|
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
struct zwp_idle_inhibitor_v1* idle_inhibitor_;
|
struct zwp_idle_inhibitor_v1* idle_inhibitor_;
|
||||||
int pid_;
|
int pid_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules
|
} // namespace waybar::modules
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
|
|
||||||
@ -19,9 +19,9 @@ class Inhibitor : public ALabel {
|
|||||||
private:
|
private:
|
||||||
auto handleToggle(::GdkEventButton* const& e) -> bool;
|
auto handleToggle(::GdkEventButton* const& e) -> bool;
|
||||||
|
|
||||||
const std::unique_ptr<::GDBusConnection, void(*)(::GDBusConnection*)> dbus_;
|
const std::unique_ptr<::GDBusConnection, void (*)(::GDBusConnection*)> dbus_;
|
||||||
const std::string inhibitors_;
|
const std::string inhibitors_;
|
||||||
int handle_ = -1;
|
int handle_ = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules
|
} // namespace waybar::modules
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
#else
|
#else
|
||||||
#include <fmt/chrono.h>
|
#include <fmt/chrono.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <gtkmm/label.h>
|
||||||
|
|
||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
#include <gtkmm/label.h>
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <libevdev/libevdev.h>
|
#include <libevdev/libevdev.h>
|
||||||
@ -24,12 +25,10 @@ class KeyboardState : public AModule {
|
|||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static auto openDevice(const std::string&) -> std::pair<int, libevdev*>;
|
Gtk::Box box_;
|
||||||
|
Gtk::Label numlock_label_;
|
||||||
Gtk::Box box_;
|
Gtk::Label capslock_label_;
|
||||||
Gtk::Label numlock_label_;
|
Gtk::Label scrolllock_label_;
|
||||||
Gtk::Label capslock_label_;
|
|
||||||
Gtk::Label scrolllock_label_;
|
|
||||||
|
|
||||||
std::string numlock_format_;
|
std::string numlock_format_;
|
||||||
std::string capslock_format_;
|
std::string capslock_format_;
|
||||||
@ -38,8 +37,8 @@ class KeyboardState : public AModule {
|
|||||||
std::string icon_locked_;
|
std::string icon_locked_;
|
||||||
std::string icon_unlocked_;
|
std::string icon_unlocked_;
|
||||||
|
|
||||||
int fd_;
|
int fd_;
|
||||||
libevdev* dev_;
|
libevdev* dev_;
|
||||||
|
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
@ -15,7 +17,7 @@ class Memory : public ALabel {
|
|||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parseMeminfo();
|
void parseMeminfo();
|
||||||
|
|
||||||
std::unordered_map<std::string, unsigned long> meminfo_;
|
std::unordered_map<std::string, unsigned long> meminfo_;
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@ class MPD : public ALabel {
|
|||||||
|
|
||||||
// Not using unique_ptr since we don't manage the pointer
|
// Not using unique_ptr since we don't manage the pointer
|
||||||
// (It's either nullptr, or from the config)
|
// (It's either nullptr, or from the config)
|
||||||
const char* server_;
|
const char* server_;
|
||||||
const unsigned port_;
|
const unsigned port_;
|
||||||
const std::string password_;
|
const std::string password_;
|
||||||
|
|
||||||
unsigned timeout_;
|
unsigned timeout_;
|
||||||
@ -31,8 +31,8 @@ class MPD : public ALabel {
|
|||||||
detail::unique_connection connection_;
|
detail::unique_connection connection_;
|
||||||
|
|
||||||
detail::unique_status status_;
|
detail::unique_status status_;
|
||||||
mpd_state state_;
|
mpd_state state_;
|
||||||
detail::unique_song song_;
|
detail::unique_song song_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MPD(const std::string&, const Json::Value&);
|
MPD(const std::string&, const Json::Value&);
|
||||||
@ -41,7 +41,7 @@ class MPD : public ALabel {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::string getTag(mpd_tag_type type, unsigned idx = 0) const;
|
std::string getTag(mpd_tag_type type, unsigned idx = 0) const;
|
||||||
void setLabel();
|
void setLabel();
|
||||||
std::string getStateIcon() const;
|
std::string getStateIcon() const;
|
||||||
std::string getOptionIcon(std::string optionName, bool activated) const;
|
std::string getOptionIcon(std::string optionName, bool activated) const;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mpd/client.h>
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
#include <mpd/client.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
@ -57,7 +57,7 @@ class State {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Idle : public State {
|
class Idle : public State {
|
||||||
Context* const ctx_;
|
Context* const ctx_;
|
||||||
sigc::connection idle_connection_;
|
sigc::connection idle_connection_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -80,7 +80,7 @@ class Idle : public State {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Playing : public State {
|
class Playing : public State {
|
||||||
Context* const ctx_;
|
Context* const ctx_;
|
||||||
sigc::connection timer_connection_;
|
sigc::connection timer_connection_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -102,7 +102,7 @@ class Playing : public State {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Paused : public State {
|
class Paused : public State {
|
||||||
Context* const ctx_;
|
Context* const ctx_;
|
||||||
sigc::connection timer_connection_;
|
sigc::connection timer_connection_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -124,7 +124,7 @@ class Paused : public State {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Stopped : public State {
|
class Stopped : public State {
|
||||||
Context* const ctx_;
|
Context* const ctx_;
|
||||||
sigc::connection timer_connection_;
|
sigc::connection timer_connection_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -146,7 +146,7 @@ class Stopped : public State {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Disconnected : public State {
|
class Disconnected : public State {
|
||||||
Context* const ctx_;
|
Context* const ctx_;
|
||||||
sigc::connection timer_connection_;
|
sigc::connection timer_connection_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -170,7 +170,7 @@ class Disconnected : public State {
|
|||||||
|
|
||||||
class Context {
|
class Context {
|
||||||
std::unique_ptr<State> state_;
|
std::unique_ptr<State> state_;
|
||||||
waybar::modules::MPD* mpd_module_;
|
waybar::modules::MPD* mpd_module_;
|
||||||
|
|
||||||
friend class State;
|
friend class State;
|
||||||
friend class Playing;
|
friend class Playing;
|
||||||
@ -188,18 +188,18 @@ class Context {
|
|||||||
state_->entry();
|
state_->entry();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_connected() const;
|
bool is_connected() const;
|
||||||
bool is_playing() const;
|
bool is_playing() const;
|
||||||
bool is_paused() const;
|
bool is_paused() const;
|
||||||
bool is_stopped() const;
|
bool is_stopped() const;
|
||||||
constexpr std::size_t interval() const;
|
constexpr std::size_t interval() const;
|
||||||
void tryConnect() const;
|
void tryConnect() const;
|
||||||
void checkErrors(mpd_connection*) const;
|
void checkErrors(mpd_connection*) const;
|
||||||
void do_update();
|
void do_update();
|
||||||
void queryMPD() const;
|
void queryMPD() const;
|
||||||
void fetchState() const;
|
void fetchState() const;
|
||||||
constexpr mpd_state state() const;
|
constexpr mpd_state state() const;
|
||||||
void emit() const;
|
void emit() const;
|
||||||
[[nodiscard]] unique_connection& connection();
|
[[nodiscard]] unique_connection& connection();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -8,13 +8,11 @@ inline bool Context::is_paused() const { return mpd_module_->paused(); }
|
|||||||
inline bool Context::is_stopped() const { return mpd_module_->stopped(); }
|
inline bool Context::is_stopped() const { return mpd_module_->stopped(); }
|
||||||
|
|
||||||
constexpr inline std::size_t Context::interval() const { return mpd_module_->interval_.count(); }
|
constexpr inline std::size_t Context::interval() const { return mpd_module_->interval_.count(); }
|
||||||
inline void Context::tryConnect() const { mpd_module_->tryConnect(); }
|
inline void Context::tryConnect() const { mpd_module_->tryConnect(); }
|
||||||
inline unique_connection& Context::connection() { return mpd_module_->connection_; }
|
inline unique_connection& Context::connection() { return mpd_module_->connection_; }
|
||||||
constexpr inline mpd_state Context::state() const { return mpd_module_->state_; }
|
constexpr inline mpd_state Context::state() const { return mpd_module_->state_; }
|
||||||
|
|
||||||
inline void Context::do_update() {
|
inline void Context::do_update() { mpd_module_->setLabel(); }
|
||||||
mpd_module_->setLabel();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Context::checkErrors(mpd_connection* conn) const { mpd_module_->checkErrors(conn); }
|
inline void Context::checkErrors(mpd_connection* conn) const { mpd_module_->checkErrors(conn); }
|
||||||
inline void Context::queryMPD() const { mpd_module_->queryMPD(); }
|
inline void Context::queryMPD() const { mpd_module_->queryMPD(); }
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
#include <netlink/genl/genl.h>
|
#include <netlink/genl/genl.h>
|
||||||
#include <netlink/netlink.h>
|
#include <netlink/netlink.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
#ifdef WANT_RFKILL
|
#ifdef WANT_RFKILL
|
||||||
@ -31,51 +34,51 @@ class Network : public ALabel {
|
|||||||
|
|
||||||
void askForStateDump(void);
|
void askForStateDump(void);
|
||||||
|
|
||||||
void worker();
|
void worker();
|
||||||
void createInfoSocket();
|
void createInfoSocket();
|
||||||
void createEventSocket();
|
void createEventSocket();
|
||||||
void parseEssid(struct nlattr**);
|
void parseEssid(struct nlattr**);
|
||||||
void parseSignal(struct nlattr**);
|
void parseSignal(struct nlattr**);
|
||||||
void parseFreq(struct nlattr**);
|
void parseFreq(struct nlattr**);
|
||||||
bool associatedOrJoined(struct nlattr**);
|
bool associatedOrJoined(struct nlattr**);
|
||||||
bool checkInterface(std::string name);
|
bool checkInterface(std::string name);
|
||||||
auto getInfo() -> void;
|
auto getInfo() -> void;
|
||||||
const std::string getNetworkState() const;
|
const std::string getNetworkState() const;
|
||||||
void clearIface();
|
void clearIface();
|
||||||
bool wildcardMatch(const std::string& pattern, const std::string& text) const;
|
bool wildcardMatch(const std::string& pattern, const std::string& text) const;
|
||||||
std::optional<std::pair<unsigned long long, unsigned long long>> readBandwidthUsage();
|
std::optional<std::pair<unsigned long long, unsigned long long>> readBandwidthUsage();
|
||||||
|
|
||||||
int ifid_;
|
int ifid_;
|
||||||
sa_family_t family_;
|
sa_family_t family_;
|
||||||
struct sockaddr_nl nladdr_ = {0};
|
struct sockaddr_nl nladdr_ = {0};
|
||||||
struct nl_sock* sock_ = nullptr;
|
struct nl_sock* sock_ = nullptr;
|
||||||
struct nl_sock* ev_sock_ = nullptr;
|
struct nl_sock* ev_sock_ = nullptr;
|
||||||
int efd_;
|
int efd_;
|
||||||
int ev_fd_;
|
int ev_fd_;
|
||||||
int nl80211_id_;
|
int nl80211_id_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
|
|
||||||
bool want_route_dump_;
|
bool want_route_dump_;
|
||||||
bool want_link_dump_;
|
bool want_link_dump_;
|
||||||
bool want_addr_dump_;
|
bool want_addr_dump_;
|
||||||
bool dump_in_progress_;
|
bool dump_in_progress_;
|
||||||
|
|
||||||
unsigned long long bandwidth_down_total_;
|
unsigned long long bandwidth_down_total_;
|
||||||
unsigned long long bandwidth_up_total_;
|
unsigned long long bandwidth_up_total_;
|
||||||
|
|
||||||
std::string state_;
|
std::string state_;
|
||||||
std::string essid_;
|
std::string essid_;
|
||||||
bool carrier_;
|
bool carrier_;
|
||||||
std::string ifname_;
|
std::string ifname_;
|
||||||
std::string ipaddr_;
|
std::string ipaddr_;
|
||||||
std::string gwaddr_;
|
std::string gwaddr_;
|
||||||
std::string netmask_;
|
std::string netmask_;
|
||||||
int cidr_;
|
int cidr_;
|
||||||
int32_t signal_strength_dbm_;
|
int32_t signal_strength_dbm_;
|
||||||
uint8_t signal_strength_;
|
uint8_t signal_strength_;
|
||||||
std::string signal_strength_app_;
|
std::string signal_strength_app_;
|
||||||
float frequency_;
|
float frequency_;
|
||||||
uint32_t route_priority;
|
uint32_t route_priority;
|
||||||
|
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
util::SleeperThread thread_timer_;
|
util::SleeperThread thread_timer_;
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <pulse/pulseaudio.h>
|
#include <pulse/pulseaudio.h>
|
||||||
#include <pulse/volume.h>
|
#include <pulse/volume.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
|
|
||||||
namespace waybar::modules {
|
namespace waybar::modules {
|
||||||
@ -23,27 +25,27 @@ class Pulseaudio : public ALabel {
|
|||||||
static void serverInfoCb(pa_context*, const pa_server_info*, void*);
|
static void serverInfoCb(pa_context*, const pa_server_info*, void*);
|
||||||
static void volumeModifyCb(pa_context*, int, void*);
|
static void volumeModifyCb(pa_context*, int, void*);
|
||||||
|
|
||||||
bool handleScroll(GdkEventScroll* e);
|
bool handleScroll(GdkEventScroll* e);
|
||||||
const std::vector<std::string> getPulseIcon() const;
|
const std::vector<std::string> getPulseIcon() const;
|
||||||
|
|
||||||
pa_threaded_mainloop* mainloop_;
|
pa_threaded_mainloop* mainloop_;
|
||||||
pa_mainloop_api* mainloop_api_;
|
pa_mainloop_api* mainloop_api_;
|
||||||
pa_context* context_;
|
pa_context* context_;
|
||||||
// SINK
|
// SINK
|
||||||
uint32_t sink_idx_{0};
|
uint32_t sink_idx_{0};
|
||||||
uint16_t volume_;
|
uint16_t volume_;
|
||||||
pa_cvolume pa_volume_;
|
pa_cvolume pa_volume_;
|
||||||
bool muted_;
|
bool muted_;
|
||||||
std::string port_name_;
|
std::string port_name_;
|
||||||
std::string form_factor_;
|
std::string form_factor_;
|
||||||
std::string desc_;
|
std::string desc_;
|
||||||
std::string monitor_;
|
std::string monitor_;
|
||||||
std::string current_sink_name_;
|
std::string current_sink_name_;
|
||||||
bool current_sink_running_;
|
bool current_sink_running_;
|
||||||
// SOURCE
|
// SOURCE
|
||||||
uint32_t source_idx_{0};
|
uint32_t source_idx_{0};
|
||||||
uint16_t source_volume_;
|
uint16_t source_volume_;
|
||||||
bool source_muted_;
|
bool source_muted_;
|
||||||
std::string source_port_name_;
|
std::string source_port_name_;
|
||||||
std::string source_desc_;
|
std::string source_desc_;
|
||||||
std::string default_source_name_;
|
std::string default_source_name_;
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "river-status-unstable-v1-client-protocol.h"
|
|
||||||
#include "river-control-unstable-v1-client-protocol.h"
|
#include "river-control-unstable-v1-client-protocol.h"
|
||||||
|
#include "river-status-unstable-v1-client-protocol.h"
|
||||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
namespace waybar::modules::river {
|
namespace waybar::modules::river {
|
||||||
@ -29,8 +29,8 @@ class Tags : public waybar::AModule {
|
|||||||
struct wl_seat *seat_;
|
struct wl_seat *seat_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const waybar::Bar & bar_;
|
const waybar::Bar &bar_;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
std::vector<Gtk::Button> buttons_;
|
std::vector<Gtk::Button> buttons_;
|
||||||
struct zriver_output_status_v1 *output_status_;
|
struct zriver_output_status_v1 *output_status_;
|
||||||
};
|
};
|
||||||
|
33
include/modules/river/window.hpp
Normal file
33
include/modules/river/window.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include "ALabel.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "river-status-unstable-v1-client-protocol.h"
|
||||||
|
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
|
namespace waybar::modules::river {
|
||||||
|
|
||||||
|
class Window : public waybar::ALabel {
|
||||||
|
public:
|
||||||
|
Window(const std::string &, const waybar::Bar &, const Json::Value &);
|
||||||
|
~Window();
|
||||||
|
|
||||||
|
// Handlers for wayland events
|
||||||
|
void handle_focused_view(const char *title);
|
||||||
|
void handle_focused_output(struct wl_output *output);
|
||||||
|
void handle_unfocused_output(struct wl_output *output);
|
||||||
|
|
||||||
|
struct zriver_status_manager_v1 *status_manager_;
|
||||||
|
struct wl_seat *seat_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const waybar::Bar &bar_;
|
||||||
|
struct wl_output *output_; // stores the output this module belongs to
|
||||||
|
struct wl_output *focused_output_; // stores the currently focused output
|
||||||
|
struct zriver_seat_status_v1 *seat_status_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace waybar::modules::river */
|
@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <sndio.h>
|
#include <sndio.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
@ -9,13 +11,13 @@ namespace waybar::modules {
|
|||||||
|
|
||||||
class Sndio : public ALabel {
|
class Sndio : public ALabel {
|
||||||
public:
|
public:
|
||||||
Sndio(const std::string&, const Json::Value&);
|
Sndio(const std::string &, const Json::Value &);
|
||||||
~Sndio();
|
~Sndio();
|
||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
auto set_desc(struct sioctl_desc *, unsigned int) -> void;
|
auto set_desc(struct sioctl_desc *, unsigned int) -> void;
|
||||||
auto put_val(unsigned int, unsigned int) -> void;
|
auto put_val(unsigned int, unsigned int) -> void;
|
||||||
bool handleScroll(GdkEventScroll *);
|
bool handleScroll(GdkEventScroll *);
|
||||||
bool handleToggle(GdkEventButton* const&);
|
bool handleToggle(GdkEventButton *const &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto connect_to_sndio() -> void;
|
auto connect_to_sndio() -> void;
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
#include <giomm.h>
|
#include <giomm.h>
|
||||||
#include <glibmm/refptr.h>
|
#include <glibmm/refptr.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "modules/sni/item.hpp"
|
#include "modules/sni/item.hpp"
|
||||||
|
|
||||||
@ -18,27 +20,27 @@ class Host {
|
|||||||
~Host();
|
~Host();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
|
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
|
||||||
void nameAppeared(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring,
|
void nameAppeared(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring,
|
||||||
const Glib::ustring&);
|
const Glib::ustring&);
|
||||||
void nameVanished(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
|
void nameVanished(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
|
||||||
static void proxyReady(GObject*, GAsyncResult*, gpointer);
|
static void proxyReady(GObject*, GAsyncResult*, gpointer);
|
||||||
static void registerHost(GObject*, GAsyncResult*, gpointer);
|
static void registerHost(GObject*, GAsyncResult*, gpointer);
|
||||||
static void itemRegistered(SnWatcher*, const gchar*, gpointer);
|
static void itemRegistered(SnWatcher*, const gchar*, gpointer);
|
||||||
static void itemUnregistered(SnWatcher*, const gchar*, gpointer);
|
static void itemUnregistered(SnWatcher*, const gchar*, gpointer);
|
||||||
|
|
||||||
std::tuple<std::string, std::string> getBusNameAndObjectPath(const std::string);
|
std::tuple<std::string, std::string> getBusNameAndObjectPath(const std::string);
|
||||||
void addRegisteredItem(std::string service);
|
void addRegisteredItem(std::string service);
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Item>> items_;
|
std::vector<std::unique_ptr<Item>> items_;
|
||||||
const std::string bus_name_;
|
const std::string bus_name_;
|
||||||
const std::string object_path_;
|
const std::string object_path_;
|
||||||
std::size_t bus_name_id_;
|
std::size_t bus_name_id_;
|
||||||
std::size_t watcher_id_;
|
std::size_t watcher_id_;
|
||||||
GCancellable* cancellable_ = nullptr;
|
GCancellable* cancellable_ = nullptr;
|
||||||
SnWatcher* watcher_ = nullptr;
|
SnWatcher* watcher_ = nullptr;
|
||||||
const Json::Value& config_;
|
const Json::Value& config_;
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
const std::function<void(std::unique_ptr<Item>&)> on_add_;
|
const std::function<void(std::unique_ptr<Item>&)> on_add_;
|
||||||
const std::function<void(std::unique_ptr<Item>&)> on_remove_;
|
const std::function<void(std::unique_ptr<Item>&)> on_remove_;
|
||||||
};
|
};
|
||||||
|
@ -31,25 +31,25 @@ class Item : public sigc::trackable {
|
|||||||
std::string bus_name;
|
std::string bus_name;
|
||||||
std::string object_path;
|
std::string object_path;
|
||||||
|
|
||||||
int icon_size;
|
int icon_size;
|
||||||
int effective_icon_size;
|
int effective_icon_size;
|
||||||
Gtk::Image image;
|
Gtk::Image image;
|
||||||
Gtk::EventBox event_box;
|
Gtk::EventBox event_box;
|
||||||
std::string category;
|
std::string category;
|
||||||
std::string id;
|
std::string id;
|
||||||
|
|
||||||
std::string title;
|
std::string title;
|
||||||
std::string icon_name;
|
std::string icon_name;
|
||||||
Glib::RefPtr<Gdk::Pixbuf> icon_pixmap;
|
Glib::RefPtr<Gdk::Pixbuf> icon_pixmap;
|
||||||
Glib::RefPtr<Gtk::IconTheme> icon_theme;
|
Glib::RefPtr<Gtk::IconTheme> icon_theme;
|
||||||
std::string overlay_icon_name;
|
std::string overlay_icon_name;
|
||||||
std::string attention_icon_name;
|
std::string attention_icon_name;
|
||||||
std::string attention_movie_name;
|
std::string attention_movie_name;
|
||||||
std::string icon_theme_path;
|
std::string icon_theme_path;
|
||||||
std::string menu;
|
std::string menu;
|
||||||
ToolTip tooltip;
|
ToolTip tooltip;
|
||||||
DbusmenuGtkMenu* dbus_menu = nullptr;
|
DbusmenuGtkMenu* dbus_menu = nullptr;
|
||||||
Gtk::Menu* gtk_menu = nullptr;
|
Gtk::Menu* gtk_menu = nullptr;
|
||||||
/**
|
/**
|
||||||
* ItemIsMenu flag means that the item only supports the context menu.
|
* ItemIsMenu flag means that the item only supports the context menu.
|
||||||
* Default value is true because libappindicator supports neither ItemIsMenu nor Activate method
|
* Default value is true because libappindicator supports neither ItemIsMenu nor Activate method
|
||||||
@ -67,15 +67,15 @@ class Item : public sigc::trackable {
|
|||||||
void onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
|
void onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
|
||||||
const Glib::VariantContainerBase& arguments);
|
const Glib::VariantContainerBase& arguments);
|
||||||
|
|
||||||
void updateImage();
|
void updateImage();
|
||||||
Glib::RefPtr<Gdk::Pixbuf> extractPixBuf(GVariant* variant);
|
Glib::RefPtr<Gdk::Pixbuf> extractPixBuf(GVariant* variant);
|
||||||
Glib::RefPtr<Gdk::Pixbuf> getIconPixbuf();
|
Glib::RefPtr<Gdk::Pixbuf> getIconPixbuf();
|
||||||
Glib::RefPtr<Gdk::Pixbuf> getIconByName(const std::string& name, int size);
|
Glib::RefPtr<Gdk::Pixbuf> getIconByName(const std::string& name, int size);
|
||||||
double getScaledIconSize();
|
double getScaledIconSize();
|
||||||
static void onMenuDestroyed(Item* self, GObject* old_menu_pointer);
|
static void onMenuDestroyed(Item* self, GObject* old_menu_pointer);
|
||||||
void makeMenu();
|
void makeMenu();
|
||||||
bool handleClick(GdkEventButton* const& /*ev*/);
|
bool handleClick(GdkEventButton* const& /*ev*/);
|
||||||
bool handleScroll(GdkEventScroll* const&);
|
bool handleScroll(GdkEventScroll* const&);
|
||||||
|
|
||||||
// smooth scrolling threshold
|
// smooth scrolling threshold
|
||||||
gdouble scroll_threshold_ = 0;
|
gdouble scroll_threshold_ = 0;
|
||||||
@ -86,7 +86,7 @@ class Item : public sigc::trackable {
|
|||||||
|
|
||||||
Glib::RefPtr<Gio::DBus::Proxy> proxy_;
|
Glib::RefPtr<Gio::DBus::Proxy> proxy_;
|
||||||
Glib::RefPtr<Gio::Cancellable> cancellable_;
|
Glib::RefPtr<Gio::Cancellable> cancellable_;
|
||||||
std::set<std::string_view> update_pending_;
|
std::set<std::string_view> update_pending_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::SNI
|
} // namespace waybar::modules::SNI
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "modules/sni/host.hpp"
|
#include "modules/sni/host.hpp"
|
||||||
@ -20,9 +21,9 @@ class Tray : public AModule {
|
|||||||
void onRemove(std::unique_ptr<Item>& item);
|
void onRemove(std::unique_ptr<Item>& item);
|
||||||
|
|
||||||
static inline std::size_t nb_hosts_ = 0;
|
static inline std::size_t nb_hosts_ = 0;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
SNI::Watcher::singleton watcher_;
|
SNI::Watcher::singleton watcher_;
|
||||||
SNI::Host host_;
|
SNI::Host host_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::SNI
|
} // namespace waybar::modules::SNI
|
||||||
|
@ -30,26 +30,26 @@ class Watcher {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GfWatchType type;
|
GfWatchType type;
|
||||||
Watcher * watcher;
|
Watcher *watcher;
|
||||||
gchar * service;
|
gchar *service;
|
||||||
gchar * bus_name;
|
gchar *bus_name;
|
||||||
gchar * object_path;
|
gchar *object_path;
|
||||||
guint watch_id;
|
guint watch_id;
|
||||||
} GfWatch;
|
} GfWatch;
|
||||||
|
|
||||||
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection> &, Glib::ustring);
|
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection> &, Glib::ustring);
|
||||||
static gboolean handleRegisterHost(Watcher *, GDBusMethodInvocation *, const gchar *);
|
static gboolean handleRegisterHost(Watcher *, GDBusMethodInvocation *, const gchar *);
|
||||||
static gboolean handleRegisterItem(Watcher *, GDBusMethodInvocation *, const gchar *);
|
static gboolean handleRegisterItem(Watcher *, GDBusMethodInvocation *, const gchar *);
|
||||||
static GfWatch *gfWatchFind(GSList *list, const gchar *bus_name, const gchar *object_path);
|
static GfWatch *gfWatchFind(GSList *list, const gchar *bus_name, const gchar *object_path);
|
||||||
static GfWatch *gfWatchNew(GfWatchType, const gchar *, const gchar *, const gchar *, Watcher *);
|
static GfWatch *gfWatchNew(GfWatchType, const gchar *, const gchar *, const gchar *, Watcher *);
|
||||||
static void nameVanished(GDBusConnection *connection, const char *name, gpointer data);
|
static void nameVanished(GDBusConnection *connection, const char *name, gpointer data);
|
||||||
static void gfWatchFree(gpointer data);
|
static void gfWatchFree(gpointer data);
|
||||||
|
|
||||||
void updateRegisteredItems(SnWatcher *obj);
|
void updateRegisteredItems(SnWatcher *obj);
|
||||||
|
|
||||||
uint32_t bus_name_id_;
|
uint32_t bus_name_id_;
|
||||||
GSList * hosts_ = nullptr;
|
GSList *hosts_ = nullptr;
|
||||||
GSList * items_ = nullptr;
|
GSList *items_ = nullptr;
|
||||||
SnWatcher *watcher_ = nullptr;
|
SnWatcher *watcher_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <atomic>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "modules/sway/ipc/client.hpp"
|
#include "modules/sway/ipc/client.hpp"
|
||||||
@ -30,18 +31,28 @@ class BarIpcClient {
|
|||||||
private:
|
private:
|
||||||
void onInitialConfig(const struct Ipc::ipc_response& res);
|
void onInitialConfig(const struct Ipc::ipc_response& res);
|
||||||
void onIpcEvent(const struct Ipc::ipc_response&);
|
void onIpcEvent(const struct Ipc::ipc_response&);
|
||||||
|
void onCmd(const struct Ipc::ipc_response&);
|
||||||
void onConfigUpdate(const swaybar_config& config);
|
void onConfigUpdate(const swaybar_config& config);
|
||||||
void onVisibilityUpdate(bool visible_by_modifier);
|
void onVisibilityUpdate(bool visible_by_modifier);
|
||||||
|
void onModeUpdate(bool visible_by_modifier);
|
||||||
|
void onUrgencyUpdate(bool visible_by_urgency);
|
||||||
void update();
|
void update();
|
||||||
|
bool isModuleEnabled(std::string name);
|
||||||
|
|
||||||
Bar& bar_;
|
Bar& bar_;
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
Ipc ipc_;
|
Ipc ipc_;
|
||||||
|
|
||||||
swaybar_config bar_config_;
|
swaybar_config bar_config_;
|
||||||
bool visible_by_modifier_ = false;
|
std::string modifier_reset_;
|
||||||
|
bool visible_by_mode_ = false;
|
||||||
|
bool visible_by_modifier_ = false;
|
||||||
|
bool visible_by_urgency_ = false;
|
||||||
|
std::atomic<bool> modifier_no_action_ = false;
|
||||||
|
|
||||||
SafeSignal<bool> signal_visible_;
|
SafeSignal<bool> signal_mode_;
|
||||||
|
SafeSignal<bool> signal_visible_;
|
||||||
|
SafeSignal<bool> signal_urgency_;
|
||||||
SafeSignal<swaybar_config> signal_config_;
|
SafeSignal<swaybar_config> signal_config_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "ipc.hpp"
|
#include "ipc.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
@ -18,8 +20,8 @@ class Ipc {
|
|||||||
~Ipc();
|
~Ipc();
|
||||||
|
|
||||||
struct ipc_response {
|
struct ipc_response {
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
std::string payload;
|
std::string payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,16 +35,16 @@ class Ipc {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
static inline const std::string ipc_magic_ = "i3-ipc";
|
static inline const std::string ipc_magic_ = "i3-ipc";
|
||||||
static inline const size_t ipc_header_size_ = ipc_magic_.size() + 8;
|
static inline const size_t ipc_header_size_ = ipc_magic_.size() + 8;
|
||||||
|
|
||||||
const std::string getSocketPath() const;
|
const std::string getSocketPath() const;
|
||||||
int open(const std::string &) const;
|
int open(const std::string &) const;
|
||||||
struct ipc_response send(int fd, uint32_t type, const std::string &payload = "");
|
struct ipc_response send(int fd, uint32_t type, const std::string &payload = "");
|
||||||
struct ipc_response recv(int fd);
|
struct ipc_response recv(int fd);
|
||||||
|
|
||||||
int fd_;
|
int fd_;
|
||||||
int fd_event_;
|
int fd_event_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#define event_mask(ev) (1u << (ev & 0x7F))
|
#define event_mask(ev) (1u << (ev & 0x7F))
|
||||||
|
|
||||||
enum ipc_command_type {
|
enum ipc_command_type : uint32_t {
|
||||||
// i3 command types - see i3's I3_REPLY_TYPE constants
|
// i3 command types - see i3's I3_REPLY_TYPE constants
|
||||||
IPC_COMMAND = 0,
|
IPC_COMMAND = 0,
|
||||||
IPC_GET_WORKSPACES = 1,
|
IPC_GET_WORKSPACES = 1,
|
||||||
@ -21,16 +23,16 @@ enum ipc_command_type {
|
|||||||
IPC_GET_SEATS = 101,
|
IPC_GET_SEATS = 101,
|
||||||
|
|
||||||
// Events sent from sway to clients. Events have the highest bits set.
|
// Events sent from sway to clients. Events have the highest bits set.
|
||||||
IPC_EVENT_WORKSPACE = ((1 << 31) | 0),
|
IPC_EVENT_WORKSPACE = ((1U << 31) | 0),
|
||||||
IPC_EVENT_OUTPUT = ((1 << 31) | 1),
|
IPC_EVENT_OUTPUT = ((1U << 31) | 1),
|
||||||
IPC_EVENT_MODE = ((1 << 31) | 2),
|
IPC_EVENT_MODE = ((1U << 31) | 2),
|
||||||
IPC_EVENT_WINDOW = ((1 << 31) | 3),
|
IPC_EVENT_WINDOW = ((1U << 31) | 3),
|
||||||
IPC_EVENT_BARCONFIG_UPDATE = ((1 << 31) | 4),
|
IPC_EVENT_BARCONFIG_UPDATE = ((1U << 31) | 4),
|
||||||
IPC_EVENT_BINDING = ((1 << 31) | 5),
|
IPC_EVENT_BINDING = ((1U << 31) | 5),
|
||||||
IPC_EVENT_SHUTDOWN = ((1 << 31) | 6),
|
IPC_EVENT_SHUTDOWN = ((1U << 31) | 6),
|
||||||
IPC_EVENT_TICK = ((1 << 31) | 7),
|
IPC_EVENT_TICK = ((1U << 31) | 7),
|
||||||
|
|
||||||
// sway-specific event types
|
// sway-specific event types
|
||||||
IPC_EVENT_BAR_STATE_UPDATE = ((1<<31) | 20),
|
IPC_EVENT_BAR_STATE_UPDATE = ((1U << 31) | 20),
|
||||||
IPC_EVENT_INPUT = ((1<<31) | 21),
|
IPC_EVENT_INPUT = ((1U << 31) | 21),
|
||||||
};
|
};
|
||||||
|
@ -21,11 +21,7 @@ class Language : public ALabel, public sigc::trackable {
|
|||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class DispayedShortFlag {
|
enum class DispayedShortFlag { None = 0, ShortName = 1, ShortDescription = 1 << 1 };
|
||||||
None = 0,
|
|
||||||
ShortName = 1,
|
|
||||||
ShortDescription = 1 << 1
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Layout {
|
struct Layout {
|
||||||
std::string full_name;
|
std::string full_name;
|
||||||
@ -37,14 +33,15 @@ class Language : public ALabel, public sigc::trackable {
|
|||||||
|
|
||||||
class XKBContext {
|
class XKBContext {
|
||||||
public:
|
public:
|
||||||
XKBContext();
|
XKBContext();
|
||||||
~XKBContext();
|
~XKBContext();
|
||||||
auto next_layout() -> Layout*;
|
auto next_layout() -> Layout*;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rxkb_context* context_ = nullptr;
|
rxkb_context* context_ = nullptr;
|
||||||
rxkb_layout* xkb_layout_ = nullptr;
|
rxkb_layout* xkb_layout_ = nullptr;
|
||||||
Layout* layout_ = nullptr;
|
Layout* layout_ = nullptr;
|
||||||
std::map<std::string, rxkb_layout*> base_layouts_by_name_;
|
std::map<std::string, rxkb_layout*> base_layouts_by_name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
void onEvent(const struct Ipc::ipc_response&);
|
void onEvent(const struct Ipc::ipc_response&);
|
||||||
@ -56,15 +53,15 @@ class Language : public ALabel, public sigc::trackable {
|
|||||||
const static std::string XKB_LAYOUT_NAMES_KEY;
|
const static std::string XKB_LAYOUT_NAMES_KEY;
|
||||||
const static std::string XKB_ACTIVE_LAYOUT_NAME_KEY;
|
const static std::string XKB_ACTIVE_LAYOUT_NAME_KEY;
|
||||||
|
|
||||||
Layout layout_;
|
Layout layout_;
|
||||||
std::string tooltip_format_ = "";
|
std::string tooltip_format_ = "";
|
||||||
std::map<std::string, Layout> layouts_map_;
|
std::map<std::string, Layout> layouts_map_;
|
||||||
bool is_variant_displayed;
|
bool is_variant_displayed;
|
||||||
std::byte displayed_short_flag = static_cast<std::byte>(DispayedShortFlag::None);
|
std::byte displayed_short_flag = static_cast<std::byte>(DispayedShortFlag::None);
|
||||||
|
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
Ipc ipc_;
|
Ipc ipc_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::sway
|
} // namespace waybar::modules::sway
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
@ -18,10 +19,10 @@ class Mode : public ALabel, public sigc::trackable {
|
|||||||
private:
|
private:
|
||||||
void onEvent(const struct Ipc::ipc_response&);
|
void onEvent(const struct Ipc::ipc_response&);
|
||||||
|
|
||||||
std::string mode_;
|
std::string mode_;
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
Ipc ipc_;
|
Ipc ipc_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::sway
|
} // namespace waybar::modules::sway
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include "ALabel.hpp"
|
|
||||||
|
#include "AIconLabel.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
#include "modules/sway/ipc/client.hpp"
|
#include "modules/sway/ipc/client.hpp"
|
||||||
@ -10,29 +12,35 @@
|
|||||||
|
|
||||||
namespace waybar::modules::sway {
|
namespace waybar::modules::sway {
|
||||||
|
|
||||||
class Window : public ALabel, public sigc::trackable {
|
class Window : public AIconLabel, public sigc::trackable {
|
||||||
public:
|
public:
|
||||||
Window(const std::string&, const waybar::Bar&, const Json::Value&);
|
Window(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
~Window() = default;
|
~Window() = default;
|
||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onEvent(const struct Ipc::ipc_response&);
|
void onEvent(const struct Ipc::ipc_response&);
|
||||||
void onCmd(const struct Ipc::ipc_response&);
|
void onCmd(const struct Ipc::ipc_response&);
|
||||||
std::tuple<std::size_t, int, std::string, std::string> getFocusedNode(const Json::Value& nodes,
|
std::tuple<std::size_t, int, std::string, std::string, std::string> getFocusedNode(
|
||||||
std::string& output);
|
const Json::Value& nodes, std::string& output);
|
||||||
void getTree();
|
void getTree();
|
||||||
std::string rewriteTitle(const std::string& title);
|
std::string rewriteTitle(const std::string& title);
|
||||||
|
void updateAppIconName();
|
||||||
|
void updateAppIcon();
|
||||||
|
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
std::string window_;
|
std::string window_;
|
||||||
int windowId_;
|
int windowId_;
|
||||||
std::string app_id_;
|
std::string app_id_;
|
||||||
std::string old_app_id_;
|
std::string app_class_;
|
||||||
std::size_t app_nb_;
|
std::string old_app_id_;
|
||||||
|
std::size_t app_nb_;
|
||||||
|
unsigned app_icon_size_{24};
|
||||||
|
bool update_app_icon_{true};
|
||||||
|
std::string app_icon_name_;
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
Ipc ipc_;
|
Ipc ipc_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::sway
|
} // namespace waybar::modules::sway
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <gtkmm/button.h>
|
#include <gtkmm/button.h>
|
||||||
#include <gtkmm/label.h>
|
#include <gtkmm/label.h>
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
@ -24,25 +25,25 @@ class Workspaces : public AModule, public sigc::trackable {
|
|||||||
|
|
||||||
static int convertWorkspaceNameToNum(std::string name);
|
static int convertWorkspaceNameToNum(std::string name);
|
||||||
|
|
||||||
void onCmd(const struct Ipc::ipc_response&);
|
void onCmd(const struct Ipc::ipc_response&);
|
||||||
void onEvent(const struct Ipc::ipc_response&);
|
void onEvent(const struct Ipc::ipc_response&);
|
||||||
bool filterButtons();
|
bool filterButtons();
|
||||||
Gtk::Button& addButton(const Json::Value&);
|
Gtk::Button& addButton(const Json::Value&);
|
||||||
void onButtonReady(const Json::Value&, Gtk::Button&);
|
void onButtonReady(const Json::Value&, Gtk::Button&);
|
||||||
std::string getIcon(const std::string&, const Json::Value&);
|
std::string getIcon(const std::string&, const Json::Value&);
|
||||||
const std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const;
|
const std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const;
|
||||||
uint16_t getWorkspaceIndex(const std::string& name) const;
|
uint16_t getWorkspaceIndex(const std::string& name) const;
|
||||||
std::string trimWorkspaceName(std::string);
|
std::string trimWorkspaceName(std::string);
|
||||||
bool handleScroll(GdkEventScroll*);
|
bool handleScroll(GdkEventScroll*);
|
||||||
|
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
std::vector<Json::Value> workspaces_;
|
std::vector<Json::Value> workspaces_;
|
||||||
std::vector<std::string> workspaces_order_;
|
std::vector<std::string> workspaces_order_;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
std::unordered_map<std::string, Gtk::Button> buttons_;
|
std::unordered_map<std::string, Gtk::Button> buttons_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
Ipc ipc_;
|
Ipc ipc_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::sway
|
} // namespace waybar::modules::sway
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
@ -14,10 +16,10 @@ class Temperature : public ALabel {
|
|||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float getTemperature();
|
float getTemperature();
|
||||||
bool isCritical(uint16_t);
|
bool isCritical(uint16_t);
|
||||||
|
|
||||||
std::string file_path_;
|
std::string file_path_;
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
78
include/modules/upower/upower.hpp
Normal file
78
include/modules/upower/upower.hpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libupower-glib/upower.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "ALabel.hpp"
|
||||||
|
#include "glibconfig.h"
|
||||||
|
#include "gtkmm/box.h"
|
||||||
|
#include "gtkmm/image.h"
|
||||||
|
#include "gtkmm/label.h"
|
||||||
|
#include "modules/upower/upower_tooltip.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::upower {
|
||||||
|
|
||||||
|
class UPower : public AModule {
|
||||||
|
public:
|
||||||
|
UPower(const std::string &, const Json::Value &);
|
||||||
|
~UPower();
|
||||||
|
auto update() -> void;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::unordered_map<std::string, UpDevice *> Devices;
|
||||||
|
|
||||||
|
const std::string DEFAULT_FORMAT = "{percentage}";
|
||||||
|
const std::string DEFAULT_FORMAT_ALT = "{percentage} {time}";
|
||||||
|
|
||||||
|
static void deviceAdded_cb(UpClient *client, UpDevice *device, gpointer data);
|
||||||
|
static void deviceRemoved_cb(UpClient *client, const gchar *objectPath, gpointer data);
|
||||||
|
static void deviceNotify_cb(UpDevice *device, GParamSpec *pspec, gpointer user_data);
|
||||||
|
static void prepareForSleep_cb(GDBusConnection *system_bus, const gchar *sender_name,
|
||||||
|
const gchar *object_path, const gchar *interface_name,
|
||||||
|
const gchar *signal_name, GVariant *parameters,
|
||||||
|
gpointer user_data);
|
||||||
|
static void upowerAppear(GDBusConnection *conn, const gchar *name, const gchar *name_owner,
|
||||||
|
gpointer data);
|
||||||
|
static void upowerDisappear(GDBusConnection *connection, const gchar *name, gpointer user_data);
|
||||||
|
|
||||||
|
void removeDevice(const gchar *objectPath);
|
||||||
|
void addDevice(UpDevice *device);
|
||||||
|
void setDisplayDevice();
|
||||||
|
void resetDevices();
|
||||||
|
void removeDevices();
|
||||||
|
bool show_tooltip_callback(int, int, bool, const Glib::RefPtr<Gtk::Tooltip> &tooltip);
|
||||||
|
bool handleToggle(GdkEventButton *const &);
|
||||||
|
std::string timeToString(gint64 time);
|
||||||
|
|
||||||
|
const std::string getDeviceStatus(UpDeviceState &state);
|
||||||
|
|
||||||
|
Gtk::Box box_;
|
||||||
|
Gtk::Image icon_;
|
||||||
|
Gtk::Label label_;
|
||||||
|
|
||||||
|
// Config
|
||||||
|
bool hideIfEmpty = true;
|
||||||
|
bool tooltip_enabled = true;
|
||||||
|
uint tooltip_spacing = 4;
|
||||||
|
uint tooltip_padding = 4;
|
||||||
|
uint iconSize = 20;
|
||||||
|
std::string format = DEFAULT_FORMAT;
|
||||||
|
std::string format_alt = DEFAULT_FORMAT_ALT;
|
||||||
|
|
||||||
|
Devices devices;
|
||||||
|
std::mutex m_Mutex;
|
||||||
|
UpClient *client;
|
||||||
|
UpDevice *displayDevice;
|
||||||
|
guint login1_id;
|
||||||
|
GDBusConnection *login1_connection;
|
||||||
|
UPowerTooltip *upower_tooltip;
|
||||||
|
std::string lastStatus;
|
||||||
|
bool showAltText;
|
||||||
|
bool upowerRunning;
|
||||||
|
guint upowerWatcher_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::upower
|
30
include/modules/upower/upower_tooltip.hpp
Normal file
30
include/modules/upower/upower_tooltip.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libupower-glib/upower.h>
|
||||||
|
|
||||||
|
#include "gtkmm/box.h"
|
||||||
|
#include "gtkmm/label.h"
|
||||||
|
#include "gtkmm/window.h"
|
||||||
|
|
||||||
|
namespace waybar::modules::upower {
|
||||||
|
|
||||||
|
class UPowerTooltip : public Gtk::Window {
|
||||||
|
private:
|
||||||
|
typedef std::unordered_map<std::string, UpDevice*> Devices;
|
||||||
|
|
||||||
|
const std::string getDeviceIcon(UpDeviceKind& kind);
|
||||||
|
|
||||||
|
Gtk::Box* contentBox;
|
||||||
|
|
||||||
|
uint iconSize;
|
||||||
|
uint tooltipSpacing;
|
||||||
|
uint tooltipPadding;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPowerTooltip(uint iconSize, uint tooltipSpacing, uint tooltipPadding);
|
||||||
|
~UPowerTooltip();
|
||||||
|
|
||||||
|
uint updateTooltip(Devices& devices);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::upower
|
@ -1,174 +1,168 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
#include <glibmm/refptr.h>
|
||||||
|
#include <gtkmm/box.h>
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <gtkmm/icontheme.h>
|
||||||
|
#include <gtkmm/image.h>
|
||||||
|
#include <gtkmm/label.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
#include "giomm/desktopappinfo.h"
|
#include "giomm/desktopappinfo.h"
|
||||||
#include "util/json.hpp"
|
#include "util/json.hpp"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#include <gdk/gdk.h>
|
|
||||||
|
|
||||||
#include <glibmm/refptr.h>
|
|
||||||
|
|
||||||
#include <gtkmm/box.h>
|
|
||||||
#include <gtkmm/button.h>
|
|
||||||
#include <gtkmm/image.h>
|
|
||||||
#include <gtkmm/label.h>
|
|
||||||
#include <gtkmm/icontheme.h>
|
|
||||||
|
|
||||||
#include <wayland-client.h>
|
|
||||||
#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
|
#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
|
|
||||||
namespace waybar::modules::wlr {
|
namespace waybar::modules::wlr {
|
||||||
|
|
||||||
class Taskbar;
|
class Taskbar;
|
||||||
|
|
||||||
class Task
|
class Task {
|
||||||
{
|
public:
|
||||||
public:
|
Task(const waybar::Bar &, const Json::Value &, Taskbar *,
|
||||||
Task(const waybar::Bar&, const Json::Value&, Taskbar*,
|
struct zwlr_foreign_toplevel_handle_v1 *, struct wl_seat *);
|
||||||
struct zwlr_foreign_toplevel_handle_v1 *, struct wl_seat*);
|
~Task();
|
||||||
~Task();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum State {
|
enum State {
|
||||||
MAXIMIZED = (1 << 0),
|
MAXIMIZED = (1 << 0),
|
||||||
MINIMIZED = (1 << 1),
|
MINIMIZED = (1 << 1),
|
||||||
ACTIVE = (1 << 2),
|
ACTIVE = (1 << 2),
|
||||||
FULLSCREEN = (1 << 3),
|
FULLSCREEN = (1 << 3),
|
||||||
INVALID = (1 << 4)
|
INVALID = (1 << 4)
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uint32_t global_id;
|
static uint32_t global_id;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const waybar::Bar &bar_;
|
const waybar::Bar &bar_;
|
||||||
const Json::Value &config_;
|
const Json::Value &config_;
|
||||||
Taskbar *tbar_;
|
Taskbar *tbar_;
|
||||||
struct zwlr_foreign_toplevel_handle_v1 *handle_;
|
struct zwlr_foreign_toplevel_handle_v1 *handle_;
|
||||||
struct wl_seat *seat_;
|
struct wl_seat *seat_;
|
||||||
|
|
||||||
uint32_t id_;
|
uint32_t id_;
|
||||||
|
|
||||||
Gtk::Button button_;
|
Gtk::Button button_;
|
||||||
Gtk::Box content_;
|
Gtk::Box content_;
|
||||||
Gtk::Image icon_;
|
Gtk::Image icon_;
|
||||||
Gtk::Label text_before_;
|
Gtk::Label text_before_;
|
||||||
Gtk::Label text_after_;
|
Gtk::Label text_after_;
|
||||||
Glib::RefPtr<Gio::DesktopAppInfo> app_info_;
|
Glib::RefPtr<Gio::DesktopAppInfo> app_info_;
|
||||||
bool button_visible_ = false;
|
bool button_visible_ = false;
|
||||||
bool ignored_ = false;
|
bool ignored_ = false;
|
||||||
|
|
||||||
bool with_icon_ = false;
|
bool with_icon_ = false;
|
||||||
bool with_name_ = false;
|
bool with_name_ = false;
|
||||||
std::string format_before_;
|
std::string format_before_;
|
||||||
std::string format_after_;
|
std::string format_after_;
|
||||||
|
|
||||||
std::string format_tooltip_;
|
std::string format_tooltip_;
|
||||||
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
std::string title_;
|
std::string title_;
|
||||||
std::string app_id_;
|
std::string app_id_;
|
||||||
uint32_t state_ = 0;
|
uint32_t state_ = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string repr() const;
|
std::string repr() const;
|
||||||
std::string state_string(bool = false) const;
|
std::string state_string(bool = false) const;
|
||||||
void set_app_info_from_app_id_list(const std::string& app_id_list);
|
void set_app_info_from_app_id_list(const std::string &app_id_list);
|
||||||
bool image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme>& icon_theme, Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
|
bool image_load_icon(Gtk::Image &image, const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
|
||||||
void hide_if_ignored();
|
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
|
||||||
|
void hide_if_ignored();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Getter functions */
|
/* Getter functions */
|
||||||
uint32_t id() const { return id_; }
|
uint32_t id() const { return id_; }
|
||||||
std::string title() const { return title_; }
|
std::string title() const { return title_; }
|
||||||
std::string app_id() const { return app_id_; }
|
std::string app_id() const { return app_id_; }
|
||||||
uint32_t state() const { return state_; }
|
uint32_t state() const { return state_; }
|
||||||
bool maximized() const { return state_ & MAXIMIZED; }
|
bool maximized() const { return state_ & MAXIMIZED; }
|
||||||
bool minimized() const { return state_ & MINIMIZED; }
|
bool minimized() const { return state_ & MINIMIZED; }
|
||||||
bool active() const { return state_ & ACTIVE; }
|
bool active() const { return state_ & ACTIVE; }
|
||||||
bool fullscreen() const { return state_ & FULLSCREEN; }
|
bool fullscreen() const { return state_ & FULLSCREEN; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Callbacks for the wlr protocol */
|
/* Callbacks for the wlr protocol */
|
||||||
void handle_title(const char *);
|
void handle_title(const char *);
|
||||||
void handle_app_id(const char *);
|
void handle_app_id(const char *);
|
||||||
void handle_output_enter(struct wl_output *);
|
void handle_output_enter(struct wl_output *);
|
||||||
void handle_output_leave(struct wl_output *);
|
void handle_output_leave(struct wl_output *);
|
||||||
void handle_state(struct wl_array *);
|
void handle_state(struct wl_array *);
|
||||||
void handle_done();
|
void handle_done();
|
||||||
void handle_closed();
|
void handle_closed();
|
||||||
|
|
||||||
/* Callbacks for Gtk events */
|
/* Callbacks for Gtk events */
|
||||||
bool handle_clicked(GdkEventButton *);
|
bool handle_clicked(GdkEventButton *);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool operator==(const Task&) const;
|
bool operator==(const Task &) const;
|
||||||
bool operator!=(const Task&) const;
|
bool operator!=(const Task &) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Interaction with the tasks */
|
/* Interaction with the tasks */
|
||||||
void maximize(bool);
|
void maximize(bool);
|
||||||
void minimize(bool);
|
void minimize(bool);
|
||||||
void activate();
|
void activate();
|
||||||
void fullscreen(bool);
|
void fullscreen(bool);
|
||||||
void close();
|
void close();
|
||||||
};
|
};
|
||||||
|
|
||||||
using TaskPtr = std::unique_ptr<Task>;
|
using TaskPtr = std::unique_ptr<Task>;
|
||||||
|
|
||||||
|
class Taskbar : public waybar::AModule {
|
||||||
|
public:
|
||||||
|
Taskbar(const std::string &, const waybar::Bar &, const Json::Value &);
|
||||||
|
~Taskbar();
|
||||||
|
void update();
|
||||||
|
|
||||||
class Taskbar : public waybar::AModule
|
private:
|
||||||
{
|
const waybar::Bar &bar_;
|
||||||
public:
|
Gtk::Box box_;
|
||||||
Taskbar(const std::string&, const waybar::Bar&, const Json::Value&);
|
std::vector<TaskPtr> tasks_;
|
||||||
~Taskbar();
|
|
||||||
void update();
|
|
||||||
|
|
||||||
private:
|
std::vector<Glib::RefPtr<Gtk::IconTheme>> icon_themes_;
|
||||||
const waybar::Bar &bar_;
|
std::unordered_set<std::string> ignore_list_;
|
||||||
Gtk::Box box_;
|
std::map<std::string, std::string> app_ids_replace_map_;
|
||||||
std::vector<TaskPtr> tasks_;
|
|
||||||
|
|
||||||
std::vector<Glib::RefPtr<Gtk::IconTheme>> icon_themes_;
|
struct zwlr_foreign_toplevel_manager_v1 *manager_;
|
||||||
std::unordered_set<std::string> ignore_list_;
|
struct wl_seat *seat_;
|
||||||
std::map<std::string, std::string> app_ids_replace_map_;
|
|
||||||
|
|
||||||
struct zwlr_foreign_toplevel_manager_v1 *manager_;
|
public:
|
||||||
struct wl_seat *seat_;
|
/* Callbacks for global registration */
|
||||||
|
void register_manager(struct wl_registry *, uint32_t name, uint32_t version);
|
||||||
|
void register_seat(struct wl_registry *, uint32_t name, uint32_t version);
|
||||||
|
|
||||||
public:
|
/* Callbacks for the wlr protocol */
|
||||||
/* Callbacks for global registration */
|
void handle_toplevel_create(struct zwlr_foreign_toplevel_handle_v1 *);
|
||||||
void register_manager(struct wl_registry*, uint32_t name, uint32_t version);
|
void handle_finished();
|
||||||
void register_seat(struct wl_registry*, uint32_t name, uint32_t version);
|
|
||||||
|
|
||||||
/* Callbacks for the wlr protocol */
|
public:
|
||||||
void handle_toplevel_create(struct zwlr_foreign_toplevel_handle_v1 *);
|
void add_button(Gtk::Button &);
|
||||||
void handle_finished();
|
void move_button(Gtk::Button &, int);
|
||||||
|
void remove_button(Gtk::Button &);
|
||||||
|
void remove_task(uint32_t);
|
||||||
|
|
||||||
public:
|
bool show_output(struct wl_output *) const;
|
||||||
void add_button(Gtk::Button &);
|
bool all_outputs() const;
|
||||||
void move_button(Gtk::Button &, int);
|
|
||||||
void remove_button(Gtk::Button &);
|
|
||||||
void remove_task(uint32_t);
|
|
||||||
|
|
||||||
bool show_output(struct wl_output *) const;
|
const std::vector<Glib::RefPtr<Gtk::IconTheme>> &icon_themes() const;
|
||||||
bool all_outputs() const;
|
const std::unordered_set<std::string> &ignore_list() const;
|
||||||
|
const std::map<std::string, std::string> &app_ids_replace_map() const;
|
||||||
const std::vector<Glib::RefPtr<Gtk::IconTheme>>& icon_themes() const;
|
|
||||||
const std::unordered_set<std::string>& ignore_list() const;
|
|
||||||
const std::map<std::string, std::string>& app_ids_replace_map() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace waybar::modules::wlr */
|
} /* namespace waybar::modules::wlr */
|
||||||
|
@ -53,24 +53,24 @@ class Workspace {
|
|||||||
private:
|
private:
|
||||||
auto get_icon() -> std::string;
|
auto get_icon() -> std::string;
|
||||||
|
|
||||||
const Bar &bar_;
|
const Bar &bar_;
|
||||||
const Json::Value &config_;
|
const Json::Value &config_;
|
||||||
WorkspaceGroup &workspace_group_;
|
WorkspaceGroup &workspace_group_;
|
||||||
|
|
||||||
// wlr stuff
|
// wlr stuff
|
||||||
zext_workspace_handle_v1 *workspace_handle_;
|
zext_workspace_handle_v1 *workspace_handle_;
|
||||||
uint32_t state_ = 0;
|
uint32_t state_ = 0;
|
||||||
|
|
||||||
uint32_t id_;
|
uint32_t id_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
std::vector<uint32_t> coordinates_;
|
std::vector<uint32_t> coordinates_;
|
||||||
static std::map<std::string, std::string> icons_map_;
|
static std::map<std::string, std::string> icons_map_;
|
||||||
std::string format_;
|
std::string format_;
|
||||||
bool with_icon_ = false;
|
bool with_icon_ = false;
|
||||||
|
|
||||||
Gtk::Button button_;
|
Gtk::Button button_;
|
||||||
Gtk::Box content_;
|
Gtk::Box content_;
|
||||||
Gtk::Label label_;
|
Gtk::Label label_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorkspaceGroup {
|
class WorkspaceGroup {
|
||||||
@ -102,19 +102,19 @@ class WorkspaceGroup {
|
|||||||
auto commit() -> void;
|
auto commit() -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uint32_t workspace_global_id;
|
static uint32_t workspace_global_id;
|
||||||
const waybar::Bar &bar_;
|
const waybar::Bar &bar_;
|
||||||
Gtk::Box &box_;
|
Gtk::Box &box_;
|
||||||
const Json::Value &config_;
|
const Json::Value &config_;
|
||||||
WorkspaceManager &workspace_manager_;
|
WorkspaceManager &workspace_manager_;
|
||||||
|
|
||||||
// wlr stuff
|
// wlr stuff
|
||||||
zext_workspace_group_handle_v1 *workspace_group_handle_;
|
zext_workspace_group_handle_v1 *workspace_group_handle_;
|
||||||
wl_output *output_ = nullptr;
|
wl_output *output_ = nullptr;
|
||||||
|
|
||||||
uint32_t id_;
|
uint32_t id_;
|
||||||
std::vector<std::unique_ptr<Workspace>> workspaces_;
|
std::vector<std::unique_ptr<Workspace>> workspaces_;
|
||||||
bool need_to_sort = false;
|
bool need_to_sort = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorkspaceManager : public AModule {
|
class WorkspaceManager : public AModule {
|
||||||
@ -141,8 +141,8 @@ class WorkspaceManager : public AModule {
|
|||||||
auto commit() -> void;
|
auto commit() -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const waybar::Bar &bar_;
|
const waybar::Bar &bar_;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
|
std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
|
||||||
|
|
||||||
// wlr stuff
|
// wlr stuff
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#include "ext-workspace-unstable-v1-client-protocol.h"
|
#include "ext-workspace-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
namespace waybar::modules::wlr {
|
namespace waybar::modules::wlr {
|
||||||
void add_registry_listener(void *data);
|
void add_registry_listener(void *data);
|
||||||
void add_workspace_listener(zext_workspace_handle_v1 *workspace_handle, void *data);
|
void add_workspace_listener(zext_workspace_handle_v1 *workspace_handle, void *data);
|
||||||
void add_workspace_group_listener(zext_workspace_group_handle_v1 *workspace_group_handle, void *data);
|
void add_workspace_group_listener(zext_workspace_group_handle_v1 *workspace_group_handle,
|
||||||
zext_workspace_manager_v1* workspace_manager_bind(wl_registry *registry, uint32_t name, uint32_t version, void *data);
|
void *data);
|
||||||
}
|
zext_workspace_manager_v1 *workspace_manager_bind(wl_registry *registry, uint32_t name,
|
||||||
|
uint32_t version, void *data);
|
||||||
|
} // namespace waybar::modules::wlr
|
||||||
|
@ -64,10 +64,10 @@ struct SafeSignal : sigc::signal<void(std::decay_t<Args>...)> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Glib::Dispatcher dp_;
|
Glib::Dispatcher dp_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
std::queue<arg_tuple_t> queue_;
|
std::queue<arg_tuple_t> queue_;
|
||||||
const std::thread::id main_tid_ = std::this_thread::get_id();
|
const std::thread::id main_tid_ = std::this_thread::get_id();
|
||||||
// cache functor for signal emission to avoid recreating it on each event
|
// cache functor for signal emission to avoid recreating it on each event
|
||||||
const slot_t cached_fn_ = make_slot();
|
const slot_t cached_fn_ = make_slot();
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,13 +20,13 @@ extern std::list<pid_t> reap;
|
|||||||
namespace waybar::util::command {
|
namespace waybar::util::command {
|
||||||
|
|
||||||
struct res {
|
struct res {
|
||||||
int exit_code;
|
int exit_code;
|
||||||
std::string out;
|
std::string out;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::string read(FILE* fp) {
|
inline std::string read(FILE* fp) {
|
||||||
std::array<char, 128> buffer = {0};
|
std::array<char, 128> buffer = {0};
|
||||||
std::string output;
|
std::string output;
|
||||||
while (feof(fp) == 0) {
|
while (feof(fp) == 0) {
|
||||||
if (fgets(buffer.data(), 128, fp) != nullptr) {
|
if (fgets(buffer.data(), 128, fp) != nullptr) {
|
||||||
output += buffer.data();
|
output += buffer.data();
|
||||||
@ -68,7 +68,10 @@ inline int close(FILE* fp, pid_t pid) {
|
|||||||
inline FILE* open(const std::string& cmd, int& pid) {
|
inline FILE* open(const std::string& cmd, int& pid) {
|
||||||
if (cmd == "") return nullptr;
|
if (cmd == "") return nullptr;
|
||||||
int fd[2];
|
int fd[2];
|
||||||
pipe(fd);
|
if (pipe(fd) != 0) {
|
||||||
|
spdlog::error("Unable to pipe fd");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
pid_t child_pid = fork();
|
pid_t child_pid = fork();
|
||||||
|
|
||||||
@ -109,7 +112,7 @@ inline FILE* open(const std::string& cmd, int& pid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline struct res exec(const std::string& cmd) {
|
inline struct res exec(const std::string& cmd) {
|
||||||
int pid;
|
int pid;
|
||||||
auto fp = command::open(cmd, pid);
|
auto fp = command::open(cmd, pid);
|
||||||
if (!fp) return {-1, ""};
|
if (!fp) return {-1, ""};
|
||||||
auto output = command::read(fp);
|
auto output = command::read(fp);
|
||||||
@ -118,7 +121,7 @@ inline struct res exec(const std::string& cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline struct res execNoRead(const std::string& cmd) {
|
inline struct res execNoRead(const std::string& cmd) {
|
||||||
int pid;
|
int pid;
|
||||||
auto fp = command::open(cmd, pid);
|
auto fp = command::open(cmd, pid);
|
||||||
if (!fp) return {-1, ""};
|
if (!fp) return {-1, ""};
|
||||||
auto stat = command::close(fp, pid);
|
auto stat = command::close(fp, pid);
|
||||||
|
@ -1,88 +1,97 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
#include <glibmm/ustring.h>
|
||||||
|
|
||||||
class pow_format {
|
class pow_format {
|
||||||
public:
|
public:
|
||||||
pow_format(long long val, std::string&& unit, bool binary = false):
|
pow_format(long long val, std::string&& unit, bool binary = false)
|
||||||
val_(val), unit_(unit), binary_(binary) { };
|
: val_(val), unit_(unit), binary_(binary){};
|
||||||
|
|
||||||
long long val_;
|
long long val_;
|
||||||
std::string unit_;
|
std::string unit_;
|
||||||
bool binary_;
|
bool binary_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
namespace fmt {
|
namespace fmt {
|
||||||
template <>
|
template <>
|
||||||
struct formatter<pow_format> {
|
struct formatter<pow_format> {
|
||||||
char spec = 0;
|
char spec = 0;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
|
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
constexpr auto parse(ParseContext& ctx) -> decltype (ctx.begin()) {
|
constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||||
auto it = ctx.begin(), end = ctx.end();
|
auto it = ctx.begin(), end = ctx.end();
|
||||||
if (it != end && *it == ':') ++it;
|
if (it != end && *it == ':') ++it;
|
||||||
if (it && (*it == '>' || *it == '<' || *it == '=')) {
|
if (it && (*it == '>' || *it == '<' || *it == '=')) {
|
||||||
spec = *it;
|
spec = *it;
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
if (it == end || *it == '}') return it;
|
if (it == end || *it == '}') return it;
|
||||||
if ('0' <= *it && *it <= '9') {
|
if ('0' <= *it && *it <= '9') {
|
||||||
// We ignore it for now, but keep it for compatibility with
|
// We ignore it for now, but keep it for compatibility with
|
||||||
// existing configs where the format for pow_format'ed numbers was
|
// existing configs where the format for pow_format'ed numbers was
|
||||||
// 'string' and specifications such as {:>9} were valid.
|
// 'string' and specifications such as {:>9} were valid.
|
||||||
// The rationale for ignoring it is that the only reason to specify
|
// The rationale for ignoring it is that the only reason to specify
|
||||||
// an alignment and a with is to get a fixed width bar, and ">" is
|
// an alignment and a with is to get a fixed width bar, and ">" is
|
||||||
// sufficient in this implementation.
|
// sufficient in this implementation.
|
||||||
#if FMT_VERSION < 80000
|
#if FMT_VERSION < 80000
|
||||||
width = parse_nonnegative_int(it, end, ctx);
|
width = parse_nonnegative_int(it, end, ctx);
|
||||||
#else
|
#else
|
||||||
width = detail::parse_nonnegative_int(it, end, -1);
|
width = detail::parse_nonnegative_int(it, end, -1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class FormatContext>
|
template <class FormatContext>
|
||||||
auto format(const pow_format& s, FormatContext &ctx) -> decltype (ctx.out()) {
|
auto format(const pow_format& s, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||||
const char* units[] = { "", "k", "M", "G", "T", "P", nullptr};
|
const char* units[] = {"", "k", "M", "G", "T", "P", nullptr};
|
||||||
|
|
||||||
auto base = s.binary_ ? 1024ull : 1000ll;
|
auto base = s.binary_ ? 1024ull : 1000ll;
|
||||||
auto fraction = (double) s.val_;
|
auto fraction = (double)s.val_;
|
||||||
|
|
||||||
int pow;
|
int pow;
|
||||||
for (pow = 0; units[pow+1] != nullptr && fraction / base >= 1; ++pow) {
|
for (pow = 0; units[pow + 1] != nullptr && fraction / base >= 1; ++pow) {
|
||||||
fraction /= base;
|
fraction /= base;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto max_width = 4 // coeff in {:.3g} format
|
auto max_width = 4 // coeff in {:.3g} format
|
||||||
+ 1 // prefix from units array
|
+ 1 // prefix from units array
|
||||||
+ s.binary_ // for the 'i' in GiB.
|
+ s.binary_ // for the 'i' in GiB.
|
||||||
+ s.unit_.length();
|
+ s.unit_.length();
|
||||||
|
|
||||||
const char * format;
|
const char* format;
|
||||||
std::string string;
|
std::string string;
|
||||||
switch (spec) {
|
switch (spec) {
|
||||||
case '>':
|
case '>':
|
||||||
return format_to(ctx.out(), "{:>{}}", fmt::format("{}", s), max_width);
|
return format_to(ctx.out(), "{:>{}}", fmt::format("{}", s), max_width);
|
||||||
case '<':
|
case '<':
|
||||||
return format_to(ctx.out(), "{:<{}}", fmt::format("{}", s), max_width);
|
return format_to(ctx.out(), "{:<{}}", fmt::format("{}", s), max_width);
|
||||||
case '=':
|
case '=':
|
||||||
format = "{coefficient:<4.3g}{padding}{prefix}{unit}";
|
format = "{coefficient:<4.3g}{padding}{prefix}{unit}";
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
default:
|
||||||
format = "{coefficient:.3g}{prefix}{unit}";
|
format = "{coefficient:.3g}{prefix}{unit}";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return format_to(ctx.out(), format
|
return format_to(
|
||||||
, fmt::arg("coefficient", fraction)
|
ctx.out(), format, fmt::arg("coefficient", fraction),
|
||||||
, fmt::arg("prefix", std::string() + units[pow] + ((s.binary_ && pow) ? "i" : ""))
|
fmt::arg("prefix", std::string() + units[pow] + ((s.binary_ && pow) ? "i" : "")),
|
||||||
, fmt::arg("unit", s.unit_)
|
fmt::arg("unit", s.unit_),
|
||||||
, fmt::arg("padding", pow ? "" : s.binary_ ? " " : " ")
|
fmt::arg("padding", pow ? ""
|
||||||
);
|
: s.binary_ ? " "
|
||||||
}
|
: " "));
|
||||||
};
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// Glib ustirng support
|
||||||
|
template <>
|
||||||
|
struct formatter<Glib::ustring> : formatter<std::string> {
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(const Glib::ustring& value, FormatContext& ctx) {
|
||||||
|
return formatter<std::string>::format(value, ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace fmt
|
||||||
|
@ -13,7 +13,7 @@ struct JsonParser {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
std::unique_ptr<Json::CharReader> const reader(builder_.newCharReader());
|
std::unique_ptr<Json::CharReader> const reader(builder_.newCharReader());
|
||||||
std::string err;
|
std::string err;
|
||||||
bool res = reader->parse(data.c_str(), data.c_str() + data.size(), &root, &err);
|
bool res = reader->parse(data.c_str(), data.c_str() + data.size(), &root, &err);
|
||||||
if (!res) throw std::runtime_error(err);
|
if (!res) throw std::runtime_error(err);
|
||||||
return root;
|
return root;
|
||||||
|
@ -17,8 +17,8 @@ class Rfkill : public sigc::trackable {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
enum rfkill_type rfkill_type_;
|
enum rfkill_type rfkill_type_;
|
||||||
bool state_ = false;
|
bool state_ = false;
|
||||||
int fd_ = -1;
|
int fd_ = -1;
|
||||||
|
|
||||||
bool on_event(Glib::IOCondition cond);
|
bool on_event(Glib::IOCondition cond);
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,8 @@ namespace waybar::util {
|
|||||||
*/
|
*/
|
||||||
class CancellationGuard {
|
class CancellationGuard {
|
||||||
int oldstate;
|
int oldstate;
|
||||||
public:
|
|
||||||
|
public:
|
||||||
CancellationGuard() { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); }
|
CancellationGuard() { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); }
|
||||||
~CancellationGuard() { pthread_setcancelstate(oldstate, &oldstate); }
|
~CancellationGuard() { pthread_setcancelstate(oldstate, &oldstate); }
|
||||||
};
|
};
|
||||||
@ -47,7 +48,7 @@ class SleeperThread {
|
|||||||
bool isRunning() const { return do_run_; }
|
bool isRunning() const { return do_run_; }
|
||||||
|
|
||||||
auto sleep_for(std::chrono::system_clock::duration dur) {
|
auto sleep_for(std::chrono::system_clock::duration dur) {
|
||||||
std::unique_lock lk(mutex_);
|
std::unique_lock lk(mutex_);
|
||||||
CancellationGuard cancel_lock;
|
CancellationGuard cancel_lock;
|
||||||
return condvar_.wait_for(lk, dur, [this] { return signal_ || !do_run_; });
|
return condvar_.wait_for(lk, dur, [this] { return signal_ || !do_run_; });
|
||||||
}
|
}
|
||||||
@ -55,7 +56,7 @@ class SleeperThread {
|
|||||||
auto sleep_until(
|
auto sleep_until(
|
||||||
std::chrono::time_point<std::chrono::system_clock, std::chrono::system_clock::duration>
|
std::chrono::time_point<std::chrono::system_clock, std::chrono::system_clock::duration>
|
||||||
time_point) {
|
time_point) {
|
||||||
std::unique_lock lk(mutex_);
|
std::unique_lock lk(mutex_);
|
||||||
CancellationGuard cancel_lock;
|
CancellationGuard cancel_lock;
|
||||||
return condvar_.wait_until(lk, time_point, [this] { return signal_ || !do_run_; });
|
return condvar_.wait_until(lk, time_point, [this] { return signal_ || !do_run_; });
|
||||||
}
|
}
|
||||||
@ -90,11 +91,11 @@ class SleeperThread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::thread thread_;
|
std::thread thread_;
|
||||||
std::condition_variable condvar_;
|
std::condition_variable condvar_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
bool do_run_ = true;
|
bool do_run_ = true;
|
||||||
bool signal_ = false;
|
bool signal_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::util
|
} // namespace waybar::util
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
const std::string WHITESPACE = " \n\r\t\f\v";
|
const std::string WHITESPACE = " \n\r\t\f\v";
|
||||||
|
|
||||||
std::string ltrim(const std::string s) {
|
inline std::string ltrim(const std::string& s) {
|
||||||
size_t begin = s.find_first_not_of(WHITESPACE);
|
size_t begin = s.find_first_not_of(WHITESPACE);
|
||||||
return (begin == std::string::npos) ? "" : s.substr(begin);
|
return (begin == std::string::npos) ? "" : s.substr(begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string rtrim(const std::string s) {
|
inline std::string rtrim(const std::string& s) {
|
||||||
size_t end = s.find_last_not_of(WHITESPACE);
|
size_t end = s.find_last_not_of(WHITESPACE);
|
||||||
return (end == std::string::npos) ? "" : s.substr(0, end + 1);
|
return (end == std::string::npos) ? "" : s.substr(0, end + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string trim(const std::string& s) { return rtrim(ltrim(s)); }
|
inline std::string trim(const std::string& s) { return rtrim(ltrim(s)); }
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
namespace waybar {
|
namespace waybar {
|
||||||
|
|
||||||
struct waybar_time {
|
struct waybar_time {
|
||||||
std::locale locale;
|
std::locale locale;
|
||||||
date::zoned_seconds ztime;
|
date::zoned_seconds ztime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,21 +6,41 @@ waybar - bluetooth module
|
|||||||
|
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
|
|
||||||
The *bluetooth* module displays information about the status of the device's bluetooth device.
|
The *bluetooth* module displays information about a bluetooth controller and its connections.
|
||||||
|
|
||||||
# CONFIGURATION
|
# CONFIGURATION
|
||||||
|
|
||||||
Addressed by *bluetooth*
|
Addressed by *bluetooth*
|
||||||
|
|
||||||
|
*controller*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Use the controller with the defined alias. Otherwise a random controller is used. Recommended to define when there is more than 1 controller available to the system.
|
||||||
|
|
||||||
|
*format-device-preference*: ++
|
||||||
|
typeof: array ++
|
||||||
|
A ranking of bluetooth devices, addressed by their alias. The order is from *first displayed* to *last displayed*. ++
|
||||||
|
If this config option is not defined or none of the devices in the list are connected, it will fall back to showing the last connected device.
|
||||||
|
|
||||||
*format*: ++
|
*format*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
default: *{icon}* ++
|
default: * {status}* ++
|
||||||
The format, how information should be displayed. This format is used when other formats aren't specified.
|
The format, how information should be displayed. This format is used when other formats aren't specified.
|
||||||
|
|
||||||
*format-icons*: ++
|
*format-disabled*: ++
|
||||||
typeof: array/object ++
|
typeof: string ++
|
||||||
Based on the device status, the corresponding icon gets selected. ++
|
This format is used when the displayed controller is disabled.
|
||||||
The order is *low* to *high*. Or by the state if it is an object.
|
|
||||||
|
*format-off*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used when the displayed controller is turned off.
|
||||||
|
|
||||||
|
*format-on*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used when the displayed controller is turned on with no devices connected.
|
||||||
|
|
||||||
|
*format-connected*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used when the displayed controller is connected to at least 1 device.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
@ -71,26 +91,104 @@ Addressed by *bluetooth*
|
|||||||
typeof: string ++
|
typeof: string ++
|
||||||
The format, how information should be displayed in the tooltip. This format is used when other formats aren't specified.
|
The format, how information should be displayed in the tooltip. This format is used when other formats aren't specified.
|
||||||
|
|
||||||
|
*tooltip-format-disabled*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used when the displayed controller is disabled.
|
||||||
|
|
||||||
|
*tooltip-format-off*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used when the displayed controller is turned off.
|
||||||
|
|
||||||
|
*tooltip-format-on*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used when the displayed controller is turned on with no devices connected.
|
||||||
|
|
||||||
|
*tooltip-format-connected*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used when the displayed controller is connected to at least 1 device.
|
||||||
|
|
||||||
|
*tooltip-format-enumerate-connected*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used to define how each connected device should be displayed within the *device_enumerate* format replacement in the tooltip menu.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{status}*: Status of the bluetooth device.
|
*{status}*: Status of the bluetooth device.
|
||||||
|
|
||||||
*{icon}*: Icon, as defined in *format-icons*.
|
*{num_connections}*: Number of connections the displayed controller has.
|
||||||
|
|
||||||
|
*{controller_address}*: Address of the displayed controller.
|
||||||
|
|
||||||
|
*{controller_address_type}*: Address type of the displayed controller.
|
||||||
|
|
||||||
|
*{controller_alias}*: Alias of the displayed controller.
|
||||||
|
|
||||||
|
*{device_address}*: Address of the displayed device.
|
||||||
|
|
||||||
|
*{device_address_type}*: Address type of the displayed device.
|
||||||
|
|
||||||
|
*{device_alias}*: Alias of the displayed device.
|
||||||
|
|
||||||
|
*{device_enumerate}*: Show a list of all connected devices, each on a seperate line. Define the format of each device with the *tooltip-format-enumerate-connected* ++
|
||||||
|
and/or *tooltip-format-enumerate-connected-battery* config options. Can only be used in the tooltip related format options.
|
||||||
|
|
||||||
|
# EXPERIMENTAL BATTERY PERCENTAGE FEATURE
|
||||||
|
|
||||||
|
At the time of writing, the experimental features of BlueZ need to be turned on, for the battery percentage options listed below to work.
|
||||||
|
|
||||||
|
## FORMAT REPLACEMENT
|
||||||
|
|
||||||
|
*{device_battery_percentage}*: Battery percentage of the displayed device if available. Use only in the config options defined below.
|
||||||
|
|
||||||
|
## CONFIGURATION
|
||||||
|
|
||||||
|
*format-connected-battery*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used when the displayed device provides its battery percentage.
|
||||||
|
|
||||||
|
*tooltip-format-connected-battery*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used when the displayed device provides its battery percentage.
|
||||||
|
|
||||||
|
*tooltip-format-enumerate-connected-battery*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used to define how each connected device with a battery should be displayed within the *device_enumerate* format replacement option. ++
|
||||||
|
When this config option is not defined, it will fall back on the *tooltip-format-enumerate-connected* config option.
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
"bluetooth": {
|
"bluetooth": {
|
||||||
"format": "{icon}",
|
// "controller": "controller1", // specify the alias of the controller if there are more than 1 on the system
|
||||||
"format-alt": "bluetooth: {status}",
|
"format": " {status}",
|
||||||
"format-icons": {
|
"format-disabled": "", // an empty format will hide the module
|
||||||
"enabled": "",
|
"format-connected": " {num_connections} connected",
|
||||||
"disabled": ""
|
"tooltip-format": "{controller_alias}\\t{controller_address}",
|
||||||
},
|
"tooltip-format-connected": "{controller_alias}\\t{controller_address}\\n\\n{device_enumerate}",
|
||||||
"tooltip-format": "{}"
|
"tooltip-format-enumerate-connected": "{device_alias}\\t{device_address}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
"bluetooth": {
|
||||||
|
"format": " {status}",
|
||||||
|
"format-connected": " {device_alias}",
|
||||||
|
"format-connected-battery": " {device_alias} {device_battery_percentage}%",
|
||||||
|
// "format-device-preference": [ "device1", "device2" ], // preference list deciding the displayed device
|
||||||
|
"tooltip-format": "{controller_alias}\\t{controller_address}\\n\\n{num_connections} connected",
|
||||||
|
"tooltip-format-connected": "{controller_alias}\\t{controller_address}\\n\\n{num_connections} connected\\n\\n{device_enumerate}",
|
||||||
|
"tooltip-format-enumerate-connected": "{device_alias}\\t{device_address}",
|
||||||
|
"tooltip-format-enumerate-connected-battery": "{device_alias}\\t{device_address}\\t{device_battery_percentage}%"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
# STYLE
|
# STYLE
|
||||||
|
|
||||||
- *#bluetooth*
|
- *#bluetooth*
|
||||||
|
- *#bluetooth.disabled*
|
||||||
|
- *#bluetooth.off*
|
||||||
|
- *#bluetooth.on*
|
||||||
|
- *#bluetooth.connected*
|
||||||
|
- *#bluetooth.discoverable*
|
||||||
|
- *#bluetooth.discovering*
|
||||||
|
- *#bluetooth.pairable*
|
||||||
|
@ -86,11 +86,17 @@ The *clock* module displays the current date and time.
|
|||||||
typeof: double ++
|
typeof: double ++
|
||||||
Threshold to be used when scrolling.
|
Threshold to be used when scrolling.
|
||||||
|
|
||||||
|
*tooltip*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
View all valid format options in *strftime(3)*.
|
View all valid format options in *strftime(3)*.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{calendar}*: Current month calendar
|
*{calendar}*: Current month calendar
|
||||||
|
*{timezoned_time_list}*: List of time in the rest timezones, if more than one timezone is set in the config
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
|
@ -151,7 +151,8 @@ $text\\n$tooltip\\n$class*
|
|||||||
"max-length": 40,
|
"max-length": 40,
|
||||||
"interval": 30, // Remove this if your script is endless and write in loop
|
"interval": 30, // Remove this if your script is endless and write in loop
|
||||||
"exec": "$HOME/.config/waybar/mediaplayer.sh 2> /dev/null", // Script in resources folder
|
"exec": "$HOME/.config/waybar/mediaplayer.sh 2> /dev/null", // Script in resources folder
|
||||||
"exec-if": "pgrep spotify"
|
"exec-if": "pgrep spotify",
|
||||||
|
"return-type": "json"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
95
man/waybar-gamemode.5.scd
Normal file
95
man/waybar-gamemode.5.scd
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
waybar-gamemode(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - gamemode module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *gamemode* module displays if any game or application is running with ++
|
||||||
|
Feral Gamemode optimizations.
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {glyph} ++
|
||||||
|
The text format.
|
||||||
|
|
||||||
|
*format-alt*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {glyph} {count} ++
|
||||||
|
The text format when toggled.
|
||||||
|
|
||||||
|
*tooltip*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
defualt: true ++
|
||||||
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*tooltip-format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: Games running: {glyph} ++
|
||||||
|
The text format of the tooltip.
|
||||||
|
|
||||||
|
*hide-not-running*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Defines if the module should be hidden if no games are running.
|
||||||
|
|
||||||
|
*use-icon*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Defines if the module should display a GTK icon instead of the specified *glyph*
|
||||||
|
|
||||||
|
*glyph*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: ++
|
||||||
|
The string icon to display. Only visible if *use-icon* is set to false.
|
||||||
|
|
||||||
|
*icon-name*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: input-gaming-symbolic ++
|
||||||
|
The GTK icon to display. Only visible if *use-icon* is set to true.
|
||||||
|
|
||||||
|
*icon-size*: ++
|
||||||
|
typeof: unsigned integer ++
|
||||||
|
default: 20 ++
|
||||||
|
Defines the size of the icons.
|
||||||
|
|
||||||
|
*icon-spacing*: ++
|
||||||
|
typeof: unsigned integer ++
|
||||||
|
default: 4 ++
|
||||||
|
Defines the spacing between the icon and the text.
|
||||||
|
|
||||||
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
*{glyph}*: The string icon glyph to use instead.
|
||||||
|
|
||||||
|
*{count}*: The amount of games running with gamemode optimizations.
|
||||||
|
|
||||||
|
# TOOLTIP FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
*{count}*: The amount of games running with gamemode optimizations.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"gamemode": {
|
||||||
|
"format": "{glyph}",
|
||||||
|
"format-alt": "{glyph} {count}",
|
||||||
|
"glyph": "",
|
||||||
|
"hide-not-running": true,
|
||||||
|
"use-icon": true,
|
||||||
|
"icon-name": "input-gaming-symbolic",
|
||||||
|
"icon-spacing": 4,
|
||||||
|
"icon-size": 20,
|
||||||
|
"tooltip": true,
|
||||||
|
"tooltip-format": "Games running: {count}"
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
# STYLE
|
||||||
|
|
||||||
|
- *#gamemode*
|
||||||
|
- *#gamemode.running*
|
@ -63,6 +63,10 @@ screensaving, also known as "presentation mode".
|
|||||||
typeof: double ++
|
typeof: double ++
|
||||||
Threshold to be used when scrolling.
|
Threshold to be used when scrolling.
|
||||||
|
|
||||||
|
*timeout*: ++
|
||||||
|
typeof: double ++
|
||||||
|
The number of minutes the inhibit should last.
|
||||||
|
|
||||||
*tooltip*: ++
|
*tooltip*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: true ++
|
default: true ++
|
||||||
@ -82,6 +86,7 @@ screensaving, also known as "presentation mode".
|
|||||||
"format-icons": {
|
"format-icons": {
|
||||||
"activated": "",
|
"activated": "",
|
||||||
"deactivated": ""
|
"deactivated": ""
|
||||||
}
|
},
|
||||||
|
"timeout": 30.5
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -8,6 +8,8 @@ waybar - keyboard-state module
|
|||||||
|
|
||||||
The *keyboard-state* module displays the state of number lock, caps lock, and scroll lock.
|
The *keyboard-state* module displays the state of number lock, caps lock, and scroll lock.
|
||||||
|
|
||||||
|
You must be a member of the input group to use this module.
|
||||||
|
|
||||||
# CONFIGURATION
|
# CONFIGURATION
|
||||||
|
|
||||||
*interval*: ++
|
*interval*: ++
|
||||||
@ -77,4 +79,9 @@ The following *format-icons* can be set.
|
|||||||
- *#keyboard-state*
|
- *#keyboard-state*
|
||||||
- *#keyboard-state label*
|
- *#keyboard-state label*
|
||||||
- *#keyboard-state label.locked*
|
- *#keyboard-state label.locked*
|
||||||
|
- *#keyboard-state label.numlock*
|
||||||
|
- *#keyboard-state label.numlock.locked*
|
||||||
|
- *#keyboard-state label.capslock*
|
||||||
|
- *#keyboard-state label.capslock.locked*
|
||||||
|
- *#keyboard-state label.scrolllock*
|
||||||
|
- *#keyboard-state label.scrolllock.locked*
|
||||||
|
@ -84,12 +84,20 @@ Addressed by *memory*
|
|||||||
|
|
||||||
*{percentage}*: Percentage of memory in use.
|
*{percentage}*: Percentage of memory in use.
|
||||||
|
|
||||||
|
*{swapPercentage}*: Percentage of swap in use.
|
||||||
|
|
||||||
*{total}*: Amount of total memory available in GiB.
|
*{total}*: Amount of total memory available in GiB.
|
||||||
|
|
||||||
|
*{swapTotal}*: Amount of total swap available in GiB.
|
||||||
|
|
||||||
*{used}*: Amount of used memory in GiB.
|
*{used}*: Amount of used memory in GiB.
|
||||||
|
|
||||||
|
*{swapUsed}*: Amount of used swap in GiB.
|
||||||
|
|
||||||
*{avail}*: Amount of available memory in GiB.
|
*{avail}*: Amount of available memory in GiB.
|
||||||
|
|
||||||
|
*{swapAvail}*: Amount of available swap in GiB.
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
|
59
man/waybar-river-window.5.scd
Normal file
59
man/waybar-river-window.5.scd
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
waybar-river-window(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - river window module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *window* module displays the title of the currently focused window in river
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
Addressed by *river/window*
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {} ++
|
||||||
|
The format, how information should be displayed. On {} data gets inserted.
|
||||||
|
|
||||||
|
*rotate*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
Positive value to rotate the text label.
|
||||||
|
|
||||||
|
*max-length*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
The maximum length in character the module should display.
|
||||||
|
|
||||||
|
*min-length*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
The minimum length in characters the module should take up.
|
||||||
|
|
||||||
|
*align*: ++
|
||||||
|
typeof: float ++
|
||||||
|
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*on-click*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when clicked on the module.
|
||||||
|
|
||||||
|
*on-click-middle*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when middle-clicked on the module using mousewheel.
|
||||||
|
|
||||||
|
*on-click-right*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when you right clicked on the module.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"river/window": {
|
||||||
|
"format": "{}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# STYLE
|
||||||
|
|
||||||
|
- *#window*
|
||||||
|
- *#window.focused* Applied when the output this module's bar belongs to is focused.
|
@ -69,7 +69,7 @@ Addressed by *sway/mode*
|
|||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
"sway/window": {
|
"sway/mode": {
|
||||||
"format": " {}",
|
"format": " {}",
|
||||||
"max-length": 50
|
"max-length": 50
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,16 @@ Addressed by *sway/window*
|
|||||||
typeof: object ++
|
typeof: object ++
|
||||||
Rules to rewrite window title. See *rewrite rules*.
|
Rules to rewrite window title. See *rewrite rules*.
|
||||||
|
|
||||||
|
*icon*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
Option to hide the application icon.
|
||||||
|
|
||||||
|
*icon-size*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
default: 24 ++
|
||||||
|
Option to change the size of the application icon.
|
||||||
|
|
||||||
# REWRITE RULES
|
# REWRITE RULES
|
||||||
|
|
||||||
*rewrite* is an object where keys are regular expressions and values are
|
*rewrite* is an object where keys are regular expressions and values are
|
||||||
|
@ -29,6 +29,10 @@ Addressed by *tray*
|
|||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Defines the spacing between the tray icons.
|
Defines the spacing between the tray icons.
|
||||||
|
|
||||||
|
*reverse-direction*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
Defines if new app icons should be added in a reverse order
|
||||||
|
|
||||||
*on-update*: ++
|
*on-update*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
Command to execute when the module is updated.
|
Command to execute when the module is updated.
|
||||||
|
76
man/waybar-upower.5.scd
Normal file
76
man/waybar-upower.5.scd
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
waybar-upower(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - upower module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *upower* module displays the main battery capacity with all other upower
|
||||||
|
compatible devices in the tooltip.
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
*icon-size*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
default: 20 ++
|
||||||
|
Defines the size of the icons.
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {percentage} ++
|
||||||
|
The text format.
|
||||||
|
|
||||||
|
*format-alt*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {percentage} {time} ++
|
||||||
|
The text format when toggled.
|
||||||
|
|
||||||
|
*hide-if-empty*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Defines visibility of the module if no devices can be found.
|
||||||
|
|
||||||
|
*tooltip*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
defualt: true ++
|
||||||
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*tooltip-spacing*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
default: 4 ++
|
||||||
|
Defines the spacing between the tooltip device name and device battery ++
|
||||||
|
status.
|
||||||
|
|
||||||
|
*tooltip-padding*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
default: 4 ++
|
||||||
|
Defines the spacing between the tooltip window edge and the tooltip content.
|
||||||
|
|
||||||
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
*{percentage}*: The battery capacity in percentage
|
||||||
|
|
||||||
|
*{time}*: An estimated time either until empty or until fully charged ++
|
||||||
|
depending on the charging state.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"upower": {
|
||||||
|
"icon-size": 20,
|
||||||
|
"hide-if-empty": true,
|
||||||
|
"tooltip": true,
|
||||||
|
"tooltip-spacing": 20
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
# STYLE
|
||||||
|
|
||||||
|
- *#upower*
|
||||||
|
- *#upower.charging*
|
||||||
|
- *#upower.discharging*
|
||||||
|
- *#upower.full*
|
||||||
|
- *#upower.empty*
|
||||||
|
- *#upower.unknown-status*
|
@ -93,10 +93,15 @@ Addressed by *wlr/taskbar*
|
|||||||
# CLICK ACTIONS
|
# CLICK ACTIONS
|
||||||
|
|
||||||
*activate*: Bring the application into foreground.
|
*activate*: Bring the application into foreground.
|
||||||
|
|
||||||
*minimize*: Toggle application's minimized state.
|
*minimize*: Toggle application's minimized state.
|
||||||
|
|
||||||
*minimize-raise*: Bring the application into foreground or toggle its minimized state.
|
*minimize-raise*: Bring the application into foreground or toggle its minimized state.
|
||||||
|
|
||||||
*maximize*: Toggle application's maximized state.
|
*maximize*: Toggle application's maximized state.
|
||||||
|
|
||||||
*fullscreen*: Toggle application's fullscreen state.
|
*fullscreen*: Toggle application's fullscreen state.
|
||||||
|
|
||||||
*close*: Close the application.
|
*close*: Close the application.
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
@ -52,6 +52,7 @@ Addressed by *wlr/workspaces*
|
|||||||
# CLICK ACTIONS
|
# CLICK ACTIONS
|
||||||
|
|
||||||
*activate*: Switch to workspace.
|
*activate*: Switch to workspace.
|
||||||
|
|
||||||
*close*: Close the workspace.
|
*close*: Close the workspace.
|
||||||
|
|
||||||
# ICONS
|
# ICONS
|
||||||
|
@ -77,6 +77,13 @@ Also a minimal example configuration can be found on the at the bottom of this m
|
|||||||
Selects one of the preconfigured display modes. This is an equivalent of the sway-bar(5) *mode* command and supports the same values: *dock*, *hide*, *invisible*, *overlay*. ++
|
Selects one of the preconfigured display modes. This is an equivalent of the sway-bar(5) *mode* command and supports the same values: *dock*, *hide*, *invisible*, *overlay*. ++
|
||||||
Note: *hide* and *invisible* modes may be not as useful without Sway IPC.
|
Note: *hide* and *invisible* modes may be not as useful without Sway IPC.
|
||||||
|
|
||||||
|
modifier-reset ++
|
||||||
|
typeof: string ++
|
||||||
|
default: *press*
|
||||||
|
Defines the timing of modifier key to reset the bar visibility.
|
||||||
|
To reset the visibility of the bar with the press of the modifier key use *press*.
|
||||||
|
Use *release* to reset the visibility upon the release of the modifier key and only if no other action happened while the key was pressed. This prevents hiding the bar when the modifier is used to switch a workspace, change binding mode or start a keybinding.
|
||||||
|
|
||||||
*exclusive* ++
|
*exclusive* ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: *true* ++
|
default: *true* ++
|
||||||
|
37
meson.build
37
meson.build
@ -1,6 +1,6 @@
|
|||||||
project(
|
project(
|
||||||
'waybar', 'cpp', 'c',
|
'waybar', 'cpp', 'c',
|
||||||
version: '0.9.9',
|
version: '0.9.13',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>= 0.49.0',
|
meson_version: '>= 0.49.0',
|
||||||
default_options : [
|
default_options : [
|
||||||
@ -86,12 +86,13 @@ wayland_cursor = dependency('wayland-cursor')
|
|||||||
wayland_protos = dependency('wayland-protocols')
|
wayland_protos = dependency('wayland-protocols')
|
||||||
gtkmm = dependency('gtkmm-3.0', version : ['>=3.22.0'])
|
gtkmm = dependency('gtkmm-3.0', version : ['>=3.22.0'])
|
||||||
dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4', required: get_option('dbusmenu-gtk'))
|
dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4', required: get_option('dbusmenu-gtk'))
|
||||||
giounix = dependency('gio-unix-2.0', required: (get_option('dbusmenu-gtk').enabled() or get_option('logind').enabled()))
|
giounix = dependency('gio-unix-2.0', required: (get_option('dbusmenu-gtk').enabled() or get_option('logind').enabled() or get_option('upower_glib').enabled()))
|
||||||
jsoncpp = dependency('jsoncpp')
|
jsoncpp = dependency('jsoncpp')
|
||||||
sigcpp = dependency('sigc++-2.0')
|
sigcpp = dependency('sigc++-2.0')
|
||||||
libepoll = dependency('epoll-shim', required: false)
|
libepoll = dependency('epoll-shim', required: false)
|
||||||
libnl = dependency('libnl-3.0', required: get_option('libnl'))
|
libnl = dependency('libnl-3.0', required: get_option('libnl'))
|
||||||
libnlgen = dependency('libnl-genl-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'))
|
||||||
libpulse = dependency('libpulse', required: get_option('pulseaudio'))
|
libpulse = dependency('libpulse', required: get_option('pulseaudio'))
|
||||||
libudev = dependency('libudev', required: get_option('libudev'))
|
libudev = dependency('libudev', required: get_option('libudev'))
|
||||||
libevdev = dependency('libevdev', required: get_option('libevdev'))
|
libevdev = dependency('libevdev', required: get_option('libevdev'))
|
||||||
@ -142,6 +143,7 @@ src_files = files(
|
|||||||
'src/factory.cpp',
|
'src/factory.cpp',
|
||||||
'src/AModule.cpp',
|
'src/AModule.cpp',
|
||||||
'src/ALabel.cpp',
|
'src/ALabel.cpp',
|
||||||
|
'src/AIconLabel.cpp',
|
||||||
'src/modules/custom.cpp',
|
'src/modules/custom.cpp',
|
||||||
'src/modules/disk.cpp',
|
'src/modules/disk.cpp',
|
||||||
'src/modules/idle_inhibitor.cpp',
|
'src/modules/idle_inhibitor.cpp',
|
||||||
@ -195,6 +197,7 @@ endif
|
|||||||
if true
|
if true
|
||||||
add_project_arguments('-DHAVE_RIVER', language: 'cpp')
|
add_project_arguments('-DHAVE_RIVER', language: 'cpp')
|
||||||
src_files += 'src/modules/river/tags.cpp'
|
src_files += 'src/modules/river/tags.cpp'
|
||||||
|
src_files += 'src/modules/river/window.cpp'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if libnl.found() and libnlgen.found()
|
if libnl.found() and libnlgen.found()
|
||||||
@ -202,6 +205,17 @@ if libnl.found() and libnlgen.found()
|
|||||||
src_files += 'src/modules/network.cpp'
|
src_files += 'src/modules/network.cpp'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if (giounix.found() and not get_option('logind').disabled())
|
||||||
|
add_project_arguments('-DHAVE_GAMEMODE', language: 'cpp')
|
||||||
|
src_files += 'src/modules/gamemode.cpp'
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (upower_glib.found() and giounix.found() and not get_option('logind').disabled())
|
||||||
|
add_project_arguments('-DHAVE_UPOWER', language: 'cpp')
|
||||||
|
src_files += 'src/modules/upower/upower.cpp'
|
||||||
|
src_files += 'src/modules/upower/upower_tooltip.cpp'
|
||||||
|
endif
|
||||||
|
|
||||||
if libpulse.found()
|
if libpulse.found()
|
||||||
add_project_arguments('-DHAVE_LIBPULSE', language: 'cpp')
|
add_project_arguments('-DHAVE_LIBPULSE', language: 'cpp')
|
||||||
src_files += 'src/modules/pulseaudio.cpp'
|
src_files += 'src/modules/pulseaudio.cpp'
|
||||||
@ -245,16 +259,14 @@ endif
|
|||||||
if (giounix.found() and not get_option('logind').disabled())
|
if (giounix.found() and not get_option('logind').disabled())
|
||||||
add_project_arguments('-DHAVE_GIO_UNIX', language: 'cpp')
|
add_project_arguments('-DHAVE_GIO_UNIX', language: 'cpp')
|
||||||
src_files += 'src/modules/inhibitor.cpp'
|
src_files += 'src/modules/inhibitor.cpp'
|
||||||
|
src_files += 'src/modules/bluetooth.cpp'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if get_option('rfkill').enabled()
|
if get_option('rfkill').enabled() and is_linux
|
||||||
if is_linux
|
add_project_arguments('-DWANT_RFKILL', language: 'cpp')
|
||||||
add_project_arguments('-DWANT_RFKILL', language: 'cpp')
|
src_files += files(
|
||||||
src_files += files(
|
'src/util/rfkill.cpp'
|
||||||
'src/modules/bluetooth.cpp',
|
)
|
||||||
'src/util/rfkill.cpp'
|
|
||||||
)
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if tz_dep.found()
|
if tz_dep.found()
|
||||||
@ -287,6 +299,7 @@ executable(
|
|||||||
giounix,
|
giounix,
|
||||||
libnl,
|
libnl,
|
||||||
libnlgen,
|
libnlgen,
|
||||||
|
upower_glib,
|
||||||
libpulse,
|
libpulse,
|
||||||
libudev,
|
libudev,
|
||||||
libepoll,
|
libepoll,
|
||||||
@ -295,7 +308,7 @@ executable(
|
|||||||
gtk_layer_shell,
|
gtk_layer_shell,
|
||||||
libsndio,
|
libsndio,
|
||||||
tz_dep,
|
tz_dep,
|
||||||
xkbregistry
|
xkbregistry
|
||||||
],
|
],
|
||||||
include_directories: [include_directories('include')],
|
include_directories: [include_directories('include')],
|
||||||
install: true,
|
install: true,
|
||||||
@ -339,6 +352,7 @@ if scdoc.found()
|
|||||||
'waybar-network.5.scd',
|
'waybar-network.5.scd',
|
||||||
'waybar-pulseaudio.5.scd',
|
'waybar-pulseaudio.5.scd',
|
||||||
'waybar-river-tags.5.scd',
|
'waybar-river-tags.5.scd',
|
||||||
|
'waybar-river-window.5.scd',
|
||||||
'waybar-sway-language.5.scd',
|
'waybar-sway-language.5.scd',
|
||||||
'waybar-sway-mode.5.scd',
|
'waybar-sway-mode.5.scd',
|
||||||
'waybar-sway-window.5.scd',
|
'waybar-sway-window.5.scd',
|
||||||
@ -350,6 +364,7 @@ if scdoc.found()
|
|||||||
'waybar-wlr-workspaces.5.scd',
|
'waybar-wlr-workspaces.5.scd',
|
||||||
'waybar-bluetooth.5.scd',
|
'waybar-bluetooth.5.scd',
|
||||||
'waybar-sndio.5.scd',
|
'waybar-sndio.5.scd',
|
||||||
|
'waybar-upower.5.scd',
|
||||||
]
|
]
|
||||||
|
|
||||||
if (giounix.found() and not get_option('logind').disabled())
|
if (giounix.found() and not get_option('logind').disabled())
|
||||||
|
@ -3,6 +3,7 @@ option('libnl', type: 'feature', value: 'auto', description: 'Enable libnl suppo
|
|||||||
option('libudev', type: 'feature', value: 'auto', description: 'Enable libudev support for udev related features')
|
option('libudev', type: 'feature', value: 'auto', description: 'Enable libudev support for udev related features')
|
||||||
option('libevdev', type: 'feature', value: 'auto', description: 'Enable libevdev support for evdev related features')
|
option('libevdev', type: 'feature', value: 'auto', description: 'Enable libevdev support for evdev related features')
|
||||||
option('pulseaudio', type: 'feature', value: 'auto', description: 'Enable support for pulseaudio')
|
option('pulseaudio', type: 'feature', value: 'auto', description: 'Enable support for pulseaudio')
|
||||||
|
option('upower_glib', type: 'feature', value: 'auto', description: 'Enable support for upower')
|
||||||
option('systemd', type: 'feature', value: 'auto', description: 'Install systemd user service unit')
|
option('systemd', type: 'feature', value: 'auto', description: 'Install systemd user service unit')
|
||||||
option('dbusmenu-gtk', type: 'feature', value: 'auto', description: 'Enable support for tray')
|
option('dbusmenu-gtk', type: 'feature', value: 'auto', description: 'Enable support for tray')
|
||||||
option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages')
|
option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages')
|
||||||
|
@ -96,7 +96,7 @@
|
|||||||
"backlight": {
|
"backlight": {
|
||||||
// "device": "acpi_video1",
|
// "device": "acpi_video1",
|
||||||
"format": "{percent}% {icon}",
|
"format": "{percent}% {icon}",
|
||||||
"format-icons": ["", ""]
|
"format-icons": ["", "", "", "", "", "", "", "", ""]
|
||||||
},
|
},
|
||||||
"battery": {
|
"battery": {
|
||||||
"states": {
|
"states": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
* {
|
* {
|
||||||
/* `otf-font-awesome` is required to be installed for icons */
|
/* `otf-font-awesome` is required to be installed for icons */
|
||||||
font-family: Roboto, Helvetica, Arial, sans-serif;
|
font-family: FontAwesome, Roboto, Helvetica, Arial, sans-serif;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
src/AIconLabel.cpp
Normal file
28
src/AIconLabel.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "AIconLabel.hpp"
|
||||||
|
|
||||||
|
#include <gdkmm/pixbuf.h>
|
||||||
|
|
||||||
|
namespace waybar {
|
||||||
|
|
||||||
|
AIconLabel::AIconLabel(const Json::Value &config, const std::string &name, const std::string &id,
|
||||||
|
const std::string &format, uint16_t interval, bool ellipsize,
|
||||||
|
bool enable_click, bool enable_scroll)
|
||||||
|
: ALabel(config, name, id, format, interval, ellipsize, enable_click, enable_scroll) {
|
||||||
|
event_box_.remove();
|
||||||
|
box_.set_orientation(Gtk::Orientation::ORIENTATION_HORIZONTAL);
|
||||||
|
box_.set_spacing(8);
|
||||||
|
box_.add(image_);
|
||||||
|
box_.add(label_);
|
||||||
|
event_box_.add(box_);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto AIconLabel::update() -> void {
|
||||||
|
image_.set_visible(image_.get_visible() && iconEnabled());
|
||||||
|
ALabel::update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AIconLabel::iconEnabled() const {
|
||||||
|
return config_["icon"].isBool() ? config_["icon"].asBool() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar
|
@ -1,5 +1,7 @@
|
|||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <util/command.hpp>
|
#include <util/command.hpp>
|
||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
@ -46,15 +48,10 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
|
|||||||
} else {
|
} else {
|
||||||
label_.set_xalign(align);
|
label_.set_xalign(align);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ALabel::update() -> void {
|
auto ALabel::update() -> void { AModule::update(); }
|
||||||
AModule::update();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ALabel::getIcon(uint16_t percentage, const std::string& alt, uint16_t max) {
|
std::string ALabel::getIcon(uint16_t percentage, const std::string& alt, uint16_t max) {
|
||||||
auto format_icons = config_["format-icons"];
|
auto format_icons = config_["format-icons"];
|
||||||
@ -78,7 +75,8 @@ std::string ALabel::getIcon(uint16_t percentage, const std::string& alt, uint16_
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ALabel::getIcon(uint16_t percentage, const std::vector<std::string>& alts, uint16_t max) {
|
std::string ALabel::getIcon(uint16_t percentage, const std::vector<std::string>& alts,
|
||||||
|
uint16_t max) {
|
||||||
auto format_icons = config_["format-icons"];
|
auto format_icons = config_["format-icons"];
|
||||||
if (format_icons.isObject()) {
|
if (format_icons.isObject()) {
|
||||||
std::string _alt = "default";
|
std::string _alt = "default";
|
||||||
|
@ -1,18 +1,32 @@
|
|||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <util/command.hpp>
|
#include <util/command.hpp>
|
||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
|
|
||||||
AModule::AModule(const Json::Value& config, const std::string& name, const std::string& id,
|
AModule::AModule(const Json::Value& config, const std::string& name, const std::string& id,
|
||||||
bool enable_click, bool enable_scroll)
|
bool enable_click, bool enable_scroll)
|
||||||
: name_(std::move(name)), config_(std::move(config)) {
|
: name_(std::move(name)),
|
||||||
|
config_(std::move(config)),
|
||||||
|
distance_scrolled_y_(0.0),
|
||||||
|
distance_scrolled_x_(0.0) {
|
||||||
// configure events' user commands
|
// configure events' user commands
|
||||||
if (config_["on-click"].isString() || config_["on-click-middle"].isString() ||
|
if (enable_click) {
|
||||||
config_["on-click-backward"].isString() || config_["on-click-forward"].isString() ||
|
|
||||||
config_["on-click-right"].isString() || enable_click) {
|
|
||||||
event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
|
event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
|
||||||
event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &AModule::handleToggle));
|
event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &AModule::handleToggle));
|
||||||
|
} else {
|
||||||
|
std::map<std::pair<uint, GdkEventType>, std::string>::const_iterator it{eventMap_.cbegin()};
|
||||||
|
while (it != eventMap_.cend()) {
|
||||||
|
if (config_[it->second].isString()) {
|
||||||
|
event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
|
||||||
|
event_box_.signal_button_press_event().connect(
|
||||||
|
sigc::mem_fun(*this, &AModule::handleToggle));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].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_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
||||||
@ -28,7 +42,6 @@ AModule::~AModule() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto AModule::update() -> void {
|
auto AModule::update() -> void {
|
||||||
// Run user-provided update handler if configured
|
// Run user-provided update handler if configured
|
||||||
if (config_["on-update"].isString()) {
|
if (config_["on-update"].isString()) {
|
||||||
@ -37,18 +50,17 @@ auto AModule::update() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AModule::handleToggle(GdkEventButton* const& e) {
|
bool AModule::handleToggle(GdkEventButton* const& e) {
|
||||||
std::string format;
|
const std::map<std::pair<uint, GdkEventType>, std::string>::const_iterator& rec{
|
||||||
if (config_["on-click"].isString() && e->button == 1) {
|
eventMap_.find(std::pair(e->button, e->type))};
|
||||||
format = config_["on-click"].asString();
|
std::string format{(rec != eventMap_.cend()) ? rec->second : std::string{""}};
|
||||||
} else if (config_["on-click-middle"].isString() && e->button == 2) {
|
|
||||||
format = config_["on-click-middle"].asString();
|
if (!format.empty()) {
|
||||||
} else if (config_["on-click-right"].isString() && e->button == 3) {
|
if (config_[format].isString())
|
||||||
format = config_["on-click-right"].asString();
|
format = config_[format].asString();
|
||||||
} else if (config_["on-click-backward"].isString() && e->button == 8) {
|
else
|
||||||
format = config_["on-click-backward"].asString();
|
format.clear();
|
||||||
} else if (config_["on-click-forward"].isString() && e->button == 9) {
|
|
||||||
format = config_["on-click-forward"].asString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!format.empty()) {
|
if (!format.empty()) {
|
||||||
pid_.push_back(util::command::forkExec(format));
|
pid_.push_back(util::command::forkExec(format));
|
||||||
}
|
}
|
||||||
@ -57,11 +69,15 @@ bool AModule::handleToggle(GdkEventButton* const& e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AModule::SCROLL_DIR AModule::getScrollDir(GdkEventScroll* e) {
|
AModule::SCROLL_DIR AModule::getScrollDir(GdkEventScroll* e) {
|
||||||
switch (e -> direction) {
|
switch (e->direction) {
|
||||||
case GDK_SCROLL_UP: return SCROLL_DIR::UP;
|
case GDK_SCROLL_UP:
|
||||||
case GDK_SCROLL_DOWN: return SCROLL_DIR::DOWN;
|
return SCROLL_DIR::UP;
|
||||||
case GDK_SCROLL_LEFT: return SCROLL_DIR::LEFT;
|
case GDK_SCROLL_DOWN:
|
||||||
case GDK_SCROLL_RIGHT: return SCROLL_DIR::RIGHT;
|
return SCROLL_DIR::DOWN;
|
||||||
|
case GDK_SCROLL_LEFT:
|
||||||
|
return SCROLL_DIR::LEFT;
|
||||||
|
case GDK_SCROLL_RIGHT:
|
||||||
|
return SCROLL_DIR::RIGHT;
|
||||||
case GDK_SCROLL_SMOOTH: {
|
case GDK_SCROLL_SMOOTH: {
|
||||||
SCROLL_DIR dir{SCROLL_DIR::NONE};
|
SCROLL_DIR dir{SCROLL_DIR::NONE};
|
||||||
|
|
||||||
@ -99,7 +115,8 @@ AModule::SCROLL_DIR AModule::getScrollDir(GdkEventScroll* e) {
|
|||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
// Silence -Wreturn-type:
|
// Silence -Wreturn-type:
|
||||||
default: return SCROLL_DIR::NONE;
|
default:
|
||||||
|
return SCROLL_DIR::NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
86
src/bar.cpp
86
src/bar.cpp
@ -170,12 +170,21 @@ struct GLSSurfaceImpl : public BarSurface, public sigc::trackable {
|
|||||||
vertical_ = true;
|
vertical_ = true;
|
||||||
unanchored = GTK_LAYER_SHELL_EDGE_LEFT;
|
unanchored = GTK_LAYER_SHELL_EDGE_LEFT;
|
||||||
}
|
}
|
||||||
for (auto edge : {GTK_LAYER_SHELL_EDGE_LEFT,
|
for (auto edge : {GTK_LAYER_SHELL_EDGE_LEFT, GTK_LAYER_SHELL_EDGE_RIGHT,
|
||||||
GTK_LAYER_SHELL_EDGE_RIGHT,
|
GTK_LAYER_SHELL_EDGE_TOP, GTK_LAYER_SHELL_EDGE_BOTTOM}) {
|
||||||
GTK_LAYER_SHELL_EDGE_TOP,
|
|
||||||
GTK_LAYER_SHELL_EDGE_BOTTOM}) {
|
|
||||||
gtk_layer_set_anchor(window_.gobj(), edge, unanchored != edge);
|
gtk_layer_set_anchor(window_.gobj(), edge, unanchored != edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable anchoring for other edges too if the width
|
||||||
|
// or the height has been set to a value other than 'auto'
|
||||||
|
// otherwise the bar will use all space
|
||||||
|
if (vertical_ && height_ > 1) {
|
||||||
|
gtk_layer_set_anchor(window_.gobj(), GTK_LAYER_SHELL_EDGE_BOTTOM, false);
|
||||||
|
gtk_layer_set_anchor(window_.gobj(), GTK_LAYER_SHELL_EDGE_TOP, false);
|
||||||
|
} else if (width_ > 1) {
|
||||||
|
gtk_layer_set_anchor(window_.gobj(), GTK_LAYER_SHELL_EDGE_LEFT, false);
|
||||||
|
gtk_layer_set_anchor(window_.gobj(), GTK_LAYER_SHELL_EDGE_RIGHT, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSize(uint32_t width, uint32_t height) override {
|
void setSize(uint32_t width, uint32_t height) override {
|
||||||
@ -186,11 +195,11 @@ struct GLSSurfaceImpl : public BarSurface, public sigc::trackable {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Gtk::Window& window_;
|
Gtk::Window& window_;
|
||||||
std::string output_name_;
|
std::string output_name_;
|
||||||
uint32_t width_;
|
uint32_t width_;
|
||||||
uint32_t height_;
|
uint32_t height_;
|
||||||
bool passthrough_ = false;
|
bool passthrough_ = false;
|
||||||
bool vertical_ = false;
|
bool vertical_ = false;
|
||||||
|
|
||||||
void onMap(GdkEventAny* ev) { setPassThrough(passthrough_); }
|
void onMap(GdkEventAny* ev) { setPassThrough(passthrough_); }
|
||||||
|
|
||||||
@ -276,8 +285,8 @@ struct RawSurfaceImpl : public BarSurface, public sigc::trackable {
|
|||||||
margins_ = margins;
|
margins_ = margins;
|
||||||
// updating already mapped window
|
// updating already mapped window
|
||||||
if (layer_surface_) {
|
if (layer_surface_) {
|
||||||
zwlr_layer_surface_v1_set_margin(
|
zwlr_layer_surface_v1_set_margin(layer_surface_.get(), margins_.top, margins_.right,
|
||||||
layer_surface_.get(), margins_.top, margins_.right, margins_.bottom, margins_.left);
|
margins_.bottom, margins_.left);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,21 +344,21 @@ struct RawSurfaceImpl : public BarSurface, public sigc::trackable {
|
|||||||
using layer_surface_ptr =
|
using layer_surface_ptr =
|
||||||
std::unique_ptr<zwlr_layer_surface_v1, deleter_fn<zwlr_layer_surface_v1_destroy>>;
|
std::unique_ptr<zwlr_layer_surface_v1, deleter_fn<zwlr_layer_surface_v1_destroy>>;
|
||||||
|
|
||||||
Gtk::Window& window_;
|
Gtk::Window& window_;
|
||||||
std::string output_name_;
|
std::string output_name_;
|
||||||
uint32_t configured_width_ = 0;
|
uint32_t configured_width_ = 0;
|
||||||
uint32_t configured_height_ = 0;
|
uint32_t configured_height_ = 0;
|
||||||
uint32_t width_ = 0;
|
uint32_t width_ = 0;
|
||||||
uint32_t height_ = 0;
|
uint32_t height_ = 0;
|
||||||
uint8_t anchor_ = HORIZONTAL_ANCHOR | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
|
uint8_t anchor_ = HORIZONTAL_ANCHOR | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
|
||||||
bool exclusive_zone_ = true;
|
bool exclusive_zone_ = true;
|
||||||
bool passthrough_ = false;
|
bool passthrough_ = false;
|
||||||
struct bar_margins margins_;
|
struct bar_margins margins_;
|
||||||
|
|
||||||
zwlr_layer_shell_v1_layer layer_ = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
|
zwlr_layer_shell_v1_layer layer_ = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
|
||||||
struct wl_output* output_ = nullptr; // owned by GTK
|
struct wl_output* output_ = nullptr; // owned by GTK
|
||||||
struct wl_surface* surface_ = nullptr; // owned by GTK
|
struct wl_surface* surface_ = nullptr; // owned by GTK
|
||||||
layer_surface_ptr layer_surface_;
|
layer_surface_ptr layer_surface_;
|
||||||
|
|
||||||
void onRealize() {
|
void onRealize() {
|
||||||
auto gdk_window = window_.get_window()->gobj();
|
auto gdk_window = window_.get_window()->gobj();
|
||||||
@ -365,14 +374,14 @@ struct RawSurfaceImpl : public BarSurface, public sigc::trackable {
|
|||||||
auto gdk_window = window_.get_window()->gobj();
|
auto gdk_window = window_.get_window()->gobj();
|
||||||
surface_ = gdk_wayland_window_get_wl_surface(gdk_window);
|
surface_ = gdk_wayland_window_get_wl_surface(gdk_window);
|
||||||
|
|
||||||
layer_surface_.reset(zwlr_layer_shell_v1_get_layer_surface(
|
layer_surface_.reset(zwlr_layer_shell_v1_get_layer_surface(client->layer_shell, surface_,
|
||||||
client->layer_shell, surface_, output_, layer_, "waybar"));
|
output_, layer_, "waybar"));
|
||||||
|
|
||||||
zwlr_layer_surface_v1_add_listener(layer_surface_.get(), &layer_surface_listener, this);
|
zwlr_layer_surface_v1_add_listener(layer_surface_.get(), &layer_surface_listener, this);
|
||||||
zwlr_layer_surface_v1_set_keyboard_interactivity(layer_surface_.get(), false);
|
zwlr_layer_surface_v1_set_keyboard_interactivity(layer_surface_.get(), false);
|
||||||
zwlr_layer_surface_v1_set_anchor(layer_surface_.get(), anchor_);
|
zwlr_layer_surface_v1_set_anchor(layer_surface_.get(), anchor_);
|
||||||
zwlr_layer_surface_v1_set_margin(
|
zwlr_layer_surface_v1_set_margin(layer_surface_.get(), margins_.top, margins_.right,
|
||||||
layer_surface_.get(), margins_.top, margins_.right, margins_.bottom, margins_.left);
|
margins_.bottom, margins_.left);
|
||||||
|
|
||||||
setSurfaceSize(width_, height_);
|
setSurfaceSize(width_, height_);
|
||||||
setExclusiveZone(exclusive_zone_);
|
setExclusiveZone(exclusive_zone_);
|
||||||
@ -453,10 +462,8 @@ struct RawSurfaceImpl : public BarSurface, public sigc::trackable {
|
|||||||
o->window_.set_size_request(o->width_, o->height_);
|
o->window_.set_size_request(o->width_, o->height_);
|
||||||
o->window_.resize(o->width_, o->height_);
|
o->window_.resize(o->width_, o->height_);
|
||||||
o->setExclusiveZone(o->exclusive_zone_);
|
o->setExclusiveZone(o->exclusive_zone_);
|
||||||
spdlog::info(BAR_SIZE_MSG,
|
spdlog::info(BAR_SIZE_MSG, o->width_ == 1 ? "auto" : std::to_string(o->width_),
|
||||||
o->width_ == 1 ? "auto" : std::to_string(o->width_),
|
o->height_ == 1 ? "auto" : std::to_string(o->height_), o->output_name_);
|
||||||
o->height_ == 1 ? "auto" : std::to_string(o->height_),
|
|
||||||
o->output_name_);
|
|
||||||
o->commit();
|
o->commit();
|
||||||
}
|
}
|
||||||
zwlr_layer_surface_v1_ack_configure(surface, serial);
|
zwlr_layer_surface_v1_ack_configure(surface, serial);
|
||||||
@ -520,7 +527,7 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
|||||||
config["margin-left"].isInt() ? config["margin-left"].asInt() : 0,
|
config["margin-left"].isInt() ? config["margin-left"].asInt() : 0,
|
||||||
};
|
};
|
||||||
} else if (config["margin"].isString()) {
|
} else if (config["margin"].isString()) {
|
||||||
std::istringstream iss(config["margin"].asString());
|
std::istringstream iss(config["margin"].asString());
|
||||||
std::vector<std::string> margins{std::istream_iterator<std::string>(iss), {}};
|
std::vector<std::string> margins{std::istream_iterator<std::string>(iss), {}};
|
||||||
try {
|
try {
|
||||||
if (margins.size() == 1) {
|
if (margins.size() == 1) {
|
||||||
@ -567,8 +574,10 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
surface_impl_->setMargins(margins_);
|
surface_impl_->setMargins(margins_);
|
||||||
surface_impl_->setPosition(position);
|
|
||||||
surface_impl_->setSize(width, height);
|
surface_impl_->setSize(width, height);
|
||||||
|
// Position needs to be set after calculating the height due to the
|
||||||
|
// GTK layer shell anchors logic relying on the dimensions of the bar.
|
||||||
|
surface_impl_->setPosition(position);
|
||||||
|
|
||||||
/* Read custom modes if available */
|
/* Read custom modes if available */
|
||||||
if (auto modes = config.get("modes", {}); modes.isObject()) {
|
if (auto modes = config.get("modes", {}); modes.isObject()) {
|
||||||
@ -665,7 +674,11 @@ void waybar::Bar::onMap(GdkEventAny*) {
|
|||||||
|
|
||||||
void waybar::Bar::setVisible(bool value) {
|
void waybar::Bar::setVisible(bool value) {
|
||||||
visible = value;
|
visible = value;
|
||||||
setMode(visible ? MODE_DEFAULT : MODE_INVISIBLE);
|
if (auto mode = config.get("mode", {}); mode.isString()) {
|
||||||
|
setMode(visible ? config["mode"].asString() : MODE_INVISIBLE);
|
||||||
|
} else {
|
||||||
|
setMode(visible ? MODE_DEFAULT : MODE_INVISIBLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Bar::toggle() { setVisible(!visible); }
|
void waybar::Bar::toggle() { setVisible(!visible); }
|
||||||
@ -719,7 +732,8 @@ void waybar::Bar::handleSignal(int signal) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Bar::getModules(const Factory& factory, const std::string& pos, Gtk::Box* group = nullptr) {
|
void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
||||||
|
Gtk::Box* group = nullptr) {
|
||||||
auto module_list = group ? config[pos]["modules"] : config[pos];
|
auto module_list = group ? config[pos]["modules"] : config[pos];
|
||||||
if (module_list.isArray()) {
|
if (module_list.isArray()) {
|
||||||
for (const auto& name : module_list) {
|
for (const auto& name : module_list) {
|
||||||
@ -750,7 +764,7 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos, Gtk
|
|||||||
modules_right_.emplace_back(module_sp);
|
modules_right_.emplace_back(module_sp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module->dp.connect([module, &name] {
|
module->dp.connect([module, name] {
|
||||||
try {
|
try {
|
||||||
module->update();
|
module->update();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
|
@ -32,7 +32,7 @@ void waybar::Client::handleGlobal(void *data, struct wl_registry *registry, uint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleGlobalRemove(void * data, struct wl_registry * /*registry*/,
|
void waybar::Client::handleGlobalRemove(void *data, struct wl_registry * /*registry*/,
|
||||||
uint32_t name) {
|
uint32_t name) {
|
||||||
// Nothing here
|
// Nothing here
|
||||||
}
|
}
|
||||||
@ -52,8 +52,8 @@ void waybar::Client::handleOutput(struct waybar_output &output) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct waybar::waybar_output &waybar::Client::getOutput(void *addr) {
|
struct waybar::waybar_output &waybar::Client::getOutput(void *addr) {
|
||||||
auto it = std::find_if(
|
auto it = std::find_if(outputs_.begin(), outputs_.end(),
|
||||||
outputs_.begin(), outputs_.end(), [&addr](const auto &output) { return &output == addr; });
|
[&addr](const auto &output) { return &output == addr; });
|
||||||
if (it == outputs_.end()) {
|
if (it == outputs_.end()) {
|
||||||
throw std::runtime_error("Unable to find valid output");
|
throw std::runtime_error("Unable to find valid output");
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ void waybar::Client::handleOutputDone(void *data, struct zxdg_output_v1 * /*xdg_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::handleOutputName(void * data, struct zxdg_output_v1 * /*xdg_output*/,
|
void waybar::Client::handleOutputName(void *data, struct zxdg_output_v1 * /*xdg_output*/,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
auto client = waybar::Client::inst();
|
auto client = waybar::Client::inst();
|
||||||
try {
|
try {
|
||||||
@ -108,7 +108,7 @@ void waybar::Client::handleOutputDescription(void *data, struct zxdg_output_v1 *
|
|||||||
const char *description) {
|
const char *description) {
|
||||||
auto client = waybar::Client::inst();
|
auto client = waybar::Client::inst();
|
||||||
try {
|
try {
|
||||||
auto & output = client->getOutput(data);
|
auto &output = client->getOutput(data);
|
||||||
const char *open_paren = strrchr(description, '(');
|
const char *open_paren = strrchr(description, '(');
|
||||||
|
|
||||||
// Description format: "identifier (name)"
|
// Description format: "identifier (name)"
|
||||||
@ -169,8 +169,8 @@ auto waybar::Client::setupCss(const std::string &css_file) -> void {
|
|||||||
throw std::runtime_error("Can't open style file");
|
throw std::runtime_error("Can't open style file");
|
||||||
}
|
}
|
||||||
// there's always only one screen
|
// there's always only one screen
|
||||||
style_context_->add_provider_for_screen(
|
style_context_->add_provider_for_screen(Gdk::Screen::get_default(), css_provider_,
|
||||||
Gdk::Screen::get_default(), css_provider_, GTK_STYLE_PROVIDER_PRIORITY_USER);
|
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::bindInterfaces() {
|
void waybar::Client::bindInterfaces() {
|
||||||
@ -195,12 +195,12 @@ void waybar::Client::bindInterfaces() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int waybar::Client::main(int argc, char *argv[]) {
|
int waybar::Client::main(int argc, char *argv[]) {
|
||||||
bool show_help = false;
|
bool show_help = false;
|
||||||
bool show_version = false;
|
bool show_version = false;
|
||||||
std::string config_opt;
|
std::string config_opt;
|
||||||
std::string style_opt;
|
std::string style_opt;
|
||||||
std::string log_level;
|
std::string log_level;
|
||||||
auto cli = clara::detail::Help(show_help) |
|
auto cli = clara::detail::Help(show_help) |
|
||||||
clara::detail::Opt(show_version)["-v"]["--version"]("Show version") |
|
clara::detail::Opt(show_version)["-v"]["--version"]("Show version") |
|
||||||
clara::detail::Opt(config_opt, "config")["-c"]["--config"]("Config path") |
|
clara::detail::Opt(config_opt, "config")["-c"]["--config"]("Config path") |
|
||||||
clara::detail::Opt(style_opt, "style")["-s"]["--style"]("Style path") |
|
clara::detail::Opt(style_opt, "style")["-s"]["--style"]("Style path") |
|
||||||
@ -224,8 +224,8 @@ int waybar::Client::main(int argc, char *argv[]) {
|
|||||||
if (!log_level.empty()) {
|
if (!log_level.empty()) {
|
||||||
spdlog::set_level(spdlog::level::from_str(log_level));
|
spdlog::set_level(spdlog::level::from_str(log_level));
|
||||||
}
|
}
|
||||||
gtk_app = Gtk::Application::create(
|
gtk_app = Gtk::Application::create(argc, argv, "fr.arouillard.waybar",
|
||||||
argc, argv, "fr.arouillard.waybar", Gio::APPLICATION_HANDLES_COMMAND_LINE);
|
Gio::APPLICATION_HANDLES_COMMAND_LINE);
|
||||||
gdk_display = Gdk::Display::get_default();
|
gdk_display = Gdk::Display::get_default();
|
||||||
if (!gdk_display) {
|
if (!gdk_display) {
|
||||||
throw std::runtime_error("Can't find display");
|
throw std::runtime_error("Can't find display");
|
||||||
@ -244,6 +244,4 @@ int waybar::Client::main(int argc, char *argv[]) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Client::reset() {
|
void waybar::Client::reset() { gtk_app->quit(); }
|
||||||
gtk_app->quit();
|
|
||||||
}
|
|
||||||
|
@ -13,12 +13,8 @@
|
|||||||
namespace waybar {
|
namespace waybar {
|
||||||
|
|
||||||
const std::vector<std::string> Config::CONFIG_DIRS = {
|
const std::vector<std::string> Config::CONFIG_DIRS = {
|
||||||
"$XDG_CONFIG_HOME/waybar/",
|
"$XDG_CONFIG_HOME/waybar/", "$HOME/.config/waybar/", "$HOME/waybar/",
|
||||||
"$HOME/.config/waybar/",
|
"/etc/xdg/waybar/", SYSCONFDIR "/xdg/waybar/", "./resources/",
|
||||||
"$HOME/waybar/",
|
|
||||||
"/etc/xdg/waybar/",
|
|
||||||
SYSCONFDIR "/xdg/waybar/",
|
|
||||||
"./resources/",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<std::string> tryExpandPath(const std::string &path) {
|
std::optional<std::string> tryExpandPath(const std::string &path) {
|
||||||
@ -55,9 +51,9 @@ void Config::setupConfig(Json::Value &dst, const std::string &config_file, int d
|
|||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
throw std::runtime_error("Can't open config file");
|
throw std::runtime_error("Can't open config file");
|
||||||
}
|
}
|
||||||
std::string str((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
std::string str((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
util::JsonParser parser;
|
util::JsonParser parser;
|
||||||
Json::Value tmp_config = parser.parse(str);
|
Json::Value tmp_config = parser.parse(str);
|
||||||
if (tmp_config.isArray()) {
|
if (tmp_config.isArray()) {
|
||||||
for (auto &config_part : tmp_config) {
|
for (auto &config_part : tmp_config) {
|
||||||
resolveConfigIncludes(config_part, depth);
|
resolveConfigIncludes(config_part, depth);
|
||||||
|
@ -12,6 +12,16 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
|||||||
return new waybar::modules::Battery(id, config_[name]);
|
return new waybar::modules::Battery(id, config_[name]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_GAMEMODE
|
||||||
|
if (ref == "gamemode") {
|
||||||
|
return new waybar::modules::Gamemode(id, config_[name]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UPOWER
|
||||||
|
if (ref == "upower") {
|
||||||
|
return new waybar::modules::upower::UPower(id, config_[name]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef HAVE_SWAY
|
#ifdef HAVE_SWAY
|
||||||
if (ref == "sway/mode") {
|
if (ref == "sway/mode") {
|
||||||
return new waybar::modules::sway::Mode(id, config_[name]);
|
return new waybar::modules::sway::Mode(id, config_[name]);
|
||||||
@ -23,7 +33,7 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
|||||||
return new waybar::modules::sway::Window(id, bar_, config_[name]);
|
return new waybar::modules::sway::Window(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
if (ref == "sway/language") {
|
if (ref == "sway/language") {
|
||||||
return new waybar::modules::sway::Language(id, config_[name]);
|
return new waybar::modules::sway::Language(id, config_[name]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_WLR
|
#ifdef HAVE_WLR
|
||||||
@ -40,6 +50,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
|||||||
if (ref == "river/tags") {
|
if (ref == "river/tags") {
|
||||||
return new waybar::modules::river::Tags(id, bar_, config_[name]);
|
return new waybar::modules::river::Tags(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
|
if (ref == "river/window") {
|
||||||
|
return new waybar::modules::river::Window(id, bar_, config_[name]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (ref == "idle_inhibitor") {
|
if (ref == "idle_inhibitor") {
|
||||||
return new waybar::modules::IdleInhibitor(id, bar_, config_[name]);
|
return new waybar::modules::IdleInhibitor(id, bar_, config_[name]);
|
||||||
@ -96,6 +109,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_GIO_UNIX
|
#ifdef HAVE_GIO_UNIX
|
||||||
|
if (ref == "bluetooth") {
|
||||||
|
return new waybar::modules::Bluetooth(id, config_[name]);
|
||||||
|
}
|
||||||
if (ref == "inhibitor") {
|
if (ref == "inhibitor") {
|
||||||
return new waybar::modules::Inhibitor(id, bar_, config_[name]);
|
return new waybar::modules::Inhibitor(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
@ -103,13 +119,6 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
|||||||
if (ref == "temperature") {
|
if (ref == "temperature") {
|
||||||
return new waybar::modules::Temperature(id, config_[name]);
|
return new waybar::modules::Temperature(id, config_[name]);
|
||||||
}
|
}
|
||||||
#if defined(__linux__)
|
|
||||||
# ifdef WANT_RFKILL
|
|
||||||
if (ref == "bluetooth") {
|
|
||||||
return new waybar::modules::Bluetooth(id, config_[name]);
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
if (ref.compare(0, 7, "custom/") == 0 && ref.size() > 7) {
|
if (ref.compare(0, 7, "custom/") == 0 && ref.size() > 7) {
|
||||||
return new waybar::modules::Custom(ref.substr(7), id, config_[name]);
|
return new waybar::modules::Custom(ref.substr(7), id, config_[name]);
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
#include "group.hpp"
|
#include "group.hpp"
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <util/command.hpp>
|
#include <util/command.hpp>
|
||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
|
|
||||||
Group::Group(const std::string& name, const Bar& bar, const Json::Value& config)
|
Group::Group(const std::string& name, const Bar& bar, const Json::Value& config)
|
||||||
: AModule(config, name, "", false, false),
|
: AModule(config, name, "", false, false),
|
||||||
box{bar.vertical ? Gtk::ORIENTATION_HORIZONTAL : Gtk::ORIENTATION_VERTICAL, 0}
|
box{bar.vertical ? Gtk::ORIENTATION_HORIZONTAL : Gtk::ORIENTATION_VERTICAL, 0} {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Group::update() -> void {
|
auto Group::update() -> void {
|
||||||
// noop
|
// noop
|
||||||
|
17
src/main.cpp
17
src/main.cpp
@ -1,9 +1,11 @@
|
|||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
|
|
||||||
std::mutex reap_mtx;
|
std::mutex reap_mtx;
|
||||||
@ -38,8 +40,7 @@ void* signalThread(void* args) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
spdlog::debug("Received signal with number {}, but not handling",
|
spdlog::debug("Received signal with number {}, but not handling", signum);
|
||||||
signum);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,9 +80,9 @@ int main(int argc, char* argv[]) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
std::signal(SIGUSR2, [](int /*signal*/) {
|
std::signal(SIGUSR2, [](int /*signal*/) {
|
||||||
spdlog::info("Reloading...");
|
spdlog::info("Reloading...");
|
||||||
reload = true;
|
reload = true;
|
||||||
waybar::Client::inst()->reset();
|
waybar::Client::inst()->reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
for (int sig = SIGRTMIN + 1; sig <= SIGRTMAX; ++sig) {
|
for (int sig = SIGRTMIN + 1; sig <= SIGRTMAX; ++sig) {
|
||||||
|
@ -93,8 +93,8 @@ waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value &
|
|||||||
{
|
{
|
||||||
std::unique_ptr<udev, UdevDeleter> udev_check{udev_new()};
|
std::unique_ptr<udev, UdevDeleter> udev_check{udev_new()};
|
||||||
check_nn(udev_check.get(), "Udev check new failed");
|
check_nn(udev_check.get(), "Udev check new failed");
|
||||||
enumerate_devices(
|
enumerate_devices(devices_.begin(), devices_.end(), std::back_inserter(devices_),
|
||||||
devices_.begin(), devices_.end(), std::back_inserter(devices_), udev_check.get());
|
udev_check.get());
|
||||||
if (devices_.empty()) {
|
if (devices_.empty()) {
|
||||||
throw std::runtime_error("No backlight found");
|
throw std::runtime_error("No backlight found");
|
||||||
}
|
}
|
||||||
@ -108,8 +108,7 @@ waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value &
|
|||||||
std::unique_ptr<udev_monitor, UdevMonitorDeleter> mon{
|
std::unique_ptr<udev_monitor, UdevMonitorDeleter> mon{
|
||||||
udev_monitor_new_from_netlink(udev.get(), "udev")};
|
udev_monitor_new_from_netlink(udev.get(), "udev")};
|
||||||
check_nn(mon.get(), "udev monitor new failed");
|
check_nn(mon.get(), "udev monitor new failed");
|
||||||
check_gte(udev_monitor_filter_add_match_subsystem_devtype(mon.get(), "backlight", nullptr),
|
check_gte(udev_monitor_filter_add_match_subsystem_devtype(mon.get(), "backlight", nullptr), 0,
|
||||||
0,
|
|
||||||
"udev failed to add monitor filter: ");
|
"udev failed to add monitor filter: ");
|
||||||
udev_monitor_enable_receiving(mon.get());
|
udev_monitor_enable_receiving(mon.get());
|
||||||
|
|
||||||
@ -126,8 +125,8 @@ waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value &
|
|||||||
epoll_event events[EPOLL_MAX_EVENTS];
|
epoll_event events[EPOLL_MAX_EVENTS];
|
||||||
|
|
||||||
while (udev_thread_.isRunning()) {
|
while (udev_thread_.isRunning()) {
|
||||||
const int event_count = epoll_wait(
|
const int event_count = epoll_wait(epoll_fd.get(), events, EPOLL_MAX_EVENTS,
|
||||||
epoll_fd.get(), events, EPOLL_MAX_EVENTS, std::chrono::milliseconds{interval_}.count());
|
std::chrono::milliseconds{interval_}.count());
|
||||||
if (!udev_thread_.isRunning()) {
|
if (!udev_thread_.isRunning()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -173,9 +172,10 @@ auto waybar::modules::Backlight::update() -> void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t percent = best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max());
|
const uint8_t percent =
|
||||||
label_.set_markup(fmt::format(
|
best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max());
|
||||||
format_, fmt::arg("percent", std::to_string(percent)), fmt::arg("icon", getIcon(percent))));
|
label_.set_markup(fmt::format(format_, fmt::arg("percent", std::to_string(percent)),
|
||||||
|
fmt::arg("icon", getIcon(percent))));
|
||||||
getState(percent);
|
getState(percent);
|
||||||
} else {
|
} else {
|
||||||
if (!previous_best_.has_value()) {
|
if (!previous_best_.has_value()) {
|
||||||
@ -214,19 +214,20 @@ void waybar::modules::Backlight::upsert_device(ForwardIt first, ForwardIt last,
|
|||||||
strncmp(name, "amdgpu_bl", 9) == 0 ? "brightness" : "actual_brightness";
|
strncmp(name, "amdgpu_bl", 9) == 0 ? "brightness" : "actual_brightness";
|
||||||
|
|
||||||
const char *actual = udev_device_get_sysattr_value(dev, actual_brightness_attr);
|
const char *actual = udev_device_get_sysattr_value(dev, actual_brightness_attr);
|
||||||
check_nn(actual);
|
|
||||||
const int actual_int = std::stoi(actual);
|
|
||||||
|
|
||||||
const char *max = udev_device_get_sysattr_value(dev, "max_brightness");
|
const char *max = udev_device_get_sysattr_value(dev, "max_brightness");
|
||||||
check_nn(max);
|
|
||||||
const int max_int = std::stoi(max);
|
|
||||||
|
|
||||||
auto found =
|
auto found =
|
||||||
std::find_if(first, last, [name](const auto &device) { return device.name() == name; });
|
std::find_if(first, last, [name](const auto &device) { return device.name() == name; });
|
||||||
if (found != last) {
|
if (found != last) {
|
||||||
found->set_actual(actual_int);
|
if (actual != nullptr) {
|
||||||
found->set_max(max_int);
|
found->set_actual(std::stoi(actual));
|
||||||
|
}
|
||||||
|
if (max != nullptr) {
|
||||||
|
found->set_max(std::stoi(max));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
const int actual_int = actual == nullptr ? 0 : std::stoi(actual);
|
||||||
|
const int max_int = max == nullptr ? 0 : std::stoi(max);
|
||||||
*inserter = BacklightDev{name, actual_int, max_int};
|
*inserter = BacklightDev{name, actual_int, max_int};
|
||||||
++inserter;
|
++inserter;
|
||||||
}
|
}
|
||||||
@ -241,7 +242,7 @@ void waybar::modules::Backlight::enumerate_devices(ForwardIt first, ForwardIt la
|
|||||||
udev_list_entry *enum_devices = udev_enumerate_get_list_entry(enumerate.get());
|
udev_list_entry *enum_devices = udev_enumerate_get_list_entry(enumerate.get());
|
||||||
udev_list_entry *dev_list_entry;
|
udev_list_entry *dev_list_entry;
|
||||||
udev_list_entry_foreach(dev_list_entry, enum_devices) {
|
udev_list_entry_foreach(dev_list_entry, enum_devices) {
|
||||||
const char * path = udev_list_entry_get_name(dev_list_entry);
|
const char *path = udev_list_entry_get_name(dev_list_entry);
|
||||||
std::unique_ptr<udev_device, UdevDeviceDeleter> dev{udev_device_new_from_syspath(udev, path)};
|
std::unique_ptr<udev_device, UdevDeviceDeleter> dev{udev_device_new_from_syspath(udev, path)};
|
||||||
check_nn(dev.get(), "dev new failed");
|
check_nn(dev.get(), "dev new failed");
|
||||||
upsert_device(first, last, inserter, dev.get());
|
upsert_device(first, last, inserter, dev.get());
|
||||||
|
@ -20,7 +20,6 @@ waybar::modules::Battery::Battery(const std::string& id, const Json::Value& conf
|
|||||||
throw std::runtime_error("Could not watch for battery plug/unplug");
|
throw std::runtime_error("Could not watch for battery plug/unplug");
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshBatteries();
|
|
||||||
worker();
|
worker();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +51,7 @@ void waybar::modules::Battery::worker() {
|
|||||||
};
|
};
|
||||||
thread_ = [this] {
|
thread_ = [this] {
|
||||||
struct inotify_event event = {0};
|
struct inotify_event event = {0};
|
||||||
int nbytes = read(battery_watch_fd_, &event, sizeof(event));
|
int nbytes = read(battery_watch_fd_, &event, sizeof(event));
|
||||||
if (nbytes != sizeof(event) || event.mask & IN_IGNORED) {
|
if (nbytes != sizeof(event) || event.mask & IN_IGNORED) {
|
||||||
thread_.stop();
|
thread_.stop();
|
||||||
return;
|
return;
|
||||||
@ -61,7 +60,7 @@ void waybar::modules::Battery::worker() {
|
|||||||
};
|
};
|
||||||
thread_battery_update_ = [this] {
|
thread_battery_update_ = [this] {
|
||||||
struct inotify_event event = {0};
|
struct inotify_event event = {0};
|
||||||
int nbytes = read(global_watch_fd_, &event, sizeof(event));
|
int nbytes = read(global_watch_fd_, &event, sizeof(event));
|
||||||
if (nbytes != sizeof(event) || event.mask & IN_IGNORED) {
|
if (nbytes != sizeof(event) || event.mask & IN_IGNORED) {
|
||||||
thread_.stop();
|
thread_.stop();
|
||||||
return;
|
return;
|
||||||
@ -73,7 +72,6 @@ void waybar::modules::Battery::worker() {
|
|||||||
|
|
||||||
void waybar::modules::Battery::refreshBatteries() {
|
void waybar::modules::Battery::refreshBatteries() {
|
||||||
std::lock_guard<std::mutex> guard(battery_list_mutex_);
|
std::lock_guard<std::mutex> guard(battery_list_mutex_);
|
||||||
|
|
||||||
// Mark existing list of batteries as not necessarily found
|
// Mark existing list of batteries as not necessarily found
|
||||||
std::map<fs::path, bool> check_map;
|
std::map<fs::path, bool> check_map;
|
||||||
for (auto const& bat : batteries_) {
|
for (auto const& bat : batteries_) {
|
||||||
@ -88,12 +86,13 @@ void waybar::modules::Battery::refreshBatteries() {
|
|||||||
auto dir_name = node.path().filename();
|
auto dir_name = node.path().filename();
|
||||||
auto bat_defined = config_["bat"].isString();
|
auto bat_defined = config_["bat"].isString();
|
||||||
if (((bat_defined && dir_name == config_["bat"].asString()) || !bat_defined) &&
|
if (((bat_defined && dir_name == config_["bat"].asString()) || !bat_defined) &&
|
||||||
fs::exists(node.path() / "capacity") && fs::exists(node.path() / "uevent") &&
|
(fs::exists(node.path() / "capacity") || fs::exists(node.path() / "charge_now")) &&
|
||||||
fs::exists(node.path() / "status") && fs::exists(node.path() / "type")) {
|
fs::exists(node.path() / "uevent") && fs::exists(node.path() / "status") &&
|
||||||
|
fs::exists(node.path() / "type")) {
|
||||||
std::string type;
|
std::string type;
|
||||||
std::ifstream(node.path() / "type") >> type;
|
std::ifstream(node.path() / "type") >> type;
|
||||||
|
|
||||||
if (!type.compare("Battery")){
|
if (!type.compare("Battery")) {
|
||||||
check_map[node.path()] = true;
|
check_map[node.path()] = true;
|
||||||
auto search = batteries_.find(node.path());
|
auto search = batteries_.find(node.path());
|
||||||
if (search == batteries_.end()) {
|
if (search == batteries_.end()) {
|
||||||
@ -116,11 +115,14 @@ void waybar::modules::Battery::refreshBatteries() {
|
|||||||
} catch (fs::filesystem_error& e) {
|
} catch (fs::filesystem_error& e) {
|
||||||
throw std::runtime_error(e.what());
|
throw std::runtime_error(e.what());
|
||||||
}
|
}
|
||||||
if (batteries_.empty()) {
|
if (warnFirstTime_ && batteries_.empty()) {
|
||||||
if (config_["bat"].isString()) {
|
if (config_["bat"].isString()) {
|
||||||
throw std::runtime_error("No battery named " + config_["bat"].asString());
|
spdlog::warn("No battery named {0}", config_["bat"].asString());
|
||||||
|
} else {
|
||||||
|
spdlog::warn("No batteries.");
|
||||||
}
|
}
|
||||||
throw std::runtime_error("No batteries.");
|
|
||||||
|
warnFirstTime_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove any batteries that are no longer present and unwatch them
|
// Remove any batteries that are no longer present and unwatch them
|
||||||
@ -137,11 +139,16 @@ void waybar::modules::Battery::refreshBatteries() {
|
|||||||
|
|
||||||
// Unknown > Full > Not charging > Discharging > Charging
|
// Unknown > Full > Not charging > Discharging > Charging
|
||||||
static bool status_gt(const std::string& a, const std::string& b) {
|
static bool status_gt(const std::string& a, const std::string& b) {
|
||||||
if (a == b) return false;
|
if (a == b)
|
||||||
else if (a == "Unknown") return true;
|
return false;
|
||||||
else if (a == "Full" && b != "Unknown") return true;
|
else if (a == "Unknown")
|
||||||
else if (a == "Not charging" && b != "Unknown" && b != "Full") return true;
|
return true;
|
||||||
else if (a == "Discharging" && b != "Unknown" && b != "Full" && b != "Not charging") return true;
|
else if (a == "Full" && b != "Unknown")
|
||||||
|
return true;
|
||||||
|
else if (a == "Not charging" && b != "Unknown" && b != "Full")
|
||||||
|
return true;
|
||||||
|
else if (a == "Discharging" && b != "Unknown" && b != "Full" && b != "Not charging")
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,30 +156,39 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
|
|||||||
std::lock_guard<std::mutex> guard(battery_list_mutex_);
|
std::lock_guard<std::mutex> guard(battery_list_mutex_);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
uint32_t total_power = 0; // μW
|
uint32_t total_power = 0; // μW
|
||||||
uint32_t total_energy = 0; // μWh
|
uint32_t total_energy = 0; // μWh
|
||||||
uint32_t total_energy_full = 0;
|
uint32_t total_energy_full = 0;
|
||||||
uint32_t total_energy_full_design = 0;
|
uint32_t total_energy_full_design = 0;
|
||||||
|
uint32_t total_capacity{0};
|
||||||
std::string status = "Unknown";
|
std::string status = "Unknown";
|
||||||
for (auto const& item : batteries_) {
|
for (auto const& item : batteries_) {
|
||||||
auto bat = item.first;
|
auto bat = item.first;
|
||||||
uint32_t power_now;
|
uint32_t power_now;
|
||||||
uint32_t energy_full;
|
uint32_t energy_full;
|
||||||
uint32_t energy_now;
|
uint32_t energy_now;
|
||||||
uint32_t energy_full_design;
|
uint32_t energy_full_design;
|
||||||
|
uint32_t capacity{0};
|
||||||
std::string _status;
|
std::string _status;
|
||||||
std::ifstream(bat / "status") >> _status;
|
std::getline(std::ifstream(bat / "status"), _status);
|
||||||
|
|
||||||
// Some battery will report current and charge in μA/μAh.
|
// Some battery will report current and charge in μA/μAh.
|
||||||
// Scale these by the voltage to get μW/μWh.
|
// Scale these by the voltage to get μW/μWh.
|
||||||
if (fs::exists(bat / "current_now")) {
|
if (fs::exists(bat / "current_now") || fs::exists(bat / "current_avg")) {
|
||||||
uint32_t voltage_now;
|
uint32_t voltage_now;
|
||||||
uint32_t current_now;
|
uint32_t current_now;
|
||||||
uint32_t charge_now;
|
uint32_t charge_now;
|
||||||
uint32_t charge_full;
|
uint32_t charge_full;
|
||||||
uint32_t charge_full_design;
|
uint32_t charge_full_design;
|
||||||
std::ifstream(bat / "voltage_now") >> voltage_now;
|
// Some batteries have only *_avg, not *_now
|
||||||
std::ifstream(bat / "current_now") >> current_now;
|
if (fs::exists(bat / "voltage_now"))
|
||||||
|
std::ifstream(bat / "voltage_now") >> voltage_now;
|
||||||
|
else
|
||||||
|
std::ifstream(bat / "voltage_avg") >> voltage_now;
|
||||||
|
if (fs::exists(bat / "current_now"))
|
||||||
|
std::ifstream(bat / "current_now") >> current_now;
|
||||||
|
else
|
||||||
|
std::ifstream(bat / "current_avg") >> current_now;
|
||||||
std::ifstream(bat / "charge_full") >> charge_full;
|
std::ifstream(bat / "charge_full") >> charge_full;
|
||||||
std::ifstream(bat / "charge_full_design") >> charge_full_design;
|
std::ifstream(bat / "charge_full_design") >> charge_full_design;
|
||||||
if (fs::exists(bat / "charge_now"))
|
if (fs::exists(bat / "charge_now"))
|
||||||
@ -187,11 +203,18 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
|
|||||||
energy_now = ((uint64_t)charge_now * (uint64_t)voltage_now) / 1000000;
|
energy_now = ((uint64_t)charge_now * (uint64_t)voltage_now) / 1000000;
|
||||||
energy_full = ((uint64_t)charge_full * (uint64_t)voltage_now) / 1000000;
|
energy_full = ((uint64_t)charge_full * (uint64_t)voltage_now) / 1000000;
|
||||||
energy_full_design = ((uint64_t)charge_full_design * (uint64_t)voltage_now) / 1000000;
|
energy_full_design = ((uint64_t)charge_full_design * (uint64_t)voltage_now) / 1000000;
|
||||||
} else {
|
} // Gamepads such as PS Dualshock provide the only capacity
|
||||||
|
else if (fs::exists(bat / "energy_now") && fs::exists(bat / "energy_full")) {
|
||||||
std::ifstream(bat / "power_now") >> power_now;
|
std::ifstream(bat / "power_now") >> power_now;
|
||||||
std::ifstream(bat / "energy_now") >> energy_now;
|
std::ifstream(bat / "energy_now") >> energy_now;
|
||||||
std::ifstream(bat / "energy_full") >> energy_full;
|
std::ifstream(bat / "energy_full") >> energy_full;
|
||||||
std::ifstream(bat / "energy_full_design") >> energy_full_design;
|
std::ifstream(bat / "energy_full_design") >> energy_full_design;
|
||||||
|
} else {
|
||||||
|
std::ifstream(bat / "capacity") >> capacity;
|
||||||
|
power_now = 0;
|
||||||
|
energy_now = 0;
|
||||||
|
energy_full = 0;
|
||||||
|
energy_full_design = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the "smallest" status among all batteries
|
// Show the "smallest" status among all batteries
|
||||||
@ -202,6 +225,7 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
|
|||||||
total_energy += energy_now;
|
total_energy += energy_now;
|
||||||
total_energy_full += energy_full;
|
total_energy_full += energy_full;
|
||||||
total_energy_full_design += energy_full_design;
|
total_energy_full_design += energy_full_design;
|
||||||
|
total_capacity += capacity;
|
||||||
}
|
}
|
||||||
if (!adapter_.empty() && status == "Discharging") {
|
if (!adapter_.empty() && status == "Discharging") {
|
||||||
bool online;
|
bool online;
|
||||||
@ -221,10 +245,15 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
|
|||||||
time_remaining = 0.0f;
|
time_remaining = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float capacity = ((float)total_energy * 100.0f / (float) total_energy_full);
|
float capacity{0.0f};
|
||||||
|
if (total_energy_full > 0.0f) {
|
||||||
|
capacity = ((float)total_energy * 100.0f / (float)total_energy_full);
|
||||||
|
} else {
|
||||||
|
capacity = (float)total_capacity;
|
||||||
|
}
|
||||||
// Handle design-capacity
|
// Handle design-capacity
|
||||||
if (config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) {
|
if (config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) {
|
||||||
capacity = ((float)total_energy * 100.0f / (float) total_energy_full_design);
|
capacity = ((float)total_energy * 100.0f / (float)total_energy_full_design);
|
||||||
}
|
}
|
||||||
// Handle full-at
|
// Handle full-at
|
||||||
if (config_["full-at"].isUInt()) {
|
if (config_["full-at"].isUInt()) {
|
||||||
@ -271,7 +300,7 @@ const std::string waybar::modules::Battery::formatTimeRemaining(float hoursRemai
|
|||||||
hoursRemaining = std::fabs(hoursRemaining);
|
hoursRemaining = std::fabs(hoursRemaining);
|
||||||
uint16_t full_hours = static_cast<uint16_t>(hoursRemaining);
|
uint16_t full_hours = static_cast<uint16_t>(hoursRemaining);
|
||||||
uint16_t minutes = static_cast<uint16_t>(60 * (hoursRemaining - full_hours));
|
uint16_t minutes = static_cast<uint16_t>(60 * (hoursRemaining - full_hours));
|
||||||
auto format = std::string("{H} h {M} min");
|
auto format = std::string("{H} h {M} min");
|
||||||
if (full_hours == 0 && minutes == 0) {
|
if (full_hours == 0 && minutes == 0) {
|
||||||
// Migh as well not show "0h 0min"
|
// Migh as well not show "0h 0min"
|
||||||
return "";
|
return "";
|
||||||
@ -283,15 +312,18 @@ const std::string waybar::modules::Battery::formatTimeRemaining(float hoursRemai
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Battery::update() -> void {
|
auto waybar::modules::Battery::update() -> void {
|
||||||
|
if (batteries_.empty()) {
|
||||||
|
event_box_.hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto [capacity, time_remaining, status, power] = getInfos();
|
auto [capacity, time_remaining, status, power] = getInfos();
|
||||||
if (status == "Unknown") {
|
if (status == "Unknown") {
|
||||||
status = getAdapterStatus(capacity);
|
status = getAdapterStatus(capacity);
|
||||||
}
|
}
|
||||||
auto status_pretty = status;
|
auto status_pretty = status;
|
||||||
// Transform to lowercase and replace space with dash
|
// Transform to lowercase and replace space with dash
|
||||||
std::transform(status.begin(), status.end(), status.begin(), [](char ch) {
|
std::transform(status.begin(), status.end(), status.begin(),
|
||||||
return ch == ' ' ? '-' : std::tolower(ch);
|
[](char ch) { return ch == ' ' ? '-' : std::tolower(ch); });
|
||||||
});
|
|
||||||
auto format = format_;
|
auto format = format_;
|
||||||
auto state = getState(capacity, true);
|
auto state = getState(capacity, true);
|
||||||
auto time_remaining_formatted = formatTimeRemaining(time_remaining);
|
auto time_remaining_formatted = formatTimeRemaining(time_remaining);
|
||||||
@ -313,8 +345,7 @@ auto waybar::modules::Battery::update() -> void {
|
|||||||
} else if (config_["tooltip-format"].isString()) {
|
} else if (config_["tooltip-format"].isString()) {
|
||||||
tooltip_format = config_["tooltip-format"].asString();
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
}
|
}
|
||||||
label_.set_tooltip_text(fmt::format(tooltip_format,
|
label_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("timeTo", tooltip_text_default),
|
||||||
fmt::arg("timeTo", tooltip_text_default),
|
|
||||||
fmt::arg("capacity", capacity),
|
fmt::arg("capacity", capacity),
|
||||||
fmt::arg("time", time_remaining_formatted)));
|
fmt::arg("time", time_remaining_formatted)));
|
||||||
}
|
}
|
||||||
@ -335,9 +366,7 @@ auto waybar::modules::Battery::update() -> void {
|
|||||||
} else {
|
} else {
|
||||||
event_box_.show();
|
event_box_.show();
|
||||||
auto icons = std::vector<std::string>{status + "-" + state, status, state};
|
auto icons = std::vector<std::string>{status + "-" + state, status, state};
|
||||||
label_.set_markup(fmt::format(format,
|
label_.set_markup(fmt::format(format, fmt::arg("capacity", capacity), fmt::arg("power", power),
|
||||||
fmt::arg("capacity", capacity),
|
|
||||||
fmt::arg("power", power),
|
|
||||||
fmt::arg("icon", getIcon(capacity, icons)),
|
fmt::arg("icon", getIcon(capacity, icons)),
|
||||||
fmt::arg("time", time_remaining_formatted)));
|
fmt::arg("time", time_remaining_formatted)));
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,391 @@
|
|||||||
#include "modules/bluetooth.hpp"
|
#include "modules/bluetooth.hpp"
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using GDBusManager = std::unique_ptr<GDBusObjectManager, void (*)(GDBusObjectManager*)>;
|
||||||
|
|
||||||
|
auto generateManager() -> GDBusManager {
|
||||||
|
GError* error = nullptr;
|
||||||
|
GDBusObjectManager* manager = g_dbus_object_manager_client_new_for_bus_sync(
|
||||||
|
G_BUS_TYPE_SYSTEM,
|
||||||
|
GDBusObjectManagerClientFlags::G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START,
|
||||||
|
"org.bluez", "/", NULL, NULL, NULL, NULL, &error);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
spdlog::error("g_dbus_object_manager_client_new_for_bus_sync() failed: {}", error->message);
|
||||||
|
g_error_free(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto destructor = [](GDBusObjectManager* manager) {
|
||||||
|
if (manager) {
|
||||||
|
g_object_unref(manager);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return GDBusManager{manager, destructor};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto getBoolProperty(GDBusProxy* proxy, const char* property_name) -> bool {
|
||||||
|
auto gvar = g_dbus_proxy_get_cached_property(proxy, property_name);
|
||||||
|
if (gvar) {
|
||||||
|
bool property_value = g_variant_get_boolean(gvar);
|
||||||
|
g_variant_unref(gvar);
|
||||||
|
return property_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::error("getBoolProperty() failed: doesn't have property {}", property_name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto getOptionalStringProperty(GDBusProxy* proxy, const char* property_name)
|
||||||
|
-> std::optional<std::string> {
|
||||||
|
auto gvar = g_dbus_proxy_get_cached_property(proxy, property_name);
|
||||||
|
if (gvar) {
|
||||||
|
std::string property_value = g_variant_get_string(gvar, NULL);
|
||||||
|
g_variant_unref(gvar);
|
||||||
|
return property_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto getStringProperty(GDBusProxy* proxy, const char* property_name) -> std::string {
|
||||||
|
auto property_value = getOptionalStringProperty(proxy, property_name);
|
||||||
|
if (!property_value.has_value()) {
|
||||||
|
spdlog::error("getStringProperty() failed: doesn't have property {}", property_name);
|
||||||
|
}
|
||||||
|
return property_value.value_or("");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto getUcharProperty(GDBusProxy* proxy, const char* property_name) -> unsigned char {
|
||||||
|
auto gvar = g_dbus_proxy_get_cached_property(proxy, property_name);
|
||||||
|
if (gvar) {
|
||||||
|
unsigned char property_value;
|
||||||
|
g_variant_get(gvar, "y", &property_value);
|
||||||
|
g_variant_unref(gvar);
|
||||||
|
|
||||||
|
return property_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::error("getUcharProperty() failed: doesn't have property {}", property_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& config)
|
waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& config)
|
||||||
: ALabel(config, "bluetooth", id, "{icon}", 10), rfkill_{RFKILL_TYPE_BLUETOOTH} {
|
: ALabel(config, "bluetooth", id, " {status}", 10),
|
||||||
|
#ifdef WANT_RFKILL
|
||||||
|
rfkill_{RFKILL_TYPE_BLUETOOTH},
|
||||||
|
#endif
|
||||||
|
manager_(generateManager()) {
|
||||||
|
|
||||||
|
if (config_["format-device-preference"].isArray()) {
|
||||||
|
std::transform(config_["format-device-preference"].begin(),
|
||||||
|
config_["format-device-preference"].end(),
|
||||||
|
std::back_inserter(device_preference_), [](auto x) { return x.asString(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: assumption made that the controller that is selcected stays unchanged
|
||||||
|
// for duration of the module
|
||||||
|
if (!findCurController(cur_controller_)) {
|
||||||
|
if (config_["controller-alias"].isString()) {
|
||||||
|
spdlog::error("findCurController() failed: no bluetooth controller found with alias '{}'",
|
||||||
|
config_["controller-alias"].asString());
|
||||||
|
} else {
|
||||||
|
spdlog::error("findCurController() failed: no bluetooth controller found");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
findConnectedDevices(cur_controller_.path, connected_devices_);
|
||||||
|
|
||||||
|
g_signal_connect(manager_.get(), "interface-proxy-properties-changed",
|
||||||
|
G_CALLBACK(onInterfaceProxyPropertiesChanged), this);
|
||||||
|
g_signal_connect(manager_.get(), "interface-added", G_CALLBACK(onInterfaceAddedOrRemoved), this);
|
||||||
|
g_signal_connect(manager_.get(), "interface-removed", G_CALLBACK(onInterfaceAddedOrRemoved),
|
||||||
|
this);
|
||||||
|
#ifdef WANT_RFKILL
|
||||||
rfkill_.on_update.connect(sigc::hide(sigc::mem_fun(*this, &Bluetooth::update)));
|
rfkill_.on_update.connect(sigc::hide(sigc::mem_fun(*this, &Bluetooth::update)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dp.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Bluetooth::update() -> void {
|
auto waybar::modules::Bluetooth::update() -> void {
|
||||||
std::string status = rfkill_.getState() ? "disabled" : "enabled";
|
// focussed device is either:
|
||||||
|
// - the first device in the device_preference_ list that is connected to the
|
||||||
|
// current controller (if none fallback to last connected device)
|
||||||
|
// - it is the last device that connected to the current controller
|
||||||
|
if (!connected_devices_.empty()) {
|
||||||
|
bool preferred_device_connected = false;
|
||||||
|
if (!device_preference_.empty()) {
|
||||||
|
for (const std::string& device_alias : device_preference_) {
|
||||||
|
auto it =
|
||||||
|
std::find_if(connected_devices_.begin(), connected_devices_.end(),
|
||||||
|
[device_alias](auto device) { return device_alias == device.alias; });
|
||||||
|
if (it != connected_devices_.end()) {
|
||||||
|
preferred_device_connected = true;
|
||||||
|
cur_focussed_device_ = *it;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!preferred_device_connected) {
|
||||||
|
cur_focussed_device_ = connected_devices_.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
label_.set_markup(
|
std::string state;
|
||||||
fmt::format(format_, fmt::arg("status", status), fmt::arg("icon", getIcon(0, status))));
|
std::string tooltip_format;
|
||||||
|
if (!cur_controller_.powered)
|
||||||
|
state = "off";
|
||||||
|
else if (!connected_devices_.empty())
|
||||||
|
state = "connected";
|
||||||
|
else
|
||||||
|
state = "on";
|
||||||
|
#ifdef WANT_RFKILL
|
||||||
|
if (rfkill_.getState()) state = "disabled";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!alt_) {
|
||||||
|
if (state == "connected" && cur_focussed_device_.battery_percentage.has_value() &&
|
||||||
|
config_["format-connected-battery"].isString()) {
|
||||||
|
format_ = config_["format-connected-battery"].asString();
|
||||||
|
} else if (config_["format-" + state].isString()) {
|
||||||
|
format_ = config_["format-" + state].asString();
|
||||||
|
} else if (config_["format"].isString()) {
|
||||||
|
format_ = config_["format"].asString();
|
||||||
|
} else {
|
||||||
|
format_ = default_format_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (config_["tooltip-format-" + state].isString()) {
|
||||||
|
tooltip_format = config_["tooltip-format-" + state].asString();
|
||||||
|
} else if (config_["tooltip-format"].isString()) {
|
||||||
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
format_.empty() ? event_box_.hide() : event_box_.show();
|
||||||
|
|
||||||
|
auto update_style_context = [this](const std::string& style_class, bool in_next_state) {
|
||||||
|
if (in_next_state && !label_.get_style_context()->has_class(style_class)) {
|
||||||
|
label_.get_style_context()->add_class(style_class);
|
||||||
|
} else if (!in_next_state && label_.get_style_context()->has_class(style_class)) {
|
||||||
|
label_.get_style_context()->remove_class(style_class);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
update_style_context("discoverable", cur_controller_.discoverable);
|
||||||
|
update_style_context("discovering", cur_controller_.discovering);
|
||||||
|
update_style_context("pairable", cur_controller_.pairable);
|
||||||
|
if (!state_.empty()) {
|
||||||
|
update_style_context(state_, false);
|
||||||
|
}
|
||||||
|
update_style_context(state, true);
|
||||||
|
state_ = state;
|
||||||
|
|
||||||
|
label_.set_markup(fmt::format(
|
||||||
|
format_, fmt::arg("status", state_), fmt::arg("num_connections", connected_devices_.size()),
|
||||||
|
fmt::arg("controller_address", cur_controller_.address),
|
||||||
|
fmt::arg("controller_address_type", cur_controller_.address_type),
|
||||||
|
fmt::arg("controller_alias", cur_controller_.alias),
|
||||||
|
fmt::arg("device_address", cur_focussed_device_.address),
|
||||||
|
fmt::arg("device_address_type", cur_focussed_device_.address_type),
|
||||||
|
fmt::arg("device_alias", cur_focussed_device_.alias),
|
||||||
|
fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0))));
|
||||||
|
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
if (config_["tooltip-format"].isString()) {
|
bool tooltip_enumerate_connections_ = config_["tooltip-format-enumerate-connected"].isString();
|
||||||
auto tooltip_format = config_["tooltip-format"].asString();
|
bool tooltip_enumerate_connections_battery_ =
|
||||||
auto tooltip_text = fmt::format(tooltip_format, status, fmt::arg("status", status));
|
config_["tooltip-format-enumerate-connected-battery"].isString();
|
||||||
label_.set_tooltip_text(tooltip_text);
|
if (tooltip_enumerate_connections_ || tooltip_enumerate_connections_battery_) {
|
||||||
} else {
|
std::stringstream ss;
|
||||||
label_.set_tooltip_text(status);
|
for (DeviceInfo dev : connected_devices_) {
|
||||||
|
if ((tooltip_enumerate_connections_battery_ && dev.battery_percentage.has_value()) ||
|
||||||
|
tooltip_enumerate_connections_) {
|
||||||
|
ss << "\n";
|
||||||
|
std::string enumerate_format =
|
||||||
|
(tooltip_enumerate_connections_battery_ && dev.battery_percentage.has_value())
|
||||||
|
? config_["tooltip-format-enumerate-connected-battery"].asString()
|
||||||
|
: config_["tooltip-format-enumerate-connected"].asString();
|
||||||
|
ss << fmt::format(
|
||||||
|
enumerate_format, fmt::arg("device_address", dev.address),
|
||||||
|
fmt::arg("device_address_type", dev.address_type),
|
||||||
|
fmt::arg("device_alias", dev.alias),
|
||||||
|
fmt::arg("device_battery_percentage", dev.battery_percentage.value_or(0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
device_enumerate_ = ss.str();
|
||||||
|
// don't start the connected devices text with a new line
|
||||||
|
if (!device_enumerate_.empty()) {
|
||||||
|
device_enumerate_.erase(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
label_.set_tooltip_text(fmt::format(
|
||||||
|
tooltip_format, fmt::arg("status", state_),
|
||||||
|
fmt::arg("num_connections", connected_devices_.size()),
|
||||||
|
fmt::arg("controller_address", cur_controller_.address),
|
||||||
|
fmt::arg("controller_address_type", cur_controller_.address_type),
|
||||||
|
fmt::arg("controller_alias", cur_controller_.alias),
|
||||||
|
fmt::arg("device_address", cur_focussed_device_.address),
|
||||||
|
fmt::arg("device_address_type", cur_focussed_device_.address_type),
|
||||||
|
fmt::arg("device_alias", cur_focussed_device_.alias),
|
||||||
|
fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0)),
|
||||||
|
fmt::arg("device_enumerate", device_enumerate_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call parent update
|
||||||
|
ALabel::update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: only for when the org.bluez.Battery1 interface is added/removed after/before a device is
|
||||||
|
// connected/disconnected
|
||||||
|
auto waybar::modules::Bluetooth::onInterfaceAddedOrRemoved(GDBusObjectManager* manager,
|
||||||
|
GDBusObject* object,
|
||||||
|
GDBusInterface* interface,
|
||||||
|
gpointer user_data) -> void {
|
||||||
|
std::string interface_name = g_dbus_proxy_get_interface_name(G_DBUS_PROXY(interface));
|
||||||
|
std::string object_path = g_dbus_proxy_get_object_path(G_DBUS_PROXY(interface));
|
||||||
|
if (interface_name == "org.bluez.Battery1") {
|
||||||
|
Bluetooth* bt = static_cast<Bluetooth*>(user_data);
|
||||||
|
auto device = std::find_if(bt->connected_devices_.begin(), bt->connected_devices_.end(),
|
||||||
|
[object_path](auto d) { return d.path == object_path; });
|
||||||
|
if (device != bt->connected_devices_.end()) {
|
||||||
|
device->battery_percentage = bt->getDeviceBatteryPercentage(object);
|
||||||
|
bt->dp.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(
|
||||||
|
GDBusObjectManagerClient* manager, GDBusObjectProxy* object_proxy, GDBusProxy* interface_proxy,
|
||||||
|
GVariant* changed_properties, const gchar* const* invalidated_properties, gpointer user_data)
|
||||||
|
-> void {
|
||||||
|
std::string interface_name = g_dbus_proxy_get_interface_name(interface_proxy);
|
||||||
|
std::string object_path = g_dbus_object_get_object_path(G_DBUS_OBJECT(object_proxy));
|
||||||
|
|
||||||
|
Bluetooth* bt = static_cast<Bluetooth*>(user_data);
|
||||||
|
if (interface_name == "org.bluez.Adapter1") {
|
||||||
|
if (object_path == bt->cur_controller_.path) {
|
||||||
|
bt->getControllerProperties(G_DBUS_OBJECT(object_proxy), bt->cur_controller_);
|
||||||
|
bt->dp.emit();
|
||||||
|
}
|
||||||
|
} else if (interface_name == "org.bluez.Device1" || interface_name == "org.bluez.Battery1") {
|
||||||
|
DeviceInfo device;
|
||||||
|
bt->getDeviceProperties(G_DBUS_OBJECT(object_proxy), device);
|
||||||
|
auto cur_device = std::find_if(bt->connected_devices_.begin(), bt->connected_devices_.end(),
|
||||||
|
[device](auto d) { return d.path == device.path; });
|
||||||
|
if (cur_device == bt->connected_devices_.end()) {
|
||||||
|
if (device.connected) {
|
||||||
|
bt->connected_devices_.push_back(device);
|
||||||
|
bt->dp.emit();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!device.connected) {
|
||||||
|
bt->connected_devices_.erase(cur_device);
|
||||||
|
} else {
|
||||||
|
*cur_device = device;
|
||||||
|
}
|
||||||
|
bt->dp.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto waybar::modules::Bluetooth::getDeviceBatteryPercentage(GDBusObject* object)
|
||||||
|
-> std::optional<unsigned char> {
|
||||||
|
GDBusProxy* proxy_device_bat =
|
||||||
|
G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Battery1"));
|
||||||
|
if (proxy_device_bat != NULL) {
|
||||||
|
unsigned char battery_percentage = getUcharProperty(proxy_device_bat, "Percentage");
|
||||||
|
g_object_unref(proxy_device_bat);
|
||||||
|
|
||||||
|
return battery_percentage;
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto waybar::modules::Bluetooth::getDeviceProperties(GDBusObject* object, DeviceInfo& device_info)
|
||||||
|
-> bool {
|
||||||
|
GDBusProxy* proxy_device = G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Device1"));
|
||||||
|
|
||||||
|
if (proxy_device != NULL) {
|
||||||
|
device_info.path = g_dbus_object_get_object_path(object);
|
||||||
|
device_info.paired_controller = getStringProperty(proxy_device, "Adapter");
|
||||||
|
device_info.address = getStringProperty(proxy_device, "Address");
|
||||||
|
device_info.address_type = getStringProperty(proxy_device, "AddressType");
|
||||||
|
device_info.alias = getStringProperty(proxy_device, "Alias");
|
||||||
|
device_info.icon = getOptionalStringProperty(proxy_device, "Icon");
|
||||||
|
device_info.paired = getBoolProperty(proxy_device, "Paired");
|
||||||
|
device_info.trusted = getBoolProperty(proxy_device, "Trusted");
|
||||||
|
device_info.blocked = getBoolProperty(proxy_device, "Blocked");
|
||||||
|
device_info.connected = getBoolProperty(proxy_device, "Connected");
|
||||||
|
device_info.services_resolved = getBoolProperty(proxy_device, "ServicesResolved");
|
||||||
|
|
||||||
|
g_object_unref(proxy_device);
|
||||||
|
|
||||||
|
device_info.battery_percentage = getDeviceBatteryPercentage(object);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto waybar::modules::Bluetooth::getControllerProperties(GDBusObject* object,
|
||||||
|
ControllerInfo& controller_info) -> bool {
|
||||||
|
GDBusProxy* proxy_controller =
|
||||||
|
G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Adapter1"));
|
||||||
|
|
||||||
|
if (proxy_controller != NULL) {
|
||||||
|
controller_info.path = g_dbus_object_get_object_path(object);
|
||||||
|
controller_info.address = getStringProperty(proxy_controller, "Address");
|
||||||
|
controller_info.address_type = getStringProperty(proxy_controller, "AddressType");
|
||||||
|
controller_info.alias = getStringProperty(proxy_controller, "Alias");
|
||||||
|
controller_info.powered = getBoolProperty(proxy_controller, "Powered");
|
||||||
|
controller_info.discoverable = getBoolProperty(proxy_controller, "Discoverable");
|
||||||
|
controller_info.pairable = getBoolProperty(proxy_controller, "Pairable");
|
||||||
|
controller_info.discovering = getBoolProperty(proxy_controller, "Discovering");
|
||||||
|
|
||||||
|
g_object_unref(proxy_controller);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto waybar::modules::Bluetooth::findCurController(ControllerInfo& controller_info) -> bool {
|
||||||
|
bool found_controller = false;
|
||||||
|
|
||||||
|
GList* objects = g_dbus_object_manager_get_objects(manager_.get());
|
||||||
|
for (GList* l = objects; l != NULL; l = l->next) {
|
||||||
|
GDBusObject* object = G_DBUS_OBJECT(l->data);
|
||||||
|
if (getControllerProperties(object, controller_info) &&
|
||||||
|
(!config_["controller-alias"].isString() ||
|
||||||
|
config_["controller-alias"].asString() == controller_info.alias)) {
|
||||||
|
found_controller = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_list_free_full(objects, g_object_unref);
|
||||||
|
|
||||||
|
return found_controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto waybar::modules::Bluetooth::findConnectedDevices(const std::string& cur_controller_path,
|
||||||
|
std::vector<DeviceInfo>& connected_devices)
|
||||||
|
-> void {
|
||||||
|
GList* objects = g_dbus_object_manager_get_objects(manager_.get());
|
||||||
|
for (GList* l = objects; l != NULL; l = l->next) {
|
||||||
|
GDBusObject* object = G_DBUS_OBJECT(l->data);
|
||||||
|
DeviceInfo device;
|
||||||
|
if (getDeviceProperties(object, device) && device.connected &&
|
||||||
|
device.paired_controller == cur_controller_.path) {
|
||||||
|
connected_devices.push_back(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_list_free_full(objects, g_object_unref);
|
||||||
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "modules/clock.hpp"
|
#include "modules/clock.hpp"
|
||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
#if FMT_VERSION < 60000
|
#if FMT_VERSION < 60000
|
||||||
#include <fmt/time.h>
|
#include <fmt/time.h>
|
||||||
#else
|
#else
|
||||||
@ -23,47 +25,45 @@ using waybar::waybar_time;
|
|||||||
waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
||||||
: ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true),
|
: ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true),
|
||||||
current_time_zone_idx_(0),
|
current_time_zone_idx_(0),
|
||||||
is_calendar_in_tooltip_(false)
|
is_calendar_in_tooltip_(false),
|
||||||
{
|
is_timezoned_list_in_tooltip_(false) {
|
||||||
if (config_["timezones"].isArray() && !config_["timezones"].empty()) {
|
if (config_["timezones"].isArray() && !config_["timezones"].empty()) {
|
||||||
for (const auto& zone_name: config_["timezones"]) {
|
for (const auto& zone_name : config_["timezones"]) {
|
||||||
if (!zone_name.isString() || zone_name.asString().empty()) {
|
if (!zone_name.isString() || zone_name.asString().empty()) {
|
||||||
time_zones_.push_back(nullptr);
|
time_zones_.push_back(nullptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
time_zones_.push_back(
|
time_zones_.push_back(date::locate_zone(zone_name.asString()));
|
||||||
date::locate_zone(
|
|
||||||
zone_name.asString()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else if (config_["timezone"].isString() && !config_["timezone"].asString().empty()) {
|
} else if (config_["timezone"].isString() && !config_["timezone"].asString().empty()) {
|
||||||
time_zones_.push_back(
|
time_zones_.push_back(date::locate_zone(config_["timezone"].asString()));
|
||||||
date::locate_zone(
|
|
||||||
config_["timezone"].asString()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If all timezones are parsed and no one is good, add nullptr to the timezones vector, to mark that local time should be shown.
|
// If all timezones are parsed and no one is good, add nullptr to the timezones vector, to mark
|
||||||
|
// that local time should be shown.
|
||||||
if (!time_zones_.size()) {
|
if (!time_zones_.size()) {
|
||||||
time_zones_.push_back(nullptr);
|
time_zones_.push_back(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_timezone_fixed()) {
|
if (!is_timezone_fixed()) {
|
||||||
spdlog::warn("As using a timezone, some format args may be missing as the date library haven't got a release since 2018.");
|
spdlog::warn(
|
||||||
|
"As using a timezone, some format args may be missing as the date library haven't got a "
|
||||||
|
"release since 2018.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a particular placeholder is present in the tooltip format, to know what to calculate on update.
|
// Check if a particular placeholder is present in the tooltip format, to know what to calculate
|
||||||
|
// on update.
|
||||||
if (config_["tooltip-format"].isString()) {
|
if (config_["tooltip-format"].isString()) {
|
||||||
std::string trimmed_format = config_["tooltip-format"].asString();
|
std::string trimmed_format = config_["tooltip-format"].asString();
|
||||||
trimmed_format.erase(std::remove_if(trimmed_format.begin(),
|
trimmed_format.erase(std::remove_if(trimmed_format.begin(), trimmed_format.end(),
|
||||||
trimmed_format.end(),
|
[](unsigned char x) { return std::isspace(x); }),
|
||||||
[](unsigned char x){return std::isspace(x);}),
|
trimmed_format.end());
|
||||||
trimmed_format.end());
|
|
||||||
if (trimmed_format.find("{" + kCalendarPlaceholder + "}") != std::string::npos) {
|
if (trimmed_format.find("{" + kCalendarPlaceholder + "}") != std::string::npos) {
|
||||||
is_calendar_in_tooltip_ = true;
|
is_calendar_in_tooltip_ = true;
|
||||||
}
|
}
|
||||||
|
if (trimmed_format.find("{" + KTimezonedTimeListPlaceholder + "}") != std::string::npos) {
|
||||||
|
is_timezoned_list_in_tooltip_ = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config_["locale"].isString()) {
|
if (config_["locale"].isString()) {
|
||||||
@ -75,14 +75,16 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
|||||||
thread_ = [this] {
|
thread_ = [this] {
|
||||||
dp.emit();
|
dp.emit();
|
||||||
auto now = std::chrono::system_clock::now();
|
auto now = std::chrono::system_clock::now();
|
||||||
auto timeout = std::chrono::floor<std::chrono::seconds>(now + interval_);
|
/* difference with projected wakeup time */
|
||||||
auto diff = std::chrono::seconds(timeout.time_since_epoch().count() % interval_.count());
|
auto diff = now.time_since_epoch() % interval_;
|
||||||
thread_.sleep_until(timeout - diff);
|
/* sleep until the next projected time */
|
||||||
|
thread_.sleep_for(interval_ - diff);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const date::time_zone* waybar::modules::Clock::current_timezone() {
|
const date::time_zone* waybar::modules::Clock::current_timezone() {
|
||||||
return time_zones_[current_time_zone_idx_] ? time_zones_[current_time_zone_idx_] : date::current_zone();
|
return time_zones_[current_time_zone_idx_] ? time_zones_[current_time_zone_idx_]
|
||||||
|
: date::current_zone();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waybar::modules::Clock::is_timezone_fixed() {
|
bool waybar::modules::Clock::is_timezone_fixed() {
|
||||||
@ -99,7 +101,7 @@ auto waybar::modules::Clock::update() -> void {
|
|||||||
// As date dep is not fully compatible, prefer fmt
|
// As date dep is not fully compatible, prefer fmt
|
||||||
tzset();
|
tzset();
|
||||||
auto localtime = fmt::localtime(std::chrono::system_clock::to_time_t(now));
|
auto localtime = fmt::localtime(std::chrono::system_clock::to_time_t(now));
|
||||||
text = fmt::format(format_, localtime);
|
text = fmt::format(locale_, format_, localtime);
|
||||||
} else {
|
} else {
|
||||||
text = fmt::format(format_, wtime);
|
text = fmt::format(format_, wtime);
|
||||||
}
|
}
|
||||||
@ -108,20 +110,26 @@ auto waybar::modules::Clock::update() -> void {
|
|||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
if (config_["tooltip-format"].isString()) {
|
if (config_["tooltip-format"].isString()) {
|
||||||
std::string calendar_lines = "";
|
std::string calendar_lines = "";
|
||||||
|
std::string timezoned_time_lines = "";
|
||||||
if (is_calendar_in_tooltip_) {
|
if (is_calendar_in_tooltip_) {
|
||||||
calendar_lines = calendar_text(wtime);
|
calendar_lines = calendar_text(wtime);
|
||||||
}
|
}
|
||||||
|
if (is_timezoned_list_in_tooltip_) {
|
||||||
|
timezoned_time_lines = timezones_text(&now);
|
||||||
|
}
|
||||||
auto tooltip_format = config_["tooltip-format"].asString();
|
auto tooltip_format = config_["tooltip-format"].asString();
|
||||||
text = fmt::format(tooltip_format, wtime, fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines));
|
text =
|
||||||
|
fmt::format(tooltip_format, wtime, fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines),
|
||||||
|
fmt::arg(KTimezonedTimeListPlaceholder.c_str(), timezoned_time_lines));
|
||||||
|
label_.set_tooltip_markup(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
label_.set_tooltip_markup(text);
|
|
||||||
// Call parent update
|
// Call parent update
|
||||||
ALabel::update();
|
ALabel::update();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waybar::modules::Clock::handleScroll(GdkEventScroll *e) {
|
bool waybar::modules::Clock::handleScroll(GdkEventScroll* e) {
|
||||||
// defer to user commands if set
|
// defer to user commands if set
|
||||||
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) {
|
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) {
|
||||||
return AModule::handleScroll(e);
|
return AModule::handleScroll(e);
|
||||||
@ -140,7 +148,8 @@ bool waybar::modules::Clock::handleScroll(GdkEventScroll *e) {
|
|||||||
size_t new_idx = current_time_zone_idx_ + 1;
|
size_t new_idx = current_time_zone_idx_ + 1;
|
||||||
current_time_zone_idx_ = new_idx == nr_zones ? 0 : new_idx;
|
current_time_zone_idx_ = new_idx == nr_zones ? 0 : new_idx;
|
||||||
} else {
|
} else {
|
||||||
current_time_zone_idx_ = current_time_zone_idx_ == 0 ? nr_zones - 1 : current_time_zone_idx_ - 1;
|
current_time_zone_idx_ =
|
||||||
|
current_time_zone_idx_ == 0 ? nr_zones - 1 : current_time_zone_idx_ - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
update();
|
update();
|
||||||
@ -155,12 +164,35 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str
|
|||||||
}
|
}
|
||||||
|
|
||||||
const date::year_month ym(ymd.year(), ymd.month());
|
const date::year_month ym(ymd.year(), ymd.month());
|
||||||
const auto curr_day = ymd.day();
|
const auto curr_day = ymd.day();
|
||||||
|
|
||||||
std::stringstream os;
|
std::stringstream os;
|
||||||
const auto first_dow = first_day_of_week();
|
|
||||||
weekdays_header(first_dow, os);
|
|
||||||
|
|
||||||
|
const auto first_dow = first_day_of_week();
|
||||||
|
int ws{0}; // weeks-pos: side(1 - left, 2 - right)
|
||||||
|
int wn{0}; // weeknumber
|
||||||
|
if (config_["calendar-weeks-pos"].isString()) {
|
||||||
|
wn = (date::sys_days{date::year_month_day{ym / 1}} -
|
||||||
|
date::sys_days{date::year_month_day{ymd.year() / 1 / 1}})
|
||||||
|
.count() /
|
||||||
|
7 +
|
||||||
|
1;
|
||||||
|
if (config_["calendar-weeks-pos"].asString() == "left") {
|
||||||
|
ws = 1;
|
||||||
|
// Add paddings before the header
|
||||||
|
os << std::string(4, ' ');
|
||||||
|
} else if (config_["calendar-weeks-pos"].asString() == "right") {
|
||||||
|
ws = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
weekdays_header(first_dow, os);
|
||||||
|
/* Print weeknumber on the left for the first row*/
|
||||||
|
if (ws == 1) {
|
||||||
|
print_iso_weeknum(os, wn);
|
||||||
|
os << ' ';
|
||||||
|
++wn;
|
||||||
|
}
|
||||||
// First week prefixed with spaces if needed.
|
// First week prefixed with spaces if needed.
|
||||||
auto wd = date::weekday(ym / 1);
|
auto wd = date::weekday(ym / 1);
|
||||||
auto empty_days = (wd - first_dow).count();
|
auto empty_days = (wd - first_dow).count();
|
||||||
@ -172,7 +204,19 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str
|
|||||||
if (wd != first_dow) {
|
if (wd != first_dow) {
|
||||||
os << ' ';
|
os << ' ';
|
||||||
} else if (unsigned(d) != 1) {
|
} else if (unsigned(d) != 1) {
|
||||||
|
if (ws == 2) {
|
||||||
|
os << ' ';
|
||||||
|
print_iso_weeknum(os, wn);
|
||||||
|
++wn;
|
||||||
|
}
|
||||||
|
|
||||||
os << '\n';
|
os << '\n';
|
||||||
|
|
||||||
|
if (ws == 1) {
|
||||||
|
print_iso_weeknum(os, wn);
|
||||||
|
os << ' ';
|
||||||
|
++wn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (d == curr_day) {
|
if (d == curr_day) {
|
||||||
if (config_["today-format"].isString()) {
|
if (config_["today-format"].isString()) {
|
||||||
@ -181,8 +225,17 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str
|
|||||||
} else {
|
} else {
|
||||||
os << "<b><u>" << date::format("%e", d) << "</u></b>";
|
os << "<b><u>" << date::format("%e", d) << "</u></b>";
|
||||||
}
|
}
|
||||||
} else {
|
} else if (config_["format-calendar"].isString()) {
|
||||||
|
os << fmt::format(config_["format-calendar"].asString(), date::format("%e", d));
|
||||||
|
} else
|
||||||
os << date::format("%e", d);
|
os << date::format("%e", d);
|
||||||
|
/*Print weeks on the right when the endings with spaces*/
|
||||||
|
if (ws == 2 && d == last_day) {
|
||||||
|
empty_days = 6 - (wd.c_encoding() - first_dow.c_encoding());
|
||||||
|
if (empty_days > 0) {
|
||||||
|
os << std::string(empty_days * 3 + 1, ' ');
|
||||||
|
print_iso_weeknum(os, wn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,21 +247,58 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str
|
|||||||
|
|
||||||
auto waybar::modules::Clock::weekdays_header(const date::weekday& first_dow, std::ostream& os)
|
auto waybar::modules::Clock::weekdays_header(const date::weekday& first_dow, std::ostream& os)
|
||||||
-> void {
|
-> void {
|
||||||
|
std::stringstream res;
|
||||||
auto wd = first_dow;
|
auto wd = first_dow;
|
||||||
do {
|
do {
|
||||||
if (wd != first_dow) os << ' ';
|
if (wd != first_dow) res << ' ';
|
||||||
Glib::ustring wd_ustring(date::format(locale_, "%a", wd));
|
Glib::ustring wd_ustring(date::format(locale_, "%a", wd));
|
||||||
auto clen = ustring_clen(wd_ustring);
|
auto clen = ustring_clen(wd_ustring);
|
||||||
auto wd_len = wd_ustring.length();
|
auto wd_len = wd_ustring.length();
|
||||||
while (clen > 2) {
|
while (clen > 2) {
|
||||||
wd_ustring = wd_ustring.substr(0, wd_len-1);
|
wd_ustring = wd_ustring.substr(0, wd_len - 1);
|
||||||
wd_len--;
|
wd_len--;
|
||||||
clen = ustring_clen(wd_ustring);
|
clen = ustring_clen(wd_ustring);
|
||||||
}
|
}
|
||||||
const std::string pad(2 - clen, ' ');
|
const std::string pad(2 - clen, ' ');
|
||||||
os << pad << wd_ustring;
|
res << pad << wd_ustring;
|
||||||
} while (++wd != first_dow);
|
} while (++wd != first_dow);
|
||||||
os << "\n";
|
res << "\n";
|
||||||
|
|
||||||
|
if (config_["format-calendar-weekdays"].isString()) {
|
||||||
|
os << fmt::format(config_["format-calendar-weekdays"].asString(), res.str());
|
||||||
|
} else
|
||||||
|
os << res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto waybar::modules::Clock::timezones_text(std::chrono::system_clock::time_point* now)
|
||||||
|
-> std::string {
|
||||||
|
if (time_zones_.size() == 1) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
std::stringstream os;
|
||||||
|
waybar_time wtime;
|
||||||
|
for (size_t time_zone_idx = 0; time_zone_idx < time_zones_.size(); ++time_zone_idx) {
|
||||||
|
if (static_cast<int>(time_zone_idx) == current_time_zone_idx_) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const date::time_zone* timezone = time_zones_[time_zone_idx];
|
||||||
|
if (!timezone) {
|
||||||
|
timezone = date::current_zone();
|
||||||
|
}
|
||||||
|
wtime = {locale_, date::make_zoned(timezone, date::floor<std::chrono::seconds>(*now))};
|
||||||
|
os << fmt::format(format_, wtime) << "\n";
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto waybar::modules::Clock::print_iso_weeknum(std::ostream& os, int weeknum) -> void {
|
||||||
|
std::stringstream res;
|
||||||
|
res << std::setfill('0') << std::setw(2) << weeknum;
|
||||||
|
|
||||||
|
if (config_["format-calendar-weeks"].isString()) {
|
||||||
|
os << fmt::format(config_["format-calendar-weeks"].asString(), res.str());
|
||||||
|
} else
|
||||||
|
os << res.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LANGINFO_1STDAY
|
#ifdef HAVE_LANGINFO_1STDAY
|
||||||
@ -226,9 +316,9 @@ auto waybar::modules::Clock::first_day_of_week() -> date::weekday {
|
|||||||
newlocale(LC_ALL, locale_.name().c_str(), nullptr)};
|
newlocale(LC_ALL, locale_.name().c_str(), nullptr)};
|
||||||
if (posix_locale) {
|
if (posix_locale) {
|
||||||
const int i = (std::intptr_t)nl_langinfo_l(_NL_TIME_WEEK_1STDAY, posix_locale.get());
|
const int i = (std::intptr_t)nl_langinfo_l(_NL_TIME_WEEK_1STDAY, posix_locale.get());
|
||||||
auto ymd = date::year(i / 10000) / (i / 100 % 100) / (i % 100);
|
auto ymd = date::year(i / 10000) / (i / 100 % 100) / (i % 100);
|
||||||
auto wd = date::weekday(ymd);
|
auto wd = date::weekday(ymd);
|
||||||
uint8_t j = *nl_langinfo_l(_NL_TIME_FIRST_WEEKDAY, posix_locale.get());
|
uint8_t j = *nl_langinfo_l(_NL_TIME_FIRST_WEEKDAY, posix_locale.get());
|
||||||
return wd + date::days(j - 1);
|
return wd + date::days(j - 1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
#include "modules/cpu.hpp"
|
#include <spdlog/spdlog.h>
|
||||||
|
// clang-format off
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <spdlog/spdlog.h>
|
// clang-format on
|
||||||
#include <cstdlib> // malloc
|
#include <unistd.h> // sysconf
|
||||||
#include <unistd.h> // sysconf
|
|
||||||
#include <cmath> // NAN
|
#include <cmath> // NAN
|
||||||
|
#include <cstdlib> // malloc
|
||||||
|
|
||||||
|
#include "modules/cpu.hpp"
|
||||||
|
|
||||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
# include <sys/sched.h>
|
#include <sys/sched.h>
|
||||||
#else
|
#else
|
||||||
# include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__NetBSD__)
|
#if defined(__NetBSD__)
|
||||||
@ -32,26 +35,26 @@ std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
|
|||||||
pcp_time_t *cp_time = static_cast<pcp_time_t *>(malloc(sz)), *pcp_time = cp_time;
|
pcp_time_t *cp_time = static_cast<pcp_time_t *>(malloc(sz)), *pcp_time = cp_time;
|
||||||
#if defined(__NetBSD__)
|
#if defined(__NetBSD__)
|
||||||
int mib[] = {
|
int mib[] = {
|
||||||
CTL_KERN,
|
CTL_KERN,
|
||||||
KERN_CP_TIME,
|
KERN_CP_TIME,
|
||||||
};
|
};
|
||||||
if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), sum_cp_time, &sum_sz, NULL, 0)) {
|
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), sum_cp_time, &sum_sz, NULL, 0)) {
|
||||||
throw std::runtime_error("sysctl kern.cp_time failed");
|
throw std::runtime_error("sysctl kern.cp_time failed");
|
||||||
}
|
}
|
||||||
for (int state = 0; state < CPUSTATES; state++) {
|
for (int state = 0; state < CPUSTATES; state++) {
|
||||||
cp_time[state] = sum_cp_time[state];
|
cp_time[state] = sum_cp_time[state];
|
||||||
}
|
}
|
||||||
pcp_time += CPUSTATES;
|
pcp_time += CPUSTATES;
|
||||||
if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), pcp_time, &sz, NULL, 0)) {
|
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), pcp_time, &sz, NULL, 0)) {
|
||||||
throw std::runtime_error("sysctl kern.cp_time failed");
|
throw std::runtime_error("sysctl kern.cp_time failed");
|
||||||
}
|
}
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__)
|
||||||
{
|
{
|
||||||
int mib[] = {
|
int mib[] = {
|
||||||
CTL_KERN,
|
CTL_KERN,
|
||||||
KERN_CPTIME,
|
KERN_CPTIME,
|
||||||
};
|
};
|
||||||
if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), sum_cp_time, &sum_sz, NULL, 0)) {
|
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), sum_cp_time, &sum_sz, NULL, 0)) {
|
||||||
throw std::runtime_error("sysctl kern.cp_time failed");
|
throw std::runtime_error("sysctl kern.cp_time failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,14 +65,14 @@ std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
|
|||||||
sz /= ncpu + 1;
|
sz /= ncpu + 1;
|
||||||
{
|
{
|
||||||
int mib[] = {
|
int mib[] = {
|
||||||
CTL_KERN,
|
CTL_KERN,
|
||||||
KERN_CPTIME2,
|
KERN_CPTIME2,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
for (int cpu = 0; cpu < ncpu; cpu++) {
|
for (int cpu = 0; cpu < ncpu; cpu++) {
|
||||||
mib[2] = cpu;
|
mib[2] = cpu;
|
||||||
pcp_time += CPUSTATES;
|
pcp_time += CPUSTATES;
|
||||||
if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), pcp_time, &sz, NULL, 0)) {
|
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), pcp_time, &sz, NULL, 0)) {
|
||||||
throw std::runtime_error("sysctl kern.cp_time2 failed");
|
throw std::runtime_error("sysctl kern.cp_time2 failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +104,8 @@ std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
|
|||||||
std::vector<float> waybar::modules::Cpu::parseCpuFrequencies() {
|
std::vector<float> waybar::modules::Cpu::parseCpuFrequencies() {
|
||||||
static std::vector<float> frequencies;
|
static std::vector<float> frequencies;
|
||||||
if (frequencies.empty()) {
|
if (frequencies.empty()) {
|
||||||
spdlog::warn("cpu/bsd: parseCpuFrequencies is not implemented, expect garbage in {*_frequency}");
|
spdlog::warn(
|
||||||
|
"cpu/bsd: parseCpuFrequencies is not implemented, expect garbage in {*_frequency}");
|
||||||
frequencies.push_back(NAN);
|
frequencies.push_back(NAN);
|
||||||
}
|
}
|
||||||
return frequencies;
|
return frequencies;
|
||||||
|
@ -46,11 +46,11 @@ auto waybar::modules::Cpu::update() -> void {
|
|||||||
store.push_back(fmt::arg("min_frequency", min_frequency));
|
store.push_back(fmt::arg("min_frequency", min_frequency));
|
||||||
store.push_back(fmt::arg("avg_frequency", avg_frequency));
|
store.push_back(fmt::arg("avg_frequency", avg_frequency));
|
||||||
for (size_t i = 1; i < cpu_usage.size(); ++i) {
|
for (size_t i = 1; i < cpu_usage.size(); ++i) {
|
||||||
auto core_i = i - 1;
|
auto core_i = i - 1;
|
||||||
auto core_format = fmt::format("usage{}", core_i);
|
auto core_format = fmt::format("usage{}", core_i);
|
||||||
store.push_back(fmt::arg(core_format.c_str(), cpu_usage[i]));
|
store.push_back(fmt::arg(core_format.c_str(), cpu_usage[i]));
|
||||||
auto icon_format = fmt::format("icon{}", core_i);
|
auto icon_format = fmt::format("icon{}", core_i);
|
||||||
store.push_back(fmt::arg(icon_format.c_str(), getIcon(cpu_usage[i], icons)));
|
store.push_back(fmt::arg(icon_format.c_str(), getIcon(cpu_usage[i], icons)));
|
||||||
}
|
}
|
||||||
label_.set_markup(fmt::vformat(format, store));
|
label_.set_markup(fmt::vformat(format, store));
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ auto waybar::modules::Cpu::update() -> void {
|
|||||||
double waybar::modules::Cpu::getCpuLoad() {
|
double waybar::modules::Cpu::getCpuLoad() {
|
||||||
double load[1];
|
double load[1];
|
||||||
if (getloadavg(load, 1) != -1) {
|
if (getloadavg(load, 1) != -1) {
|
||||||
return load[0];
|
return std::ceil(load[0] * 100.0) / 100.0;
|
||||||
}
|
}
|
||||||
throw std::runtime_error("Can't get Cpu load");
|
throw std::runtime_error("Can't get Cpu load");
|
||||||
}
|
}
|
||||||
@ -73,14 +73,14 @@ std::tuple<std::vector<uint16_t>, std::string> waybar::modules::Cpu::getCpuUsage
|
|||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
}
|
}
|
||||||
std::vector<std::tuple<size_t, size_t>> curr_times = parseCpuinfo();
|
std::vector<std::tuple<size_t, size_t>> curr_times = parseCpuinfo();
|
||||||
std::string tooltip;
|
std::string tooltip;
|
||||||
std::vector<uint16_t> usage;
|
std::vector<uint16_t> usage;
|
||||||
for (size_t i = 0; i < curr_times.size(); ++i) {
|
for (size_t i = 0; i < curr_times.size(); ++i) {
|
||||||
auto [curr_idle, curr_total] = curr_times[i];
|
auto [curr_idle, curr_total] = curr_times[i];
|
||||||
auto [prev_idle, prev_total] = prev_times_[i];
|
auto [prev_idle, prev_total] = prev_times_[i];
|
||||||
const float delta_idle = curr_idle - prev_idle;
|
const float delta_idle = curr_idle - prev_idle;
|
||||||
const float delta_total = curr_total - prev_total;
|
const float delta_total = curr_total - prev_total;
|
||||||
uint16_t tmp = 100 * (1 - delta_idle / delta_total);
|
uint16_t tmp = 100 * (1 - delta_idle / delta_total);
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
tooltip = fmt::format("Total: {}%", tmp);
|
tooltip = fmt::format("Total: {}%", tmp);
|
||||||
} else {
|
} else {
|
||||||
@ -94,13 +94,17 @@ std::tuple<std::vector<uint16_t>, std::string> waybar::modules::Cpu::getCpuUsage
|
|||||||
|
|
||||||
std::tuple<float, float, float> waybar::modules::Cpu::getCpuFrequency() {
|
std::tuple<float, float, float> waybar::modules::Cpu::getCpuFrequency() {
|
||||||
std::vector<float> frequencies = parseCpuFrequencies();
|
std::vector<float> frequencies = parseCpuFrequencies();
|
||||||
|
if (frequencies.empty()) {
|
||||||
|
return {0.f, 0.f, 0.f};
|
||||||
|
}
|
||||||
auto [min, max] = std::minmax_element(std::begin(frequencies), std::end(frequencies));
|
auto [min, max] = std::minmax_element(std::begin(frequencies), std::end(frequencies));
|
||||||
float avg_frequency = std::accumulate(std::begin(frequencies), std::end(frequencies), 0.0) / frequencies.size();
|
float avg_frequency =
|
||||||
|
std::accumulate(std::begin(frequencies), std::end(frequencies), 0.0) / frequencies.size();
|
||||||
|
|
||||||
// Round frequencies with double decimal precision to get GHz
|
// Round frequencies with double decimal precision to get GHz
|
||||||
float max_frequency = std::ceil(*max / 10.0) / 100.0;
|
float max_frequency = std::ceil(*max / 10.0) / 100.0;
|
||||||
float min_frequency = std::ceil(*min / 10.0) / 100.0;
|
float min_frequency = std::ceil(*min / 10.0) / 100.0;
|
||||||
avg_frequency = std::ceil(avg_frequency / 10.0) / 100.0;
|
avg_frequency = std::ceil(avg_frequency / 10.0) / 100.0;
|
||||||
|
|
||||||
return { max_frequency, min_frequency, avg_frequency };
|
return {max_frequency, min_frequency, avg_frequency};
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
#include "modules/cpu.hpp"
|
#include "modules/cpu.hpp"
|
||||||
|
|
||||||
std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
|
std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
|
||||||
@ -8,12 +9,12 @@ std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
|
|||||||
throw std::runtime_error("Can't open " + data_dir_);
|
throw std::runtime_error("Can't open " + data_dir_);
|
||||||
}
|
}
|
||||||
std::vector<std::tuple<size_t, size_t>> cpuinfo;
|
std::vector<std::tuple<size_t, size_t>> cpuinfo;
|
||||||
std::string line;
|
std::string line;
|
||||||
while (getline(info, line)) {
|
while (getline(info, line)) {
|
||||||
if (line.substr(0, 3).compare("cpu") != 0) {
|
if (line.substr(0, 3).compare("cpu") != 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::stringstream sline(line.substr(5));
|
std::stringstream sline(line.substr(5));
|
||||||
std::vector<size_t> times;
|
std::vector<size_t> times;
|
||||||
for (size_t time = 0; sline >> time; times.push_back(time))
|
for (size_t time = 0; sline >> time; times.push_back(time))
|
||||||
;
|
;
|
||||||
@ -51,12 +52,9 @@ std::vector<float> waybar::modules::Cpu::parseCpuFrequencies() {
|
|||||||
if (frequencies.size() <= 0) {
|
if (frequencies.size() <= 0) {
|
||||||
std::string cpufreq_dir = "/sys/devices/system/cpu/cpufreq";
|
std::string cpufreq_dir = "/sys/devices/system/cpu/cpufreq";
|
||||||
if (std::filesystem::exists(cpufreq_dir)) {
|
if (std::filesystem::exists(cpufreq_dir)) {
|
||||||
std::vector<std::string> frequency_files = {
|
std::vector<std::string> frequency_files = {"/cpuinfo_min_freq", "/cpuinfo_max_freq"};
|
||||||
"/cpuinfo_min_freq",
|
for (auto& p : std::filesystem::directory_iterator(cpufreq_dir)) {
|
||||||
"/cpuinfo_max_freq"
|
for (auto freq_file : frequency_files) {
|
||||||
};
|
|
||||||
for (auto& p: std::filesystem::directory_iterator(cpufreq_dir)) {
|
|
||||||
for (auto freq_file: frequency_files) {
|
|
||||||
std::string freq_file_path = p.path().string() + freq_file;
|
std::string freq_file_path = p.path().string() + freq_file;
|
||||||
if (std::filesystem::exists(freq_file_path)) {
|
if (std::filesystem::exists(freq_file_path)) {
|
||||||
std::string freq_value;
|
std::string freq_value;
|
||||||
|
@ -48,7 +48,7 @@ void waybar::modules::Custom::continuousWorker() {
|
|||||||
throw std::runtime_error("Unable to open " + cmd);
|
throw std::runtime_error("Unable to open " + cmd);
|
||||||
}
|
}
|
||||||
thread_ = [this, cmd] {
|
thread_ = [this, cmd] {
|
||||||
char* buff = nullptr;
|
char* buff = nullptr;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
if (getline(&buff, &len, fp_) == -1) {
|
if (getline(&buff, &len, fp_) == -1) {
|
||||||
int exit_code = 1;
|
int exit_code = 1;
|
||||||
@ -120,9 +120,7 @@ auto waybar::modules::Custom::update() -> void {
|
|||||||
} else {
|
} else {
|
||||||
parseOutputRaw();
|
parseOutputRaw();
|
||||||
}
|
}
|
||||||
auto str = fmt::format(format_,
|
auto str = fmt::format(format_, text_, fmt::arg("alt", alt_),
|
||||||
text_,
|
|
||||||
fmt::arg("alt", alt_),
|
|
||||||
fmt::arg("icon", getIcon(percentage_, alt_)),
|
fmt::arg("icon", getIcon(percentage_, alt_)),
|
||||||
fmt::arg("percentage", percentage_));
|
fmt::arg("percentage", percentage_));
|
||||||
if (str.empty()) {
|
if (str.empty()) {
|
||||||
@ -156,8 +154,8 @@ auto waybar::modules::Custom::update() -> void {
|
|||||||
|
|
||||||
void waybar::modules::Custom::parseOutputRaw() {
|
void waybar::modules::Custom::parseOutputRaw() {
|
||||||
std::istringstream output(output_.out);
|
std::istringstream output(output_.out);
|
||||||
std::string line;
|
std::string line;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (getline(output, line)) {
|
while (getline(output, line)) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
if (config_["escape"].isBool() && config_["escape"].asBool()) {
|
if (config_["escape"].isBool() && config_["escape"].asBool()) {
|
||||||
@ -180,7 +178,7 @@ void waybar::modules::Custom::parseOutputRaw() {
|
|||||||
|
|
||||||
void waybar::modules::Custom::parseOutputJson() {
|
void waybar::modules::Custom::parseOutputJson() {
|
||||||
std::istringstream output(output_.out);
|
std::istringstream output(output_.out);
|
||||||
std::string line;
|
std::string line;
|
||||||
class_.clear();
|
class_.clear();
|
||||||
while (getline(output, line)) {
|
while (getline(output, line)) {
|
||||||
auto parsed = parser_.parse(line);
|
auto parsed = parser_.parse(line);
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
using namespace waybar::util;
|
using namespace waybar::util;
|
||||||
|
|
||||||
waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config)
|
waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config)
|
||||||
: ALabel(config, "disk", id, "{}%", 30)
|
: ALabel(config, "disk", id, "{}%", 30), path_("/") {
|
||||||
, path_("/")
|
|
||||||
{
|
|
||||||
thread_ = [this] {
|
thread_ = [this] {
|
||||||
dp.emit();
|
dp.emit();
|
||||||
thread_.sleep_for(interval_);
|
thread_.sleep_for(interval_);
|
||||||
@ -28,7 +26,8 @@ auto waybar::modules::Disk::update() -> void {
|
|||||||
unsigned long f_fsid; // filesystem ID
|
unsigned long f_fsid; // filesystem ID
|
||||||
unsigned long f_flag; // mount flags
|
unsigned long f_flag; // mount flags
|
||||||
unsigned long f_namemax; // maximum filename length
|
unsigned long f_namemax; // maximum filename length
|
||||||
}; */ stats;
|
}; */
|
||||||
|
stats;
|
||||||
int err = statvfs(path_.c_str(), &stats);
|
int err = statvfs(path_.c_str(), &stats);
|
||||||
|
|
||||||
/* Conky options
|
/* Conky options
|
||||||
@ -59,15 +58,11 @@ auto waybar::modules::Disk::update() -> void {
|
|||||||
event_box_.hide();
|
event_box_.hide();
|
||||||
} else {
|
} else {
|
||||||
event_box_.show();
|
event_box_.show();
|
||||||
label_.set_markup(fmt::format(format
|
label_.set_markup(
|
||||||
, stats.f_bavail * 100 / stats.f_blocks
|
fmt::format(format, stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free),
|
||||||
, fmt::arg("free", free)
|
fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks),
|
||||||
, fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks)
|
fmt::arg("used", used), fmt::arg("percentage_used", percentage_used),
|
||||||
, fmt::arg("used", used)
|
fmt::arg("total", total), fmt::arg("path", path_)));
|
||||||
, fmt::arg("percentage_used", percentage_used)
|
|
||||||
, fmt::arg("total", total)
|
|
||||||
, fmt::arg("path", path_)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
@ -75,15 +70,11 @@ auto waybar::modules::Disk::update() -> void {
|
|||||||
if (config_["tooltip-format"].isString()) {
|
if (config_["tooltip-format"].isString()) {
|
||||||
tooltip_format = config_["tooltip-format"].asString();
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
}
|
}
|
||||||
label_.set_tooltip_text(fmt::format(tooltip_format
|
label_.set_tooltip_text(
|
||||||
, stats.f_bavail * 100 / stats.f_blocks
|
fmt::format(tooltip_format, stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free),
|
||||||
, fmt::arg("free", free)
|
fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks),
|
||||||
, fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks)
|
fmt::arg("used", used), fmt::arg("percentage_used", percentage_used),
|
||||||
, fmt::arg("used", used)
|
fmt::arg("total", total), fmt::arg("path", path_)));
|
||||||
, fmt::arg("percentage_used", percentage_used)
|
|
||||||
, fmt::arg("total", total)
|
|
||||||
, fmt::arg("path", path_)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
// Call parent update
|
// Call parent update
|
||||||
ALabel::update();
|
ALabel::update();
|
||||||
|
237
src/modules/gamemode.cpp
Normal file
237
src/modules/gamemode.cpp
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
#include "modules/gamemode.hpp"
|
||||||
|
|
||||||
|
#include <fmt/core.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "AModule.hpp"
|
||||||
|
#include "giomm/dbusconnection.h"
|
||||||
|
#include "giomm/dbusinterface.h"
|
||||||
|
#include "giomm/dbusproxy.h"
|
||||||
|
#include "giomm/dbuswatchname.h"
|
||||||
|
#include "glibmm/error.h"
|
||||||
|
#include "glibmm/ustring.h"
|
||||||
|
#include "glibmm/variant.h"
|
||||||
|
#include "glibmm/varianttype.h"
|
||||||
|
#include "gtkmm/icontheme.h"
|
||||||
|
#include "gtkmm/label.h"
|
||||||
|
#include "gtkmm/tooltip.h"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
Gamemode::Gamemode(const std::string& id, const Json::Value& config)
|
||||||
|
: AModule(config, "gamemode", id), box_(Gtk::ORIENTATION_HORIZONTAL, 0), icon_(), label_() {
|
||||||
|
box_.pack_start(icon_);
|
||||||
|
box_.pack_start(label_);
|
||||||
|
box_.set_name(name_);
|
||||||
|
event_box_.add(box_);
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
if (config_["tooltip"].isBool()) {
|
||||||
|
tooltip = config_["tooltip"].asBool();
|
||||||
|
}
|
||||||
|
box_.set_has_tooltip(tooltip);
|
||||||
|
|
||||||
|
// Tooltip Format
|
||||||
|
if (config_["tooltip-format"].isString()) {
|
||||||
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide when game count is 0
|
||||||
|
if (config_["hide-not-running"].isBool()) {
|
||||||
|
hideNotRunning = config_["hide-not-running"].asBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icon Name
|
||||||
|
if (config_["icon-name"].isString()) {
|
||||||
|
iconName = config_["icon-name"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icon Spacing
|
||||||
|
if (config_["icon-spacing"].isUInt()) {
|
||||||
|
iconSpacing = config_["icon-spacing"].asUInt();
|
||||||
|
}
|
||||||
|
box_.set_spacing(iconSpacing);
|
||||||
|
|
||||||
|
// Wether to use icon or not
|
||||||
|
if (config_["use-icon"].isBool()) {
|
||||||
|
useIcon = config_["use-icon"].asBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icon Size
|
||||||
|
if (config_["icon-size"].isUInt()) {
|
||||||
|
iconSize = config_["icon-size"].asUInt();
|
||||||
|
}
|
||||||
|
icon_.set_pixel_size(iconSize);
|
||||||
|
|
||||||
|
// Format
|
||||||
|
if (config_["format"].isString()) {
|
||||||
|
format = config_["format"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format Alt
|
||||||
|
if (config_["format-alt"].isString()) {
|
||||||
|
format_alt = config_["format-alt"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Glyph
|
||||||
|
if (config_["glyph"].isString()) {
|
||||||
|
glyph = config_["glyph"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
gamemodeWatcher_id = Gio::DBus::watch_name(
|
||||||
|
Gio::DBus::BUS_TYPE_SESSION, dbus_name, sigc::mem_fun(*this, &Gamemode::appear),
|
||||||
|
sigc::mem_fun(*this, &Gamemode::disappear),
|
||||||
|
Gio::DBus::BusNameWatcherFlags::BUS_NAME_WATCHER_FLAGS_AUTO_START);
|
||||||
|
|
||||||
|
// Connect to gamemode
|
||||||
|
gamemode_proxy = Gio::DBus::Proxy::create_for_bus_sync(Gio::DBus::BusType::BUS_TYPE_SESSION,
|
||||||
|
dbus_name, dbus_obj_path, dbus_interface);
|
||||||
|
if (!gamemode_proxy) {
|
||||||
|
throw std::runtime_error("Unable to connect to gamemode DBus!...");
|
||||||
|
} else {
|
||||||
|
gamemode_proxy->signal_signal().connect(sigc::mem_fun(*this, &Gamemode::notify_cb));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to Login1 PrepareForSleep signal
|
||||||
|
system_connection = Gio::DBus::Connection::get_sync(Gio::DBus::BusType::BUS_TYPE_SYSTEM);
|
||||||
|
if (!system_connection) {
|
||||||
|
throw std::runtime_error("Unable to connect to the SYSTEM Bus!...");
|
||||||
|
} else {
|
||||||
|
login1_id = system_connection->signal_subscribe(
|
||||||
|
sigc::mem_fun(*this, &Gamemode::prepareForSleep_cb), "org.freedesktop.login1",
|
||||||
|
"org.freedesktop.login1.Manager", "PrepareForSleep", "/org/freedesktop/login1");
|
||||||
|
}
|
||||||
|
|
||||||
|
event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &Gamemode::handleToggle));
|
||||||
|
}
|
||||||
|
|
||||||
|
Gamemode::~Gamemode() {
|
||||||
|
if (gamemode_proxy) gamemode_proxy->unreference();
|
||||||
|
if (gamemodeWatcher_id > 0) {
|
||||||
|
Gio::DBus::unwatch_name(gamemodeWatcher_id);
|
||||||
|
gamemodeWatcher_id = 0;
|
||||||
|
}
|
||||||
|
if (login1_id > 0) {
|
||||||
|
system_connection->signal_unsubscribe(login1_id);
|
||||||
|
login1_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the DBus ClientCount
|
||||||
|
void Gamemode::getData() {
|
||||||
|
if (gamemodeRunning && gamemode_proxy) {
|
||||||
|
try {
|
||||||
|
// Get game count
|
||||||
|
auto parameters = Glib::VariantContainerBase(
|
||||||
|
g_variant_new("(ss)", dbus_get_interface.c_str(), "ClientCount"));
|
||||||
|
Glib::VariantContainerBase data = gamemode_proxy->call_sync("Get", parameters);
|
||||||
|
if (data && data.is_of_type(Glib::VariantType("(v)"))) {
|
||||||
|
Glib::VariantBase variant;
|
||||||
|
g_variant_get(data.gobj_copy(), "(v)", &variant);
|
||||||
|
if (variant && variant.is_of_type(Glib::VARIANT_TYPE_INT32)) {
|
||||||
|
g_variant_get(variant.gobj_copy(), "i", &gameCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Glib::Error& e) {
|
||||||
|
spdlog::error("Gamemode Error {}", e.what().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gameCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whenever the DBus ClientCount changes
|
||||||
|
void Gamemode::notify_cb(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
|
||||||
|
const Glib::VariantContainerBase& arguments) {
|
||||||
|
if (signal_name == "PropertiesChanged") {
|
||||||
|
getData();
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gamemode::prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection>& connection,
|
||||||
|
const Glib::ustring& sender_name,
|
||||||
|
const Glib::ustring& object_path,
|
||||||
|
const Glib::ustring& interface_name,
|
||||||
|
const Glib::ustring& signal_name,
|
||||||
|
const Glib::VariantContainerBase& parameters) {
|
||||||
|
if (parameters.is_of_type(Glib::VariantType("(b)"))) {
|
||||||
|
gboolean sleeping;
|
||||||
|
g_variant_get(parameters.gobj_copy(), "(b)", &sleeping);
|
||||||
|
if (!sleeping) {
|
||||||
|
getData();
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the gamemode name appears
|
||||||
|
void Gamemode::appear(const Glib::RefPtr<Gio::DBus::Connection>& connection,
|
||||||
|
const Glib::ustring& name, const Glib::ustring& name_owner) {
|
||||||
|
gamemodeRunning = true;
|
||||||
|
event_box_.set_visible(true);
|
||||||
|
getData();
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
// When the gamemode name disappears
|
||||||
|
void Gamemode::disappear(const Glib::RefPtr<Gio::DBus::Connection>& connection,
|
||||||
|
const Glib::ustring& name) {
|
||||||
|
gamemodeRunning = false;
|
||||||
|
event_box_.set_visible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Gamemode::handleToggle(GdkEventButton* const& event) {
|
||||||
|
showAltText = !showAltText;
|
||||||
|
dp.emit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Gamemode::update() -> void {
|
||||||
|
// Don't update widget if the Gamemode service isn't running
|
||||||
|
if (!gamemodeRunning || (gameCount <= 0 && hideNotRunning)) {
|
||||||
|
event_box_.set_visible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the module
|
||||||
|
if (!event_box_.get_visible()) event_box_.set_visible(true);
|
||||||
|
|
||||||
|
// CSS status class
|
||||||
|
const std::string status = gamemodeRunning && gameCount > 0 ? "running" : "";
|
||||||
|
// Remove last status if it exists
|
||||||
|
if (!lastStatus.empty() && box_.get_style_context()->has_class(lastStatus)) {
|
||||||
|
box_.get_style_context()->remove_class(lastStatus);
|
||||||
|
}
|
||||||
|
// Add the new status class to the Box
|
||||||
|
if (!status.empty() && !box_.get_style_context()->has_class(status)) {
|
||||||
|
box_.get_style_context()->add_class(status);
|
||||||
|
}
|
||||||
|
lastStatus = status;
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
if (tooltip) {
|
||||||
|
std::string text = fmt::format(tooltip_format, fmt::arg("count", gameCount));
|
||||||
|
box_.set_tooltip_text(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label format
|
||||||
|
std::string str =
|
||||||
|
fmt::format(showAltText ? format_alt : format, fmt::arg("glyph", useIcon ? "" : glyph),
|
||||||
|
fmt::arg("count", gameCount > 0 ? std::to_string(gameCount) : ""));
|
||||||
|
label_.set_markup(str);
|
||||||
|
|
||||||
|
if (useIcon) {
|
||||||
|
if (!Gtk::IconTheme::get_default()->has_icon(iconName)) {
|
||||||
|
iconName = DEFAULT_ICON_NAME;
|
||||||
|
}
|
||||||
|
icon_.set_from_icon_name(iconName, Gtk::ICON_SIZE_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call parent update
|
||||||
|
AModule::update();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
@ -4,7 +4,7 @@
|
|||||||
#include "util/command.hpp"
|
#include "util/command.hpp"
|
||||||
|
|
||||||
std::list<waybar::AModule*> waybar::modules::IdleInhibitor::modules;
|
std::list<waybar::AModule*> waybar::modules::IdleInhibitor::modules;
|
||||||
bool waybar::modules::IdleInhibitor::status = false;
|
bool waybar::modules::IdleInhibitor::status = false;
|
||||||
|
|
||||||
waybar::modules::IdleInhibitor::IdleInhibitor(const std::string& id, const Bar& bar,
|
waybar::modules::IdleInhibitor::IdleInhibitor(const std::string& id, const Bar& bar,
|
||||||
const Json::Value& config)
|
const Json::Value& config)
|
||||||
@ -47,7 +47,7 @@ auto waybar::modules::IdleInhibitor::update() -> void {
|
|||||||
label_.get_style_context()->remove_class("deactivated");
|
label_.get_style_context()->remove_class("deactivated");
|
||||||
if (idle_inhibitor_ == nullptr) {
|
if (idle_inhibitor_ == nullptr) {
|
||||||
idle_inhibitor_ = zwp_idle_inhibit_manager_v1_create_inhibitor(
|
idle_inhibitor_ = zwp_idle_inhibit_manager_v1_create_inhibitor(
|
||||||
waybar::Client::inst()->idle_inhibit_manager, bar_.surface);
|
waybar::Client::inst()->idle_inhibit_manager, bar_.surface);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
label_.get_style_context()->remove_class("activated");
|
label_.get_style_context()->remove_class("activated");
|
||||||
@ -58,8 +58,8 @@ auto waybar::modules::IdleInhibitor::update() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string status_text = status ? "activated" : "deactivated";
|
std::string status_text = status ? "activated" : "deactivated";
|
||||||
label_.set_markup(
|
label_.set_markup(fmt::format(format_, fmt::arg("status", status_text),
|
||||||
fmt::format(format_, fmt::arg("status", status_text), fmt::arg("icon", getIcon(0, status_text))));
|
fmt::arg("icon", getIcon(0, status_text))));
|
||||||
label_.get_style_context()->add_class(status_text);
|
label_.get_style_context()->add_class(status_text);
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
label_.set_tooltip_text(status_text);
|
label_.set_tooltip_text(status_text);
|
||||||
@ -72,6 +72,31 @@ bool waybar::modules::IdleInhibitor::handleToggle(GdkEventButton* const& e) {
|
|||||||
if (e->button == 1) {
|
if (e->button == 1) {
|
||||||
status = !status;
|
status = !status;
|
||||||
|
|
||||||
|
if (timeout_.connected()) {
|
||||||
|
/* cancel any already active timeout handler */
|
||||||
|
timeout_.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status && config_["timeout"].isNumeric()) {
|
||||||
|
auto timeoutMins = config_["timeout"].asDouble();
|
||||||
|
int timeoutSecs = timeoutMins * 60;
|
||||||
|
|
||||||
|
timeout_ = Glib::signal_timeout().connect_seconds(
|
||||||
|
[]() {
|
||||||
|
/* intentionally not tied to a module instance lifetime
|
||||||
|
* as the output with `this` can be disconnected
|
||||||
|
*/
|
||||||
|
spdlog::info("deactivating idle_inhibitor by timeout");
|
||||||
|
status = false;
|
||||||
|
for (auto const& module : waybar::modules::IdleInhibitor::modules) {
|
||||||
|
module->update();
|
||||||
|
}
|
||||||
|
/* disconnect */
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
timeoutSecs);
|
||||||
|
}
|
||||||
|
|
||||||
// Make all other idle inhibitor modules update
|
// Make all other idle inhibitor modules update
|
||||||
for (auto const& module : waybar::modules::IdleInhibitor::modules) {
|
for (auto const& module : waybar::modules::IdleInhibitor::modules) {
|
||||||
if (module != this) {
|
if (module != this) {
|
||||||
|
@ -6,12 +6,11 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using DBus = std::unique_ptr<GDBusConnection, void(*)(GDBusConnection*)>;
|
using DBus = std::unique_ptr<GDBusConnection, void (*)(GDBusConnection*)>;
|
||||||
|
|
||||||
auto dbus() -> DBus {
|
auto dbus() -> DBus {
|
||||||
GError *error = nullptr;
|
GError* error = nullptr;
|
||||||
GDBusConnection* connection =
|
GDBusConnection* connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||||
g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
spdlog::error("g_bus_get_sync() failed: {}", error->message);
|
spdlog::error("g_bus_get_sync() failed: {}", error->message);
|
||||||
@ -20,46 +19,29 @@ auto dbus() -> DBus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto destructor = [](GDBusConnection* connection) {
|
auto destructor = [](GDBusConnection* connection) {
|
||||||
GError *error = nullptr;
|
GError* error = nullptr;
|
||||||
g_dbus_connection_close_sync(connection, nullptr, &error);
|
g_dbus_connection_close_sync(connection, nullptr, &error);
|
||||||
if (error) {
|
if (error) {
|
||||||
spdlog::error(
|
spdlog::error("g_bus_connection_close_sync failed(): {}", error->message);
|
||||||
"g_bus_connection_close_sync failed(): {}",
|
g_error_free(error);
|
||||||
error->message);
|
}
|
||||||
g_error_free(error);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return DBus{connection, destructor};
|
return DBus{connection, destructor};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto getLocks(const DBus& bus, const std::string& inhibitors) -> int {
|
auto getLocks(const DBus& bus, const std::string& inhibitors) -> int {
|
||||||
GError *error = nullptr;
|
GError* error = nullptr;
|
||||||
GUnixFDList* fd_list;
|
GUnixFDList* fd_list;
|
||||||
int handle;
|
int handle;
|
||||||
|
|
||||||
auto reply = g_dbus_connection_call_with_unix_fd_list_sync(bus.get(),
|
auto reply = g_dbus_connection_call_with_unix_fd_list_sync(
|
||||||
"org.freedesktop.login1",
|
bus.get(), "org.freedesktop.login1", "/org/freedesktop/login1",
|
||||||
"/org/freedesktop/login1",
|
"org.freedesktop.login1.Manager", "Inhibit",
|
||||||
"org.freedesktop.login1.Manager",
|
g_variant_new("(ssss)", inhibitors.c_str(), "waybar", "Asked by user", "block"),
|
||||||
"Inhibit",
|
G_VARIANT_TYPE("(h)"), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &fd_list, nullptr, &error);
|
||||||
g_variant_new(
|
|
||||||
"(ssss)",
|
|
||||||
inhibitors.c_str(),
|
|
||||||
"waybar",
|
|
||||||
"Asked by user",
|
|
||||||
"block"),
|
|
||||||
G_VARIANT_TYPE("(h)"),
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1,
|
|
||||||
nullptr,
|
|
||||||
&fd_list,
|
|
||||||
nullptr,
|
|
||||||
&error);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
spdlog::error(
|
spdlog::error("g_dbus_connection_call_with_unix_fd_list_sync() failed: {}", error->message);
|
||||||
"g_dbus_connection_call_with_unix_fd_list_sync() failed: {}",
|
|
||||||
error->message);
|
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
handle = -1;
|
handle = -1;
|
||||||
} else {
|
} else {
|
||||||
@ -74,18 +56,15 @@ auto getLocks(const DBus& bus, const std::string& inhibitors) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto checkInhibitor(const std::string& inhibitor) -> const std::string& {
|
auto checkInhibitor(const std::string& inhibitor) -> const std::string& {
|
||||||
static const auto inhibitors = std::array{
|
static const auto inhibitors = std::array{"idle",
|
||||||
"idle",
|
"shutdown",
|
||||||
"shutdown",
|
"sleep",
|
||||||
"sleep",
|
"handle-power-key",
|
||||||
"handle-power-key",
|
"handle-suspend-key",
|
||||||
"handle-suspend-key",
|
"handle-hibernate-key",
|
||||||
"handle-hibernate-key",
|
"handle-lid-switch"};
|
||||||
"handle-lid-switch"
|
|
||||||
};
|
|
||||||
|
|
||||||
if (std::find(inhibitors.begin(), inhibitors.end(), inhibitor)
|
if (std::find(inhibitors.begin(), inhibitors.end(), inhibitor) == inhibitors.end()) {
|
||||||
== inhibitors.end()) {
|
|
||||||
throw std::runtime_error("invalid logind inhibitor " + inhibitor);
|
throw std::runtime_error("invalid logind inhibitor " + inhibitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,18 +93,16 @@ auto getInhibitors(const Json::Value& config) -> std::string {
|
|||||||
return inhibitors;
|
return inhibitors;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
namespace waybar::modules {
|
namespace waybar::modules {
|
||||||
|
|
||||||
Inhibitor::Inhibitor(const std::string& id, const Bar& bar,
|
Inhibitor::Inhibitor(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||||
const Json::Value& config)
|
|
||||||
: ALabel(config, "inhibitor", id, "{status}", true),
|
: ALabel(config, "inhibitor", id, "{status}", true),
|
||||||
dbus_(::dbus()),
|
dbus_(::dbus()),
|
||||||
inhibitors_(::getInhibitors(config)) {
|
inhibitors_(::getInhibitors(config)) {
|
||||||
event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
|
event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
|
||||||
event_box_.signal_button_press_event().connect(
|
event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &Inhibitor::handleToggle));
|
||||||
sigc::mem_fun(*this, &Inhibitor::handleToggle));
|
|
||||||
dp.emit();
|
dp.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,18 +112,14 @@ Inhibitor::~Inhibitor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Inhibitor::activated() -> bool {
|
auto Inhibitor::activated() -> bool { return handle_ != -1; }
|
||||||
return handle_ != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Inhibitor::update() -> void {
|
auto Inhibitor::update() -> void {
|
||||||
std::string status_text = activated() ? "activated" : "deactivated";
|
std::string status_text = activated() ? "activated" : "deactivated";
|
||||||
|
|
||||||
label_.get_style_context()->remove_class(
|
label_.get_style_context()->remove_class(activated() ? "deactivated" : "activated");
|
||||||
activated() ? "deactivated" : "activated");
|
label_.set_markup(fmt::format(format_, fmt::arg("status", status_text),
|
||||||
label_.set_markup(
|
fmt::arg("icon", getIcon(0, status_text))));
|
||||||
fmt::format(format_, fmt::arg("status", status_text),
|
|
||||||
fmt::arg("icon", getIcon(0, status_text))));
|
|
||||||
label_.get_style_context()->add_class(status_text);
|
label_.get_style_context()->add_class(status_text);
|
||||||
|
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
@ -172,4 +145,4 @@ auto Inhibitor::handleToggle(GdkEventButton* const& e) -> bool {
|
|||||||
return ALabel::handleToggle(e);
|
return ALabel::handleToggle(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // waybar::modules
|
} // namespace waybar::modules
|
||||||
|
@ -1,44 +1,117 @@
|
|||||||
#include "modules/keyboard_state.hpp"
|
#include "modules/keyboard_state.hpp"
|
||||||
#include <filesystem>
|
|
||||||
|
#include <errno.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& bar, const Json::Value& config)
|
class errno_error : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
int code;
|
||||||
|
errno_error(int code, const std::string& msg)
|
||||||
|
: std::runtime_error(getErrorMsg(code, msg.c_str())), code(code) {}
|
||||||
|
errno_error(int code, const char* msg) : std::runtime_error(getErrorMsg(code, msg)), code(code) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static auto getErrorMsg(int err, const char* msg) -> std::string {
|
||||||
|
std::string error_msg{msg};
|
||||||
|
error_msg += ": ";
|
||||||
|
|
||||||
|
#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 32)
|
||||||
|
// strerrorname_np gets the error code's name; it's nice to have, but it's a recent GNU
|
||||||
|
// extension
|
||||||
|
const auto errno_name = strerrorname_np(err);
|
||||||
|
error_msg += errno_name;
|
||||||
|
error_msg += " ";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const auto errno_str = strerror(err);
|
||||||
|
error_msg += errno_str;
|
||||||
|
|
||||||
|
return error_msg;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto openFile(const std::string& path, int flags) -> int {
|
||||||
|
int fd = open(path.c_str(), flags);
|
||||||
|
if (fd < 0) {
|
||||||
|
if (errno == EACCES) {
|
||||||
|
throw errno_error(errno, "Can't open " + path + " (are you in the input group?)");
|
||||||
|
} else {
|
||||||
|
throw errno_error(errno, "Can't open " + path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto closeFile(int fd) -> void {
|
||||||
|
int res = close(fd);
|
||||||
|
if (res < 0) {
|
||||||
|
throw errno_error(errno, "Can't close file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto openDevice(int fd) -> libevdev* {
|
||||||
|
libevdev* dev;
|
||||||
|
int err = libevdev_new_from_fd(fd, &dev);
|
||||||
|
if (err < 0) {
|
||||||
|
throw errno_error(-err, "Can't create libevdev device");
|
||||||
|
}
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto supportsLockStates(const libevdev* dev) -> bool {
|
||||||
|
return libevdev_has_event_type(dev, EV_LED) && libevdev_has_event_code(dev, EV_LED, LED_NUML) &&
|
||||||
|
libevdev_has_event_code(dev, EV_LED, LED_CAPSL) &&
|
||||||
|
libevdev_has_event_code(dev, EV_LED, LED_SCROLLL);
|
||||||
|
}
|
||||||
|
|
||||||
|
waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& bar,
|
||||||
|
const Json::Value& config)
|
||||||
: AModule(config, "keyboard-state", id, false, !config["disable-scroll"].asBool()),
|
: AModule(config, "keyboard-state", id, false, !config["disable-scroll"].asBool()),
|
||||||
box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0),
|
box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0),
|
||||||
numlock_label_(""),
|
numlock_label_(""),
|
||||||
capslock_label_(""),
|
capslock_label_(""),
|
||||||
numlock_format_(config_["format"].isString() ? config_["format"].asString()
|
numlock_format_(config_["format"].isString() ? config_["format"].asString()
|
||||||
: config_["format"]["numlock"].isString() ? config_["format"]["numlock"].asString()
|
: config_["format"]["numlock"].isString()
|
||||||
: "{name} {icon}"),
|
? config_["format"]["numlock"].asString()
|
||||||
|
: "{name} {icon}"),
|
||||||
capslock_format_(config_["format"].isString() ? config_["format"].asString()
|
capslock_format_(config_["format"].isString() ? config_["format"].asString()
|
||||||
: config_["format"]["capslock"].isString() ? config_["format"]["capslock"].asString()
|
: config_["format"]["capslock"].isString()
|
||||||
: "{name} {icon}"),
|
? config_["format"]["capslock"].asString()
|
||||||
|
: "{name} {icon}"),
|
||||||
scrolllock_format_(config_["format"].isString() ? config_["format"].asString()
|
scrolllock_format_(config_["format"].isString() ? config_["format"].asString()
|
||||||
: config_["format"]["scrolllock"].isString() ? config_["format"]["scrolllock"].asString()
|
: config_["format"]["scrolllock"].isString()
|
||||||
: "{name} {icon}"),
|
? config_["format"]["scrolllock"].asString()
|
||||||
interval_(std::chrono::seconds(config_["interval"].isUInt() ? config_["interval"].asUInt() : 1)),
|
: "{name} {icon}"),
|
||||||
|
interval_(
|
||||||
|
std::chrono::seconds(config_["interval"].isUInt() ? config_["interval"].asUInt() : 1)),
|
||||||
icon_locked_(config_["format-icons"]["locked"].isString()
|
icon_locked_(config_["format-icons"]["locked"].isString()
|
||||||
? config_["format-icons"]["locked"].asString()
|
? config_["format-icons"]["locked"].asString()
|
||||||
: "locked"),
|
: "locked"),
|
||||||
icon_unlocked_(config_["format-icons"]["unlocked"].isString()
|
icon_unlocked_(config_["format-icons"]["unlocked"].isString()
|
||||||
? config_["format-icons"]["unlocked"].asString()
|
? config_["format-icons"]["unlocked"].asString()
|
||||||
: "unlocked"),
|
: "unlocked"),
|
||||||
fd_(0),
|
fd_(0),
|
||||||
dev_(nullptr) {
|
dev_(nullptr) {
|
||||||
box_.set_name("keyboard-state");
|
box_.set_name("keyboard-state");
|
||||||
if (config_["numlock"].asBool()) {
|
if (config_["numlock"].asBool()) {
|
||||||
|
numlock_label_.get_style_context()->add_class("numlock");
|
||||||
box_.pack_end(numlock_label_, false, false, 0);
|
box_.pack_end(numlock_label_, false, false, 0);
|
||||||
}
|
}
|
||||||
if (config_["capslock"].asBool()) {
|
if (config_["capslock"].asBool()) {
|
||||||
|
capslock_label_.get_style_context()->add_class("capslock");
|
||||||
box_.pack_end(capslock_label_, false, false, 0);
|
box_.pack_end(capslock_label_, false, false, 0);
|
||||||
}
|
}
|
||||||
if (config_["scrolllock"].asBool()) {
|
if (config_["scrolllock"].asBool()) {
|
||||||
|
scrolllock_label_.get_style_context()->add_class("scrolllock");
|
||||||
box_.pack_end(scrolllock_label_, false, false, 0);
|
box_.pack_end(scrolllock_label_, false, false, 0);
|
||||||
}
|
}
|
||||||
if (!id.empty()) {
|
if (!id.empty()) {
|
||||||
@ -48,26 +121,36 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
|
|||||||
|
|
||||||
if (config_["device-path"].isString()) {
|
if (config_["device-path"].isString()) {
|
||||||
std::string dev_path = config_["device-path"].asString();
|
std::string dev_path = config_["device-path"].asString();
|
||||||
std::tie(fd_, dev_) = openDevice(dev_path);
|
fd_ = openFile(dev_path, O_NONBLOCK | O_CLOEXEC | O_RDONLY);
|
||||||
|
dev_ = openDevice(fd_);
|
||||||
} else {
|
} else {
|
||||||
DIR* dev_dir = opendir("/dev/input");
|
DIR* dev_dir = opendir("/dev/input");
|
||||||
if (dev_dir == nullptr) {
|
if (dev_dir == nullptr) {
|
||||||
throw std::runtime_error("Failed to open /dev/input");
|
throw errno_error(errno, "Failed to open /dev/input");
|
||||||
}
|
}
|
||||||
dirent *ep;
|
dirent* ep;
|
||||||
while ((ep = readdir(dev_dir))) {
|
while ((ep = readdir(dev_dir))) {
|
||||||
if (ep->d_type != DT_CHR) continue;
|
if (ep->d_type != DT_CHR) continue;
|
||||||
std::string dev_path = std::string("/dev/input/") + ep->d_name;
|
std::string dev_path = std::string("/dev/input/") + ep->d_name;
|
||||||
|
int fd = openFile(dev_path.c_str(), O_NONBLOCK | O_CLOEXEC | O_RDONLY);
|
||||||
try {
|
try {
|
||||||
std::tie(fd_, dev_) = openDevice(dev_path);
|
auto dev = openDevice(fd);
|
||||||
spdlog::info("Found device {} at '{}'", libevdev_get_name(dev_), dev_path);
|
if (supportsLockStates(dev)) {
|
||||||
break;
|
spdlog::info("Found device {} at '{}'", libevdev_get_name(dev), dev_path);
|
||||||
} catch (const std::runtime_error& e) {
|
fd_ = fd;
|
||||||
continue;
|
dev_ = dev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (const errno_error& e) {
|
||||||
|
// ENOTTY just means the device isn't an evdev device, skip it
|
||||||
|
if (e.code != ENOTTY) {
|
||||||
|
spdlog::warn(e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
closeFile(fd);
|
||||||
}
|
}
|
||||||
if (dev_ == nullptr) {
|
if (dev_ == nullptr) {
|
||||||
throw std::runtime_error("Failed to find keyboard device");
|
throw errno_error(errno, "Failed to find keyboard device");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,35 +162,13 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
|
|||||||
|
|
||||||
waybar::modules::KeyboardState::~KeyboardState() {
|
waybar::modules::KeyboardState::~KeyboardState() {
|
||||||
libevdev_free(dev_);
|
libevdev_free(dev_);
|
||||||
int err = close(fd_);
|
try {
|
||||||
if (err < 0) {
|
closeFile(fd_);
|
||||||
// Not much we can do, so ignore it.
|
} catch (const std::runtime_error& e) {
|
||||||
|
spdlog::warn(e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::KeyboardState::openDevice(const std::string& path) -> std::pair<int, libevdev*> {
|
|
||||||
int fd = open(path.c_str(), O_NONBLOCK | O_CLOEXEC | O_RDONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
throw std::runtime_error("Can't open " + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
libevdev* dev;
|
|
||||||
int err = libevdev_new_from_fd(fd, &dev);
|
|
||||||
if (err < 0) {
|
|
||||||
throw std::runtime_error("Can't create libevdev device");
|
|
||||||
}
|
|
||||||
if (!libevdev_has_event_type(dev, EV_LED)) {
|
|
||||||
throw std::runtime_error("Device doesn't support LED events");
|
|
||||||
}
|
|
||||||
if (!libevdev_has_event_code(dev, EV_LED, LED_NUML)
|
|
||||||
|| !libevdev_has_event_code(dev, EV_LED, LED_CAPSL)
|
|
||||||
|| !libevdev_has_event_code(dev, EV_LED, LED_SCROLLL)) {
|
|
||||||
throw std::runtime_error("Device doesn't support num lock, caps lock, or scroll lock events");
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_pair(fd, dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto waybar::modules::KeyboardState::update() -> void {
|
auto waybar::modules::KeyboardState::update() -> void {
|
||||||
int err = LIBEVDEV_READ_STATUS_SUCCESS;
|
int err = LIBEVDEV_READ_STATUS_SUCCESS;
|
||||||
while (err == LIBEVDEV_READ_STATUS_SUCCESS) {
|
while (err == LIBEVDEV_READ_STATUS_SUCCESS) {
|
||||||
@ -117,8 +178,8 @@ auto waybar::modules::KeyboardState::update() -> void {
|
|||||||
err = libevdev_next_event(dev_, LIBEVDEV_READ_FLAG_SYNC, &ev);
|
err = libevdev_next_event(dev_, LIBEVDEV_READ_FLAG_SYNC, &ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (err != -EAGAIN) {
|
if (-err != EAGAIN) {
|
||||||
throw std::runtime_error("Failed to sync evdev device");
|
throw errno_error(-err, "Failed to sync evdev device");
|
||||||
}
|
}
|
||||||
|
|
||||||
int numl = libevdev_get_event_value(dev_, EV_LED, LED_NUML);
|
int numl = libevdev_get_event_value(dev_, EV_LED, LED_NUML);
|
||||||
@ -131,9 +192,9 @@ auto waybar::modules::KeyboardState::update() -> void {
|
|||||||
const std::string& format;
|
const std::string& format;
|
||||||
const char* name;
|
const char* name;
|
||||||
} label_states[] = {
|
} label_states[] = {
|
||||||
{(bool) numl, numlock_label_, numlock_format_, "Num"},
|
{(bool)numl, numlock_label_, numlock_format_, "Num"},
|
||||||
{(bool) capsl, capslock_label_, capslock_format_, "Caps"},
|
{(bool)capsl, capslock_label_, capslock_format_, "Caps"},
|
||||||
{(bool) scrolll, scrolllock_label_, scrolllock_format_, "Scroll"},
|
{(bool)scrolll, scrolllock_label_, scrolllock_format_, "Scroll"},
|
||||||
};
|
};
|
||||||
for (auto& label_state : label_states) {
|
for (auto& label_state : label_states) {
|
||||||
std::string text;
|
std::string text;
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
#include "modules/memory.hpp"
|
// clang-format off
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <unistd.h> // getpagesize
|
// clang-format on
|
||||||
|
#include <unistd.h> // getpagesize
|
||||||
|
|
||||||
|
#include "modules/memory.hpp"
|
||||||
|
|
||||||
#if defined(__DragonFly__)
|
#if defined(__DragonFly__)
|
||||||
# include <sys/vmmeter.h> // struct vmstats
|
#include <sys/vmmeter.h> // struct vmstats
|
||||||
#elif defined(__NetBSD__)
|
#elif defined(__NetBSD__)
|
||||||
# include <uvm/uvm_extern.h> // struct uvmexp_sysctl
|
#include <uvm/uvm_extern.h> // struct uvmexp_sysctl
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__)
|
||||||
# include <uvm/uvmexp.h> // struct uvmexp
|
#include <uvm/uvmexp.h> // struct uvmexp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint64_t get_total_memory() {
|
static uint64_t get_total_memory() {
|
||||||
@ -43,33 +45,27 @@ static uint64_t get_free_memory() {
|
|||||||
if (sysctlbyname("vm.vmstats", &vms, &sz, NULL, 0)) {
|
if (sysctlbyname("vm.vmstats", &vms, &sz, NULL, 0)) {
|
||||||
throw std::runtime_error("sysctl vm.vmstats failed");
|
throw std::runtime_error("sysctl vm.vmstats failed");
|
||||||
}
|
}
|
||||||
return static_cast<uint64_t>
|
return static_cast<uint64_t>(vms.v_free_count + vms.v_inactive_count + vms.v_cache_count) *
|
||||||
(vms.v_free_count + vms.v_inactive_count + vms.v_cache_count)
|
getpagesize();
|
||||||
* getpagesize();
|
|
||||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
u_int v_free_count = 0, v_inactive_count = 0, v_cache_count = 0;
|
u_int v_free_count = 0, v_inactive_count = 0, v_cache_count = 0;
|
||||||
size_t sz = sizeof(u_int);
|
size_t sz = sizeof(u_int);
|
||||||
sysctlbyname("vm.stats.vm.v_free_count",
|
sysctlbyname("vm.stats.vm.v_free_count", &v_free_count, &sz, NULL, 0);
|
||||||
&v_free_count, &sz, NULL, 0);
|
sysctlbyname("vm.stats.vm.v_inactive_count", &v_inactive_count, &sz, NULL, 0);
|
||||||
sysctlbyname("vm.stats.vm.v_inactive_count",
|
sysctlbyname("vm.stats.vm.v_cache_count", &v_cache_count, &sz, NULL, 0);
|
||||||
&v_inactive_count, &sz, NULL, 0);
|
return static_cast<uint64_t>(v_free_count + v_inactive_count + v_cache_count) * getpagesize();
|
||||||
sysctlbyname("vm.stats.vm.v_cache_count",
|
|
||||||
&v_cache_count, &sz, NULL, 0);
|
|
||||||
return static_cast<uint64_t>
|
|
||||||
(v_free_count + v_inactive_count + v_cache_count)
|
|
||||||
* getpagesize();
|
|
||||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
#ifdef VM_UVMEXP2
|
#ifdef VM_UVMEXP2
|
||||||
# undef VM_UVMEXP
|
#undef VM_UVMEXP
|
||||||
# define VM_UVMEXP VM_UVMEXP2
|
#define VM_UVMEXP VM_UVMEXP2
|
||||||
# define uvmexp uvmexp_sysctl
|
#define uvmexp uvmexp_sysctl
|
||||||
#else
|
#else
|
||||||
# define filepages vnodepages
|
#define filepages vnodepages
|
||||||
# define execpages vtextpages
|
#define execpages vtextpages
|
||||||
#endif
|
#endif
|
||||||
int mib[] = {
|
int mib[] = {
|
||||||
CTL_VM,
|
CTL_VM,
|
||||||
VM_UVMEXP,
|
VM_UVMEXP,
|
||||||
};
|
};
|
||||||
u_int miblen = sizeof(mib) / sizeof(mib[0]);
|
u_int miblen = sizeof(mib) / sizeof(mib[0]);
|
||||||
struct uvmexp uvmexp;
|
struct uvmexp uvmexp;
|
||||||
@ -77,9 +73,9 @@ static uint64_t get_free_memory() {
|
|||||||
if (sysctl(mib, miblen, &uvmexp, &sz, NULL, 0)) {
|
if (sysctl(mib, miblen, &uvmexp, &sz, NULL, 0)) {
|
||||||
throw std::runtime_error("sysctl vm.uvmexp failed");
|
throw std::runtime_error("sysctl vm.uvmexp failed");
|
||||||
}
|
}
|
||||||
return static_cast<uint64_t>
|
return static_cast<uint64_t>(uvmexp.free + uvmexp.inactive + uvmexp.filepages +
|
||||||
(uvmexp.free + uvmexp.inactive + uvmexp.filepages + uvmexp.execpages)
|
uvmexp.execpages) *
|
||||||
* uvmexp.pagesize;
|
uvmexp.pagesize;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user