05cfa60d34746b6f2152ef0d612a95604d526a69
[platform/core/uifw/libtdm.git] / src / tdm_event.c
1 /**************************************************************************
2
3 libtdm
4
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: Eunchul Kim <chulspro.kim@samsung.com>,
8          JinYoung Jeon <jy0.jeon@samsung.com>,
9          Taeheon Kim <th908.kim@samsung.com>,
10          YoungJun Cho <yj44.cho@samsung.com>,
11          SooChan Lim <sc1.lim@samsung.com>,
12          Boram Park <sc1.lim@samsung.com>
13
14 Permission is hereby granted, free of charge, to any person obtaining a
15 copy of this software and associated documentation files (the
16 "Software"), to deal in the Software without restriction, including
17 without limitation the rights to use, copy, modify, merge, publish,
18 distribute, sub license, and/or sell copies of the Software, and to
19 permit persons to whom the Software is furnished to do so, subject to
20 the following conditions:
21
22 The above copyright notice and this permission notice (including the
23 next paragraph) shall be included in all copies or substantial portions
24 of the Software.
25
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
29 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
30 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33
34 **************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "tdm.h"
41 #include "tdm_private.h"
42 #include "tdm_list.h"
43
44 #include <wayland-server-core.h>
45
46 struct _tdm_private_event {
47         struct wl_display *wl_display;
48         struct wl_event_loop *event_loop;
49
50         int backend_fd;
51         tdm_event_source *backend_source;
52
53         struct wl_display *wl_display2;
54         struct wl_event_loop *event_loop2;
55 };
56
57 typedef struct _tdm_event_source_base
58 {
59         struct wl_event_source *wl_source;
60 } tdm_event_source_base;
61
62 typedef struct _tdm_event_source_fd
63 {
64         tdm_event_source_base base;
65         tdm_private_display *private_display;
66         tdm_event_fd_handler func;
67         void *user_data;
68 } tdm_event_source_fd;
69
70 typedef struct _tdm_event_source_timer
71 {
72         tdm_event_source_base base;
73         tdm_private_display *private_display;
74         tdm_event_timer_handler func;
75         void *user_data;
76 } tdm_event_source_timer;
77
78 static tdm_error
79 _tdm_event_main_fd_handler(int fd, tdm_event_mask mask, void *user_data)
80 {
81         tdm_private_display *private_display = (tdm_private_display*)user_data;
82         tdm_private_event *private_event;
83         tdm_func_display *func_display;
84
85         TDM_RETURN_VAL_IF_FAIL(private_display != NULL, TDM_ERROR_OPERATION_FAILED);
86         TDM_RETURN_VAL_IF_FAIL(private_display->private_event != NULL, TDM_ERROR_OPERATION_FAILED);
87
88         private_event = private_display->private_event;
89
90         if (tdm_debug_thread)
91                 TDM_INFO("backend fd(%d) event happens", private_event->backend_fd);
92
93         func_display = &private_display->func_display;
94         if (!func_display->display_handle_events)
95                 return TDM_ERROR_NONE;
96
97         return func_display->display_handle_events(private_display->bdata);
98 }
99
100 INTERN tdm_error
101 tdm_event_init(tdm_private_display *private_display)
102 {
103         tdm_private_event *private_event;
104
105         if (private_display->private_event)
106                 return TDM_ERROR_NONE;
107
108         private_event = calloc(1, sizeof *private_event);
109         if (!private_event) {
110                 TDM_ERR("alloc failed");
111                 return TDM_ERROR_OUT_OF_MEMORY;
112         }
113
114         private_event->backend_fd = -1;
115
116         private_event->wl_display = wl_display_create();
117         if (!private_event->wl_display) {
118                 TDM_ERR("creating a wayland display failed");
119                 free(private_event);
120                 return TDM_ERROR_OUT_OF_MEMORY;
121         }
122
123         private_event->event_loop = wl_display_get_event_loop(private_event->wl_display);
124         if (!private_event->event_loop) {
125                 TDM_ERR("no event loop");
126                 wl_display_destroy(private_event->wl_display);
127                 free(private_event);
128                 return TDM_ERROR_OUT_OF_MEMORY;
129         }
130
131         TDM_INFO("event loop fd(%d)", wl_event_loop_get_fd(private_event->event_loop));
132
133         private_event->wl_display2 = wl_display_create();
134         if (!private_event->wl_display2) {
135                 TDM_ERR("creating a wayland display2 failed");
136                 return TDM_ERROR_OUT_OF_MEMORY;
137         }
138
139         private_event->event_loop2 = wl_display_get_event_loop(private_event->wl_display2);
140         if (!private_event->event_loop2) {
141                 TDM_ERR("no event loop2");
142                 wl_display_destroy(private_event->wl_display2);
143                 private_event->wl_display2 = NULL;
144                 return TDM_ERROR_OUT_OF_MEMORY;
145         }
146
147         private_display->private_event = private_event;
148
149         return TDM_ERROR_NONE;
150 }
151
152 INTERN void
153 tdm_event_deinit(tdm_private_display *private_display)
154 {
155         if (!private_display->private_event)
156                 return;
157
158         if (private_display->private_event->backend_source)
159                 tdm_event_source_remove(private_display->private_event->backend_source);
160
161         if (private_display->private_event->wl_display)
162                 wl_display_destroy(private_display->private_event->wl_display);
163
164         free(private_display->private_event);
165         private_display->private_event = NULL;
166 }
167
168 INTERN void
169 tdm_event_create_backend_source(tdm_private_display *private_display)
170 {
171         tdm_private_event *private_event = private_display->private_event;
172         tdm_func_display *func_display;
173         tdm_error ret;
174         int fd = -1;
175
176         TDM_RETURN_IF_FAIL(private_event != NULL);
177
178         func_display = &private_display->func_display;
179         if (!func_display->display_get_fd) {
180                 TDM_INFO("TDM backend module won't offer a display fd");
181                 return;
182         }
183
184         ret = func_display->display_get_fd(private_display->bdata, &fd);
185         if (fd < 0) {
186                 TDM_WRN("TDM backend module returns fd(%d)", fd);
187                 return;
188         }
189
190         if (!func_display->display_handle_events) {
191                 TDM_ERR("no display_handle_events function");
192                 return;
193         }
194
195         private_event->backend_source =
196                 tdm_event_add_fd_handler(private_display, fd, TDM_EVENT_READABLE,
197                                          _tdm_event_main_fd_handler, private_display,
198                                          &ret);
199         if (!private_event->backend_source) {
200                 TDM_ERR("no backend fd(%d) source", fd);
201                 return;
202         }
203
204         private_event->backend_fd = fd;
205
206         TDM_INFO("backend fd(%d) source created", private_event->backend_fd);
207 }
208
209 INTERN int
210 tdm_event_get_fd(tdm_private_display *private_display)
211 {
212         tdm_private_event *private_event = private_display->private_event;
213
214         TDM_RETURN_VAL_IF_FAIL(private_event->event_loop != NULL, -1);
215
216         return wl_event_loop_get_fd(private_event->event_loop);
217 }
218
219 INTERN tdm_error
220 tdm_event_dispatch(tdm_private_display *private_display)
221 {
222         tdm_private_event *private_event = private_display->private_event;
223
224         TDM_RETURN_VAL_IF_FAIL(private_event->event_loop != NULL, TDM_ERROR_OPERATION_FAILED);
225
226         if (tdm_debug_thread)
227                 TDM_INFO("dispatch");
228
229         /* Don't set timeout to -1. It can make deadblock by two mutex locks.
230          * If need to set -1, use poll() and call tdm_event_dispatch() after
231          * escaping polling.
232          */
233         if (wl_event_loop_dispatch(private_event->event_loop, 0) < 0)
234                 TDM_ERR("dispatch failed");
235
236         return TDM_ERROR_NONE;
237 }
238
239 INTERN tdm_error
240 tdm_event_add_socket(tdm_private_display *private_display, const char *name)
241 {
242         tdm_private_event *private_event = private_display->private_event;
243
244         TDM_RETURN_VAL_IF_FAIL(private_event->wl_display != NULL, TDM_ERROR_OPERATION_FAILED);
245
246         if (wl_display_add_socket(private_event->wl_display, name) < 0) {
247                 TDM_ERR("add socket(\"%s\") failed", name);
248                 return TDM_ERROR_OPERATION_FAILED;
249         }
250
251         return TDM_ERROR_NONE;
252 }
253
254 static int
255 _tdm_event_loop_fd_func(int fd, uint32_t wl_mask, void *data)
256 {
257         tdm_event_source_fd *fd_source = (tdm_event_source_fd*)data;
258         tdm_event_mask mask = 0;
259
260         TDM_RETURN_VAL_IF_FAIL(fd_source, 1);
261         TDM_RETURN_VAL_IF_FAIL(fd_source->func, 1);
262
263         if (wl_mask & WL_EVENT_READABLE)
264                 mask |= TDM_EVENT_READABLE;
265         if (wl_mask & WL_EVENT_WRITABLE)
266                 mask |= TDM_EVENT_WRITABLE;
267         if (wl_mask & WL_EVENT_HANGUP)
268                 mask |= TDM_EVENT_HANGUP;
269         if (wl_mask & WL_EVENT_ERROR)
270                 mask |= TDM_EVENT_ERROR;
271
272         fd_source->func(fd, mask, fd_source->user_data);
273
274         return 1;
275 }
276
277 EXTERN tdm_event_source*
278 tdm_event_add_fd_handler(tdm_display *dpy, int fd, tdm_event_mask mask,
279                          tdm_event_fd_handler func, void *user_data,
280                          tdm_error *error)
281 {
282         tdm_private_display *private_display;
283         tdm_private_event *private_event;
284         tdm_event_source_fd *fd_source;
285         uint32_t wl_mask = 0;
286         tdm_error ret;
287
288         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
289         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd >= 0, TDM_ERROR_INVALID_PARAMETER, NULL);
290         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
291
292         private_display = (tdm_private_display*)dpy;
293         private_event = private_display->private_event;
294         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_event, TDM_ERROR_INVALID_PARAMETER, NULL);
295         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_event->event_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
296
297         fd_source = calloc(1, sizeof(tdm_event_source_fd));
298         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
299
300         if (mask & TDM_EVENT_READABLE)
301                 wl_mask |= WL_EVENT_READABLE;
302         if (mask & TDM_EVENT_WRITABLE)
303                 wl_mask |= WL_EVENT_WRITABLE;
304
305         fd_source->base.wl_source =
306                 wl_event_loop_add_fd(private_event->event_loop,
307                                      fd, wl_mask, _tdm_event_loop_fd_func, fd_source);
308         if (!fd_source->base.wl_source) {
309                 if (error)
310                         *error = TDM_ERROR_OUT_OF_MEMORY;
311                 free(fd_source);
312                 return NULL;
313         }
314
315         fd_source->private_display = private_display;
316         fd_source->func = func;
317         fd_source->user_data = user_data;
318
319         if (error)
320                 *error = TDM_ERROR_NONE;
321
322         return (tdm_event_source*)fd_source;
323 }
324
325 EXTERN tdm_error
326 tdm_event_source_fd_update(tdm_event_source *source, tdm_event_mask mask)
327 {
328         tdm_event_source_fd *fd_source = source;
329         uint32_t wl_mask = 0;
330
331         TDM_RETURN_VAL_IF_FAIL(fd_source, TDM_ERROR_INVALID_PARAMETER);
332
333         if (mask & TDM_EVENT_READABLE)
334                 wl_mask |= WL_EVENT_READABLE;
335         if (mask & TDM_EVENT_WRITABLE)
336                 wl_mask |= WL_EVENT_WRITABLE;
337
338         if (wl_event_source_fd_update(fd_source->base.wl_source, wl_mask) < 0) {
339                 TDM_ERR("source update failed: %m");
340                 return TDM_ERROR_OPERATION_FAILED;
341         }
342
343         return TDM_ERROR_NONE;
344 }
345
346 static int
347 _tdm_event_loop_timer_func(void *data)
348 {
349         tdm_event_source_timer *timer_source = (tdm_event_source_timer*)data;
350
351         TDM_RETURN_VAL_IF_FAIL(timer_source, 1);
352         TDM_RETURN_VAL_IF_FAIL(timer_source->func, 1);
353
354         timer_source->func(timer_source->user_data);
355
356         return 1;
357 }
358
359 EXTERN tdm_event_source*
360 tdm_event_add_timer_handler(tdm_display *dpy, tdm_event_timer_handler func,
361                             void *user_data, tdm_error *error)
362 {
363         tdm_private_display *private_display;
364         tdm_private_event *private_event;
365         tdm_event_source_timer *timer_source;
366         tdm_error ret;
367
368         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
369         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
370
371         private_display = (tdm_private_display*)dpy;
372         private_event = private_display->private_event;
373         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_event, TDM_ERROR_INVALID_PARAMETER, NULL);
374         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_event->event_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
375
376         timer_source = calloc(1, sizeof(tdm_event_source_timer));
377         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(timer_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
378
379         timer_source->base.wl_source =
380                 wl_event_loop_add_timer(private_event->event_loop,
381                                         _tdm_event_loop_timer_func, timer_source);
382         if (!timer_source->base.wl_source) {
383                 if (error)
384                         *error = TDM_ERROR_OUT_OF_MEMORY;
385                 free(timer_source);
386                 return NULL;
387         }
388
389         timer_source->private_display = private_display;
390         timer_source->func = func;
391         timer_source->user_data = user_data;
392
393         if (error)
394                 *error = TDM_ERROR_NONE;
395
396         return (tdm_event_source*)timer_source;
397 }
398
399 EXTERN tdm_error
400 tdm_event_source_timer_update(tdm_event_source *source, int ms_delay)
401 {
402         tdm_event_source_timer *timer_source = source;
403
404         TDM_RETURN_VAL_IF_FAIL(timer_source, TDM_ERROR_INVALID_PARAMETER);
405
406         if (wl_event_source_timer_update(timer_source->base.wl_source, ms_delay) < 0) {
407                 TDM_ERR("source update failed: %m");
408                 return TDM_ERROR_OPERATION_FAILED;
409         }
410
411         return TDM_ERROR_NONE;
412 }
413
414 EXTERN void
415 tdm_event_source_remove(tdm_event_source *source)
416 {
417         tdm_event_source_base *base = (tdm_event_source_base*)source;
418
419         if (!base)
420                 return;
421
422         wl_event_source_remove(base->wl_source);
423
424         free(source);
425 }