Imported Upstream version 1.7.4
[platform/upstream/ecore.git] / src / lib / ecore_wayland / ecore_wl.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #ifdef STDC_HEADERS
6 # include <stdlib.h>
7 # include <stddef.h>
8 #else
9 # ifdef HAVE_STDLIB_H
10 #  include <stdlib.h>
11 # endif
12 #endif
13 #ifdef HAVE_ALLOCA_H
14 # include <alloca.h>
15 #elif !defined alloca
16 # ifdef __GNUC__
17 #  define alloca __builtin_alloca
18 # elif defined _AIX
19 #  define alloca __alloca
20 # elif defined _MSC_VER
21 #  include <malloc.h>
22 #  define alloca _alloca
23 # elif !defined HAVE_ALLOCA
24 #  ifdef  __cplusplus
25 extern "C"
26 #  endif
27 void *alloca (size_t);
28 # endif
29 #endif
30
31 #include <fcntl.h>
32 #include "ecore_wl_private.h"
33
34 /* local function prototypes */
35 static Eina_Bool _ecore_wl_shutdown(Eina_Bool close);
36 static Eina_Bool _ecore_wl_cb_idle_enterer(void *data);
37 static Eina_Bool _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl);
38 static void _ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned int id, const char *interface, unsigned int version __UNUSED__);
39 static Eina_Bool _ecore_wl_xkb_init(Ecore_Wl_Display *ewd);
40 static Eina_Bool _ecore_wl_xkb_shutdown(Ecore_Wl_Display *ewd);
41
42 /* local variables */
43 static int _ecore_wl_init_count = 0;
44 static const struct wl_registry_listener _ecore_wl_registry_listener = 
45 {
46    _ecore_wl_cb_handle_global,
47    NULL // handle_global_remove
48 };
49
50 /* external variables */
51 int _ecore_wl_log_dom = -1;
52 Ecore_Wl_Display *_ecore_wl_disp = NULL;
53
54 EAPI int ECORE_WL_EVENT_MOUSE_IN = 0;
55 EAPI int ECORE_WL_EVENT_MOUSE_OUT = 0;
56 EAPI int ECORE_WL_EVENT_FOCUS_IN = 0;
57 EAPI int ECORE_WL_EVENT_FOCUS_OUT = 0;
58 EAPI int ECORE_WL_EVENT_WINDOW_CONFIGURE = 0;
59 EAPI int ECORE_WL_EVENT_DND_ENTER = 0;
60 EAPI int ECORE_WL_EVENT_DND_POSITION = 0;
61 EAPI int ECORE_WL_EVENT_DND_LEAVE = 0;
62 EAPI int ECORE_WL_EVENT_DND_DROP = 0;
63 EAPI int ECORE_WL_EVENT_DATA_SOURCE_TARGET = 0;
64 EAPI int ECORE_WL_EVENT_DATA_SOURCE_SEND = 0;
65 EAPI int ECORE_WL_EVENT_SELECTION_DATA_READY = 0;
66 EAPI int ECORE_WL_EVENT_DATA_SOURCE_CANCELLED = 0;
67 EAPI int ECORE_WL_EVENT_INTERFACES_BOUND = 0;
68
69 /**
70  * @defgroup Ecore_Wl_Init_Group Wayland Library Init and Shutdown Functions
71  * 
72  * Functions that start and shutdown the Ecore Wayland Library.
73  */
74
75 /**
76  * Initialize the Wayland display connection to the given display.
77  * 
78  * @param   name Display target name. if @c NULL, the default display is 
79  *          assumed.
80  * @return  The number of times the library has been initialized without being 
81  *          shut down. 0 is returned if an error occurs.
82  * 
83  * @ingroup Ecore_Wl_Init_Group
84  */
85 EAPI int 
86 ecore_wl_init(const char *name)
87 {
88    LOGFN(__FILE__, __LINE__, __FUNCTION__);
89
90    if (++_ecore_wl_init_count != 1) return _ecore_wl_init_count;
91
92    if (!eina_init()) return --_ecore_wl_init_count;
93
94    _ecore_wl_log_dom = 
95      eina_log_domain_register("ecore_wl", ECORE_WL_DEFAULT_LOG_COLOR);
96    if (_ecore_wl_log_dom < 0)
97      {
98         EINA_LOG_ERR("Cannot create a log domain for Ecore Wayland");
99         eina_shutdown();
100         return --_ecore_wl_init_count;
101      }
102
103    if (!ecore_init())
104      {
105         ERR("Could not initialize ecore");
106         eina_log_domain_unregister(_ecore_wl_log_dom);
107         _ecore_wl_log_dom = -1;
108         eina_shutdown();
109         return --_ecore_wl_init_count;
110      }
111
112    if (!ecore_event_init())
113      {
114         ERR("Could not initialize ecore_event");
115         eina_log_domain_unregister(_ecore_wl_log_dom);
116         _ecore_wl_log_dom = -1;
117         ecore_shutdown();
118         eina_shutdown();
119         return --_ecore_wl_init_count;
120      }
121
122    if (!ECORE_WL_EVENT_MOUSE_IN)
123      {
124         ECORE_WL_EVENT_MOUSE_IN = ecore_event_type_new();
125         ECORE_WL_EVENT_MOUSE_OUT = ecore_event_type_new();
126         ECORE_WL_EVENT_FOCUS_IN = ecore_event_type_new();
127         ECORE_WL_EVENT_FOCUS_OUT = ecore_event_type_new();
128         ECORE_WL_EVENT_WINDOW_CONFIGURE = ecore_event_type_new();
129         ECORE_WL_EVENT_DND_ENTER = ecore_event_type_new();
130         ECORE_WL_EVENT_DND_POSITION = ecore_event_type_new();
131         ECORE_WL_EVENT_DND_LEAVE = ecore_event_type_new();
132         ECORE_WL_EVENT_DND_DROP = ecore_event_type_new();
133         ECORE_WL_EVENT_DATA_SOURCE_TARGET = ecore_event_type_new();
134         ECORE_WL_EVENT_DATA_SOURCE_SEND = ecore_event_type_new();
135         ECORE_WL_EVENT_SELECTION_DATA_READY = ecore_event_type_new();
136         ECORE_WL_EVENT_DATA_SOURCE_CANCELLED = ecore_event_type_new();
137         ECORE_WL_EVENT_INTERFACES_BOUND = ecore_event_type_new();
138      }
139
140    if (!(_ecore_wl_disp = malloc(sizeof(Ecore_Wl_Display))))
141      {
142         ERR("Could not allocate memory for Ecore_Wl_Display structure");
143         eina_log_domain_unregister(_ecore_wl_log_dom);
144         _ecore_wl_log_dom = -1;
145         ecore_event_shutdown();
146         ecore_shutdown();
147         eina_shutdown();
148         return --_ecore_wl_init_count;
149      }
150
151    memset(_ecore_wl_disp, 0, sizeof(Ecore_Wl_Display));
152
153    if (!(_ecore_wl_disp->wl.display = wl_display_connect(name)))
154      {
155         ERR("Could not connect to Wayland display");
156         eina_log_domain_unregister(_ecore_wl_log_dom);
157         _ecore_wl_log_dom = -1;
158         ecore_event_shutdown();
159         ecore_shutdown();
160         eina_shutdown();
161         return --_ecore_wl_init_count;
162      }
163
164    _ecore_wl_disp->fd = wl_display_get_fd(_ecore_wl_disp->wl.display);
165
166    _ecore_wl_disp->fd_hdl =
167      ecore_main_fd_handler_add(_ecore_wl_disp->fd,
168                                ECORE_FD_READ,
169                                _ecore_wl_cb_handle_data, _ecore_wl_disp,
170                                NULL, NULL);
171
172    _ecore_wl_disp->idle_enterer =
173      ecore_idle_enterer_add(_ecore_wl_cb_idle_enterer, _ecore_wl_disp);
174
175    wl_list_init(&_ecore_wl_disp->inputs);
176    wl_list_init(&_ecore_wl_disp->outputs);
177
178    _ecore_wl_disp->wl.registry = 
179      wl_display_get_registry(_ecore_wl_disp->wl.display);
180    wl_registry_add_listener(_ecore_wl_disp->wl.registry, 
181                             &_ecore_wl_registry_listener, _ecore_wl_disp);
182
183    wl_display_dispatch(_ecore_wl_disp->wl.display);
184
185    if (!_ecore_wl_xkb_init(_ecore_wl_disp))
186      {
187         ERR("Could not initialize XKB");
188         free(_ecore_wl_disp);
189         eina_log_domain_unregister(_ecore_wl_log_dom);
190         _ecore_wl_log_dom = -1;
191         ecore_event_shutdown();
192         ecore_shutdown();
193         eina_shutdown();
194         return --_ecore_wl_init_count;
195      }
196
197    _ecore_wl_window_init();
198
199    return _ecore_wl_init_count;
200 }
201
202 /**
203  * Shuts down the Ecore Wayland Library
204  * 
205  * In shutting down the library, the Wayland display connection is terminated 
206  * and any event handlers for it are removed.
207  * 
208  * @return  The number of times the library has been initialized without 
209  *          being shut down.
210  * 
211  * @ingroup Ecore_Wl_Init_Group
212  */
213 EAPI int 
214 ecore_wl_shutdown(void)
215 {
216    LOGFN(__FILE__, __LINE__, __FUNCTION__);
217
218    return _ecore_wl_shutdown(EINA_TRUE);
219 }
220
221 /**
222  * @defgroup Ecore_Wl_Flush_Group Wayland Synchronization Functions
223  * 
224  * Functions that ensure that all commands which have been issued by the 
225  * Ecore Wayland library have been sent to the server.
226  */
227
228 /**
229  * Sends all Wayland commands to the Wayland Display.
230  * 
231  * @ingroup Ecore_Wl_Flush_Group
232  * @since 1.2
233  */
234 EAPI void 
235 ecore_wl_flush(void)
236 {
237 //   LOGFN(__FILE__, __LINE__, __FUNCTION__);
238
239    wl_display_flush(_ecore_wl_disp->wl.display);
240 }
241
242 /**
243  * Flushes the command buffer and waits until all requests have been 
244  * processed by the server.
245  * 
246  * @ingroup Ecore_Wl_Flush_Group
247  * @since 1.2
248  */
249 EAPI void 
250 ecore_wl_sync(void)
251 {
252 //   LOGFN(__FILE__, __LINE__, __FUNCTION__);
253
254    wl_display_sync(_ecore_wl_disp->wl.display);
255 }
256
257 /**
258  * @defgroup Ecore_Wl_Display_Group Wayland Display Functions
259  * 
260  * Functions that set and retrieve various information about the Wayland Display.
261  */
262
263 /**
264  * Retrieves the Wayland Shm Interface used for the current Wayland connection.
265  * 
266  * @return The current wayland shm interface
267  * 
268  * @ingroup Ecore_Wl_Display_Group
269  * @since 1.2
270  */
271 EAPI struct wl_shm *
272 ecore_wl_shm_get(void)
273 {
274    return _ecore_wl_disp->wl.shm;
275 }
276
277 /**
278  * Retrieves the Wayland Display Interface used for the current Wayland connection.
279  * 
280  * @return The current wayland display interface
281  * 
282  * @ingroup Ecore_Wl_Display_Group
283  * @since 1.2
284  */
285 EAPI struct wl_display *
286 ecore_wl_display_get(void)
287 {
288    return _ecore_wl_disp->wl.display;
289 }
290
291 /**
292  * Retrieves the size of the current screen.
293  * 
294  * @param w where to return the width. May be NULL. Returns 0 on error.
295  * @param h where to return the height. May be NULL. Returns 0 on error.
296  * 
297  * @ingroup Ecore_Wl_Display_Group
298  * @since 1.2
299  */
300 EAPI void 
301 ecore_wl_screen_size_get(int *w, int *h)
302 {
303    LOGFN(__FILE__, __LINE__, __FUNCTION__);
304
305    if (w) *w = 0;
306    if (h) *h = 0;
307
308    if (!_ecore_wl_disp->output) return;
309
310    if (w) *w = _ecore_wl_disp->output->allocation.w;
311    if (h) *h = _ecore_wl_disp->output->allocation.h;
312 }
313
314 /* @since 1.2 */
315 EAPI void 
316 ecore_wl_pointer_xy_get(int *x, int *y)
317 {
318    LOGFN(__FILE__, __LINE__, __FUNCTION__);
319
320    _ecore_wl_input_pointer_xy_get(x, y);
321 }
322
323 /**
324  * Return the screen DPI
325  *
326  * This is a simplistic call to get DPI. It does not account for differing
327  * DPI in the x and y axes nor does it account for multihead or xinerama and
328  * xrandr where different parts of the screen may have different DPI etc.
329  *
330  * @return the general screen DPI (dots/pixels per inch).
331  * 
332  * @since 1.2
333  */
334 EAPI int 
335 ecore_wl_dpi_get(void)
336 {
337    int w, mw;
338
339    LOGFN(__FILE__, __LINE__, __FUNCTION__);
340
341    if (!_ecore_wl_disp->output) return 75;
342
343    mw = _ecore_wl_disp->output->mw;
344    if (mw <= 0) return 75;
345
346    w = _ecore_wl_disp->output->allocation.w;
347    /* FIXME: NB: Hrrrmmm, need to verify this. xorg code is using a different 
348     * formula to calc this */
349    return (((w * 254) / mw) + 5) / 10;
350 }
351
352 EAPI void 
353 ecore_wl_display_iterate(void)
354 {
355    wl_display_dispatch(_ecore_wl_disp->wl.display);
356 }
357
358 /**
359  * Retrieves the requested cursor from the cursor theme
360  * 
361  * @param cursor_name The desired cursor name to be looked up in the theme
362  * @return the cursor or NULL if the cursor cannot be found
363  *
364  * @since 1.2
365  */
366 EAPI struct wl_cursor *
367 ecore_wl_cursor_get(const char *cursor_name)
368 {
369    if ((!_ecore_wl_disp) || (!_ecore_wl_disp->cursor_theme)) 
370      return NULL;
371
372    return wl_cursor_theme_get_cursor(_ecore_wl_disp->cursor_theme,
373                                      cursor_name);
374 }
375
376 /* local functions */
377 static Eina_Bool 
378 _ecore_wl_shutdown(Eina_Bool close)
379 {
380    LOGFN(__FILE__, __LINE__, __FUNCTION__);
381
382    if (--_ecore_wl_init_count != 0) return _ecore_wl_init_count;
383    if (!_ecore_wl_disp) return _ecore_wl_init_count;
384
385    _ecore_wl_window_shutdown();
386
387    if (_ecore_wl_disp->fd_hdl) 
388      ecore_main_fd_handler_del(_ecore_wl_disp->fd_hdl);
389    if (_ecore_wl_disp->idle_enterer)
390       ecore_idle_enterer_del(_ecore_wl_disp->idle_enterer);
391
392    if (close) 
393      {
394         Ecore_Wl_Output *out, *tout;
395         Ecore_Wl_Input *in, *tin;
396
397         wl_list_for_each_safe(out, tout, &_ecore_wl_disp->outputs, link)
398           _ecore_wl_output_del(out);
399
400         wl_list_for_each_safe(in, tin, &_ecore_wl_disp->inputs, link)
401           _ecore_wl_input_del(in);
402
403         _ecore_wl_xkb_shutdown(_ecore_wl_disp);
404
405         if (_ecore_wl_disp->wl.shell) 
406           wl_shell_destroy(_ecore_wl_disp->wl.shell);
407         if (_ecore_wl_disp->wl.shm) wl_shm_destroy(_ecore_wl_disp->wl.shm);
408         if (_ecore_wl_disp->wl.data_device_manager)
409           wl_data_device_manager_destroy(_ecore_wl_disp->wl.data_device_manager);
410         if (_ecore_wl_disp->wl.compositor)
411           wl_compositor_destroy(_ecore_wl_disp->wl.compositor);
412         if (_ecore_wl_disp->wl.display)
413           {
414              wl_registry_destroy(_ecore_wl_disp->wl.registry);
415              wl_display_flush(_ecore_wl_disp->wl.display);
416              wl_display_disconnect(_ecore_wl_disp->wl.display);
417           }
418         free(_ecore_wl_disp);
419      }
420
421    ecore_event_shutdown();
422    ecore_shutdown();
423
424    eina_log_domain_unregister(_ecore_wl_log_dom);
425    _ecore_wl_log_dom = -1;
426    eina_shutdown();
427
428    return _ecore_wl_init_count;
429 }
430
431 static Eina_Bool
432 _ecore_wl_cb_idle_enterer(void *data)
433 {
434    Ecore_Wl_Display *ewd;
435    int ret;
436
437    if (!(ewd = data)) return ECORE_CALLBACK_RENEW;
438
439    ret = wl_display_flush(ewd->wl.display);
440    if ((ret < 0) && (errno == EAGAIN))
441      {
442         ecore_main_fd_handler_active_set(ewd->fd_hdl, 
443                                          (ECORE_FD_READ | ECORE_FD_WRITE));
444      }
445    else if (ret < 0)
446      {
447       /* FIXME: need do error processing? */
448      }
449
450    return ECORE_CALLBACK_RENEW;
451 }
452
453 static Eina_Bool
454 _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl)
455 {
456    Ecore_Wl_Display *ewd;
457    int ret;
458
459    /* LOGFN(__FILE__, __LINE__, __FUNCTION__); */
460
461    if (!(ewd = data)) return ECORE_CALLBACK_RENEW;
462
463    /* FIXME: This should also catch ECORE_FD_ERROR and exit */
464
465    /* wl_display_dispatch_pending(ewd->wl.display); */
466
467    if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_READ))
468      wl_display_dispatch(ewd->wl.display);
469    else if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_WRITE))
470      {
471         ret = wl_display_flush(ewd->wl.display);
472         if (ret == 0)
473           ecore_main_fd_handler_active_set(hdl, ECORE_FD_READ);
474         else if ((ret == -1) && (errno != EAGAIN))
475           {
476             /* FIXME: need do error processing? */
477           }
478      }
479
480    return ECORE_CALLBACK_RENEW;
481 }
482
483 static void 
484 _ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned int id, const char *interface, unsigned int version __UNUSED__)
485 {
486    Ecore_Wl_Display *ewd;
487
488    LOGFN(__FILE__, __LINE__, __FUNCTION__);
489
490    ewd = data;
491
492    if (!strcmp(interface, "wl_compositor"))
493      {
494         ewd->wl.compositor = 
495           wl_registry_bind(registry, id, &wl_compositor_interface, 1);
496      }
497    else if (!strcmp(interface, "wl_output"))
498      _ecore_wl_output_add(ewd, id);
499    else if (!strcmp(interface, "wl_seat"))
500      _ecore_wl_input_add(ewd, id);
501    else if (!strcmp(interface, "wl_shell"))
502      {
503         ewd->wl.shell = 
504           wl_registry_bind(registry, id, &wl_shell_interface, 1);
505      }
506    else if (!strcmp(interface, "wl_shm"))
507      {
508         ewd->wl.shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
509
510         /* FIXME: We should not hard-code a cursor size here, and we should 
511          * also import the theme name from a config or env variable */
512         ewd->cursor_theme = wl_cursor_theme_load(NULL, 32, ewd->wl.shm);
513      }
514    else if (!strcmp(interface, "wl_data_device_manager"))
515      {
516         ewd->wl.data_device_manager = 
517           wl_registry_bind(registry, id, &wl_data_device_manager_interface, 1);
518      }
519
520    if ((ewd->wl.compositor) && (ewd->wl.shm) && (ewd->wl.shell))
521      {
522         Ecore_Wl_Event_Interfaces_Bound *ev;
523
524         if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Interfaces_Bound))))
525           return;
526
527         ev->compositor = (ewd->wl.compositor != NULL);
528         ev->shm = (ewd->wl.shm != NULL);
529         ev->shell = (ewd->wl.shell != NULL);
530
531         ecore_event_add(ECORE_WL_EVENT_INTERFACES_BOUND, ev, NULL, NULL);
532      }
533 }
534
535 static Eina_Bool 
536 _ecore_wl_xkb_init(Ecore_Wl_Display *ewd)
537 {
538    LOGFN(__FILE__, __LINE__, __FUNCTION__);
539
540    if (!(ewd->xkb.context = xkb_context_new(0)))
541      return EINA_FALSE;
542
543    return EINA_TRUE;
544 }
545
546 static Eina_Bool 
547 _ecore_wl_xkb_shutdown(Ecore_Wl_Display *ewd)
548 {
549    LOGFN(__FILE__, __LINE__, __FUNCTION__);
550
551    xkb_context_unref(ewd->xkb.context);
552
553    return EINA_TRUE;
554 }
555
556 struct wl_data_source *
557 _ecore_wl_create_data_source(Ecore_Wl_Display *ewd)
558 {
559    return wl_data_device_manager_create_data_source(ewd->wl.data_device_manager);
560 }