Ecore_Wayland: Add keyrepeating support :) Fixes ticket #1292

This commit adds support to efl applications (elm) under wayland so
that they can get key repeats. All of this is internal and does not
require the application to do anything, which means the elm test for
notepad now works with repeating keys.



SVN revision: 75037
This commit is contained in:
Christopher Michael 2012-08-09 09:57:47 +00:00
parent bd45f13f66
commit a5e2b68c69
2 changed files with 106 additions and 4 deletions

View File

@ -151,6 +151,13 @@ struct _Ecore_Wl_Input
xkb_mod_mask_t alt_mask;
xkb_mod_mask_t shift_mask;
} xkb;
struct
{
Ecore_Fd_Handler *hdlr;
int timerfd;
unsigned int sym, key, time;
} repeat;
};
struct _Ecore_Wl_Window

View File

@ -19,6 +19,7 @@
#include "ecore_wl_private.h"
#include <sys/mman.h>
#include <sys/timerfd.h>
/* FIXME: This gives BTN_LEFT/RIGHT/MIDDLE for linux systems ...
* What about other OSs ?? */
@ -52,6 +53,7 @@ static void _ecore_wl_input_cb_keyboard_enter(void *data, struct wl_keyboard *ke
static void _ecore_wl_input_cb_keyboard_leave(void *data, struct wl_keyboard *keyboard __UNUSED__, unsigned int serial, struct wl_surface *surface);
static void _ecore_wl_input_cb_keyboard_key(void *data, struct wl_keyboard *keyboard __UNUSED__, unsigned int serial, unsigned int timestamp, unsigned int key, unsigned int state);
static void _ecore_wl_input_cb_keyboard_modifiers(void *data, struct wl_keyboard *keyboard __UNUSED__, unsigned int serial __UNUSED__, unsigned int depressed, unsigned int latched, unsigned int locked, unsigned int group);
static Eina_Bool _ecore_wl_input_cb_keyboard_repeat(void *data, Ecore_Fd_Handler *handler __UNUSED__);
static void _ecore_wl_input_cb_touch_down(void *data, struct wl_touch *touch __UNUSED__, unsigned int serial, unsigned int timestamp, struct wl_surface *surface __UNUSED__, int id __UNUSED__, wl_fixed_t x, wl_fixed_t y);
static void _ecore_wl_input_cb_touch_up(void *data, struct wl_touch *touch __UNUSED__, unsigned int serial, unsigned int timestamp, int id __UNUSED__);
static void _ecore_wl_input_cb_touch_motion(void *data, struct wl_touch *touch __UNUSED__, unsigned int timestamp, int id __UNUSED__, wl_fixed_t x, wl_fixed_t y);
@ -207,6 +209,7 @@ ecore_wl_input_cursor_default_restore(Ecore_Wl_Input *input)
ecore_wl_input_cursor_from_name_set(input, "left_ptr");
}
/* local functions */
void
_ecore_wl_input_add(Ecore_Wl_Display *ewd, unsigned int id)
{
@ -237,6 +240,14 @@ _ecore_wl_input_add(Ecore_Wl_Display *ewd, unsigned int id)
input->cursor_surface =
wl_compositor_create_surface(_ecore_wl_disp->wl.compositor);
input->repeat.timerfd =
timerfd_create(CLOCK_MONOTONIC, (TFD_CLOEXEC | TFD_NONBLOCK));
input->repeat.hdlr =
ecore_main_fd_handler_add(input->repeat.timerfd, ECORE_FD_READ,
_ecore_wl_input_cb_keyboard_repeat, input,
NULL, NULL);
ewd->input = input;
}
@ -245,6 +256,16 @@ _ecore_wl_input_del(Ecore_Wl_Input *input)
{
if (!input) return;
if (input->keyboard_focus)
{
Ecore_Wl_Window *win = NULL;
if ((win = input->keyboard_focus))
win->keyboard_device = NULL;
input->keyboard_focus = NULL;
}
if (input->drag_source) _ecore_wl_dnd_del(input->drag_source);
input->drag_source = NULL;
@ -264,6 +285,12 @@ _ecore_wl_input_del(Ecore_Wl_Input *input)
wl_list_remove(&input->link);
if (input->seat) wl_seat_destroy(input->seat);
if (input->repeat.hdlr) ecore_main_fd_handler_del(input->repeat.hdlr);
input->repeat.hdlr = NULL;
if (input->repeat.timerfd) close(input->repeat.timerfd);
input->repeat.timerfd = 0;
free(input);
}
@ -274,7 +301,6 @@ _ecore_wl_input_pointer_xy_get(int *x, int *y)
if (y) *y = _pointer_y;
}
/* local functions */
static void
_ecore_wl_input_seat_handle_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps)
{
@ -472,6 +498,7 @@ _ecore_wl_input_cb_keyboard_key(void *data, struct wl_keyboard *keyboard __UNUSE
xkb_keysym_t sym;
char string[32], key[32], keyname[32];
Ecore_Event_Key *e;
struct itimerspec ts;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
@ -480,7 +507,8 @@ _ecore_wl_input_cb_keyboard_key(void *data, struct wl_keyboard *keyboard __UNUSE
code = keycode + 8;
win = input->keyboard_focus;
if ((!win) || (win->keyboard_device != input)) return;
if ((!win) || (win->keyboard_device != input) || (!input->xkb.state))
return;
num = xkb_key_get_syms(input->xkb.state, code, &syms);
@ -522,6 +550,38 @@ _ecore_wl_input_cb_keyboard_key(void *data, struct wl_keyboard *keyboard __UNUSE
ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL);
else
ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL);
if ((!state) && (keycode == input->repeat.key))
{
input->repeat.sym = 0;
input->repeat.key = 0;
input->repeat.time = 0;
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
ts.it_value.tv_sec = 0;
ts.it_value.tv_nsec = 0;
timerfd_settime(input->repeat.timerfd, 0, &ts, NULL);
}
else if ((state) &&
((!input->repeat.key) ||
((keycode) && (keycode != input->repeat.key))))
{
input->repeat.sym = sym;
input->repeat.key = keycode;
input->repeat.time = timestamp;
/* interval after expires */
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 35 * 1000 * 1000;
/* initial expiration */
ts.it_value.tv_sec = 0;
ts.it_value.tv_nsec = 500 * 1000 * 1000;
timerfd_settime(input->repeat.timerfd, 0, &ts, NULL);
}
}
static void
@ -554,6 +614,29 @@ _ecore_wl_input_cb_keyboard_modifiers(void *data, struct wl_keyboard *keyboard _
input->modifiers |= MOD_SHIFT_MASK;
}
static Eina_Bool
_ecore_wl_input_cb_keyboard_repeat(void *data, Ecore_Fd_Handler *handler __UNUSED__)
{
Ecore_Wl_Input *input;
Ecore_Wl_Window *win = NULL;
unsigned long long int xp;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!(input = data)) return ECORE_CALLBACK_RENEW;
/* Trap for EAGAIN */
if (read(input->repeat.timerfd, &xp, sizeof(xp)) != sizeof(xp))
return ECORE_CALLBACK_RENEW;
if ((win = input->keyboard_focus))
_ecore_wl_input_cb_keyboard_key(input, NULL, input->display->serial,
input->repeat.time,
input->repeat.key, EINA_TRUE);
return ECORE_CALLBACK_RENEW;
}
static void
_ecore_wl_input_cb_pointer_enter(void *data, struct wl_pointer *pointer __UNUSED__, unsigned int serial, struct wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy)
{
@ -693,6 +776,18 @@ _ecore_wl_input_cb_keyboard_leave(void *data, struct wl_keyboard *keyboard __UNU
if (!surface) return;
if (!(input = data)) return;
if (input->repeat.timerfd)
{
struct itimerspec ts;
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
ts.it_value.tv_sec = 0;
ts.it_value.tv_nsec = 0;
timerfd_settime(input->repeat.timerfd, 0, &ts, NULL);
}
if (!input->timestamp)
{
struct timeval tv;
@ -707,9 +802,9 @@ _ecore_wl_input_cb_keyboard_leave(void *data, struct wl_keyboard *keyboard __UNU
if (!(win = wl_surface_get_user_data(surface))) return;
win->keyboard_device = NULL;
input->keyboard_focus = NULL;
_ecore_wl_input_focus_out_send(input, win, input->timestamp);
input->keyboard_focus = NULL;
}
static void