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