2 * Copyright © 2021 Samsung Electronics co., Ltd. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 #include "wayland-input.h"
25 #include "mmi-keyboard-provider.h"
26 #include <mmi-manager-dbg.h>
27 #include <mmi-common.h>
35 #include <wayland-client.h>
36 #include <xkbcommon/xkbcommon.h>
37 #include <tizen-extension-client-protocol.h>
39 struct wl_display *display = NULL;
40 struct wl_registry *registry = NULL;
41 struct wl_seat *seat = NULL;
42 struct wl_keyboard *keyboard = NULL;
43 struct tizen_keyrouter *tz_keyrouter = NULL;
45 struct xkb_context *xkb_context;
46 struct xkb_keymap *keymap;
48 Ecore_Fd_Handler *fd_hdl;
50 typedef struct tizen_keyrouter_notify tizen_keyrouter_notify_t;
51 struct tizen_keyrouter_notify
58 typedef struct keycode_map keycode_map_t;
62 xkb_keycode_t *keycodes;
66 typedef struct keymap_info keymap_info_t;
73 unsigned int has_keymap = 0;
74 unsigned int set_keymap = 0;
76 // wl_registry listener
77 static void handle_global(void *, struct wl_registry *, unsigned int, const char *, unsigned int);
78 static void handle_global_remove(void *, struct wl_registry *, unsigned int);
81 static void seat_capabilities(void *, struct wl_seat *, enum wl_seat_capability);
82 static void seat_name(void *data, struct wl_seat *seat, const char *name);
84 // wl_keyboard listener
85 static void keyboard_keymap(void *, struct wl_keyboard *, unsigned int, int fd, unsigned int);
86 static void keyboard_enter(void *, struct wl_keyboard *, unsigned int, struct wl_surface *, struct wl_array *);
87 static void keyboard_leave(void *, struct wl_keyboard *, unsigned int, struct wl_surface *);
88 static void keyboard_key(void *, struct wl_keyboard *, unsigned int, unsigned int, unsigned int, unsigned int);
89 static void keyboard_modifiers(void *, struct wl_keyboard *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int);
90 static void keyboard_repeat_setup(void *, struct wl_keyboard *, int32_t, int32_t);
92 // tizen_keyrouter listener
93 static void keygrab_notify(void *data, struct tizen_keyrouter *tizen_keyrouter, struct wl_surface *surface, uint32_t key, uint32_t mode, uint32_t error);
94 static void keygrab_notify_list(void *data, struct tizen_keyrouter *tizen_keyrouter, struct wl_surface *surface, struct wl_array *notify_result);
95 static void getgrab_notify_list(void *data, struct tizen_keyrouter *tizen_keyrouter, struct wl_surface *surface, struct wl_array *notify_result);
96 static void set_register_none_key(void *data, struct tizen_keyrouter *tizen_keyrouter, struct wl_surface *surface, uint32_t mode);
97 static void keyregister_notify(void *data, struct tizen_keyrouter *tizen_keyrouter, uint32_t status);
98 static void set_input_config(void *data, struct tizen_keyrouter *tizen_keyrouter, uint32_t status);
99 static void key_cancel(void *data, struct tizen_keyrouter *tizen_keyrouter, uint32_t key);
101 static const struct wl_registry_listener registry_listener = {
103 handle_global_remove,
106 static const struct wl_seat_listener seat_listener = {
111 static const struct wl_keyboard_listener keyboard_listener = {
117 keyboard_repeat_setup,
120 static const struct tizen_keyrouter_listener keyrouter_listener = {
124 set_register_none_key,
131 handle_global(void *data, struct wl_registry *registry, unsigned int id, const char *interface, unsigned int version)
133 if (!strcmp("wl_seat", interface))
135 seat = wl_registry_bind(registry, id, &wl_seat_interface, 4);
136 wl_seat_add_listener(seat, &seat_listener, NULL);
138 else if (!strcmp("tizen_keyrouter", interface))
140 tz_keyrouter = wl_registry_bind(registry, id, &tizen_keyrouter_interface, 1);
141 tizen_keyrouter_add_listener(tz_keyrouter, &keyrouter_listener, NULL);
146 handle_global_remove(void *data, struct wl_registry *registry, unsigned int id)
153 seat_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps)
155 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD))
159 wl_keyboard_release(keyboard);
163 keyboard = wl_seat_get_keyboard(seat);
166 LOGE("Failed to get wl_keyboard from a seat !\n");
169 wl_keyboard_add_listener(keyboard, &keyboard_listener, NULL);
170 LOGD("seat caps update : keyboard added\n");
172 else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && (keyboard))
174 wl_keyboard_release(keyboard);
180 seat_name(void *data, struct wl_seat *seat, const char *name)
187 keyboard_keymap(void *data, struct wl_keyboard *keyboard, unsigned int format, int fd, unsigned int size)
191 LOGD("...WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1=%d, WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP=%d\n",
192 WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP);
193 LOGD("... format=%d, fd=%d, size=%d\n", format, fd, size);
197 LOGE("... This client failed to make xkb context\n");
201 if (format == WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP)
207 LOGD("wl_keyboard has keymap...\n");
208 map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
209 if(map == MAP_FAILED)
211 LOGE("... Failed to mmap from fd(%d) size(%d)\n", fd, size);
216 if(keymap) xkb_map_unref(keymap);
217 keymap = xkb_map_new_from_string(xkb_context, map, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
219 LOGE("... Failed to get keymap from fd(%d)\n", fd);
230 LOGD("has_keymap = %s\n", has_keymap ? "true" : "false");
235 keyboard_enter(void *data, struct wl_keyboard *keyboard, unsigned int serial, struct wl_surface *surface, struct wl_array *keys)
244 keyboard_leave(void *data, struct wl_keyboard *keyboard, unsigned int serial, struct wl_surface *surface)
252 _covert_kernel_keycode_to_user_keycode(unsigned int kernel_keycode)
254 LOGD("kernel keycode : %d, user keycode : %d\n", kernel_keycode, kernel_keycode+8);
255 return (kernel_keycode+8);
259 _input_event_key_cb_free(void *data EINA_UNUSED, void *event)
261 mmi_provider_event_key *ev = event;
268 _input_add_key_event(unsigned int keycode, unsigned int state, unsigned int timestamp)
270 const char * name = NULL;
272 if((name = xkb_keymap_key_get_name(keymap, keycode)))
274 LOGD("key name = %s, keycode = %d\n", name, keycode);
276 mmi_provider_event_key *ev = calloc(1, sizeof(mmi_provider_event_key));
279 ev->type = MMI_EVENT_KEY_TYPE_DOWN;
281 ev->type = MMI_EVENT_KEY_TYPE_UP;
282 ev->timestamp = timestamp;
283 ev->keycode = keycode;
284 ev->key_down = state;
285 ev->keyname = strdup(name);
287 LOGI("type = %s, keyname = %s, key = %d, time = %d", (ev->type)?"MMI_EVENT_KEY_TYPE_DOWN":"MMI_EVENT_KEY_TYPE_UP", ev->keyname, ev->keycode, ev->timestamp);
288 ecore_event_add(MMI_PROVIDER_EVENT_KEY, ev, _input_event_key_cb_free, NULL);
291 LOGD("No matched keyname from keycode = %d\n", keycode);
293 LOGI("MMI_PROVIDER_EVENT_KEY has been added !\n");
297 keyboard_key(void *data, struct wl_keyboard *keyboard, unsigned int serial, unsigned int timestamp, unsigned int keycode, unsigned int state)
299 unsigned int user_keycode = _covert_kernel_keycode_to_user_keycode(keycode);
301 LOGD("... serial=%d, time=%d, key=%d, state=%d\n", serial, timestamp, user_keycode, state);
304 //TODO : do anything with the given keycode
305 // ex> call application callback(s)
306 LOGD("keycode : %d, state : %d, timestamp : %d\n", user_keycode, state, timestamp);
310 LOGD("has_keymap | keycode : %d, state : %d, timestamp : %d\n", user_keycode, state, timestamp);
311 if(_provider_mode == MODALITY_PROVIDER_MODE_PROPAGATE_EVENT)
313 _input_add_key_event(user_keycode, state, timestamp);
319 keyboard_modifiers(void *data, struct wl_keyboard *keyboard, unsigned int serial, unsigned int depressed, unsigned int latched, unsigned int locked, unsigned int group)
330 keyboard_repeat_setup(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay)
338 keygrab_notify(void *data, struct tizen_keyrouter *tizen_keyrouter, struct wl_surface *surface, uint32_t key, uint32_t mode, uint32_t error)
340 LOGD("key : %d, mode : %d, error : %d\n", key, mode, error);
344 keygrab_notify_list(void *data, struct tizen_keyrouter *tizen_keyrouter, struct wl_surface *surface, struct wl_array *notify_result)
346 tizen_keyrouter_notify_t *tz_keyrouter_notify;
347 struct wl_array array;
349 wl_array_init(&array);
350 wl_array_copy(&array, notify_result);
352 wl_array_for_each(tz_keyrouter_notify, &array)
354 LOGD("... keygrab result ! (keycode : %d, mode : %d, error : %d)\n",
355 tz_keyrouter_notify->keycode, tz_keyrouter_notify->mode, tz_keyrouter_notify->error);
358 wl_array_release(&array);
361 static void getgrab_notify_list(void *data, struct tizen_keyrouter *tizen_keyrouter, struct wl_surface *surface, struct wl_array *notify_result)
363 (void) tizen_keyrouter;
365 (void) notify_result;
368 static void set_register_none_key(void *data, struct tizen_keyrouter *tizen_keyrouter, struct wl_surface *surface, uint32_t mode)
370 (void) tizen_keyrouter;
375 static void keyregister_notify(void *data, struct tizen_keyrouter *tizen_keyrouter, uint32_t status)
377 (void) tizen_keyrouter;
381 static void set_input_config(void *data, struct tizen_keyrouter *tizen_keyrouter, uint32_t status)
383 (void) tizen_keyrouter;
387 static void key_cancel(void *data, struct tizen_keyrouter *tizen_keyrouter, uint32_t key)
389 (void) tizen_keyrouter;
393 int _xkb_context_init(void)
395 xkb_context = xkb_context_new(0);
398 LOGE("Failed to get xkb_context!\n");
404 void _xkb_context_shutdown(void)
409 xkb_context_unref(xkb_context);
413 _find_keycode(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
415 keycode_map_t *found_keycodes = (keycode_map_t *)data;
416 xkb_keysym_t keysym = found_keycodes->keysym;
418 const xkb_keysym_t *syms_out = NULL;
419 xkb_keycode_t *tmp_keycodes = NULL;
423 LOGE("Invalied keymap \n");
427 nsyms = xkb_keymap_key_get_syms_by_level(keymap, key, 0, 0, &syms_out);
429 if (nsyms && syms_out)
431 if (*syms_out == keysym)
433 tmp_keycodes = calloc(1, sizeof(int)*(found_keycodes->nkeycodes+1));
437 memcpy(tmp_keycodes, found_keycodes->keycodes, sizeof(int)*found_keycodes->nkeycodes);
438 free(found_keycodes->keycodes);
440 found_keycodes->nkeycodes++;
441 found_keycodes->keycodes = tmp_keycodes;
442 found_keycodes->keycodes[found_keycodes->nkeycodes-1] = key;
448 int _get_keycode_from_keysym(struct xkb_keymap *keymap, xkb_keysym_t keysym, xkb_keycode_t **keycodes)
450 keycode_map_t found_keycodes = {0,};
451 found_keycodes.keysym = keysym;
455 LOGE("Invalied keymap \n");
459 xkb_keymap_key_for_each(keymap, _find_keycode, &found_keycodes);
461 *keycodes = found_keycodes.keycodes;
462 return found_keycodes.nkeycodes;
465 void _do_keygrab(const char *keyname, uint32_t mode)
467 xkb_keysym_t keysym = 0x0;
469 xkb_keycode_t *keycodes = NULL;
472 keysym = xkb_keysym_from_name(keyname, XKB_KEYSYM_NO_FLAGS);
473 nkeycodes = _get_keycode_from_keysym(keymap, keysym, &keycodes);
476 LOGE("Failed do keygrab on %s(%d)\n", keyname, keysym);
482 for(i=0; i<nkeycodes; i++)
484 tizen_keyrouter_set_keygrab(tz_keyrouter, NULL, keycodes[i], mode);
489 static keymap_info_t stored_keymap[] = {
490 { "XF86Back", TIZEN_KEYROUTER_MODE_EXCLUSIVE },
491 { "XF86Info", TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE}
494 void _keygrab_init(void)
497 int size = sizeof(stored_keymap)/sizeof(keymap_info_t);
499 LOGD("stored keymap size = %d\n", size);
500 for(i=0; i < size; i++)
502 LOGD("stored keymap %d = %s, %d\n", i, stored_keymap[i].keyname, stored_keymap[i].mode);
503 _do_keygrab(stored_keymap[i].keyname, stored_keymap[i].mode);
508 _cb_handle_data(void *data, Ecore_Fd_Handler *hdl)
511 if(ecore_main_fd_handler_active_get(hdl, ECORE_FD_ERROR))
513 LOGE("Received error on wayland display fd");
517 if(ecore_main_fd_handler_active_get(hdl, ECORE_FD_READ))
519 ret = wl_display_dispatch(display);
521 else if(ecore_main_fd_handler_active_get(hdl, ECORE_FD_WRITE))
523 ret = wl_display_flush(display);
525 ecore_main_fd_handler_active_set(hdl, ECORE_FD_READ);
529 if((ret < 0) && (errno != EAGAIN) && (errno != EINVAL))
532 return ECORE_CALLBACK_RENEW;
536 LOGE("Wayland Socket Error : %s\n", eina_error_msg_get(errno));
537 return ECORE_CALLBACK_CANCEL;
543 const char *socket_name = NULL;
545 socket_name = getenv("WAYLAND_DISPLAY");
546 LOGD("socket name = %s\n", socket_name);
549 LOGD("NO has socket name\n");
550 socket_name = "wayland-0";
552 if (!getenv("XDG_RUNTIME_DIR"))
554 LOGD("no xdg runtime dir\n");
555 setenv("XDG_RUNTIME_DIR", "/run", 1);
558 display = wl_display_connect(socket_name);
561 LOGE("Failed to connect wayland display (socket_name = %s) !\n", socket_name);
565 res = _xkb_context_init();
568 LOGE("Failed to init xkb\n");
571 registry = wl_display_get_registry(display);
574 LOGE("Failed to get registry\n");
577 wl_registry_add_listener(registry, ®istry_listener, NULL);
579 fd_hdl = ecore_main_fd_handler_add(wl_display_get_fd(display),
580 (ECORE_FD_READ | ECORE_FD_WRITE | ECORE_FD_ERROR),
581 _cb_handle_data, NULL, NULL, NULL);
585 LOGE("Failed to add ecore fd(%d, wl.display) handler\n", wl_display_get_fd(display));
586 wl_registry_destroy(registry);
587 wl_display_disconnect(display);
594 wl_display_roundtrip(display);
597 void _wl_shutdown(void)
599 tizen_keyrouter_destroy(tz_keyrouter);
600 wl_keyboard_release(keyboard);
601 wl_seat_destroy(seat);
602 wl_display_disconnect(display);
605 void _keymap_shutdown(void)
607 if(keymap) xkb_map_unref(keymap);
610 void wayland_input_init(void)
616 void wayland_input_shutdown(void)
620 _xkb_context_shutdown();