mirror of
https://github.com/rad4day/Waybar.git
synced 2023-12-21 10:22:59 +01:00
Compare commits
131 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 |
@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
BasedOnStyle: Google
|
BasedOnStyle: Google
|
||||||
AlignConsecutiveDeclarations: true
|
AlignConsecutiveDeclarations: false
|
||||||
BinPackArguments: false
|
|
||||||
ColumnLimit: 100
|
ColumnLimit: 100
|
||||||
...
|
...
|
||||||
|
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
|
@ -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,7 +11,8 @@ 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);
|
||||||
|
@ -36,6 +36,22 @@ class AModule : public IModule {
|
|||||||
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,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 {
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
|
||||||
@ -44,6 +46,7 @@ class Battery : public ALabel {
|
|||||||
int global_watch_fd_;
|
int global_watch_fd_;
|
||||||
std::mutex battery_list_mutex_;
|
std::mutex battery_list_mutex_;
|
||||||
std::string old_status_;
|
std::string old_status_;
|
||||||
|
bool warnFirstTime_{true};
|
||||||
|
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
util::SleeperThread thread_battery_update_;
|
util::SleeperThread thread_battery_update_;
|
||||||
|
@ -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"
|
||||||
|
|
||||||
@ -35,8 +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::_V2::system_clock::time_point *now) -> std::string;
|
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"
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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,6 +9,8 @@
|
|||||||
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();
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -12,9 +12,7 @@ inline void Context::tryConnect() const { mpd_module_->tryConne
|
|||||||
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
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
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"
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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_;
|
||||||
|
std::string modifier_reset_;
|
||||||
|
bool visible_by_mode_ = false;
|
||||||
bool visible_by_modifier_ = false;
|
bool visible_by_modifier_ = false;
|
||||||
|
bool visible_by_urgency_ = false;
|
||||||
|
std::atomic<bool> modifier_no_action_ = false;
|
||||||
|
|
||||||
|
SafeSignal<bool> signal_mode_;
|
||||||
SafeSignal<bool> signal_visible_;
|
SafeSignal<bool> signal_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"
|
||||||
|
|
||||||
|
@ -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;
|
||||||
@ -40,6 +36,7 @@ class Language : public ALabel, public sigc::trackable {
|
|||||||
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;
|
||||||
|
@ -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"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include "AIconLabel.hpp"
|
#include "AIconLabel.hpp"
|
||||||
@ -20,18 +21,23 @@ class Window : public AIconLabel, public sigc::trackable {
|
|||||||
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();
|
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 app_class_;
|
||||||
std::string old_app_id_;
|
std::string old_app_id_;
|
||||||
std::size_t app_nb_;
|
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_;
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
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,37 +1,32 @@
|
|||||||
#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 *);
|
||||||
@ -83,7 +78,8 @@ class Task
|
|||||||
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,
|
||||||
|
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
|
||||||
void hide_if_ignored();
|
void hide_if_ignored();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -128,9 +124,7 @@ class Task
|
|||||||
|
|
||||||
using TaskPtr = std::unique_ptr<Task>;
|
using TaskPtr = std::unique_ptr<Task>;
|
||||||
|
|
||||||
|
class Taskbar : public waybar::AModule {
|
||||||
class Taskbar : public waybar::AModule
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Taskbar(const std::string &, const waybar::Bar &, const Json::Value &);
|
Taskbar(const std::string &, const waybar::Bar &, const Json::Value &);
|
||||||
~Taskbar();
|
~Taskbar();
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
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
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// ----------- #included from clara_textflow.hpp -----------
|
// ----------- #included from clara_textflow.hpp -----------
|
||||||
|
|
||||||
// TextFlowCpp
|
// TextFlowCpp
|
||||||
@ -51,8 +50,8 @@
|
|||||||
#define CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
|
#define CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace clara {
|
||||||
namespace clara { namespace TextFlow {
|
namespace TextFlow {
|
||||||
|
|
||||||
inline auto isWhitespace(char c) -> bool {
|
inline auto isWhitespace(char c) -> bool {
|
||||||
static std::string chars = " \t\n\r";
|
static std::string chars = " \t\n\r";
|
||||||
@ -88,9 +87,7 @@ namespace clara { namespace TextFlow {
|
|||||||
bool m_suffix = false;
|
bool m_suffix = false;
|
||||||
|
|
||||||
iterator(Column const &column, size_t stringIndex)
|
iterator(Column const &column, size_t stringIndex)
|
||||||
: m_column( column ),
|
: m_column(column), m_stringIndex(stringIndex) {}
|
||||||
m_stringIndex( stringIndex )
|
|
||||||
{}
|
|
||||||
|
|
||||||
auto line() const -> std::string const & { return m_column.m_strings[m_stringIndex]; }
|
auto line() const -> std::string const & { return m_column.m_strings[m_stringIndex]; }
|
||||||
|
|
||||||
@ -98,10 +95,8 @@ namespace clara { namespace TextFlow {
|
|||||||
assert(at > 0);
|
assert(at > 0);
|
||||||
assert(at <= line().size());
|
assert(at <= line().size());
|
||||||
|
|
||||||
return at == line().size() ||
|
return at == line().size() || (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
|
||||||
( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) ||
|
isBreakableBefore(line()[at]) || isBreakableAfter(line()[at - 1]);
|
||||||
isBreakableBefore( line()[at] ) ||
|
|
||||||
isBreakableAfter( line()[at-1] );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void calcLength() {
|
void calcLength() {
|
||||||
@ -110,18 +105,14 @@ namespace clara { namespace TextFlow {
|
|||||||
m_suffix = false;
|
m_suffix = false;
|
||||||
auto width = m_column.m_width - indent();
|
auto width = m_column.m_width - indent();
|
||||||
m_end = m_pos;
|
m_end = m_pos;
|
||||||
while( m_end < line().size() && line()[m_end] != '\n' )
|
while (m_end < line().size() && line()[m_end] != '\n') ++m_end;
|
||||||
++m_end;
|
|
||||||
|
|
||||||
if (m_end < m_pos + width) {
|
if (m_end < m_pos + width) {
|
||||||
m_len = m_end - m_pos;
|
m_len = m_end - m_pos;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
size_t len = width;
|
size_t len = width;
|
||||||
while (len > 0 && !isBoundary(m_pos + len))
|
while (len > 0 && !isBoundary(m_pos + len)) --len;
|
||||||
--len;
|
while (len > 0 && isWhitespace(line()[m_pos + len - 1])) --len;
|
||||||
while (len > 0 && isWhitespace( line()[m_pos + len - 1] ))
|
|
||||||
--len;
|
|
||||||
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
m_len = len;
|
m_len = len;
|
||||||
@ -133,7 +124,8 @@ namespace clara { namespace TextFlow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto indent() const -> size_t {
|
auto indent() const -> size_t {
|
||||||
auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
|
auto initial =
|
||||||
|
m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
|
||||||
return initial == std::string::npos ? m_column.m_indent : initial;
|
return initial == std::string::npos ? m_column.m_indent : initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,10 +142,10 @@ namespace clara { namespace TextFlow {
|
|||||||
|
|
||||||
explicit iterator(Column const &column) : m_column(column) {
|
explicit iterator(Column const &column) : m_column(column) {
|
||||||
assert(m_column.m_width > m_column.m_indent);
|
assert(m_column.m_width > m_column.m_indent);
|
||||||
assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent );
|
assert(m_column.m_initialIndent == std::string::npos ||
|
||||||
|
m_column.m_width > m_column.m_initialIndent);
|
||||||
calcLength();
|
calcLength();
|
||||||
if( m_len == 0 )
|
if (m_len == 0) m_stringIndex++; // Empty string
|
||||||
m_stringIndex++; // Empty string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator*() const -> std::string {
|
auto operator*() const -> std::string {
|
||||||
@ -167,15 +159,13 @@ namespace clara { namespace TextFlow {
|
|||||||
if (m_pos < line().size() && line()[m_pos] == '\n')
|
if (m_pos < line().size() && line()[m_pos] == '\n')
|
||||||
m_pos += 1;
|
m_pos += 1;
|
||||||
else
|
else
|
||||||
while( m_pos < line().size() && isWhitespace( line()[m_pos] ) )
|
while (m_pos < line().size() && isWhitespace(line()[m_pos])) ++m_pos;
|
||||||
++m_pos;
|
|
||||||
|
|
||||||
if (m_pos == line().size()) {
|
if (m_pos == line().size()) {
|
||||||
m_pos = 0;
|
m_pos = 0;
|
||||||
++m_stringIndex;
|
++m_stringIndex;
|
||||||
}
|
}
|
||||||
if( m_stringIndex < m_column.m_strings.size() )
|
if (m_stringIndex < m_column.m_strings.size()) calcLength();
|
||||||
calcLength();
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
auto operator++(int) -> iterator {
|
auto operator++(int) -> iterator {
|
||||||
@ -185,14 +175,10 @@ namespace clara { namespace TextFlow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto operator==(iterator const &other) const -> bool {
|
auto operator==(iterator const &other) const -> bool {
|
||||||
return
|
return m_pos == other.m_pos && m_stringIndex == other.m_stringIndex &&
|
||||||
m_pos == other.m_pos &&
|
|
||||||
m_stringIndex == other.m_stringIndex &&
|
|
||||||
&m_column == &other.m_column;
|
&m_column == &other.m_column;
|
||||||
}
|
}
|
||||||
auto operator !=( iterator const& other ) const -> bool {
|
auto operator!=(iterator const &other) const -> bool { return !operator==(other); }
|
||||||
return !operator==( other );
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
using const_iterator = iterator;
|
using const_iterator = iterator;
|
||||||
|
|
||||||
@ -238,18 +224,14 @@ namespace clara { namespace TextFlow {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Spacer : public Column {
|
class Spacer : public Column {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Spacer( size_t spaceWidth ) : Column( "" ) {
|
explicit Spacer(size_t spaceWidth) : Column("") { width(spaceWidth); }
|
||||||
width( spaceWidth );
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Columns {
|
class Columns {
|
||||||
std::vector<Column> m_columns;
|
std::vector<Column> m_columns;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class iterator {
|
class iterator {
|
||||||
friend Columns;
|
friend Columns;
|
||||||
struct EndTag {};
|
struct EndTag {};
|
||||||
@ -258,14 +240,10 @@ namespace clara { namespace TextFlow {
|
|||||||
std::vector<Column::iterator> m_iterators;
|
std::vector<Column::iterator> m_iterators;
|
||||||
size_t m_activeIterators;
|
size_t m_activeIterators;
|
||||||
|
|
||||||
iterator( Columns const& columns, EndTag )
|
iterator(Columns const &columns, EndTag) : m_columns(columns.m_columns), m_activeIterators(0) {
|
||||||
: m_columns( columns.m_columns ),
|
|
||||||
m_activeIterators( 0 )
|
|
||||||
{
|
|
||||||
m_iterators.reserve(m_columns.size());
|
m_iterators.reserve(m_columns.size());
|
||||||
|
|
||||||
for( auto const& col : m_columns )
|
for (auto const &col : m_columns) m_iterators.push_back(col.end());
|
||||||
m_iterators.push_back( col.end() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -276,13 +254,10 @@ namespace clara { namespace TextFlow {
|
|||||||
using iterator_category = std::forward_iterator_tag;
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
|
||||||
explicit iterator(Columns const &columns)
|
explicit iterator(Columns const &columns)
|
||||||
: m_columns( columns.m_columns ),
|
: m_columns(columns.m_columns), m_activeIterators(m_columns.size()) {
|
||||||
m_activeIterators( m_columns.size() )
|
|
||||||
{
|
|
||||||
m_iterators.reserve(m_columns.size());
|
m_iterators.reserve(m_columns.size());
|
||||||
|
|
||||||
for( auto const& col : m_columns )
|
for (auto const &col : m_columns) m_iterators.push_back(col.begin());
|
||||||
m_iterators.push_back( col.begin() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator==(iterator const &other) const -> bool {
|
auto operator==(iterator const &other) const -> bool {
|
||||||
@ -303,8 +278,7 @@ namespace clara { namespace TextFlow {
|
|||||||
padding = std::string(width - col.size(), ' ');
|
padding = std::string(width - col.size(), ' ');
|
||||||
else
|
else
|
||||||
padding = "";
|
padding = "";
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
padding += std::string(width, ' ');
|
padding += std::string(width, ' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -312,8 +286,7 @@ namespace clara { namespace TextFlow {
|
|||||||
}
|
}
|
||||||
auto operator++() -> iterator & {
|
auto operator++() -> iterator & {
|
||||||
for (size_t i = 0; i < m_columns.size(); ++i) {
|
for (size_t i = 0; i < m_columns.size(); ++i) {
|
||||||
if (m_iterators[i] != m_columns[i].end())
|
if (m_iterators[i] != m_columns[i].end()) ++m_iterators[i];
|
||||||
++m_iterators[i];
|
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -339,7 +312,6 @@ namespace clara { namespace TextFlow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline friend std::ostream &operator<<(std::ostream &os, Columns const &cols) {
|
inline friend std::ostream &operator<<(std::ostream &os, Columns const &cols) {
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto line : cols) {
|
for (auto line : cols) {
|
||||||
if (first)
|
if (first)
|
||||||
@ -364,19 +336,20 @@ namespace clara { namespace TextFlow {
|
|||||||
cols += other;
|
cols += other;
|
||||||
return cols;
|
return cols;
|
||||||
}
|
}
|
||||||
}}
|
} // namespace TextFlow
|
||||||
|
} // namespace clara
|
||||||
|
|
||||||
#endif // CLARA_TEXTFLOW_HPP_INCLUDED
|
#endif // CLARA_TEXTFLOW_HPP_INCLUDED
|
||||||
|
|
||||||
// ----------- end of #include from clara_textflow.hpp -----------
|
// ----------- end of #include from clara_textflow.hpp -----------
|
||||||
// ........... back in clara.hpp
|
// ........... back in clara.hpp
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#if !defined(CLARA_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
|
#if !defined(CLARA_PLATFORM_WINDOWS) && \
|
||||||
|
(defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER))
|
||||||
#define CLARA_PLATFORM_WINDOWS
|
#define CLARA_PLATFORM_WINDOWS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -408,25 +381,17 @@ namespace detail {
|
|||||||
std::vector<std::string> m_args;
|
std::vector<std::string> m_args;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Args( int argc, char const* const* argv )
|
Args(int argc, char const *const *argv) : m_exeName(argv[0]), m_args(argv + 1, argv + argc) {}
|
||||||
: m_exeName(argv[0]),
|
|
||||||
m_args(argv + 1, argv + argc) {}
|
|
||||||
|
|
||||||
Args(std::initializer_list<std::string> args)
|
Args(std::initializer_list<std::string> args)
|
||||||
: m_exeName( *args.begin() ),
|
: m_exeName(*args.begin()), m_args(args.begin() + 1, args.end()) {}
|
||||||
m_args( args.begin()+1, args.end() )
|
|
||||||
{}
|
|
||||||
|
|
||||||
auto exeName() const -> std::string {
|
auto exeName() const -> std::string { return m_exeName; }
|
||||||
return m_exeName;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wraps a token coming from a token stream. These may not directly correspond to strings as a single string
|
// Wraps a token coming from a token stream. These may not directly correspond to strings as a
|
||||||
// may encode an option + its argument if the : or = form is used
|
// single string may encode an option + its argument if the : or = form is used
|
||||||
enum class TokenType {
|
enum class TokenType { Option, Argument };
|
||||||
Option, Argument
|
|
||||||
};
|
|
||||||
struct Token {
|
struct Token {
|
||||||
TokenType type;
|
TokenType type;
|
||||||
std::string token;
|
std::string token;
|
||||||
@ -451,8 +416,7 @@ namespace detail {
|
|||||||
m_tokenBuffer.resize(0);
|
m_tokenBuffer.resize(0);
|
||||||
|
|
||||||
// Skip any empty strings
|
// Skip any empty strings
|
||||||
while( it != itEnd && it->empty() )
|
while (it != itEnd && it->empty()) ++it;
|
||||||
++it;
|
|
||||||
|
|
||||||
if (it != itEnd) {
|
if (it != itEnd) {
|
||||||
auto const &next = *it;
|
auto const &next = *it;
|
||||||
@ -481,13 +445,9 @@ namespace detail {
|
|||||||
public:
|
public:
|
||||||
explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {}
|
explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {}
|
||||||
|
|
||||||
TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
|
TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { loadBuffer(); }
|
||||||
loadBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const {
|
explicit operator bool() const { return !m_tokenBuffer.empty() || it != itEnd; }
|
||||||
return !m_tokenBuffer.empty() || it != itEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }
|
auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }
|
||||||
|
|
||||||
@ -505,20 +465,16 @@ namespace detail {
|
|||||||
if (m_tokenBuffer.size() >= 2) {
|
if (m_tokenBuffer.size() >= 2) {
|
||||||
m_tokenBuffer.erase(m_tokenBuffer.begin());
|
m_tokenBuffer.erase(m_tokenBuffer.begin());
|
||||||
} else {
|
} else {
|
||||||
if( it != itEnd )
|
if (it != itEnd) ++it;
|
||||||
++it;
|
|
||||||
loadBuffer();
|
loadBuffer();
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ResultBase {
|
class ResultBase {
|
||||||
public:
|
public:
|
||||||
enum Type {
|
enum Type { Ok, LogicError, RuntimeError };
|
||||||
Ok, LogicError, RuntimeError
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ResultBase(Type type) : m_type(type) {}
|
ResultBase(Type type) : m_type(type) {}
|
||||||
@ -541,26 +497,20 @@ namespace detail {
|
|||||||
ResultValueBase(Type type) : ResultBase(type) {}
|
ResultValueBase(Type type) : ResultBase(type) {}
|
||||||
|
|
||||||
ResultValueBase(ResultValueBase const &other) : ResultBase(other) {
|
ResultValueBase(ResultValueBase const &other) : ResultBase(other) {
|
||||||
if( m_type == ResultBase::Ok )
|
if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value);
|
||||||
new( &m_value ) T( other.m_value );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {
|
ResultValueBase(Type, T const &value) : ResultBase(Ok) { new (&m_value) T(value); }
|
||||||
new( &m_value ) T( value );
|
|
||||||
}
|
|
||||||
|
|
||||||
auto operator=(ResultValueBase const &other) -> ResultValueBase & {
|
auto operator=(ResultValueBase const &other) -> ResultValueBase & {
|
||||||
if( m_type == ResultBase::Ok )
|
if (m_type == ResultBase::Ok) m_value.~T();
|
||||||
m_value.~T();
|
|
||||||
ResultBase::operator=(other);
|
ResultBase::operator=(other);
|
||||||
if( m_type == ResultBase::Ok )
|
if (m_type == ResultBase::Ok) new (&m_value) T(other.m_value);
|
||||||
new( &m_value ) T( other.m_value );
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ResultValueBase() override {
|
~ResultValueBase() override {
|
||||||
if( m_type == Ok )
|
if (m_type == Ok) m_value.~T();
|
||||||
m_value.~T();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
union {
|
union {
|
||||||
@ -579,17 +529,21 @@ namespace detail {
|
|||||||
public:
|
public:
|
||||||
template <typename U>
|
template <typename U>
|
||||||
explicit BasicResult(BasicResult<U> const &other)
|
explicit BasicResult(BasicResult<U> const &other)
|
||||||
: ResultValueBase<T>( other.type() ),
|
: ResultValueBase<T>(other.type()), m_errorMessage(other.errorMessage()) {
|
||||||
m_errorMessage( other.errorMessage() )
|
|
||||||
{
|
|
||||||
assert(type() != ResultBase::Ok);
|
assert(type() != ResultBase::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; }
|
static auto ok(U const &value) -> BasicResult {
|
||||||
|
return {ResultBase::Ok, value};
|
||||||
|
}
|
||||||
static auto ok() -> BasicResult { return {ResultBase::Ok}; }
|
static auto ok() -> BasicResult { return {ResultBase::Ok}; }
|
||||||
static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; }
|
static auto logicError(std::string const &message) -> BasicResult {
|
||||||
static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; }
|
return {ResultBase::LogicError, message};
|
||||||
|
}
|
||||||
|
static auto runtimeError(std::string const &message) -> BasicResult {
|
||||||
|
return {ResultBase::RuntimeError, message};
|
||||||
|
}
|
||||||
|
|
||||||
explicit operator bool() const { return m_type == ResultBase::Ok; }
|
explicit operator bool() const { return m_type == ResultBase::Ok; }
|
||||||
auto type() const -> ResultBase::Type { return m_type; }
|
auto type() const -> ResultBase::Type { return m_type; }
|
||||||
@ -597,21 +551,17 @@ namespace detail {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void enforceOk() const override {
|
void enforceOk() const override {
|
||||||
|
|
||||||
// Errors shouldn't reach this point, but if they do
|
// Errors shouldn't reach this point, but if they do
|
||||||
// the actual error message will be in m_errorMessage
|
// the actual error message will be in m_errorMessage
|
||||||
assert(m_type != ResultBase::LogicError);
|
assert(m_type != ResultBase::LogicError);
|
||||||
assert(m_type != ResultBase::RuntimeError);
|
assert(m_type != ResultBase::RuntimeError);
|
||||||
if( m_type != ResultBase::Ok )
|
if (m_type != ResultBase::Ok) std::abort();
|
||||||
std::abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string m_errorMessage; // Only populated if resultType is an error
|
std::string m_errorMessage; // Only populated if resultType is an error
|
||||||
|
|
||||||
BasicResult(ResultBase::Type type, std::string const &message)
|
BasicResult(ResultBase::Type type, std::string const &message)
|
||||||
: ResultValueBase<T>(type),
|
: ResultValueBase<T>(type), m_errorMessage(message) {
|
||||||
m_errorMessage(message)
|
|
||||||
{
|
|
||||||
assert(m_type != ResultBase::Ok);
|
assert(m_type != ResultBase::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,17 +569,12 @@ namespace detail {
|
|||||||
using ResultBase::m_type;
|
using ResultBase::m_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ParseResultType {
|
enum class ParseResultType { Matched, NoMatch, ShortCircuitAll, ShortCircuitSame };
|
||||||
Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
|
|
||||||
};
|
|
||||||
|
|
||||||
class ParseState {
|
class ParseState {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ParseState(ParseResultType type, TokenStream const &remainingTokens)
|
ParseState(ParseResultType type, TokenStream const &remainingTokens)
|
||||||
: m_type(type),
|
: m_type(type), m_remainingTokens(remainingTokens) {}
|
||||||
m_remainingTokens( remainingTokens )
|
|
||||||
{}
|
|
||||||
|
|
||||||
auto type() const -> ParseResultType { return m_type; }
|
auto type() const -> ParseResultType { return m_type; }
|
||||||
auto remainingTokens() const -> TokenStream { return m_remainingTokens; }
|
auto remainingTokens() const -> TokenStream { return m_remainingTokens; }
|
||||||
@ -664,22 +609,24 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
inline auto convertInto(std::string const &source, bool &target) -> ParserResult {
|
inline auto convertInto(std::string const &source, bool &target) -> ParserResult {
|
||||||
std::string srcLC = source;
|
std::string srcLC = source;
|
||||||
std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( ::tolower(c) ); } );
|
std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(),
|
||||||
|
[](char c) { return static_cast<char>(::tolower(c)); });
|
||||||
if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
|
if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
|
||||||
target = true;
|
target = true;
|
||||||
else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
|
else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
|
||||||
target = false;
|
target = false;
|
||||||
else
|
else
|
||||||
return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
|
return ParserResult::runtimeError("Expected a boolean value but did not recognise: '" + source +
|
||||||
|
"'");
|
||||||
return ParserResult::ok(ParseResultType::Matched);
|
return ParserResult::ok(ParseResultType::Matched);
|
||||||
}
|
}
|
||||||
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
|
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
|
inline auto convertInto(std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T> &target)
|
||||||
|
-> ParserResult {
|
||||||
T temp;
|
T temp;
|
||||||
auto result = convertInto(source, temp);
|
auto result = convertInto(source, temp);
|
||||||
if( result )
|
if (result) target = std::move(temp);
|
||||||
target = std::move(temp);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif // CLARA_CONFIG_OPTIONAL_TYPE
|
#endif // CLARA_CONFIG_OPTIONAL_TYPE
|
||||||
@ -711,9 +658,7 @@ namespace detail {
|
|||||||
|
|
||||||
explicit BoundValueRef(T &ref) : m_ref(ref) {}
|
explicit BoundValueRef(T &ref) : m_ref(ref) {}
|
||||||
|
|
||||||
auto setValue( std::string const &arg ) -> ParserResult override {
|
auto setValue(std::string const &arg) -> ParserResult override { return convertInto(arg, m_ref); }
|
||||||
return convertInto( arg, m_ref );
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -727,8 +672,7 @@ namespace detail {
|
|||||||
auto setValue(std::string const &arg) -> ParserResult override {
|
auto setValue(std::string const &arg) -> ParserResult override {
|
||||||
T temp;
|
T temp;
|
||||||
auto result = convertInto(arg, temp);
|
auto result = convertInto(arg, temp);
|
||||||
if( result )
|
if (result) m_ref.push_back(temp);
|
||||||
m_ref.push_back( temp );
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -746,7 +690,8 @@ namespace detail {
|
|||||||
|
|
||||||
template <typename ReturnType>
|
template <typename ReturnType>
|
||||||
struct LambdaInvoker {
|
struct LambdaInvoker {
|
||||||
static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" );
|
static_assert(std::is_same<ReturnType, ParserResult>::value,
|
||||||
|
"Lambda must return void or clara::ParserResult");
|
||||||
|
|
||||||
template <typename L, typename ArgType>
|
template <typename L, typename ArgType>
|
||||||
static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult {
|
static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult {
|
||||||
@ -767,12 +712,10 @@ namespace detail {
|
|||||||
inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult {
|
inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult {
|
||||||
ArgType temp{};
|
ArgType temp{};
|
||||||
auto result = convertInto(arg, temp);
|
auto result = convertInto(arg, temp);
|
||||||
return !result
|
return !result ? result
|
||||||
? result
|
|
||||||
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(lambda, temp);
|
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(lambda, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename L>
|
template <typename L>
|
||||||
struct BoundLambda : BoundValueRefBase {
|
struct BoundLambda : BoundValueRefBase {
|
||||||
L m_lambda;
|
L m_lambda;
|
||||||
@ -790,7 +733,8 @@ namespace detail {
|
|||||||
L m_lambda;
|
L m_lambda;
|
||||||
|
|
||||||
static_assert(UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument");
|
static_assert(UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument");
|
||||||
static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" );
|
static_assert(std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value,
|
||||||
|
"flags must be boolean");
|
||||||
|
|
||||||
explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {}
|
explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {}
|
||||||
|
|
||||||
@ -807,7 +751,8 @@ namespace detail {
|
|||||||
public:
|
public:
|
||||||
virtual ~ParserBase() = default;
|
virtual ~ParserBase() = default;
|
||||||
virtual auto validate() const -> Result { return Result::ok(); }
|
virtual auto validate() const -> Result { return Result::ok(); }
|
||||||
virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0;
|
virtual auto parse(std::string const &exeName, TokenStream const &tokens) const
|
||||||
|
-> InternalParseResult = 0;
|
||||||
virtual auto cardinality() const -> size_t { return 1; }
|
virtual auto cardinality() const -> size_t { return 1; }
|
||||||
|
|
||||||
auto parse(Args const &args) const -> InternalParseResult {
|
auto parse(Args const &args) const -> InternalParseResult {
|
||||||
@ -839,15 +784,11 @@ namespace detail {
|
|||||||
public:
|
public:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
ParserRefImpl(T &ref, std::string const &hint)
|
ParserRefImpl(T &ref, std::string const &hint)
|
||||||
: m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
|
: m_ref(std::make_shared<BoundValueRef<T>>(ref)), m_hint(hint) {}
|
||||||
m_hint( hint )
|
|
||||||
{}
|
|
||||||
|
|
||||||
template <typename LambdaT>
|
template <typename LambdaT>
|
||||||
ParserRefImpl(LambdaT const &ref, std::string const &hint)
|
ParserRefImpl(LambdaT const &ref, std::string const &hint)
|
||||||
: m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
|
: m_ref(std::make_shared<BoundLambda<LambdaT>>(ref)), m_hint(hint) {}
|
||||||
m_hint(hint)
|
|
||||||
{}
|
|
||||||
|
|
||||||
auto operator()(std::string const &description) -> DerivedT & {
|
auto operator()(std::string const &description) -> DerivedT & {
|
||||||
m_description = description;
|
m_description = description;
|
||||||
@ -864,9 +805,7 @@ namespace detail {
|
|||||||
return static_cast<DerivedT &>(*this);
|
return static_cast<DerivedT &>(*this);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto isOptional() const -> bool {
|
auto isOptional() const -> bool { return m_optionality == Optionality::Optional; }
|
||||||
return m_optionality == Optionality::Optional;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cardinality() const -> size_t override {
|
auto cardinality() const -> size_t override {
|
||||||
if (m_ref->isContainer())
|
if (m_ref->isContainer())
|
||||||
@ -906,11 +845,8 @@ namespace detail {
|
|||||||
|
|
||||||
auto name() const -> std::string { return *m_name; }
|
auto name() const -> std::string { return *m_name; }
|
||||||
auto set(std::string const &newName) -> ParserResult {
|
auto set(std::string const &newName) -> ParserResult {
|
||||||
|
|
||||||
auto lastSlash = newName.find_last_of("\\/");
|
auto lastSlash = newName.find_last_of("\\/");
|
||||||
auto filename = ( lastSlash == std::string::npos )
|
auto filename = (lastSlash == std::string::npos) ? newName : newName.substr(lastSlash + 1);
|
||||||
? newName
|
|
||||||
: newName.substr( lastSlash+1 );
|
|
||||||
|
|
||||||
*m_name = filename;
|
*m_name = filename;
|
||||||
if (m_ref)
|
if (m_ref)
|
||||||
@ -926,8 +862,7 @@ namespace detail {
|
|||||||
|
|
||||||
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override {
|
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override {
|
||||||
auto validationResult = validate();
|
auto validationResult = validate();
|
||||||
if( !validationResult )
|
if (!validationResult) return InternalParseResult(validationResult);
|
||||||
return InternalParseResult( validationResult );
|
|
||||||
|
|
||||||
auto remainingTokens = tokens;
|
auto remainingTokens = tokens;
|
||||||
auto const &token = *remainingTokens;
|
auto const &token = *remainingTokens;
|
||||||
@ -960,7 +895,8 @@ namespace detail {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename LambdaT>
|
template <typename LambdaT>
|
||||||
explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
|
explicit Opt(LambdaT const &ref)
|
||||||
|
: ParserRefImpl(std::make_shared<BoundFlagLambda<LambdaT>>(ref)) {}
|
||||||
|
|
||||||
explicit Opt(bool &ref) : ParserRefImpl(std::make_shared<BoundFlagRef>(ref)) {}
|
explicit Opt(bool &ref) : ParserRefImpl(std::make_shared<BoundFlagRef>(ref)) {}
|
||||||
|
|
||||||
@ -985,16 +921,14 @@ namespace detail {
|
|||||||
oss << ", ";
|
oss << ", ";
|
||||||
oss << opt;
|
oss << opt;
|
||||||
}
|
}
|
||||||
if( !m_hint.empty() )
|
if (!m_hint.empty()) oss << " <" << m_hint << ">";
|
||||||
oss << " <" << m_hint << ">";
|
|
||||||
return {{oss.str(), m_description}};
|
return {{oss.str(), m_description}};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto isMatch(std::string const &optToken) const -> bool {
|
auto isMatch(std::string const &optToken) const -> bool {
|
||||||
auto normalisedToken = normaliseOpt(optToken);
|
auto normalisedToken = normaliseOpt(optToken);
|
||||||
for (auto const &name : m_optNames) {
|
for (auto const &name : m_optNames) {
|
||||||
if( normaliseOpt( name ) == normalisedToken )
|
if (normaliseOpt(name) == normalisedToken) return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1003,8 +937,7 @@ namespace detail {
|
|||||||
|
|
||||||
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override {
|
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override {
|
||||||
auto validationResult = validate();
|
auto validationResult = validate();
|
||||||
if( !validationResult )
|
if (!validationResult) return InternalParseResult(validationResult);
|
||||||
return InternalParseResult( validationResult );
|
|
||||||
|
|
||||||
auto remainingTokens = tokens;
|
auto remainingTokens = tokens;
|
||||||
if (remainingTokens && remainingTokens->type == TokenType::Option) {
|
if (remainingTokens && remainingTokens->type == TokenType::Option) {
|
||||||
@ -1013,8 +946,7 @@ namespace detail {
|
|||||||
if (m_ref->isFlag()) {
|
if (m_ref->isFlag()) {
|
||||||
auto flagRef = static_cast<detail::BoundFlagRefBase *>(m_ref.get());
|
auto flagRef = static_cast<detail::BoundFlagRefBase *>(m_ref.get());
|
||||||
auto result = flagRef->setFlag(true);
|
auto result = flagRef->setFlag(true);
|
||||||
if( !result )
|
if (!result) return InternalParseResult(result);
|
||||||
return InternalParseResult( result );
|
|
||||||
if (result.value() == ParseResultType::ShortCircuitAll)
|
if (result.value() == ParseResultType::ShortCircuitAll)
|
||||||
return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
|
return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
|
||||||
} else {
|
} else {
|
||||||
@ -1026,8 +958,7 @@ namespace detail {
|
|||||||
if (argToken.type != TokenType::Argument)
|
if (argToken.type != TokenType::Argument)
|
||||||
return InternalParseResult::runtimeError("Expected argument following " + token.token);
|
return InternalParseResult::runtimeError("Expected argument following " + token.token);
|
||||||
auto result = valueRef->setValue(argToken.token);
|
auto result = valueRef->setValue(argToken.token);
|
||||||
if( !result )
|
if (!result) return InternalParseResult(result);
|
||||||
return InternalParseResult( result );
|
|
||||||
if (result.value() == ParseResultType::ShortCircuitAll)
|
if (result.value() == ParseResultType::ShortCircuitAll)
|
||||||
return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
|
return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
|
||||||
}
|
}
|
||||||
@ -1038,17 +969,14 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto validate() const -> Result override {
|
auto validate() const -> Result override {
|
||||||
if( m_optNames.empty() )
|
if (m_optNames.empty()) return Result::logicError("No options supplied to Opt");
|
||||||
return Result::logicError( "No options supplied to Opt" );
|
|
||||||
for (auto const &name : m_optNames) {
|
for (auto const &name : m_optNames) {
|
||||||
if( name.empty() )
|
if (name.empty()) return Result::logicError("Option name cannot be empty");
|
||||||
return Result::logicError( "Option name cannot be empty" );
|
|
||||||
#ifdef CLARA_PLATFORM_WINDOWS
|
#ifdef CLARA_PLATFORM_WINDOWS
|
||||||
if (name[0] != '-' && name[0] != '/')
|
if (name[0] != '-' && name[0] != '/')
|
||||||
return Result::logicError("Option name must begin with '-' or '/'");
|
return Result::logicError("Option name must begin with '-' or '/'");
|
||||||
#else
|
#else
|
||||||
if( name[0] != '-' )
|
if (name[0] != '-') return Result::logicError("Option name must begin with '-'");
|
||||||
return Result::logicError( "Option name must begin with '-'" );
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return ParserRefImpl::validate();
|
return ParserRefImpl::validate();
|
||||||
@ -1060,18 +988,12 @@ namespace detail {
|
|||||||
: Opt([&](bool flag) {
|
: Opt([&](bool flag) {
|
||||||
showHelpFlag = flag;
|
showHelpFlag = flag;
|
||||||
return ParserResult::ok(ParseResultType::ShortCircuitAll);
|
return ParserResult::ok(ParseResultType::ShortCircuitAll);
|
||||||
})
|
}) {
|
||||||
{
|
static_cast<Opt &> (*this)("display usage information")["-?"]["-h"]["--help"].optional();
|
||||||
static_cast<Opt &>( *this )
|
|
||||||
("display usage information")
|
|
||||||
["-?"]["-h"]["--help"]
|
|
||||||
.optional();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Parser : ParserBase {
|
struct Parser : ParserBase {
|
||||||
|
|
||||||
mutable ExeName m_exeName;
|
mutable ExeName m_exeName;
|
||||||
std::vector<Opt> m_options;
|
std::vector<Opt> m_options;
|
||||||
std::vector<Arg> m_args;
|
std::vector<Arg> m_args;
|
||||||
@ -1104,9 +1026,13 @@ namespace detail {
|
|||||||
|
|
||||||
// Forward deprecated interface with '+' instead of '|'
|
// Forward deprecated interface with '+' instead of '|'
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
|
auto operator+=(T const &other) -> Parser & {
|
||||||
|
return operator|=(other);
|
||||||
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto operator+( T const &other ) const -> Parser { return operator|( other ); }
|
auto operator+(T const &other) const -> Parser {
|
||||||
|
return operator|(other);
|
||||||
|
}
|
||||||
|
|
||||||
auto getHelpColumns() const -> std::vector<HelpColumns> {
|
auto getHelpColumns() const -> std::vector<HelpColumns> {
|
||||||
std::vector<HelpColumns> cols;
|
std::vector<HelpColumns> cols;
|
||||||
@ -1119,7 +1045,8 @@ namespace detail {
|
|||||||
|
|
||||||
void writeToStream(std::ostream &os) const {
|
void writeToStream(std::ostream &os) const {
|
||||||
if (!m_exeName.name().empty()) {
|
if (!m_exeName.name().empty()) {
|
||||||
os << "usage:\n" << " " << m_exeName.name() << " ";
|
os << "usage:\n"
|
||||||
|
<< " " << m_exeName.name() << " ";
|
||||||
bool required = true, first = true;
|
bool required = true, first = true;
|
||||||
for (auto const &arg : m_args) {
|
for (auto const &arg : m_args) {
|
||||||
if (first)
|
if (first)
|
||||||
@ -1131,28 +1058,22 @@ namespace detail {
|
|||||||
required = false;
|
required = false;
|
||||||
}
|
}
|
||||||
os << "<" << arg.hint() << ">";
|
os << "<" << arg.hint() << ">";
|
||||||
if( arg.cardinality() == 0 )
|
if (arg.cardinality() == 0) os << " ... ";
|
||||||
os << " ... ";
|
|
||||||
}
|
}
|
||||||
if( !required )
|
if (!required) os << "]";
|
||||||
os << "]";
|
if (!m_options.empty()) os << " options";
|
||||||
if( !m_options.empty() )
|
|
||||||
os << " options";
|
|
||||||
os << "\n\nwhere options are:" << std::endl;
|
os << "\n\nwhere options are:" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rows = getHelpColumns();
|
auto rows = getHelpColumns();
|
||||||
size_t consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
|
size_t consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
|
||||||
size_t optWidth = 0;
|
size_t optWidth = 0;
|
||||||
for( auto const &cols : rows )
|
for (auto const &cols : rows) optWidth = (std::max)(optWidth, cols.left.size() + 2);
|
||||||
optWidth = (std::max)(optWidth, cols.left.size() + 2);
|
|
||||||
|
|
||||||
optWidth = (std::min)(optWidth, consoleWidth / 2);
|
optWidth = (std::min)(optWidth, consoleWidth / 2);
|
||||||
|
|
||||||
for (auto const &cols : rows) {
|
for (auto const &cols : rows) {
|
||||||
auto row =
|
auto row = TextFlow::Column(cols.left).width(optWidth).indent(2) + TextFlow::Spacer(4) +
|
||||||
TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
|
|
||||||
TextFlow::Spacer(4) +
|
|
||||||
TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth);
|
TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth);
|
||||||
os << row << std::endl;
|
os << row << std::endl;
|
||||||
}
|
}
|
||||||
@ -1166,21 +1087,19 @@ namespace detail {
|
|||||||
auto validate() const -> Result override {
|
auto validate() const -> Result override {
|
||||||
for (auto const &opt : m_options) {
|
for (auto const &opt : m_options) {
|
||||||
auto result = opt.validate();
|
auto result = opt.validate();
|
||||||
if( !result )
|
if (!result) return result;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
for (auto const &arg : m_args) {
|
for (auto const &arg : m_args) {
|
||||||
auto result = arg.validate();
|
auto result = arg.validate();
|
||||||
if( !result )
|
if (!result) return result;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
return Result::ok();
|
return Result::ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
using ParserBase::parse;
|
using ParserBase::parse;
|
||||||
|
|
||||||
auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override {
|
auto parse(std::string const &exeName, TokenStream const &tokens) const
|
||||||
|
-> InternalParseResult override {
|
||||||
struct ParserInfo {
|
struct ParserInfo {
|
||||||
ParserBase const *parser = nullptr;
|
ParserBase const *parser = nullptr;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
@ -1204,10 +1123,10 @@ namespace detail {
|
|||||||
|
|
||||||
for (size_t i = 0; i < totalParsers; ++i) {
|
for (size_t i = 0; i < totalParsers; ++i) {
|
||||||
auto &parseInfo = parseInfos[i];
|
auto &parseInfo = parseInfos[i];
|
||||||
if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
|
if (parseInfo.parser->cardinality() == 0 ||
|
||||||
|
parseInfo.count < parseInfo.parser->cardinality()) {
|
||||||
result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
|
result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
|
||||||
if (!result)
|
if (!result) return result;
|
||||||
return result;
|
|
||||||
if (result.value().type() != ParseResultType::NoMatch) {
|
if (result.value().type() != ParseResultType::NoMatch) {
|
||||||
tokenParsed = true;
|
tokenParsed = true;
|
||||||
++parseInfo.count;
|
++parseInfo.count;
|
||||||
@ -1216,10 +1135,10 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( result.value().type() == ParseResultType::ShortCircuitAll )
|
if (result.value().type() == ParseResultType::ShortCircuitAll) return result;
|
||||||
return result;
|
|
||||||
if (!tokenParsed)
|
if (!tokenParsed)
|
||||||
return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token );
|
return InternalParseResult::runtimeError("Unrecognised token: " +
|
||||||
|
result.value().remainingTokens()->token);
|
||||||
}
|
}
|
||||||
// !TBD Check missing required options
|
// !TBD Check missing required options
|
||||||
return result;
|
return result;
|
||||||
@ -1233,7 +1152,6 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
// A Combined parser
|
// A Combined parser
|
||||||
using detail::Parser;
|
using detail::Parser;
|
||||||
|
|
||||||
@ -1258,7 +1176,6 @@ using detail::ParseResultType;
|
|||||||
// Result type for parser operation
|
// Result type for parser operation
|
||||||
using detail::ParserResult;
|
using detail::ParserResult;
|
||||||
|
|
||||||
|
|
||||||
} // namespace clara
|
} // namespace clara
|
||||||
|
|
||||||
#endif // CLARA_HPP_INCLUDED
|
#endif // CLARA_HPP_INCLUDED
|
||||||
|
@ -5,15 +5,14 @@
|
|||||||
|
|
||||||
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> {
|
||||||
@ -77,16 +76,16 @@ namespace fmt {
|
|||||||
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
|
// Glib ustirng support
|
||||||
template <>
|
template <>
|
||||||
struct formatter<Glib::ustring> : formatter<std::string> {
|
struct formatter<Glib::ustring> : formatter<std::string> {
|
||||||
@ -95,5 +94,4 @@ namespace fmt {
|
|||||||
return formatter<std::string>::format(value, ctx);
|
return formatter<std::string>::format(value, ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace fmt
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ 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); }
|
||||||
|
@ -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*
|
||||||
|
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
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -79,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*
|
||||||
|
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.
|
@ -75,6 +75,11 @@ Addressed by *sway/window*
|
|||||||
default: false ++
|
default: false ++
|
||||||
Option to hide the application icon.
|
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
|
||||||
|
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*
|
@ -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* ++
|
||||||
|
26
meson.build
26
meson.build
@ -1,6 +1,6 @@
|
|||||||
project(
|
project(
|
||||||
'waybar', 'cpp', 'c',
|
'waybar', 'cpp', 'c',
|
||||||
version: '0.9.12',
|
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'))
|
||||||
@ -196,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()
|
||||||
@ -203,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'
|
||||||
@ -246,17 +259,15 @@ 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/modules/bluetooth.cpp',
|
|
||||||
'src/util/rfkill.cpp'
|
'src/util/rfkill.cpp'
|
||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
endif
|
|
||||||
|
|
||||||
if tz_dep.found()
|
if tz_dep.found()
|
||||||
add_project_arguments('-DHAVE_LIBDATE', language: 'cpp')
|
add_project_arguments('-DHAVE_LIBDATE', language: 'cpp')
|
||||||
@ -288,6 +299,7 @@ executable(
|
|||||||
giounix,
|
giounix,
|
||||||
libnl,
|
libnl,
|
||||||
libnlgen,
|
libnlgen,
|
||||||
|
upower_glib,
|
||||||
libpulse,
|
libpulse,
|
||||||
libudev,
|
libudev,
|
||||||
libepoll,
|
libepoll,
|
||||||
@ -340,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',
|
||||||
@ -351,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,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 { AModule::update(); }
|
||||||
}
|
|
||||||
|
|
||||||
auto ALabel::update() -> void {
|
|
||||||
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,20 +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)),
|
||||||
, distance_scrolled_y_(0.0)
|
config_(std::move(config)),
|
||||||
, distance_scrolled_x_(0.0) {
|
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);
|
||||||
@ -30,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()) {
|
||||||
@ -39,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));
|
||||||
}
|
}
|
||||||
@ -60,10 +70,14 @@ 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};
|
||||||
|
|
||||||
@ -101,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
46
src/bar.cpp
46
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 {
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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);
|
||||||
@ -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,8 +674,12 @@ void waybar::Bar::onMap(GdkEventAny*) {
|
|||||||
|
|
||||||
void waybar::Bar::setVisible(bool value) {
|
void waybar::Bar::setVisible(bool value) {
|
||||||
visible = value;
|
visible = value;
|
||||||
|
if (auto mode = config.get("mode", {}); mode.isString()) {
|
||||||
|
setMode(visible ? config["mode"].asString() : MODE_INVISIBLE);
|
||||||
|
} else {
|
||||||
setMode(visible ? MODE_DEFAULT : MODE_INVISIBLE);
|
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) {
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
@ -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() {
|
||||||
@ -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) {
|
||||||
|
@ -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]);
|
||||||
@ -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
|
||||||
|
11
src/main.cpp
11
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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,8 +86,9 @@ 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;
|
||||||
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,6 +160,7 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
|
|||||||
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;
|
||||||
@ -160,19 +168,27 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
|
|||||||
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::getline(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;
|
||||||
|
// Some batteries have only *_avg, not *_now
|
||||||
|
if (fs::exists(bat / "voltage_now"))
|
||||||
std::ifstream(bat / "voltage_now") >> 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;
|
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,7 +245,12 @@ 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);
|
||||||
@ -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_) {
|
||||||
|
std::stringstream ss;
|
||||||
|
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 {
|
} else {
|
||||||
label_.set_tooltip_text(status);
|
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
|
||||||
@ -24,42 +26,36 @@ 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)
|
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) {
|
||||||
@ -79,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() {
|
||||||
@ -120,7 +118,9 @@ auto waybar::modules::Clock::update() -> void {
|
|||||||
timezoned_time_lines = timezones_text(&now);
|
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), fmt::arg(KTimezonedTimeListPlaceholder.c_str(), timezoned_time_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,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();
|
||||||
@ -166,9 +167,32 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str
|
|||||||
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();
|
||||||
@ -180,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()) {
|
||||||
@ -189,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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,9 +247,10 @@ 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();
|
||||||
@ -214,12 +260,18 @@ auto waybar::modules::Clock::weekdays_header(const date::weekday& first_dow, std
|
|||||||
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::_V2::system_clock::time_point *now) -> std::string {
|
auto waybar::modules::Clock::timezones_text(std::chrono::system_clock::time_point* now)
|
||||||
|
-> std::string {
|
||||||
if (time_zones_.size() == 1) {
|
if (time_zones_.size() == 1) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -239,6 +291,16 @@ auto waybar::modules::Clock::timezones_text(std::chrono::_V2::system_clock::time
|
|||||||
return os.str();
|
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
|
||||||
template <auto fn>
|
template <auto fn>
|
||||||
using deleter_from_fn = std::integral_constant<decltype(fn), fn>;
|
using deleter_from_fn = std::integral_constant<decltype(fn), fn>;
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
#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>
|
||||||
@ -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;
|
||||||
|
@ -94,8 +94,12 @@ 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;
|
||||||
|
@ -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() {
|
||||||
@ -51,10 +52,7 @@ 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",
|
|
||||||
"/cpuinfo_max_freq"
|
|
||||||
};
|
|
||||||
for (auto& p : std::filesystem::directory_iterator(cpufreq_dir)) {
|
for (auto& p : std::filesystem::directory_iterator(cpufreq_dir)) {
|
||||||
for (auto freq_file : frequency_files) {
|
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;
|
||||||
|
@ -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()) {
|
||||||
|
@ -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
|
@ -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) {
|
||||||
|
@ -10,8 +10,7 @@ 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);
|
||||||
@ -23,9 +22,7 @@ auto dbus() -> DBus {
|
|||||||
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(): {}",
|
|
||||||
error->message);
|
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -38,28 +35,13 @@ auto getLocks(const DBus& bus, const std::string& inhibitors) -> int {
|
|||||||
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,17 +112,13 @@ 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::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);
|
||||||
|
|
||||||
@ -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,31 +1,32 @@
|
|||||||
#include "modules/keyboard_state.hpp"
|
#include "modules/keyboard_state.hpp"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <filesystem>
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <string.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>
|
||||||
}
|
}
|
||||||
|
|
||||||
class errno_error : public std::runtime_error {
|
class errno_error : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
int code;
|
int code;
|
||||||
errno_error(int code, const std::string& msg)
|
errno_error(int code, const std::string& msg)
|
||||||
: std::runtime_error(getErrorMsg(code, msg.c_str())),
|
: std::runtime_error(getErrorMsg(code, msg.c_str())), code(code) {}
|
||||||
code(code) {}
|
errno_error(int code, const char* msg) : std::runtime_error(getErrorMsg(code, msg)), code(code) {}
|
||||||
errno_error(int code, const char* msg)
|
|
||||||
: std::runtime_error(getErrorMsg(code, msg)),
|
|
||||||
code(code) {}
|
|
||||||
private:
|
private:
|
||||||
static auto getErrorMsg(int err, const char* msg) -> std::string {
|
static auto getErrorMsg(int err, const char* msg) -> std::string {
|
||||||
std::string error_msg{msg};
|
std::string error_msg{msg};
|
||||||
error_msg += ": ";
|
error_msg += ": ";
|
||||||
|
|
||||||
#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 32)
|
#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
|
// 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);
|
const auto errno_name = strerrorname_np(err);
|
||||||
error_msg += errno_name;
|
error_msg += errno_name;
|
||||||
error_msg += " ";
|
error_msg += " ";
|
||||||
@ -67,27 +68,31 @@ auto openDevice(int fd) -> libevdev* {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto supportsLockStates(const libevdev* dev) -> bool {
|
auto supportsLockStates(const libevdev* dev) -> bool {
|
||||||
return libevdev_has_event_type(dev, EV_LED)
|
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_NUML)
|
libevdev_has_event_code(dev, EV_LED, LED_CAPSL) &&
|
||||||
&& libevdev_has_event_code(dev, EV_LED, LED_CAPSL)
|
libevdev_has_event_code(dev, EV_LED, LED_SCROLLL);
|
||||||
&& libevdev_has_event_code(dev, EV_LED, LED_SCROLLL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& bar, const Json::Value& config)
|
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()
|
||||||
|
? config_["format"]["numlock"].asString()
|
||||||
: "{name} {icon}"),
|
: "{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()
|
||||||
|
? config_["format"]["capslock"].asString()
|
||||||
: "{name} {icon}"),
|
: "{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()
|
||||||
|
? config_["format"]["scrolllock"].asString()
|
||||||
: "{name} {icon}"),
|
: "{name} {icon}"),
|
||||||
interval_(std::chrono::seconds(config_["interval"].isUInt() ? config_["interval"].asUInt() : 1)),
|
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"),
|
||||||
@ -98,12 +103,15 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
|
|||||||
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()) {
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#include "modules/memory.hpp"
|
// clang-format off
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
// clang-format on
|
||||||
#include <unistd.h> // getpagesize
|
#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__)
|
||||||
@ -43,21 +45,15 @@ 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
|
||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,31 +54,24 @@ auto waybar::modules::Memory::update() -> void {
|
|||||||
} else {
|
} else {
|
||||||
event_box_.show();
|
event_box_.show();
|
||||||
auto icons = std::vector<std::string>{state};
|
auto icons = std::vector<std::string>{state};
|
||||||
label_.set_markup(fmt::format(format,
|
label_.set_markup(fmt::format(
|
||||||
used_ram_percentage,
|
format, used_ram_percentage, fmt::arg("icon", getIcon(used_ram_percentage, icons)),
|
||||||
fmt::arg("icon", getIcon(used_ram_percentage, icons)),
|
fmt::arg("total", total_ram_gigabytes), fmt::arg("swapTotal", total_swap_gigabytes),
|
||||||
fmt::arg("total", total_ram_gigabytes),
|
|
||||||
fmt::arg("swapTotal", total_swap_gigabytes),
|
|
||||||
fmt::arg("percentage", used_ram_percentage),
|
fmt::arg("percentage", used_ram_percentage),
|
||||||
fmt::arg("swapPercentage", used_swap_percentage),
|
fmt::arg("swapPercentage", used_swap_percentage), fmt::arg("used", used_ram_gigabytes),
|
||||||
fmt::arg("used", used_ram_gigabytes),
|
fmt::arg("swapUsed", used_swap_gigabytes), fmt::arg("avail", available_ram_gigabytes),
|
||||||
fmt::arg("swapUsed", used_swap_gigabytes),
|
|
||||||
fmt::arg("avail", available_ram_gigabytes),
|
|
||||||
fmt::arg("swapAvail", available_swap_gigabytes)));
|
fmt::arg("swapAvail", available_swap_gigabytes)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
if (config_["tooltip-format"].isString()) {
|
if (config_["tooltip-format"].isString()) {
|
||||||
auto tooltip_format = config_["tooltip-format"].asString();
|
auto tooltip_format = config_["tooltip-format"].asString();
|
||||||
label_.set_tooltip_text(fmt::format(tooltip_format,
|
label_.set_tooltip_text(fmt::format(
|
||||||
used_ram_percentage,
|
tooltip_format, used_ram_percentage, fmt::arg("total", total_ram_gigabytes),
|
||||||
fmt::arg("total", total_ram_gigabytes),
|
|
||||||
fmt::arg("swapTotal", total_swap_gigabytes),
|
fmt::arg("swapTotal", total_swap_gigabytes),
|
||||||
fmt::arg("percentage", used_ram_percentage),
|
fmt::arg("percentage", used_ram_percentage),
|
||||||
fmt::arg("swapPercentage", used_swap_percentage),
|
fmt::arg("swapPercentage", used_swap_percentage), fmt::arg("used", used_ram_gigabytes),
|
||||||
fmt::arg("used", used_ram_gigabytes),
|
fmt::arg("swapUsed", used_swap_gigabytes), fmt::arg("avail", available_ram_gigabytes),
|
||||||
fmt::arg("swapUsed", used_swap_gigabytes),
|
|
||||||
fmt::arg("avail", available_ram_gigabytes),
|
|
||||||
fmt::arg("swapAvail", available_swap_gigabytes)));
|
fmt::arg("swapAvail", available_swap_gigabytes)));
|
||||||
} else {
|
} else {
|
||||||
label_.set_tooltip_text(fmt::format("{:.{}f}GiB used", used_ram_gigabytes, 1));
|
label_.set_tooltip_text(fmt::format("{:.{}f}GiB used", used_ram_gigabytes, 1));
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#include "modules/mpd/mpd.hpp"
|
#include "modules/mpd/mpd.hpp"
|
||||||
|
|
||||||
#include <fmt/chrono.h>
|
#include <fmt/chrono.h>
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
#include <glibmm/ustring.h>
|
#include <glibmm/ustring.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
#include "modules/mpd/state.hpp"
|
#include "modules/mpd/state.hpp"
|
||||||
#if defined(MPD_NOINLINE)
|
#if defined(MPD_NOINLINE)
|
||||||
namespace waybar::modules {
|
namespace waybar::modules {
|
||||||
@ -148,28 +149,23 @@ void waybar::modules::MPD::setLabel() {
|
|||||||
bool singleActivated = mpd_status_get_single(status_.get());
|
bool singleActivated = mpd_status_get_single(status_.get());
|
||||||
std::string singleIcon = getOptionIcon("single", singleActivated);
|
std::string singleIcon = getOptionIcon("single", singleActivated);
|
||||||
if (config_["artist-len"].isInt()) artist = artist.substr(0, config_["artist-len"].asInt());
|
if (config_["artist-len"].isInt()) artist = artist.substr(0, config_["artist-len"].asInt());
|
||||||
if (config_["album-artist-len"].isInt()) album_artist = album_artist.substr(0, config_["album-artist-len"].asInt());
|
if (config_["album-artist-len"].isInt())
|
||||||
|
album_artist = album_artist.substr(0, config_["album-artist-len"].asInt());
|
||||||
if (config_["album-len"].isInt()) album = album.substr(0, config_["album-len"].asInt());
|
if (config_["album-len"].isInt()) album = album.substr(0, config_["album-len"].asInt());
|
||||||
if (config_["title-len"].isInt()) title = title.substr(0, config_["title-len"].asInt());
|
if (config_["title-len"].isInt()) title = title.substr(0, config_["title-len"].asInt());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
label_.set_markup(
|
label_.set_markup(
|
||||||
fmt::format(format,
|
fmt::format(format, fmt::arg("artist", Glib::Markup::escape_text(artist).raw()),
|
||||||
fmt::arg("artist", Glib::Markup::escape_text(artist).raw()),
|
|
||||||
fmt::arg("albumArtist", Glib::Markup::escape_text(album_artist).raw()),
|
fmt::arg("albumArtist", Glib::Markup::escape_text(album_artist).raw()),
|
||||||
fmt::arg("album", Glib::Markup::escape_text(album).raw()),
|
fmt::arg("album", Glib::Markup::escape_text(album).raw()),
|
||||||
fmt::arg("title", Glib::Markup::escape_text(title).raw()),
|
fmt::arg("title", Glib::Markup::escape_text(title).raw()),
|
||||||
fmt::arg("date", Glib::Markup::escape_text(date).raw()),
|
fmt::arg("date", Glib::Markup::escape_text(date).raw()),
|
||||||
fmt::arg("volume", volume),
|
fmt::arg("volume", volume), fmt::arg("elapsedTime", elapsedTime),
|
||||||
fmt::arg("elapsedTime", elapsedTime),
|
fmt::arg("totalTime", totalTime), fmt::arg("songPosition", song_pos),
|
||||||
fmt::arg("totalTime", totalTime),
|
fmt::arg("queueLength", queue_length), fmt::arg("stateIcon", stateIcon),
|
||||||
fmt::arg("songPosition", song_pos),
|
fmt::arg("consumeIcon", consumeIcon), fmt::arg("randomIcon", randomIcon),
|
||||||
fmt::arg("queueLength", queue_length),
|
fmt::arg("repeatIcon", repeatIcon), fmt::arg("singleIcon", singleIcon)));
|
||||||
fmt::arg("stateIcon", stateIcon),
|
|
||||||
fmt::arg("consumeIcon", consumeIcon),
|
|
||||||
fmt::arg("randomIcon", randomIcon),
|
|
||||||
fmt::arg("repeatIcon", repeatIcon),
|
|
||||||
fmt::arg("singleIcon", singleIcon)));
|
|
||||||
} catch (fmt::format_error const& e) {
|
} catch (fmt::format_error const& e) {
|
||||||
spdlog::warn("mpd: format error: {}", e.what());
|
spdlog::warn("mpd: format error: {}", e.what());
|
||||||
}
|
}
|
||||||
@ -179,22 +175,15 @@ void waybar::modules::MPD::setLabel() {
|
|||||||
tooltip_format = config_["tooltip-format"].isString() ? config_["tooltip-format"].asString()
|
tooltip_format = config_["tooltip-format"].isString() ? config_["tooltip-format"].asString()
|
||||||
: "MPD (connected)";
|
: "MPD (connected)";
|
||||||
try {
|
try {
|
||||||
auto tooltip_text = fmt::format(tooltip_format,
|
auto tooltip_text =
|
||||||
fmt::arg("artist", artist.raw()),
|
fmt::format(tooltip_format, fmt::arg("artist", artist.raw()),
|
||||||
fmt::arg("albumArtist", album_artist.raw()),
|
fmt::arg("albumArtist", album_artist.raw()), fmt::arg("album", album.raw()),
|
||||||
fmt::arg("album", album.raw()),
|
fmt::arg("title", title.raw()), fmt::arg("date", date),
|
||||||
fmt::arg("title", title.raw()),
|
fmt::arg("volume", volume), fmt::arg("elapsedTime", elapsedTime),
|
||||||
fmt::arg("date", date),
|
fmt::arg("totalTime", totalTime), fmt::arg("songPosition", song_pos),
|
||||||
fmt::arg("volume", volume),
|
fmt::arg("queueLength", queue_length), fmt::arg("stateIcon", stateIcon),
|
||||||
fmt::arg("elapsedTime", elapsedTime),
|
fmt::arg("consumeIcon", consumeIcon), fmt::arg("randomIcon", randomIcon),
|
||||||
fmt::arg("totalTime", totalTime),
|
fmt::arg("repeatIcon", repeatIcon), fmt::arg("singleIcon", singleIcon));
|
||||||
fmt::arg("songPosition", song_pos),
|
|
||||||
fmt::arg("queueLength", queue_length),
|
|
||||||
fmt::arg("stateIcon", stateIcon),
|
|
||||||
fmt::arg("consumeIcon", consumeIcon),
|
|
||||||
fmt::arg("randomIcon", randomIcon),
|
|
||||||
fmt::arg("repeatIcon", repeatIcon),
|
|
||||||
fmt::arg("singleIcon", singleIcon));
|
|
||||||
label_.set_tooltip_text(tooltip_text);
|
label_.set_tooltip_text(tooltip_text);
|
||||||
} catch (fmt::format_error const& e) {
|
} catch (fmt::format_error const& e) {
|
||||||
spdlog::warn("mpd: format error (tooltip): {}", e.what());
|
spdlog::warn("mpd: format error (tooltip): {}", e.what());
|
||||||
|
@ -61,8 +61,7 @@ void Idle::entry() noexcept {
|
|||||||
spdlog::debug("mpd: Idle: watching FD");
|
spdlog::debug("mpd: Idle: watching FD");
|
||||||
sigc::slot<bool, Glib::IOCondition const&> idle_slot = sigc::mem_fun(*this, &Idle::on_io);
|
sigc::slot<bool, Glib::IOCondition const&> idle_slot = sigc::mem_fun(*this, &Idle::on_io);
|
||||||
idle_connection_ =
|
idle_connection_ =
|
||||||
Glib::signal_io().connect(idle_slot,
|
Glib::signal_io().connect(idle_slot, mpd_connection_get_fd(conn),
|
||||||
mpd_connection_get_fd(conn),
|
|
||||||
Glib::IO_IN | Glib::IO_PRI | Glib::IO_ERR | Glib::IO_HUP);
|
Glib::IO_IN | Glib::IO_PRI | Glib::IO_ERR | Glib::IO_HUP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -327,8 +326,7 @@ void Disconnected::arm_timer(int interval) noexcept {
|
|||||||
|
|
||||||
// register timer
|
// register timer
|
||||||
sigc::slot<bool> timer_slot = sigc::mem_fun(*this, &Disconnected::on_timer);
|
sigc::slot<bool> timer_slot = sigc::mem_fun(*this, &Disconnected::on_timer);
|
||||||
timer_connection_ =
|
timer_connection_ = Glib::signal_timeout().connect(timer_slot, interval);
|
||||||
Glib::signal_timeout().connect(timer_slot, interval);
|
|
||||||
spdlog::debug("mpd: Disconnected: enabled interval timer.");
|
spdlog::debug("mpd: Disconnected: enabled interval timer.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,9 +343,7 @@ void Disconnected::entry() noexcept {
|
|||||||
arm_timer(1'000);
|
arm_timer(1'000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disconnected::exit() noexcept {
|
void Disconnected::exit() noexcept { disarm_timer(); }
|
||||||
disarm_timer();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Disconnected::on_timer() {
|
bool Disconnected::on_timer() {
|
||||||
// Attempt to connect with MPD.
|
// Attempt to connect with MPD.
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
|
#include "modules/network.hpp"
|
||||||
|
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "modules/network.hpp"
|
|
||||||
#include "util/format.hpp"
|
#include "util/format.hpp"
|
||||||
#ifdef WANT_RFKILL
|
#ifdef WANT_RFKILL
|
||||||
#include "util/rfkill.hpp"
|
#include "util/rfkill.hpp"
|
||||||
@ -41,7 +42,7 @@ waybar::modules::Network::readBandwidthUsage() {
|
|||||||
std::string ifacename;
|
std::string ifacename;
|
||||||
iss >> ifacename; // ifacename contains "eth0:"
|
iss >> ifacename; // ifacename contains "eth0:"
|
||||||
ifacename.pop_back(); // remove trailing ':'
|
ifacename.pop_back(); // remove trailing ':'
|
||||||
if (!checkInterface(ifacename)) {
|
if (ifacename != ifname_) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,9 +59,13 @@ waybar::modules::Network::readBandwidthUsage() {
|
|||||||
// Skip all the other columns in the received group
|
// Skip all the other columns in the received group
|
||||||
for (int colsToSkip = 7; colsToSkip > 0; colsToSkip--) {
|
for (int colsToSkip = 7; colsToSkip > 0; colsToSkip--) {
|
||||||
// skip whitespace between columns
|
// skip whitespace between columns
|
||||||
while (iss.peek() == ' ') { iss.ignore(); }
|
while (iss.peek() == ' ') {
|
||||||
|
iss.ignore();
|
||||||
|
}
|
||||||
// skip the irrelevant column
|
// skip the irrelevant column
|
||||||
while (iss.peek() != ' ') { iss.ignore(); }
|
while (iss.peek() != ' ') {
|
||||||
|
iss.ignore();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Read transmit bytes
|
// Read transmit bytes
|
||||||
iss >> t;
|
iss >> t;
|
||||||
@ -274,8 +279,7 @@ void waybar::modules::Network::worker() {
|
|||||||
const std::string waybar::modules::Network::getNetworkState() const {
|
const std::string waybar::modules::Network::getNetworkState() const {
|
||||||
if (ifid_ == -1) {
|
if (ifid_ == -1) {
|
||||||
#ifdef WANT_RFKILL
|
#ifdef WANT_RFKILL
|
||||||
if (rfkill_.getState())
|
if (rfkill_.getState()) return "disabled";
|
||||||
return "disabled";
|
|
||||||
#endif
|
#endif
|
||||||
return "disconnected";
|
return "disconnected";
|
||||||
}
|
}
|
||||||
@ -327,22 +331,18 @@ auto waybar::modules::Network::update() -> void {
|
|||||||
getState(signal_strength_);
|
getState(signal_strength_);
|
||||||
|
|
||||||
auto text = fmt::format(
|
auto text = fmt::format(
|
||||||
format_,
|
format_, fmt::arg("essid", essid_), fmt::arg("signaldBm", signal_strength_dbm_),
|
||||||
fmt::arg("essid", essid_),
|
|
||||||
fmt::arg("signaldBm", signal_strength_dbm_),
|
|
||||||
fmt::arg("signalStrength", signal_strength_),
|
fmt::arg("signalStrength", signal_strength_),
|
||||||
fmt::arg("signalStrengthApp", signal_strength_app_),
|
fmt::arg("signalStrengthApp", signal_strength_app_), fmt::arg("ifname", ifname_),
|
||||||
fmt::arg("ifname", ifname_),
|
fmt::arg("netmask", netmask_), fmt::arg("ipaddr", ipaddr_), fmt::arg("gwaddr", gwaddr_),
|
||||||
fmt::arg("netmask", netmask_),
|
fmt::arg("cidr", cidr_), fmt::arg("frequency", fmt::format("{:.1f}", frequency_)),
|
||||||
fmt::arg("ipaddr", ipaddr_),
|
|
||||||
fmt::arg("gwaddr", gwaddr_),
|
|
||||||
fmt::arg("cidr", cidr_),
|
|
||||||
fmt::arg("frequency", fmt::format("{:.1f}", frequency_)),
|
|
||||||
fmt::arg("icon", getIcon(signal_strength_, state_)),
|
fmt::arg("icon", getIcon(signal_strength_, state_)),
|
||||||
fmt::arg("bandwidthDownBits", pow_format(bandwidth_down * 8ull / interval_.count(), "b/s")),
|
fmt::arg("bandwidthDownBits", pow_format(bandwidth_down * 8ull / interval_.count(), "b/s")),
|
||||||
fmt::arg("bandwidthUpBits", pow_format(bandwidth_up * 8ull / interval_.count(), "b/s")),
|
fmt::arg("bandwidthUpBits", pow_format(bandwidth_up * 8ull / interval_.count(), "b/s")),
|
||||||
fmt::arg("bandwidthDownOctets", pow_format(bandwidth_down / interval_.count(), "o/s")),
|
fmt::arg("bandwidthDownOctets", pow_format(bandwidth_down / interval_.count(), "o/s")),
|
||||||
fmt::arg("bandwidthUpOctets", pow_format(bandwidth_up / interval_.count(), "o/s")));
|
fmt::arg("bandwidthUpOctets", pow_format(bandwidth_up / interval_.count(), "o/s")),
|
||||||
|
fmt::arg("bandwidthDownBytes", pow_format(bandwidth_down / interval_.count(), "B/s")),
|
||||||
|
fmt::arg("bandwidthUpBytes", pow_format(bandwidth_up / interval_.count(), "B/s")));
|
||||||
if (text.compare(label_.get_label()) != 0) {
|
if (text.compare(label_.get_label()) != 0) {
|
||||||
label_.set_markup(text);
|
label_.set_markup(text);
|
||||||
if (text.empty()) {
|
if (text.empty()) {
|
||||||
@ -357,23 +357,19 @@ auto waybar::modules::Network::update() -> void {
|
|||||||
}
|
}
|
||||||
if (!tooltip_format.empty()) {
|
if (!tooltip_format.empty()) {
|
||||||
auto tooltip_text = fmt::format(
|
auto tooltip_text = fmt::format(
|
||||||
tooltip_format,
|
tooltip_format, fmt::arg("essid", essid_), fmt::arg("signaldBm", signal_strength_dbm_),
|
||||||
fmt::arg("essid", essid_),
|
|
||||||
fmt::arg("signaldBm", signal_strength_dbm_),
|
|
||||||
fmt::arg("signalStrength", signal_strength_),
|
fmt::arg("signalStrength", signal_strength_),
|
||||||
fmt::arg("signalStrengthApp", signal_strength_app_),
|
fmt::arg("signalStrengthApp", signal_strength_app_), fmt::arg("ifname", ifname_),
|
||||||
fmt::arg("ifname", ifname_),
|
fmt::arg("netmask", netmask_), fmt::arg("ipaddr", ipaddr_), fmt::arg("gwaddr", gwaddr_),
|
||||||
fmt::arg("netmask", netmask_),
|
fmt::arg("cidr", cidr_), fmt::arg("frequency", fmt::format("{:.1f}", frequency_)),
|
||||||
fmt::arg("ipaddr", ipaddr_),
|
|
||||||
fmt::arg("gwaddr", gwaddr_),
|
|
||||||
fmt::arg("cidr", cidr_),
|
|
||||||
fmt::arg("frequency", fmt::format("{:.1f}", frequency_)),
|
|
||||||
fmt::arg("icon", getIcon(signal_strength_, state_)),
|
fmt::arg("icon", getIcon(signal_strength_, state_)),
|
||||||
fmt::arg("bandwidthDownBits",
|
fmt::arg("bandwidthDownBits",
|
||||||
pow_format(bandwidth_down * 8ull / interval_.count(), "b/s")),
|
pow_format(bandwidth_down * 8ull / interval_.count(), "b/s")),
|
||||||
fmt::arg("bandwidthUpBits", pow_format(bandwidth_up * 8ull / interval_.count(), "b/s")),
|
fmt::arg("bandwidthUpBits", pow_format(bandwidth_up * 8ull / interval_.count(), "b/s")),
|
||||||
fmt::arg("bandwidthDownOctets", pow_format(bandwidth_down / interval_.count(), "o/s")),
|
fmt::arg("bandwidthDownOctets", pow_format(bandwidth_down / interval_.count(), "o/s")),
|
||||||
fmt::arg("bandwidthUpOctets", pow_format(bandwidth_up / interval_.count(), "o/s")));
|
fmt::arg("bandwidthUpOctets", pow_format(bandwidth_up / interval_.count(), "o/s")),
|
||||||
|
fmt::arg("bandwidthDownBytes", pow_format(bandwidth_down / interval_.count(), "B/s")),
|
||||||
|
fmt::arg("bandwidthUpBytes", pow_format(bandwidth_up / interval_.count(), "B/s")));
|
||||||
if (label_.get_tooltip_text() != tooltip_text) {
|
if (label_.get_tooltip_text() != tooltip_text) {
|
||||||
label_.set_tooltip_text(tooltip_text);
|
label_.set_tooltip_text(tooltip_text);
|
||||||
}
|
}
|
||||||
@ -432,8 +428,7 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
|
|
||||||
// Check if the interface goes "down" and if we want to detect the
|
// Check if the interface goes "down" and if we want to detect the
|
||||||
// external interface.
|
// external interface.
|
||||||
if (net->ifid_ != -1 && !(ifi->ifi_flags & IFF_UP)
|
if (net->ifid_ != -1 && !(ifi->ifi_flags & IFF_UP) && !net->config_["interface"].isString()) {
|
||||||
&& !net->config_["interface"].isString()) {
|
|
||||||
// The current interface is now down, all the routes associated with
|
// The current interface is now down, all the routes associated with
|
||||||
// it have been deleted, so start looking for a new default route.
|
// it have been deleted, so start looking for a new default route.
|
||||||
spdlog::debug("network: if{} down", net->ifid_);
|
spdlog::debug("network: if{} down", net->ifid_);
|
||||||
@ -533,15 +528,13 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
case IFA_ADDRESS: {
|
case IFA_ADDRESS: {
|
||||||
char ipaddr[INET6_ADDRSTRLEN];
|
char ipaddr[INET6_ADDRSTRLEN];
|
||||||
if (!is_del_event) {
|
if (!is_del_event) {
|
||||||
net->ipaddr_ = inet_ntop(ifa->ifa_family, RTA_DATA(ifa_rta),
|
net->ipaddr_ = inet_ntop(ifa->ifa_family, RTA_DATA(ifa_rta), ipaddr, sizeof(ipaddr));
|
||||||
ipaddr, sizeof (ipaddr));
|
|
||||||
net->cidr_ = ifa->ifa_prefixlen;
|
net->cidr_ = ifa->ifa_prefixlen;
|
||||||
switch (ifa->ifa_family) {
|
switch (ifa->ifa_family) {
|
||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
struct in_addr netmask;
|
struct in_addr netmask;
|
||||||
netmask.s_addr = htonl(~0 << (32 - ifa->ifa_prefixlen));
|
netmask.s_addr = htonl(~0 << (32 - ifa->ifa_prefixlen));
|
||||||
net->netmask_ = inet_ntop(ifa->ifa_family, &netmask,
|
net->netmask_ = inet_ntop(ifa->ifa_family, &netmask, ipaddr, sizeof(ipaddr));
|
||||||
ipaddr, sizeof (ipaddr));
|
|
||||||
}
|
}
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
struct in6_addr netmask;
|
struct in6_addr netmask;
|
||||||
@ -551,8 +544,7 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
if (v > 8) v = 8;
|
if (v > 8) v = 8;
|
||||||
netmask.s6_addr[i] = ~0 << v;
|
netmask.s6_addr[i] = ~0 << v;
|
||||||
}
|
}
|
||||||
net->netmask_ = inet_ntop(ifa->ifa_family, &netmask,
|
net->netmask_ = inet_ntop(ifa->ifa_family, &netmask, ipaddr, sizeof(ipaddr));
|
||||||
ipaddr, sizeof (ipaddr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spdlog::debug("network: {}, new addr {}/{}", net->ifname_, net->ipaddr_, net->cidr_);
|
spdlog::debug("network: {}, new addr {}/{}", net->ifname_, net->ipaddr_, net->cidr_);
|
||||||
@ -560,10 +552,8 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
net->ipaddr_.clear();
|
net->ipaddr_.clear();
|
||||||
net->cidr_ = 0;
|
net->cidr_ = 0;
|
||||||
net->netmask_.clear();
|
net->netmask_.clear();
|
||||||
spdlog::debug("network: {} addr deleted {}/{}",
|
spdlog::debug("network: {} addr deleted {}/{}", net->ifname_,
|
||||||
net->ifname_,
|
inet_ntop(ifa->ifa_family, RTA_DATA(ifa_rta), ipaddr, sizeof(ipaddr)),
|
||||||
inet_ntop(ifa->ifa_family, RTA_DATA(ifa_rta),
|
|
||||||
ipaddr, sizeof (ipaddr)),
|
|
||||||
ifa->ifa_prefixlen);
|
ifa->ifa_prefixlen);
|
||||||
}
|
}
|
||||||
net->dp.emit();
|
net->dp.emit();
|
||||||
@ -589,7 +579,6 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
int temp_idx = -1;
|
int temp_idx = -1;
|
||||||
uint32_t priority = 0;
|
uint32_t priority = 0;
|
||||||
|
|
||||||
|
|
||||||
/* Find the message(s) concerting the main routing table, each message
|
/* Find the message(s) concerting the main routing table, each message
|
||||||
* corresponds to a single routing table entry.
|
* corresponds to a single routing table entry.
|
||||||
*/
|
*/
|
||||||
@ -652,7 +641,8 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
net->ifid_ = temp_idx;
|
net->ifid_ = temp_idx;
|
||||||
net->route_priority = priority;
|
net->route_priority = priority;
|
||||||
net->gwaddr_ = temp_gw_addr;
|
net->gwaddr_ = temp_gw_addr;
|
||||||
spdlog::debug("network: new default route via {} on if{} metric {}", temp_gw_addr, temp_idx, priority);
|
spdlog::debug("network: new default route via {} on if{} metric {}", temp_gw_addr,
|
||||||
|
temp_idx, priority);
|
||||||
|
|
||||||
/* Ask ifname associated with temp_idx as well as carrier status */
|
/* Ask ifname associated with temp_idx as well as carrier status */
|
||||||
struct ifinfomsg ifinfo_hdr = {
|
struct ifinfomsg ifinfo_hdr = {
|
||||||
@ -660,8 +650,8 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
.ifi_index = temp_idx,
|
.ifi_index = temp_idx,
|
||||||
};
|
};
|
||||||
int err;
|
int err;
|
||||||
err = nl_send_simple(net->ev_sock_, RTM_GETLINK, NLM_F_REQUEST,
|
err = nl_send_simple(net->ev_sock_, RTM_GETLINK, NLM_F_REQUEST, &ifinfo_hdr,
|
||||||
&ifinfo_hdr, sizeof (ifinfo_hdr));
|
sizeof(ifinfo_hdr));
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
spdlog::error("network: failed to ask link info: {}", err);
|
spdlog::error("network: failed to ask link info: {}", err);
|
||||||
/* Ask for a dump of all links instead */
|
/* Ask for a dump of all links instead */
|
||||||
@ -674,10 +664,9 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
net->want_addr_dump_ = true;
|
net->want_addr_dump_ = true;
|
||||||
net->askForStateDump();
|
net->askForStateDump();
|
||||||
net->thread_timer_.wake_up();
|
net->thread_timer_.wake_up();
|
||||||
} else if (is_del_event && temp_idx == net->ifid_
|
} else if (is_del_event && temp_idx == net->ifid_ && net->route_priority == priority) {
|
||||||
&& net->route_priority == priority) {
|
spdlog::debug("network: default route deleted {}/if{} metric {}", net->ifname_, temp_idx,
|
||||||
spdlog::debug("network: default route deleted {}/if{} metric {}",
|
priority);
|
||||||
net->ifname_, temp_idx, priority);
|
|
||||||
|
|
||||||
net->clearIface();
|
net->clearIface();
|
||||||
net->dp.emit();
|
net->dp.emit();
|
||||||
@ -698,8 +687,7 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
|||||||
void waybar::modules::Network::askForStateDump(void) {
|
void waybar::modules::Network::askForStateDump(void) {
|
||||||
/* We need to wait until the current dump is done before sending new
|
/* We need to wait until the current dump is done before sending new
|
||||||
* messages. handleEventsDone() is called when a dump is done. */
|
* messages. handleEventsDone() is called when a dump is done. */
|
||||||
if (dump_in_progress_)
|
if (dump_in_progress_) return;
|
||||||
return;
|
|
||||||
|
|
||||||
struct rtgenmsg rt_hdr = {
|
struct rtgenmsg rt_hdr = {
|
||||||
.rtgen_family = AF_UNSPEC,
|
.rtgen_family = AF_UNSPEC,
|
||||||
@ -707,21 +695,18 @@ void waybar::modules::Network::askForStateDump(void) {
|
|||||||
|
|
||||||
if (want_route_dump_) {
|
if (want_route_dump_) {
|
||||||
rt_hdr.rtgen_family = family_;
|
rt_hdr.rtgen_family = family_;
|
||||||
nl_send_simple(ev_sock_, RTM_GETROUTE, NLM_F_DUMP,
|
nl_send_simple(ev_sock_, RTM_GETROUTE, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));
|
||||||
&rt_hdr, sizeof (rt_hdr));
|
|
||||||
want_route_dump_ = false;
|
want_route_dump_ = false;
|
||||||
dump_in_progress_ = true;
|
dump_in_progress_ = true;
|
||||||
|
|
||||||
} else if (want_link_dump_) {
|
} else if (want_link_dump_) {
|
||||||
nl_send_simple(ev_sock_, RTM_GETLINK, NLM_F_DUMP,
|
nl_send_simple(ev_sock_, RTM_GETLINK, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));
|
||||||
&rt_hdr, sizeof (rt_hdr));
|
|
||||||
want_link_dump_ = false;
|
want_link_dump_ = false;
|
||||||
dump_in_progress_ = true;
|
dump_in_progress_ = true;
|
||||||
|
|
||||||
} else if (want_addr_dump_) {
|
} else if (want_addr_dump_) {
|
||||||
rt_hdr.rtgen_family = family_;
|
rt_hdr.rtgen_family = family_;
|
||||||
nl_send_simple(ev_sock_, RTM_GETADDR, NLM_F_DUMP,
|
nl_send_simple(ev_sock_, RTM_GETADDR, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));
|
||||||
&rt_hdr, sizeof (rt_hdr));
|
|
||||||
want_addr_dump_ = false;
|
want_addr_dump_ = false;
|
||||||
dump_in_progress_ = true;
|
dump_in_progress_ = true;
|
||||||
}
|
}
|
||||||
@ -750,8 +735,8 @@ int waybar::modules::Network::handleScan(struct nl_msg *msg, void *data) {
|
|||||||
bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
|
bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
|
||||||
bss_policy[NL80211_BSS_STATUS].type = NLA_U32;
|
bss_policy[NL80211_BSS_STATUS].type = NLA_U32;
|
||||||
|
|
||||||
if (nla_parse(
|
if (nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0),
|
||||||
tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), nullptr) < 0) {
|
nullptr) < 0) {
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
if (tb[NL80211_ATTR_BSS] == nullptr) {
|
if (tb[NL80211_ATTR_BSS] == nullptr) {
|
||||||
@ -800,7 +785,9 @@ void waybar::modules::Network::parseSignal(struct nlattr **bss) {
|
|||||||
const int hardwareOptimum = -45;
|
const int hardwareOptimum = -45;
|
||||||
const int hardwareMin = -90;
|
const int hardwareMin = -90;
|
||||||
const int strength =
|
const int strength =
|
||||||
100 - ((abs(signal_strength_dbm_ - hardwareOptimum) / double{hardwareOptimum - hardwareMin}) * 100);
|
100 -
|
||||||
|
((abs(signal_strength_dbm_ - hardwareOptimum) / double{hardwareOptimum - hardwareMin}) *
|
||||||
|
100);
|
||||||
signal_strength_ = std::clamp(strength, 0, 100);
|
signal_strength_ = std::clamp(strength, 0, 100);
|
||||||
|
|
||||||
if (signal_strength_dbm_ >= -50) {
|
if (signal_strength_dbm_ >= -50) {
|
||||||
@ -849,9 +836,8 @@ auto waybar::modules::Network::getInfo() -> void {
|
|||||||
if (nl_msg == nullptr) {
|
if (nl_msg == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (genlmsg_put(
|
if (genlmsg_put(nl_msg, NL_AUTO_PORT, NL_AUTO_SEQ, nl80211_id_, 0, NLM_F_DUMP,
|
||||||
nl_msg, NL_AUTO_PORT, NL_AUTO_SEQ, nl80211_id_, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0) ==
|
NL80211_CMD_GET_SCAN, 0) == nullptr ||
|
||||||
nullptr ||
|
|
||||||
nla_put_u32(nl_msg, NL80211_ATTR_IFINDEX, ifid_) < 0) {
|
nla_put_u32(nl_msg, NL80211_ATTR_IFINDEX, ifid_) < 0) {
|
||||||
nlmsg_free(nl_msg);
|
nlmsg_free(nl_msg);
|
||||||
return;
|
return;
|
||||||
|
@ -50,15 +50,14 @@ void waybar::modules::Pulseaudio::contextStateCb(pa_context *c, void *data) {
|
|||||||
case PA_CONTEXT_READY:
|
case PA_CONTEXT_READY:
|
||||||
pa_context_get_server_info(c, serverInfoCb, data);
|
pa_context_get_server_info(c, serverInfoCb, data);
|
||||||
pa_context_set_subscribe_callback(c, subscribeCb, data);
|
pa_context_set_subscribe_callback(c, subscribeCb, data);
|
||||||
pa_context_subscribe(
|
pa_context_subscribe(c,
|
||||||
c,
|
static_cast<enum pa_subscription_mask>(
|
||||||
static_cast<enum pa_subscription_mask>(static_cast<int>(PA_SUBSCRIPTION_MASK_SERVER) |
|
static_cast<int>(PA_SUBSCRIPTION_MASK_SERVER) |
|
||||||
static_cast<int>(PA_SUBSCRIPTION_MASK_SINK) |
|
static_cast<int>(PA_SUBSCRIPTION_MASK_SINK) |
|
||||||
static_cast<int>(PA_SUBSCRIPTION_MASK_SINK_INPUT) |
|
static_cast<int>(PA_SUBSCRIPTION_MASK_SINK_INPUT) |
|
||||||
static_cast<int>(PA_SUBSCRIPTION_MASK_SOURCE) |
|
static_cast<int>(PA_SUBSCRIPTION_MASK_SOURCE) |
|
||||||
static_cast<int>(PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)),
|
static_cast<int>(PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)),
|
||||||
nullptr,
|
nullptr, nullptr);
|
||||||
nullptr);
|
|
||||||
break;
|
break;
|
||||||
case PA_CONTEXT_FAILED:
|
case PA_CONTEXT_FAILED:
|
||||||
pa->mainloop_api_->quit(pa->mainloop_api_, 1);
|
pa->mainloop_api_->quit(pa->mainloop_api_, 1);
|
||||||
@ -164,8 +163,7 @@ void waybar::modules::Pulseaudio::sourceInfoCb(pa_context * /*context*/, const p
|
|||||||
*/
|
*/
|
||||||
void waybar::modules::Pulseaudio::sinkInfoCb(pa_context * /*context*/, const pa_sink_info *i,
|
void waybar::modules::Pulseaudio::sinkInfoCb(pa_context * /*context*/, const pa_sink_info *i,
|
||||||
int /*eol*/, void *data) {
|
int /*eol*/, void *data) {
|
||||||
if (i == nullptr)
|
if (i == nullptr) return;
|
||||||
return;
|
|
||||||
|
|
||||||
auto pa = static_cast<waybar::modules::Pulseaudio *>(data);
|
auto pa = static_cast<waybar::modules::Pulseaudio *>(data);
|
||||||
if (pa->current_sink_name_ == i->name) {
|
if (pa->current_sink_name_ == i->name) {
|
||||||
@ -212,15 +210,7 @@ void waybar::modules::Pulseaudio::serverInfoCb(pa_context *context, const pa_ser
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const std::array<std::string, 9> ports = {
|
static const std::array<std::string, 9> ports = {
|
||||||
"headphone",
|
"headphone", "speaker", "hdmi", "headset", "hands-free", "portable", "car", "hifi", "phone",
|
||||||
"speaker",
|
|
||||||
"hdmi",
|
|
||||||
"headset",
|
|
||||||
"hands-free",
|
|
||||||
"portable",
|
|
||||||
"car",
|
|
||||||
"hifi",
|
|
||||||
"phone",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<std::string> waybar::modules::Pulseaudio::getPulseIcon() const {
|
const std::vector<std::string> waybar::modules::Pulseaudio::getPulseIcon() const {
|
||||||
@ -260,8 +250,7 @@ auto waybar::modules::Pulseaudio::update() -> void {
|
|||||||
label_.get_style_context()->remove_class("muted");
|
label_.get_style_context()->remove_class("muted");
|
||||||
label_.get_style_context()->remove_class("sink-muted");
|
label_.get_style_context()->remove_class("sink-muted");
|
||||||
}
|
}
|
||||||
format =
|
format = config_[format_name].isString() ? config_[format_name].asString() : format;
|
||||||
config_[format_name].isString() ? config_[format_name].asString() : format;
|
|
||||||
}
|
}
|
||||||
// TODO: find a better way to split source/sink
|
// TODO: find a better way to split source/sink
|
||||||
std::string format_source = "{volume}%";
|
std::string format_source = "{volume}%";
|
||||||
@ -277,13 +266,10 @@ auto waybar::modules::Pulseaudio::update() -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
format_source = fmt::format(format_source, fmt::arg("volume", source_volume_));
|
format_source = fmt::format(format_source, fmt::arg("volume", source_volume_));
|
||||||
label_.set_markup(fmt::format(format,
|
label_.set_markup(fmt::format(
|
||||||
fmt::arg("desc", desc_),
|
format, fmt::arg("desc", desc_), fmt::arg("volume", volume_),
|
||||||
fmt::arg("volume", volume_),
|
fmt::arg("format_source", format_source), fmt::arg("source_volume", source_volume_),
|
||||||
fmt::arg("format_source", format_source),
|
fmt::arg("source_desc", source_desc_), fmt::arg("icon", getIcon(volume_, getPulseIcon()))));
|
||||||
fmt::arg("source_volume", source_volume_),
|
|
||||||
fmt::arg("source_desc", source_desc_),
|
|
||||||
fmt::arg("icon", getIcon(volume_, getPulseIcon()))));
|
|
||||||
getState(volume_);
|
getState(volume_);
|
||||||
|
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
@ -292,11 +278,8 @@ auto waybar::modules::Pulseaudio::update() -> void {
|
|||||||
}
|
}
|
||||||
if (!tooltip_format.empty()) {
|
if (!tooltip_format.empty()) {
|
||||||
label_.set_tooltip_text(fmt::format(
|
label_.set_tooltip_text(fmt::format(
|
||||||
tooltip_format,
|
tooltip_format, fmt::arg("desc", desc_), fmt::arg("volume", volume_),
|
||||||
fmt::arg("desc", desc_),
|
fmt::arg("format_source", format_source), fmt::arg("source_volume", source_volume_),
|
||||||
fmt::arg("volume", volume_),
|
|
||||||
fmt::arg("format_source", format_source),
|
|
||||||
fmt::arg("source_volume", source_volume_),
|
|
||||||
fmt::arg("source_desc", source_desc_),
|
fmt::arg("source_desc", source_desc_),
|
||||||
fmt::arg("icon", getIcon(volume_, getPulseIcon()))));
|
fmt::arg("icon", getIcon(volume_, getPulseIcon()))));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include "modules/river/tags.hpp"
|
||||||
|
|
||||||
#include <gtkmm/button.h>
|
#include <gtkmm/button.h>
|
||||||
#include <gtkmm/label.h>
|
#include <gtkmm/label.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
@ -6,7 +8,6 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
#include "modules/river/tags.hpp"
|
|
||||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
namespace waybar::modules::river {
|
namespace waybar::modules::river {
|
||||||
@ -77,7 +78,6 @@ static void handle_global_remove(void *data, struct wl_registry *registry, uint3
|
|||||||
/* Ignore event */
|
/* Ignore event */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
|
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
|
||||||
.global_remove = handle_global_remove};
|
.global_remove = handle_global_remove};
|
||||||
|
|
||||||
@ -134,8 +134,10 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
|
|||||||
button.set_relief(Gtk::RELIEF_NONE);
|
button.set_relief(Gtk::RELIEF_NONE);
|
||||||
box_.pack_start(button, false, false, 0);
|
box_.pack_start(button, false, false, 0);
|
||||||
if (!config_["disable-click"].asBool()) {
|
if (!config_["disable-click"].asBool()) {
|
||||||
button.signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &Tags::handle_primary_clicked), i));
|
button.signal_clicked().connect(
|
||||||
button.signal_button_press_event().connect(sigc::bind(sigc::mem_fun(*this, &Tags::handle_button_press), i));
|
sigc::bind(sigc::mem_fun(*this, &Tags::handle_primary_clicked), i));
|
||||||
|
button.signal_button_press_event().connect(
|
||||||
|
sigc::bind(sigc::mem_fun(*this, &Tags::handle_button_press), i));
|
||||||
}
|
}
|
||||||
button.show();
|
button.show();
|
||||||
i <<= 1;
|
i <<= 1;
|
||||||
|
124
src/modules/river/window.cpp
Normal file
124
src/modules/river/window.cpp
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#include "modules/river/window.hpp"
|
||||||
|
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "client.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::river {
|
||||||
|
|
||||||
|
static void listen_focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1,
|
||||||
|
const char *title) {
|
||||||
|
static_cast<Window *>(data)->handle_focused_view(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void listen_focused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1,
|
||||||
|
struct wl_output *output) {
|
||||||
|
static_cast<Window *>(data)->handle_focused_output(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void listen_unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1,
|
||||||
|
struct wl_output *output) {
|
||||||
|
static_cast<Window *>(data)->handle_unfocused_output(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const zriver_seat_status_v1_listener seat_status_listener_impl{
|
||||||
|
.focused_output = listen_focused_output,
|
||||||
|
.unfocused_output = listen_unfocused_output,
|
||||||
|
.focused_view = listen_focused_view,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
|
const char *interface, uint32_t version) {
|
||||||
|
if (std::strcmp(interface, zriver_status_manager_v1_interface.name) == 0) {
|
||||||
|
version = std::min<uint32_t>(version, 2);
|
||||||
|
static_cast<Window *>(data)->status_manager_ = static_cast<struct zriver_status_manager_v1 *>(
|
||||||
|
wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, version));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::strcmp(interface, wl_seat_interface.name) == 0) {
|
||||||
|
version = std::min<uint32_t>(version, 1);
|
||||||
|
static_cast<Window *>(data)->seat_ = static_cast<struct wl_seat *>(
|
||||||
|
wl_registry_bind(registry, name, &wl_seat_interface, version));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
|
||||||
|
/* Ignore event */
|
||||||
|
}
|
||||||
|
|
||||||
|
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
|
||||||
|
.global_remove = handle_global_remove};
|
||||||
|
|
||||||
|
Window::Window(const std::string &id, const waybar::Bar &bar, const Json::Value &config)
|
||||||
|
: waybar::ALabel(config, "window", id, "{}", 30),
|
||||||
|
status_manager_{nullptr},
|
||||||
|
seat_{nullptr},
|
||||||
|
bar_(bar),
|
||||||
|
seat_status_{nullptr} {
|
||||||
|
struct wl_display *display = Client::inst()->wl_display;
|
||||||
|
struct wl_registry *registry = wl_display_get_registry(display);
|
||||||
|
wl_registry_add_listener(registry, ®istry_listener_impl, this);
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
output_ = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
||||||
|
|
||||||
|
if (!status_manager_) {
|
||||||
|
spdlog::error("river_status_manager_v1 not advertised");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!seat_) {
|
||||||
|
spdlog::error("wl_seat not advertised");
|
||||||
|
}
|
||||||
|
|
||||||
|
label_.hide(); // hide the label until populated
|
||||||
|
ALabel::update();
|
||||||
|
|
||||||
|
seat_status_ = zriver_status_manager_v1_get_river_seat_status(status_manager_, seat_);
|
||||||
|
zriver_seat_status_v1_add_listener(seat_status_, &seat_status_listener_impl, this);
|
||||||
|
|
||||||
|
zriver_status_manager_v1_destroy(status_manager_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::~Window() {
|
||||||
|
if (seat_status_) {
|
||||||
|
zriver_seat_status_v1_destroy(seat_status_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::handle_focused_view(const char *title) {
|
||||||
|
// don't change the label on unfocused outputs.
|
||||||
|
// this makes the current output report its currently focused view, and unfocused outputs will
|
||||||
|
// report their last focused views. when freshly starting the bar, unfocused outputs don't have a
|
||||||
|
// last focused view, and will get blank labels until they are brought into focus at least once.
|
||||||
|
if (focused_output_ != output_) return;
|
||||||
|
|
||||||
|
if (std::strcmp(title, "") == 0 || format_.empty()) {
|
||||||
|
label_.hide(); // hide empty labels or labels with empty format
|
||||||
|
} else {
|
||||||
|
label_.show();
|
||||||
|
label_.set_markup(fmt::format(format_, title));
|
||||||
|
}
|
||||||
|
|
||||||
|
ALabel::update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::handle_focused_output(struct wl_output *output) {
|
||||||
|
if (output_ == output) { // if we focused the output this bar belongs to
|
||||||
|
label_.get_style_context()->add_class("focused");
|
||||||
|
ALabel::update();
|
||||||
|
}
|
||||||
|
focused_output_ = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::handle_unfocused_output(struct wl_output *output) {
|
||||||
|
if (output_ == output) { // if we unfocused the output this bar belongs to
|
||||||
|
label_.get_style_context()->remove_class("focused");
|
||||||
|
ALabel::update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace waybar::modules::river */
|
@ -1,4 +1,5 @@
|
|||||||
#include "modules/simpleclock.hpp"
|
#include "modules/simpleclock.hpp"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
||||||
@ -6,9 +7,10 @@ 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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#include "modules/sndio.hpp"
|
#include "modules/sndio.hpp"
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <poll.h>
|
|
||||||
#include <fmt/format.h>
|
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
|
|
||||||
namespace waybar::modules {
|
namespace waybar::modules {
|
||||||
|
|
||||||
@ -52,10 +54,8 @@ Sndio::Sndio(const std::string &id, const Json::Value &config)
|
|||||||
event_box_.show();
|
event_box_.show();
|
||||||
|
|
||||||
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK | Gdk::BUTTON_PRESS_MASK);
|
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK | Gdk::BUTTON_PRESS_MASK);
|
||||||
event_box_.signal_scroll_event().connect(
|
event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &Sndio::handleScroll));
|
||||||
sigc::mem_fun(*this, &Sndio::handleScroll));
|
event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &Sndio::handleToggle));
|
||||||
event_box_.signal_button_press_event().connect(
|
|
||||||
sigc::mem_fun(*this, &Sndio::handleToggle));
|
|
||||||
|
|
||||||
thread_ = [this] {
|
thread_ = [this] {
|
||||||
dp.emit();
|
dp.emit();
|
||||||
@ -98,9 +98,7 @@ Sndio::Sndio(const std::string &id, const Json::Value &config)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Sndio::~Sndio() {
|
Sndio::~Sndio() { sioctl_close(hdl_); }
|
||||||
sioctl_close(hdl_);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Sndio::update() -> void {
|
auto Sndio::update() -> void {
|
||||||
auto format = format_;
|
auto format = format_;
|
||||||
@ -112,9 +110,7 @@ auto Sndio::update() -> void {
|
|||||||
label_.get_style_context()->remove_class("muted");
|
label_.get_style_context()->remove_class("muted");
|
||||||
}
|
}
|
||||||
|
|
||||||
label_.set_markup(fmt::format(format,
|
label_.set_markup(fmt::format(format, fmt::arg("volume", vol), fmt::arg("raw_value", volume_)));
|
||||||
fmt::arg("volume", vol),
|
|
||||||
fmt::arg("raw_value", volume_)));
|
|
||||||
|
|
||||||
ALabel::update();
|
ALabel::update();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "modules/sni/host.hpp"
|
#include "modules/sni/host.hpp"
|
||||||
|
|
||||||
#include <fmt/ostream.h>
|
#include <fmt/ostream.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
@ -32,8 +33,7 @@ Host::~Host() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Host::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name) {
|
void Host::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name) {
|
||||||
watcher_id_ = Gio::DBus::watch_name(conn,
|
watcher_id_ = Gio::DBus::watch_name(conn, "org.kde.StatusNotifierWatcher",
|
||||||
"org.kde.StatusNotifierWatcher",
|
|
||||||
sigc::mem_fun(*this, &Host::nameAppeared),
|
sigc::mem_fun(*this, &Host::nameAppeared),
|
||||||
sigc::mem_fun(*this, &Host::nameVanished));
|
sigc::mem_fun(*this, &Host::nameVanished));
|
||||||
}
|
}
|
||||||
@ -45,13 +45,8 @@ void Host::nameAppeared(const Glib::RefPtr<Gio::DBus::Connection>& conn, const G
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cancellable_ = g_cancellable_new();
|
cancellable_ = g_cancellable_new();
|
||||||
sn_watcher_proxy_new(conn->gobj(),
|
sn_watcher_proxy_new(conn->gobj(), G_DBUS_PROXY_FLAGS_NONE, "org.kde.StatusNotifierWatcher",
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
"/StatusNotifierWatcher", cancellable_, &Host::proxyReady, this);
|
||||||
"org.kde.StatusNotifierWatcher",
|
|
||||||
"/StatusNotifierWatcher",
|
|
||||||
cancellable_,
|
|
||||||
&Host::proxyReady,
|
|
||||||
this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::nameVanished(const Glib::RefPtr<Gio::DBus::Connection>& conn, const Glib::ustring name) {
|
void Host::nameVanished(const Glib::RefPtr<Gio::DBus::Connection>& conn, const Glib::ustring name) {
|
||||||
@ -76,8 +71,8 @@ void Host::proxyReady(GObject* src, GAsyncResult* res, gpointer data) {
|
|||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sn_watcher_call_register_host(
|
sn_watcher_call_register_host(host->watcher_, host->object_path_.c_str(), host->cancellable_,
|
||||||
host->watcher_, host->object_path_.c_str(), host->cancellable_, &Host::registerHost, data);
|
&Host::registerHost, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::registerHost(GObject* src, GAsyncResult* res, gpointer data) {
|
void Host::registerHost(GObject* src, GAsyncResult* res, gpointer data) {
|
||||||
|
@ -62,18 +62,12 @@ Item::Item(const std::string& bn, const std::string& op, const Json::Value& conf
|
|||||||
cancellable_ = Gio::Cancellable::create();
|
cancellable_ = Gio::Cancellable::create();
|
||||||
|
|
||||||
auto interface = Glib::wrap(sn_item_interface_info(), true);
|
auto interface = Glib::wrap(sn_item_interface_info(), true);
|
||||||
Gio::DBus::Proxy::create_for_bus(Gio::DBus::BusType::BUS_TYPE_SESSION,
|
Gio::DBus::Proxy::create_for_bus(Gio::DBus::BusType::BUS_TYPE_SESSION, bus_name, object_path,
|
||||||
bus_name,
|
SNI_INTERFACE_NAME, sigc::mem_fun(*this, &Item::proxyReady),
|
||||||
object_path,
|
cancellable_, interface);
|
||||||
SNI_INTERFACE_NAME,
|
|
||||||
sigc::mem_fun(*this, &Item::proxyReady),
|
|
||||||
cancellable_,
|
|
||||||
interface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::onConfigure(GdkEventConfigure* ev) {
|
void Item::onConfigure(GdkEventConfigure* ev) { this->updateImage(); }
|
||||||
this->updateImage();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Item::proxyReady(Glib::RefPtr<Gio::AsyncResult>& result) {
|
void Item::proxyReady(Glib::RefPtr<Gio::AsyncResult>& result) {
|
||||||
try {
|
try {
|
||||||
@ -167,16 +161,10 @@ void Item::setProperty(const Glib::ustring& name, Glib::VariantBase& value) {
|
|||||||
}
|
}
|
||||||
} catch (const Glib::Error& err) {
|
} catch (const Glib::Error& err) {
|
||||||
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
||||||
id.empty() ? bus_name : id,
|
id.empty() ? bus_name : id, name, value, err.what());
|
||||||
name,
|
|
||||||
value,
|
|
||||||
err.what());
|
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
||||||
id.empty() ? bus_name : id,
|
id.empty() ? bus_name : id, name, value, err.what());
|
||||||
name,
|
|
||||||
value,
|
|
||||||
err.what());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,8 +187,7 @@ void Item::getUpdatedProperties() {
|
|||||||
auto params = Glib::VariantContainerBase::create_tuple(
|
auto params = Glib::VariantContainerBase::create_tuple(
|
||||||
{Glib::Variant<Glib::ustring>::create(SNI_INTERFACE_NAME)});
|
{Glib::Variant<Glib::ustring>::create(SNI_INTERFACE_NAME)});
|
||||||
proxy_->call("org.freedesktop.DBus.Properties.GetAll",
|
proxy_->call("org.freedesktop.DBus.Properties.GetAll",
|
||||||
sigc::mem_fun(*this, &Item::processUpdatedProperties),
|
sigc::mem_fun(*this, &Item::processUpdatedProperties), params);
|
||||||
params);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Item::processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& _result) {
|
void Item::processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& _result) {
|
||||||
@ -303,14 +290,8 @@ Glib::RefPtr<Gdk::Pixbuf> Item::extractPixBuf(GVariant* variant) {
|
|||||||
array[i + 2] = array[i + 3];
|
array[i + 2] = array[i + 3];
|
||||||
array[i + 3] = alpha;
|
array[i + 3] = alpha;
|
||||||
}
|
}
|
||||||
return Gdk::Pixbuf::create_from_data(array,
|
return Gdk::Pixbuf::create_from_data(array, Gdk::Colorspace::COLORSPACE_RGB, true, 8, lwidth,
|
||||||
Gdk::Colorspace::COLORSPACE_RGB,
|
lheight, 4 * lwidth, &pixbuf_data_deleter);
|
||||||
true,
|
|
||||||
8,
|
|
||||||
lwidth,
|
|
||||||
lheight,
|
|
||||||
4 * lwidth,
|
|
||||||
&pixbuf_data_deleter);
|
|
||||||
}
|
}
|
||||||
return Glib::RefPtr<Gdk::Pixbuf>{};
|
return Glib::RefPtr<Gdk::Pixbuf>{};
|
||||||
}
|
}
|
||||||
@ -374,15 +355,15 @@ Glib::RefPtr<Gdk::Pixbuf> Item::getIconByName(const std::string& name, int reque
|
|||||||
tmp_size = request_size;
|
tmp_size = request_size;
|
||||||
}
|
}
|
||||||
if (!icon_theme_path.empty() &&
|
if (!icon_theme_path.empty() &&
|
||||||
icon_theme->lookup_icon(
|
icon_theme->lookup_icon(name.c_str(), tmp_size,
|
||||||
name.c_str(), tmp_size, Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE)) {
|
Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE)) {
|
||||||
return icon_theme->load_icon(
|
return icon_theme->load_icon(name.c_str(), tmp_size,
|
||||||
name.c_str(), tmp_size, Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
|
Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
|
||||||
}
|
}
|
||||||
Glib::RefPtr<Gtk::IconTheme> default_theme = Gtk::IconTheme::get_default();
|
Glib::RefPtr<Gtk::IconTheme> default_theme = Gtk::IconTheme::get_default();
|
||||||
default_theme->rescan_if_needed();
|
default_theme->rescan_if_needed();
|
||||||
return default_theme->load_icon(
|
return default_theme->load_icon(name.c_str(), tmp_size,
|
||||||
name.c_str(), tmp_size, Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
|
Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Item::getScaledIconSize() {
|
double Item::getScaledIconSize() {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "modules/sni/tray.hpp"
|
#include "modules/sni/tray.hpp"
|
||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
namespace waybar::modules::SNI {
|
namespace waybar::modules::SNI {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "modules/sni/watcher.hpp"
|
#include "modules/sni/watcher.hpp"
|
||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
using namespace waybar::modules::SNI;
|
using namespace waybar::modules::SNI;
|
||||||
@ -29,8 +30,8 @@ Watcher::~Watcher() {
|
|||||||
|
|
||||||
void Watcher::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name) {
|
void Watcher::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name) {
|
||||||
GError* error = nullptr;
|
GError* error = nullptr;
|
||||||
g_dbus_interface_skeleton_export(
|
g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(watcher_), conn->gobj(),
|
||||||
G_DBUS_INTERFACE_SKELETON(watcher_), conn->gobj(), "/StatusNotifierWatcher", &error);
|
"/StatusNotifierWatcher", &error);
|
||||||
if (error != nullptr) {
|
if (error != nullptr) {
|
||||||
// Don't print an error when a watcher is already present
|
// Don't print an error when a watcher is already present
|
||||||
if (error->code != 2) {
|
if (error->code != 2) {
|
||||||
@ -39,10 +40,10 @@ void Watcher::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib:
|
|||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_signal_connect_swapped(
|
g_signal_connect_swapped(watcher_, "handle-register-item",
|
||||||
watcher_, "handle-register-item", G_CALLBACK(&Watcher::handleRegisterItem), this);
|
G_CALLBACK(&Watcher::handleRegisterItem), this);
|
||||||
g_signal_connect_swapped(
|
g_signal_connect_swapped(watcher_, "handle-register-host",
|
||||||
watcher_, "handle-register-host", G_CALLBACK(&Watcher::handleRegisterHost), this);
|
G_CALLBACK(&Watcher::handleRegisterHost), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean Watcher::handleRegisterHost(Watcher* obj, GDBusMethodInvocation* invocation,
|
gboolean Watcher::handleRegisterHost(Watcher* obj, GDBusMethodInvocation* invocation,
|
||||||
@ -55,22 +56,16 @@ gboolean Watcher::handleRegisterHost(Watcher* obj, GDBusMethodInvocation* invoca
|
|||||||
object_path = service;
|
object_path = service;
|
||||||
}
|
}
|
||||||
if (g_dbus_is_name(bus_name) == FALSE) {
|
if (g_dbus_is_name(bus_name) == FALSE) {
|
||||||
g_dbus_method_invocation_return_error(invocation,
|
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
||||||
G_DBUS_ERROR,
|
"D-Bus bus name '%s' is not valid", bus_name);
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
|
||||||
"D-Bus bus name '%s' is not valid",
|
|
||||||
bus_name);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
auto watch = gfWatchFind(obj->hosts_, bus_name, object_path);
|
auto watch = gfWatchFind(obj->hosts_, bus_name, object_path);
|
||||||
if (watch != nullptr) {
|
if (watch != nullptr) {
|
||||||
g_dbus_method_invocation_return_error(
|
g_dbus_method_invocation_return_error(
|
||||||
invocation,
|
invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
||||||
G_DBUS_ERROR,
|
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
|
||||||
"Status Notifier Host with bus name '%s' and object path '%s' is already registered",
|
"Status Notifier Host with bus name '%s' and object path '%s' is already registered",
|
||||||
bus_name,
|
bus_name, object_path);
|
||||||
object_path);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
watch = gfWatchNew(GF_WATCH_TYPE_HOST, service, bus_name, object_path, obj);
|
watch = gfWatchNew(GF_WATCH_TYPE_HOST, service, bus_name, object_path, obj);
|
||||||
@ -93,18 +88,14 @@ gboolean Watcher::handleRegisterItem(Watcher* obj, GDBusMethodInvocation* invoca
|
|||||||
object_path = service;
|
object_path = service;
|
||||||
}
|
}
|
||||||
if (g_dbus_is_name(bus_name) == FALSE) {
|
if (g_dbus_is_name(bus_name) == FALSE) {
|
||||||
g_dbus_method_invocation_return_error(invocation,
|
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
||||||
G_DBUS_ERROR,
|
"D-Bus bus name '%s' is not valid", bus_name);
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
|
||||||
"D-Bus bus name '%s' is not valid",
|
|
||||||
bus_name);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
auto watch = gfWatchFind(obj->items_, bus_name, object_path);
|
auto watch = gfWatchFind(obj->items_, bus_name, object_path);
|
||||||
if (watch != nullptr) {
|
if (watch != nullptr) {
|
||||||
g_warning("Status Notifier Item with bus name '%s' and object path '%s' is already registered",
|
g_warning("Status Notifier Item with bus name '%s' and object path '%s' is already registered",
|
||||||
bus_name,
|
bus_name, object_path);
|
||||||
object_path);
|
|
||||||
sn_watcher_complete_register_item(obj->watcher_, invocation);
|
sn_watcher_complete_register_item(obj->watcher_, invocation);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -152,13 +143,8 @@ Watcher::GfWatch* Watcher::gfWatchNew(GfWatchType type, const gchar* service, co
|
|||||||
watch->service = g_strdup(service);
|
watch->service = g_strdup(service);
|
||||||
watch->bus_name = g_strdup(bus_name);
|
watch->bus_name = g_strdup(bus_name);
|
||||||
watch->object_path = g_strdup(object_path);
|
watch->object_path = g_strdup(object_path);
|
||||||
watch->watch_id = g_bus_watch_name(G_BUS_TYPE_SESSION,
|
watch->watch_id = g_bus_watch_name(G_BUS_TYPE_SESSION, bus_name, G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||||
bus_name,
|
nullptr, &Watcher::nameVanished, watch, nullptr);
|
||||||
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
||||||
nullptr,
|
|
||||||
&Watcher::nameVanished,
|
|
||||||
watch,
|
|
||||||
nullptr);
|
|
||||||
return watch;
|
return watch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <fmt/ostream.h>
|
#include <fmt/ostream.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
@ -19,11 +20,37 @@ BarIpcClient::BarIpcClient(waybar::Bar& bar) : bar_{bar} {
|
|||||||
handle.disconnect();
|
handle.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json::Value subscribe_events{Json::arrayValue};
|
||||||
|
subscribe_events.append("bar_state_update");
|
||||||
|
subscribe_events.append("barconfig_update");
|
||||||
|
|
||||||
|
bool has_mode = isModuleEnabled("sway/mode");
|
||||||
|
bool has_workspaces = isModuleEnabled("sway/workspaces");
|
||||||
|
|
||||||
|
if (has_mode) {
|
||||||
|
subscribe_events.append("mode");
|
||||||
|
}
|
||||||
|
if (has_workspaces) {
|
||||||
|
subscribe_events.append("workspace");
|
||||||
|
}
|
||||||
|
if (has_mode || has_workspaces) {
|
||||||
|
subscribe_events.append("binding");
|
||||||
|
}
|
||||||
|
|
||||||
|
modifier_reset_ = bar.config.get("modifier-reset", "press").asString();
|
||||||
|
|
||||||
signal_config_.connect(sigc::mem_fun(*this, &BarIpcClient::onConfigUpdate));
|
signal_config_.connect(sigc::mem_fun(*this, &BarIpcClient::onConfigUpdate));
|
||||||
signal_visible_.connect(sigc::mem_fun(*this, &BarIpcClient::onVisibilityUpdate));
|
signal_visible_.connect(sigc::mem_fun(*this, &BarIpcClient::onVisibilityUpdate));
|
||||||
|
signal_urgency_.connect(sigc::mem_fun(*this, &BarIpcClient::onUrgencyUpdate));
|
||||||
|
signal_mode_.connect(sigc::mem_fun(*this, &BarIpcClient::onModeUpdate));
|
||||||
|
|
||||||
ipc_.subscribe(R"(["bar_state_update", "barconfig_update"])");
|
// Subscribe to non bar events to determine if the modifier key press is followed by another
|
||||||
|
// action.
|
||||||
|
std::ostringstream oss_events;
|
||||||
|
oss_events << subscribe_events;
|
||||||
|
ipc_.subscribe(oss_events.str());
|
||||||
ipc_.signal_event.connect(sigc::mem_fun(*this, &BarIpcClient::onIpcEvent));
|
ipc_.signal_event.connect(sigc::mem_fun(*this, &BarIpcClient::onIpcEvent));
|
||||||
|
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &BarIpcClient::onCmd));
|
||||||
// Launch worker
|
// Launch worker
|
||||||
ipc_.setWorker([this] {
|
ipc_.setWorker([this] {
|
||||||
try {
|
try {
|
||||||
@ -34,6 +61,19 @@ BarIpcClient::BarIpcClient(waybar::Bar& bar) : bar_{bar} {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BarIpcClient::isModuleEnabled(std::string name) {
|
||||||
|
for (const auto& section : {"modules-left", "modules-center", "modules-right"}) {
|
||||||
|
if (const auto& modules = bar_.config.get(section, {}); modules.isArray()) {
|
||||||
|
for (const auto& module : modules) {
|
||||||
|
if (module.asString().rfind(name, 0) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct swaybar_config parseConfig(const Json::Value& payload) {
|
struct swaybar_config parseConfig(const Json::Value& payload) {
|
||||||
swaybar_config conf;
|
swaybar_config conf;
|
||||||
if (auto id = payload["id"]; id.isString()) {
|
if (auto id = payload["id"]; id.isString()) {
|
||||||
@ -61,6 +101,36 @@ void BarIpcClient::onInitialConfig(const struct Ipc::ipc_response& res) {
|
|||||||
void BarIpcClient::onIpcEvent(const struct Ipc::ipc_response& res) {
|
void BarIpcClient::onIpcEvent(const struct Ipc::ipc_response& res) {
|
||||||
try {
|
try {
|
||||||
auto payload = parser_.parse(res.payload);
|
auto payload = parser_.parse(res.payload);
|
||||||
|
switch (res.type) {
|
||||||
|
case IPC_EVENT_WORKSPACE:
|
||||||
|
if (payload.isMember("change")) {
|
||||||
|
// only check and send signal if the workspace update reason was because of a urgent
|
||||||
|
// change
|
||||||
|
if (payload["change"] == "urgent") {
|
||||||
|
auto urgent = payload["current"]["urgent"];
|
||||||
|
if (urgent.asBool()) {
|
||||||
|
// Event for a new urgency, update the visibly
|
||||||
|
signal_urgency_(true);
|
||||||
|
} else if (!urgent.asBool() && visible_by_urgency_) {
|
||||||
|
// Event clearing an urgency, bar is visible, check if another workspace still has
|
||||||
|
// the urgency hint set
|
||||||
|
ipc_.sendCmd(IPC_GET_WORKSPACES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modifier_no_action_ = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPC_EVENT_MODE:
|
||||||
|
if (payload.isMember("change")) {
|
||||||
|
signal_mode_(payload["change"] != "default");
|
||||||
|
modifier_no_action_ = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPC_EVENT_BINDING:
|
||||||
|
modifier_no_action_ = false;
|
||||||
|
break;
|
||||||
|
case IPC_EVENT_BAR_STATE_UPDATE:
|
||||||
|
case IPC_EVENT_BARCONFIG_UPDATE:
|
||||||
if (auto id = payload["id"]; id.isString() && id.asString() != bar_.bar_id) {
|
if (auto id = payload["id"]; id.isString() && id.asString() != bar_.bar_id) {
|
||||||
spdlog::trace("swaybar ipc: ignore event for {}", id.asString());
|
spdlog::trace("swaybar ipc: ignore event for {}", id.asString());
|
||||||
return;
|
return;
|
||||||
@ -73,29 +143,74 @@ void BarIpcClient::onIpcEvent(const struct Ipc::ipc_response& res) {
|
|||||||
auto config = parseConfig(payload);
|
auto config = parseConfig(payload);
|
||||||
signal_config_(std::move(config));
|
signal_config_(std::move(config));
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
spdlog::error("BarIpcClient::onEvent {}", e.what());
|
spdlog::error("BarIpcClient::onEvent {}", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BarIpcClient::onCmd(const struct Ipc::ipc_response& res) {
|
||||||
|
if (res.type == IPC_GET_WORKSPACES) {
|
||||||
|
try {
|
||||||
|
auto payload = parser_.parse(res.payload);
|
||||||
|
for (auto& ws : payload) {
|
||||||
|
if (ws["urgent"].asBool()) {
|
||||||
|
spdlog::debug("Found workspace {} with urgency set. Stopping search.", ws["name"]);
|
||||||
|
// Found one workspace with urgency set, signal bar visibility
|
||||||
|
signal_urgency_(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Command to get workspaces was sent after a change in workspaces was based on "urgent",
|
||||||
|
// if no workspace has this flag set to true, all flags must be cleared.
|
||||||
|
signal_urgency_(false);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
spdlog::error("Bar: {}", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BarIpcClient::onConfigUpdate(const swaybar_config& config) {
|
void BarIpcClient::onConfigUpdate(const swaybar_config& config) {
|
||||||
spdlog::info("config update for {}: id {}, mode {}, hidden_state {}",
|
spdlog::info("config update for {}: id {}, mode {}, hidden_state {}", bar_.bar_id, config.id,
|
||||||
bar_.bar_id,
|
config.mode, config.hidden_state);
|
||||||
config.id,
|
|
||||||
config.mode,
|
|
||||||
config.hidden_state);
|
|
||||||
bar_config_ = config;
|
bar_config_ = config;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BarIpcClient::onModeUpdate(bool visible_by_mode) {
|
||||||
|
spdlog::debug("mode update for {}: {}", bar_.bar_id, visible_by_mode);
|
||||||
|
visible_by_mode_ = visible_by_mode;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void BarIpcClient::onVisibilityUpdate(bool visible_by_modifier) {
|
void BarIpcClient::onVisibilityUpdate(bool visible_by_modifier) {
|
||||||
spdlog::debug("visiblity update for {}: {}", bar_.bar_id, visible_by_modifier);
|
spdlog::debug("visibility update for {}: {}", bar_.bar_id, visible_by_modifier);
|
||||||
visible_by_modifier_ = visible_by_modifier;
|
visible_by_modifier_ = visible_by_modifier;
|
||||||
|
if (visible_by_modifier) {
|
||||||
|
modifier_no_action_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear on either press or release depending on bar_.bar_config_.action value.
|
||||||
|
// For the check on release, make sure that the modifier key was not used for another action.
|
||||||
|
if (((modifier_reset_ == "press" && visible_by_modifier_) ||
|
||||||
|
(modifier_reset_ == "release" && !visible_by_modifier_ && modifier_no_action_))) {
|
||||||
|
// Clear the flags to hide the bar.
|
||||||
|
visible_by_urgency_ = false;
|
||||||
|
visible_by_mode_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BarIpcClient::onUrgencyUpdate(bool visible_by_urgency) {
|
||||||
|
spdlog::debug("urgency update for {}: {}", bar_.bar_id, visible_by_urgency);
|
||||||
|
visible_by_urgency_ = visible_by_urgency;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BarIpcClient::update() {
|
void BarIpcClient::update() {
|
||||||
bool visible = visible_by_modifier_;
|
bool visible = visible_by_modifier_ || visible_by_mode_ || visible_by_urgency_;
|
||||||
if (bar_config_.mode == "invisible") {
|
if (bar_config_.mode == "invisible") {
|
||||||
visible = false;
|
visible = false;
|
||||||
} else if (bar_config_.mode != "hide" || bar_config_.hidden_state != "hide") {
|
} else if (bar_config_.mode != "hide" || bar_config_.hidden_state != "hide") {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "modules/sway/ipc/client.hpp"
|
#include "modules/sway/ipc/client.hpp"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
namespace waybar::modules::sway {
|
namespace waybar::modules::sway {
|
||||||
|
@ -45,7 +45,7 @@ Language::Language(const std::string& id, const Json::Value& config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Language::onCmd(const struct Ipc::ipc_response& res) {
|
void Language::onCmd(const struct Ipc::ipc_response& res) {
|
||||||
if (res.type != static_cast<uint32_t>(IPC_GET_INPUTS)) {
|
if (res.type != IPC_GET_INPUTS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ void Language::onCmd(const struct Ipc::ipc_response& res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Language::onEvent(const struct Ipc::ipc_response& res) {
|
void Language::onEvent(const struct Ipc::ipc_response& res) {
|
||||||
if (res.type != static_cast<uint32_t>(IPC_EVENT_INPUT)) {
|
if (res.type != IPC_EVENT_INPUT) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,20 +95,17 @@ void Language::onEvent(const struct Ipc::ipc_response& res) {
|
|||||||
|
|
||||||
auto Language::update() -> void {
|
auto Language::update() -> void {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
auto display_layout = trim(fmt::format(format_,
|
auto display_layout = trim(fmt::format(
|
||||||
fmt::arg("short", layout_.short_name),
|
format_, fmt::arg("short", layout_.short_name),
|
||||||
fmt::arg("shortDescription", layout_.short_description),
|
fmt::arg("shortDescription", layout_.short_description), fmt::arg("long", layout_.full_name),
|
||||||
fmt::arg("long", layout_.full_name),
|
fmt::arg("variant", layout_.variant), fmt::arg("flag", layout_.country_flag())));
|
||||||
fmt::arg("variant", layout_.variant),
|
|
||||||
fmt::arg("flag", layout_.country_flag())));
|
|
||||||
label_.set_markup(display_layout);
|
label_.set_markup(display_layout);
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
if (tooltip_format_ != "") {
|
if (tooltip_format_ != "") {
|
||||||
auto tooltip_display_layout = trim(fmt::format(tooltip_format_,
|
auto tooltip_display_layout = trim(
|
||||||
fmt::arg("short", layout_.short_name),
|
fmt::format(tooltip_format_, fmt::arg("short", layout_.short_name),
|
||||||
fmt::arg("shortDescription", layout_.short_description),
|
fmt::arg("shortDescription", layout_.short_description),
|
||||||
fmt::arg("long", layout_.full_name),
|
fmt::arg("long", layout_.full_name), fmt::arg("variant", layout_.variant),
|
||||||
fmt::arg("variant", layout_.variant),
|
|
||||||
fmt::arg("flag", layout_.country_flag())));
|
fmt::arg("flag", layout_.country_flag())));
|
||||||
label_.set_tooltip_markup(tooltip_display_layout);
|
label_.set_tooltip_markup(tooltip_display_layout);
|
||||||
} else {
|
} else {
|
||||||
@ -155,8 +152,7 @@ auto Language::init_layouts_map(const std::vector<std::string>& used_layouts) ->
|
|||||||
std::map<std::string, int> short_name_to_number_map;
|
std::map<std::string, int> short_name_to_number_map;
|
||||||
for (const auto& used_layout_name : used_layouts) {
|
for (const auto& used_layout_name : used_layouts) {
|
||||||
auto found = layouts_map_.find(used_layout_name);
|
auto found = layouts_map_.find(used_layout_name);
|
||||||
if (found == layouts_map_.end())
|
if (found == layouts_map_.end()) continue;
|
||||||
continue;
|
|
||||||
auto used_layout = &found->second;
|
auto used_layout = &found->second;
|
||||||
auto layouts_with_same_name_list = found_by_short_names[used_layout->short_name];
|
auto layouts_with_same_name_list = found_by_short_names[used_layout->short_name];
|
||||||
if (layouts_with_same_name_list.size() < 2) {
|
if (layouts_with_same_name_list.size() < 2) {
|
||||||
@ -169,18 +165,15 @@ auto Language::init_layouts_map(const std::vector<std::string>& used_layouts) ->
|
|||||||
|
|
||||||
if (displayed_short_flag != static_cast<std::byte>(0)) {
|
if (displayed_short_flag != static_cast<std::byte>(0)) {
|
||||||
int& number = short_name_to_number_map[used_layout->short_name];
|
int& number = short_name_to_number_map[used_layout->short_name];
|
||||||
used_layout->short_name =
|
used_layout->short_name = used_layout->short_name + std::to_string(number);
|
||||||
used_layout->short_name + std::to_string(number);
|
used_layout->short_description = used_layout->short_description + std::to_string(number);
|
||||||
used_layout->short_description =
|
|
||||||
used_layout->short_description + std::to_string(number);
|
|
||||||
++number;
|
++number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Language::XKBContext::XKBContext() {
|
Language::XKBContext::XKBContext() {
|
||||||
context_ = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES);
|
context_ = rxkb_context_new(RXKB_CONTEXT_LOAD_EXOTIC_RULES);
|
||||||
rxkb_context_include_path_append_default(context_);
|
|
||||||
rxkb_context_parse_default_ruleset(context_);
|
rxkb_context_parse_default_ruleset(context_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +199,8 @@ auto Language::XKBContext::next_layout() -> Layout* {
|
|||||||
base_layouts_by_name_.emplace(name, xkb_layout_);
|
base_layouts_by_name_.emplace(name, xkb_layout_);
|
||||||
} else {
|
} else {
|
||||||
auto base_layout = base_layouts_by_name_[name];
|
auto base_layout = base_layouts_by_name_[name];
|
||||||
short_description = base_layout == nullptr ? "" : std::string(rxkb_layout_get_brief(base_layout));
|
short_description =
|
||||||
|
base_layout == nullptr ? "" : std::string(rxkb_layout_get_brief(base_layout));
|
||||||
}
|
}
|
||||||
delete layout_;
|
delete layout_;
|
||||||
layout_ = new Layout{description, name, variant, short_description};
|
layout_ = new Layout{description, name, variant, short_description};
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "modules/sway/mode.hpp"
|
#include "modules/sway/mode.hpp"
|
||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
namespace waybar::modules::sway {
|
namespace waybar::modules::sway {
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <glibmm/keyfile.h>
|
#include <glibmm/keyfile.h>
|
||||||
#include <glibmm/miscutils.h>
|
#include <glibmm/miscutils.h>
|
||||||
#include <gtkmm/enums.h>
|
#include <gtkmm/enums.h>
|
||||||
|
#include <gtkmm/icontheme.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@ -15,6 +16,12 @@ namespace waybar::modules::sway {
|
|||||||
|
|
||||||
Window::Window(const std::string& id, const Bar& bar, const Json::Value& config)
|
Window::Window(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||||
: AIconLabel(config, "window", id, "{}", 0, true), bar_(bar), windowId_(-1) {
|
: AIconLabel(config, "window", id, "{}", 0, true), bar_(bar), windowId_(-1) {
|
||||||
|
// Icon size
|
||||||
|
if (config_["icon-size"].isUInt()) {
|
||||||
|
app_icon_size_ = config["icon-size"].asUInt();
|
||||||
|
}
|
||||||
|
image_.set_pixel_size(app_icon_size_);
|
||||||
|
|
||||||
ipc_.subscribe(R"(["window","workspace"])");
|
ipc_.subscribe(R"(["window","workspace"])");
|
||||||
ipc_.signal_event.connect(sigc::mem_fun(*this, &Window::onEvent));
|
ipc_.signal_event.connect(sigc::mem_fun(*this, &Window::onEvent));
|
||||||
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Window::onCmd));
|
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Window::onCmd));
|
||||||
@ -37,59 +44,113 @@ void Window::onCmd(const struct Ipc::ipc_response& res) {
|
|||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
auto payload = parser_.parse(res.payload);
|
auto payload = parser_.parse(res.payload);
|
||||||
auto output = payload["output"].isString() ? payload["output"].asString() : "";
|
auto output = payload["output"].isString() ? payload["output"].asString() : "";
|
||||||
std::tie(app_nb_, windowId_, window_, app_id_) = getFocusedNode(payload["nodes"], output);
|
std::tie(app_nb_, windowId_, window_, app_id_, app_class_) =
|
||||||
updateAppIcon();
|
getFocusedNode(payload["nodes"], output);
|
||||||
|
updateAppIconName();
|
||||||
dp.emit();
|
dp.emit();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
spdlog::error("Window: {}", e.what());
|
spdlog::error("Window: {}", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> getDesktopFilePath(const std::string& app_id) {
|
std::optional<std::string> getDesktopFilePath(const std::string& app_id,
|
||||||
|
const std::string& app_class) {
|
||||||
const auto data_dirs = Glib::get_system_data_dirs();
|
const auto data_dirs = Glib::get_system_data_dirs();
|
||||||
for (const auto& data_dir : data_dirs) {
|
for (const auto& data_dir : data_dirs) {
|
||||||
const auto desktop_file_path = data_dir + "applications/" + app_id + ".desktop";
|
const auto data_app_dir = data_dir + "applications/";
|
||||||
|
auto desktop_file_path = data_app_dir + app_id + ".desktop";
|
||||||
|
if (std::filesystem::exists(desktop_file_path)) {
|
||||||
|
return desktop_file_path;
|
||||||
|
}
|
||||||
|
if (!app_class.empty()) {
|
||||||
|
desktop_file_path = data_app_dir + app_class + ".desktop";
|
||||||
if (std::filesystem::exists(desktop_file_path)) {
|
if (std::filesystem::exists(desktop_file_path)) {
|
||||||
return desktop_file_path;
|
return desktop_file_path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Glib::ustring> getIconName(const std::string& app_id) {
|
std::optional<Glib::ustring> getIconName(const std::string& app_id, const std::string& app_class) {
|
||||||
const auto desktop_file_path = getDesktopFilePath(app_id);
|
const auto desktop_file_path = getDesktopFilePath(app_id, app_class);
|
||||||
if (!desktop_file_path.has_value()) {
|
if (!desktop_file_path.has_value()) {
|
||||||
|
// Try some heuristics to find a matching icon
|
||||||
|
|
||||||
|
const auto default_icon_theme = Gtk::IconTheme::get_default();
|
||||||
|
if (default_icon_theme->has_icon(app_id)) {
|
||||||
|
return app_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto app_id_desktop = app_id + "-desktop";
|
||||||
|
if (default_icon_theme->has_icon(app_id_desktop)) {
|
||||||
|
return app_id_desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto to_lower = [](const std::string& str) {
|
||||||
|
auto str_cpy = str;
|
||||||
|
std::transform(str_cpy.begin(), str_cpy.end(), str_cpy.begin(),
|
||||||
|
[](unsigned char c) { return std::tolower(c); });
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto first_space = app_id.find_first_of(' ');
|
||||||
|
if (first_space != std::string::npos) {
|
||||||
|
const auto first_word = to_lower(app_id.substr(0, first_space));
|
||||||
|
if (default_icon_theme->has_icon(first_word)) {
|
||||||
|
return first_word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto first_dash = app_id.find_first_of('-');
|
||||||
|
if (first_dash != std::string::npos) {
|
||||||
|
const auto first_word = to_lower(app_id.substr(0, first_dash));
|
||||||
|
if (default_icon_theme->has_icon(first_word)) {
|
||||||
|
return first_word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Glib::KeyFile desktop_file;
|
Glib::KeyFile desktop_file;
|
||||||
desktop_file.load_from_file(desktop_file_path.value());
|
desktop_file.load_from_file(desktop_file_path.value());
|
||||||
const auto icon_name = desktop_file.get_string("Desktop Entry", "Icon");
|
return desktop_file.get_string("Desktop Entry", "Icon");
|
||||||
if (icon_name.empty()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return icon_name;
|
|
||||||
} catch (Glib::FileError& error) {
|
} catch (Glib::FileError& error) {
|
||||||
spdlog::warn(
|
spdlog::warn("Error while loading desktop file {}: {}", desktop_file_path.value(),
|
||||||
"Error while loading desktop file {}: {}", desktop_file_path.value(), error.what().c_str());
|
error.what().c_str());
|
||||||
} catch (Glib::KeyFileError& error) {
|
} catch (Glib::KeyFileError& error) {
|
||||||
spdlog::warn(
|
spdlog::warn("Error while loading desktop file {}: {}", desktop_file_path.value(),
|
||||||
"Error while loading desktop file {}: {}", desktop_file_path.value(), error.what().c_str());
|
error.what().c_str());
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::updateAppIcon() {
|
void Window::updateAppIconName() {
|
||||||
if (!iconEnabled()) {
|
if (!iconEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto icon_name = getIconName(app_id_);
|
|
||||||
|
const auto icon_name = getIconName(app_id_, app_class_);
|
||||||
if (icon_name.has_value()) {
|
if (icon_name.has_value()) {
|
||||||
image_.set_from_icon_name(icon_name.value(), Gtk::ICON_SIZE_LARGE_TOOLBAR);
|
app_icon_name_ = icon_name.value();
|
||||||
image_.set_visible(true);
|
} else {
|
||||||
return;
|
app_icon_name_ = "";
|
||||||
}
|
}
|
||||||
|
update_app_icon_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::updateAppIcon() {
|
||||||
|
if (update_app_icon_) {
|
||||||
|
update_app_icon_ = false;
|
||||||
|
if (app_icon_name_.empty()) {
|
||||||
image_.set_visible(false);
|
image_.set_visible(false);
|
||||||
|
} else {
|
||||||
|
image_.set_from_icon_name(app_icon_name_, Gtk::ICON_SIZE_INVALID);
|
||||||
|
image_.set_visible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Window::update() -> void {
|
auto Window::update() -> void {
|
||||||
@ -114,11 +175,14 @@ auto Window::update() -> void {
|
|||||||
bar_.window.get_style_context()->remove_class("solo");
|
bar_.window.get_style_context()->remove_class("solo");
|
||||||
bar_.window.get_style_context()->remove_class("empty");
|
bar_.window.get_style_context()->remove_class("empty");
|
||||||
}
|
}
|
||||||
label_.set_markup(fmt::format(format_, fmt::arg("title", rewriteTitle(window_)),
|
label_.set_markup(
|
||||||
fmt::arg("app_id", app_id_)));
|
fmt::format(format_, fmt::arg("title", rewriteTitle(window_)), fmt::arg("app_id", app_id_)));
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
label_.set_tooltip_text(window_);
|
label_.set_tooltip_text(window_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateAppIcon();
|
||||||
|
|
||||||
// Call parent update
|
// Call parent update
|
||||||
AIconLabel::update();
|
AIconLabel::update();
|
||||||
}
|
}
|
||||||
@ -134,19 +198,17 @@ int leafNodesInWorkspace(const Json::Value& node) {
|
|||||||
}
|
}
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
if (!nodes.empty()) {
|
if (!nodes.empty()) {
|
||||||
for(auto const& node : nodes)
|
for (auto const& node : nodes) sum += leafNodesInWorkspace(node);
|
||||||
sum += leafNodesInWorkspace(node);
|
|
||||||
}
|
}
|
||||||
if (!floating_nodes.empty()) {
|
if (!floating_nodes.empty()) {
|
||||||
for(auto const& node : floating_nodes)
|
for (auto const& node : floating_nodes) sum += leafNodesInWorkspace(node);
|
||||||
sum += leafNodesInWorkspace(node);
|
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<std::size_t, int, std::string, std::string> gfnWithWorkspace(
|
std::tuple<std::size_t, int, std::string, std::string, std::string> gfnWithWorkspace(
|
||||||
const Json::Value& nodes, std::string& output, const Json::Value& config_,
|
const Json::Value& nodes, std::string& output, const Json::Value& config_, const Bar& bar_,
|
||||||
const Bar& bar_, Json::Value& parentWorkspace) {
|
Json::Value& parentWorkspace) {
|
||||||
for (auto const& node : nodes) {
|
for (auto const& node : nodes) {
|
||||||
if (node["output"].isString()) {
|
if (node["output"].isString()) {
|
||||||
output = node["output"].asString();
|
output = node["output"].asString();
|
||||||
@ -157,32 +219,33 @@ std::tuple<std::size_t, int, std::string, std::string> gfnWithWorkspace(
|
|||||||
config_["all-outputs"].asBool()) {
|
config_["all-outputs"].asBool()) {
|
||||||
auto app_id = node["app_id"].isString() ? node["app_id"].asString()
|
auto app_id = node["app_id"].isString() ? node["app_id"].asString()
|
||||||
: node["window_properties"]["instance"].asString();
|
: node["window_properties"]["instance"].asString();
|
||||||
|
const auto app_class = node["window_properties"]["class"].isString()
|
||||||
|
? node["window_properties"]["class"].asString()
|
||||||
|
: "";
|
||||||
int nb = node.size();
|
int nb = node.size();
|
||||||
if(parentWorkspace != 0)
|
if (parentWorkspace != 0) nb = leafNodesInWorkspace(parentWorkspace);
|
||||||
nb = leafNodesInWorkspace(parentWorkspace);
|
return {nb, node["id"].asInt(), Glib::Markup::escape_text(node["name"].asString()), app_id,
|
||||||
return {nb,
|
app_class};
|
||||||
node["id"].asInt(),
|
|
||||||
Glib::Markup::escape_text(node["name"].asString()),
|
|
||||||
app_id};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// iterate
|
// iterate
|
||||||
if(node["type"] == "workspace")
|
if (node["type"] == "workspace") parentWorkspace = node;
|
||||||
parentWorkspace = node;
|
auto [nb, id, name, app_id, app_class] =
|
||||||
auto [nb, id, name, app_id] = gfnWithWorkspace(node["nodes"], output, config_, bar_, parentWorkspace);
|
gfnWithWorkspace(node["nodes"], output, config_, bar_, parentWorkspace);
|
||||||
if (id > -1 && !name.empty()) {
|
if (id > -1 && !name.empty()) {
|
||||||
return {nb, id, name, app_id};
|
return {nb, id, name, app_id, app_class};
|
||||||
}
|
}
|
||||||
// Search for floating node
|
// Search for floating node
|
||||||
std::tie(nb, id, name, app_id) = gfnWithWorkspace(node["floating_nodes"], output, config_, bar_, parentWorkspace);
|
std::tie(nb, id, name, app_id, app_class) =
|
||||||
|
gfnWithWorkspace(node["floating_nodes"], output, config_, bar_, parentWorkspace);
|
||||||
if (id > -1 && !name.empty()) {
|
if (id > -1 && !name.empty()) {
|
||||||
return {nb, id, name, app_id};
|
return {nb, id, name, app_id, app_class};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {0, -1, "", ""};
|
return {0, -1, "", "", ""};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<std::size_t, int, std::string, std::string> Window::getFocusedNode(
|
std::tuple<std::size_t, int, std::string, std::string, std::string> Window::getFocusedNode(
|
||||||
const Json::Value& nodes, std::string& output) {
|
const Json::Value& nodes, std::string& output) {
|
||||||
Json::Value placeholder = 0;
|
Json::Value placeholder = 0;
|
||||||
return gfnWithWorkspace(nodes, output, config_, bar_, placeholder);
|
return gfnWithWorkspace(nodes, output, config_, bar_, placeholder);
|
||||||
|
@ -67,9 +67,7 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
|
|||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
auto payload = parser_.parse(res.payload);
|
auto payload = parser_.parse(res.payload);
|
||||||
workspaces_.clear();
|
workspaces_.clear();
|
||||||
std::copy_if(payload.begin(),
|
std::copy_if(payload.begin(), payload.end(), std::back_inserter(workspaces_),
|
||||||
payload.end(),
|
|
||||||
std::back_inserter(workspaces_),
|
|
||||||
[&](const auto &workspace) {
|
[&](const auto &workspace) {
|
||||||
return !config_["all-outputs"].asBool()
|
return !config_["all-outputs"].asBool()
|
||||||
? workspace["output"].asString() == bar_.output->name
|
? workspace["output"].asString() == bar_.output->name
|
||||||
@ -144,8 +142,7 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
|
|||||||
workspace["sort"] = ++max_num;
|
workspace["sort"] = ++max_num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(workspaces_.begin(),
|
std::sort(workspaces_.begin(), workspaces_.end(),
|
||||||
workspaces_.end(),
|
|
||||||
[](const Json::Value &lhs, const Json::Value &rhs) {
|
[](const Json::Value &lhs, const Json::Value &rhs) {
|
||||||
auto lname = lhs["name"].asString();
|
auto lname = lhs["name"].asString();
|
||||||
auto rname = rhs["name"].asString();
|
auto rname = rhs["name"].asString();
|
||||||
@ -161,7 +158,6 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
|
|||||||
|
|
||||||
return l < r;
|
return l < r;
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
dp.emit();
|
dp.emit();
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
@ -173,9 +169,8 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
|
|||||||
bool Workspaces::filterButtons() {
|
bool Workspaces::filterButtons() {
|
||||||
bool needReorder = false;
|
bool needReorder = false;
|
||||||
for (auto it = buttons_.begin(); it != buttons_.end();) {
|
for (auto it = buttons_.begin(); it != buttons_.end();) {
|
||||||
auto ws = std::find_if(workspaces_.begin(), workspaces_.end(), [it](const auto &node) {
|
auto ws = std::find_if(workspaces_.begin(), workspaces_.end(),
|
||||||
return node["name"].asString() == it->first;
|
[it](const auto &node) { return node["name"].asString() == it->first; });
|
||||||
});
|
|
||||||
if (ws == workspaces_.end() ||
|
if (ws == workspaces_.end() ||
|
||||||
(!config_["all-outputs"].asBool() && (*ws)["output"].asString() != bar_.output->name)) {
|
(!config_["all-outputs"].asBool() && (*ws)["output"].asString() != bar_.output->name)) {
|
||||||
it = buttons_.erase(it);
|
it = buttons_.erase(it);
|
||||||
@ -231,10 +226,8 @@ auto Workspaces::update() -> void {
|
|||||||
std::string output = (*it)["name"].asString();
|
std::string output = (*it)["name"].asString();
|
||||||
if (config_["format"].isString()) {
|
if (config_["format"].isString()) {
|
||||||
auto format = config_["format"].asString();
|
auto format = config_["format"].asString();
|
||||||
output = fmt::format(format,
|
output = fmt::format(format, fmt::arg("icon", getIcon(output, *it)),
|
||||||
fmt::arg("icon", getIcon(output, *it)),
|
fmt::arg("value", output), fmt::arg("name", trimWorkspaceName(output)),
|
||||||
fmt::arg("value", output),
|
|
||||||
fmt::arg("name", trimWorkspaceName(output)),
|
|
||||||
fmt::arg("index", (*it)["num"].asString()));
|
fmt::arg("index", (*it)["num"].asString()));
|
||||||
}
|
}
|
||||||
if (!config_["disable-markup"].asBool()) {
|
if (!config_["disable-markup"].asBool()) {
|
||||||
@ -258,18 +251,14 @@ Gtk::Button &Workspaces::addButton(const Json::Value &node) {
|
|||||||
button.signal_pressed().connect([this, node] {
|
button.signal_pressed().connect([this, node] {
|
||||||
try {
|
try {
|
||||||
if (node["target_output"].isString()) {
|
if (node["target_output"].isString()) {
|
||||||
ipc_.sendCmd(
|
ipc_.sendCmd(IPC_COMMAND,
|
||||||
IPC_COMMAND,
|
fmt::format(workspace_switch_cmd_ + "; move workspace to output \"{}\"; " +
|
||||||
fmt::format(workspace_switch_cmd_ + "; move workspace to output \"{}\"; " + workspace_switch_cmd_,
|
workspace_switch_cmd_,
|
||||||
"--no-auto-back-and-forth",
|
"--no-auto-back-and-forth", node["name"].asString(),
|
||||||
node["name"].asString(),
|
node["target_output"].asString(), "--no-auto-back-and-forth",
|
||||||
node["target_output"].asString(),
|
|
||||||
"--no-auto-back-and-forth",
|
|
||||||
node["name"].asString()));
|
node["name"].asString()));
|
||||||
} else {
|
} else {
|
||||||
ipc_.sendCmd(
|
ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace {} \"{}\"",
|
||||||
IPC_COMMAND,
|
|
||||||
fmt::format("workspace {} \"{}\"",
|
|
||||||
config_["disable-auto-back-and-forth"].asBool()
|
config_["disable-auto-back-and-forth"].asBool()
|
||||||
? "--no-auto-back-and-forth"
|
? "--no-auto-back-and-forth"
|
||||||
: "",
|
: "",
|
||||||
@ -316,9 +305,8 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
|
|||||||
std::string name;
|
std::string name;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
auto it = std::find_if(workspaces_.begin(), workspaces_.end(), [](const auto &workspace) {
|
auto it = std::find_if(workspaces_.begin(), workspaces_.end(),
|
||||||
return workspace["focused"].asBool();
|
[](const auto &workspace) { return workspace["focused"].asBool(); });
|
||||||
});
|
|
||||||
if (it == workspaces_.end()) {
|
if (it == workspaces_.end()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -334,9 +322,7 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ipc_.sendCmd(
|
ipc_.sendCmd(IPC_COMMAND, fmt::format(workspace_switch_cmd_, "--no-auto-back-and-forth", name));
|
||||||
IPC_COMMAND,
|
|
||||||
fmt::format(workspace_switch_cmd_, "--no-auto-back-and-forth", name));
|
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
spdlog::error("Workspaces: {}", e.what());
|
spdlog::error("Workspaces: {}", e.what());
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "modules/temperature.hpp"
|
#include "modules/temperature.hpp"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
waybar::modules::Temperature::Temperature(const std::string& id, const Json::Value& config)
|
waybar::modules::Temperature::Temperature(const std::string& id, const Json::Value& config)
|
||||||
@ -6,7 +7,10 @@ waybar::modules::Temperature::Temperature(const std::string& id, const Json::Val
|
|||||||
if (config_["hwmon-path"].isString()) {
|
if (config_["hwmon-path"].isString()) {
|
||||||
file_path_ = config_["hwmon-path"].asString();
|
file_path_ = config_["hwmon-path"].asString();
|
||||||
} else if (config_["hwmon-path-abs"].isString() && config_["input-filename"].isString()) {
|
} else if (config_["hwmon-path-abs"].isString() && config_["input-filename"].isString()) {
|
||||||
file_path_ = (*std::filesystem::directory_iterator(config_["hwmon-path-abs"].asString())).path().string() + "/" + config_["input-filename"].asString();
|
file_path_ = (*std::filesystem::directory_iterator(config_["hwmon-path-abs"].asString()))
|
||||||
|
.path()
|
||||||
|
.string() +
|
||||||
|
"/" + config_["input-filename"].asString();
|
||||||
} else {
|
} else {
|
||||||
auto zone = config_["thermal-zone"].isInt() ? config_["thermal-zone"].asInt() : 0;
|
auto zone = config_["thermal-zone"].isInt() ? config_["thermal-zone"].asInt() : 0;
|
||||||
file_path_ = fmt::format("/sys/class/thermal/thermal_zone{}/temp", zone);
|
file_path_ = fmt::format("/sys/class/thermal/thermal_zone{}/temp", zone);
|
||||||
@ -34,9 +38,16 @@ auto waybar::modules::Temperature::update() -> void {
|
|||||||
} else {
|
} else {
|
||||||
label_.get_style_context()->remove_class("critical");
|
label_.get_style_context()->remove_class("critical");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (format.empty()) {
|
||||||
|
event_box_.hide();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
event_box_.show();
|
||||||
|
}
|
||||||
|
|
||||||
auto max_temp = config_["critical-threshold"].isInt() ? config_["critical-threshold"].asInt() : 0;
|
auto max_temp = config_["critical-threshold"].isInt() ? config_["critical-threshold"].asInt() : 0;
|
||||||
label_.set_markup(fmt::format(format,
|
label_.set_markup(fmt::format(format, fmt::arg("temperatureC", temperature_c),
|
||||||
fmt::arg("temperatureC", temperature_c),
|
|
||||||
fmt::arg("temperatureF", temperature_f),
|
fmt::arg("temperatureF", temperature_f),
|
||||||
fmt::arg("temperatureK", temperature_k),
|
fmt::arg("temperatureK", temperature_k),
|
||||||
fmt::arg("icon", getIcon(temperature_c, "", max_temp))));
|
fmt::arg("icon", getIcon(temperature_c, "", max_temp))));
|
||||||
@ -45,8 +56,7 @@ auto waybar::modules::Temperature::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(fmt::format(tooltip_format, fmt::arg("temperatureC", temperature_c),
|
||||||
fmt::arg("temperatureC", temperature_c),
|
|
||||||
fmt::arg("temperatureF", temperature_f),
|
fmt::arg("temperatureF", temperature_f),
|
||||||
fmt::arg("temperatureK", temperature_k)));
|
fmt::arg("temperatureK", temperature_k)));
|
||||||
}
|
}
|
||||||
|
361
src/modules/upower/upower.cpp
Normal file
361
src/modules/upower/upower.cpp
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
#include "modules/upower/upower.hpp"
|
||||||
|
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "gtkmm/icontheme.h"
|
||||||
|
#include "gtkmm/label.h"
|
||||||
|
#include "gtkmm/tooltip.h"
|
||||||
|
#include "modules/upower/upower_tooltip.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::upower {
|
||||||
|
UPower::UPower(const std::string& id, const Json::Value& config)
|
||||||
|
: AModule(config, "upower", id),
|
||||||
|
box_(Gtk::ORIENTATION_HORIZONTAL, 0),
|
||||||
|
icon_(),
|
||||||
|
label_(),
|
||||||
|
devices(),
|
||||||
|
m_Mutex(),
|
||||||
|
client(),
|
||||||
|
showAltText(false) {
|
||||||
|
box_.pack_start(icon_);
|
||||||
|
box_.pack_start(label_);
|
||||||
|
box_.set_name(name_);
|
||||||
|
event_box_.add(box_);
|
||||||
|
|
||||||
|
// Icon Size
|
||||||
|
if (config_["icon-size"].isUInt()) {
|
||||||
|
iconSize = config_["icon-size"].asUInt();
|
||||||
|
}
|
||||||
|
icon_.set_pixel_size(iconSize);
|
||||||
|
|
||||||
|
// Hide If Empty
|
||||||
|
if (config_["hide-if-empty"].isBool()) {
|
||||||
|
hideIfEmpty = config_["hide-if-empty"].asBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format
|
||||||
|
if (config_["format"].isString()) {
|
||||||
|
format = config_["format"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format Alt
|
||||||
|
if (config_["format-alt"].isString()) {
|
||||||
|
format_alt = config_["format-alt"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tooltip Spacing
|
||||||
|
if (config_["tooltip-spacing"].isUInt()) {
|
||||||
|
tooltip_spacing = config_["tooltip-spacing"].asUInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tooltip Padding
|
||||||
|
if (config_["tooltip-padding"].isUInt()) {
|
||||||
|
tooltip_padding = config_["tooltip-padding"].asUInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
if (config_["tooltip"].isBool()) {
|
||||||
|
tooltip_enabled = config_["tooltip"].asBool();
|
||||||
|
}
|
||||||
|
box_.set_has_tooltip(tooltip_enabled);
|
||||||
|
if (tooltip_enabled) {
|
||||||
|
// Sets the window to use when showing the tooltip
|
||||||
|
upower_tooltip = new UPowerTooltip(iconSize, tooltip_spacing, tooltip_padding);
|
||||||
|
box_.set_tooltip_window(*upower_tooltip);
|
||||||
|
box_.signal_query_tooltip().connect(sigc::mem_fun(*this, &UPower::show_tooltip_callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
upowerWatcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM, "org.freedesktop.UPower",
|
||||||
|
G_BUS_NAME_WATCHER_FLAGS_AUTO_START, upowerAppear,
|
||||||
|
upowerDisappear, this, NULL);
|
||||||
|
|
||||||
|
GError* error = NULL;
|
||||||
|
client = up_client_new_full(NULL, &error);
|
||||||
|
if (client == NULL) {
|
||||||
|
throw std::runtime_error("Unable to create UPower client!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to Login1 PrepareForSleep signal
|
||||||
|
login1_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||||
|
if (!login1_connection) {
|
||||||
|
throw std::runtime_error("Unable to connect to the SYSTEM Bus!...");
|
||||||
|
} else {
|
||||||
|
login1_id = g_dbus_connection_signal_subscribe(
|
||||||
|
login1_connection, "org.freedesktop.login1", "org.freedesktop.login1.Manager",
|
||||||
|
"PrepareForSleep", "/org/freedesktop/login1", NULL, G_DBUS_SIGNAL_FLAGS_NONE,
|
||||||
|
prepareForSleep_cb, this, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &UPower::handleToggle));
|
||||||
|
|
||||||
|
g_signal_connect(client, "device-added", G_CALLBACK(deviceAdded_cb), this);
|
||||||
|
g_signal_connect(client, "device-removed", G_CALLBACK(deviceRemoved_cb), this);
|
||||||
|
|
||||||
|
resetDevices();
|
||||||
|
setDisplayDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
UPower::~UPower() {
|
||||||
|
if (client != NULL) g_object_unref(client);
|
||||||
|
if (login1_id > 0) {
|
||||||
|
g_dbus_connection_signal_unsubscribe(login1_connection, login1_id);
|
||||||
|
login1_id = 0;
|
||||||
|
}
|
||||||
|
g_bus_unwatch_name(upowerWatcher_id);
|
||||||
|
removeDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPower::deviceAdded_cb(UpClient* client, UpDevice* device, gpointer data) {
|
||||||
|
UPower* up = static_cast<UPower*>(data);
|
||||||
|
up->addDevice(device);
|
||||||
|
up->setDisplayDevice();
|
||||||
|
// Update the widget
|
||||||
|
up->dp.emit();
|
||||||
|
}
|
||||||
|
void UPower::deviceRemoved_cb(UpClient* client, const gchar* objectPath, gpointer data) {
|
||||||
|
UPower* up = static_cast<UPower*>(data);
|
||||||
|
up->removeDevice(objectPath);
|
||||||
|
up->setDisplayDevice();
|
||||||
|
// Update the widget
|
||||||
|
up->dp.emit();
|
||||||
|
}
|
||||||
|
void UPower::deviceNotify_cb(UpDevice* device, GParamSpec* pspec, gpointer data) {
|
||||||
|
UPower* up = static_cast<UPower*>(data);
|
||||||
|
// Update the widget
|
||||||
|
up->dp.emit();
|
||||||
|
}
|
||||||
|
void UPower::prepareForSleep_cb(GDBusConnection* system_bus, const gchar* sender_name,
|
||||||
|
const gchar* object_path, const gchar* interface_name,
|
||||||
|
const gchar* signal_name, GVariant* parameters, gpointer data) {
|
||||||
|
if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(b)"))) {
|
||||||
|
gboolean sleeping;
|
||||||
|
g_variant_get(parameters, "(b)", &sleeping);
|
||||||
|
|
||||||
|
if (!sleeping) {
|
||||||
|
UPower* up = static_cast<UPower*>(data);
|
||||||
|
up->resetDevices();
|
||||||
|
up->setDisplayDevice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void UPower::upowerAppear(GDBusConnection* conn, const gchar* name, const gchar* name_owner,
|
||||||
|
gpointer data) {
|
||||||
|
UPower* up = static_cast<UPower*>(data);
|
||||||
|
up->upowerRunning = true;
|
||||||
|
up->event_box_.set_visible(true);
|
||||||
|
}
|
||||||
|
void UPower::upowerDisappear(GDBusConnection* conn, const gchar* name, gpointer data) {
|
||||||
|
UPower* up = static_cast<UPower*>(data);
|
||||||
|
up->upowerRunning = false;
|
||||||
|
up->event_box_.set_visible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPower::removeDevice(const gchar* objectPath) {
|
||||||
|
std::lock_guard<std::mutex> guard(m_Mutex);
|
||||||
|
if (devices.find(objectPath) != devices.end()) {
|
||||||
|
UpDevice* device = devices[objectPath];
|
||||||
|
if (G_IS_OBJECT(device)) {
|
||||||
|
g_object_unref(device);
|
||||||
|
}
|
||||||
|
devices.erase(objectPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPower::addDevice(UpDevice* device) {
|
||||||
|
if (G_IS_OBJECT(device)) {
|
||||||
|
const gchar* objectPath = up_device_get_object_path(device);
|
||||||
|
|
||||||
|
// Due to the device getting cleared after this event is fired, we
|
||||||
|
// create a new object pointing to its objectPath
|
||||||
|
gboolean ret;
|
||||||
|
device = up_device_new();
|
||||||
|
ret = up_device_set_object_path_sync(device, objectPath, NULL, NULL);
|
||||||
|
if (!ret) {
|
||||||
|
g_object_unref(G_OBJECT(device));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> guard(m_Mutex);
|
||||||
|
|
||||||
|
if (devices.find(objectPath) != devices.end()) {
|
||||||
|
UpDevice* device = devices[objectPath];
|
||||||
|
if (G_IS_OBJECT(device)) {
|
||||||
|
g_object_unref(device);
|
||||||
|
}
|
||||||
|
devices.erase(objectPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect(device, "notify", G_CALLBACK(deviceNotify_cb), this);
|
||||||
|
devices.emplace(Devices::value_type(objectPath, device));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPower::setDisplayDevice() {
|
||||||
|
std::lock_guard<std::mutex> guard(m_Mutex);
|
||||||
|
displayDevice = up_client_get_display_device(client);
|
||||||
|
g_signal_connect(displayDevice, "notify", G_CALLBACK(deviceNotify_cb), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPower::removeDevices() {
|
||||||
|
std::lock_guard<std::mutex> guard(m_Mutex);
|
||||||
|
if (!devices.empty()) {
|
||||||
|
auto it = devices.cbegin();
|
||||||
|
while (it != devices.cend()) {
|
||||||
|
if (G_IS_OBJECT(it->second)) {
|
||||||
|
g_object_unref(it->second);
|
||||||
|
}
|
||||||
|
devices.erase(it++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Removes all devices and adds the current devices */
|
||||||
|
void UPower::resetDevices() {
|
||||||
|
// Removes all devices
|
||||||
|
removeDevices();
|
||||||
|
|
||||||
|
// Adds all devices
|
||||||
|
GPtrArray* newDevices = up_client_get_devices2(client);
|
||||||
|
for (guint i = 0; i < newDevices->len; i++) {
|
||||||
|
UpDevice* device = (UpDevice*)g_ptr_array_index(newDevices, i);
|
||||||
|
if (device && G_IS_OBJECT(device)) addDevice(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the widget
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UPower::show_tooltip_callback(int, int, bool, const Glib::RefPtr<Gtk::Tooltip>& tooltip) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string UPower::getDeviceStatus(UpDeviceState& state) {
|
||||||
|
switch (state) {
|
||||||
|
case UP_DEVICE_STATE_CHARGING:
|
||||||
|
case UP_DEVICE_STATE_PENDING_CHARGE:
|
||||||
|
return "charging";
|
||||||
|
case UP_DEVICE_STATE_DISCHARGING:
|
||||||
|
case UP_DEVICE_STATE_PENDING_DISCHARGE:
|
||||||
|
return "discharging";
|
||||||
|
case UP_DEVICE_STATE_FULLY_CHARGED:
|
||||||
|
return "full";
|
||||||
|
case UP_DEVICE_STATE_EMPTY:
|
||||||
|
return "empty";
|
||||||
|
default:
|
||||||
|
return "unknown-status";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UPower::handleToggle(GdkEventButton* const& event) {
|
||||||
|
std::lock_guard<std::mutex> guard(m_Mutex);
|
||||||
|
showAltText = !showAltText;
|
||||||
|
dp.emit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string UPower::timeToString(gint64 time) {
|
||||||
|
if (time == 0) return "";
|
||||||
|
float hours = (float)time / 3600;
|
||||||
|
float hours_fixed = static_cast<float>(static_cast<int>(hours * 10)) / 10;
|
||||||
|
float minutes = static_cast<float>(static_cast<int>(hours * 60 * 10)) / 10;
|
||||||
|
if (hours_fixed >= 1) {
|
||||||
|
return fmt::format("{H} h", fmt::arg("H", hours_fixed));
|
||||||
|
} else {
|
||||||
|
return fmt::format("{M} min", fmt::arg("M", minutes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto UPower::update() -> void {
|
||||||
|
std::lock_guard<std::mutex> guard(m_Mutex);
|
||||||
|
|
||||||
|
// Don't update widget if the UPower service isn't running
|
||||||
|
if (!upowerRunning) return;
|
||||||
|
|
||||||
|
UpDeviceKind kind;
|
||||||
|
UpDeviceState state;
|
||||||
|
double percentage;
|
||||||
|
gint64 time_empty;
|
||||||
|
gint64 time_full;
|
||||||
|
gchar* icon_name;
|
||||||
|
|
||||||
|
g_object_get(displayDevice, "kind", &kind, "state", &state, "percentage", &percentage,
|
||||||
|
"icon-name", &icon_name, "time-to-empty", &time_empty, "time-to-full", &time_full,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
bool displayDeviceValid =
|
||||||
|
kind == UpDeviceKind::UP_DEVICE_KIND_BATTERY || kind == UpDeviceKind::UP_DEVICE_KIND_UPS;
|
||||||
|
|
||||||
|
// CSS status class
|
||||||
|
const std::string status = getDeviceStatus(state);
|
||||||
|
// 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 (!box_.get_style_context()->has_class(status)) {
|
||||||
|
box_.get_style_context()->add_class(status);
|
||||||
|
}
|
||||||
|
lastStatus = status;
|
||||||
|
|
||||||
|
if (devices.size() == 0 && !displayDeviceValid && hideIfEmpty) {
|
||||||
|
event_box_.set_visible(false);
|
||||||
|
// Call parent update
|
||||||
|
AModule::update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_box_.set_visible(true);
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
if (tooltip_enabled) {
|
||||||
|
uint tooltipCount = upower_tooltip->updateTooltip(devices);
|
||||||
|
// Disable the tooltip if there aren't any devices in the tooltip
|
||||||
|
box_.set_has_tooltip(!devices.empty() && tooltipCount > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set percentage
|
||||||
|
std::string percentString = "";
|
||||||
|
if (displayDeviceValid) {
|
||||||
|
percentString = std::to_string(int(percentage + 0.5)) + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label format
|
||||||
|
std::string time_format = "";
|
||||||
|
switch (state) {
|
||||||
|
case UP_DEVICE_STATE_CHARGING:
|
||||||
|
case UP_DEVICE_STATE_PENDING_CHARGE:
|
||||||
|
time_format = timeToString(time_full);
|
||||||
|
break;
|
||||||
|
case UP_DEVICE_STATE_DISCHARGING:
|
||||||
|
case UP_DEVICE_STATE_PENDING_DISCHARGE:
|
||||||
|
time_format = timeToString(time_empty);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::string label_format =
|
||||||
|
fmt::format(showAltText ? format_alt : format, fmt::arg("percentage", percentString),
|
||||||
|
fmt::arg("time", time_format));
|
||||||
|
// Only set the label text if it doesn't only contain spaces
|
||||||
|
bool onlySpaces = true;
|
||||||
|
for (auto& character : label_format) {
|
||||||
|
if (character == ' ') continue;
|
||||||
|
onlySpaces = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
label_.set_markup(onlySpaces ? "" : label_format);
|
||||||
|
|
||||||
|
// Set icon
|
||||||
|
if (icon_name == NULL || !Gtk::IconTheme::get_default()->has_icon(icon_name)) {
|
||||||
|
icon_name = (char*)"battery-missing-symbolic";
|
||||||
|
}
|
||||||
|
icon_.set_from_icon_name(icon_name, Gtk::ICON_SIZE_INVALID);
|
||||||
|
|
||||||
|
// Call parent update
|
||||||
|
AModule::update();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules::upower
|
161
src/modules/upower/upower_tooltip.cpp
Normal file
161
src/modules/upower/upower_tooltip.cpp
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
#include "modules/upower/upower_tooltip.hpp"
|
||||||
|
|
||||||
|
#include "gtkmm/box.h"
|
||||||
|
#include "gtkmm/enums.h"
|
||||||
|
#include "gtkmm/icontheme.h"
|
||||||
|
#include "gtkmm/image.h"
|
||||||
|
#include "gtkmm/label.h"
|
||||||
|
|
||||||
|
namespace waybar::modules::upower {
|
||||||
|
UPowerTooltip::UPowerTooltip(uint iconSize_, uint tooltipSpacing_, uint tooltipPadding_)
|
||||||
|
: Gtk::Window(),
|
||||||
|
iconSize(iconSize_),
|
||||||
|
tooltipSpacing(tooltipSpacing_),
|
||||||
|
tooltipPadding(tooltipPadding_) {
|
||||||
|
contentBox = new Gtk::Box(Gtk::ORIENTATION_VERTICAL);
|
||||||
|
|
||||||
|
// Sets the Tooltip Padding
|
||||||
|
contentBox->set_margin_top(tooltipPadding);
|
||||||
|
contentBox->set_margin_bottom(tooltipPadding);
|
||||||
|
contentBox->set_margin_left(tooltipPadding);
|
||||||
|
contentBox->set_margin_right(tooltipPadding);
|
||||||
|
|
||||||
|
add(*contentBox);
|
||||||
|
contentBox->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
UPowerTooltip::~UPowerTooltip() {}
|
||||||
|
|
||||||
|
uint UPowerTooltip::updateTooltip(Devices& devices) {
|
||||||
|
// Removes all old devices
|
||||||
|
for (auto child : contentBox->get_children()) {
|
||||||
|
child->~Widget();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint deviceCount = 0;
|
||||||
|
// Adds all valid devices
|
||||||
|
for (auto pair : devices) {
|
||||||
|
UpDevice* device = pair.second;
|
||||||
|
std::string objectPath = pair.first;
|
||||||
|
|
||||||
|
if (!G_IS_OBJECT(device)) continue;
|
||||||
|
|
||||||
|
Gtk::Box* box = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, tooltipSpacing);
|
||||||
|
|
||||||
|
UpDeviceKind kind;
|
||||||
|
double percentage;
|
||||||
|
gchar* native_path;
|
||||||
|
gchar* model;
|
||||||
|
gchar* icon_name;
|
||||||
|
|
||||||
|
g_object_get(device, "kind", &kind, "percentage", &percentage, "native-path", &native_path,
|
||||||
|
"model", &model, "icon-name", &icon_name, NULL);
|
||||||
|
|
||||||
|
// Skip Line_Power and BAT0 devices
|
||||||
|
if (kind == UP_DEVICE_KIND_LINE_POWER || native_path == NULL || strlen(native_path) == 0 ||
|
||||||
|
strcmp(native_path, "BAT0") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Gtk::Box* modelBox = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL);
|
||||||
|
box->add(*modelBox);
|
||||||
|
// Set device icon
|
||||||
|
std::string deviceIconName = getDeviceIcon(kind);
|
||||||
|
Gtk::Image* deviceIcon = new Gtk::Image();
|
||||||
|
deviceIcon->set_pixel_size(iconSize);
|
||||||
|
if (!Gtk::IconTheme::get_default()->has_icon(deviceIconName)) {
|
||||||
|
deviceIconName = "battery-missing-symbolic";
|
||||||
|
}
|
||||||
|
deviceIcon->set_from_icon_name(deviceIconName, Gtk::ICON_SIZE_INVALID);
|
||||||
|
modelBox->add(*deviceIcon);
|
||||||
|
|
||||||
|
// Set model
|
||||||
|
if (model == NULL) model = (gchar*)"";
|
||||||
|
Gtk::Label* modelLabel = new Gtk::Label(model);
|
||||||
|
modelBox->add(*modelLabel);
|
||||||
|
|
||||||
|
Gtk::Box* chargeBox = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL);
|
||||||
|
box->add(*chargeBox);
|
||||||
|
|
||||||
|
// Set icon
|
||||||
|
Gtk::Image* icon = new Gtk::Image();
|
||||||
|
icon->set_pixel_size(iconSize);
|
||||||
|
if (icon_name == NULL || !Gtk::IconTheme::get_default()->has_icon(icon_name)) {
|
||||||
|
icon_name = (char*)"battery-missing-symbolic";
|
||||||
|
}
|
||||||
|
icon->set_from_icon_name(icon_name, Gtk::ICON_SIZE_INVALID);
|
||||||
|
chargeBox->add(*icon);
|
||||||
|
|
||||||
|
// Set percentage
|
||||||
|
std::string percentString = std::to_string(int(percentage + 0.5)) + "%";
|
||||||
|
Gtk::Label* percentLabel = new Gtk::Label(percentString);
|
||||||
|
chargeBox->add(*percentLabel);
|
||||||
|
|
||||||
|
contentBox->add(*box);
|
||||||
|
|
||||||
|
deviceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
contentBox->show_all();
|
||||||
|
return deviceCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string UPowerTooltip::getDeviceIcon(UpDeviceKind& kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case UP_DEVICE_KIND_LINE_POWER:
|
||||||
|
return "ac-adapter-symbolic";
|
||||||
|
case UP_DEVICE_KIND_BATTERY:
|
||||||
|
return "battery";
|
||||||
|
case UP_DEVICE_KIND_UPS:
|
||||||
|
return "uninterruptible-power-supply-symbolic";
|
||||||
|
case UP_DEVICE_KIND_MONITOR:
|
||||||
|
return "video-display-symbolic";
|
||||||
|
case UP_DEVICE_KIND_MOUSE:
|
||||||
|
return "input-mouse-symbolic";
|
||||||
|
case UP_DEVICE_KIND_KEYBOARD:
|
||||||
|
return "input-keyboard-symbolic";
|
||||||
|
case UP_DEVICE_KIND_PDA:
|
||||||
|
return "pda-symbolic";
|
||||||
|
case UP_DEVICE_KIND_PHONE:
|
||||||
|
return "phone-symbolic";
|
||||||
|
case UP_DEVICE_KIND_MEDIA_PLAYER:
|
||||||
|
return "multimedia-player-symbolic";
|
||||||
|
case UP_DEVICE_KIND_TABLET:
|
||||||
|
return "computer-apple-ipad-symbolic";
|
||||||
|
case UP_DEVICE_KIND_COMPUTER:
|
||||||
|
return "computer-symbolic";
|
||||||
|
case UP_DEVICE_KIND_GAMING_INPUT:
|
||||||
|
return "input-gaming-symbolic";
|
||||||
|
case UP_DEVICE_KIND_PEN:
|
||||||
|
return "input-tablet-symbolic";
|
||||||
|
case UP_DEVICE_KIND_TOUCHPAD:
|
||||||
|
return "input-touchpad-symbolic";
|
||||||
|
case UP_DEVICE_KIND_MODEM:
|
||||||
|
return "modem-symbolic";
|
||||||
|
case UP_DEVICE_KIND_NETWORK:
|
||||||
|
return "network-wired-symbolic";
|
||||||
|
case UP_DEVICE_KIND_HEADSET:
|
||||||
|
return "audio-headset-symbolic";
|
||||||
|
case UP_DEVICE_KIND_HEADPHONES:
|
||||||
|
return "audio-headphones-symbolic";
|
||||||
|
case UP_DEVICE_KIND_OTHER_AUDIO:
|
||||||
|
case UP_DEVICE_KIND_SPEAKERS:
|
||||||
|
return "audio-speakers-symbolic";
|
||||||
|
case UP_DEVICE_KIND_VIDEO:
|
||||||
|
return "camera-web-symbolic";
|
||||||
|
case UP_DEVICE_KIND_PRINTER:
|
||||||
|
return "printer-symbolic";
|
||||||
|
case UP_DEVICE_KIND_SCANNER:
|
||||||
|
return "scanner-symbolic";
|
||||||
|
case UP_DEVICE_KIND_CAMERA:
|
||||||
|
return "camera-photo-symbolic";
|
||||||
|
case UP_DEVICE_KIND_BLUETOOTH_GENERIC:
|
||||||
|
return "bluetooth-active-symbolic";
|
||||||
|
case UP_DEVICE_KIND_TOY:
|
||||||
|
case UP_DEVICE_KIND_REMOTE_CONTROL:
|
||||||
|
case UP_DEVICE_KIND_WEARABLE:
|
||||||
|
case UP_DEVICE_KIND_LAST:
|
||||||
|
default:
|
||||||
|
return "battery-symbolic";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace waybar::modules::upower
|
@ -1,10 +1,11 @@
|
|||||||
#include "modules/wlr/taskbar.hpp"
|
#include "modules/wlr/taskbar.hpp"
|
||||||
|
|
||||||
#include "glibmm/error.h"
|
#include <fmt/core.h>
|
||||||
#include "glibmm/fileutils.h"
|
#include <gdkmm/monitor.h>
|
||||||
#include "glibmm/refptr.h"
|
#include <gio/gdesktopappinfo.h>
|
||||||
#include "util/format.hpp"
|
#include <giomm/desktopappinfo.h>
|
||||||
#include "util/string.hpp"
|
#include <gtkmm/icontheme.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
@ -14,22 +15,16 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <fmt/core.h>
|
#include "glibmm/error.h"
|
||||||
#include <gdkmm/monitor.h>
|
#include "glibmm/fileutils.h"
|
||||||
|
#include "glibmm/refptr.h"
|
||||||
#include <gtkmm/icontheme.h>
|
#include "util/format.hpp"
|
||||||
|
#include "util/string.hpp"
|
||||||
#include <giomm/desktopappinfo.h>
|
|
||||||
#include <gio/gdesktopappinfo.h>
|
|
||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace waybar::modules::wlr {
|
namespace waybar::modules::wlr {
|
||||||
|
|
||||||
/* Icon loading functions */
|
/* Icon loading functions */
|
||||||
static std::vector<std::string> search_prefix()
|
static std::vector<std::string> search_prefix() {
|
||||||
{
|
|
||||||
std::vector<std::string> prefixes = {""};
|
std::vector<std::string> prefixes = {""};
|
||||||
|
|
||||||
auto xdg_data_dirs = std::getenv("XDG_DATA_DIRS");
|
auto xdg_data_dirs = std::getenv("XDG_DATA_DIRS");
|
||||||
@ -52,14 +47,12 @@ static std::vector<std::string> search_prefix()
|
|||||||
std::string home_dir = std::getenv("HOME");
|
std::string home_dir = std::getenv("HOME");
|
||||||
prefixes.push_back(home_dir + "/.local/share/");
|
prefixes.push_back(home_dir + "/.local/share/");
|
||||||
|
|
||||||
for (auto& p : prefixes)
|
for (auto &p : prefixes) spdlog::debug("Using 'desktop' search path prefix: {}", p);
|
||||||
spdlog::debug("Using 'desktop' search path prefix: {}", p);
|
|
||||||
|
|
||||||
return prefixes;
|
return prefixes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string icon_path, int size)
|
static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string icon_path, int size) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
auto pb = Gdk::Pixbuf::create_from_file(icon_path, size, size);
|
auto pb = Gdk::Pixbuf::create_from_file(icon_path, size, size);
|
||||||
return pb;
|
return pb;
|
||||||
@ -68,26 +61,19 @@ static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string icon_path, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string& app_id)
|
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string &app_id) {
|
||||||
{
|
|
||||||
static std::vector<std::string> prefixes = search_prefix();
|
static std::vector<std::string> prefixes = search_prefix();
|
||||||
|
|
||||||
std::vector<std::string> app_folders = {
|
std::vector<std::string> app_folders = {"", "applications/", "applications/kde/",
|
||||||
"",
|
"applications/org.kde."};
|
||||||
"applications/",
|
|
||||||
"applications/kde/",
|
|
||||||
"applications/org.kde."
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<std::string> suffixes = {
|
std::vector<std::string> suffixes = {"", ".desktop"};
|
||||||
"",
|
|
||||||
".desktop"
|
|
||||||
};
|
|
||||||
|
|
||||||
for (auto &prefix : prefixes) {
|
for (auto &prefix : prefixes) {
|
||||||
for (auto &folder : app_folders) {
|
for (auto &folder : app_folders) {
|
||||||
for (auto &suffix : suffixes) {
|
for (auto &suffix : suffixes) {
|
||||||
auto app_info_ = Gio::DesktopAppInfo::create_from_filename(prefix + folder + app_id + suffix);
|
auto app_info_ =
|
||||||
|
Gio::DesktopAppInfo::create_from_filename(prefix + folder + app_id + suffix);
|
||||||
if (!app_info_) {
|
if (!app_info_) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -100,8 +86,7 @@ static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string&
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Glib::RefPtr<Gio::DesktopAppInfo> get_desktop_app_info(const std::string &app_id)
|
Glib::RefPtr<Gio::DesktopAppInfo> get_desktop_app_info(const std::string &app_id) {
|
||||||
{
|
|
||||||
auto app_info = get_app_info_by_name(app_id);
|
auto app_info = get_app_info_by_name(app_id);
|
||||||
if (app_info) {
|
if (app_info) {
|
||||||
return app_info;
|
return app_info;
|
||||||
@ -137,8 +122,7 @@ void Task::set_app_info_from_app_id_list(const std::string& app_id_list) {
|
|||||||
|
|
||||||
/* Wayfire sends a list of app-id's in space separated format, other compositors
|
/* Wayfire sends a list of app-id's in space separated format, other compositors
|
||||||
* send a single app-id, but in any case this works fine */
|
* send a single app-id, but in any case this works fine */
|
||||||
while (stream >> app_id)
|
while (stream >> app_id) {
|
||||||
{
|
|
||||||
app_info_ = get_desktop_app_info(app_id);
|
app_info_ = get_desktop_app_info(app_id);
|
||||||
if (app_info_) {
|
if (app_info_) {
|
||||||
return;
|
return;
|
||||||
@ -167,19 +151,18 @@ void Task::set_app_info_from_app_id_list(const std::string& app_id_list) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
|
static std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
|
||||||
const std::string &app_id)
|
const std::string &app_id) {
|
||||||
{
|
if (icon_theme->lookup_icon(app_id, 24)) return app_id;
|
||||||
if (icon_theme->lookup_icon(app_id, 24))
|
|
||||||
return app_id;
|
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Task::image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme>& icon_theme, Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size)
|
bool Task::image_load_icon(Gtk::Image &image, const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
|
||||||
{
|
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size) {
|
||||||
std::string ret_icon_name = "unknown";
|
std::string ret_icon_name = "unknown";
|
||||||
if (app_info) {
|
if (app_info) {
|
||||||
std::string icon_name = get_icon_name_from_icon_theme(icon_theme, app_info->get_startup_wm_class());
|
std::string icon_name =
|
||||||
|
get_icon_name_from_icon_theme(icon_theme, app_info->get_startup_wm_class());
|
||||||
if (!icon_name.empty()) {
|
if (!icon_name.empty()) {
|
||||||
ret_icon_name = icon_name;
|
ret_icon_name = icon_name;
|
||||||
} else {
|
} else {
|
||||||
@ -212,48 +195,40 @@ bool Task::image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme>
|
|||||||
uint32_t Task::global_id = 0;
|
uint32_t Task::global_id = 0;
|
||||||
|
|
||||||
static void tl_handle_title(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
static void tl_handle_title(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
||||||
const char *title)
|
const char *title) {
|
||||||
{
|
|
||||||
return static_cast<Task *>(data)->handle_title(title);
|
return static_cast<Task *>(data)->handle_title(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tl_handle_app_id(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
static void tl_handle_app_id(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
||||||
const char *app_id)
|
const char *app_id) {
|
||||||
{
|
|
||||||
return static_cast<Task *>(data)->handle_app_id(app_id);
|
return static_cast<Task *>(data)->handle_app_id(app_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tl_handle_output_enter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
static void tl_handle_output_enter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
||||||
struct wl_output *output)
|
struct wl_output *output) {
|
||||||
{
|
|
||||||
return static_cast<Task *>(data)->handle_output_enter(output);
|
return static_cast<Task *>(data)->handle_output_enter(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tl_handle_output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
static void tl_handle_output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
||||||
struct wl_output *output)
|
struct wl_output *output) {
|
||||||
{
|
|
||||||
return static_cast<Task *>(data)->handle_output_leave(output);
|
return static_cast<Task *>(data)->handle_output_leave(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tl_handle_state(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
static void tl_handle_state(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
||||||
struct wl_array *state)
|
struct wl_array *state) {
|
||||||
{
|
|
||||||
return static_cast<Task *>(data)->handle_state(state);
|
return static_cast<Task *>(data)->handle_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tl_handle_done(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle)
|
static void tl_handle_done(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle) {
|
||||||
{
|
|
||||||
return static_cast<Task *>(data)->handle_done();
|
return static_cast<Task *>(data)->handle_done();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tl_handle_parent(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
static void tl_handle_parent(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
|
||||||
struct zwlr_foreign_toplevel_handle_v1 *parent)
|
struct zwlr_foreign_toplevel_handle_v1 *parent) {
|
||||||
{
|
|
||||||
/* This is explicitly left blank */
|
/* This is explicitly left blank */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tl_handle_closed(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle)
|
static void tl_handle_closed(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle) {
|
||||||
{
|
|
||||||
return static_cast<Task *>(data)->handle_closed();
|
return static_cast<Task *>(data)->handle_closed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,11 +244,14 @@ static const struct zwlr_foreign_toplevel_handle_v1_listener toplevel_handle_imp
|
|||||||
};
|
};
|
||||||
|
|
||||||
Task::Task(const waybar::Bar &bar, const Json::Value &config, Taskbar *tbar,
|
Task::Task(const waybar::Bar &bar, const Json::Value &config, Taskbar *tbar,
|
||||||
struct zwlr_foreign_toplevel_handle_v1 *tl_handle, struct wl_seat *seat) :
|
struct zwlr_foreign_toplevel_handle_v1 *tl_handle, struct wl_seat *seat)
|
||||||
bar_{bar}, config_{config}, tbar_{tbar}, handle_{tl_handle}, seat_{seat},
|
: bar_{bar},
|
||||||
|
config_{config},
|
||||||
|
tbar_{tbar},
|
||||||
|
handle_{tl_handle},
|
||||||
|
seat_{seat},
|
||||||
id_{global_id++},
|
id_{global_id++},
|
||||||
content_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0}
|
content_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0} {
|
||||||
{
|
|
||||||
zwlr_foreign_toplevel_handle_v1_add_listener(handle_, &toplevel_handle_impl, this);
|
zwlr_foreign_toplevel_handle_v1_add_listener(handle_, &toplevel_handle_impl, this);
|
||||||
|
|
||||||
button_.set_relief(Gtk::RELIEF_NONE);
|
button_.set_relief(Gtk::RELIEF_NONE);
|
||||||
@ -321,16 +299,14 @@ Task::Task(const waybar::Bar &bar, const Json::Value &config, Taskbar *tbar,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Handle click events if configured */
|
/* Handle click events if configured */
|
||||||
if (config_["on-click"].isString() || config_["on-click-middle"].isString()
|
if (config_["on-click"].isString() || config_["on-click-middle"].isString() ||
|
||||||
|| config_["on-click-right"].isString()) {
|
config_["on-click-right"].isString()) {
|
||||||
button_.add_events(Gdk::BUTTON_PRESS_MASK);
|
button_.add_events(Gdk::BUTTON_PRESS_MASK);
|
||||||
button_.signal_button_press_event().connect(
|
button_.signal_button_press_event().connect(sigc::mem_fun(*this, &Task::handle_clicked), false);
|
||||||
sigc::mem_fun(*this, &Task::handle_clicked), false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::~Task()
|
Task::~Task() {
|
||||||
{
|
|
||||||
if (handle_) {
|
if (handle_) {
|
||||||
zwlr_foreign_toplevel_handle_v1_destroy(handle_);
|
zwlr_foreign_toplevel_handle_v1_destroy(handle_);
|
||||||
handle_ = nullptr;
|
handle_ = nullptr;
|
||||||
@ -341,25 +317,19 @@ Task::~Task()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Task::repr() const
|
std::string Task::repr() const {
|
||||||
{
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Task (" << id_ << ") " << title_ << " [" << app_id_ << "] <"
|
ss << "Task (" << id_ << ") " << title_ << " [" << app_id_ << "] <" << (active() ? "A" : "a")
|
||||||
<< (active() ? "A" : "a")
|
<< (maximized() ? "M" : "m") << (minimized() ? "I" : "i") << (fullscreen() ? "F" : "f") << ">";
|
||||||
<< (maximized() ? "M" : "m")
|
|
||||||
<< (minimized() ? "I" : "i")
|
|
||||||
<< (fullscreen() ? "F" : "f")
|
|
||||||
<< ">";
|
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Task::state_string(bool shortened) const
|
std::string Task::state_string(bool shortened) const {
|
||||||
{
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if (shortened)
|
if (shortened)
|
||||||
ss << (minimized() ? "m" : "") << (maximized() ? "M" : "")
|
ss << (minimized() ? "m" : "") << (maximized() ? "M" : "") << (active() ? "A" : "")
|
||||||
<< (active() ? "A" : "") << (fullscreen() ? "F" : "");
|
<< (fullscreen() ? "F" : "");
|
||||||
else
|
else
|
||||||
ss << (minimized() ? "minimized " : "") << (maximized() ? "maximized " : "")
|
ss << (minimized() ? "minimized " : "") << (maximized() ? "maximized " : "")
|
||||||
<< (active() ? "active " : "") << (fullscreen() ? "fullscreen " : "");
|
<< (active() ? "active " : "") << (fullscreen() ? "fullscreen " : "");
|
||||||
@ -371,14 +341,12 @@ std::string Task::state_string(bool shortened) const
|
|||||||
return res.substr(0, res.size() - 1);
|
return res.substr(0, res.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::handle_title(const char *title)
|
void Task::handle_title(const char *title) {
|
||||||
{
|
|
||||||
title_ = title;
|
title_ = title;
|
||||||
hide_if_ignored();
|
hide_if_ignored();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::hide_if_ignored()
|
void Task::hide_if_ignored() {
|
||||||
{
|
|
||||||
if (tbar_->ignore_list().count(app_id_) || tbar_->ignore_list().count(title_)) {
|
if (tbar_->ignore_list().count(app_id_) || tbar_->ignore_list().count(title_)) {
|
||||||
ignored_ = true;
|
ignored_ = true;
|
||||||
if (button_visible_) {
|
if (button_visible_) {
|
||||||
@ -395,15 +363,15 @@ void Task::hide_if_ignored()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::handle_app_id(const char *app_id)
|
void Task::handle_app_id(const char *app_id) {
|
||||||
{
|
|
||||||
app_id_ = app_id;
|
app_id_ = app_id;
|
||||||
hide_if_ignored();
|
hide_if_ignored();
|
||||||
|
|
||||||
auto ids_replace_map = tbar_->app_ids_replace_map();
|
auto ids_replace_map = tbar_->app_ids_replace_map();
|
||||||
if (ids_replace_map.count(app_id_)) {
|
if (ids_replace_map.count(app_id_)) {
|
||||||
auto replaced_id = ids_replace_map[app_id_];
|
auto replaced_id = ids_replace_map[app_id_];
|
||||||
spdlog::debug(fmt::format("Task ({}) [{}] app_id was replaced with {}", id_, app_id_, replaced_id));
|
spdlog::debug(
|
||||||
|
fmt::format("Task ({}) [{}] app_id was replaced with {}", id_, app_id_, replaced_id));
|
||||||
app_id_ = replaced_id;
|
app_id_ = replaced_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,8 +401,7 @@ void Task::handle_app_id(const char *app_id)
|
|||||||
spdlog::debug("Couldn't find icon for {}", app_id_);
|
spdlog::debug("Couldn't find icon for {}", app_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::handle_output_enter(struct wl_output *output)
|
void Task::handle_output_enter(struct wl_output *output) {
|
||||||
{
|
|
||||||
if (ignored_) {
|
if (ignored_) {
|
||||||
spdlog::debug("{} is ignored", repr());
|
spdlog::debug("{} is ignored", repr());
|
||||||
return;
|
return;
|
||||||
@ -451,8 +418,7 @@ void Task::handle_output_enter(struct wl_output *output)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::handle_output_leave(struct wl_output *output)
|
void Task::handle_output_leave(struct wl_output *output) {
|
||||||
{
|
|
||||||
spdlog::debug("{} left output {}", repr(), (void *)output);
|
spdlog::debug("{} left output {}", repr(), (void *)output);
|
||||||
|
|
||||||
if (button_visible_ && !tbar_->all_outputs() && tbar_->show_output(output)) {
|
if (button_visible_ && !tbar_->all_outputs() && tbar_->show_output(output)) {
|
||||||
@ -464,25 +430,19 @@ void Task::handle_output_leave(struct wl_output *output)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::handle_state(struct wl_array *state)
|
void Task::handle_state(struct wl_array *state) {
|
||||||
{
|
|
||||||
state_ = 0;
|
state_ = 0;
|
||||||
size_t size = state->size / sizeof(uint32_t);
|
size_t size = state->size / sizeof(uint32_t);
|
||||||
for (size_t i = 0; i < size; ++i) {
|
for (size_t i = 0; i < size; ++i) {
|
||||||
auto entry = static_cast<uint32_t *>(state->data)[i];
|
auto entry = static_cast<uint32_t *>(state->data)[i];
|
||||||
if (entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED)
|
if (entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED) state_ |= MAXIMIZED;
|
||||||
state_ |= MAXIMIZED;
|
if (entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED) state_ |= MINIMIZED;
|
||||||
if (entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED)
|
if (entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED) state_ |= ACTIVE;
|
||||||
state_ |= MINIMIZED;
|
if (entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN) state_ |= FULLSCREEN;
|
||||||
if (entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED)
|
|
||||||
state_ |= ACTIVE;
|
|
||||||
if (entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN)
|
|
||||||
state_ |= FULLSCREEN;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::handle_done()
|
void Task::handle_done() {
|
||||||
{
|
|
||||||
spdlog::debug("{} changed", repr());
|
spdlog::debug("{} changed", repr());
|
||||||
|
|
||||||
if (state_ & MAXIMIZED) {
|
if (state_ & MAXIMIZED) {
|
||||||
@ -515,8 +475,7 @@ void Task::handle_done()
|
|||||||
tbar_->dp.emit();
|
tbar_->dp.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::handle_closed()
|
void Task::handle_closed() {
|
||||||
{
|
|
||||||
spdlog::debug("{} closed", repr());
|
spdlog::debug("{} closed", repr());
|
||||||
zwlr_foreign_toplevel_handle_v1_destroy(handle_);
|
zwlr_foreign_toplevel_handle_v1_destroy(handle_);
|
||||||
handle_ = nullptr;
|
handle_ = nullptr;
|
||||||
@ -527,8 +486,7 @@ void Task::handle_closed()
|
|||||||
tbar_->remove_task(id_);
|
tbar_->remove_task(id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Task::handle_clicked(GdkEventButton *bt)
|
bool Task::handle_clicked(GdkEventButton *bt) {
|
||||||
{
|
|
||||||
std::string action;
|
std::string action;
|
||||||
if (config_["on-click"].isString() && bt->button == 1)
|
if (config_["on-click"].isString() && bt->button == 1)
|
||||||
action = config_["on-click"].asString();
|
action = config_["on-click"].asString();
|
||||||
@ -550,8 +508,7 @@ bool Task::handle_clicked(GdkEventButton *bt)
|
|||||||
minimize(true);
|
minimize(true);
|
||||||
else
|
else
|
||||||
activate();
|
activate();
|
||||||
}
|
} else if (action == "maximize")
|
||||||
else if (action == "maximize")
|
|
||||||
maximize(!maximized());
|
maximize(!maximized());
|
||||||
else if (action == "fullscreen")
|
else if (action == "fullscreen")
|
||||||
fullscreen(!fullscreen());
|
fullscreen(!fullscreen());
|
||||||
@ -563,18 +520,11 @@ bool Task::handle_clicked(GdkEventButton *bt)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Task::operator==(const Task &o) const
|
bool Task::operator==(const Task &o) const { return o.id_ == id_; }
|
||||||
{
|
|
||||||
return o.id_ == id_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Task::operator!=(const Task &o) const
|
bool Task::operator!=(const Task &o) const { return o.id_ != id_; }
|
||||||
{
|
|
||||||
return o.id_ != id_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Task::update()
|
void Task::update() {
|
||||||
{
|
|
||||||
bool markup = config_["markup"].isBool() ? config_["markup"].asBool() : false;
|
bool markup = config_["markup"].isBool() ? config_["markup"].asBool() : false;
|
||||||
std::string title = title_;
|
std::string title = title_;
|
||||||
std::string name = name_;
|
std::string name = name_;
|
||||||
@ -585,13 +535,9 @@ void Task::update()
|
|||||||
app_id = Glib::Markup::escape_text(app_id);
|
app_id = Glib::Markup::escape_text(app_id);
|
||||||
}
|
}
|
||||||
if (!format_before_.empty()) {
|
if (!format_before_.empty()) {
|
||||||
auto txt = fmt::format(format_before_,
|
auto txt = fmt::format(format_before_, fmt::arg("title", title), fmt::arg("name", name),
|
||||||
fmt::arg("title", title),
|
fmt::arg("app_id", app_id), fmt::arg("state", state_string()),
|
||||||
fmt::arg("name", name),
|
fmt::arg("short_state", state_string(true)));
|
||||||
fmt::arg("app_id", app_id),
|
|
||||||
fmt::arg("state", state_string()),
|
|
||||||
fmt::arg("short_state", state_string(true))
|
|
||||||
);
|
|
||||||
if (markup)
|
if (markup)
|
||||||
text_before_.set_markup(txt);
|
text_before_.set_markup(txt);
|
||||||
else
|
else
|
||||||
@ -599,13 +545,9 @@ void Task::update()
|
|||||||
text_before_.show();
|
text_before_.show();
|
||||||
}
|
}
|
||||||
if (!format_after_.empty()) {
|
if (!format_after_.empty()) {
|
||||||
auto txt = fmt::format(format_after_,
|
auto txt = fmt::format(format_after_, fmt::arg("title", title), fmt::arg("name", name),
|
||||||
fmt::arg("title", title),
|
fmt::arg("app_id", app_id), fmt::arg("state", state_string()),
|
||||||
fmt::arg("name", name),
|
fmt::arg("short_state", state_string(true)));
|
||||||
fmt::arg("app_id", app_id),
|
|
||||||
fmt::arg("state", state_string()),
|
|
||||||
fmt::arg("short_state", state_string(true))
|
|
||||||
);
|
|
||||||
if (markup)
|
if (markup)
|
||||||
text_after_.set_markup(txt);
|
text_after_.set_markup(txt);
|
||||||
else
|
else
|
||||||
@ -614,13 +556,9 @@ void Task::update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!format_tooltip_.empty()) {
|
if (!format_tooltip_.empty()) {
|
||||||
auto txt = fmt::format(format_tooltip_,
|
auto txt = fmt::format(format_tooltip_, fmt::arg("title", title), fmt::arg("name", name),
|
||||||
fmt::arg("title", title),
|
fmt::arg("app_id", app_id), fmt::arg("state", state_string()),
|
||||||
fmt::arg("name", name),
|
fmt::arg("short_state", state_string(true)));
|
||||||
fmt::arg("app_id", app_id),
|
|
||||||
fmt::arg("state", state_string()),
|
|
||||||
fmt::arg("short_state", state_string(true))
|
|
||||||
);
|
|
||||||
if (markup)
|
if (markup)
|
||||||
button_.set_tooltip_markup(txt);
|
button_.set_tooltip_markup(txt);
|
||||||
else
|
else
|
||||||
@ -628,30 +566,25 @@ void Task::update()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::maximize(bool set)
|
void Task::maximize(bool set) {
|
||||||
{
|
|
||||||
if (set)
|
if (set)
|
||||||
zwlr_foreign_toplevel_handle_v1_set_maximized(handle_);
|
zwlr_foreign_toplevel_handle_v1_set_maximized(handle_);
|
||||||
else
|
else
|
||||||
zwlr_foreign_toplevel_handle_v1_unset_maximized(handle_);
|
zwlr_foreign_toplevel_handle_v1_unset_maximized(handle_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::minimize(bool set)
|
void Task::minimize(bool set) {
|
||||||
{
|
|
||||||
if (set)
|
if (set)
|
||||||
zwlr_foreign_toplevel_handle_v1_set_minimized(handle_);
|
zwlr_foreign_toplevel_handle_v1_set_minimized(handle_);
|
||||||
else
|
else
|
||||||
zwlr_foreign_toplevel_handle_v1_unset_minimized(handle_);
|
zwlr_foreign_toplevel_handle_v1_unset_minimized(handle_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::activate()
|
void Task::activate() { zwlr_foreign_toplevel_handle_v1_activate(handle_, seat_); }
|
||||||
{
|
|
||||||
zwlr_foreign_toplevel_handle_v1_activate(handle_, seat_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Task::fullscreen(bool set)
|
void Task::fullscreen(bool set) {
|
||||||
{
|
if (zwlr_foreign_toplevel_handle_v1_get_version(handle_) <
|
||||||
if (zwlr_foreign_toplevel_handle_v1_get_version(handle_) < ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_FULLSCREEN_SINCE_VERSION) {
|
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_FULLSCREEN_SINCE_VERSION) {
|
||||||
spdlog::warn("Foreign toplevel manager server does not support for set/unset fullscreen.");
|
spdlog::warn("Foreign toplevel manager server does not support for set/unset fullscreen.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -662,16 +595,11 @@ void Task::fullscreen(bool set)
|
|||||||
zwlr_foreign_toplevel_handle_v1_unset_fullscreen(handle_);
|
zwlr_foreign_toplevel_handle_v1_unset_fullscreen(handle_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::close()
|
void Task::close() { zwlr_foreign_toplevel_handle_v1_close(handle_); }
|
||||||
{
|
|
||||||
zwlr_foreign_toplevel_handle_v1_close(handle_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Taskbar class implementation */
|
/* Taskbar class implementation */
|
||||||
static void handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
static void handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
const char *interface, uint32_t version)
|
const char *interface, uint32_t version) {
|
||||||
{
|
|
||||||
if (std::strcmp(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0) {
|
if (std::strcmp(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0) {
|
||||||
static_cast<Taskbar *>(data)->register_manager(registry, name, version);
|
static_cast<Taskbar *>(data)->register_manager(registry, name, version);
|
||||||
} else if (std::strcmp(interface, wl_seat_interface.name) == 0) {
|
} else if (std::strcmp(interface, wl_seat_interface.name) == 0) {
|
||||||
@ -679,22 +607,19 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
|
static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
|
||||||
{
|
|
||||||
/* Nothing to do here */
|
/* Nothing to do here */
|
||||||
}
|
}
|
||||||
|
|
||||||
static const wl_registry_listener registry_listener_impl = {
|
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
|
||||||
.global = handle_global,
|
.global_remove = handle_global_remove};
|
||||||
.global_remove = handle_global_remove
|
|
||||||
};
|
|
||||||
|
|
||||||
Taskbar::Taskbar(const std::string &id, const waybar::Bar &bar, const Json::Value &config)
|
Taskbar::Taskbar(const std::string &id, const waybar::Bar &bar, const Json::Value &config)
|
||||||
: waybar::AModule(config, "taskbar", id, false, false),
|
: waybar::AModule(config, "taskbar", id, false, false),
|
||||||
bar_(bar),
|
bar_(bar),
|
||||||
box_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0},
|
box_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0},
|
||||||
manager_{nullptr}, seat_{nullptr}
|
manager_{nullptr},
|
||||||
{
|
seat_{nullptr} {
|
||||||
box_.set_name("taskbar");
|
box_.set_name("taskbar");
|
||||||
if (!id.empty()) {
|
if (!id.empty()) {
|
||||||
box_.get_style_context()->add_class(id);
|
box_.get_style_context()->add_class(id);
|
||||||
@ -756,8 +681,7 @@ Taskbar::Taskbar(const std::string &id, const waybar::Bar &bar, const Json::Valu
|
|||||||
icon_themes_.push_back(Gtk::IconTheme::get_default());
|
icon_themes_.push_back(Gtk::IconTheme::get_default());
|
||||||
}
|
}
|
||||||
|
|
||||||
Taskbar::~Taskbar()
|
Taskbar::~Taskbar() {
|
||||||
{
|
|
||||||
if (manager_) {
|
if (manager_) {
|
||||||
struct wl_display *display = Client::inst()->wl_display;
|
struct wl_display *display = Client::inst()->wl_display;
|
||||||
/*
|
/*
|
||||||
@ -776,8 +700,7 @@ Taskbar::~Taskbar()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Taskbar::update()
|
void Taskbar::update() {
|
||||||
{
|
|
||||||
for (auto &t : tasks_) {
|
for (auto &t : tasks_) {
|
||||||
t->update();
|
t->update();
|
||||||
}
|
}
|
||||||
@ -786,13 +709,11 @@ void Taskbar::update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void tm_handle_toplevel(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager,
|
static void tm_handle_toplevel(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager,
|
||||||
struct zwlr_foreign_toplevel_handle_v1 *tl_handle)
|
struct zwlr_foreign_toplevel_handle_v1 *tl_handle) {
|
||||||
{
|
|
||||||
return static_cast<Taskbar *>(data)->handle_toplevel_create(tl_handle);
|
return static_cast<Taskbar *>(data)->handle_toplevel_create(tl_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tm_handle_finished(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager)
|
static void tm_handle_finished(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager) {
|
||||||
{
|
|
||||||
return static_cast<Taskbar *>(data)->handle_finished();
|
return static_cast<Taskbar *>(data)->handle_finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,22 +722,23 @@ static const struct zwlr_foreign_toplevel_manager_v1_listener toplevel_manager_i
|
|||||||
.finished = tm_handle_finished,
|
.finished = tm_handle_finished,
|
||||||
};
|
};
|
||||||
|
|
||||||
void Taskbar::register_manager(struct wl_registry *registry, uint32_t name, uint32_t version)
|
void Taskbar::register_manager(struct wl_registry *registry, uint32_t name, uint32_t version) {
|
||||||
{
|
|
||||||
if (manager_) {
|
if (manager_) {
|
||||||
spdlog::warn("Register foreign toplevel manager again although already existing!");
|
spdlog::warn("Register foreign toplevel manager again although already existing!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (version < ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_FULLSCREEN_SINCE_VERSION) {
|
if (version < ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SET_FULLSCREEN_SINCE_VERSION) {
|
||||||
spdlog::warn("Foreign toplevel manager server does not have the appropriate version."
|
spdlog::warn(
|
||||||
" To be able to use all features, you need at least version 2, but server is version {}", version);
|
"Foreign toplevel manager server does not have the appropriate version."
|
||||||
|
" To be able to use all features, you need at least version 2, but server is version {}",
|
||||||
|
version);
|
||||||
}
|
}
|
||||||
|
|
||||||
// limit version to a highest supported by the client protocol file
|
// limit version to a highest supported by the client protocol file
|
||||||
version = std::min<uint32_t>(version, zwlr_foreign_toplevel_manager_v1_interface.version);
|
version = std::min<uint32_t>(version, zwlr_foreign_toplevel_manager_v1_interface.version);
|
||||||
|
|
||||||
manager_ = static_cast<struct zwlr_foreign_toplevel_manager_v1 *>(wl_registry_bind(registry, name,
|
manager_ = static_cast<struct zwlr_foreign_toplevel_manager_v1 *>(
|
||||||
&zwlr_foreign_toplevel_manager_v1_interface, version));
|
wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, version));
|
||||||
|
|
||||||
if (manager_)
|
if (manager_)
|
||||||
zwlr_foreign_toplevel_manager_v1_add_listener(manager_, &toplevel_manager_impl, this);
|
zwlr_foreign_toplevel_manager_v1_add_listener(manager_, &toplevel_manager_impl, this);
|
||||||
@ -824,8 +746,7 @@ void Taskbar::register_manager(struct wl_registry *registry, uint32_t name, uint
|
|||||||
spdlog::debug("Failed to register manager");
|
spdlog::debug("Failed to register manager");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Taskbar::register_seat(struct wl_registry *registry, uint32_t name, uint32_t version)
|
void Taskbar::register_seat(struct wl_registry *registry, uint32_t name, uint32_t version) {
|
||||||
{
|
|
||||||
if (seat_) {
|
if (seat_) {
|
||||||
spdlog::warn("Register seat again although already existing!");
|
spdlog::warn("Register seat again although already existing!");
|
||||||
return;
|
return;
|
||||||
@ -835,34 +756,22 @@ void Taskbar::register_seat(struct wl_registry *registry, uint32_t name, uint32_
|
|||||||
seat_ = static_cast<wl_seat *>(wl_registry_bind(registry, name, &wl_seat_interface, version));
|
seat_ = static_cast<wl_seat *>(wl_registry_bind(registry, name, &wl_seat_interface, version));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Taskbar::handle_toplevel_create(struct zwlr_foreign_toplevel_handle_v1 *tl_handle)
|
void Taskbar::handle_toplevel_create(struct zwlr_foreign_toplevel_handle_v1 *tl_handle) {
|
||||||
{
|
|
||||||
tasks_.push_back(std::make_unique<Task>(bar_, config_, this, tl_handle, seat_));
|
tasks_.push_back(std::make_unique<Task>(bar_, config_, this, tl_handle, seat_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Taskbar::handle_finished()
|
void Taskbar::handle_finished() {
|
||||||
{
|
|
||||||
zwlr_foreign_toplevel_manager_v1_destroy(manager_);
|
zwlr_foreign_toplevel_manager_v1_destroy(manager_);
|
||||||
manager_ = nullptr;
|
manager_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Taskbar::add_button(Gtk::Button &bt)
|
void Taskbar::add_button(Gtk::Button &bt) { box_.pack_start(bt, false, false); }
|
||||||
{
|
|
||||||
box_.pack_start(bt, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Taskbar::move_button(Gtk::Button &bt, int pos)
|
void Taskbar::move_button(Gtk::Button &bt, int pos) { box_.reorder_child(bt, pos); }
|
||||||
{
|
|
||||||
box_.reorder_child(bt, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Taskbar::remove_button(Gtk::Button &bt)
|
void Taskbar::remove_button(Gtk::Button &bt) { box_.remove(bt); }
|
||||||
{
|
|
||||||
box_.remove(bt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Taskbar::remove_task(uint32_t id)
|
void Taskbar::remove_task(uint32_t id) {
|
||||||
{
|
|
||||||
auto it = std::find_if(std::begin(tasks_), std::end(tasks_),
|
auto it = std::find_if(std::begin(tasks_), std::end(tasks_),
|
||||||
[id](const TaskPtr &p) { return p->id() == id; });
|
[id](const TaskPtr &p) { return p->id() == id; });
|
||||||
|
|
||||||
@ -874,20 +783,22 @@ void Taskbar::remove_task(uint32_t id)
|
|||||||
tasks_.erase(it);
|
tasks_.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Taskbar::show_output(struct wl_output *output) const
|
bool Taskbar::show_output(struct wl_output *output) const {
|
||||||
{
|
|
||||||
return output == gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
return output == gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Taskbar::all_outputs() const
|
bool Taskbar::all_outputs() const {
|
||||||
{
|
|
||||||
return config_["all-outputs"].isBool() && config_["all-outputs"].asBool();
|
return config_["all-outputs"].isBool() && config_["all-outputs"].asBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<Glib::RefPtr<Gtk::IconTheme>>& Taskbar::icon_themes() const { return icon_themes_; }
|
const std::vector<Glib::RefPtr<Gtk::IconTheme>> &Taskbar::icon_themes() const {
|
||||||
|
return icon_themes_;
|
||||||
|
}
|
||||||
|
|
||||||
const std::unordered_set<std::string> &Taskbar::ignore_list() const { return ignore_list_; }
|
const std::unordered_set<std::string> &Taskbar::ignore_list() const { return ignore_list_; }
|
||||||
|
|
||||||
const std::map<std::string, std::string>& Taskbar::app_ids_replace_map() const { return app_ids_replace_map_; }
|
const std::map<std::string, std::string> &Taskbar::app_ids_replace_map() const {
|
||||||
|
return app_ids_replace_map_;
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace waybar::modules::wlr */
|
} /* namespace waybar::modules::wlr */
|
||||||
|
@ -156,8 +156,7 @@ WorkspaceManager::~WorkspaceManager() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto WorkspaceManager::remove_workspace_group(uint32_t id) -> void {
|
auto WorkspaceManager::remove_workspace_group(uint32_t id) -> void {
|
||||||
auto it = std::find_if(groups_.begin(),
|
auto it = std::find_if(groups_.begin(), groups_.end(),
|
||||||
groups_.end(),
|
|
||||||
[id](const std::unique_ptr<WorkspaceGroup> &g) { return g->id() == id; });
|
[id](const std::unique_ptr<WorkspaceGroup> &g) { return g->id() == id; });
|
||||||
|
|
||||||
if (it == groups_.end()) {
|
if (it == groups_.end()) {
|
||||||
@ -257,8 +256,7 @@ auto WorkspaceGroup::update() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto WorkspaceGroup::remove_workspace(uint32_t id) -> void {
|
auto WorkspaceGroup::remove_workspace(uint32_t id) -> void {
|
||||||
auto it = std::find_if(workspaces_.begin(),
|
auto it = std::find_if(workspaces_.begin(), workspaces_.end(),
|
||||||
workspaces_.end(),
|
|
||||||
[id](const std::unique_ptr<Workspace> &w) { return w->id() == id; });
|
[id](const std::unique_ptr<Workspace> &w) { return w->id() == id; });
|
||||||
|
|
||||||
if (it == workspaces_.end()) {
|
if (it == workspaces_.end()) {
|
||||||
@ -353,8 +351,8 @@ Workspace::~Workspace() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto Workspace::update() -> void {
|
auto Workspace::update() -> void {
|
||||||
label_.set_markup(fmt::format(
|
label_.set_markup(fmt::format(format_, fmt::arg("name", name_),
|
||||||
format_, fmt::arg("name", name_), fmt::arg("icon", with_icon_ ? get_icon() : "")));
|
fmt::arg("icon", with_icon_ ? get_icon() : "")));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspace::handle_state(const std::vector<uint32_t> &state) -> void {
|
auto Workspace::handle_state(const std::vector<uint32_t> &state) -> void {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "modules/wlr/workspace_manager_binding.hpp"
|
#include "modules/wlr/workspace_manager_binding.hpp"
|
||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
|
@ -39,8 +39,8 @@ waybar::util::Rfkill::Rfkill(const enum rfkill_type rfkill_type) : rfkill_type_(
|
|||||||
fd_ = -1;
|
fd_ = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Glib::signal_io().connect(
|
Glib::signal_io().connect(sigc::mem_fun(*this, &Rfkill::on_event), fd_,
|
||||||
sigc::mem_fun(*this, &Rfkill::on_event), fd_, Glib::IO_IN | Glib::IO_ERR | Glib::IO_HUP);
|
Glib::IO_IN | Glib::IO_ERR | Glib::IO_HUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
waybar::util::Rfkill::~Rfkill() {
|
waybar::util::Rfkill::~Rfkill() {
|
||||||
|
Reference in New Issue
Block a user