ee65ceef9ea61cb5f4f5ba296978d8ee48d08f83
[platform/upstream/enlightenment.git] / src / bin / e_comp_wl_input.c
1 #define EXECUTIVE_MODE_ENABLED
2 #include "e.h"
3 #include <sys/mman.h>
4 #include <pixman.h>
5
6 #include <relative-pointer-unstable-v1-server-protocol.h>
7 #include <pointer-constraints-unstable-v1-server-protocol.h>
8
9 typedef struct _E_Comp_Wl_Pointer_Constraint E_Comp_Wl_Pointer_Constraint;
10
11 typedef enum _E_Comp_Wl_Pointer_Constraint_Type
12 {
13    E_COMP_WL_POINTER_CONSTRAINT_TYPE_NONE = 0,
14    E_COMP_WL_POINTER_CONSTRAINT_TYPE_LOCK = 1,
15    E_COMP_WL_POINTER_CONSTRAINT_TYPE_CONFINE = 2,
16 } E_Comp_Wl_Pointer_Constraint_Type;
17
18 struct _E_Comp_Wl_Pointer_Constraint
19 {
20    struct wl_list link;
21
22    E_Client *ec;
23    struct wl_resource *surface;
24    struct wl_resource *resource;
25    struct wl_resource *pointer;
26    Eina_Bool active;
27
28    E_Comp_Wl_Pointer_Constraint_Type type;
29    int lifetime;
30
31    pixman_region32_t region;
32    pixman_region32_t region_pending;
33    Eina_Bool is_region_pending;
34    Eina_Bool has_region_set;
35
36    int hint_x;
37    int hint_y;
38    wl_fixed_t hint_x_pending;
39    wl_fixed_t hint_y_pending;
40    Eina_Bool is_hint_pending;
41    Eina_Bool has_hint_set;
42
43    struct wl_listener pointer_destroy_listener;
44    struct wl_listener surface_unmap_listener;
45    struct wl_listener surface_commit_listener;
46    struct wl_listener surface_mousein_listener;
47 };
48
49 E_API int E_EVENT_TEXT_INPUT_PANEL_VISIBILITY_CHANGE = -1;
50 static Eina_Bool dont_set_e_input_keymap = EINA_FALSE;
51 static Eina_Bool dont_use_xkb_cache = EINA_FALSE;
52 static Eina_Bool use_cache_keymap = EINA_FALSE;
53
54 static E_Comp_Wl_Hook *_surface_commit_hook = NULL;
55
56 /* default XKB values from environment variables */
57 static char *_env_e_default_xkb_rules   = NULL;
58 static char *_env_e_default_xkb_model   = NULL;
59 static char *_env_e_default_xkb_layout  = NULL;
60 static char *_env_e_default_xkb_variant = NULL;
61 static char *_env_e_default_xkb_opts    = NULL;
62
63 static Eina_Bool
64 _e_comp_wl_input_is_position_inside_constraint_region(E_Comp_Wl_Pointer_Constraint *constraint,
65                                                       wl_fixed_t fx,
66                                                       wl_fixed_t fy);
67
68 static void
69 _e_comp_wl_input_update_seat_caps(struct wl_client *wc)
70 {
71    Eina_List *l;
72    struct wl_resource *res;
73    enum wl_seat_capability caps = 0;
74
75    if (e_comp_wl->ptr.enabled)
76      caps |= WL_SEAT_CAPABILITY_POINTER;
77    if (e_comp_wl->kbd.enabled)
78      caps |= WL_SEAT_CAPABILITY_KEYBOARD;
79    if (e_comp_wl->touch.enabled)
80      caps |= WL_SEAT_CAPABILITY_TOUCH;
81
82    EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, res)
83      {
84         /* if a wc is null, send seat capability to all wl_seat resources */
85         if (wc && (wl_resource_get_client(res) != wc)) continue;
86         wl_seat_send_capabilities(res, caps);
87      }
88 }
89
90 static void
91 _e_comp_wl_input_pointer_map(struct wl_resource *resource)
92 {
93    E_Client *ec;
94    E_Pointer *ptr;
95    struct wl_client *wc;
96
97    if (!(ec = e_client_from_surface_resource(resource))) return;
98    if (e_object_is_del(E_OBJECT(ec))) return;
99
100    //if cursor ec have external content
101    e_comp_object_content_unset(ec->frame);
102
103    if (!e_comp_wl->ptr.ec || !e_comp_wl->ptr.ec->comp_data) return;
104    struct wl_resource *surface = e_comp_wl_client_surface_get(e_comp_wl->ptr.ec);
105    if (!surface) return;
106
107    wc = wl_resource_get_client(resource);
108    if (wc != wl_resource_get_client(surface)) return;
109    if (!e_comp_wl->ptr.ec->pointer_enter_sent) return;
110
111    if ((ptr = e_comp->pointer))
112      e_pointer_object_set(ptr, ec->frame, ptr->hot.x, ptr->hot.y);
113 }
114
115 static void
116 _e_comp_wl_input_pointer_configure(struct wl_resource *resource,
117                                    Evas_Coord x, Evas_Coord y,
118                                    Evas_Coord w, Evas_Coord h)
119 {
120    E_Client *ec;
121
122    if (!(ec = e_client_from_surface_resource(resource))) return;
123    if (e_object_is_del(E_OBJECT(ec))) return;
124
125    e_client_util_resize_without_frame(ec, w, h);
126 }
127
128 static void
129 _e_comp_wl_input_cb_resource_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
130 {
131    wl_resource_destroy(resource);
132 }
133
134 static void
135 _e_comp_wl_input_pointer_cb_cursor_set(struct wl_client *client, struct wl_resource *resource EINA_UNUSED, uint32_t serial EINA_UNUSED, struct wl_resource *surface_resource, int32_t x, int32_t y)
136 {
137    E_Client *ec;
138    Eina_Bool got_mouse = EINA_FALSE;
139    struct wl_resource *surface;
140
141    E_CLIENT_FOREACH(ec)
142      {
143        if (e_object_is_del(E_OBJECT(ec))) continue;
144        if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) continue;
145        surface = e_comp_wl_client_surface_get(ec);
146        if (!surface) continue;
147        if (client != wl_resource_get_client(surface)) continue;
148        if (ec->mouse.in && ec->pointer_enter_sent)
149          {
150             got_mouse = EINA_TRUE;
151             break;
152          }
153      }
154    if (!got_mouse)
155      {
156         ELOGF("COMP", "Cursor Set. got_mouse: false", NULL);
157         return;
158      }
159    if (!surface_resource)
160      {
161         e_pointer_object_set(e_comp->pointer, NULL, x, y);
162         ec->has_cursor_unset = EINA_TRUE;
163         return;
164      }
165
166    ec->has_cursor_unset = EINA_FALSE;
167
168    ec = e_client_from_surface_resource(surface_resource);
169    if (!ec) return;
170
171    if (!ec->re_manage)
172      {
173         ec->re_manage = 1;
174         ec->ignored = 0;
175
176         ec->lock_focus_out = ec->layer_block = ec->visible = 1;
177         if (!e_config->show_cursor)
178           {
179              ELOGF("COMP", "Cursor Set. show_cursor: false", ec);
180              ec->override = 1;
181           }
182         ec->icccm.title = eina_stringshare_add("Cursor");
183         e_client_window_role_set(ec, "wl_pointer-cursor");
184         evas_object_pass_events_set(ec->frame, 1);
185         /* wl_pointer-cursor surface is always alpha window */
186         ec->argb = EINA_TRUE;
187         ELOGF("COMP", "Cursor Set. argb:%d", ec, ec->argb);
188         e_comp_object_alpha_set(ec->frame, EINA_TRUE);
189         EC_CHANGED(ec);
190
191         /* Set fuctions to prevent unwanted handling by shell */
192         ec->comp_data->shell.surface = surface_resource;
193         ec->comp_data->shell.configure = _e_comp_wl_input_pointer_configure;
194         ec->comp_data->shell.map = _e_comp_wl_input_pointer_map;
195
196         e_client_layer_set(ec, E_LAYER_CLIENT_CURSOR);
197         ec->is_cursor = EINA_TRUE;
198      }
199
200    /* Set a pointer_object after wl_surface commit
201     * if cursor image is changed,
202     * changed information is sent using attach / damage
203     * So in commit, we can know real current cursor image.
204     */
205 #if 0
206    /* ignore cursor changes during resize/move I guess */
207    if (e_client_action_get()) return;
208    e_pointer_object_set(e_comp->pointer, ec->frame, x, y);
209 #endif
210    if (e_comp->pointer)
211      {
212         e_comp->pointer->hot.x = x;
213         e_comp->pointer->hot.y = y;
214         if (e_config->show_cursor)
215           ec->visible = EINA_TRUE;
216      }
217 }
218
219 static const struct wl_pointer_interface _e_pointer_interface =
220 {
221    _e_comp_wl_input_pointer_cb_cursor_set,
222    _e_comp_wl_input_cb_resource_destroy
223 };
224
225 static const struct wl_keyboard_interface _e_keyboard_interface =
226 {
227    _e_comp_wl_input_cb_resource_destroy
228 };
229
230 static const struct wl_touch_interface _e_touch_interface =
231 {
232    _e_comp_wl_input_cb_resource_destroy
233 };
234
235 static void
236 _e_comp_wl_input_cb_pointer_unbind(struct wl_resource *resource)
237 {
238    e_comp_wl->ptr.resources =
239      eina_list_remove(e_comp_wl->ptr.resources, resource);
240
241    wl_signal_emit(&e_comp_wl->ptr_constraints.pointer_destroy_signal, resource);
242 }
243
244 static void
245 _e_comp_wl_input_cb_pointer_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
246 {
247    struct wl_resource *res;
248    struct wl_client *ptr_client = NULL;
249    E_Comp_Wl_Client_Data *cdata = NULL;
250
251    /* try to create pointer resource */
252    res = wl_resource_create(client, &wl_pointer_interface,
253                             wl_resource_get_version(resource), id);
254    if (!res)
255      {
256         ERR("Could not create pointer on seat %s: %m",
257             e_comp_wl->seat.name);
258         wl_client_post_no_memory(client);
259         return;
260      }
261
262    e_comp_wl->ptr.resources =
263      eina_list_append(e_comp_wl->ptr.resources, res);
264    wl_resource_set_implementation(res, &_e_pointer_interface,
265                                   e_comp->wl_comp_data,
266                                  _e_comp_wl_input_cb_pointer_unbind);
267
268    if ((e_comp_wl->ptr.num_devices == 1) && e_comp_wl->ptr.ec && !e_comp_wl->ptr.ec->pointer_enter_sent && !e_config->use_cursor_timer)
269      {
270         cdata = (E_Comp_Wl_Client_Data*)e_comp_wl->ptr.ec->comp_data;
271         if (cdata && cdata->wl_surface)
272           ptr_client = wl_resource_get_client(cdata->wl_surface);
273
274         if (ptr_client == client)
275           {
276              Evas_Device *last_ptr = NULL, *dev;
277              Eina_List *list, *l;
278              const char *name, *desc;
279
280              list = (Eina_List *)evas_device_list(evas_object_evas_get(e_comp_wl->ptr.ec->frame), NULL);
281              EINA_LIST_FOREACH(list, l, dev)
282                {
283                   name = evas_device_name_get(dev);
284                   desc = evas_device_description_get(dev);
285                   if (!name || !desc) continue;
286
287                   if ((!strncmp(name, e_devicemgr->last_device_ptr->name, strlen(e_devicemgr->last_device_ptr->name))) &&
288                       (!strncmp(desc, e_devicemgr->last_device_ptr->identifier, strlen(e_devicemgr->last_device_ptr->identifier))) &&
289                       (evas_device_class_get(dev) == (Evas_Device_Class)e_devicemgr->last_device_ptr->clas))
290                     {
291                        last_ptr = dev;
292                        break;
293                     }
294                }
295              if (last_ptr)
296                e_comp_wl_mouse_in_renew(e_comp_wl->ptr.ec, 0, wl_fixed_to_int(e_comp_wl->ptr.x), wl_fixed_to_int(e_comp_wl->ptr.y), NULL, NULL, NULL, ecore_time_get(), EVAS_EVENT_FLAG_NONE, last_ptr, NULL);
297           }
298      }
299 }
300
301 static void
302 _e_comp_wl_input_cb_keyboard_unbind(struct wl_resource *resource)
303 {
304    Eina_List *l, *ll;
305    struct wl_resource *res;
306
307    g_mutex_lock(&e_comp_wl->kbd.resource_mutex);
308
309    e_comp_wl->kbd.resources =
310      eina_list_remove(e_comp_wl->kbd.resources, resource);
311
312    g_mutex_unlock(&e_comp_wl->kbd.resource_mutex);
313
314    g_mutex_lock(&e_comp_wl->kbd.focused_mutex);
315
316    EINA_LIST_FOREACH_SAFE(e_comp_wl->kbd.focused, l, ll, res)
317      if (res == resource)
318        e_comp_wl->kbd.focused =
319          eina_list_remove_list(e_comp_wl->kbd.focused, l);
320
321    g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
322 }
323
324 void
325 e_comp_wl_input_keyboard_enter_send(E_Client *ec)
326 {
327    struct wl_resource *res;
328    Eina_List *l;
329    uint32_t serial;
330    struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
331    if (!surface) return;
332
333    g_mutex_lock(&e_comp_wl->kbd.focused_mutex);
334
335    if (!e_comp_wl->kbd.focused)
336      {
337         g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
338         return;
339      }
340
341    g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
342
343    e_comp_wl_input_keyboard_modifiers_serialize();
344
345    serial = wl_display_next_serial(e_comp_wl->wl.disp);
346
347    g_mutex_lock(&e_comp_wl->kbd.mod_changed_mutex);
348    g_mutex_lock(&e_comp_wl->kbd.focused_mutex);
349    g_mutex_lock(&e_comp_wl->kbd.keys_mutex);
350    EINA_LIST_FOREACH(e_comp_wl->kbd.focused, l, res)
351      {
352         wl_keyboard_send_enter(res, serial, surface,
353                                &e_comp_wl->kbd.keys);
354         wl_keyboard_send_modifiers(res, serial,
355                                    e_comp_wl->kbd.mod_depressed,
356                                    e_comp_wl->kbd.mod_latched,
357                                    e_comp_wl->kbd.mod_locked,
358                                    e_comp_wl->kbd.mod_group);
359      }
360    g_mutex_unlock(&e_comp_wl->kbd.keys_mutex);
361    g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
362    g_mutex_unlock(&e_comp_wl->kbd.mod_changed_mutex);
363 }
364
365 static void
366 _e_comp_wl_input_cb_keyboard_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
367 {
368    E_Client *focused;
369    struct wl_resource *res;
370
371    /* try to create keyboard resource */
372    res = wl_resource_create(client, &wl_keyboard_interface,
373                             wl_resource_get_version(resource), id);
374    if (!res)
375      {
376         ERR("Could not create keyboard on seat %s: %m",
377             e_comp_wl->seat.name);
378         wl_client_post_no_memory(client);
379         return;
380      }
381
382    g_mutex_lock(&e_comp_wl->kbd.resource_mutex);
383    e_comp_wl->kbd.resources =
384      eina_list_append(e_comp_wl->kbd.resources, res);
385    g_mutex_unlock(&e_comp_wl->kbd.resource_mutex);
386    wl_resource_set_implementation(res, &_e_keyboard_interface,
387                                   e_comp->wl_comp_data,
388                                   _e_comp_wl_input_cb_keyboard_unbind);
389
390    /* send current repeat_info */
391    if (wl_resource_get_version(res) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
392      {
393         g_mutex_lock(&e_comp_wl->kbd.repeat_rate_mutex);
394         g_mutex_lock(&e_comp_wl->kbd.repeat_delay_mutex);
395         wl_keyboard_send_repeat_info(res, e_comp_wl->kbd.repeat_rate, e_comp_wl->kbd.repeat_delay);
396         g_mutex_unlock(&e_comp_wl->kbd.repeat_delay_mutex);
397         g_mutex_unlock(&e_comp_wl->kbd.repeat_rate_mutex);
398      }
399
400    /* send current keymap */
401    TRACE_INPUT_BEGIN(wl_keyboard_send_keymap);
402    wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
403                            e_comp_wl->xkb.fd,
404                            e_comp_wl->xkb.size);
405    TRACE_INPUT_END();
406
407    /* if the client owns the focused surface, we need to send an enter */
408    focused = e_client_focused_get();
409    if ((!focused) || (e_object_is_del(E_OBJECT(focused))) ||
410        (!focused->comp_data)) return;
411
412    struct wl_resource *surface = e_comp_wl_client_surface_get(focused);
413    if (!surface) return;
414
415    if (client != wl_resource_get_client(surface)) return;
416    g_mutex_lock(&e_comp_wl->kbd.focused_mutex);
417    e_comp_wl->kbd.focused = eina_list_append(e_comp_wl->kbd.focused, res);
418    g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
419
420    e_comp_wl_input_keyboard_enter_send(focused);
421 }
422
423 static void
424 _e_comp_wl_input_cb_touch_unbind(struct wl_resource *resource)
425 {
426    e_comp_wl->touch.resources =
427      eina_list_remove(e_comp_wl->touch.resources, resource);
428 }
429
430 static void
431 _e_comp_wl_input_cb_touch_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id EINA_UNUSED)
432 {
433     struct wl_resource *res;
434
435     /* try to create pointer resource */
436     res = wl_resource_create(client, &wl_touch_interface,
437                              wl_resource_get_version(resource), id);
438     if (!res)
439       {
440          ERR("Could not create touch on seat %s: %m",
441              e_comp_wl->seat.name);
442          wl_client_post_no_memory(client);
443          return;
444       }
445
446     e_comp_wl->touch.resources =
447      eina_list_append(e_comp_wl->touch.resources, res);
448     wl_resource_set_implementation(res, &_e_touch_interface,
449                                    e_comp->wl_comp_data,
450                                   _e_comp_wl_input_cb_touch_unbind);
451 }
452
453 static const struct wl_seat_interface _e_seat_interface =
454 {
455    _e_comp_wl_input_cb_pointer_get,
456    _e_comp_wl_input_cb_keyboard_get,
457    _e_comp_wl_input_cb_touch_get,
458 };
459
460 static void
461 _e_comp_wl_input_cb_unbind_seat(struct wl_resource *resource)
462 {
463    E_Comp_Wl_Seat *seat = wl_resource_get_user_data(resource);
464
465    DBG("Unbind seat: %u (client: %p)", wl_resource_get_id(resource), wl_resource_get_client(resource));
466
467    e_comp_wl->seat.resources =
468      eina_list_remove(e_comp_wl->seat.resources, resource);
469    E_FREE(seat);
470 }
471
472 static void
473 _e_comp_wl_input_cb_bind_seat(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
474 {
475    struct wl_resource *res;
476    Eina_List *l;
477    struct wl_resource *tmp_res;
478    E_Comp_Wl_Seat *seat;
479
480    seat = E_NEW(E_Comp_Wl_Seat, 1);
481    if (!seat)
482      {
483         ERR("Failed to allocate memory for seat data\n");
484         wl_client_post_no_memory(client);
485         return;
486      }
487    seat->is_first_resource = 1;
488
489    EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, tmp_res)
490      {
491         if (wl_resource_get_client(tmp_res) != client) continue;
492         DBG("wl_seat (res: %d) is already bound to client (%p)",
493             wl_resource_get_id(tmp_res), client);
494         seat->is_first_resource = 0;
495         break;
496      }
497
498    res = wl_resource_create(client, &wl_seat_interface, version, id);
499    if (!res)
500      {
501         ERR("Could not create seat resource: %m");
502         E_FREE(seat);
503         return;
504      }
505    DBG("Bind seat: %u (client: %p)", wl_resource_get_id(res), client);
506
507    /* store version of seat interface for reuse in updating capabilities */
508    e_comp_wl->seat.version = version;
509    e_comp_wl->seat.resources =
510      eina_list_append(e_comp_wl->seat.resources, res);
511
512    wl_resource_set_implementation(res, &_e_seat_interface,
513                                   seat,
514                                   _e_comp_wl_input_cb_unbind_seat);
515
516    _e_comp_wl_input_update_seat_caps(client);
517    if (e_comp_wl->seat.version >= WL_SEAT_NAME_SINCE_VERSION)
518      wl_seat_send_name(res, e_comp_wl->seat.name);
519 }
520
521 static void
522 _e_comp_wl_input_cb_relative_pointer_destroy(struct wl_client *client,
523                                              struct wl_resource *resource)
524 {
525    wl_resource_destroy(resource);
526 }
527
528 static const struct zwp_relative_pointer_v1_interface _e_relative_pointer_interface = {
529    _e_comp_wl_input_cb_relative_pointer_destroy
530 };
531
532 static void
533 _e_comp_wl_input_cb_relative_pointer_manager_destroy(struct wl_client *client,
534                                                      struct wl_resource *resource)
535 {
536    wl_resource_destroy(resource);
537 }
538
539 static void
540 _e_comp_wl_input_cb_unbind_relative_pointer(struct wl_resource *resource)
541 {
542    e_comp_wl->relative_ptr.resources =
543      eina_list_remove(e_comp_wl->relative_ptr.resources, resource);
544 }
545
546 static void
547 _e_comp_wl_input_cb_relative_pointer_manager_get_relative_pointer(struct wl_client *client,
548                                                               struct wl_resource *resource,
549                                                               uint32_t id,
550                                                               struct wl_resource *pointer_resource)
551 {
552    struct wl_resource *res = NULL;
553
554    res = wl_resource_create(client, &zwp_relative_pointer_v1_interface, 1, id);
555
556    if (!res)
557      {
558         ERR("Could not create the resource for relative pointer: %m");
559         wl_client_post_no_memory(client);
560         return;
561      }
562
563    e_comp_wl->relative_ptr.resources =
564      eina_list_append(e_comp_wl->relative_ptr.resources, res);
565
566    /* FIXME: must consider destroying relative pointer together
567              when the wl_pointer is destroyed */
568    (void) pointer_resource;
569    wl_resource_set_implementation(res, &_e_relative_pointer_interface,
570                                   NULL, _e_comp_wl_input_cb_unbind_relative_pointer);
571 }
572
573 static const struct zwp_relative_pointer_manager_v1_interface _e_relative_pointer_manager_interface = {
574    _e_comp_wl_input_cb_relative_pointer_manager_destroy,
575    _e_comp_wl_input_cb_relative_pointer_manager_get_relative_pointer,
576 };
577
578 static void
579 _e_comp_wl_input_cb_unbind_relative_pointer_manager(struct wl_resource *resource)
580 {
581    e_comp_wl->relative_ptr.manager_resources =
582      eina_list_remove(e_comp_wl->relative_ptr.manager_resources, resource);
583 }
584
585 static void
586 _e_comp_wl_input_cb_bind_relative_pointer_manager(struct wl_client *client,
587                                                   void *data EINA_UNUSED,
588                                                   uint32_t version,
589                                                   uint32_t id)
590 {
591    struct wl_resource *resource = NULL;
592
593    resource = wl_resource_create(client, &zwp_relative_pointer_manager_v1_interface, 1, id);
594
595    if (!resource)
596      {
597         ERR("Could not create resource for relative pointer manager: %m");
598         wl_client_post_no_memory(client);
599         return;
600      }
601
602    e_comp_wl->relative_ptr.manager_resources =
603      eina_list_append(e_comp_wl->relative_ptr.manager_resources, resource);
604    wl_resource_set_implementation(resource, &_e_relative_pointer_manager_interface,
605                                   NULL, _e_comp_wl_input_cb_unbind_relative_pointer_manager);
606 }
607
608 void
609 _e_comp_wl_input_relative_motion_handler(double dx[2], double dy[2], uint64_t time_us)
610 {
611    //intended to be empty just for now.
612 }
613
614 static void
615 _e_comp_wl_input_pointer_constraint_notify_deactivated(E_Comp_Wl_Pointer_Constraint *constraint)
616 {
617    struct wl_resource *resource = constraint->resource;
618    E_Comp_Wl_Pointer_Constraint_Type type = constraint->type;
619
620    if (E_COMP_WL_POINTER_CONSTRAINT_TYPE_LOCK == type)
621      zwp_locked_pointer_v1_send_unlocked(resource);
622    else if (E_COMP_WL_POINTER_CONSTRAINT_TYPE_CONFINE == type)
623      zwp_confined_pointer_v1_send_unconfined(resource);
624    else
625      ERR("unknown pointer constraint type (%d) !", type);
626
627    INF("Pointer Constraint deactivated.");
628
629    if (constraint->ec &&
630        constraint->has_hint_set)
631      {
632
633         INF("Pointer Constraint. Pointer Warp to (%d, %d)", constraint->hint_x, constraint->hint_y);
634         e_input_device_pointer_warp(NULL, constraint->hint_x, constraint->hint_y);
635      }
636 }
637
638 static void
639 _e_comp_wl_input_pointer_constraint_deactivate(E_Comp_Wl_Pointer_Constraint *constraint)
640 {
641    constraint->active = EINA_FALSE;
642    e_comp_wl->ptr_constraints.activated = EINA_FALSE;
643    e_comp_wl->ptr_constraints.ec = NULL;
644    e_comp_wl->relative_ptr.activated = EINA_FALSE;
645    e_comp_wl->relative_ptr.ec = NULL;
646    e_input_relative_motion_handler_set(NULL);
647    _e_comp_wl_input_pointer_constraint_notify_deactivated(constraint);
648    wl_list_remove(&constraint->surface_unmap_listener.link);
649    wl_list_init(&constraint->surface_unmap_listener.link);
650 }
651
652 static void
653 _e_comp_wl_input_pointer_constraint_destroy(E_Comp_Wl_Pointer_Constraint *constraint)
654 {
655    if (constraint->active)
656      _e_comp_wl_input_pointer_constraint_deactivate(constraint);
657
658    wl_list_remove(&constraint->pointer_destroy_listener.link);
659    wl_list_remove(&constraint->surface_unmap_listener.link);
660    wl_list_remove(&constraint->surface_commit_listener.link);
661    wl_list_remove(&constraint->surface_mousein_listener.link);
662
663    wl_resource_set_user_data(constraint->resource, NULL);
664    pixman_region32_fini(&constraint->region);
665    wl_list_remove(&constraint->link);
666
667    free(constraint);
668 }
669
670 static Eina_Bool
671 _e_comp_wl_input_is_position_inside_constraint_region(E_Comp_Wl_Pointer_Constraint *constraint,
672                                                       wl_fixed_t fx,
673                                                       wl_fixed_t fy)
674 {
675    pixman_region32_t *region = &constraint->region;
676    pixman_region32_t cregion;
677    pixman_region32_t input_region;
678
679    pixman_region32_init(&cregion);
680    pixman_region32_init(&input_region);
681
682    //FIXME: get input_region from ec's input region
683    E_Client *ec = constraint->ec;
684    pixman_region32_init_rect(&input_region, 0, 0, ec->w, ec->h);
685    pixman_region32_intersect(&cregion, &input_region, region);
686
687    Eina_Bool inside = pixman_region32_contains_point(&cregion,
688                                                      wl_fixed_to_int(fx),
689                                                      wl_fixed_to_int(fy),
690                                                      NULL);
691
692    pixman_region32_fini(&cregion);
693    pixman_region32_fini(&input_region);
694
695    if (!inside)
696      INF("(%d, %d) is not inside of constraint region.", wl_fixed_to_int(fx), wl_fixed_to_int(fy));
697
698    return inside;
699 }
700
701 static void
702 _e_comp_wl_input_pointer_constraint_notify_activated(E_Comp_Wl_Pointer_Constraint *constraint)
703 {
704    struct wl_resource *resource = constraint->resource;
705    E_Comp_Wl_Pointer_Constraint_Type type = constraint->type;
706
707    if (E_COMP_WL_POINTER_CONSTRAINT_TYPE_LOCK == type)
708      zwp_locked_pointer_v1_send_locked(resource);
709    else if (E_COMP_WL_POINTER_CONSTRAINT_TYPE_CONFINE == type)
710      zwp_confined_pointer_v1_send_confined(resource);
711    else
712      ERR("unknown pointer constraint type (%d) !", type);
713
714    INF("Pointer Constraint activated.");
715 }
716
717 static void
718 _e_comp_wl_input_pointer_constraint_enable(E_Comp_Wl_Pointer_Constraint *constraint)
719 {
720    if (constraint->active)
721      {
722         ERR("ERROR! Pointer constraint has been activated already !");
723         return;
724      }
725
726    constraint->active = EINA_TRUE;
727    E_Client *ec = constraint->ec;
728    e_comp_wl->ptr_constraints.activated = EINA_TRUE;
729    e_comp_wl->ptr_constraints.ec = ec;
730    e_comp_wl->relative_ptr.activated = EINA_TRUE;
731    e_comp_wl->relative_ptr.ec = ec;
732    _e_comp_wl_input_pointer_constraint_notify_activated(constraint);
733    wl_signal_add(&e_comp_wl->ptr_constraints.surface_unmap_signal,
734                  &constraint->surface_unmap_listener);
735    if (!e_input_relative_motion_handler_set(_e_comp_wl_input_relative_motion_handler))
736      ERR("ERROR! Could not set relative motion handler !");
737 }
738
739 static void
740 _e_comp_wl_input_pointer_constraints_check_enable(E_Comp_Wl_Pointer_Constraint *constraint)
741 {
742    if (!constraint || !constraint->ec)
743      {
744         ERR("Invalid constraint or ec of it.");
745         return;
746      }
747
748    E_Client *ec = constraint->ec;
749    wl_fixed_t cx = e_comp_wl->ptr.x - wl_fixed_from_int(ec->client.x);
750    wl_fixed_t cy = e_comp_wl->ptr.y - wl_fixed_from_int(ec->client.y);
751
752    if ((!e_comp_wl->ptr.ec) || (e_comp_wl->ptr.ec != ec)
753         || (!ec->pointer_enter_sent))
754      return;
755
756    if (!_e_comp_wl_input_is_position_inside_constraint_region(constraint,
757                                                               cx,
758                                                               cy))
759      return;
760
761    _e_comp_wl_input_pointer_constraint_enable(constraint);
762 }
763
764 static void
765 _e_comp_wl_input_pointer_constraint_disable(E_Comp_Wl_Pointer_Constraint *constraint)
766 {
767    int lifetime = constraint->lifetime;
768
769    if (lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT)
770      _e_comp_wl_input_pointer_constraint_destroy(constraint);
771    else if (lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT)
772      _e_comp_wl_input_pointer_constraint_deactivate(constraint);
773    else
774      ERR("unknown pointer constraint lifetime (%d) !", lifetime);
775 }
776
777 static void
778 _e_comp_wl_input_cb_pointer_constraints_pointer_destroyed(struct wl_listener *listener,
779                                                           void *data)
780 {
781    struct wl_resource *pointer_resource = (struct wl_resource *)data;
782    E_Comp_Wl_Pointer_Constraint *constraint = container_of(listener,
783                                               E_Comp_Wl_Pointer_Constraint,
784                                               pointer_destroy_listener);
785
786    if (pointer_resource == constraint->pointer)
787      _e_comp_wl_input_pointer_constraint_destroy(constraint);
788 }
789
790 static void
791 _e_comp_wl_input_cb_pointer_constraints_surface_committed(struct wl_listener *listener,
792                                                           void *data)
793 {
794    E_Client *ec = (E_Client *)data;
795    E_Comp_Wl_Pointer_Constraint *constraint = container_of(listener,
796                                               E_Comp_Wl_Pointer_Constraint,
797                                               surface_commit_listener);
798    int new_x, new_y;;
799
800    if (ec != constraint->ec)
801      return;
802
803    if (constraint->is_hint_pending)
804      {
805         constraint->is_hint_pending = EINA_FALSE;
806
807         new_x = ec->client.x + wl_fixed_to_int(constraint->hint_x_pending);
808         new_y = ec->client.y + wl_fixed_to_int(constraint->hint_y_pending);
809
810         if (e_client_transform_core_enable_get(ec))
811           {
812              e_comp_wl_map_inv_coord_get(ec, new_x, new_y, &constraint->hint_x, &constraint->hint_y);
813              WRN("Pointer Constraint. Committed. hint (%d, %d) -> map_inv_coord (%d, %d)",
814                  new_x, new_y, constraint->hint_x, constraint->hint_y);
815           }
816         else
817           {
818              constraint->hint_x = new_x;
819              constraint->hint_y = new_y;
820              WRN("Pointer Constraint. Committed. hint (%d, %d)",
821                  constraint->hint_x, constraint->hint_y);
822           }
823      }
824
825    if (constraint->is_region_pending)
826      {
827         constraint->is_region_pending = EINA_FALSE;
828         pixman_region32_copy(&constraint->region,
829                              &constraint->region_pending);
830         pixman_region32_fini(&constraint->region_pending);
831         pixman_region32_init(&constraint->region_pending);
832      }
833
834    //CHECKME: check if the updated region can take effect on the given constraint
835 }
836
837 static void
838 _e_comp_wl_input_cb_pointer_constraints_surface_mousein(struct wl_listener *listener,
839                                                         void *data)
840 {
841    E_Client *ec = (E_Client *)data;
842    E_Comp_Wl_Pointer_Constraint *constraint = container_of(listener,
843                                               E_Comp_Wl_Pointer_Constraint,
844                                               surface_mousein_listener);
845
846    Eina_Bool found = EINA_FALSE;
847    E_Comp_Wl_Pointer_Constraint *tmp_constraint;
848    wl_list_for_each(tmp_constraint, &ec->comp_data->pointer_constraints, link)
849      {
850         if (tmp_constraint == constraint)
851           {
852              found = EINA_TRUE;
853              break;
854           }
855      }
856
857    if (found && !constraint->active)
858      _e_comp_wl_input_pointer_constraints_check_enable(constraint);
859    else if (!found && constraint->active)
860      _e_comp_wl_input_pointer_constraint_disable(constraint);
861 }
862
863 static void
864 _e_comp_wl_input_cb_pointer_constraints_surface_unmapped(struct wl_listener *listener,
865                                                          void *data)
866 {
867    E_Client *ec = (E_Client *)data;
868    E_Comp_Wl_Pointer_Constraint *constraint = container_of(listener,
869                                               E_Comp_Wl_Pointer_Constraint,
870                                               surface_unmap_listener);
871
872    if (ec == constraint->ec)
873      _e_comp_wl_input_pointer_constraint_disable(constraint);
874 }
875
876 static E_Comp_Wl_Pointer_Constraint *
877 _e_comp_wl_input_pointer_constraint_create(E_Client *ec,
878                                            struct wl_resource *resource,
879                                            struct wl_resource *pointer,
880                                            struct wl_resource *region_resource,
881                                            enum zwp_pointer_constraints_v1_lifetime lifetime,
882                                            E_Comp_Wl_Pointer_Constraint_Type type)
883 {
884    E_Comp_Wl_Pointer_Constraint *constraint;
885
886    constraint = E_NEW(E_Comp_Wl_Pointer_Constraint, 1);
887
888    if (!constraint)
889      {
890         ERR("Could not allocate memory for pointer constraint: %m");
891         return NULL;
892      }
893
894    constraint->active = EINA_FALSE;
895    constraint->ec = ec;
896    constraint->lifetime = lifetime;
897    constraint->type = type;
898    constraint->pointer = pointer;
899    constraint->resource = resource;
900    constraint->surface = e_comp_wl_client_surface_get(ec);
901    wl_list_init(&constraint->link);
902    wl_list_insert(&ec->comp_data->pointer_constraints, &constraint->link);
903    pixman_region32_init(&constraint->region);
904    pixman_region32_init(&constraint->region_pending);
905
906    if (region_resource)
907      {
908         pixman_region32_t *region = wl_resource_get_user_data(region_resource);
909         if (region)
910           {
911              pixman_region32_copy(&constraint->region, region);
912              constraint->has_region_set = EINA_TRUE;
913           }
914         else
915           {
916              //CHECKME: check whether this situation is a kind of bug
917              ERR("Invalid pixman_region from region (pointer constraint region!");
918              pixman_region32_fini(&constraint->region);
919              pixman_region32_init_rect(&constraint->region,
920                                        INT32_MIN, INT32_MIN,
921                                        UINT32_MAX, UINT32_MAX);
922           }
923      }
924    else
925      {
926         pixman_region32_fini(&constraint->region);
927         pixman_region32_init_rect(&constraint->region,
928                                   INT32_MIN, INT32_MIN,
929                                   UINT32_MAX, UINT32_MAX);
930         constraint->has_region_set = EINA_TRUE;
931      }
932
933    ERR("Pointer Constraint created.");
934
935    constraint->pointer_destroy_listener.notify =
936      _e_comp_wl_input_cb_pointer_constraints_pointer_destroyed;
937    constraint->surface_commit_listener.notify =
938      _e_comp_wl_input_cb_pointer_constraints_surface_committed;
939    constraint->surface_unmap_listener.notify =
940      _e_comp_wl_input_cb_pointer_constraints_surface_unmapped;
941    constraint->surface_mousein_listener.notify =
942      _e_comp_wl_input_cb_pointer_constraints_surface_mousein;
943
944    wl_signal_add(&e_comp_wl->ptr_constraints.pointer_destroy_signal,
945                  &constraint->pointer_destroy_listener);
946    wl_signal_add(&e_comp_wl->ptr_constraints.surface_commit_signal,
947                  &constraint->surface_commit_listener);
948    wl_signal_add(&e_comp_wl->ptr_constraints.surface_mousein_signal,
949                  &constraint->surface_mousein_listener);
950    wl_list_init(&constraint->surface_unmap_listener.link);
951
952    return constraint;
953 }
954
955 static Eina_Bool
956 _e_comp_wl_input_has_pointer_constraints_for_pointer(E_Client *ec, struct wl_resource *pointer)
957 {
958    E_Comp_Wl_Pointer_Constraint *constraint;
959
960    wl_list_for_each(constraint, &ec->comp_data->pointer_constraints, link)
961      {
962         if (constraint->pointer == pointer)
963           return EINA_TRUE;
964      }
965
966    return EINA_FALSE;
967 }
968
969 static void
970 _e_comp_wl_input_cb_unbind_locked_pointer(struct wl_resource *resource)
971 {
972    E_Comp_Wl_Pointer_Constraint *constraint;
973    constraint = wl_resource_get_user_data(resource);
974
975    if (!constraint)
976      return;
977
978    _e_comp_wl_input_pointer_constraint_destroy(constraint);
979 }
980
981 static void
982 _e_comp_wl_input_cb_locked_pointer_destroy(struct wl_client *client,
983                                            struct wl_resource *resource)
984 {
985    wl_resource_destroy(resource);
986 }
987
988 static void
989 _e_comp_wl_input_cb_locked_pointer_set_cursor_position_hint(struct wl_client *client,
990                                                             struct wl_resource *resource,
991                                                             wl_fixed_t surface_x,
992                                                             wl_fixed_t surface_y)
993 {
994    E_Comp_Wl_Pointer_Constraint *constraint =
995            (E_Comp_Wl_Pointer_Constraint *)wl_resource_get_user_data(resource);
996
997    if (!constraint)
998      return;
999
1000    constraint->hint_x_pending = surface_x;
1001    constraint->hint_y_pending = surface_y;
1002    constraint->is_hint_pending = EINA_TRUE;
1003    constraint->has_hint_set = EINA_TRUE;
1004 }
1005
1006 static void
1007 _e_comp_wl_input_cb_locked_pointer_set_region(struct wl_client *client,
1008                                               struct wl_resource *resource,
1009                                               struct wl_resource *region_resource)
1010 {
1011    E_Comp_Wl_Pointer_Constraint *constraint =
1012            (E_Comp_Wl_Pointer_Constraint *)wl_resource_get_user_data(resource);
1013
1014    if (!constraint)
1015      return;
1016
1017    if (region_resource)
1018      {
1019         pixman_region32_t *region = wl_resource_get_user_data(region_resource);
1020
1021         if (region)
1022           {
1023              pixman_region32_copy(&constraint->region_pending, region);
1024           }
1025         else
1026           {
1027              //CHECKME: check whether this situation is a kind of bug
1028              ERR("Invalid pixman_region from region (pointer constraint region!");
1029              pixman_region32_fini(&constraint->region_pending);
1030              pixman_region32_init_rect(&constraint->region_pending,
1031                                        INT32_MIN, INT32_MIN,
1032                                        UINT32_MAX, UINT32_MAX);
1033           }
1034
1035         constraint->has_region_set = EINA_TRUE;
1036      }
1037    else
1038      {
1039         pixman_region32_fini(&constraint->region_pending);
1040         pixman_region32_init_rect(&constraint->region_pending,
1041                                   INT32_MIN, INT32_MIN,
1042                                   UINT32_MAX, UINT32_MAX);
1043      }
1044
1045      constraint->is_region_pending = EINA_TRUE;
1046 }
1047
1048 static const struct zwp_locked_pointer_v1_interface _e_comp_wl_locked_pointer_interface =
1049 {
1050    _e_comp_wl_input_cb_locked_pointer_destroy,
1051    _e_comp_wl_input_cb_locked_pointer_set_cursor_position_hint,
1052    _e_comp_wl_input_cb_locked_pointer_set_region,
1053 };
1054
1055 static void
1056 _e_comp_wl_input_cb_pointer_constraints_lock_pointer(struct wl_client *client,
1057                                                      struct wl_resource *resource,
1058                                                      uint32_t id,
1059                                                      struct wl_resource *surface,
1060                                                      struct wl_resource *pointer,
1061                                                      struct wl_resource *region,
1062                                                      uint32_t lifetime)
1063 {
1064    if (!pointer || !surface)
1065      {
1066         ERR("Pointer resource or surface resource is invalid !");
1067         return;
1068      }
1069
1070    E_Client *ec = e_client_from_surface_resource(surface);
1071
1072    if (!ec)
1073      {
1074         ERR("Could not get ec from surface resource !");
1075         return;
1076      }
1077
1078    if (_e_comp_wl_input_has_pointer_constraints_for_pointer(ec, pointer))
1079      {
1080         ERR("Pointer constraints has been created already (ec: %p, pointer_resource: %u)",
1081              ec, wl_resource_get_id(resource));
1082         wl_resource_post_error(resource,
1083                                ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED,
1084                                "the pointer has a lock set already on this surface");
1085         return;
1086      }
1087
1088    struct wl_resource *res;
1089    res = wl_resource_create(client, &zwp_locked_pointer_v1_interface, 1, id);
1090
1091    if (!res)
1092      {
1093         ERR("Could not create a resource for pointer constraints lock: %m");
1094         wl_client_post_no_memory(client);
1095         return;
1096      }
1097
1098    E_Comp_Wl_Pointer_Constraint *constraint;
1099    constraint = _e_comp_wl_input_pointer_constraint_create(ec, res, pointer, region, lifetime,
1100                                                            E_COMP_WL_POINTER_CONSTRAINT_TYPE_LOCK);
1101
1102    if (!constraint)
1103      {
1104         ERR("Could not create a pointer constraint.");
1105         wl_resource_destroy(res);
1106         wl_client_post_no_memory(client);
1107         return;
1108      }
1109
1110    wl_resource_set_implementation(res, &_e_comp_wl_locked_pointer_interface,
1111                                   constraint, _e_comp_wl_input_cb_unbind_locked_pointer);
1112
1113    _e_comp_wl_input_pointer_constraints_check_enable(constraint);
1114 }
1115
1116 static void
1117 _e_comp_wl_input_cb_pointer_constraints_confine_pointer(struct wl_client *client,
1118                                                         struct wl_resource *resource,
1119                                                         uint32_t id,
1120                                                         struct wl_resource *surface,
1121                                                         struct wl_resource *pointer,
1122                                                         struct wl_resource *region,
1123                                                         uint32_t lifetime)
1124 {
1125    (void) client;
1126    (void) resource;
1127    (void) id;
1128    (void) surface;
1129    (void) pointer;
1130    (void) region;
1131    (void) lifetime;
1132
1133    /* TODO: pointer constraints confine */
1134 }
1135
1136 static void
1137 _e_comp_wl_input_cb_pointer_constraints_destroy(struct wl_client *client,
1138                                           struct wl_resource *resource)
1139 {
1140    wl_resource_destroy(resource);
1141 }
1142
1143 static const struct zwp_pointer_constraints_v1_interface _e_pointer_constraints_interface = {
1144         _e_comp_wl_input_cb_pointer_constraints_destroy,
1145         _e_comp_wl_input_cb_pointer_constraints_lock_pointer,
1146         _e_comp_wl_input_cb_pointer_constraints_confine_pointer,
1147 };
1148
1149 static void
1150 _e_comp_wl_input_cb_unbind_pointer_constraints(struct wl_resource *resource)
1151 {
1152    e_comp_wl->ptr_constraints.resources =
1153      eina_list_remove(e_comp_wl->ptr_constraints.resources, resource);
1154 }
1155
1156 static void
1157 _e_comp_wl_input_cb_bind_pointer_constraints(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
1158 {
1159    struct wl_resource *resource;
1160
1161    resource = wl_resource_create(client, &zwp_pointer_constraints_v1_interface, version, id);
1162
1163    if (!resource)
1164      {
1165         ERR("Could not create pointer constraints resource: %m");
1166         return;
1167      }
1168
1169    e_comp_wl->ptr_constraints.resources =
1170      eina_list_append(e_comp_wl->ptr_constraints.resources, resource);
1171    wl_resource_set_implementation(resource, &_e_pointer_constraints_interface,
1172                                   NULL, _e_comp_wl_input_cb_unbind_pointer_constraints);
1173 }
1174
1175 static void
1176 _e_comp_wl_input_cb_surface_commit(void *data EINA_UNUSED, E_Client *ec)
1177 {
1178    wl_signal_emit(&e_comp_wl->ptr_constraints.surface_commit_signal, ec);
1179 }
1180
1181 static void
1182 _e_comp_wl_input_keymap_cache_create(const char *keymap_path, char *keymap_data)
1183 {
1184    FILE *file = NULL;
1185    TRACE_INPUT_BEGIN(_e_comp_wl_input_keymap_cache_create);
1186
1187    if ((EINA_FALSE == e_config->xkb.use_cache) && !dont_use_xkb_cache)
1188      {
1189         TRACE_INPUT_END();
1190         return;
1191      }
1192
1193    if (keymap_path)
1194      {
1195         if (!e_util_file_realpath_check(keymap_path, EINA_TRUE))
1196           {
1197              WRN("%s is maybe link, so delete it\n", keymap_path);
1198           }
1199
1200         file = fopen(keymap_path, "w");
1201         EINA_SAFETY_ON_NULL_RETURN(file);
1202
1203         if (fputs(keymap_data, file) < 0)
1204           {
1205              WRN("Failed  to write keymap file: %s\n", keymap_path);
1206              fclose(file);
1207              unlink(keymap_path);
1208           }
1209         else
1210           {
1211              INF("Success to make keymap file: %s\n", keymap_path);
1212              fclose(file);
1213           }
1214      }
1215    TRACE_INPUT_END();
1216 }
1217
1218 static int
1219 _e_comp_wl_input_keymap_fd_get(off_t size)
1220 {
1221    int fd = 0, blen = 0, len = 0;
1222    char *path;
1223    char tmp[PATH_MAX] = {0, };
1224    long flags;
1225    mode_t old_umask;
1226
1227    blen = sizeof(tmp) - 20;
1228
1229    path = e_util_env_get("XDG_RUNTIME_DIR");
1230    if (!path) return -1;
1231
1232    len = strlen(path) + 19;
1233    if (len < blen)
1234      {
1235         strncpy(tmp, path, PATH_MAX - 20);
1236         strncat(tmp, "/e-wl-keymap-XXXXXX", 19);
1237         E_FREE(path);
1238      }
1239    else
1240      {
1241         E_FREE(path);
1242         return -1;
1243      }
1244
1245    old_umask = umask(S_IRWXG|S_IRWXO);
1246    fd = mkstemp(tmp);
1247    umask(old_umask);
1248
1249    EINA_SAFETY_ON_FALSE_RETURN_VAL(fd >= 0, -1);
1250
1251    flags = fcntl(fd, F_GETFD);
1252    if (flags < 0)
1253      {
1254         close(fd);
1255         return -1;
1256      }
1257
1258    if (fcntl(fd, F_SETFD, (flags | FD_CLOEXEC)) == -1)
1259      {
1260         close(fd);
1261         return -1;
1262      }
1263
1264    if (ftruncate(fd, size) < 0)
1265      {
1266         close(fd);
1267         return -1;
1268      }
1269
1270    unlink(tmp);
1271    return fd;
1272 }
1273
1274 static void
1275 _e_comp_wl_input_keymap_update(struct xkb_keymap *keymap, const char *keymap_path)
1276 {
1277    char *tmp;
1278    xkb_mod_mask_t latched = 0, locked = 0, group = 0;
1279    struct wl_resource *res;
1280    Eina_List *l;
1281
1282    /* unreference any existing keymap */
1283    g_mutex_lock(&e_comp_wl->xkb.keymap_mutex);
1284    if (e_comp_wl->xkb.keymap)
1285      xkb_map_unref(e_comp_wl->xkb.keymap);
1286
1287    g_mutex_unlock(&e_comp_wl->xkb.keymap_mutex);
1288
1289    /* unmap any existing keyboard area */
1290    if (e_comp_wl->xkb.area)
1291      munmap(e_comp_wl->xkb.area, e_comp_wl->xkb.size);
1292    if (e_comp_wl->xkb.fd >= 0) close(e_comp_wl->xkb.fd);
1293
1294    /* unreference any existing keyboard state */
1295    g_mutex_lock(&e_comp_wl->xkb.state_mutex);
1296    if (e_comp_wl->xkb.state)
1297      {
1298         latched =
1299           xkb_state_serialize_mods(e_comp_wl->xkb.state,
1300                                    XKB_STATE_MODS_LATCHED);
1301         locked =
1302           xkb_state_serialize_mods(e_comp_wl->xkb.state,
1303                                    XKB_STATE_MODS_LOCKED);
1304         group =
1305           xkb_state_serialize_layout(e_comp_wl->xkb.state,
1306                                      XKB_STATE_LAYOUT_EFFECTIVE);
1307         xkb_state_unref(e_comp_wl->xkb.state);
1308      }
1309
1310    /* create a new xkb state */
1311    e_comp_wl->xkb.state = xkb_state_new(keymap);
1312
1313    if (!e_comp_wl->xkb.state)
1314      {
1315         g_mutex_unlock(&e_comp_wl->xkb.state_mutex);
1316         return;
1317      }
1318
1319    if ((latched) || (locked) || (group))
1320      xkb_state_update_mask(e_comp_wl->xkb.state, 0,
1321                            latched, locked, 0, 0, group);
1322
1323    g_mutex_unlock(&e_comp_wl->xkb.state_mutex);
1324
1325    /* increment keymap reference */
1326    g_mutex_lock(&e_comp_wl->xkb.keymap_mutex);
1327    e_comp_wl->xkb.keymap = keymap;
1328    g_mutex_unlock(&e_comp_wl->xkb.keymap_mutex);
1329
1330    /* fetch updated modifiers */
1331    e_comp_wl->kbd.mod_shift =
1332      xkb_map_mod_get_index(keymap, XKB_MOD_NAME_SHIFT);
1333    e_comp_wl->kbd.mod_caps =
1334      xkb_map_mod_get_index(keymap, XKB_MOD_NAME_CAPS);
1335    e_comp_wl->kbd.mod_ctrl =
1336      xkb_map_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
1337    e_comp_wl->kbd.mod_alt =
1338      xkb_map_mod_get_index(keymap, XKB_MOD_NAME_ALT);
1339    e_comp_wl->kbd.mod_super =
1340      xkb_map_mod_get_index(keymap, XKB_MOD_NAME_LOGO);
1341
1342    if (!(tmp = xkb_map_get_as_string(keymap)))
1343      {
1344         ERR("Could not get keymap string");
1345         return;
1346      }
1347
1348    e_comp_wl->xkb.size = strlen(tmp) + 1;
1349    e_comp_wl->xkb.fd =
1350      _e_comp_wl_input_keymap_fd_get(e_comp_wl->xkb.size);
1351    if (e_comp_wl->xkb.fd < 0)
1352      {
1353         ERR("Could not create keymap file");
1354         free(tmp);
1355         return;
1356      }
1357
1358    _e_comp_wl_input_keymap_cache_create(keymap_path, tmp);
1359
1360    e_comp_wl->xkb.area =
1361      mmap(NULL, e_comp_wl->xkb.size, (PROT_READ | PROT_WRITE),
1362           MAP_SHARED, e_comp_wl->xkb.fd, 0);
1363    if (e_comp_wl->xkb.area == MAP_FAILED)
1364      {
1365         ERR("Failed to mmap keymap area: %m");
1366         free(tmp);
1367         return;
1368      }
1369
1370    strncpy(e_comp_wl->xkb.area, tmp, e_comp_wl->xkb.size);
1371    free(tmp);
1372
1373    /* send updated keymap */
1374    TRACE_INPUT_BEGIN(wl_keyboard_send_keymap_update);
1375    g_mutex_lock(&e_comp_wl->kbd.resource_mutex);
1376    EINA_LIST_FOREACH(e_comp_wl->kbd.resources, l, res)
1377      wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1378                              e_comp_wl->xkb.fd,
1379                              e_comp_wl->xkb.size);
1380    g_mutex_unlock(&e_comp_wl->kbd.resource_mutex);
1381    TRACE_INPUT_END();
1382
1383    /* update modifiers */
1384    e_comp_wl_input_keyboard_modifiers_update();
1385 }
1386
1387 EINTERN Eina_Bool
1388 e_comp_wl_input_init(void)
1389 {
1390    /* set default seat name */
1391    if (!e_comp_wl->seat.name)
1392      e_comp_wl->seat.name = "default";
1393
1394    e_comp_wl->xkb.fd = -1;
1395    dont_set_e_input_keymap = getenv("NO_E_INPUT_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
1396    dont_use_xkb_cache = getenv("NO_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
1397
1398    g_mutex_init(&e_comp_wl->kbd.mod_changed_mutex);
1399    g_mutex_init(&e_comp_wl->kbd.resource_mutex);
1400    g_mutex_init(&e_comp_wl->kbd.focused_mutex);
1401    g_mutex_init(&e_comp_wl->kbd.keys_mutex);
1402    g_mutex_init(&e_comp_wl->kbd.repeat_delay_mutex);
1403    g_mutex_init(&e_comp_wl->kbd.repeat_rate_mutex);
1404
1405    g_mutex_init(&e_comp_wl->xkb.keymap_mutex);
1406    g_mutex_init(&e_comp_wl->xkb.state_mutex);
1407
1408    g_mutex_lock(&e_comp_wl->kbd.repeat_delay_mutex);
1409    /* get default keyboard repeat delay from configuration */
1410    e_comp_wl->kbd.repeat_delay = e_config->keyboard.repeat_delay;
1411    /* check for valid repeat_delay */
1412    /* if invalid, set the default value of repeat delay */
1413    if (e_comp_wl->kbd.repeat_delay < 0) e_comp_wl->kbd.repeat_delay = 400;
1414    g_mutex_unlock(&e_comp_wl->kbd.repeat_delay_mutex);
1415
1416    g_mutex_lock(&e_comp_wl->kbd.repeat_rate_mutex);
1417    /* get default keyboard repeat rate from configuration */
1418    e_comp_wl->kbd.repeat_rate = e_config->keyboard.repeat_rate;
1419    /* check for valid repeat_rate value */
1420    /* if invalid, set the default value of repeat rate value */
1421    if (e_comp_wl->kbd.repeat_rate < 0) e_comp_wl->kbd.repeat_rate = 25;
1422    g_mutex_unlock(&e_comp_wl->kbd.repeat_rate_mutex);
1423
1424    /* create the global resource for input seat */
1425    e_comp_wl->seat.global =
1426      wl_global_create(e_comp_wl->wl.disp, &wl_seat_interface, 4,
1427                       e_comp->wl_comp_data, _e_comp_wl_input_cb_bind_seat);
1428    if (!e_comp_wl->seat.global)
1429      {
1430         ERR("Could not create global for seat: %m");
1431         return EINA_FALSE;
1432      }
1433
1434    /* create the global resource for relative pointer */
1435    e_comp_wl->relative_ptr.global =
1436      wl_global_create(e_comp_wl->wl.disp,
1437                       &zwp_relative_pointer_manager_v1_interface, 1,
1438                       e_comp->wl_comp_data,
1439                       _e_comp_wl_input_cb_bind_relative_pointer_manager);
1440    if (!e_comp_wl->relative_ptr.global)
1441      {
1442         ERR("Could not create global for relative pointer: %m");
1443         return EINA_FALSE;
1444      }
1445
1446    /* create the global resource for pointer-constraints */
1447    e_comp_wl->ptr_constraints.global =
1448      wl_global_create(e_comp_wl->wl.disp,
1449                       &zwp_pointer_constraints_v1_interface, 1,
1450                       e_comp->wl_comp_data,
1451                       _e_comp_wl_input_cb_bind_pointer_constraints);
1452    if (!e_comp_wl->ptr_constraints.global)
1453      {
1454         ERR("Could not create global for pointer constraints: %m");
1455         return EINA_FALSE;
1456      }
1457
1458    e_comp_wl->ptr_constraints.ec = NULL;
1459    e_comp_wl->ptr_constraints.activated = EINA_FALSE;
1460    wl_signal_init(&e_comp_wl->ptr_constraints.pointer_destroy_signal);
1461    wl_signal_init(&e_comp_wl->ptr_constraints.surface_unmap_signal);
1462    wl_signal_init(&e_comp_wl->ptr_constraints.surface_commit_signal);
1463    wl_signal_init(&e_comp_wl->ptr_constraints.surface_mousein_signal);
1464
1465    _surface_commit_hook = e_comp_wl_hook_add(E_COMP_WL_HOOK_CLIENT_SURFACE_COMMIT,
1466                                              _e_comp_wl_input_cb_surface_commit,
1467                                              NULL);
1468
1469    g_mutex_lock(&e_comp_wl->kbd.keys_mutex);
1470    wl_array_init(&e_comp_wl->kbd.keys);
1471    g_mutex_unlock(&e_comp_wl->kbd.keys_mutex);
1472
1473    wl_array_init(&e_comp_wl->kbd.routed_keys);
1474
1475    E_EVENT_TEXT_INPUT_PANEL_VISIBILITY_CHANGE = ecore_event_type_new();
1476
1477    /* get string values from environment variables */
1478    _env_e_default_xkb_rules   = e_util_env_get("E_DEFAULT_XKB_RULES"  );
1479    _env_e_default_xkb_model   = e_util_env_get("E_DEFAULT_XKB_MODEL"  );
1480    _env_e_default_xkb_layout  = e_util_env_get("E_DEFAULT_XKB_LAYOUT" );
1481    _env_e_default_xkb_variant = e_util_env_get("E_DEFAULT_XKB_VARIANT");
1482    _env_e_default_xkb_opts    = e_util_env_get("E_DEFAULT_XKB_OPTIONS");
1483
1484    return EINA_TRUE;
1485 }
1486
1487 EINTERN void
1488 e_comp_wl_input_shutdown(void)
1489 {
1490    struct wl_resource *res;
1491
1492    /* free environment variable string */
1493    E_FREE(_env_e_default_xkb_rules  );
1494    E_FREE(_env_e_default_xkb_model  );
1495    E_FREE(_env_e_default_xkb_layout );
1496    E_FREE(_env_e_default_xkb_variant);
1497    E_FREE(_env_e_default_xkb_opts   );
1498
1499    /* delete surface commit hook */
1500    if (_surface_commit_hook)
1501      {
1502         e_comp_wl_hook_del(_surface_commit_hook);
1503         _surface_commit_hook = NULL;
1504      }
1505
1506    g_mutex_clear(&e_comp_wl->kbd.mod_changed_mutex);
1507
1508    /* destroy pointer resources */
1509    EINA_LIST_FREE(e_comp_wl->ptr.resources, res)
1510      wl_resource_destroy(res);
1511
1512    /* destroy relative pointer resources */
1513    EINA_LIST_FREE(e_comp_wl->relative_ptr.resources, res)
1514      wl_resource_destroy(res);
1515
1516    /* destroy relative pointer manager resources */
1517    EINA_LIST_FREE(e_comp_wl->relative_ptr.manager_resources, res)
1518      wl_resource_destroy(res);
1519
1520    /* destroy pointer constraints resources */
1521    EINA_LIST_FREE(e_comp_wl->ptr_constraints.resources, res)
1522      wl_resource_destroy(res);
1523
1524    /* destroy keyboard resources */
1525    g_mutex_lock(&e_comp_wl->kbd.resource_mutex);
1526    EINA_LIST_FREE(e_comp_wl->kbd.resources, res)
1527      wl_resource_destroy(res);
1528    e_comp_wl->kbd.resources = eina_list_free(e_comp_wl->kbd.resources);
1529    g_mutex_unlock(&e_comp_wl->kbd.resource_mutex);
1530
1531    g_mutex_clear(&e_comp_wl->kbd.resource_mutex);
1532    g_mutex_clear(&e_comp_wl->kbd.focused_mutex);
1533
1534    /* destroy touch resources */
1535    EINA_LIST_FREE(e_comp_wl->touch.resources, res)
1536      wl_resource_destroy(res);
1537
1538    /* destroy e_comp_wl->kbd.keys array */
1539    g_mutex_lock(&e_comp_wl->kbd.keys_mutex);
1540    wl_array_release(&e_comp_wl->kbd.keys);
1541    g_mutex_unlock(&e_comp_wl->kbd.keys_mutex);
1542
1543    wl_array_release(&e_comp_wl->kbd.routed_keys);
1544
1545    /* unmap any existing keyboard area */
1546    if (e_comp_wl->xkb.area)
1547      munmap(e_comp_wl->xkb.area, e_comp_wl->xkb.size);
1548    if (e_comp_wl->xkb.fd >= 0) close(e_comp_wl->xkb.fd);
1549
1550    /* unreference any existing keyboard state */
1551    g_mutex_lock(&e_comp_wl->xkb.state_mutex);
1552    if (e_comp_wl->xkb.state)
1553      xkb_state_unref(e_comp_wl->xkb.state);
1554
1555    g_mutex_unlock(&e_comp_wl->xkb.state_mutex);
1556
1557    /* unreference any existing keymap */
1558    g_mutex_lock(&e_comp_wl->xkb.keymap_mutex);
1559    if (e_comp_wl->xkb.keymap)
1560      xkb_map_unref(e_comp_wl->xkb.keymap);
1561    g_mutex_unlock(&e_comp_wl->xkb.keymap_mutex);
1562
1563    /* unreference any existing context */
1564    if (e_comp_wl->xkb.context)
1565      xkb_context_unref(e_comp_wl->xkb.context);
1566
1567    /* destroy the global relative pointer resource */
1568    if (e_comp_wl->relative_ptr.global)
1569      wl_global_destroy(e_comp_wl->relative_ptr.global);
1570    e_comp_wl->relative_ptr.global = NULL;
1571
1572    /* destroy the global pointer constraints resource */
1573    if (e_comp_wl->ptr_constraints.global)
1574      wl_global_destroy(e_comp_wl->ptr_constraints.global);
1575    e_comp_wl->ptr_constraints.global = NULL;
1576
1577    /* destroy the global seat resource */
1578    if (e_comp_wl->seat.global)
1579      wl_global_destroy(e_comp_wl->seat.global);
1580    e_comp_wl->seat.global = NULL;
1581
1582    dont_set_e_input_keymap = EINA_FALSE;
1583    dont_use_xkb_cache = EINA_FALSE;
1584
1585    g_mutex_clear(&e_comp_wl->xkb.keymap_mutex);
1586    g_mutex_clear(&e_comp_wl->xkb.state_mutex);
1587
1588    g_mutex_clear(&e_comp_wl->kbd.keys_mutex);
1589    g_mutex_clear(&e_comp_wl->kbd.repeat_delay_mutex);
1590    g_mutex_clear(&e_comp_wl->kbd.repeat_rate_mutex);
1591 }
1592
1593 EINTERN Eina_Bool
1594 e_comp_wl_input_pointer_check(struct wl_resource *res)
1595 {
1596    return wl_resource_instance_of(res, &wl_pointer_interface,
1597                                   &_e_pointer_interface);
1598 }
1599
1600 EINTERN Eina_Bool
1601 e_comp_wl_input_relative_pointer_check(struct wl_resource *res)
1602 {
1603    return wl_resource_instance_of(res, &zwp_relative_pointer_v1_interface,
1604                                   &_e_relative_pointer_interface);
1605 }
1606
1607 EINTERN Eina_Bool
1608 e_comp_wl_input_keyboard_check(struct wl_resource *res)
1609 {
1610    return wl_resource_instance_of(res, &wl_keyboard_interface,
1611                                   &_e_keyboard_interface);
1612 }
1613
1614 EINTERN Eina_Bool
1615 e_comp_wl_input_keyboard_modifiers_serialize(void)
1616 {
1617    Eina_Bool changed = EINA_FALSE;
1618    xkb_mod_mask_t mod;
1619    xkb_layout_index_t grp;
1620
1621    g_mutex_lock(&e_comp_wl->kbd.mod_changed_mutex);
1622    g_mutex_lock(&e_comp_wl->xkb.state_mutex);
1623
1624    mod = xkb_state_serialize_mods(e_comp_wl->xkb.state,
1625                               XKB_STATE_DEPRESSED);
1626    changed |= mod != e_comp_wl->kbd.mod_depressed;
1627    e_comp_wl->kbd.mod_depressed = mod;
1628
1629    mod = xkb_state_serialize_mods(e_comp_wl->xkb.state,
1630                               XKB_STATE_MODS_LATCHED);
1631    changed |= mod != e_comp_wl->kbd.mod_latched;
1632    e_comp_wl->kbd.mod_latched = mod;
1633
1634    mod = xkb_state_serialize_mods(e_comp_wl->xkb.state,
1635                               XKB_STATE_MODS_LOCKED);
1636    changed |= mod != e_comp_wl->kbd.mod_locked;
1637    e_comp_wl->kbd.mod_locked = mod;
1638
1639    grp = xkb_state_serialize_layout(e_comp_wl->xkb.state,
1640                                 XKB_STATE_LAYOUT_EFFECTIVE);
1641    changed |= grp != e_comp_wl->kbd.mod_group;
1642    e_comp_wl->kbd.mod_group = grp;
1643
1644    g_mutex_unlock(&e_comp_wl->xkb.state_mutex);
1645    g_mutex_unlock(&e_comp_wl->kbd.mod_changed_mutex);
1646
1647    return changed;
1648 }
1649
1650 EINTERN void
1651 e_comp_wl_input_keyboard_modifiers_update(void)
1652 {
1653    uint32_t serial;
1654    struct wl_resource *res;
1655    Eina_List *l;
1656
1657    if (!e_comp_wl_input_keyboard_modifiers_serialize()) return;
1658    g_mutex_lock(&e_comp_wl->kbd.focused_mutex);
1659    if (!e_comp_wl->kbd.focused)
1660      {
1661        g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
1662        return;
1663      }
1664
1665    g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
1666
1667    serial = wl_display_next_serial(e_comp_wl->wl.disp);
1668    g_mutex_lock(&e_comp_wl->kbd.mod_changed_mutex);
1669    g_mutex_lock(&e_comp_wl->kbd.focused_mutex);
1670    EINA_LIST_FOREACH(e_comp_wl->kbd.focused, l, res)
1671      wl_keyboard_send_modifiers(res, serial,
1672                                 e_comp_wl->kbd.mod_depressed,
1673                                 e_comp_wl->kbd.mod_latched,
1674                                 e_comp_wl->kbd.mod_locked,
1675                                 e_comp_wl->kbd.mod_group);
1676    g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
1677    g_mutex_unlock(&e_comp_wl->kbd.mod_changed_mutex);
1678 }
1679
1680 EINTERN void
1681 e_comp_wl_input_keyboard_state_update(uint32_t keycode, Eina_Bool pressed)
1682 {
1683    enum xkb_key_direction dir;
1684
1685    g_mutex_lock(&e_comp_wl->xkb.state_mutex);
1686    if (!e_comp_wl->xkb.state)
1687      {
1688         g_mutex_unlock(&e_comp_wl->xkb.state_mutex);
1689         return;
1690      }
1691
1692    if (pressed) dir = XKB_KEY_DOWN;
1693    else dir = XKB_KEY_UP;
1694
1695    e_comp_wl->kbd.mod_changed =
1696      xkb_state_update_key(e_comp_wl->xkb.state, keycode + 8, dir);
1697
1698    g_mutex_unlock(&e_comp_wl->xkb.state_mutex);
1699
1700    e_comp_wl_input_keyboard_modifiers_update();
1701 }
1702
1703 EINTERN void
1704 e_comp_wl_input_pointer_enabled_set(Eina_Bool enabled)
1705 {
1706    /* check for valid compositor data */
1707    if (!e_comp->wl_comp_data)
1708      {
1709         ERR("No compositor data");
1710         return;
1711      }
1712
1713    e_comp_wl->ptr.enabled = !!enabled;
1714    _e_comp_wl_input_update_seat_caps(NULL);
1715 }
1716
1717 EINTERN void
1718 e_comp_wl_input_keyboard_enabled_set(Eina_Bool enabled)
1719 {
1720    /* check for valid compositor data */
1721    if (!e_comp->wl_comp_data)
1722      {
1723         ERR("No compositor data");
1724         return;
1725      }
1726
1727    e_comp_wl->kbd.enabled = !!enabled;
1728    _e_comp_wl_input_update_seat_caps(NULL);
1729 }
1730
1731 E_API Eina_Bool
1732 e_comp_wl_input_keymap_cache_file_use_get(void)
1733 {
1734    return use_cache_keymap;
1735 }
1736
1737 E_API Eina_Stringshare *
1738 e_comp_wl_input_keymap_path_get(struct xkb_rule_names names)
1739 {
1740    return eina_stringshare_printf("/var/lib/xkb/%s-%s-%s-%s-%s.xkb",
1741             names.rules ? names.rules : "evdev",
1742             names.model ? names.model : "pc105",
1743             names.layout ? names.layout : "us",
1744             names.variant ? names.variant : "",
1745             names.options ? names.options : "");
1746 }
1747
1748 EINTERN struct xkb_keymap *
1749 e_comp_wl_input_keymap_compile(struct xkb_context *ctx, struct xkb_rule_names names, char **keymap_path)
1750 {
1751    struct xkb_keymap *keymap;
1752    char *cache_path = NULL;
1753    FILE *file = NULL;
1754
1755    EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
1756
1757    TRACE_INPUT_BEGIN(e_comp_wl_input_keymap_compile);
1758
1759    if (e_config->xkb.use_cache && !dont_use_xkb_cache)
1760      {
1761         cache_path = (char *)e_comp_wl_input_keymap_path_get(names);
1762         file = fopen(cache_path, "r");
1763      }
1764
1765    if (!file)
1766      {
1767         INF("There is a no keymap file (%s). Generate keymap using rmlvo\n", cache_path);
1768
1769         /* fetch new keymap based on names */
1770         keymap = xkb_map_new_from_names(ctx, &names, 0);
1771         use_cache_keymap = EINA_FALSE;
1772      }
1773    else
1774      {
1775         INF("Keymap file (%s) has been found. xkb_keymap is going to be generated with it.\n", cache_path);
1776         keymap = xkb_map_new_from_file(ctx, file, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
1777         if (!keymap)
1778           {
1779              WRN("Keymap file is exist (%s) but it is invaild file. Generate keymap using rmlvo\n", cache_path);
1780              fclose(file);
1781              if (remove(cache_path) != 0)
1782                WRN("Failed to remove keymap file: %s (errno: %d)", cache_path, errno);
1783              keymap = xkb_map_new_from_names(ctx, &names, 0);
1784              use_cache_keymap = EINA_FALSE;
1785           }
1786         else
1787           {
1788              eina_stringshare_del(cache_path);
1789              cache_path = NULL;
1790              fclose(file);
1791              use_cache_keymap = EINA_TRUE;
1792           }
1793      }
1794
1795    *keymap_path = cache_path;
1796    EINA_SAFETY_ON_NULL_RETURN_VAL(keymap, NULL);
1797
1798    TRACE_INPUT_END();
1799
1800    return keymap;
1801 }
1802
1803 E_API void
1804 e_comp_wl_input_keymap_set(const char *rules, const char *model, const char *layout,
1805                            const char *variant, const char *options,
1806                            struct xkb_context *dflt_ctx, struct xkb_keymap *dflt_map)
1807 {
1808    struct xkb_keymap *keymap;
1809    struct xkb_rule_names names;
1810    char *keymap_path = NULL;
1811    Eina_Bool use_dflt_xkb = EINA_FALSE;
1812    const char *default_rules, *default_model, *default_layout, *default_variant, *default_options;
1813
1814    /* DBG("COMP_WL: Keymap Set: %s %s %s", rules, model, layout); */
1815    TRACE_INPUT_BEGIN(e_comp_wl_input_keymap_set);
1816
1817    if (dflt_ctx && dflt_map) use_dflt_xkb = EINA_TRUE;
1818
1819    /* unreference any existing context */
1820    if (e_comp_wl->xkb.context)
1821      xkb_context_unref(e_comp_wl->xkb.context);
1822
1823    /* create a new xkb context */
1824    if (use_dflt_xkb) e_comp_wl->xkb.context = dflt_ctx;
1825    else e_comp_wl->xkb.context = xkb_context_new(0);
1826
1827    if (!e_comp_wl->xkb.context)
1828      {
1829         TRACE_INPUT_END();
1830         return;
1831      }
1832
1833    if (e_config->xkb.use_cache && !dont_set_e_input_keymap)
1834      e_input_device_keyboard_cached_context_set(e_comp_wl->xkb.context);
1835
1836    /* assemble xkb_rule_names so we can fetch keymap */
1837    memset(&names, 0, sizeof(names));
1838    if (rules) names.rules = strdup(rules);
1839    else
1840      {
1841         default_rules = e_comp_wl_input_keymap_default_rules_get();
1842         names.rules = strdup(default_rules);
1843      }
1844    if (model) names.model = strdup(model);
1845    else
1846      {
1847         default_model = e_comp_wl_input_keymap_default_model_get();
1848         names.model = strdup(default_model);
1849      }
1850    if (layout) names.layout = strdup(layout);
1851    else
1852      {
1853         default_layout = e_comp_wl_input_keymap_default_layout_get();
1854         names.layout = strdup(default_layout);
1855      }
1856    if (variant) names.variant = strdup(variant);
1857    else
1858      {
1859         default_variant = e_comp_wl_input_keymap_default_variant_get();
1860         if (default_variant) names.variant = strdup(default_variant);
1861      }
1862    if (options) names.options = strdup(options);
1863    else
1864      {
1865         default_options = e_comp_wl_input_keymap_default_options_get();
1866         if (default_options) names.options = strdup(default_options);
1867      }
1868
1869    TRACE_INPUT_BEGIN(e_comp_wl_input_keymap_set_keymap_compile);
1870    if (use_dflt_xkb)
1871      {
1872         keymap = dflt_map;
1873         keymap_path = (char *)e_comp_wl_input_keymap_path_get(names);
1874         if (access(keymap_path, R_OK) == 0)
1875           {
1876              eina_stringshare_del(keymap_path);
1877              keymap_path = NULL;
1878           }
1879      }
1880    else
1881      keymap = e_comp_wl_input_keymap_compile(e_comp_wl->xkb.context, names, &keymap_path);
1882    TRACE_INPUT_END();
1883
1884    /* update compositor keymap */
1885    _e_comp_wl_input_keymap_update(keymap, keymap_path);
1886
1887    if (e_config->xkb.use_cache && !dont_set_e_input_keymap)
1888      e_input_device_keyboard_cached_keymap_set(keymap);
1889
1890    /* cleanup */
1891    if (keymap_path) eina_stringshare_del(keymap_path);
1892    free((char *)names.rules);
1893    free((char *)names.model);
1894    free((char *)names.layout);
1895    if (names.variant) free((char *)names.variant);
1896    if (names.options) free((char *)names.options);
1897    TRACE_INPUT_END();
1898 }
1899
1900 EINTERN const char*
1901 e_comp_wl_input_keymap_default_rules_get(void)
1902 {
1903    if (e_config->xkb.default_rmlvo.rules)
1904      return e_config->xkb.default_rmlvo.rules;
1905
1906    if (_env_e_default_xkb_rules)
1907      return _env_e_default_xkb_rules;
1908
1909    return "evdev";
1910 }
1911
1912 EINTERN const char*
1913 e_comp_wl_input_keymap_default_model_get(void)
1914 {
1915    if (e_config->xkb.default_rmlvo.model)
1916      return e_config->xkb.default_rmlvo.model;
1917
1918    if (_env_e_default_xkb_model)
1919      return _env_e_default_xkb_model;
1920
1921    return "pc105";
1922 }
1923
1924 EINTERN const char*
1925 e_comp_wl_input_keymap_default_layout_get(void)
1926 {
1927    if (e_config->xkb.default_rmlvo.layout)
1928      return e_config->xkb.default_rmlvo.layout;
1929
1930    if (_env_e_default_xkb_layout)
1931      return _env_e_default_xkb_layout;
1932
1933    return "us";
1934 }
1935
1936 EINTERN const char*
1937 e_comp_wl_input_keymap_default_variant_get(void)
1938 {
1939    if (e_config->xkb.default_rmlvo.variant)
1940      return e_config->xkb.default_rmlvo.variant;
1941
1942    if (_env_e_default_xkb_variant)
1943      return _env_e_default_xkb_variant;
1944
1945    return NULL;
1946 }
1947
1948 EINTERN const char*
1949 e_comp_wl_input_keymap_default_options_get(void)
1950 {
1951    if (e_config->xkb.default_rmlvo.options)
1952      return e_config->xkb.default_rmlvo.options;
1953
1954    if (_env_e_default_xkb_opts)
1955      return _env_e_default_xkb_opts;
1956
1957    return NULL;
1958 }
1959
1960 EINTERN void
1961 e_comp_wl_input_touch_enabled_set(Eina_Bool enabled)
1962 {
1963    /* check for valid compositor data */
1964    if (!e_comp->wl_comp_data)
1965      {
1966         ERR("No compositor data");
1967         return;
1968      }
1969
1970    e_comp_wl->touch.enabled = !!enabled;
1971    _e_comp_wl_input_update_seat_caps(NULL);
1972 }
1973
1974 EINTERN void
1975 e_comp_wl_input_seat_caps_set(unsigned int caps)
1976 {
1977    Eina_Bool need_update = EINA_FALSE;
1978
1979    /* check for valid compositor data */
1980    if (!e_comp->wl_comp_data)
1981      {
1982         ERR("No compositor data");
1983         return;
1984      }
1985
1986    if (caps & E_INPUT_SEAT_POINTER)
1987      e_comp_wl->ptr.enabled = need_update = EINA_TRUE;
1988    if (caps & E_INPUT_SEAT_KEYBOARD)
1989      e_comp_wl->kbd.enabled = need_update = EINA_TRUE;
1990    if (caps & E_INPUT_SEAT_TOUCH)
1991      e_comp_wl->touch.enabled = need_update = EINA_TRUE;
1992
1993    if (need_update)
1994      _e_comp_wl_input_update_seat_caps(NULL);
1995 }
1996
1997 EINTERN Eina_Bool
1998 e_comp_wl_input_touch_check(struct wl_resource *res)
1999 {
2000    return wl_resource_instance_of(res, &wl_touch_interface,
2001                                   &_e_touch_interface);
2002 }
2003
2004 E_API void
2005 e_comp_wl_input_keyboard_repeat_set(int delay, int rate)
2006 {
2007    struct wl_resource *res;
2008    Eina_List *l;
2009
2010    EINA_SAFETY_ON_NULL_RETURN(e_comp_wl);
2011
2012    g_mutex_lock(&e_comp_wl->kbd.repeat_delay_mutex);
2013    e_comp_wl->kbd.repeat_delay = delay;
2014    g_mutex_unlock(&e_comp_wl->kbd.repeat_delay_mutex);
2015
2016    g_mutex_lock(&e_comp_wl->kbd.repeat_rate_mutex);
2017    e_comp_wl->kbd.repeat_rate = rate;
2018    g_mutex_unlock(&e_comp_wl->kbd.repeat_rate_mutex);
2019
2020    g_mutex_lock(&e_comp_wl->kbd.resource_mutex);
2021    g_mutex_lock(&e_comp_wl->kbd.repeat_delay_mutex);
2022    g_mutex_lock(&e_comp_wl->kbd.repeat_rate_mutex);
2023    EINA_LIST_FOREACH(e_comp_wl->kbd.resources, l, res)
2024      {
2025         if (wl_resource_get_version(res) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
2026           wl_keyboard_send_repeat_info(res, e_comp_wl->kbd.repeat_rate,
2027                                        e_comp_wl->kbd.repeat_delay);
2028      }
2029    g_mutex_unlock(&e_comp_wl->kbd.repeat_rate_mutex);
2030    g_mutex_unlock(&e_comp_wl->kbd.repeat_delay_mutex);
2031    g_mutex_unlock(&e_comp_wl->kbd.resource_mutex);
2032 }
2033
2034 typedef struct _keycode_map{
2035     xkb_keysym_t keysym;
2036     xkb_keycode_t keycode;
2037 } keycode_map;
2038
2039 static void
2040 find_keycode(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
2041 {
2042    keycode_map *found_keycodes = (keycode_map *)data;
2043    xkb_keysym_t keysym = found_keycodes->keysym;
2044    int nsyms = 0;
2045    const xkb_keysym_t *syms_out = NULL;
2046
2047    nsyms = xkb_keymap_key_get_syms_by_level(keymap, key, 0, 0, &syms_out);
2048    if (nsyms && syms_out)
2049      {
2050         if (*syms_out == keysym)
2051           {
2052              found_keycodes->keycode = key;
2053           }
2054      }
2055 }
2056
2057 int
2058 _e_comp_wl_input_keymap_keysym_to_keycode(struct xkb_keymap *keymap, xkb_keysym_t keysym)
2059 {
2060    keycode_map found_keycodes = {0,};
2061    found_keycodes.keysym = keysym;
2062    xkb_keymap_key_for_each(keymap, find_keycode, &found_keycodes);
2063
2064    return found_keycodes.keycode;
2065 }
2066
2067 E_API int
2068 e_comp_wl_input_keymap_keyname_to_keycode(const char * name)
2069 {
2070    struct xkb_keymap *keymap = NULL;
2071    xkb_keysym_t keysym = 0x0;
2072    int keycode = 0;
2073    char *name_tmp;
2074
2075    EINA_SAFETY_ON_NULL_RETURN_VAL(name, 0);
2076    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, 0);
2077
2078    g_mutex_lock(&e_comp_wl->xkb.keymap_mutex);
2079    keymap = e_comp_wl->xkb.keymap;
2080    g_mutex_unlock(&e_comp_wl->xkb.keymap_mutex);
2081    EINA_SAFETY_ON_NULL_GOTO(keymap, finish);
2082
2083    keysym = xkb_keysym_from_name(name, XKB_KEYSYM_NO_FLAGS);
2084    if (keysym == XKB_KEY_NoSymbol)
2085      {
2086         if (strlen(name) <= sizeof("Keycode-")) goto finish;
2087
2088         if (!strncmp(name, "Keycode-", sizeof("Keycode-") - 1))
2089           {
2090              name_tmp = (char *)name + sizeof("Keycode-") - 1;
2091              keycode = atoi(name_tmp);
2092              if (keycode <= 8) goto finish;
2093
2094              return keycode;
2095           }
2096         else
2097           goto finish;
2098      }
2099
2100    keycode = _e_comp_wl_input_keymap_keysym_to_keycode(keymap, keysym);
2101
2102    return keycode;
2103
2104 finish:
2105    return 0;
2106 }
2107
2108 EINTERN char *
2109 e_comp_wl_input_keymap_keycode_to_keyname(int keycode)
2110 {
2111    struct xkb_state *state;
2112    xkb_keysym_t sym = XKB_KEY_NoSymbol;
2113    char name[256] = {0, };
2114
2115    EINA_SAFETY_ON_FALSE_RETURN_VAL(8 <= keycode, NULL);
2116    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, NULL);
2117    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl->xkb.state, NULL);
2118
2119    g_mutex_lock(&e_comp_wl->xkb.state_mutex);
2120    state = e_comp_wl->xkb.state;
2121    g_mutex_unlock(&e_comp_wl->xkb.state_mutex);
2122
2123    sym = xkb_state_key_get_one_sym(state, keycode);
2124    if (sym == XKB_KEY_NoSymbol)
2125      {
2126         snprintf(name, sizeof(name), "Keycode-%u", keycode);
2127      }
2128    else
2129      xkb_keysym_get_name(sym, name, sizeof(name));
2130
2131    return strdup(name);
2132 }