Files
furui/filter.c
2026-04-01 22:30:31 +09:00

108 lines
3.0 KiB
C

/*
This file is part of Furui.
Furui is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Furui is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Furui. If not, see <https://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "filter.h"
struct furui_filter *furui_filter_new(struct libevdev *dev, struct libevdev *model_keyboard, struct libevdev *model_mouse, void (*filter)(struct furui_filter *, unsigned int, unsigned int, int), void (*idle)(struct furui_filter *), struct timeval (*timeout)(struct furui_filter *), void *obj) {
struct furui_filter *new_obj;
new_obj = malloc(sizeof(struct furui_filter));
if (new_obj == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
new_obj->dev = dev;
new_obj->vkeyboard = furui_vkeyboard_new(model_keyboard);
new_obj->vmouse = furui_vmouse_new(model_mouse);
new_obj->filter = filter;
new_obj->idle = idle;
new_obj->timeout = timeout;
new_obj->obj = obj;
return new_obj;
}
void furui_filter_free(struct furui_filter *filter) {
if (filter == NULL) {
return;
}
furui_vkeyboard_free(filter->vkeyboard);
furui_vmouse_free(filter->vmouse);
free(filter);
}
int furui_filter_vkeyboard_write_event(struct furui_filter *filter, unsigned int type, unsigned int code, int value) {
return libevdev_uinput_write_event(filter->vkeyboard->dev, type, code, value);
}
int furui_filter_vmouse_write_event(struct furui_filter *filter, unsigned int type, unsigned int code, int value) {
return libevdev_uinput_write_event(filter->vmouse->dev, type, code, value);
}
static void run_filter(struct furui_filter *filter) {
int fd = libevdev_get_fd(filter->dev);
fd_set rfds;
struct timeval tv;
int retval;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv = filter->timeout(filter);
retval = select(fd + 1, &rfds, NULL, NULL, &tv);
if (retval == -1) {
perror("select");
exit(EXIT_FAILURE);
} else if (retval) {
struct input_event ev;
int rc;
do {
rc = libevdev_next_event(filter->dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
if (rc == LIBEVDEV_READ_STATUS_SYNC) {
do {
rc = libevdev_next_event(filter->dev, LIBEVDEV_READ_FLAG_SYNC, &ev);
filter->filter(filter, ev.type, ev.code, ev.value);
} while (rc == LIBEVDEV_READ_STATUS_SYNC);
} else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
filter->filter(filter, ev.type, ev.code, ev.value);
}
} while (rc == LIBEVDEV_READ_STATUS_SUCCESS);
} else {
filter->idle(filter);
}
}
int furui_filter_loop(struct furui_filter *filter) {
while (1) {
run_filter(filter);
}
/* never reached */
assert(0);
return 1;
}