1 #define EXECUTIVE_MODE_ENABLED
2 #define E_COMP_WL
3 #include "e.h"
4 #include <sys/mman.h>
5 #ifdef HAVE_WL_DRM
6 #include <Ecore_Drm2.h>
7 #endif
8 #include <Efl_Canvas_Wl.h>
9 
10 E_API int E_EVENT_TEXT_INPUT_PANEL_VISIBILITY_CHANGE = -1;
11 static xkb_keycode_t (*_xkb_keymap_key_by_name)(void *, const char *);
12 static void _e_comp_wl_input_context_keymap_set(struct xkb_keymap *keymap, struct xkb_context *context);
13 
14 static Eina_Hash *input_gen_modifiers;
15 
16 //the following two fields are just set by e_comp_wl_input_keymap_set if it is called before e_comp_wl is valid.
17 //when then later init is called those two fields are used in the keymap of the e_comp_wl struct
18 static struct xkb_context *cached_context;
19 static struct xkb_keymap *cached_keymap;
20 static xkb_layout_index_t choosen_group;
21 
22 static void
_e_comp_wl_input_update_seat_caps(void)23 _e_comp_wl_input_update_seat_caps(void)
24 {
25    Eina_List *l;
26    struct wl_resource *res;
27    enum wl_seat_capability caps = 0;
28 
29    if (e_comp_wl->ptr.enabled)
30      caps |= WL_SEAT_CAPABILITY_POINTER;
31    if (e_comp_wl->kbd.enabled)
32      caps |= WL_SEAT_CAPABILITY_KEYBOARD;
33    if (e_comp_wl->touch.enabled)
34      caps |= WL_SEAT_CAPABILITY_TOUCH;
35 
36    EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, res)
37      wl_seat_send_capabilities(res, caps);
38 }
39 
40 static void
_e_comp_wl_input_cb_resource_destroy(struct wl_client * client EINA_UNUSED,struct wl_resource * resource)41 _e_comp_wl_input_cb_resource_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
42 {
43    wl_resource_destroy(resource);
44 }
45 
46 static void
_e_comp_wl_input_pointer_cb_cursor_set(struct wl_client * client EINA_UNUSED,struct wl_resource * resource,uint32_t serial EINA_UNUSED,struct wl_resource * surface_resource,int32_t x,int32_t y)47 _e_comp_wl_input_pointer_cb_cursor_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial EINA_UNUSED, struct wl_resource *surface_resource, int32_t x, int32_t y)
48 {
49    E_Client *ec;
50    E_Comp_Wl_Pointer *ptr = wl_resource_get_user_data(resource);
51 
52    if (!surface_resource)
53      {
54         ptr->cursor_set = 1;
55         ptr->cursor = NULL;
56         ptr->offset.x = x;
57         ptr->offset.y = y;
58         if (ptr->entered)
59           {
60              ecore_evas_cursor_unset(e_comp->ee);
61              evas_object_hide(e_comp->pointer->o_ptr);
62           }
63         return;
64      }
65    ec = wl_resource_get_user_data(surface_resource);
66    /* I think this only happens when we've deleted the resource from
67     * the client del callback - so the client is gone and shouldn't be
68     * setting a cursor, but the surface still exists so stale requests
69     * are being processed... let's BAIL.
70     */
71    if (!ec) return;
72    ptr->cursor_set = 1;
73    ptr->cursor = ec;
74    ptr->offset.x = x;
75    ptr->offset.y = y;
76    if (ec->comp_data->pending.input)
77      eina_tiler_clear(ec->comp_data->pending.input);
78    else
79      {
80         ec->comp_data->pending.input = eina_tiler_new(65535, 65535);
81         eina_tiler_tile_size_set(ec->comp_data->pending.input, 1, 1);
82      }
83    if (!ec->re_manage)
84      {
85         ec->comp_data->cursor = ec->re_manage = 1;
86         ec->ignored = 0;
87         evas_object_layer_set(ec->frame, E_LAYER_CLIENT_PRIO);
88 
89         ec->lock_focus_out = ec->layer_block = ec->visible = ec->override = 1;
90         ec->icccm.title = eina_stringshare_add("noshadow");
91         evas_object_pass_events_set(ec->frame, 1);
92         evas_object_show(ec->frame);
93         if (e_comp_object_damage_exists(ec->frame))
94           e_comp_object_render_update_add(ec->frame);
95         ec->comp_data->mapped = 1;
96         e_client_focus_stack_set(eina_list_remove(e_client_focus_stack_get(), ec));
97         EC_CHANGED(ec);
98      }
99 
100    if (ptr->entered)
101      e_comp_wl_input_pointer_cursor_update(ptr);
102 }
103 
104 static const struct wl_pointer_interface _e_pointer_interface =
105 {
106    _e_comp_wl_input_pointer_cb_cursor_set,
107    _e_comp_wl_input_cb_resource_destroy
108 };
109 
110 static const struct wl_keyboard_interface _e_keyboard_interface =
111 {
112    _e_comp_wl_input_cb_resource_destroy
113 };
114 
115 static const struct wl_touch_interface _e_touch_interface =
116 {
117    _e_comp_wl_input_cb_resource_destroy
118 };
119 
120 static void
_e_comp_wl_input_cb_pointer_unbind(struct wl_resource * resource)121 _e_comp_wl_input_cb_pointer_unbind(struct wl_resource *resource)
122 {
123    E_Comp_Wl_Pointer *ptr = wl_resource_get_user_data(resource);
124 
125    if (ptr->cursor_set && ptr->entered)
126      e_pointer_object_set(e_comp->pointer, NULL, 0, 0);
127    e_comp_wl->ptr.resources =
128      eina_list_remove(e_comp_wl->ptr.resources, resource);
129    free(ptr);
130 }
131 
132 static void
_e_comp_wl_input_cb_pointer_get(struct wl_client * client,struct wl_resource * resource,uint32_t id)133 _e_comp_wl_input_cb_pointer_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
134 {
135    struct wl_resource *res;
136    E_Comp_Wl_Pointer *ptr;
137 
138    /* try to create pointer resource */
139    res = wl_resource_create(client, &wl_pointer_interface,
140                             wl_resource_get_version(resource), id);
141    if (!res)
142      {
143         ERR("Could not create pointer on seat %s",
144             e_comp_wl->seat.name);
145         wl_client_post_no_memory(client);
146         return;
147      }
148    ptr = E_NEW(E_Comp_Wl_Pointer, 1);
149 
150    e_comp_wl->ptr.resources =
151      eina_list_append(e_comp_wl->ptr.resources, res);
152    wl_resource_set_implementation(res, &_e_pointer_interface,
153                                  ptr,
154                                  _e_comp_wl_input_cb_pointer_unbind);
155 }
156 
157 static void
_e_comp_wl_input_cb_keyboard_unbind(struct wl_resource * resource)158 _e_comp_wl_input_cb_keyboard_unbind(struct wl_resource *resource)
159 {
160    Eina_List *l, *ll;
161    struct wl_resource *res;
162 
163    e_comp_wl->kbd.resources =
164      eina_list_remove(e_comp_wl->kbd.resources, resource);
165    EINA_LIST_FOREACH_SAFE(e_comp_wl->kbd.focused, l, ll, res)
166      {
167         if (res == resource)
168           {
169              e_comp_wl->kbd.focused =
170                eina_list_remove_list(e_comp_wl->kbd.focused, l);
171           }
172      }
173 }
174 
175 void
e_comp_wl_input_keyboard_enter_send(E_Client * ec)176 e_comp_wl_input_keyboard_enter_send(E_Client *ec)
177 {
178    struct wl_resource *res;
179    Eina_List *l;
180    uint32_t serial;
181 
182    if (!ec->comp_data->surface) return;
183 
184    if (!e_comp_wl->kbd.focused) return;
185 
186    e_comp_wl_input_keyboard_modifiers_serialize();
187 
188    serial = wl_display_next_serial(e_comp_wl->wl.disp);
189 
190    EINA_LIST_FOREACH(e_comp_wl->kbd.focused, l, res)
191      {
192         wl_keyboard_send_enter(res, serial, ec->comp_data->surface,
193                                &e_comp_wl->kbd.keys);
194         wl_keyboard_send_modifiers(res, serial,
195                                    e_comp_wl->kbd.mod_depressed,
196                                    e_comp_wl->kbd.mod_latched,
197                                    e_comp_wl->kbd.mod_locked,
198                                    e_comp_wl->kbd.mod_group);
199      }
200 }
201 
202 static void
_e_comp_wl_input_cb_keyboard_get(struct wl_client * client,struct wl_resource * resource,uint32_t id)203 _e_comp_wl_input_cb_keyboard_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
204 {
205    E_Client *focused;
206    struct wl_resource *res;
207 
208    /* try to create keyboard resource */
209    res = wl_resource_create(client, &wl_keyboard_interface,
210                             wl_resource_get_version(resource), id);
211    if (!res)
212      {
213         ERR("Could not create keyboard on seat %s", e_comp_wl->seat.name);
214         wl_client_post_no_memory(client);
215         return;
216      }
217    wl_resource_set_user_data(res, resource);
218 
219    e_comp_wl->kbd.resources =
220      eina_list_append(e_comp_wl->kbd.resources, res);
221    wl_resource_set_implementation(res, &_e_keyboard_interface,
222                                   e_comp->wl_comp_data,
223                                   _e_comp_wl_input_cb_keyboard_unbind);
224 
225    /* send current repeat_info */
226    if (wl_resource_get_version(res) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
227      wl_keyboard_send_repeat_info(res, e_config->keyboard.repeat_rate, e_config->keyboard.repeat_delay);
228 
229    /* send current keymap */
230    e_comp_wl_input_keymap_send(res);
231 
232    /* if the client owns the focused surface, we need to send an enter */
233    focused = e_client_focused_get();
234    if (!focused) return;
235 
236    if (client != wl_resource_get_client(focused->comp_data->surface)) return;
237    e_comp_wl->kbd.focused = eina_list_append(e_comp_wl->kbd.focused, res);
238 
239    e_comp_wl_input_keyboard_enter_send(focused);
240 }
241 
242 static void
_e_comp_wl_input_cb_touch_unbind(struct wl_resource * resource)243 _e_comp_wl_input_cb_touch_unbind(struct wl_resource *resource)
244 {
245    e_comp_wl->touch.resources =
246      eina_list_remove(e_comp_wl->touch.resources, resource);
247 }
248 
249 static void
_e_comp_wl_input_cb_touch_get(struct wl_client * client EINA_UNUSED,struct wl_resource * resource,uint32_t id EINA_UNUSED)250 _e_comp_wl_input_cb_touch_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id EINA_UNUSED)
251 {
252    struct wl_resource *res;
253 
254     /* try to create pointer resource */
255    res = wl_resource_create(client, &wl_touch_interface,
256                             wl_resource_get_version(resource), id);
257    if (!res)
258      {
259         ERR("Could not create touch on seat %s",
260             e_comp_wl->seat.name);
261         wl_client_post_no_memory(client);
262         return;
263      }
264 
265    e_comp_wl->touch.resources =
266      eina_list_append(e_comp_wl->touch.resources, res);
267    wl_resource_set_implementation(res, &_e_touch_interface,
268                                   e_comp->wl_comp_data,
269                                   _e_comp_wl_input_cb_touch_unbind);
270 }
271 
272 static void
_e_comp_wl_input_cb_release(struct wl_client * client EINA_UNUSED,struct wl_resource * resource)273 _e_comp_wl_input_cb_release(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
274 {
275    wl_resource_destroy(resource);
276 }
277 
278 static const struct wl_seat_interface _e_seat_interface =
279 {
280    _e_comp_wl_input_cb_pointer_get,
281    _e_comp_wl_input_cb_keyboard_get,
282    _e_comp_wl_input_cb_touch_get,
283    _e_comp_wl_input_cb_release,
284 };
285 
286 static void
_e_comp_wl_input_cb_unbind_seat(struct wl_resource * resource)287 _e_comp_wl_input_cb_unbind_seat(struct wl_resource *resource)
288 {
289    e_comp_wl->seat.resources =
290      eina_list_remove(e_comp_wl->seat.resources, resource);
291 }
292 
293 static void
_e_comp_wl_input_cb_bind_seat(struct wl_client * client,void * data EINA_UNUSED,uint32_t version,uint32_t id)294 _e_comp_wl_input_cb_bind_seat(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
295 {
296    struct wl_resource *res;
297 
298    res = wl_resource_create(client, &wl_seat_interface, version, id);
299    if (!res)
300      {
301         ERR("Could not create seat resource");
302         return;
303      }
304 
305    /* store version of seat interface for reuse in updating capabilities */
306    e_comp_wl->seat.version = version;
307    e_comp_wl->seat.resources =
308      eina_list_append(e_comp_wl->seat.resources, res);
309 
310    wl_resource_set_implementation(res, &_e_seat_interface,
311                                   e_comp->wl_comp_data,
312                                   _e_comp_wl_input_cb_unbind_seat);
313 
314    _e_comp_wl_input_update_seat_caps();
315    if (e_comp_wl->seat.version >= WL_SEAT_NAME_SINCE_VERSION)
316      wl_seat_send_name(res, e_comp_wl->seat.name);
317 }
318 
319 int
_e_comp_wl_input_keymap_fd_get(void)320 _e_comp_wl_input_keymap_fd_get(void)
321 {
322    int fd = 0, blen = 0, len = 0;
323    const char *path;
324    char tmp[PATH_MAX];
325    long flags;
326    void *mm;
327    Eina_Tmpstr *tmpstr = NULL;
328 
329    blen = sizeof(tmp) - 1;
330 
331    if (!(path = getenv("XDG_RUNTIME_DIR")))
332      return -1;
333 
334    len = strlen(path);
335    if (len < blen)
336      {
337         strcpy(tmp, path);
338         strcat(tmp, "/e-wl-keymap-XXXXXX");
339      }
340    else
341      return -1;
342 
343    if ((fd = eina_file_mkstemp(tmp, &tmpstr)) < 0) return -1;
344 
345    flags = fcntl(fd, F_GETFD);
346    if (flags < 0)
347      {
348         eina_tmpstr_del(tmpstr);
349         close(fd);
350         return -1;
351      }
352 
353    if (fcntl(fd, F_SETFD, (flags | FD_CLOEXEC)) == -1)
354      {
355         eina_tmpstr_del(tmpstr);
356         close(fd);
357         return -1;
358      }
359 
360    if (ftruncate(fd, e_comp_wl->xkb.map_size) < 0)
361      {
362         eina_tmpstr_del(tmpstr);
363         close(fd);
364         return -1;
365      }
366 
367    unlink(tmpstr);
368    eina_tmpstr_del(tmpstr);
369 
370    mm = mmap(NULL, e_comp_wl->xkb.map_size, (PROT_READ | PROT_WRITE),
371              MAP_SHARED, fd, 0);
372    if (mm == MAP_FAILED)
373      {
374         ERR("Failed to mmap keymap area: %m");
375         close(fd);
376         return -1;
377      }
378 
379    memcpy(mm, e_comp_wl->xkb.map_string, e_comp_wl->xkb.map_size);
380    munmap(mm, e_comp_wl->xkb.map_size);
381 
382    return fd;
383 }
384 
385 static void
_e_comp_wl_input_state_update(void)386 _e_comp_wl_input_state_update(void)
387 {
388    xkb_mod_mask_t latched = 0, locked = 0;
389 
390    /* unreference any existing keyboard state */
391    if (e_comp_wl->xkb.state)
392      {
393         latched =
394           xkb_state_serialize_mods(e_comp_wl->xkb.state,
395                                    XKB_STATE_MODS_LATCHED);
396         locked =
397           xkb_state_serialize_mods(e_comp_wl->xkb.state,
398                                    XKB_STATE_MODS_LOCKED);
399         xkb_state_unref(e_comp_wl->xkb.state);
400      }
401 
402    /* create a new xkb state */
403    e_comp_wl->xkb.state = xkb_state_new(e_comp_wl->xkb.keymap);
404 
405    xkb_state_update_mask(e_comp_wl->xkb.state, 0,
406                          latched, locked, e_comp_wl->kbd.choosen_group,
407                          0, 0);
408 }
409 
410 void
e_comp_wl_input_keymap_send(struct wl_resource * res)411 e_comp_wl_input_keymap_send(struct wl_resource *res)
412 {
413    int fd;
414 
415    fd = _e_comp_wl_input_keymap_fd_get();
416    if (fd == -1)
417      return;
418 
419    wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
420                            fd, e_comp_wl->xkb.map_size);
421 
422    close(fd);
423 }
424 
425 static void
nested_keymap_update(void)426 nested_keymap_update(void)
427 {
428    Eina_List *l;
429    Evas_Object *obj;
430 
431    EINA_LIST_FOREACH(e_comp_wl->efl_wls, l, obj)
432      efl_canvas_wl_seat_keymap_set(obj, NULL, e_comp_wl->xkb.state, e_comp_wl->xkb.map_string, &e_comp_wl->kbd.keys);
433 }
434 
435 static void
_e_comp_wl_input_keymap_update(struct xkb_keymap * keymap)436 _e_comp_wl_input_keymap_update(struct xkb_keymap *keymap)
437 {
438    struct wl_resource *res;
439    Eina_List *l;
440 
441    /* unreference any existing keymap */
442    if (e_comp_wl->xkb.keymap)
443      xkb_map_unref(e_comp_wl->xkb.keymap);
444 
445    /* free any existing keyboard map string */
446    free(e_comp_wl->xkb.map_string);
447    e_comp_wl->xkb.map_string = NULL;
448 
449    /* increment keymap reference */
450    e_comp_wl->xkb.keymap = keymap;
451 
452    /* update the state */
453    _e_comp_wl_input_state_update();
454 
455    if (!(e_comp_wl->xkb.map_string = xkb_map_get_as_string(keymap)))
456      {
457         ERR("Could not get keymap string");
458         return;
459      }
460 
461    e_comp_wl->xkb.map_size = strlen(e_comp_wl->xkb.map_string) + 1;
462 
463    /* send updated keymap */
464    EINA_LIST_FOREACH(e_comp_wl->kbd.resources, l, res)
465      e_comp_wl_input_keymap_send(res);
466 
467    /* update modifiers */
468    e_comp_wl_input_keyboard_modifiers_update();
469    nested_keymap_update();
470 }
471 
472 EINTERN Eina_Bool
e_comp_wl_input_init(void)473 e_comp_wl_input_init(void)
474 {
475    /* set default seat name */
476    if (!e_comp_wl->seat.name)
477      e_comp_wl->seat.name = "seat0";
478 
479    /* create the global resource for input seat */
480    e_comp_wl->seat.global =
481      wl_global_create(e_comp_wl->wl.disp, &wl_seat_interface, 4,
482                       e_comp->wl_comp_data, _e_comp_wl_input_cb_bind_seat);
483    if (!e_comp_wl->seat.global)
484      {
485         ERR("Could not create global for seat");
486         return EINA_FALSE;
487      }
488 
489    wl_array_init(&e_comp_wl->kbd.keys);
490 
491    E_EVENT_TEXT_INPUT_PANEL_VISIBILITY_CHANGE = ecore_event_type_new();
492 
493    _xkb_keymap_key_by_name = dlsym(NULL, "xkb_keymap_key_by_name");
494 
495     if (cached_keymap)
496       _e_comp_wl_input_context_keymap_set(cached_keymap, cached_context);
497     else
498       e_comp_wl_input_keymap_set(NULL, NULL, NULL, NULL, NULL);
499 
500     if (choosen_group)
501       e_comp_wl_input_keymap_index_set(choosen_group);
502     else
503       e_comp_wl_input_keymap_index_set(0);
504 
505    e_comp_wl_input_keyboard_modifiers_update();
506 
507    return EINA_TRUE;
508 }
509 
510 EINTERN void
e_comp_wl_input_shutdown(void)511 e_comp_wl_input_shutdown(void)
512 {
513    struct wl_resource *res;
514 
515    E_FREE_FUNC(input_gen_modifiers, eina_hash_free);
516 
517    /* destroy pointer resources */
518    EINA_LIST_FREE(e_comp_wl->ptr.resources, res)
519      wl_resource_destroy(res);
520 
521    /* destroy keyboard resources */
522    EINA_LIST_FREE(e_comp_wl->kbd.resources, res)
523      wl_resource_destroy(res);
524    e_comp_wl->kbd.resources = eina_list_free(e_comp_wl->kbd.resources);
525 
526    /* destroy touch resources */
527    EINA_LIST_FREE(e_comp_wl->touch.resources, res)
528      wl_resource_destroy(res);
529 
530    /* destroy e_comp_wl->kbd.keys array */
531    wl_array_release(&e_comp_wl->kbd.keys);
532 
533    /* free the string copy of the keyboard map */
534    free(e_comp_wl->xkb.map_string);
535 
536    /* unreference any existing keyboard state */
537    if (e_comp_wl->xkb.state)
538      xkb_state_unref(e_comp_wl->xkb.state);
539 
540    /* unreference any existing keymap */
541    if (e_comp_wl->xkb.keymap)
542      xkb_map_unref(e_comp_wl->xkb.keymap);
543 
544    /* unreference any existing context */
545    if (e_comp_wl->xkb.context)
546      xkb_context_unref(e_comp_wl->xkb.context);
547 
548    /* destroy the global seat resource */
549    if (e_comp_wl->seat.global)
550      wl_global_destroy(e_comp_wl->seat.global);
551    e_comp_wl->seat.global = NULL;
552 }
553 
554 EINTERN void
e_comp_wl_input_pointer_cursor_update(E_Comp_Wl_Pointer * ptr)555 e_comp_wl_input_pointer_cursor_update(E_Comp_Wl_Pointer *ptr)
556 {
557    EINA_SAFETY_ON_TRUE_RETURN(!ptr->entered);
558    if (ptr->cursor_set && (!e_comp_util_mouse_grabbed()))
559      {
560         if (ptr->cursor)
561           e_pointer_object_set(e_comp->pointer, ptr->cursor->frame, ptr->offset.x, ptr->offset.y);
562         else
563           {
564              ecore_evas_cursor_unset(e_comp->ee);
565              evas_object_hide(e_comp->pointer->o_ptr);
566           }
567      }
568    else
569      e_pointer_object_set(e_comp->pointer, NULL, 0, 0);
570 }
571 
572 EINTERN Eina_Bool
e_comp_wl_input_pointer_check(struct wl_resource * res)573 e_comp_wl_input_pointer_check(struct wl_resource *res)
574 {
575    return wl_resource_instance_of(res, &wl_pointer_interface,
576                                   &_e_pointer_interface);
577 }
578 
579 EINTERN Eina_Bool
e_comp_wl_input_keyboard_check(struct wl_resource * res)580 e_comp_wl_input_keyboard_check(struct wl_resource *res)
581 {
582    return wl_resource_instance_of(res, &wl_keyboard_interface,
583                                   &_e_keyboard_interface);
584 }
585 
586 EINTERN Eina_Bool
e_comp_wl_input_keyboard_modifiers_serialize(void)587 e_comp_wl_input_keyboard_modifiers_serialize(void)
588 {
589    Eina_Bool changed = EINA_FALSE;
590    xkb_mod_mask_t mod;
591    xkb_layout_index_t grp;
592 
593    mod = xkb_state_serialize_mods(e_comp_wl->xkb.state, XKB_STATE_DEPRESSED);
594    changed |= mod != e_comp_wl->kbd.mod_depressed;
595    e_comp_wl->kbd.mod_depressed = mod;
596 
597    mod = xkb_state_serialize_mods(e_comp_wl->xkb.state, XKB_STATE_MODS_LATCHED);
598    changed |= mod != e_comp_wl->kbd.mod_latched;
599    e_comp_wl->kbd.mod_latched = mod;
600 
601    mod = xkb_state_serialize_mods(e_comp_wl->xkb.state, XKB_STATE_MODS_LOCKED);
602    changed |= mod != e_comp_wl->kbd.mod_locked;
603    e_comp_wl->kbd.mod_locked = mod;
604 
605    grp = xkb_state_serialize_layout(e_comp_wl->xkb.state,
606                                     XKB_STATE_LAYOUT_EFFECTIVE);
607    if (grp != e_comp_wl->kbd.mod_group)
608      {
609         e_config->xkb.cur_group = grp;
610         ecore_event_add(E_EVENT_XKB_CHANGED, NULL, NULL, NULL);
611      }
612    changed |= grp != e_comp_wl->kbd.mod_group;
613    e_comp_wl->kbd.mod_group = grp;
614    return changed;
615 }
616 
617 EINTERN void
e_comp_wl_input_keyboard_modifiers_update(void)618 e_comp_wl_input_keyboard_modifiers_update(void)
619 {
620    uint32_t serial;
621    struct wl_resource *res;
622    Eina_List *l;
623 
624    if (!e_comp_wl_input_keyboard_modifiers_serialize()) return;
625 
626    if ((!e_comp_wl->kbd.focused) || e_comp->input_key_grabs) return;
627 
628    serial = wl_display_next_serial(e_comp_wl->wl.disp);
629    EINA_LIST_FOREACH(e_comp_wl->kbd.focused, l, res)
630      wl_keyboard_send_modifiers(res, serial,
631                                 e_comp_wl->kbd.mod_depressed,
632                                 e_comp_wl->kbd.mod_latched,
633                                 e_comp_wl->kbd.mod_locked,
634                                 e_comp_wl->kbd.mod_group);
635 }
636 
637 EINTERN void
e_comp_wl_input_keyboard_state_update(uint32_t keycode,Eina_Bool pressed)638 e_comp_wl_input_keyboard_state_update(uint32_t keycode, Eina_Bool pressed)
639 {
640    enum xkb_key_direction dir;
641 
642    if (!e_comp_wl->xkb.state) return;
643 
644    if (pressed) dir = XKB_KEY_DOWN;
645    else dir = XKB_KEY_UP;
646 
647    e_comp_wl->kbd.mod_changed =
648      xkb_state_update_key(e_comp_wl->xkb.state, keycode + 8, dir);
649 
650    e_comp_wl_input_keyboard_modifiers_update();
651 }
652 
653 E_API void
e_comp_wl_input_pointer_enabled_set(Eina_Bool enabled)654 e_comp_wl_input_pointer_enabled_set(Eina_Bool enabled)
655 {
656    /* check for valid compositor data */
657    if (!e_comp->wl_comp_data)
658      {
659         ERR("No compositor data");
660         return;
661      }
662 
663    e_comp_wl->ptr.enabled = !!enabled;
664    _e_comp_wl_input_update_seat_caps();
665 }
666 
667 E_API void
e_comp_wl_input_keyboard_enabled_set(Eina_Bool enabled)668 e_comp_wl_input_keyboard_enabled_set(Eina_Bool enabled)
669 {
670    /* check for valid compositor data */
671    if (!e_comp->wl_comp_data)
672      {
673         ERR("No compositor data");
674         return;
675      }
676 
677    e_comp_wl->kbd.enabled = !!enabled;
678    _e_comp_wl_input_update_seat_caps();
679 }
680 
681 static void
_e_comp_wl_input_context_keymap_set(struct xkb_keymap * keymap,struct xkb_context * context)682 _e_comp_wl_input_context_keymap_set(struct xkb_keymap *keymap, struct xkb_context *context)
683 {
684    if (e_comp_wl)
685      {
686         //we have a initializied and running compositor here
687         if (e_comp_wl->xkb.context)
688           xkb_context_unref(e_comp_wl->xkb.context);
689         e_comp_wl->xkb.context = context;
690 
691         /* update compositor keymap */
692         _e_comp_wl_input_keymap_update(keymap);
693      }
694    else
695      {
696         //we dont have a running compositor here, cache the values, init will pick them
697         cached_context = context;
698         cached_keymap = keymap;
699      }
700 
701    if (!e_comp->ee) return;
702 //set the values to the drm devices
703 #ifdef HAVE_WL_DRM
704    if (strstr(ecore_evas_engine_name_get(e_comp->ee), "drm"))
705      {
706         Ecore_Drm2_Device *dev;
707 
708         dev = ecore_evas_data_get(e_comp->ee, "device");
709         if (dev)
710           ecore_drm2_device_keyboard_info_set(dev, context, keymap,
711             e_comp_wl ? e_comp_wl->kbd.choosen_group : choosen_group);
712      }
713 #endif
714 }
715 
716 E_API void
e_comp_wl_input_keymap_index_set(xkb_layout_index_t index)717 e_comp_wl_input_keymap_index_set(xkb_layout_index_t index)
718 {
719 #ifdef HAVE_WL_DRM
720    if (e_comp && e_comp->ee && strstr(ecore_evas_engine_name_get(e_comp->ee), "drm"))
721      {
722         Ecore_Drm2_Device *dev;
723 
724         dev = ecore_evas_data_get(e_comp->ee, "device");
725         if (dev)
726           ecore_drm2_device_keyboard_group_set(dev, index);
727      }
728 #endif
729    if (e_comp_wl)
730      {
731         e_comp_wl->kbd.choosen_group = index;
732         _e_comp_wl_input_state_update();
733         e_comp_wl_input_keyboard_modifiers_update();
734         nested_keymap_update();
735      }
736    else
737      choosen_group = index;
738 }
739 
740 E_API void
e_comp_wl_input_keymap_set(const char * rules,const char * model,const char * layout,const char * variant,const char * options)741 e_comp_wl_input_keymap_set(const char *rules, const char *model, const char *layout, const char *variant, const char *options)
742 {
743    struct xkb_keymap *keymap;
744    struct xkb_context *context;
745    struct xkb_rule_names names;
746 
747    /* DBG("COMP_WL: Keymap Set: %s %s %s", rules, model, layout); */
748 
749    /* assemble xkb_rule_names so we can fetch keymap */
750    memset(&names, 0, sizeof(names));
751 
752    if (rules) names.rules = rules;
753    else names.rules = "evdev";
754 
755    if (model) names.model = model;
756    else names.model = "pc105";
757 
758    if (layout) names.layout = layout;
759    else names.layout = "us";
760 
761    if (variant) names.variant = variant;
762    else names.variant = NULL;
763 
764    if (options) names.options = options;
765    else names.options = NULL;
766 
767    /* create a new xkb context */
768    context = xkb_context_new(0);
769 
770    /* fetch new keymap based on names */
771    keymap = xkb_map_new_from_names(context, &names, 0);
772 
773    if (!keymap)
774      {
775         ERR("Failed to compile keymap");
776         return;
777      }
778 
779    _e_comp_wl_input_context_keymap_set(keymap, context);
780 }
781 
782 E_API void
e_comp_wl_input_touch_enabled_set(Eina_Bool enabled)783 e_comp_wl_input_touch_enabled_set(Eina_Bool enabled)
784 {
785    /* check for valid compositor data */
786    if (!e_comp->wl_comp_data)
787      {
788         ERR("No compositor data");
789         return;
790      }
791 
792    e_comp_wl->touch.enabled = !!enabled;
793    _e_comp_wl_input_update_seat_caps();
794 }
795 
796 EINTERN Eina_Bool
e_comp_wl_input_touch_check(struct wl_resource * res)797 e_comp_wl_input_touch_check(struct wl_resource *res)
798 {
799    return wl_resource_instance_of(res, &wl_touch_interface,
800                                   &_e_touch_interface);
801 }
802 
803 EINTERN void
e_comp_wl_input_keyboard_modifers_clear(void)804 e_comp_wl_input_keyboard_modifers_clear(void)
805 {
806    e_comp_wl->kbd.mod_depressed = 0;
807    e_comp_wl->kbd.mod_latched = 0;
808    e_comp_wl->kbd.mod_locked = 0;
809    e_comp_wl->kbd.mod_group = 0;
810 
811    e_comp_wl_input_keyboard_modifiers_serialize();
812 }
813 
814 static void
_event_generate(const char * key,const char * keyname,int mods,Eina_Bool up)815 _event_generate(const char *key, const char *keyname, int mods, Eina_Bool up)
816 {
817    Ecore_Event_Key *ev;
818    int keycode;
819 
820    keycode = _xkb_keymap_key_by_name(e_comp_wl->xkb.keymap, keyname ?: key);
821    if (keycode == -1)
822      {
823         ERR("no keycode found for key '%s'", keyname ?: key);
824         return;
825      }
826    ev = calloc(1, sizeof(Ecore_Event_Key) + (2 * (strlen(key) + 1)));
827 
828    ev->keyname = (char *)(ev + 1);
829    ev->key = ev->keyname + strlen(key) + 1;
830 
831    strcpy((char *)ev->keyname, key);
832    strcpy((char *)ev->key, key);
833 
834    ev->window = e_comp->ee_win;
835    ev->event_window = e_comp->ee_win;
836    ev->timestamp = 0;
837    ev->modifiers = mods;
838    ev->keycode = keycode;
839    ecore_event_add(up ? ECORE_EVENT_KEY_UP : ECORE_EVENT_KEY_DOWN, ev, NULL, NULL);
840 }
841 
842 static void
_event_generate_mods(int mods,Eina_Bool up)843 _event_generate_mods(int mods, Eina_Bool up)
844 {
845    if (!mods) return;
846    if (mods & ECORE_EVENT_MODIFIER_SHIFT)
847      _event_generate("Shift", "LFSH", mods, up);
848    if (mods & ECORE_EVENT_MODIFIER_CTRL)
849      _event_generate("Control_L", "LCTL", mods, up);
850    if (mods & ECORE_EVENT_MODIFIER_ALT)
851      _event_generate("Alt_L", "LALT", mods, up);
852    if (mods & ECORE_EVENT_MODIFIER_WIN)
853      _event_generate("Super_L", "LWIN", mods, up);
854    if (mods & ECORE_EVENT_MODIFIER_ALTGR)
855      _event_generate("Mode_switch", "ALGR", mods, up);
856 }
857 
858 E_API void
e_comp_wl_input_keyboard_event_generate(const char * key,int mods,Eina_Bool up)859 e_comp_wl_input_keyboard_event_generate(const char *key, int mods, Eina_Bool up)
860 {
861    const char *keyname = NULL;
862    /* assumes qwerty layout */
863    /* /usr/share/X11/xkb/keycodes/evdev */
864    static const char *keycodes[] =
865    {
866       ['`'] = "TLDE",
867       ['1'] = "AE01",
868       ['2'] = "AE02",
869       ['3'] = "AE03",
870       ['4'] = "AE04",
871       ['5'] = "AE05",
872       ['6'] = "AE06",
873       ['7'] = "AE07",
874       ['8'] = "AE08",
875       ['9'] = "AE09",
876       ['0'] = "AE10",
877       ['-'] = "AE11",
878       ['='] = "AE12",
879       //''] = "BKSP",
880       ['\t'] = "TAB",
881       ['q'] = "AD01",
882       ['w'] = "AD02",
883       ['e'] = "AD03",
884       ['r'] = "AD04",
885       ['t'] = "AD05",
886       ['y'] = "AD06",
887       ['u'] = "AD07",
888       ['i'] = "AD08",
889       ['o'] = "AD09",
890       ['p'] = "AD10",
891       ['['] = "AD11",
892       [']'] = "AD12",
893       ['\\'] = "BKSL",
894       ['\r'] = "RTRN",
895       //''] = "CAPS",
896       ['a'] = "AC01",
897       ['s'] = "AC02",
898       ['d'] = "AC03",
899       ['f'] = "AC04",
900       ['g'] = "AC05",
901       ['h'] = "AC06",
902       ['j'] = "AC07",
903       ['k'] = "AC08",
904       ['l'] = "AC09",
905       [';'] = "AC10",
906       ['\''] = "AC11",
907       //''] = "LFSH",
908       ['z'] = "AB01",
909       ['x'] = "AB02",
910       ['c'] = "AB03",
911       ['v'] = "AB04",
912       ['b'] = "AB05",
913       ['n'] = "AB06",
914       ['m'] = "AB07",
915       [','] = "AB08",
916       ['.'] = "AB09",
917       ['/'] = "AB10",
918       //''] = "RTSH",
919       [' '] = "SPCE",
920    };
921 
922    if (!_xkb_keymap_key_by_name)
923      {
924         ERR("xkbcommon >= 0.6.0 required for keyboard event generation!");
925         return;
926      }
927    EINA_SAFETY_ON_NULL_RETURN(key);
928    EINA_SAFETY_ON_TRUE_RETURN(!key[0]);
929    if (!input_gen_modifiers)
930      {
931 //<RTSH> = 62;
932 //<LALT> = 64;
933 //<LCTL> = 37;
934 //<RCTL> = 105;
935 //<RALT> = 108;
936 //<LWIN> = 133;
937 //<RWIN> = 134;
938 //<COMP> = 135;
939 //alias <MENU> = <COMP>;
940 //<ESC> = 9;
941         static const char *modcodes[] =
942         {
943            "Shift_L",
944            "LFSH",
945 
946            "Control_L",
947            "LCTL",
948 
949            "Super_L",
950            "LWIN",
951 
952            "Alt_L",
953            "LALT",
954 
955            "Escape",
956            "ESC",
957 
958            "Alt_R",
959            "RALT",
960 
961            "Super_R",
962            "RWIN",
963 
964            "Menu",
965            "MENU",
966 
967            "Control_R",
968            "RCTRL",
969 
970            "Mode_switch",
971            "ALGR",
972 
973            "Return",
974            "RTRN",
975 
976            "Caps_Lock",
977            "CAPS",
978         };
979         unsigned int i;
980 
981         input_gen_modifiers = eina_hash_string_superfast_new(NULL);
982         for (i = 0; i < EINA_C_ARRAY_LENGTH(modcodes); i += 2)
983           eina_hash_add(input_gen_modifiers, modcodes[i], modcodes[i + 1]);
984      }
985 
986    if (!up)
987      _event_generate_mods(mods, up);
988    keyname = eina_hash_find(input_gen_modifiers, key);
989    if ((!keyname) && (!key[1]))
990      {
991         if (key[0] < (int)EINA_C_ARRAY_LENGTH(keycodes))
992           keyname = keycodes[(unsigned char)key[0]];
993      }
994    _event_generate(key, keyname, mods, up);
995    if (up)
996      _event_generate_mods(mods, up);
997 }
998