#include "Touchpad.h" #include #include #include #include #include "log.h" namespace fs = std::filesystem; namespace { fs::path eventfile_from_index(int i) { fs::path result{"/dev/input/event"}; result += fs::path{std::to_string(i)}; return result; } libevdev* get_evdev(int& result_fd) { for (int i = 0; ; ++i) { fs::path filename = eventfile_from_index(i); if (!fs::exists(filename)) { log_cout << "Warning: No suitable evdev device found.\n"; return nullptr; } int fd = open(filename.string().c_str(), O_RDONLY | O_NONBLOCK); if (fd < 0) { log_cout << fmt::format("Warning: evdev open() failed for {}", filename.string()) << std::endl; continue; } libevdev* result{}; int rc = libevdev_new_from_fd(fd, &result); if (rc < 0) { log_cout << fmt::format("Warning: Failed to init libevdev ({})\n", strerror(-rc)); continue; } if (!libevdev_has_event_type(result, EV_REL) || !libevdev_has_event_code(result, EV_KEY, BTN_LEFT) || !libevdev_has_event_code(result, EV_KEY, BTN_RIGHT)) { // Not the correct device continue; } log_cout << fmt::format("evdev using: Input device name: \"{}\"\n", libevdev_get_name(result)); log_cout << fmt::format("evdev using: Input device ID: bus {:x} vendor {:x} product {:x}\n", libevdev_get_id_bustype(result), libevdev_get_id_vendor(result), libevdev_get_id_product(result)); result_fd = fd; return result; } } void free_evdev(libevdev* evdev, int fd) { if (evdev) { libevdev_free(evdev); close(fd); } } } Touchpad::Touchpad(): m_fd{}, m_dev{}, m_valid{}, m_ev{} { m_dev = get_evdev(m_fd); if (m_dev != nullptr) { m_valid = true; } } Touchpad::~Touchpad() { free_evdev(m_dev, m_fd); } bool Touchpad::is_valid() { return m_valid; } bool Touchpad::event_available() { if (!m_valid) { return false; } if (m_ev.has_value()) { return true; } input_event ev{}; int rc = libevdev_next_event(m_dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); if (rc != 0) { return false; } log_cout << fmt::format("Event: {} {} {}\n", libevdev_event_type_get_name(ev.type), libevdev_event_code_get_name(ev.type, ev.code), ev.value); m_ev = ev; return true; } input_event Touchpad::get_event() { if (m_ev.has_value()) { input_event result = *m_ev; m_ev.reset(); return result; } input_event ev{}; int rc = libevdev_next_event(m_dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); if (rc != 0) { throw std::runtime_error("Touchpad::get_event() couldn't read event"); } log_cout << fmt::format("Event: {} {} {}\n", libevdev_event_type_get_name(ev.type), libevdev_event_code_get_name(ev.type, ev.code), ev.value); return ev; } bool Touchpad::event_is_button1(const input_event& ev) { return ev.type == EV_KEY && ev.code == BTN_LEFT && ev.value == 0; // Press down } bool Touchpad::event_is_button2(const input_event& ev) { return ev.type == EV_KEY && ev.code == BTN_RIGHT && ev.value == 0; // Press down }