Wayland: Use a timerfd for key repeat

This commit is contained in:
Emmanuel Gil Peyrot 2018-01-30 16:22:25 +01:00 committed by linkmauve
parent c14a35e21e
commit 90f5edc0b8
3 changed files with 45 additions and 3 deletions

View File

@ -32,6 +32,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/timerfd.h>
#include <unistd.h> #include <unistd.h>
#include <wayland-client.h> #include <wayland-client.h>
@ -365,6 +366,7 @@ static void keyboardHandleKey(void* data,
int keyCode; int keyCode;
int action; int action;
_GLFWwindow* window = _glfw.wl.keyboardFocus; _GLFWwindow* window = _glfw.wl.keyboardFocus;
struct itimerspec timer = {};
if (!window) if (!window)
return; return;
@ -377,7 +379,20 @@ static void keyboardHandleKey(void* data,
_glfw.wl.xkb.modifiers); _glfw.wl.xkb.modifiers);
if (action == GLFW_PRESS) if (action == GLFW_PRESS)
{
inputChar(window, key); inputChar(window, key);
if (_glfw.wl.keyboardRepeatRate > 0)
{
_glfw.wl.keyboardLastKey = keyCode;
_glfw.wl.keyboardLastScancode = key;
timer.it_interval.tv_sec = _glfw.wl.keyboardRepeatRate / 1000;
timer.it_interval.tv_nsec = (_glfw.wl.keyboardRepeatRate % 1000) * 1000000;
timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
}
}
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
} }
static void keyboardHandleModifiers(void* data, static void keyboardHandleModifiers(void* data,
@ -822,6 +837,10 @@ int _glfwPlatformInit(void)
_glfwInitTimerPOSIX(); _glfwInitTimerPOSIX();
_glfw.wl.timerfd = -1;
if (_glfw.wl.seatVersion >= 4)
_glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
if (_glfw.wl.pointer && _glfw.wl.shm) if (_glfw.wl.pointer && _glfw.wl.shm)
{ {
_glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm); _glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);

View File

@ -208,6 +208,9 @@ typedef struct _GLFWlibraryWayland
int32_t keyboardRepeatRate; int32_t keyboardRepeatRate;
int32_t keyboardRepeatDelay; int32_t keyboardRepeatDelay;
int keyboardLastKey;
int keyboardLastScancode;
int timerfd;
short int keycodes[256]; short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1]; short int scancodes[GLFW_KEY_LAST + 1];

View File

@ -35,6 +35,7 @@
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/timerfd.h>
#include <poll.h> #include <poll.h>
@ -442,7 +443,9 @@ handleEvents(int timeout)
struct wl_display* display = _glfw.wl.display; struct wl_display* display = _glfw.wl.display;
struct pollfd fds[] = { struct pollfd fds[] = {
{ wl_display_get_fd(display), POLLIN }, { wl_display_get_fd(display), POLLIN },
{ _glfw.wl.timerfd, POLLIN },
}; };
char buf[8];
while (wl_display_prepare_read(display) != 0) while (wl_display_prepare_read(display) != 0)
wl_display_dispatch_pending(display); wl_display_dispatch_pending(display);
@ -462,10 +465,27 @@ handleEvents(int timeout)
return; return;
} }
if (poll(fds, 1, timeout) > 0) if (poll(fds, 2, timeout) > 0)
{ {
wl_display_read_events(display); if (fds[0].revents & POLLIN)
wl_display_dispatch_pending(display); {
wl_display_read_events(display);
wl_display_dispatch_pending(display);
}
else
{
wl_display_cancel_read(display);
}
if (fds[1].revents & POLLIN)
{
_glfwInputKey(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastKey,
_glfw.wl.keyboardLastScancode, GLFW_REPEAT,
_glfw.wl.xkb.modifiers);
// Required to mark the fd as clean.
read(_glfw.wl.timerfd, &buf, 8);
}
} }
else else
{ {