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