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