pull/3064/head
commit
c0d3b6f0ab
|
@ -8,7 +8,7 @@
|
||||||
- Sway (Workspaces, Binding mode, Focused window name)
|
- Sway (Workspaces, Binding mode, Focused window name)
|
||||||
- River (Mapping mode, Tags, Focused window name)
|
- River (Mapping mode, Tags, Focused window name)
|
||||||
- Hyprland (Window Icons, Workspaces, Focused window name)
|
- Hyprland (Window Icons, Workspaces, Focused window name)
|
||||||
- DWL (Tags) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc)
|
- DWL (Tags, Focused window name) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc)
|
||||||
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
|
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
|
||||||
- Local time
|
- Local time
|
||||||
- Battery
|
- Battery
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "AAppIconLabel.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "dwl-ipc-unstable-v2-client-protocol.h"
|
||||||
|
#include "util/json.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::dwl {
|
||||||
|
|
||||||
|
class Window : public AAppIconLabel, public sigc::trackable {
|
||||||
|
public:
|
||||||
|
Window(const std::string &, const waybar::Bar &, const Json::Value &);
|
||||||
|
virtual ~Window() = default;
|
||||||
|
|
||||||
|
void handle_layout(const uint32_t layout);
|
||||||
|
void handle_title(const char *title);
|
||||||
|
void handle_appid(const char *ppid);
|
||||||
|
void handle_layout_symbol(const char *layout_symbol);
|
||||||
|
void handle_frame();
|
||||||
|
|
||||||
|
struct zdwl_ipc_manager_v2 *status_manager_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Bar &bar_;
|
||||||
|
|
||||||
|
std::string title_;
|
||||||
|
std::string appid_;
|
||||||
|
std::string layout_symbol_;
|
||||||
|
uint32_t layout_;
|
||||||
|
|
||||||
|
struct zdwl_ipc_output_v2 *output_status_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::dwl
|
|
@ -127,6 +127,7 @@ class Workspaces : public AModule, public EventHandler {
|
||||||
auto allOutputs() const -> bool { return m_allOutputs; }
|
auto allOutputs() const -> bool { return m_allOutputs; }
|
||||||
auto showSpecial() const -> bool { return m_showSpecial; }
|
auto showSpecial() const -> bool { return m_showSpecial; }
|
||||||
auto activeOnly() const -> bool { return m_activeOnly; }
|
auto activeOnly() const -> bool { return m_activeOnly; }
|
||||||
|
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
|
||||||
|
|
||||||
auto getBarOutput() const -> std::string { return m_bar.output->name; }
|
auto getBarOutput() const -> std::string { return m_bar.output->name; }
|
||||||
|
|
||||||
|
@ -183,6 +184,7 @@ class Workspaces : public AModule, public EventHandler {
|
||||||
bool m_allOutputs = false;
|
bool m_allOutputs = false;
|
||||||
bool m_showSpecial = false;
|
bool m_showSpecial = false;
|
||||||
bool m_activeOnly = false;
|
bool m_activeOnly = false;
|
||||||
|
bool m_moveToMonitor = false;
|
||||||
Json::Value m_persistentWorkspaceConfig;
|
Json::Value m_persistentWorkspaceConfig;
|
||||||
|
|
||||||
// Map for windows stored in workspaces not present in the current bar.
|
// Map for windows stored in workspaces not present in the current bar.
|
||||||
|
|
|
@ -71,6 +71,7 @@ class UPower : public AModule {
|
||||||
GDBusConnection *login1_connection;
|
GDBusConnection *login1_connection;
|
||||||
std::unique_ptr<UPowerTooltip> upower_tooltip;
|
std::unique_ptr<UPowerTooltip> upower_tooltip;
|
||||||
std::string lastStatus;
|
std::string lastStatus;
|
||||||
|
const char *lastWarningLevel;
|
||||||
bool showAltText;
|
bool showAltText;
|
||||||
bool showIcon = true;
|
bool showIcon = true;
|
||||||
bool upowerRunning;
|
bool upowerRunning;
|
||||||
|
|
|
@ -17,12 +17,15 @@ class Wireplumber : public ALabel {
|
||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadRequiredApiModules();
|
void asyncLoadRequiredApiModules();
|
||||||
void prepare();
|
void prepare();
|
||||||
void activatePlugins();
|
void activatePlugins();
|
||||||
static void updateVolume(waybar::modules::Wireplumber* self, uint32_t id);
|
static void updateVolume(waybar::modules::Wireplumber* self, uint32_t id);
|
||||||
static void updateNodeName(waybar::modules::Wireplumber* self, uint32_t id);
|
static void updateNodeName(waybar::modules::Wireplumber* self, uint32_t id);
|
||||||
static void onPluginActivated(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
|
static void onPluginActivated(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
|
||||||
|
static void onDefaultNodesApiLoaded(WpObject* p, GAsyncResult* res,
|
||||||
|
waybar::modules::Wireplumber* self);
|
||||||
|
static void onMixerApiLoaded(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
|
||||||
static void onObjectManagerInstalled(waybar::modules::Wireplumber* self);
|
static void onObjectManagerInstalled(waybar::modules::Wireplumber* self);
|
||||||
static void onMixerChanged(waybar::modules::Wireplumber* self, uint32_t id);
|
static void onMixerChanged(waybar::modules::Wireplumber* self, uint32_t id);
|
||||||
static void onDefaultNodesApiChanged(waybar::modules::Wireplumber* self);
|
static void onDefaultNodesApiChanged(waybar::modules::Wireplumber* self);
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
std::scoped_lock<std::mutex> lock((backend).udev_thread_mutex_); \
|
std::scoped_lock<std::mutex> lock((backend).udev_thread_mutex_); \
|
||||||
__devices = (backend).devices_; \
|
__devices = (backend).devices_; \
|
||||||
} \
|
} \
|
||||||
auto varname = (backend).best_device(__devices.cbegin(), __devices.cend(), preferred_device);
|
auto varname = (backend).best_device(__devices, preferred_device);
|
||||||
|
|
||||||
namespace waybar::util {
|
namespace waybar::util {
|
||||||
|
|
||||||
|
@ -61,16 +61,10 @@ class BacklightBackend {
|
||||||
void set_scaled_brightness(std::string preferred_device, int brightness);
|
void set_scaled_brightness(std::string preferred_device, int brightness);
|
||||||
int get_scaled_brightness(std::string preferred_device);
|
int get_scaled_brightness(std::string preferred_device);
|
||||||
|
|
||||||
template <class ForwardIt, class Inserter>
|
|
||||||
static void upsert_device(ForwardIt first, ForwardIt last, Inserter inserter, udev_device *dev);
|
|
||||||
|
|
||||||
template <class ForwardIt, class Inserter>
|
|
||||||
static void enumerate_devices(ForwardIt first, ForwardIt last, Inserter inserter, udev *udev);
|
|
||||||
|
|
||||||
bool is_login_proxy_initialized() const { return static_cast<bool>(login_proxy_); }
|
bool is_login_proxy_initialized() const { return static_cast<bool>(login_proxy_); }
|
||||||
|
|
||||||
template <class ForwardIt>
|
static const BacklightDevice *best_device(const std::vector<BacklightDevice> &devices,
|
||||||
static const BacklightDevice *best_device(ForwardIt first, ForwardIt last, std::string_view);
|
std::string_view);
|
||||||
|
|
||||||
std::vector<BacklightDevice> devices_;
|
std::vector<BacklightDevice> devices_;
|
||||||
std::mutex udev_thread_mutex_;
|
std::mutex udev_thread_mutex_;
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
waybar-dwl-window(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - dwl window module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *window* module displays the title of the currently focused window in DWL
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
Addressed by *dwl/window*
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {title} ++
|
||||||
|
The format, how information should be displayed.
|
||||||
|
|
||||||
|
*rotate*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
Positive value to rotate the text label.
|
||||||
|
|
||||||
|
*max-length*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
The maximum length in character the module should display.
|
||||||
|
|
||||||
|
*min-length*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
The minimum length in characters the module should accept.
|
||||||
|
|
||||||
|
*align*: ++
|
||||||
|
typeof: float ++
|
||||||
|
The alignment of the label within the module, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*justify*: ++
|
||||||
|
typeof: string ++
|
||||||
|
The alignment of the text within the module's label, allowing options 'left', 'right', or 'center' to define the positioning.
|
||||||
|
|
||||||
|
*on-click*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when clicked on the module.
|
||||||
|
|
||||||
|
*on-click-middle*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when middle-clicked on the module using mousewheel.
|
||||||
|
|
||||||
|
*on-click-right*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when you right-click on the module.
|
||||||
|
|
||||||
|
*on-update*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when the module is updated.
|
||||||
|
|
||||||
|
*on-scroll-up*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when scrolling up on the module.
|
||||||
|
|
||||||
|
*on-scroll-down*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when scrolling down on the module.
|
||||||
|
|
||||||
|
*smooth-scrolling-threshold*: ++
|
||||||
|
typeof: double ++
|
||||||
|
Threshold to be used when scrolling.
|
||||||
|
|
||||||
|
*tooltip*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*rewrite*: ++
|
||||||
|
typeof: object ++
|
||||||
|
Rules to rewrite the module format output. See *rewrite rules*.
|
||||||
|
|
||||||
|
*icon*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
Option to hide the application icon.
|
||||||
|
|
||||||
|
*icon-size*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
default: 24 ++
|
||||||
|
Option to change the size of the application icon.
|
||||||
|
|
||||||
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
*{title}*: The title of the focused window.
|
||||||
|
|
||||||
|
*{app_id}*: The app_id of the focused window.
|
||||||
|
|
||||||
|
*{layout}*: The layout of the focused window.
|
||||||
|
|
||||||
|
# REWRITE RULES
|
||||||
|
|
||||||
|
*rewrite* is an object where keys are regular expressions and values are
|
||||||
|
rewrite rules if the expression matches. Rules may contain references to
|
||||||
|
captures of the expression.
|
||||||
|
|
||||||
|
Regular expression and replacement follow ECMA-script rules.
|
||||||
|
|
||||||
|
If no expression matches, the format output is left unchanged.
|
||||||
|
|
||||||
|
Invalid expressions (e.g., mismatched parentheses) are skipped.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"dwl/window": {
|
||||||
|
"format": "{}",
|
||||||
|
"max-length": 50,
|
||||||
|
"rewrite": {
|
||||||
|
"(.*) - Mozilla Firefox": "🌎 $1",
|
||||||
|
"(.*) - zsh": "> [$1]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
|
@ -52,6 +52,13 @@ Addressed by *hyprland/workspaces*
|
||||||
default: false ++
|
default: false ++
|
||||||
If set to true, only the active workspace will be shown.
|
If set to true, only the active workspace will be shown.
|
||||||
|
|
||||||
|
*move-to-monitor*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If set to true, open the workspace on the current monitor when clicking on a workspace button.
|
||||||
|
Otherwise, the workspace will open on the monitor where it was previously assigned.
|
||||||
|
Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland.
|
||||||
|
|
||||||
*ignore-workspaces*: ++
|
*ignore-workspaces*: ++
|
||||||
typeof: array ++
|
typeof: array ++
|
||||||
default: [] ++
|
default: [] ++
|
||||||
|
|
|
@ -182,5 +182,6 @@ n.b.: the list of outputs can be obtained from command line using *swaymsg -t ge
|
||||||
- *#workspaces button.focused*
|
- *#workspaces button.focused*
|
||||||
- *#workspaces button.urgent*
|
- *#workspaces button.urgent*
|
||||||
- *#workspaces button.persistent*
|
- *#workspaces button.persistent*
|
||||||
|
- *#workspaces button.empty*
|
||||||
- *#workspaces button.current_output*
|
- *#workspaces button.current_output*
|
||||||
- *#workspaces button#sway-workspace-${name}*
|
- *#workspaces button#sway-workspace-${name}*
|
||||||
|
|
|
@ -310,6 +310,7 @@ A group may hide all but one element, showing them only on mouse hover. In order
|
||||||
- *waybar-custom(5)*
|
- *waybar-custom(5)*
|
||||||
- *waybar-disk(5)*
|
- *waybar-disk(5)*
|
||||||
- *waybar-dwl-tags(5)*
|
- *waybar-dwl-tags(5)*
|
||||||
|
- *waybar-dwl-window(5)*
|
||||||
- *waybar-gamemode(5)*
|
- *waybar-gamemode(5)*
|
||||||
- *waybar-hyprland-language(5)*
|
- *waybar-hyprland-language(5)*
|
||||||
- *waybar-hyprland-submap(5)*
|
- *waybar-hyprland-submap(5)*
|
||||||
|
|
|
@ -92,7 +92,7 @@ libevdev = dependency('libevdev', required: get_option('libevdev'))
|
||||||
libmpdclient = dependency('libmpdclient', required: get_option('mpd'))
|
libmpdclient = dependency('libmpdclient', required: get_option('mpd'))
|
||||||
xkbregistry = dependency('xkbregistry')
|
xkbregistry = dependency('xkbregistry')
|
||||||
libjack = dependency('jack', required: get_option('jack'))
|
libjack = dependency('jack', required: get_option('jack'))
|
||||||
libwireplumber = dependency('wireplumber-0.4', required: get_option('wireplumber'))
|
libwireplumber = dependency('wireplumber-0.5', required: get_option('wireplumber'))
|
||||||
|
|
||||||
libsndio = compiler.find_library('sndio', required: get_option('sndio'))
|
libsndio = compiler.find_library('sndio', required: get_option('sndio'))
|
||||||
if libsndio.found()
|
if libsndio.found()
|
||||||
|
@ -293,7 +293,9 @@ endif
|
||||||
if true
|
if true
|
||||||
add_project_arguments('-DHAVE_DWL', language: 'cpp')
|
add_project_arguments('-DHAVE_DWL', language: 'cpp')
|
||||||
src_files += files('src/modules/dwl/tags.cpp')
|
src_files += files('src/modules/dwl/tags.cpp')
|
||||||
|
src_files += files('src/modules/dwl/window.cpp')
|
||||||
man_files += files('man/waybar-dwl-tags.5.scd')
|
man_files += files('man/waybar-dwl-tags.5.scd')
|
||||||
|
man_files += files('man/waybar-dwl-window.5.scd')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if true
|
if true
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_DWL
|
#ifdef HAVE_DWL
|
||||||
#include "modules/dwl/tags.hpp"
|
#include "modules/dwl/tags.hpp"
|
||||||
|
#include "modules/dwl/window.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_HYPRLAND
|
#ifdef HAVE_HYPRLAND
|
||||||
#include "modules/hyprland/language.hpp"
|
#include "modules/hyprland/language.hpp"
|
||||||
|
@ -187,6 +188,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
|
||||||
if (ref == "dwl/tags") {
|
if (ref == "dwl/tags") {
|
||||||
return new waybar::modules::dwl::Tags(id, bar_, config_[name]);
|
return new waybar::modules::dwl::Tags(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
|
if (ref == "dwl/window") {
|
||||||
|
return new waybar::modules::dwl::Window(id, bar_, config_[name]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_HYPRLAND
|
#ifdef HAVE_HYPRLAND
|
||||||
if (ref == "hyprland/window") {
|
if (ref == "hyprland/window") {
|
||||||
|
|
|
@ -21,11 +21,11 @@ wl_array tags, layouts;
|
||||||
|
|
||||||
static uint num_tags = 0;
|
static uint num_tags = 0;
|
||||||
|
|
||||||
void toggle_visibility(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
|
static void toggle_visibility(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
void active(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t active) {
|
static void active(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t active) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,15 +37,15 @@ static void set_tag(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t tag
|
||||||
: num_tags & ~(1 << tag);
|
: num_tags & ~(1 << tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_layout_symbol(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *layout) {
|
static void set_layout_symbol(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *layout) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
void title(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *title) {
|
static void title(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *title) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
void dwl_frame(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
|
static void dwl_frame(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
|
||||||
// Intentionally empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +97,7 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
|
||||||
output_status_{nullptr} {
|
output_status_{nullptr} {
|
||||||
struct wl_display *display = Client::inst()->wl_display;
|
struct wl_display *display = Client::inst()->wl_display;
|
||||||
struct wl_registry *registry = wl_display_get_registry(display);
|
struct wl_registry *registry = wl_display_get_registry(display);
|
||||||
|
|
||||||
wl_registry_add_listener(registry, ®istry_listener_impl, this);
|
wl_registry_add_listener(registry, ®istry_listener_impl, this);
|
||||||
wl_display_roundtrip(display);
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
@ -155,7 +156,7 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
|
||||||
}
|
}
|
||||||
|
|
||||||
Tags::~Tags() {
|
Tags::~Tags() {
|
||||||
if(output_status_) {
|
if (output_status_) {
|
||||||
zdwl_ipc_output_v2_destroy(output_status_);
|
zdwl_ipc_output_v2_destroy(output_status_);
|
||||||
}
|
}
|
||||||
if (status_manager_) {
|
if (status_manager_) {
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
#include "modules/dwl/window.hpp"
|
||||||
|
|
||||||
|
#include <gdkmm/pixbuf.h>
|
||||||
|
#include <glibmm/fileutils.h>
|
||||||
|
#include <glibmm/keyfile.h>
|
||||||
|
#include <glibmm/miscutils.h>
|
||||||
|
#include <gtkmm/enums.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include "client.hpp"
|
||||||
|
#include "dwl-ipc-unstable-v2-client-protocol.h"
|
||||||
|
#include "util/rewrite_string.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::dwl {
|
||||||
|
|
||||||
|
static void toggle_visibility(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
|
||||||
|
// Intentionally empty
|
||||||
|
}
|
||||||
|
|
||||||
|
static void active(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t active) {
|
||||||
|
// Intentionally empty
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_tag(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t tag, uint32_t state,
|
||||||
|
uint32_t clients, uint32_t focused) {
|
||||||
|
// Intentionally empty
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_layout_symbol(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *layout) {
|
||||||
|
static_cast<Window *>(data)->handle_layout_symbol(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void title(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *title) {
|
||||||
|
static_cast<Window *>(data)->handle_title(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwl_frame(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
|
||||||
|
static_cast<Window *>(data)->handle_frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_layout(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, uint32_t layout) {
|
||||||
|
static_cast<Window *>(data)->handle_layout(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void appid(void *data, zdwl_ipc_output_v2 *zdwl_output_v2, const char *appid) {
|
||||||
|
static_cast<Window *>(data)->handle_appid(appid);
|
||||||
|
};
|
||||||
|
|
||||||
|
static const zdwl_ipc_output_v2_listener output_status_listener_impl{
|
||||||
|
.toggle_visibility = toggle_visibility,
|
||||||
|
.active = active,
|
||||||
|
.tag = set_tag,
|
||||||
|
.layout = set_layout,
|
||||||
|
.title = title,
|
||||||
|
.appid = appid,
|
||||||
|
.layout_symbol = set_layout_symbol,
|
||||||
|
.frame = dwl_frame,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
|
const char *interface, uint32_t version) {
|
||||||
|
if (std::strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) {
|
||||||
|
static_cast<Window *>(data)->status_manager_ = static_cast<struct zdwl_ipc_manager_v2 *>(
|
||||||
|
(zdwl_ipc_manager_v2 *)wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
|
||||||
|
/* Ignore event */
|
||||||
|
}
|
||||||
|
|
||||||
|
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
|
||||||
|
.global_remove = handle_global_remove};
|
||||||
|
|
||||||
|
Window::Window(const std::string &id, const Bar &bar, const Json::Value &config)
|
||||||
|
: AAppIconLabel(config, "window", id, "{}", 0, true), bar_(bar) {
|
||||||
|
struct wl_display *display = Client::inst()->wl_display;
|
||||||
|
struct wl_registry *registry = wl_display_get_registry(display);
|
||||||
|
|
||||||
|
wl_registry_add_listener(registry, ®istry_listener_impl, this);
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
if (!status_manager_) {
|
||||||
|
spdlog::error("dwl_status_manager_v2 not advertised");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_output *output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
||||||
|
output_status_ = zdwl_ipc_manager_v2_get_output(status_manager_, output);
|
||||||
|
zdwl_ipc_output_v2_add_listener(output_status_, &output_status_listener_impl, this);
|
||||||
|
zdwl_ipc_manager_v2_destroy(status_manager_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::handle_title(const char *title) { title_ = title; }
|
||||||
|
|
||||||
|
void Window::handle_appid(const char *appid) { appid_ = appid; }
|
||||||
|
|
||||||
|
void Window::handle_layout_symbol(const char *layout_symbol) { layout_symbol_ = layout_symbol; }
|
||||||
|
|
||||||
|
void Window::handle_layout(const uint32_t layout) { layout_ = layout; }
|
||||||
|
|
||||||
|
void Window::handle_frame() {
|
||||||
|
label_.set_markup(waybar::util::rewriteString(
|
||||||
|
fmt::format(fmt::runtime(format_), fmt::arg("title", title_),
|
||||||
|
fmt::arg("layout", layout_symbol_), fmt::arg("app_id", appid_)),
|
||||||
|
config_["rewrite"]));
|
||||||
|
updateAppIconName(appid_, "");
|
||||||
|
updateAppIcon();
|
||||||
|
if (tooltipEnabled()) {
|
||||||
|
label_.set_tooltip_text(title_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules::dwl
|
|
@ -83,6 +83,11 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void {
|
||||||
m_activeOnly = configActiveOnly.asBool();
|
m_activeOnly = configActiveOnly.asBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto configMoveToMonitor = config_["move-to-monitor"];
|
||||||
|
if (configMoveToMonitor.isBool()) {
|
||||||
|
m_moveToMonitor = configMoveToMonitor.asBool();
|
||||||
|
}
|
||||||
|
|
||||||
auto configSortBy = config_["sort-by"];
|
auto configSortBy = config_["sort-by"];
|
||||||
if (configSortBy.isString()) {
|
if (configSortBy.isString()) {
|
||||||
auto sortByStr = configSortBy.asString();
|
auto sortByStr = configSortBy.asString();
|
||||||
|
@ -1034,9 +1039,17 @@ bool Workspace::handleClicked(GdkEventButton *bt) const {
|
||||||
if (bt->type == GDK_BUTTON_PRESS) {
|
if (bt->type == GDK_BUTTON_PRESS) {
|
||||||
try {
|
try {
|
||||||
if (id() > 0) { // normal
|
if (id() > 0) { // normal
|
||||||
gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id()));
|
if (m_workspaceManager.moveToMonitor()) {
|
||||||
|
gIPC->getSocket1Reply("dispatch focusworkspaceoncurrentmonitor " + std::to_string(id()));
|
||||||
|
} else {
|
||||||
|
gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id()));
|
||||||
|
}
|
||||||
} else if (!isSpecial()) { // named (this includes persistent)
|
} else if (!isSpecial()) { // named (this includes persistent)
|
||||||
gIPC->getSocket1Reply("dispatch workspace name:" + name());
|
if (m_workspaceManager.moveToMonitor()) {
|
||||||
|
gIPC->getSocket1Reply("dispatch focusworkspaceoncurrentmonitor name:" + name());
|
||||||
|
} else {
|
||||||
|
gIPC->getSocket1Reply("dispatch workspace name:" + name());
|
||||||
|
}
|
||||||
} else if (id() != -99) { // named special
|
} else if (id() != -99) { // named special
|
||||||
gIPC->getSocket1Reply("dispatch togglespecialworkspace " + name());
|
gIPC->getSocket1Reply("dispatch togglespecialworkspace " + name());
|
||||||
} else { // special
|
} else { // special
|
||||||
|
|
|
@ -319,6 +319,11 @@ auto Workspaces::update() -> void {
|
||||||
} else {
|
} else {
|
||||||
button.get_style_context()->remove_class("persistent");
|
button.get_style_context()->remove_class("persistent");
|
||||||
}
|
}
|
||||||
|
if ((*it)["nodes"].size() == 0) {
|
||||||
|
button.get_style_context()->add_class("empty");
|
||||||
|
} else {
|
||||||
|
button.get_style_context()->remove_class("empty");
|
||||||
|
}
|
||||||
if ((*it)["output"].isString()) {
|
if ((*it)["output"].isString()) {
|
||||||
if (((*it)["output"].asString()) == bar_.output->name) {
|
if (((*it)["output"].asString()) == bar_.output->name) {
|
||||||
button.get_style_context()->add_class("current_output");
|
button.get_style_context()->add_class("current_output");
|
||||||
|
|
|
@ -8,6 +8,17 @@
|
||||||
#include "gtkmm/tooltip.h"
|
#include "gtkmm/tooltip.h"
|
||||||
#include "util/gtk_icon.hpp"
|
#include "util/gtk_icon.hpp"
|
||||||
|
|
||||||
|
static const char* getDeviceWarningLevel(UpDeviceLevel level) {
|
||||||
|
switch (level) {
|
||||||
|
case UP_DEVICE_LEVEL_CRITICAL:
|
||||||
|
return "critical";
|
||||||
|
case UP_DEVICE_LEVEL_LOW:
|
||||||
|
return "low";
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace waybar::modules::upower {
|
namespace waybar::modules::upower {
|
||||||
UPower::UPower(const std::string& id, const Json::Value& config)
|
UPower::UPower(const std::string& id, const Json::Value& config)
|
||||||
: AModule(config, "upower", id),
|
: AModule(config, "upower", id),
|
||||||
|
@ -304,11 +315,12 @@ auto UPower::update() -> void {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpDeviceKind kind;
|
UpDeviceKind kind = UP_DEVICE_KIND_UNKNOWN;
|
||||||
UpDeviceState state;
|
UpDeviceState state = UP_DEVICE_STATE_UNKNOWN;
|
||||||
double percentage;
|
UpDeviceLevel level = UP_DEVICE_LEVEL_UNKNOWN;
|
||||||
gint64 time_empty;
|
double percentage = 0.0;
|
||||||
gint64 time_full;
|
gint64 time_empty = 0;
|
||||||
|
gint64 time_full = 0;
|
||||||
gchar* icon_name{(char*)'\0'};
|
gchar* icon_name{(char*)'\0'};
|
||||||
std::string percentString{""};
|
std::string percentString{""};
|
||||||
std::string time_format{""};
|
std::string time_format{""};
|
||||||
|
@ -318,7 +330,7 @@ auto UPower::update() -> void {
|
||||||
if (displayDevice) {
|
if (displayDevice) {
|
||||||
g_object_get(displayDevice, "kind", &kind, "state", &state, "percentage", &percentage,
|
g_object_get(displayDevice, "kind", &kind, "state", &state, "percentage", &percentage,
|
||||||
"icon-name", &icon_name, "time-to-empty", &time_empty, "time-to-full", &time_full,
|
"icon-name", &icon_name, "time-to-empty", &time_empty, "time-to-full", &time_full,
|
||||||
NULL);
|
"warning-level", &level, NULL);
|
||||||
/* Every Device which is handled by Upower and which is not
|
/* Every Device which is handled by Upower and which is not
|
||||||
* UP_DEVICE_KIND_UNKNOWN (0) or UP_DEVICE_KIND_LINE_POWER (1) is a Battery
|
* UP_DEVICE_KIND_UNKNOWN (0) or UP_DEVICE_KIND_LINE_POWER (1) is a Battery
|
||||||
*/
|
*/
|
||||||
|
@ -338,6 +350,15 @@ auto UPower::update() -> void {
|
||||||
}
|
}
|
||||||
lastStatus = status;
|
lastStatus = status;
|
||||||
|
|
||||||
|
const char* warning_level = getDeviceWarningLevel(level);
|
||||||
|
if (lastWarningLevel && box_.get_style_context()->has_class(lastWarningLevel)) {
|
||||||
|
box_.get_style_context()->remove_class(lastWarningLevel);
|
||||||
|
}
|
||||||
|
if (warning_level && !box_.get_style_context()->has_class(warning_level)) {
|
||||||
|
box_.get_style_context()->add_class(warning_level);
|
||||||
|
}
|
||||||
|
lastWarningLevel = warning_level;
|
||||||
|
|
||||||
if (devices.size() == 0 && !displayDeviceValid && hideIfEmpty) {
|
if (devices.size() == 0 && !displayDeviceValid && hideIfEmpty) {
|
||||||
event_box_.set_visible(false);
|
event_box_.set_visible(false);
|
||||||
// Call parent update
|
// Call parent update
|
||||||
|
|
|
@ -18,31 +18,24 @@ waybar::modules::Wireplumber::Wireplumber(const std::string& id, const Json::Val
|
||||||
min_step_(0.0),
|
min_step_(0.0),
|
||||||
node_id_(0) {
|
node_id_(0) {
|
||||||
wp_init(WP_INIT_PIPEWIRE);
|
wp_init(WP_INIT_PIPEWIRE);
|
||||||
wp_core_ = wp_core_new(NULL, NULL);
|
wp_core_ = wp_core_new(nullptr, nullptr, nullptr);
|
||||||
apis_ = g_ptr_array_new_with_free_func(g_object_unref);
|
apis_ = g_ptr_array_new_with_free_func(g_object_unref);
|
||||||
om_ = wp_object_manager_new();
|
om_ = wp_object_manager_new();
|
||||||
|
|
||||||
prepare();
|
prepare();
|
||||||
|
|
||||||
loadRequiredApiModules();
|
spdlog::debug("[{}]: connecting to pipewire...", name_);
|
||||||
|
|
||||||
spdlog::debug("[{}]: connecting to pipewire...", this->name_);
|
if (wp_core_connect(wp_core_) == 0) {
|
||||||
|
spdlog::error("[{}]: Could not connect to PipeWire", name_);
|
||||||
if (!wp_core_connect(wp_core_)) {
|
|
||||||
spdlog::error("[{}]: Could not connect to PipeWire", this->name_);
|
|
||||||
throw std::runtime_error("Could not connect to PipeWire\n");
|
throw std::runtime_error("Could not connect to PipeWire\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
spdlog::debug("[{}]: connected!", this->name_);
|
spdlog::debug("[{}]: connected!", name_);
|
||||||
|
|
||||||
g_signal_connect_swapped(om_, "installed", (GCallback)onObjectManagerInstalled, this);
|
g_signal_connect_swapped(om_, "installed", (GCallback)onObjectManagerInstalled, this);
|
||||||
|
|
||||||
activatePlugins();
|
asyncLoadRequiredApiModules();
|
||||||
|
|
||||||
dp.emit();
|
|
||||||
|
|
||||||
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
|
||||||
event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &Wireplumber::handleScroll));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
waybar::modules::Wireplumber::~Wireplumber() {
|
waybar::modules::Wireplumber::~Wireplumber() {
|
||||||
|
@ -63,32 +56,36 @@ void waybar::modules::Wireplumber::updateNodeName(waybar::modules::Wireplumber*
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto proxy = static_cast<WpProxy*>(wp_object_manager_lookup(
|
auto* proxy = static_cast<WpProxy*>(wp_object_manager_lookup(self->om_, WP_TYPE_GLOBAL_PROXY,
|
||||||
self->om_, WP_TYPE_GLOBAL_PROXY, WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", id, NULL));
|
WP_CONSTRAINT_TYPE_G_PROPERTY,
|
||||||
|
"bound-id", "=u", id, nullptr));
|
||||||
|
|
||||||
if (!proxy) {
|
if (proxy == nullptr) {
|
||||||
auto err = fmt::format("Object '{}' not found\n", id);
|
auto err = fmt::format("Object '{}' not found\n", id);
|
||||||
spdlog::error("[{}]: {}", self->name_, err);
|
spdlog::error("[{}]: {}", self->name_, err);
|
||||||
throw std::runtime_error(err);
|
throw std::runtime_error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_autoptr(WpProperties) properties =
|
g_autoptr(WpProperties) properties =
|
||||||
WP_IS_PIPEWIRE_OBJECT(proxy) ? wp_pipewire_object_get_properties(WP_PIPEWIRE_OBJECT(proxy))
|
WP_IS_PIPEWIRE_OBJECT(proxy) != 0
|
||||||
: wp_properties_new_empty();
|
? wp_pipewire_object_get_properties(WP_PIPEWIRE_OBJECT(proxy))
|
||||||
g_autoptr(WpProperties) global_p = wp_global_proxy_get_global_properties(WP_GLOBAL_PROXY(proxy));
|
: wp_properties_new_empty();
|
||||||
|
g_autoptr(WpProperties) globalP = wp_global_proxy_get_global_properties(WP_GLOBAL_PROXY(proxy));
|
||||||
properties = wp_properties_ensure_unique_owner(properties);
|
properties = wp_properties_ensure_unique_owner(properties);
|
||||||
wp_properties_add(properties, global_p);
|
wp_properties_add(properties, globalP);
|
||||||
wp_properties_set(properties, "object.id", NULL);
|
wp_properties_set(properties, "object.id", nullptr);
|
||||||
auto nick = wp_properties_get(properties, "node.nick");
|
const auto* nick = wp_properties_get(properties, "node.nick");
|
||||||
auto description = wp_properties_get(properties, "node.description");
|
const auto* description = wp_properties_get(properties, "node.description");
|
||||||
|
|
||||||
self->node_name_ = nick ? nick : description ? description : "Unknown node name";
|
self->node_name_ = nick != nullptr ? nick
|
||||||
|
: description != nullptr ? description
|
||||||
|
: "Unknown node name";
|
||||||
spdlog::debug("[{}]: Updating node name to: {}", self->name_, self->node_name_);
|
spdlog::debug("[{}]: Updating node name to: {}", self->name_, self->node_name_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::Wireplumber::updateVolume(waybar::modules::Wireplumber* self, uint32_t id) {
|
void waybar::modules::Wireplumber::updateVolume(waybar::modules::Wireplumber* self, uint32_t id) {
|
||||||
spdlog::debug("[{}]: updating volume", self->name_);
|
spdlog::debug("[{}]: updating volume", self->name_);
|
||||||
GVariant* variant = NULL;
|
GVariant* variant = nullptr;
|
||||||
|
|
||||||
if (!isValidNodeId(id)) {
|
if (!isValidNodeId(id)) {
|
||||||
spdlog::error("[{}]: '{}' is not a valid node ID. Ignoring volume update.", self->name_, id);
|
spdlog::error("[{}]: '{}' is not a valid node ID. Ignoring volume update.", self->name_, id);
|
||||||
|
@ -97,7 +94,7 @@ void waybar::modules::Wireplumber::updateVolume(waybar::modules::Wireplumber* se
|
||||||
|
|
||||||
g_signal_emit_by_name(self->mixer_api_, "get-volume", id, &variant);
|
g_signal_emit_by_name(self->mixer_api_, "get-volume", id, &variant);
|
||||||
|
|
||||||
if (!variant) {
|
if (variant == nullptr) {
|
||||||
auto err = fmt::format("Node {} does not support volume\n", id);
|
auto err = fmt::format("Node {} does not support volume\n", id);
|
||||||
spdlog::error("[{}]: {}", self->name_, err);
|
spdlog::error("[{}]: {}", self->name_, err);
|
||||||
throw std::runtime_error(err);
|
throw std::runtime_error(err);
|
||||||
|
@ -115,9 +112,9 @@ void waybar::modules::Wireplumber::onMixerChanged(waybar::modules::Wireplumber*
|
||||||
spdlog::debug("[{}]: (onMixerChanged) - id: {}", self->name_, id);
|
spdlog::debug("[{}]: (onMixerChanged) - id: {}", self->name_, id);
|
||||||
|
|
||||||
g_autoptr(WpNode) node = static_cast<WpNode*>(wp_object_manager_lookup(
|
g_autoptr(WpNode) node = static_cast<WpNode*>(wp_object_manager_lookup(
|
||||||
self->om_, WP_TYPE_NODE, WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", id, NULL));
|
self->om_, WP_TYPE_NODE, WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", id, nullptr));
|
||||||
|
|
||||||
if (!node) {
|
if (node == nullptr) {
|
||||||
spdlog::warn("[{}]: (onMixerChanged) - Object with id {} not found", self->name_, id);
|
spdlog::warn("[{}]: (onMixerChanged) - Object with id {} not found", self->name_, id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -140,49 +137,49 @@ void waybar::modules::Wireplumber::onMixerChanged(waybar::modules::Wireplumber*
|
||||||
void waybar::modules::Wireplumber::onDefaultNodesApiChanged(waybar::modules::Wireplumber* self) {
|
void waybar::modules::Wireplumber::onDefaultNodesApiChanged(waybar::modules::Wireplumber* self) {
|
||||||
spdlog::debug("[{}]: (onDefaultNodesApiChanged)", self->name_);
|
spdlog::debug("[{}]: (onDefaultNodesApiChanged)", self->name_);
|
||||||
|
|
||||||
uint32_t default_node_id;
|
uint32_t defaultNodeId;
|
||||||
g_signal_emit_by_name(self->def_nodes_api_, "get-default-node", "Audio/Sink", &default_node_id);
|
g_signal_emit_by_name(self->def_nodes_api_, "get-default-node", "Audio/Sink", &defaultNodeId);
|
||||||
|
|
||||||
if (!isValidNodeId(default_node_id)) {
|
if (!isValidNodeId(defaultNodeId)) {
|
||||||
spdlog::warn("[{}]: '{}' is not a valid node ID. Ignoring node change.", self->name_,
|
spdlog::warn("[{}]: '{}' is not a valid node ID. Ignoring node change.", self->name_,
|
||||||
default_node_id);
|
defaultNodeId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_autoptr(WpNode) node = static_cast<WpNode*>(
|
g_autoptr(WpNode) node = static_cast<WpNode*>(
|
||||||
wp_object_manager_lookup(self->om_, WP_TYPE_NODE, WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id",
|
wp_object_manager_lookup(self->om_, WP_TYPE_NODE, WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id",
|
||||||
"=u", default_node_id, NULL));
|
"=u", defaultNodeId, nullptr));
|
||||||
|
|
||||||
if (!node) {
|
if (node == nullptr) {
|
||||||
spdlog::warn("[{}]: (onDefaultNodesApiChanged) - Object with id {} not found", self->name_,
|
spdlog::warn("[{}]: (onDefaultNodesApiChanged) - Object with id {} not found", self->name_,
|
||||||
default_node_id);
|
defaultNodeId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gchar* default_node_name =
|
const gchar* defaultNodeName =
|
||||||
wp_pipewire_object_get_property(WP_PIPEWIRE_OBJECT(node), "node.name");
|
wp_pipewire_object_get_property(WP_PIPEWIRE_OBJECT(node), "node.name");
|
||||||
|
|
||||||
spdlog::debug(
|
spdlog::debug(
|
||||||
"[{}]: (onDefaultNodesApiChanged) - got the following default node: Node(name: {}, id: {})",
|
"[{}]: (onDefaultNodesApiChanged) - got the following default node: Node(name: {}, id: {})",
|
||||||
self->name_, default_node_name, default_node_id);
|
self->name_, defaultNodeName, defaultNodeId);
|
||||||
|
|
||||||
if (g_strcmp0(self->default_node_name_, default_node_name) == 0) {
|
if (g_strcmp0(self->default_node_name_, defaultNodeName) == 0) {
|
||||||
spdlog::debug(
|
spdlog::debug(
|
||||||
"[{}]: (onDefaultNodesApiChanged) - Default node has not changed. Node(name: {}, id: {}). "
|
"[{}]: (onDefaultNodesApiChanged) - Default node has not changed. Node(name: {}, id: {}). "
|
||||||
"Ignoring.",
|
"Ignoring.",
|
||||||
self->name_, self->default_node_name_, default_node_id);
|
self->name_, self->default_node_name_, defaultNodeId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
spdlog::debug(
|
spdlog::debug(
|
||||||
"[{}]: (onDefaultNodesApiChanged) - Default node changed to -> Node(name: {}, id: {})",
|
"[{}]: (onDefaultNodesApiChanged) - Default node changed to -> Node(name: {}, id: {})",
|
||||||
self->name_, default_node_name, default_node_id);
|
self->name_, defaultNodeName, defaultNodeId);
|
||||||
|
|
||||||
g_free(self->default_node_name_);
|
g_free(self->default_node_name_);
|
||||||
self->default_node_name_ = g_strdup(default_node_name);
|
self->default_node_name_ = g_strdup(defaultNodeName);
|
||||||
self->node_id_ = default_node_id;
|
self->node_id_ = defaultNodeId;
|
||||||
updateVolume(self, default_node_id);
|
updateVolume(self, defaultNodeId);
|
||||||
updateNodeName(self, default_node_id);
|
updateNodeName(self, defaultNodeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::Wireplumber::onObjectManagerInstalled(waybar::modules::Wireplumber* self) {
|
void waybar::modules::Wireplumber::onObjectManagerInstalled(waybar::modules::Wireplumber* self) {
|
||||||
|
@ -190,14 +187,14 @@ void waybar::modules::Wireplumber::onObjectManagerInstalled(waybar::modules::Wir
|
||||||
|
|
||||||
self->def_nodes_api_ = wp_plugin_find(self->wp_core_, "default-nodes-api");
|
self->def_nodes_api_ = wp_plugin_find(self->wp_core_, "default-nodes-api");
|
||||||
|
|
||||||
if (!self->def_nodes_api_) {
|
if (self->def_nodes_api_ == nullptr) {
|
||||||
spdlog::error("[{}]: default nodes api is not loaded.", self->name_);
|
spdlog::error("[{}]: default nodes api is not loaded.", self->name_);
|
||||||
throw std::runtime_error("Default nodes API is not loaded\n");
|
throw std::runtime_error("Default nodes API is not loaded\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
self->mixer_api_ = wp_plugin_find(self->wp_core_, "mixer-api");
|
self->mixer_api_ = wp_plugin_find(self->wp_core_, "mixer-api");
|
||||||
|
|
||||||
if (!self->mixer_api_) {
|
if (self->mixer_api_ == nullptr) {
|
||||||
spdlog::error("[{}]: mixer api is not loaded.", self->name_);
|
spdlog::error("[{}]: mixer api is not loaded.", self->name_);
|
||||||
throw std::runtime_error("Mixer api is not loaded\n");
|
throw std::runtime_error("Mixer api is not loaded\n");
|
||||||
}
|
}
|
||||||
|
@ -206,7 +203,7 @@ void waybar::modules::Wireplumber::onObjectManagerInstalled(waybar::modules::Wir
|
||||||
&self->default_node_name_);
|
&self->default_node_name_);
|
||||||
g_signal_emit_by_name(self->def_nodes_api_, "get-default-node", "Audio/Sink", &self->node_id_);
|
g_signal_emit_by_name(self->def_nodes_api_, "get-default-node", "Audio/Sink", &self->node_id_);
|
||||||
|
|
||||||
if (self->default_node_name_) {
|
if (self->default_node_name_ != nullptr) {
|
||||||
spdlog::debug("[{}]: (onObjectManagerInstalled) - default configured node name: {} and id: {}",
|
spdlog::debug("[{}]: (onObjectManagerInstalled) - default configured node name: {} and id: {}",
|
||||||
self->name_, self->default_node_name_, self->node_id_);
|
self->name_, self->default_node_name_, self->node_id_);
|
||||||
}
|
}
|
||||||
|
@ -221,11 +218,11 @@ void waybar::modules::Wireplumber::onObjectManagerInstalled(waybar::modules::Wir
|
||||||
|
|
||||||
void waybar::modules::Wireplumber::onPluginActivated(WpObject* p, GAsyncResult* res,
|
void waybar::modules::Wireplumber::onPluginActivated(WpObject* p, GAsyncResult* res,
|
||||||
waybar::modules::Wireplumber* self) {
|
waybar::modules::Wireplumber* self) {
|
||||||
auto plugin_name = wp_plugin_get_name(WP_PLUGIN(p));
|
const auto* pluginName = wp_plugin_get_name(WP_PLUGIN(p));
|
||||||
spdlog::debug("[{}]: onPluginActivated: {}", self->name_, plugin_name);
|
spdlog::debug("[{}]: onPluginActivated: {}", self->name_, pluginName);
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = nullptr;
|
||||||
|
|
||||||
if (!wp_object_activate_finish(p, res, &error)) {
|
if (wp_object_activate_finish(p, res, &error) == 0) {
|
||||||
spdlog::error("[{}]: error activating plugin: {}", self->name_, error->message);
|
spdlog::error("[{}]: error activating plugin: {}", self->name_, error->message);
|
||||||
throw std::runtime_error(error->message);
|
throw std::runtime_error(error->message);
|
||||||
}
|
}
|
||||||
|
@ -240,7 +237,7 @@ void waybar::modules::Wireplumber::activatePlugins() {
|
||||||
for (uint16_t i = 0; i < apis_->len; i++) {
|
for (uint16_t i = 0; i < apis_->len; i++) {
|
||||||
WpPlugin* plugin = static_cast<WpPlugin*>(g_ptr_array_index(apis_, i));
|
WpPlugin* plugin = static_cast<WpPlugin*>(g_ptr_array_index(apis_, i));
|
||||||
pending_plugins_++;
|
pending_plugins_++;
|
||||||
wp_object_activate(WP_OBJECT(plugin), WP_PLUGIN_FEATURE_ENABLED, NULL,
|
wp_object_activate(WP_OBJECT(plugin), WP_PLUGIN_FEATURE_ENABLED, nullptr,
|
||||||
(GAsyncReadyCallback)onPluginActivated, this);
|
(GAsyncReadyCallback)onPluginActivated, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,34 +245,67 @@ void waybar::modules::Wireplumber::activatePlugins() {
|
||||||
void waybar::modules::Wireplumber::prepare() {
|
void waybar::modules::Wireplumber::prepare() {
|
||||||
spdlog::debug("[{}]: preparing object manager", name_);
|
spdlog::debug("[{}]: preparing object manager", name_);
|
||||||
wp_object_manager_add_interest(om_, WP_TYPE_NODE, WP_CONSTRAINT_TYPE_PW_PROPERTY, "media.class",
|
wp_object_manager_add_interest(om_, WP_TYPE_NODE, WP_CONSTRAINT_TYPE_PW_PROPERTY, "media.class",
|
||||||
"=s", "Audio/Sink", NULL);
|
"=s", "Audio/Sink", nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::Wireplumber::loadRequiredApiModules() {
|
void waybar::modules::Wireplumber::onDefaultNodesApiLoaded(WpObject* p, GAsyncResult* res,
|
||||||
spdlog::debug("[{}]: loading required modules", name_);
|
waybar::modules::Wireplumber* self) {
|
||||||
g_autoptr(GError) error = NULL;
|
gboolean success = FALSE;
|
||||||
|
g_autoptr(GError) error = nullptr;
|
||||||
|
|
||||||
if (!wp_core_load_component(wp_core_, "libwireplumber-module-default-nodes-api", "module", NULL,
|
spdlog::debug("[{}]: callback loading default node api module", self->name_);
|
||||||
&error)) {
|
|
||||||
|
success = wp_core_load_component_finish(self->wp_core_, res, &error);
|
||||||
|
|
||||||
|
if (success == FALSE) {
|
||||||
|
spdlog::error("[{}]: default nodes API load failed", self->name_);
|
||||||
|
throw std::runtime_error(error->message);
|
||||||
|
}
|
||||||
|
spdlog::debug("[{}]: loaded default nodes api", self->name_);
|
||||||
|
g_ptr_array_add(self->apis_, wp_plugin_find(self->wp_core_, "default-nodes-api"));
|
||||||
|
|
||||||
|
spdlog::debug("[{}]: loading mixer api module", self->name_);
|
||||||
|
wp_core_load_component(self->wp_core_, "libwireplumber-module-mixer-api", "module", nullptr,
|
||||||
|
"mixer-api", nullptr, (GAsyncReadyCallback)onMixerApiLoaded, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void waybar::modules::Wireplumber::onMixerApiLoaded(WpObject* p, GAsyncResult* res,
|
||||||
|
waybar::modules::Wireplumber* self) {
|
||||||
|
gboolean success = FALSE;
|
||||||
|
g_autoptr(GError) error = nullptr;
|
||||||
|
|
||||||
|
success = wp_core_load_component_finish(self->wp_core_, res, nullptr);
|
||||||
|
|
||||||
|
if (success == FALSE) {
|
||||||
|
spdlog::error("[{}]: mixer API load failed", self->name_);
|
||||||
throw std::runtime_error(error->message);
|
throw std::runtime_error(error->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wp_core_load_component(wp_core_, "libwireplumber-module-mixer-api", "module", NULL,
|
spdlog::debug("[{}]: loaded mixer API", self->name_);
|
||||||
&error)) {
|
g_ptr_array_add(self->apis_, ({
|
||||||
throw std::runtime_error(error->message);
|
WpPlugin* p = wp_plugin_find(self->wp_core_, "mixer-api");
|
||||||
}
|
g_object_set(G_OBJECT(p), "scale", 1 /* cubic */, nullptr);
|
||||||
|
|
||||||
g_ptr_array_add(apis_, wp_plugin_find(wp_core_, "default-nodes-api"));
|
|
||||||
g_ptr_array_add(apis_, ({
|
|
||||||
WpPlugin* p = wp_plugin_find(wp_core_, "mixer-api");
|
|
||||||
g_object_set(G_OBJECT(p), "scale", 1 /* cubic */, NULL);
|
|
||||||
p;
|
p;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
self->activatePlugins();
|
||||||
|
|
||||||
|
self->dp.emit();
|
||||||
|
|
||||||
|
self->event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
||||||
|
self->event_box_.signal_scroll_event().connect(sigc::mem_fun(*self, &Wireplumber::handleScroll));
|
||||||
|
}
|
||||||
|
|
||||||
|
void waybar::modules::Wireplumber::asyncLoadRequiredApiModules() {
|
||||||
|
spdlog::debug("[{}]: loading default nodes api module", name_);
|
||||||
|
wp_core_load_component(wp_core_, "libwireplumber-module-default-nodes-api", "module", nullptr,
|
||||||
|
"default-nodes-api", nullptr, (GAsyncReadyCallback)onDefaultNodesApiLoaded,
|
||||||
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Wireplumber::update() -> void {
|
auto waybar::modules::Wireplumber::update() -> void {
|
||||||
auto format = format_;
|
auto format = format_;
|
||||||
std::string tooltip_format;
|
std::string tooltipFormat;
|
||||||
|
|
||||||
if (muted_) {
|
if (muted_) {
|
||||||
format = config_["format-muted"].isString() ? config_["format-muted"].asString() : format;
|
format = config_["format-muted"].isString() ? config_["format-muted"].asString() : format;
|
||||||
|
@ -292,12 +322,12 @@ auto waybar::modules::Wireplumber::update() -> void {
|
||||||
getState(vol);
|
getState(vol);
|
||||||
|
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
if (tooltip_format.empty() && config_["tooltip-format"].isString()) {
|
if (tooltipFormat.empty() && config_["tooltip-format"].isString()) {
|
||||||
tooltip_format = config_["tooltip-format"].asString();
|
tooltipFormat = config_["tooltip-format"].asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tooltip_format.empty()) {
|
if (!tooltipFormat.empty()) {
|
||||||
label_.set_tooltip_text(fmt::format(fmt::runtime(tooltip_format),
|
label_.set_tooltip_text(fmt::format(fmt::runtime(tooltipFormat),
|
||||||
fmt::arg("node_name", node_name_),
|
fmt::arg("node_name", node_name_),
|
||||||
fmt::arg("volume", vol), fmt::arg("icon", getIcon(vol))));
|
fmt::arg("volume", vol), fmt::arg("icon", getIcon(vol))));
|
||||||
} else {
|
} else {
|
||||||
|
@ -317,31 +347,31 @@ bool waybar::modules::Wireplumber::handleScroll(GdkEventScroll* e) {
|
||||||
if (dir == SCROLL_DIR::NONE) {
|
if (dir == SCROLL_DIR::NONE) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
double max_volume = 1;
|
double maxVolume = 1;
|
||||||
double step = 1.0 / 100.0;
|
double step = 1.0 / 100.0;
|
||||||
if (config_["scroll-step"].isDouble()) {
|
if (config_["scroll-step"].isDouble()) {
|
||||||
step = config_["scroll-step"].asDouble() / 100.0;
|
step = config_["scroll-step"].asDouble() / 100.0;
|
||||||
}
|
}
|
||||||
if (config_["max-volume"].isDouble()) {
|
if (config_["max-volume"].isDouble()) {
|
||||||
max_volume = config_["max-volume"].asDouble() / 100.0;
|
maxVolume = config_["max-volume"].asDouble() / 100.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step < min_step_) step = min_step_;
|
if (step < min_step_) step = min_step_;
|
||||||
|
|
||||||
double new_vol = volume_;
|
double newVol = volume_;
|
||||||
if (dir == SCROLL_DIR::UP) {
|
if (dir == SCROLL_DIR::UP) {
|
||||||
if (volume_ < max_volume) {
|
if (volume_ < maxVolume) {
|
||||||
new_vol = volume_ + step;
|
newVol = volume_ + step;
|
||||||
if (new_vol > max_volume) new_vol = max_volume;
|
if (newVol > maxVolume) newVol = maxVolume;
|
||||||
}
|
}
|
||||||
} else if (dir == SCROLL_DIR::DOWN) {
|
} else if (dir == SCROLL_DIR::DOWN) {
|
||||||
if (volume_ > 0) {
|
if (volume_ > 0) {
|
||||||
new_vol = volume_ - step;
|
newVol = volume_ - step;
|
||||||
if (new_vol < 0) new_vol = 0;
|
if (newVol < 0) newVol = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (new_vol != volume_) {
|
if (newVol != volume_) {
|
||||||
GVariant* variant = g_variant_new_double(new_vol);
|
GVariant* variant = g_variant_new_double(newVol);
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
g_signal_emit_by_name(mixer_api_, "set-volume", node_id_, variant, &ret);
|
g_signal_emit_by_name(mixer_api_, "set-volume", node_id_, variant, &ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,54 @@ void check_nn(const void *ptr, const char *message = "ptr was null") {
|
||||||
|
|
||||||
namespace waybar::util {
|
namespace waybar::util {
|
||||||
|
|
||||||
|
static void upsert_device(std::vector<BacklightDevice> &devices, udev_device *dev) {
|
||||||
|
const char *name = udev_device_get_sysname(dev);
|
||||||
|
check_nn(name);
|
||||||
|
|
||||||
|
const char *actual_brightness_attr =
|
||||||
|
strncmp(name, "amdgpu_bl", 9) == 0 || strcmp(name, "apple-panel-bl") == 0
|
||||||
|
? "brightness"
|
||||||
|
: "actual_brightness";
|
||||||
|
|
||||||
|
const char *actual = udev_device_get_sysattr_value(dev, actual_brightness_attr);
|
||||||
|
const char *max = udev_device_get_sysattr_value(dev, "max_brightness");
|
||||||
|
const char *power = udev_device_get_sysattr_value(dev, "bl_power");
|
||||||
|
|
||||||
|
auto found = std::find_if(devices.begin(), devices.end(), [name](const BacklightDevice &device) {
|
||||||
|
return device.name() == name;
|
||||||
|
});
|
||||||
|
if (found != devices.end()) {
|
||||||
|
if (actual != nullptr) {
|
||||||
|
found->set_actual(std::stoi(actual));
|
||||||
|
}
|
||||||
|
if (max != nullptr) {
|
||||||
|
found->set_max(std::stoi(max));
|
||||||
|
}
|
||||||
|
if (power != nullptr) {
|
||||||
|
found->set_powered(std::stoi(power) == 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const int actual_int = actual == nullptr ? 0 : std::stoi(actual);
|
||||||
|
const int max_int = max == nullptr ? 0 : std::stoi(max);
|
||||||
|
const bool power_bool = power == nullptr ? true : std::stoi(power) == 0;
|
||||||
|
devices.emplace_back(name, actual_int, max_int, power_bool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enumerate_devices(std::vector<BacklightDevice> &devices, udev *udev) {
|
||||||
|
std::unique_ptr<udev_enumerate, UdevEnumerateDeleter> enumerate{udev_enumerate_new(udev)};
|
||||||
|
udev_enumerate_add_match_subsystem(enumerate.get(), "backlight");
|
||||||
|
udev_enumerate_scan_devices(enumerate.get());
|
||||||
|
udev_list_entry *enum_devices = udev_enumerate_get_list_entry(enumerate.get());
|
||||||
|
udev_list_entry *dev_list_entry;
|
||||||
|
udev_list_entry_foreach(dev_list_entry, enum_devices) {
|
||||||
|
const char *path = udev_list_entry_get_name(dev_list_entry);
|
||||||
|
std::unique_ptr<udev_device, UdevDeviceDeleter> dev{udev_device_new_from_syspath(udev, path)};
|
||||||
|
check_nn(dev.get(), "dev new failed");
|
||||||
|
upsert_device(devices, dev.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BacklightDevice::BacklightDevice(std::string name, int actual, int max, bool powered)
|
BacklightDevice::BacklightDevice(std::string name, int actual, int max, bool powered)
|
||||||
: name_(name), actual_(actual), max_(max), powered_(powered) {}
|
: name_(name), actual_(actual), max_(max), powered_(powered) {}
|
||||||
|
|
||||||
|
@ -95,8 +143,7 @@ BacklightBackend::BacklightBackend(std::chrono::milliseconds interval,
|
||||||
: on_updated_cb_(on_updated_cb), polling_interval_(interval), previous_best_({}) {
|
: on_updated_cb_(on_updated_cb), polling_interval_(interval), previous_best_({}) {
|
||||||
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(devices_.begin(), devices_.end(), std::back_inserter(devices_),
|
enumerate_devices(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");
|
||||||
}
|
}
|
||||||
|
@ -145,12 +192,12 @@ BacklightBackend::BacklightBackend(std::chrono::milliseconds interval,
|
||||||
check_eq(event.data.fd, udev_fd, "unexpected udev fd");
|
check_eq(event.data.fd, udev_fd, "unexpected udev fd");
|
||||||
std::unique_ptr<udev_device, UdevDeviceDeleter> dev{udev_monitor_receive_device(mon.get())};
|
std::unique_ptr<udev_device, UdevDeviceDeleter> dev{udev_monitor_receive_device(mon.get())};
|
||||||
check_nn(dev.get(), "epoll dev was null");
|
check_nn(dev.get(), "epoll dev was null");
|
||||||
upsert_device(devices.begin(), devices.end(), std::back_inserter(devices), dev.get());
|
upsert_device(devices, dev.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh state if timed out
|
// Refresh state if timed out
|
||||||
if (event_count == 0) {
|
if (event_count == 0) {
|
||||||
enumerate_devices(devices.begin(), devices.end(), std::back_inserter(devices), udev.get());
|
enumerate_devices(devices, udev.get());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::scoped_lock<std::mutex> lock(udev_thread_mutex_);
|
std::scoped_lock<std::mutex> lock(udev_thread_mutex_);
|
||||||
|
@ -161,19 +208,20 @@ BacklightBackend::BacklightBackend(std::chrono::milliseconds interval,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ForwardIt>
|
const BacklightDevice *BacklightBackend::best_device(const std::vector<BacklightDevice> &devices,
|
||||||
const BacklightDevice *BacklightBackend::best_device(ForwardIt first, ForwardIt last,
|
|
||||||
std::string_view preferred_device) {
|
std::string_view preferred_device) {
|
||||||
const auto found = std::find_if(
|
const auto found = std::find_if(
|
||||||
first, last, [preferred_device](const auto &dev) { return dev.name() == preferred_device; });
|
devices.begin(), devices.end(),
|
||||||
if (found != last) {
|
[preferred_device](const BacklightDevice &dev) { return dev.name() == preferred_device; });
|
||||||
|
if (found != devices.end()) {
|
||||||
return &(*found);
|
return &(*found);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto max = std::max_element(
|
const auto max = std::max_element(
|
||||||
first, last, [](const auto &l, const auto &r) { return l.get_max() < r.get_max(); });
|
devices.begin(), devices.end(),
|
||||||
|
[](const BacklightDevice &l, const BacklightDevice &r) { return l.get_max() < r.get_max(); });
|
||||||
|
|
||||||
return max == last ? nullptr : &(*max);
|
return max == devices.end() ? nullptr : &(*max);
|
||||||
}
|
}
|
||||||
|
|
||||||
const BacklightDevice *BacklightBackend::get_previous_best_device() {
|
const BacklightDevice *BacklightBackend::get_previous_best_device() {
|
||||||
|
@ -233,56 +281,4 @@ int BacklightBackend::get_scaled_brightness(std::string preferred_device) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ForwardIt, class Inserter>
|
|
||||||
void BacklightBackend::upsert_device(ForwardIt first, ForwardIt last, Inserter inserter,
|
|
||||||
udev_device *dev) {
|
|
||||||
const char *name = udev_device_get_sysname(dev);
|
|
||||||
check_nn(name);
|
|
||||||
|
|
||||||
const char *actual_brightness_attr =
|
|
||||||
strncmp(name, "amdgpu_bl", 9) == 0 || strcmp(name, "apple-panel-bl") == 0
|
|
||||||
? "brightness"
|
|
||||||
: "actual_brightness";
|
|
||||||
|
|
||||||
const char *actual = udev_device_get_sysattr_value(dev, actual_brightness_attr);
|
|
||||||
const char *max = udev_device_get_sysattr_value(dev, "max_brightness");
|
|
||||||
const char *power = udev_device_get_sysattr_value(dev, "bl_power");
|
|
||||||
|
|
||||||
auto found =
|
|
||||||
std::find_if(first, last, [name](const auto &device) { return device.name() == name; });
|
|
||||||
if (found != last) {
|
|
||||||
if (actual != nullptr) {
|
|
||||||
found->set_actual(std::stoi(actual));
|
|
||||||
}
|
|
||||||
if (max != nullptr) {
|
|
||||||
found->set_max(std::stoi(max));
|
|
||||||
}
|
|
||||||
if (power != nullptr) {
|
|
||||||
found->set_powered(std::stoi(power) == 0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const int actual_int = actual == nullptr ? 0 : std::stoi(actual);
|
|
||||||
const int max_int = max == nullptr ? 0 : std::stoi(max);
|
|
||||||
const bool power_bool = power == nullptr ? true : std::stoi(power) == 0;
|
|
||||||
*inserter = BacklightDevice{name, actual_int, max_int, power_bool};
|
|
||||||
++inserter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ForwardIt, class Inserter>
|
|
||||||
void BacklightBackend::enumerate_devices(ForwardIt first, ForwardIt last, Inserter inserter,
|
|
||||||
udev *udev) {
|
|
||||||
std::unique_ptr<udev_enumerate, UdevEnumerateDeleter> enumerate{udev_enumerate_new(udev)};
|
|
||||||
udev_enumerate_add_match_subsystem(enumerate.get(), "backlight");
|
|
||||||
udev_enumerate_scan_devices(enumerate.get());
|
|
||||||
udev_list_entry *enum_devices = udev_enumerate_get_list_entry(enumerate.get());
|
|
||||||
udev_list_entry *dev_list_entry;
|
|
||||||
udev_list_entry_foreach(dev_list_entry, enum_devices) {
|
|
||||||
const char *path = udev_list_entry_get_name(dev_list_entry);
|
|
||||||
std::unique_ptr<udev_device, UdevDeviceDeleter> dev{udev_device_new_from_syspath(udev, path)};
|
|
||||||
check_nn(dev.get(), "dev new failed");
|
|
||||||
upsert_device(first, last, inserter, dev.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace waybar::util
|
} // namespace waybar::util
|
Loading…
Reference in New Issue