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