use wl_event_loop to support the event handling system
[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 typedef struct _tdm_event_source_base
45 {
46         struct wl_event_source *wl_source;
47 } tdm_event_source_base;
48
49 typedef struct _tdm_event_source_fd
50 {
51         tdm_event_source_base base;
52         tdm_private_display *private_display;
53         tdm_event_fd_handler func;
54         void *user_data;
55 } tdm_event_source_fd;
56
57 typedef struct _tdm_event_source_timer
58 {
59         tdm_event_source_base base;
60         tdm_private_display *private_display;
61         tdm_event_timer_handler func;
62         void *user_data;
63 } tdm_event_source_timer;
64
65 static tdm_error
66 _tdm_event_main_fd_handler(int fd, tdm_event_mask mask, void *user_data)
67 {
68         tdm_private_display *private_display = (tdm_private_display*)user_data;
69         tdm_func_display *func_display;
70
71         TDM_RETURN_VAL_IF_FAIL(private_display != NULL, TDM_ERROR_OPERATION_FAILED);
72
73         func_display = &private_display->func_display;
74         if (!func_display->display_handle_events)
75                 return TDM_ERROR_NONE;
76
77         return func_display->display_handle_events(private_display->bdata);
78 }
79
80 INTERN tdm_error
81 tdm_event_init(tdm_private_display *private_display)
82 {
83         if (private_display->event_loop)
84                 return TDM_ERROR_NONE;
85
86         private_display->event_loop = wl_event_loop_create();
87         if (!private_display->event_loop) {
88                 TDM_ERR("creating a event loop failed");
89                 return TDM_ERROR_OUT_OF_MEMORY;
90         }
91
92         TDM_INFO("event_loop fd(%d)",
93                  wl_event_loop_get_fd(private_display->event_loop));
94
95         return TDM_ERROR_NONE;
96 }
97
98 INTERN void
99 tdm_event_deinit(tdm_private_display *private_display)
100 {
101         if (private_display->main_source) {
102                 tdm_event_source_remove(private_display->main_source);
103                 private_display->main_source = NULL;
104         }
105
106         if (private_display->event_loop) {
107                 wl_event_loop_destroy(private_display->event_loop);
108                 private_display->event_loop = NULL;
109         }
110 }
111
112 INTERN void
113 tdm_event_create_main_source(tdm_private_display *private_display)
114 {
115         tdm_func_display *func_display;
116         tdm_error ret;
117         int fd = -1;
118
119         func_display = &private_display->func_display;
120         if (!func_display->display_get_fd) {
121                 TDM_INFO("TDM backend module won't offer a display fd");
122                 return;
123         }
124
125         ret = func_display->display_get_fd(private_display->bdata, &fd);
126         if (fd < 0) {
127                 TDM_WRN("TDM backend module returns fd(%d)", fd);
128                 return;
129         }
130
131         if (!func_display->display_handle_events) {
132                 TDM_ERR("no display_handle_events function");
133                 return;
134         }
135
136         private_display->main_source =
137                 tdm_event_add_fd_handler(private_display, fd, TDM_EVENT_READABLE,
138                                          _tdm_event_main_fd_handler, private_display,
139                                          &ret);
140         if (!private_display->main_source) {
141                 TDM_ERR("no main event source");
142                 return;
143         }
144
145         TDM_INFO("main event source created");
146 }
147
148 INTERN int
149 tdm_event_get_fd(tdm_private_display *private_display)
150 {
151         if (!private_display->event_loop)
152                 return -1;
153
154         return wl_event_loop_get_fd(private_display->event_loop);
155 }
156
157 INTERN tdm_error
158 tdm_event_dispatch(tdm_private_display *private_display)
159 {
160         if (!private_display->event_loop)
161                 return TDM_ERROR_NONE;
162
163         if (wl_event_loop_dispatch(private_display->event_loop, 0) < 0) {
164                 TDM_ERR("dispatch failed");
165                 return TDM_ERROR_OPERATION_FAILED;
166         }
167
168         return TDM_ERROR_NONE;
169 }
170
171 static int
172 _tdm_event_loop_fd_func(int fd, uint32_t wl_mask, void *data)
173 {
174         tdm_event_source_fd *fd_source = (tdm_event_source_fd*)data;
175         tdm_event_mask mask = 0;
176
177         TDM_RETURN_VAL_IF_FAIL(fd_source, 1);
178         TDM_RETURN_VAL_IF_FAIL(fd_source->func, 1);
179
180         if (wl_mask & WL_EVENT_READABLE)
181                 mask |= TDM_EVENT_READABLE;
182         if (wl_mask & WL_EVENT_WRITABLE)
183                 mask |= TDM_EVENT_WRITABLE;
184         if (wl_mask & WL_EVENT_HANGUP)
185                 mask |= TDM_EVENT_HANGUP;
186         if (wl_mask & WL_EVENT_ERROR)
187                 mask |= TDM_EVENT_ERROR;
188
189         fd_source->func(fd, mask, fd_source->user_data);
190
191         return 1;
192 }
193
194 EXTERN tdm_event_source*
195 tdm_event_add_fd_handler(tdm_display *dpy, int fd, tdm_event_mask mask,
196                          tdm_event_fd_handler func, void *user_data,
197                          tdm_error *error)
198 {
199         tdm_private_display *private_display;
200         tdm_event_source_fd *fd_source;
201         uint32_t wl_mask = 0;
202         tdm_error ret;
203
204         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
205         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd >= 0, TDM_ERROR_INVALID_PARAMETER, NULL);
206         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
207
208         private_display = (tdm_private_display*)dpy;
209         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_display->event_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
210
211         fd_source = calloc(1, sizeof(tdm_event_source_fd));
212         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
213
214         if (mask & TDM_EVENT_READABLE)
215                 wl_mask |= WL_EVENT_READABLE;
216         if (mask & TDM_EVENT_WRITABLE)
217                 wl_mask |= WL_EVENT_WRITABLE;
218
219         fd_source->base.wl_source =
220                 wl_event_loop_add_fd(private_display->event_loop,
221                                      fd, wl_mask, _tdm_event_loop_fd_func, fd_source);
222         if (!fd_source->base.wl_source) {
223                 if (error)
224                         *error = TDM_ERROR_OUT_OF_MEMORY;
225                 free(fd_source);
226                 return NULL;
227         }
228
229         fd_source->private_display = private_display;
230         fd_source->func = func;
231         fd_source->user_data = user_data;
232
233         if (error)
234                 *error = TDM_ERROR_NONE;
235
236         return (tdm_event_source*)fd_source;
237 }
238
239 EXTERN tdm_error
240 tdm_event_source_fd_update(tdm_event_source *source, tdm_event_mask mask)
241 {
242         tdm_event_source_fd *fd_source = source;
243         uint32_t wl_mask = 0;
244
245         TDM_RETURN_VAL_IF_FAIL(fd_source, TDM_ERROR_INVALID_PARAMETER);
246
247         if (mask & TDM_EVENT_READABLE)
248                 wl_mask |= WL_EVENT_READABLE;
249         if (mask & TDM_EVENT_WRITABLE)
250                 wl_mask |= WL_EVENT_WRITABLE;
251
252         if (wl_event_source_fd_update(fd_source->base.wl_source, wl_mask) < 0) {
253                 TDM_ERR("source update failed: %m");
254                 return TDM_ERROR_OPERATION_FAILED;
255         }
256
257         return TDM_ERROR_NONE;
258 }
259
260 static int
261 _tdm_event_loop_timer_func(void *data)
262 {
263         tdm_event_source_timer *timer_source = (tdm_event_source_timer*)data;
264
265         TDM_RETURN_VAL_IF_FAIL(timer_source, 1);
266         TDM_RETURN_VAL_IF_FAIL(timer_source->func, 1);
267
268         timer_source->func(timer_source->user_data);
269
270         return 1;
271 }
272
273 EXTERN tdm_event_source*
274 tdm_event_add_timer_handler(tdm_display *dpy, tdm_event_timer_handler func,
275                             void *user_data, tdm_error *error)
276 {
277         tdm_private_display *private_display;
278         tdm_event_source_timer *timer_source;
279         tdm_error ret;
280
281         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
282         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
283
284         private_display = (tdm_private_display*)dpy;
285         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_display->event_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
286
287         timer_source = calloc(1, sizeof(tdm_event_source_timer));
288         TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(timer_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
289
290         timer_source->base.wl_source =
291                 wl_event_loop_add_timer(private_display->event_loop,
292                                         _tdm_event_loop_timer_func, timer_source);
293         if (!timer_source->base.wl_source) {
294                 if (error)
295                         *error = TDM_ERROR_OUT_OF_MEMORY;
296                 free(timer_source);
297                 return NULL;
298         }
299
300         timer_source->private_display = private_display;
301         timer_source->func = func;
302         timer_source->user_data = user_data;
303
304         if (error)
305                 *error = TDM_ERROR_NONE;
306
307         return (tdm_event_source*)timer_source;
308 }
309
310 EXTERN tdm_error
311 tdm_event_source_timer_update(tdm_event_source *source, int ms_delay)
312 {
313         tdm_event_source_timer *timer_source = source;
314
315         TDM_RETURN_VAL_IF_FAIL(timer_source, TDM_ERROR_INVALID_PARAMETER);
316
317         if (wl_event_source_timer_update(timer_source->base.wl_source, ms_delay) < 0) {
318                 TDM_ERR("source update failed: %m");
319                 return TDM_ERROR_OPERATION_FAILED;
320         }
321
322         return TDM_ERROR_NONE;
323 }
324
325 EXTERN void
326 tdm_event_source_remove(tdm_event_source *source)
327 {
328         tdm_event_source_base *base = (tdm_event_source_base*)source;
329
330         if (!base)
331                 return;
332
333         wl_event_source_remove(base->wl_source);
334
335         free(source);
336 }