diff --git a/include/components/controller.hpp b/include/components/controller.hpp index fde2268d..40120498 100644 --- a/include/components/controller.hpp +++ b/include/components/controller.hpp @@ -19,6 +19,7 @@ #include "utils/throttle.hpp" #include "modules/backlight.hpp" +#include "modules/xbacklight.hpp" #include "modules/battery.hpp" #include "modules/bspwm.hpp" #include "modules/counter.hpp" @@ -237,10 +238,14 @@ class controller { } } + m_connection.flush(); + m_log.trace("controller: Listen for X events"); while (m_running) { - m_connection.flush(); - m_connection.dispatch_event(m_connection.wait_for_event()); + auto evt = m_connection.wait_for_event(); + + if (evt != nullptr) + m_connection.dispatch_event(evt); } }); @@ -375,6 +380,8 @@ class controller { modules.emplace_back(new counter_module(bar, m_log, m_conf, module_name)); else if (type == "internal/backlight") modules.emplace_back(new backlight_module(bar, m_log, m_conf, module_name)); + else if (type == "internal/xbacklight") + modules.emplace_back(new xbacklight_module(bar, m_log, m_conf, module_name)); else if (type == "internal/battery") modules.emplace_back(new battery_module(bar, m_log, m_conf, module_name)); else if (type == "internal/bspwm") diff --git a/include/components/x11/atoms.hpp b/include/components/x11/atoms.hpp index af066dea..da4534a5 100644 --- a/include/components/x11/atoms.hpp +++ b/include/components/x11/atoms.hpp @@ -31,9 +31,11 @@ static xcb_atom_t MANAGER; static xcb_atom_t WM_STATE; static xcb_atom_t _NET_SYSTEM_TRAY_ORIENTATION; static xcb_atom_t WM_TAKE_FOCUS; +static xcb_atom_t Backlight; +static xcb_atom_t BACKLIGHT; // clang-format off -static cached_atom ATOMS[22] = { +static cached_atom ATOMS[24] = { {"_NET_WM_NAME", sizeof("_NET_WM_NAME") - 1, &_NET_WM_NAME}, {"_NET_WM_DESKTOP", sizeof("_NET_WM_DESKTOP") - 1, &_NET_WM_DESKTOP}, {"_NET_WM_WINDOW_TYPE", sizeof("_NET_WM_WINDOW_TYPE") - 1, &_NET_WM_WINDOW_TYPE}, @@ -56,5 +58,7 @@ static cached_atom ATOMS[22] = { {"WM_STATE", sizeof("WM_STATE") - 1, &WM_STATE}, {"_NET_SYSTEM_TRAY_ORIENTATION", sizeof("_NET_SYSTEM_TRAY_ORIENTATION") - 1, &_NET_SYSTEM_TRAY_ORIENTATION}, {"WM_TAKE_FOCUS", sizeof("WM_TAKE_FOCUS") - 1, &WM_TAKE_FOCUS}, + {"Backlight", sizeof("Backlight") - 1, &Backlight}, + {"BACKLIGHT", sizeof("BACKLIGHT") - 1, &BACKLIGHT}, }; // clang-format on diff --git a/include/components/x11/randr.hpp b/include/components/x11/randr.hpp index 9d7b2efa..4eb82ea9 100644 --- a/include/components/x11/randr.hpp +++ b/include/components/x11/randr.hpp @@ -6,12 +6,20 @@ LEMONBUDDY_NS +struct backlight_values { + uint32_t min = 0; + uint32_t max = 0; + uint32_t val = 0; +}; + struct randr_output { + xcb_randr_output_t randr_output; string name; int w = 0; int h = 0; int x = 0; int y = 0; + backlight_values backlight; }; using monitor_t = shared_ptr; @@ -20,8 +28,9 @@ namespace randr_util { /** * Define monitor */ - inline monitor_t make_monitor(string name, int w, int h, int x, int y) { + inline monitor_t make_monitor(xcb_randr_output_t randr, string name, int w, int h, int x, int y) { monitor_t mon{new monitor_t::element_type{}}; + mon->randr_output = randr; mon->name = name; mon->x = x; mon->y = y; @@ -44,7 +53,7 @@ namespace randr_util { continue; auto crtc = conn.get_crtc_info(info->crtc); string name{info.name().begin(), info.name().end()}; - monitors.emplace_back(make_monitor(name, crtc->width, crtc->height, crtc->x, crtc->y)); + monitors.emplace_back(make_monitor(*it, name, crtc->width, crtc->height, crtc->x, crtc->y)); } catch (const xpp::randr::error::bad_crtc&) { } catch (const xpp::randr::error::bad_output&) { } @@ -61,6 +70,33 @@ namespace randr_util { return monitors; } + + inline void get_backlight_range(connection& conn, const monitor_t& mon, backlight_values& dst) { + auto reply = conn.query_output_property(mon->randr_output, Backlight); + + if (!reply->range || reply->length != 2) + reply = conn.query_output_property(mon->randr_output, BACKLIGHT); + + if (!reply->range || reply->length != 2) + return; + + auto range = reply.valid_values().begin(); + + dst.min = *range++; + dst.max = *range; + } + + inline void get_backlight_value(connection& conn, const monitor_t& mon, backlight_values& dst) { + auto reply = conn.get_output_property(mon->randr_output, Backlight, XCB_ATOM_NONE, 0, 4, 0, 0); + + if (!reply->num_items) + reply = conn.get_output_property(mon->randr_output, BACKLIGHT, XCB_ATOM_NONE, 0, 4, 0, 0); + + if(!reply->num_items) + return; + + dst.val = *reply.data().begin(); + } } LEMONBUDDY_NS_END diff --git a/include/modules/backlight.hpp b/include/modules/backlight.hpp index 6a5ba6e0..4a70dfc0 100644 --- a/include/modules/backlight.hpp +++ b/include/modules/backlight.hpp @@ -1,6 +1,7 @@ #pragma once #include "config.hpp" +#include "components/config.hpp" #include "drawtypes/label.hpp" #include "drawtypes/progressbar.hpp" #include "drawtypes/ramp.hpp" @@ -9,6 +10,21 @@ LEMONBUDDY_NS namespace modules { + struct brightness_handle { + void filepath(string path) { + if (!file_util::exists(path)) + throw module_error("The file '" + path + "' does not exist"); + m_path = path; + } + + float read() const { + return std::strtof(file_util::get_contents(m_path).c_str(), 0); + } + + private: + string m_path; + }; + class backlight_module : public inotify_module { public: using inotify_module::inotify_module; @@ -28,29 +44,22 @@ namespace modules { m_ramp = get_config_ramp(m_conf, name(), TAG_RAMP); // Build path to the file where the current/maximum brightness value is located - m_path_val = string_util::replace(PATH_BACKLIGHT_VAL, "%card%", card); - m_path_max = string_util::replace(PATH_BACKLIGHT_MAX, "%card%", card); - - if (!file_util::exists(m_path_val)) - throw module_error("backlight_module: The file '" + m_path_val + "' does not exist"); - if (!file_util::exists(m_path_max)) - throw module_error("backlight_module: The file '" + m_path_max + "' does not exist"); + m_val.filepath(string_util::replace(PATH_BACKLIGHT_VAL, "%card%", card)); + m_max.filepath(string_util::replace(PATH_BACKLIGHT_MAX, "%card%", card)); // Add inotify watch watch(string_util::replace(PATH_BACKLIGHT_VAL, "%card%", card)); } + void idle() { + sleep(75ms); + } + bool on_event(inotify_event* event) { if (event != nullptr) m_log.trace("%s: %s", name(), event->filename); - auto val = file_util::get_contents(m_path_val); - m_val = std::stoull(val.c_str(), 0, 10); - - auto max = file_util::get_contents(m_path_max); - m_max = std::stoull(max.c_str(), 0, 10); - - m_percentage = static_cast(float(m_val) / float(m_max) * 100.0f + 0.5f); + m_percentage = static_cast(m_val.read() / m_max.read() * 100.0f + 0.5f); if (m_label) { m_label->reset_tokens(); @@ -72,10 +81,6 @@ namespace modules { return true; } - void idle() { - this_thread::sleep_for(75ms); - } - private: static constexpr auto TAG_LABEL = "