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