From a5e2b68c698fd46298c21e213f5e1481375302a6 Mon Sep 17 00:00:00 2001 From: Christopher Michael Date: Thu, 9 Aug 2012 09:57:47 +0000 Subject: [PATCH] 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 --- .../src/lib/ecore_wayland/Ecore_Wayland.h | 7 ++ .../src/lib/ecore_wayland/ecore_wl_input.c | 103 +++++++++++++++++- 2 files changed, 106 insertions(+), 4 deletions(-) diff --git a/legacy/ecore/src/lib/ecore_wayland/Ecore_Wayland.h b/legacy/ecore/src/lib/ecore_wayland/Ecore_Wayland.h index a6a4acb001..8d25c06ab0 100644 --- a/legacy/ecore/src/lib/ecore_wayland/Ecore_Wayland.h +++ b/legacy/ecore/src/lib/ecore_wayland/Ecore_Wayland.h @@ -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 diff --git a/legacy/ecore/src/lib/ecore_wayland/ecore_wl_input.c b/legacy/ecore/src/lib/ecore_wayland/ecore_wl_input.c index a5f52512cb..9475c51014 100644 --- a/legacy/ecore/src/lib/ecore_wayland/ecore_wl_input.c +++ b/legacy/ecore/src/lib/ecore_wayland/ecore_wl_input.c @@ -19,6 +19,7 @@ #include "ecore_wl_private.h" #include +#include /* 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