diff --git a/include/modules/backlight.hpp b/include/modules/backlight.hpp index 81e2516a..a2ce878d 100644 --- a/include/modules/backlight.hpp +++ b/include/modules/backlight.hpp @@ -50,6 +50,8 @@ class Backlight : public ALabel { template static void enumerate_devices(ForwardIt first, ForwardIt last, Inserter inserter, udev *udev); + bool handleScroll(GdkEventScroll* e); + const std::string preferred_device_; static constexpr int EPOLL_MAX_EVENTS = 16; diff --git a/man/waybar-backlight.5.scd b/man/waybar-backlight.5.scd index 9c8ba791..ca3d922b 100644 --- a/man/waybar-backlight.5.scd +++ b/man/waybar-backlight.5.scd @@ -58,16 +58,25 @@ The *backlight* module displays the current backlight level. *on-scroll-up*: ++ typeof: string ++ - Command to execute when performing a scroll up on the module. + Command to execute when performing a scroll up on the module. This replaces the default behaviour of brightness control. *on-scroll-down*: ++ typeof: string - Command to execute when performing a scroll down on the module. + Command to execute when performing a scroll down on the module. This replaces the default behaviour of brightness control. *smooth-scrolling-threshold*: ++ typeof: double Threshold to be used when scrolling. +*reverse-scrolling*: ++ + typeof: bool ++ + Option to reverse the scroll direction. + +*scroll-step*: ++ + typeof: float ++ + default: 1.0 ++ + The speed in which to change the brightness when scrolling. + # EXAMPLE: ``` diff --git a/src/modules/backlight.cpp b/src/modules/backlight.cpp index 77c1dc0e..65eb11ad 100644 --- a/src/modules/backlight.cpp +++ b/src/modules/backlight.cpp @@ -106,6 +106,10 @@ waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value & dp.emit(); } + // Set up scroll handler + event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); + event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &Backlight::handleScroll)); + udev_thread_ = [this] { std::unique_ptr udev{udev_new()}; check_nn(udev.get(), "Udev new failed"); @@ -264,3 +268,71 @@ void waybar::modules::Backlight::enumerate_devices(ForwardIt first, ForwardIt la upsert_device(first, last, inserter, dev.get()); } } + +bool waybar::modules::Backlight::handleScroll(GdkEventScroll *e) { + // Check if the user has set a custom command for scrolling + if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) { + return AModule::handleScroll(e); + } + + // Check scroll direction + auto dir = AModule::getScrollDir(e); + if (dir == SCROLL_DIR::NONE) { + return true; + } + + if (config_["reverse-scrolling"].asBool()) { + if (dir == SCROLL_DIR::UP) { + dir = SCROLL_DIR::DOWN; + } else if (dir == SCROLL_DIR::DOWN) { + dir = SCROLL_DIR::UP; + } + } + + // Get scroll step + double step = 1; + + if (config_["scroll-step"].isDouble()) { + step = config_["scroll-step"].asDouble(); + } + + // Get the best device + decltype(devices_) devices; + { + std::scoped_lock lock(udev_thread_mutex_); + devices = devices_; + } + const auto best = best_device(devices.cbegin(), devices.cend(), preferred_device_); + + if (best == nullptr) { + return true; + } + + // Compute the absolute step + const auto abs_step = static_cast(round(step * best->get_max() / 100.0f)); + + // Compute the new value + int new_value = best->get_actual(); + + if (dir == SCROLL_DIR::UP) { + new_value += abs_step; + } else if (dir == SCROLL_DIR::DOWN) { + new_value -= abs_step; + } + + // Clamp the value + new_value = std::clamp(new_value, 0, best->get_max()); + + // Get a udev instance + std::unique_ptr udev{udev_new()}; + check_nn(udev.get(), "Udev new failed"); + + // Get the udev device + std::unique_ptr dev{udev_device_new_from_subsystem_sysname(udev.get(), "backlight", std::string(best->name()).c_str())}; + check_nn(dev.get(), "Udev device new failed"); + + // Set the new value + udev_device_set_sysattr_value(dev.get(), "brightness", std::to_string(new_value).c_str()); + + return true; +}