5e829a3e87db0c4d7d6d42379f268c15f94f301c
[platform/upstream/enlightenment.git] / src / bin / e_devicemgr_wl.c
1 #include "e_devicemgr_private.h"
2 #include "e_input_intern.h"
3 #include "e_comp_wl_intern.h"
4
5 #ifdef HAVE_CYNARA
6 #define E_DEVMGR_CYNARA_ERROR_CHECK_GOTO(func_name, ret, label) \
7   do \
8     { \
9        if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret)) \
10           { \
11              _e_devicemgr_util_cynara_log(func_name, ret); \
12              goto label; \
13           } \
14     } \
15   while (0)
16
17 static void
18 _e_devicemgr_util_cynara_log(const char *func_name, int err)
19 {
20 #define CYNARA_BUFSIZE 128
21    char buf[CYNARA_BUFSIZE] = "\0";
22    int ret;
23
24    ret = cynara_strerror(err, buf, CYNARA_BUFSIZE);
25    if (ret != CYNARA_API_SUCCESS)
26      {
27         DMDBG("Failed to cynara_strerror: %d (error log about %s: %d)\n", ret, func_name, err);
28         return;
29      }
30    DMDBG("%s is failed: %s\n", func_name, buf);
31 }
32
33 static Eina_Bool
34 _e_devicemgr_util_do_privilege_check(struct wl_client *client, int socket_fd, const char *rule)
35 {
36    int ret, pid;
37    char *clientSmack=NULL, *uid=NULL, *client_session=NULL;
38    Eina_Bool res = EINA_FALSE;
39
40    /* If initialization of cynara has been failed, let's not to do further permission checks. */
41    if (e_devicemgr->wl_data->p_cynara == NULL && e_devicemgr->wl_data->cynara_initialized) return EINA_TRUE;
42    if (socket_fd < 0) return EINA_FALSE;
43
44    ret = cynara_creds_socket_get_client(socket_fd, CLIENT_METHOD_SMACK, &clientSmack);
45    E_DEVMGR_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_client", ret, finish);
46
47    ret = cynara_creds_socket_get_user(socket_fd, USER_METHOD_UID, &uid);
48    E_DEVMGR_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_user", ret, finish);
49
50    ret = cynara_creds_socket_get_pid(socket_fd, &pid);
51    E_DEVMGR_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_pid", ret, finish);
52
53    client_session = cynara_session_from_pid(pid);
54
55    ret = cynara_check(e_devicemgr->wl_data->p_cynara, clientSmack, client_session, uid, rule);
56
57    if (CYNARA_API_ACCESS_ALLOWED == ret)
58         res = EINA_TRUE;
59
60 finish:
61    E_FREE(client_session);
62    E_FREE(clientSmack);
63    E_FREE(uid);
64
65    return res;
66 }
67 #endif
68
69 static void
70 _e_devicemgr_wl_device_cb_axes_select(struct wl_client *client, struct wl_resource *resource, struct wl_array *axes)
71 {
72    return;
73 }
74
75 static void
76 _e_devicemgr_wl_device_cb_release(struct wl_client *client, struct wl_resource *resource)
77 {
78    wl_resource_destroy(resource);
79 }
80
81 static const struct tizen_input_device_interface _e_devicemgr_wl_device_interface =
82 {
83    _e_devicemgr_wl_device_cb_axes_select,
84    _e_devicemgr_wl_device_cb_release,
85 };
86
87 static void
88 _e_devicemgr_wl_device_data_destroy(E_Devicemgr_Input_Device_User_Data *device_user_data)
89 {
90    if (!device_user_data) return;
91
92    DMDBG("Destroy device user data. (res: %u)", device_user_data->dev_res ? wl_resource_get_id(device_user_data->dev_res) : 0x0);
93
94    if (device_user_data->mgr_data)
95      device_user_data->mgr_data->user_data_list = eina_list_remove(device_user_data->mgr_data->user_data_list, device_user_data);
96
97    if (device_user_data->dev)
98      device_user_data->dev->resources = eina_list_remove(device_user_data->dev->resources, device_user_data->dev_res);
99
100    if (device_user_data->dev_res)
101      wl_resource_set_user_data(device_user_data->dev_res, NULL);
102
103    E_FREE(device_user_data);
104 }
105
106 static void
107 _e_devicemgr_wl_device_cb_unbind(struct wl_resource *resource)
108 {
109    E_Devicemgr_Input_Device_User_Data *device_user_data;
110
111    DMDBG("Unbind tizen_input_device: %u (client: %p)", wl_resource_get_id(resource), wl_resource_get_client(resource));
112    if (!(device_user_data = wl_resource_get_user_data(resource))) return;
113
114    _e_devicemgr_wl_device_data_destroy(device_user_data);
115 }
116
117 void
118 e_devicemgr_wl_device_update(E_Devicemgr_Input_Device *dev)
119 {
120    struct wl_array axes;
121    Eina_List *l;
122    struct wl_resource *res;
123
124    wl_array_init(&axes);
125
126    EINA_LIST_FOREACH(dev->resources, l, res)
127      {
128         tizen_input_device_send_device_info(res, dev->name, dev->clas, dev->subclas, &axes);
129      }
130 }
131
132 void
133 e_devicemgr_wl_device_add(E_Devicemgr_Input_Device *dev)
134 {
135    struct wl_resource *res, *seat_res, *dev_mgr_res;
136    Eina_List *l, *ll;
137    uint32_t serial;
138    struct wl_client *wc;
139    E_Devicemgr_Input_Device_User_Data *device_user_data;
140    struct wl_array axes;
141    E_Devicemgr_Input_Device_Mgr_Data *mgr_data;
142    E_Comp_Wl_Seat *seat_data;
143
144    /* TODO: find the seat corresponding to event */
145    serial = wl_display_next_serial(e_comp_wl->wl.disp);
146    wl_array_init(&axes);
147
148    EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_res)
149      {
150         seat_data = wl_resource_get_user_data(seat_res);
151         if (!seat_data) continue;
152         if (!seat_data->is_first_resource)
153           {
154              DMDBG("The seat (res:%d) is not the first resource bound to client (%p)",
155                    wl_resource_get_id(seat_res), wl_resource_get_client(seat_res));
156              continue;
157           }
158
159         wc = wl_resource_get_client(seat_res);
160
161         EINA_LIST_FOREACH(e_devicemgr->wl_data->mgr_data_list, ll, mgr_data)
162           {
163              dev_mgr_res = mgr_data->resource;
164              if (wl_resource_get_client(dev_mgr_res) != wc) continue;
165              if (!mgr_data->is_first_resource)
166                {
167                   DMDBG("This device_manager (res:%d) not the first resource bound to client (%p)",
168                         wl_resource_get_id(dev_mgr_res), wc);
169                   continue;
170                }
171              res = wl_resource_create(wc, &tizen_input_device_interface, 1, 0);
172              if (!res)
173                {
174                   DMERR("Could not create tizen_input_device resource");
175                   wl_client_post_no_memory(wc);
176                   break;
177                }
178
179              device_user_data = E_NEW(E_Devicemgr_Input_Device_User_Data, 1);
180              if (!device_user_data)
181                {
182                   DMERR("Failed to allocate memory for input device user data\n");
183                   wl_client_post_no_memory(wc);
184                   wl_resource_destroy(res);
185                   break;
186                }
187              device_user_data->dev = dev;
188              device_user_data->dev_mgr_res = dev_mgr_res;
189              device_user_data->seat_res = seat_res;
190              device_user_data->dev_res = res;
191              device_user_data->mgr_data = mgr_data;
192
193              dev->resources = eina_list_append(dev->resources, res);
194              mgr_data->user_data_list = eina_list_append(mgr_data->user_data_list, device_user_data);
195
196              wl_resource_set_implementation(res, &_e_devicemgr_wl_device_interface, device_user_data,
197                                             _e_devicemgr_wl_device_cb_unbind);
198              tizen_input_device_manager_send_device_add(dev_mgr_res, serial, dev->identifier, res, seat_res);
199              tizen_input_device_send_device_info(res, dev->name, dev->clas, dev->subclas, &axes);
200           }
201      }
202 }
203
204 void
205 e_devicemgr_wl_device_del(E_Devicemgr_Input_Device *dev)
206 {
207    struct wl_resource *res;
208    uint32_t serial;
209    E_Devicemgr_Input_Device_User_Data *device_user_data;
210
211    serial = wl_display_next_serial(e_comp_wl->wl.disp);
212
213    EINA_LIST_FREE(dev->resources, res)
214      {
215         device_user_data = wl_resource_get_user_data(res);
216         if (!device_user_data) continue;
217         if (!device_user_data->dev_mgr_res || !device_user_data->seat_res ||
218             !device_user_data->dev_res)
219           continue;
220
221         device_user_data->dev = NULL;
222         tizen_input_device_manager_send_device_remove(
223                                    device_user_data->dev_mgr_res,
224                                    serial, dev->identifier,
225                                    device_user_data->dev_res,
226                                    device_user_data->seat_res);
227
228         _e_devicemgr_wl_device_data_destroy(device_user_data); // Make inert
229      }
230 }
231
232 void
233 e_devicemgr_wl_detent_send_event(int detent)
234 {
235    E_Devicemgr_Input_Device *input_dev;
236    struct wl_resource *dev_res;
237    struct wl_client *wc;
238    Eina_List *l, *ll;
239    wl_fixed_t f_value;
240    E_Client *ec;
241    struct wl_resource *surface = NULL;
242
243    ec = e_client_focused_get();
244
245    if (!ec) return;
246    if (e_object_is_del(E_OBJECT(ec))) return;
247    if (ec->ignored) return;
248    if (!ec->comp_data) return;
249
250    surface = e_comp_wl_client_surface_get(ec);
251    if (!surface) return;
252
253    f_value = wl_fixed_from_double(detent * 1.0);
254    wc = wl_resource_get_client(surface);
255
256    g_rec_mutex_lock(&e_devicemgr->device_list_mutex);
257    EINA_LIST_FOREACH(e_devicemgr->device_list, l, input_dev)
258      {
259         if (!strncmp(input_dev->name, DETENT_DEVICE_NAME, sizeof(DETENT_DEVICE_NAME)))
260           {
261              EINA_LIST_FOREACH(input_dev->resources, ll, dev_res)
262                {
263                   if (wl_resource_get_client(dev_res) != wc) continue;
264                   tizen_input_device_send_axis(dev_res, TIZEN_INPUT_DEVICE_AXIS_TYPE_DETENT, f_value);
265
266                   DMINF("DETENT : %d => E_Client: %p (pid: %d) (pname: %s)",
267                          detent, ec, ec->netwm.pid, e_client_util_name_get(ec));
268                }
269           }
270      }
271    g_rec_mutex_unlock(&e_devicemgr->device_list_mutex);
272 }
273
274 void
275 e_devicemgr_wl_block_send_expired(struct wl_resource *resource)
276 {
277    if (!resource) return;
278    tizen_input_device_manager_send_block_expired(resource);
279 }
280
281 void
282 e_devicemgr_wl_touch_max_count_send(int slot, struct wl_resource *res, struct wl_resource *seat_res)
283 {
284    struct wl_resource *seat_resource, *dev_mgr_resource;
285    Eina_List *l, *ll;
286    uint32_t serial;
287    struct wl_client *wc;
288    E_Devicemgr_Input_Device_Mgr_Data *mgr_data;
289
290    serial = wl_display_next_serial(e_comp_wl->wl.disp);
291
292    if (res && seat_res)
293      {
294         if (wl_resource_get_version(res) < 4) return;
295         tizen_input_device_manager_send_max_touch_count(res, serial, slot, seat_res);
296      }
297    else
298      {
299         EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_resource)
300           {
301              wc = wl_resource_get_client(seat_resource);
302
303              EINA_LIST_FOREACH(e_devicemgr->wl_data->mgr_data_list, ll, mgr_data)
304                {
305                   dev_mgr_resource = mgr_data->resource;
306                   if (wl_resource_get_client(dev_mgr_resource) != wc) continue;
307                   if (wl_resource_get_version(dev_mgr_resource) < 4) continue;
308                   tizen_input_device_manager_send_max_touch_count(dev_mgr_resource, serial, slot, seat_resource);
309                }
310           }
311      }
312 }
313
314 void
315 e_devicemgr_wl_generator_with_sync_send_event(struct wl_resource *resource, int result)
316 {
317    if (!resource) return;
318    DMDBG("Init Generator with sync. send result: %d", result);
319    tizen_input_device_manager_send_error(resource, result);
320 }
321
322 static void
323 _e_devicemgr_wl_cb_block_events(struct wl_client *client, struct wl_resource *resource, uint32_t serial, uint32_t clas, uint32_t duration)
324 {
325    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
326
327 #ifdef HAVE_CYNARA
328    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
329                                                           "http://tizen.org/privilege/internal/inputdevice.block"))
330      {
331         DMERR("block_events request:priv check failed");
332         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
333         return;
334      }
335 #endif
336
337    ret = e_devicemgr_block_add(client, resource, clas, duration);
338    tizen_input_device_manager_send_error(resource, ret);
339 }
340
341 static void
342 _e_devicemgr_wl_cb_unblock_events(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
343 {
344    int ret;
345
346 #ifdef HAVE_CYNARA
347    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
348                                                           "http://tizen.org/privilege/internal/inputdevice.block"))
349      {
350         DMERR("unblock_events request:priv check failed");
351         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
352         return;
353      }
354 #endif
355
356    ret = e_devicemgr_block_remove(client);
357    tizen_input_device_manager_send_error(resource, ret);
358 }
359
360 static void
361 _e_devicemgr_wl_cb_init_generator(struct wl_client *client, struct wl_resource *resource, uint32_t clas)
362 {
363    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
364
365 #ifdef HAVE_CYNARA
366    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
367                                                           "http://tizen.org/privilege/inputgenerator"))
368      {
369         DMERR("init_generator request:priv check failed");
370         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
371         return;
372      }
373 #endif
374
375    ret = e_devicemgr_inputgen_add(client, resource, clas, INPUT_GENERATOR_DEVICE);
376    tizen_input_device_manager_send_error(resource, ret);
377 }
378
379 static void
380 _e_devicemgr_wl_cb_init_generator_with_name(struct wl_client *client, struct wl_resource *resource, uint32_t clas, const char *name)
381 {
382    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
383
384 #ifdef HAVE_CYNARA
385    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
386                                                           "http://tizen.org/privilege/inputgenerator"))
387      {
388         DMERR("init_generator_with_name request:priv check failed");
389         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
390         return;
391      }
392 #endif
393
394    ret = e_devicemgr_inputgen_add(client, resource, clas, name);
395    tizen_input_device_manager_send_error(resource, ret);
396 }
397
398 static void
399 _e_devicemgr_wl_cb_init_generator_with_sync(struct wl_client *client, struct wl_resource *resource, uint32_t clas, const char *name)
400 {
401 #ifdef HAVE_CYNARA
402    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
403                                                           "http://tizen.org/privilege/inputgenerator"))
404      {
405         DMERR("_e_devicemgr_wl_cb_init_generator_with_sync request:priv check failed");
406         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
407         return;
408      }
409 #endif
410
411    e_devicemgr_inputgen_add_with_sync(client, resource, clas, name);
412 }
413
414 static void
415 _e_devicemgr_wl_cb_deinit_generator(struct wl_client *client, struct wl_resource *resource, uint32_t clas)
416 {
417    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
418
419 #ifdef HAVE_CYNARA
420    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
421                                                           "http://tizen.org/privilege/inputgenerator"))
422      {
423         DMERR("deinit_generator request:priv check failed");
424         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
425         return;
426      }
427 #endif
428
429    e_devicemgr_inputgen_remove(client, resource, clas);
430    tizen_input_device_manager_send_error(resource, ret);
431 }
432
433 static void
434 _e_devicemgr_wl_cb_generate_key(struct wl_client *client, struct wl_resource *resource, const char *keyname, uint32_t pressed)
435 {
436    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
437
438 #ifdef HAVE_CYNARA
439    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
440                                                           "http://tizen.org/privilege/inputgenerator"))
441      {
442         DMERR("generate_key request:priv check failed");
443         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
444         return;
445      }
446 #endif
447
448    ret = e_devicemgr_inputgen_generate_key(client, resource, keyname, (Eina_Bool)!!pressed);
449    tizen_input_device_manager_send_error(resource, ret);
450 }
451
452 static void
453 _e_devicemgr_wl_cb_generate_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t button)
454 {
455    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
456
457 #ifdef HAVE_CYNARA
458    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
459                                                           "http://tizen.org/privilege/inputgenerator"))
460      {
461         DMERR("_generate_pointer request:priv check failed");
462         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
463         return;
464      }
465 #endif
466
467    ret = e_devicemgr_inputgen_generate_pointer(client, resource, type, x, y, button);
468    tizen_input_device_manager_send_error(resource, ret);
469 }
470
471 static void
472 _e_devicemgr_wl_cb_generate_touch(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t finger)
473 {
474    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
475
476 #ifdef HAVE_CYNARA
477    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client), "http://tizen.org/privilege/inputgenerator"))
478      {
479         DMERR("_e_input_devmgr_cb_generate_touch:priv check failed");
480         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
481         return;
482      }
483 #endif
484
485    ret = e_devicemgr_inputgen_generate_touch(client, resource, type, x, y, finger);
486    tizen_input_device_manager_send_error(resource, ret);
487 }
488
489 static void
490 _e_devicemgr_wl_cb_pointer_warp(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y)
491 {
492    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
493
494    ret = e_devicemgr_input_pointer_warp(client, resource, surface, x, y);
495
496    tizen_input_device_manager_send_error(resource, ret);
497 }
498
499 static void
500 _e_devicemgr_wl_cb_destroy(struct wl_client *client, struct wl_resource *resource)
501 {
502    wl_resource_destroy(resource);
503 }
504
505 static void
506 _e_devicemgr_wl_cb_generate_axis(struct wl_client *client, struct wl_resource *resource, uint32_t type, wl_fixed_t value)
507 {
508    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
509
510 #ifdef HAVE_CYNARA
511    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
512                                                           "http://tizen.org/privilege/inputgenerator"))
513      {
514         DMERR("_generate_pointer request:priv check failed");
515         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
516         return;
517      }
518 #endif
519
520    if (type == TIZEN_INPUT_DEVICE_MANAGER_AXIS_TYPE_WHEEL ||
521        type == TIZEN_INPUT_DEVICE_MANAGER_AXIS_TYPE_HWHEEL)
522      ret = e_devicemgr_inputgen_generate_wheel(client, resource, type, (int)wl_fixed_to_double(value));
523    else
524      ret = e_devicemgr_inputgen_touch_axis_store(client, resource, type, wl_fixed_to_double(value));
525    tizen_input_device_manager_send_error(resource, ret);
526 }
527
528 static void
529 _e_devicemgr_wl_cb_set_touch_count(struct wl_client *client, struct wl_resource *resource, int32_t max_count)
530 {
531    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
532
533 #ifdef HAVE_CYNARA
534    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
535                                                           "http://tizen.org/privilege/inputgenerator"))
536      {
537         DMERR("_generate_pointer request:priv check failed");
538         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
539         return;
540      }
541 #endif
542
543    if (e_config->configured_max_touch.use)
544      {
545         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NOT_ALLOWED;
546      }
547    else
548      {
549         if (max_count > e_input_touch_max_count_get())
550           {
551              e_input_touch_max_count_set(max_count);
552           }
553      }
554
555    tizen_input_device_manager_send_error(resource, ret);
556 }
557
558 static void
559 _e_devicemgr_wl_cb_keyboard_grab(struct wl_client *client, struct wl_resource *resource,
560                                  struct wl_resource *surface, uint32_t subclas)
561 {
562    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
563
564 #ifdef HAVE_CYNARA
565    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
566                                                           E_PRIVILEGE_INTERNAL_DEFAULT_PLATFORM))
567      {
568         DMERR("keyboard_grab request:priv check failed");
569         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
570         return;
571      }
572 #endif
573
574    ret = e_devicemgr_keyboard_grab(client, surface, subclas);
575    tizen_input_device_manager_send_error(resource, ret);
576 }
577
578 static void
579 _e_devicemgr_wl_cb_keyboard_ungrab(struct wl_client *client, struct wl_resource *resource,
580                                    struct wl_resource *surface)
581 {
582    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
583
584 #ifdef HAVE_CYNARA
585    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
586                                                           E_PRIVILEGE_INTERNAL_DEFAULT_PLATFORM))
587      {
588         DMERR("keyboard_ungrab request:priv check failed");
589         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
590         return;
591      }
592 #endif
593
594    ret = e_devicemgr_keyboard_ungrab(client, surface);
595    tizen_input_device_manager_send_error(resource, ret);
596 }
597
598
599 static const struct tizen_input_device_manager_interface _e_devicemgr_wl_implementation = {
600    _e_devicemgr_wl_cb_block_events,
601    _e_devicemgr_wl_cb_unblock_events,
602    _e_devicemgr_wl_cb_init_generator,
603    _e_devicemgr_wl_cb_deinit_generator,
604    _e_devicemgr_wl_cb_generate_key,
605    _e_devicemgr_wl_cb_generate_pointer,
606    _e_devicemgr_wl_cb_generate_touch,
607    _e_devicemgr_wl_cb_pointer_warp,
608    _e_devicemgr_wl_cb_init_generator_with_name,
609    _e_devicemgr_wl_cb_destroy,
610    _e_devicemgr_wl_cb_generate_axis,
611    _e_devicemgr_wl_cb_set_touch_count,
612    _e_devicemgr_wl_cb_init_generator_with_sync,
613    _e_devicemgr_wl_cb_keyboard_grab,
614    _e_devicemgr_wl_cb_keyboard_ungrab
615 };
616
617 static void
618 _e_devicemgr_wl_cb_unbind(struct wl_resource *resource)
619 {
620    E_Devicemgr_Input_Device_Mgr_Data *mgr_data;
621    E_Devicemgr_Input_Device_User_Data *device_user_data;
622
623    if(!e_comp_wl) return;
624
625    mgr_data = wl_resource_get_user_data(resource);
626    if (!mgr_data) return;
627
628    DMDBG("Unbind tizen_input_device_manager: %u (client: %p)", wl_resource_get_id(resource), wl_resource_get_client(resource));
629
630    EINA_LIST_FREE(mgr_data->user_data_list, device_user_data)
631      {
632         device_user_data->mgr_data = NULL;
633         _e_devicemgr_wl_device_data_destroy(device_user_data);
634      }
635    e_devicemgr->wl_data->mgr_data_list = eina_list_remove(e_devicemgr->wl_data->mgr_data_list, mgr_data);
636
637    E_FREE(mgr_data);
638 }
639
640 static void
641 _e_devicemgr_wl_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
642 {
643    struct wl_resource *res, *seat_res, *device_res;
644    Eina_List *l, *ll;
645    uint32_t serial;
646    E_Devicemgr_Input_Device *dev;
647    struct wl_array axes;
648    E_Devicemgr_Input_Device_User_Data *device_user_data;
649    E_Devicemgr_Input_Device_Mgr_Data *mgr_data, *tmp_data;
650
651    mgr_data = E_NEW(E_Devicemgr_Input_Device_Mgr_Data, 1);
652    if (!mgr_data)
653      {
654         DMERR("Failed to allocate memory for input device mgr data\n");
655         wl_client_post_no_memory(client);
656         return;
657      }
658    mgr_data->is_first_resource = 1;
659
660    EINA_LIST_FOREACH(e_devicemgr->wl_data->mgr_data_list, l, tmp_data)
661      {
662         if (wl_resource_get_client(tmp_data->resource) != client) continue;
663         DMDBG("tizen_input_device_manager (res: %d) is already bound to client (%p)",
664               wl_resource_get_id(tmp_data->resource), client);
665         mgr_data->is_first_resource = 0;
666         break;
667      }
668
669    if (!(res = wl_resource_create(client, &tizen_input_device_manager_interface, version, id)))
670      {
671         DMERR("Could not create tizen_input_device_manager_interface resource: %m");
672         wl_client_post_no_memory(client);
673         E_FREE(mgr_data);
674         return;
675      }
676
677    DMDBG("Bind tizen_input_device_manager: %u (client: %p)", wl_resource_get_id(res), wl_resource_get_client(res));
678
679    mgr_data->resource = res;
680    mgr_data->user_data_list = NULL;
681    e_devicemgr->wl_data->mgr_data_list = eina_list_append(e_devicemgr->wl_data->mgr_data_list, mgr_data);
682
683    wl_resource_set_implementation(res, &_e_devicemgr_wl_implementation, mgr_data,
684                                   _e_devicemgr_wl_cb_unbind);
685
686    EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_res)
687      {
688         if (wl_resource_get_client(seat_res) != client) continue;
689
690         wl_array_init(&axes);
691         serial = wl_display_next_serial(e_comp_wl->wl.disp);
692
693         if (e_devicemgr->max_touch_count > 0)
694           {
695              e_devicemgr_wl_touch_max_count_send(e_devicemgr->max_touch_count, res, seat_res);
696           }
697
698         if (!mgr_data->is_first_resource)
699           {
700              DMDBG("This device_manager (res:%d) is not the first resource bound to client (%p)",
701                    wl_resource_get_id(res), client);
702              continue;
703           }
704
705         g_rec_mutex_lock(&e_devicemgr->device_list_mutex);
706         EINA_LIST_FOREACH(e_devicemgr->device_list, ll, dev)
707           {
708              device_res = wl_resource_create(client, &tizen_input_device_interface, 1, 0);
709              if (!device_res)
710                {
711                   DMERR("Could not create tizen_input_device resource: %m");
712                   wl_client_post_no_memory(client);
713                   g_rec_mutex_unlock(&e_devicemgr->device_list_mutex);
714                   return;
715                }
716              device_user_data = E_NEW(E_Devicemgr_Input_Device_User_Data, 1);
717              if (!device_user_data)
718                {
719                   DMERR("Failed to allocate memory for input device user data\n");
720                   wl_client_post_no_memory(client);
721                   wl_resource_destroy(device_res);
722                   g_rec_mutex_unlock(&e_devicemgr->device_list_mutex);
723                   return;
724                }
725              device_user_data->dev = dev;
726              device_user_data->dev_mgr_res = res;
727              device_user_data->seat_res = seat_res;
728              device_user_data->dev_res = device_res;
729              device_user_data->mgr_data = mgr_data;
730
731              dev->resources = eina_list_append(dev->resources, device_res);
732              mgr_data->user_data_list = eina_list_append(mgr_data->user_data_list, device_user_data);
733
734              wl_resource_set_implementation(device_res, &_e_devicemgr_wl_device_interface, device_user_data,
735                                             _e_devicemgr_wl_device_cb_unbind);
736
737              tizen_input_device_manager_send_device_add(res, serial, dev->identifier, device_res, seat_res);
738              tizen_input_device_send_device_info(device_res, dev->name, dev->clas, dev->subclas, &axes);
739           }
740         g_rec_mutex_unlock(&e_devicemgr->device_list_mutex);
741      }
742 }
743
744 Eina_Bool
745 e_devicemgr_wl_init(void)
746 {
747    if (!e_comp_wl) return EINA_FALSE;
748    if (!e_comp_wl->wl.disp) return EINA_FALSE;
749
750    if (e_devicemgr->wl_data) return EINA_TRUE;
751
752    e_devicemgr->wl_data = E_NEW(E_Devicemgr_Wl_Data, 1);
753    EINA_SAFETY_ON_NULL_RETURN_VAL(e_devicemgr->wl_data, EINA_FALSE);
754
755    /* try to add tizen_input_device_manager to wayland globals */
756    e_devicemgr->wl_data->global = wl_global_create(e_comp_wl->wl.disp,
757                                                    &tizen_input_device_manager_interface, 6,
758                                                    NULL, _e_devicemgr_wl_cb_bind);
759    if (!e_devicemgr->wl_data->global)
760      {
761         DMERR("Could not add tizen_input_device_manager to wayland globals");
762         return EINA_FALSE;
763      }
764    e_devicemgr->wl_data->mgr_data_list = NULL;
765
766    /* initialization of cynara for checking privilege */
767 #ifdef HAVE_CYNARA
768    int ret;
769
770    ret = cynara_initialize(&e_devicemgr->wl_data->p_cynara, NULL);
771    if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
772      {
773         _e_devicemgr_util_cynara_log("cynara_initialize", ret);
774         e_devicemgr->wl_data->p_cynara = NULL;
775      }
776    e_devicemgr->wl_data->cynara_initialized = EINA_TRUE;
777 #endif
778
779    return EINA_TRUE;
780 }
781
782 void
783 e_devicemgr_wl_shutdown(void)
784 {
785    if (!e_devicemgr->wl_data) return;
786    /* destroy the global seat resource */
787    if (e_devicemgr->wl_data->global)
788      wl_global_destroy(e_devicemgr->wl_data->global);
789    e_devicemgr->wl_data->global = NULL;
790    eina_list_free(e_devicemgr->wl_data->mgr_data_list);
791
792    /* deinitialization of cynara if it has been initialized */
793 #ifdef HAVE_CYNARA
794    if (e_devicemgr->wl_data->p_cynara) cynara_finish(e_devicemgr->wl_data->p_cynara);
795    e_devicemgr->wl_data->cynara_initialized = EINA_FALSE;
796 #endif
797
798    E_FREE(e_devicemgr->wl_data);
799 }
800