Files
86Box/src/qt/evdev_mouse.cpp

131 lines
3.6 KiB
C++
Raw Normal View History

2022-02-07 15:00:02 +06:00
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Linux/FreeBSD libevdev mouse input module.
*
*
*
* Authors: Cacodemon345
*
* Copyright 2021-2022 Cacodemon345
*/
2021-12-10 01:03:20 +06:00
#include "evdev_mouse.hpp"
#include <libevdev/libevdev.h>
#include <unistd.h>
#include <fcntl.h>
#include <vector>
#include <atomic>
#include <string>
#include <tuple>
#include <QThread>
2022-11-19 08:49:04 -05:00
extern "C" {
2021-12-10 01:03:20 +06:00
#include <86box/86box.h>
#include <86box/plat.h>
#include <86box/mouse.h>
#include <poll.h>
2021-12-10 01:03:20 +06:00
}
2022-11-19 08:49:04 -05:00
static std::vector<std::pair<int, libevdev *>> evdev_mice;
static std::atomic<bool> stopped = false;
static QThread *evdev_thread;
2021-12-10 01:03:20 +06:00
static std::atomic<int> evdev_mouse_rel_x = 0, evdev_mouse_rel_y = 0;
2022-11-19 08:49:04 -05:00
void
evdev_mouse_poll()
2021-12-10 01:03:20 +06:00
{
2022-11-19 08:49:04 -05:00
if (!evdev_mice.size() || !mouse_capture) {
2021-12-10 01:03:20 +06:00
evdev_mouse_rel_x = 0;
evdev_mouse_rel_y = 0;
return;
}
2022-11-19 08:49:04 -05:00
mouse_x = evdev_mouse_rel_x;
mouse_y = evdev_mouse_rel_y;
2021-12-10 01:03:20 +06:00
evdev_mouse_rel_x = evdev_mouse_rel_y = 0;
}
2022-11-19 08:49:04 -05:00
void
evdev_thread_func()
2021-12-10 01:03:20 +06:00
{
2022-11-19 08:49:04 -05:00
struct pollfd *pfds = (struct pollfd *) calloc(evdev_mice.size(), sizeof(struct pollfd));
for (unsigned int i = 0; i < evdev_mice.size(); i++) {
pfds[i].fd = libevdev_get_fd(evdev_mice[i].second);
pfds[i].events = POLLIN;
}
2022-11-19 08:49:04 -05:00
while (!stopped) {
poll(pfds, evdev_mice.size(), 500);
2022-11-19 08:49:04 -05:00
for (unsigned int i = 0; i < evdev_mice.size(); i++) {
2021-12-10 01:03:20 +06:00
struct input_event ev;
if (pfds[i].revents & POLLIN) {
2022-11-19 08:49:04 -05:00
while (libevdev_next_event(evdev_mice[i].second, LIBEVDEV_READ_FLAG_NORMAL, &ev) == 0) {
if (ev.type == EV_REL && mouse_capture) {
if (ev.code == REL_X)
evdev_mouse_rel_x += ev.value;
if (ev.code == REL_Y)
evdev_mouse_rel_y += ev.value;
}
}
2021-12-10 01:03:20 +06:00
}
}
}
2022-11-19 08:49:04 -05:00
for (unsigned int i = 0; i < evdev_mice.size(); i++) {
2021-12-10 01:03:20 +06:00
libevdev_free(evdev_mice[i].second);
evdev_mice[i].second = nullptr;
2021-12-10 01:03:20 +06:00
close(evdev_mice[i].first);
}
free(pfds);
2021-12-10 01:03:20 +06:00
evdev_mice.clear();
}
2022-11-19 08:49:04 -05:00
void
evdev_stop()
2021-12-10 01:03:20 +06:00
{
if (evdev_thread) {
stopped = true;
evdev_thread->wait();
evdev_thread = nullptr;
}
2021-12-10 01:03:20 +06:00
}
2022-11-19 08:49:04 -05:00
void
evdev_init()
2021-12-10 01:03:20 +06:00
{
2022-11-19 08:49:04 -05:00
if (evdev_thread)
return;
for (int i = 0; i < 256; i++) {
2021-12-10 01:03:20 +06:00
std::string evdev_device_path = "/dev/input/event" + std::to_string(i);
2022-11-19 08:49:04 -05:00
int fd = open(evdev_device_path.c_str(), O_NONBLOCK | O_RDONLY);
if (fd != -1) {
libevdev *input_struct = nullptr;
int rc = libevdev_new_from_fd(fd, &input_struct);
if (rc <= -1) {
2021-12-10 01:03:20 +06:00
close(fd);
continue;
2022-11-19 08:49:04 -05:00
} else {
if (!libevdev_has_event_type(input_struct, EV_REL) || !libevdev_has_event_code(input_struct, EV_KEY, BTN_LEFT)) {
2021-12-10 01:03:20 +06:00
libevdev_free(input_struct);
close(fd);
continue;
}
evdev_mice.push_back(std::make_pair(fd, input_struct));
}
2022-11-19 08:49:04 -05:00
} else if (errno == ENOENT)
break;
2021-12-10 01:03:20 +06:00
}
2022-11-19 08:49:04 -05:00
if (evdev_mice.size() != 0) {
2021-12-10 01:03:20 +06:00
evdev_thread = QThread::create(evdev_thread_func);
evdev_thread->start();
atexit(evdev_stop);
}
}