Search for device automatically if none given

This commit is contained in:
Grant Moyer 2021-02-07 21:05:34 -05:00
parent 6fdbc27998
commit 08e886ebc6
3 changed files with 52 additions and 25 deletions

View File

@ -24,6 +24,8 @@ class KeyboardState : public AModule {
auto update() -> void; auto update() -> void;
private: private:
static auto openDevice(const std::string&) -> std::pair<int, libevdev*>;
const Bar& bar_; const Bar& bar_;
Gtk::Box box_; Gtk::Box box_;
Gtk::Label numlock_label_; Gtk::Label numlock_label_;
@ -37,7 +39,6 @@ class KeyboardState : public AModule {
std::string icon_locked_; std::string icon_locked_;
std::string icon_unlocked_; std::string icon_unlocked_;
std::string dev_path_;
int fd_; int fd_;
libevdev* dev_; libevdev* dev_;

View File

@ -25,13 +25,12 @@
// }, // },
"keyboard_state": { "keyboard_state": {
"numlock": true, "numlock": true,
"capslock": true,
"format": "{name} {icon}", "format": "{name} {icon}",
"format-icons": { "format-icons": {
"locked": "", "locked": "",
"unlocked": "" "unlocked": ""
}, }
"capslock": true,
"device-path": "/dev/input/by-path/platform-i8042-serio-0-event-kbd"
}, },
"sway/mode": { "sway/mode": {
"format": "<span style=\"italic\">{}</span>" "format": "<span style=\"italic\">{}</span>"

View File

@ -1,5 +1,6 @@
#include "modules/keyboard_state.hpp" #include "modules/keyboard_state.hpp"
#include <filesystem> #include <filesystem>
#include <spdlog/spdlog.h>
extern "C" { extern "C" {
#include <sys/types.h> #include <sys/types.h>
@ -28,8 +29,9 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
: "locked"), : "locked"),
icon_unlocked_(config_["format-icons"]["unlocked"].isString() icon_unlocked_(config_["format-icons"]["unlocked"].isString()
? config_["format-icons"]["unlocked"].asString() ? config_["format-icons"]["unlocked"].asString()
: "unlocked") : "unlocked"),
{ fd_(0),
dev_(nullptr) {
box_.set_name("keyboard_state"); box_.set_name("keyboard_state");
if (config_["numlock"].asBool()) { if (config_["numlock"].asBool()) {
box_.pack_end(numlock_label_, false, false, 0); box_.pack_end(numlock_label_, false, false, 0);
@ -46,26 +48,28 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
event_box_.add(box_); event_box_.add(box_);
if (config_["device-path"].isString()) { if (config_["device-path"].isString()) {
dev_path_ = config_["device-path"].asString(); std::string dev_path = config_["device-path"].asString();
std::tie(fd_, dev_) = openDevice(dev_path);
} else { } else {
dev_path_ = ""; DIR* dev_dir = opendir("/dev/input");
if (dev_dir == nullptr) {
throw std::runtime_error("Failed to open /dev/input");
} }
dirent *ep;
fd_ = open(dev_path_.c_str(), O_NONBLOCK | O_CLOEXEC | O_RDONLY); while ((ep = readdir(dev_dir))) {
if (fd_ < 0) { if (ep->d_type != DT_CHR) continue;
throw std::runtime_error("Can't open " + dev_path_); std::string dev_path = std::string("/dev/input/") + ep->d_name;
try {
std::tie(fd_, dev_) = openDevice(dev_path);
spdlog::info("Found device {} at '{}'", libevdev_get_name(dev_), dev_path);
break;
} catch (const std::runtime_error& e) {
continue;
} }
int err = libevdev_new_from_fd(fd_, &dev_);
if (err < 0) {
throw std::runtime_error("Can't create libevdev device");
} }
if (!libevdev_has_event_type(dev_, EV_LED)) { if (dev_ == nullptr) {
throw std::runtime_error("Device doesn't support LED events"); throw std::runtime_error("Failed to find keyboard device");
} }
if (!libevdev_has_event_code(dev_, EV_LED, LED_NUML)
|| !libevdev_has_event_code(dev_, EV_LED, LED_CAPSL)
|| !libevdev_has_event_code(dev_, EV_LED, LED_SCROLLL)) {
throw std::runtime_error("Device doesn't support num lock, caps lock, or scroll lock events");
} }
thread_ = [this] { thread_ = [this] {
@ -82,6 +86,29 @@ waybar::modules::KeyboardState::~KeyboardState() {
} }
} }
auto waybar::modules::KeyboardState::openDevice(const std::string& path) -> std::pair<int, libevdev*> {
int fd = open(path.c_str(), O_NONBLOCK | O_CLOEXEC | O_RDONLY);
if (fd < 0) {
throw std::runtime_error("Can't open " + path);
}
libevdev* dev;
int err = libevdev_new_from_fd(fd, &dev);
if (err < 0) {
throw std::runtime_error("Can't create libevdev device");
}
if (!libevdev_has_event_type(dev, EV_LED)) {
throw std::runtime_error("Device doesn't support LED events");
}
if (!libevdev_has_event_code(dev, EV_LED, LED_NUML)
|| !libevdev_has_event_code(dev, EV_LED, LED_CAPSL)
|| !libevdev_has_event_code(dev, EV_LED, LED_SCROLLL)) {
throw std::runtime_error("Device doesn't support num lock, caps lock, or scroll lock events");
}
return std::make_pair(fd, dev);
}
auto waybar::modules::KeyboardState::update() -> void { auto waybar::modules::KeyboardState::update() -> void {
int err = LIBEVDEV_READ_STATUS_SUCCESS; int err = LIBEVDEV_READ_STATUS_SUCCESS;
while (err == LIBEVDEV_READ_STATUS_SUCCESS) { while (err == LIBEVDEV_READ_STATUS_SUCCESS) {