1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #include <fcntl.h>
6 #include "ecore_wl_private.h"
7 
8 /*
9  * The subsurface protocol was moved into Wayland Core
10  * around v1.3.90 (i.e. v1.4.0).
11  * Test if subsurface protocol is part of wayland-client.h.
12  * If not, we include our own copy of the protocol header.
13  */
14 #include <wayland-client.h>
15 #ifndef WL_SUBSURFACE_ERROR_ENUM
16 # include <subsurface-client-protocol.h>
17 #endif
18 
19 #include "xdg-shell-client-protocol.h"
20 #define XDG_VERSION 5
21 
22 #include "session-recovery-client-protocol.h"
23 
24 /* local function prototypes */
25 static int _ecore_wl_shutdown(Eina_Bool close);
26 static Eina_Bool _ecore_wl_cb_idle_enterer(void *data);
27 static Eina_Bool _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl);
28 static void _ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned int id, const char *interface, unsigned int version EINA_UNUSED);
29 static void _ecore_wl_cb_handle_global_remove(void *data, struct wl_registry *registry EINA_UNUSED, unsigned int id);
30 static Eina_Bool _ecore_wl_xkb_init(Ecore_Wl_Display *ewd);
31 static Eina_Bool _ecore_wl_xkb_shutdown(Ecore_Wl_Display *ewd);
32 static void _ecore_wl_sync_wait(Ecore_Wl_Display *ewd);
33 static void _ecore_wl_sync_callback(void *data, struct wl_callback *callback, uint32_t serial);
34 static void _ecore_wl_animator_tick_cb_begin(void *data EINA_UNUSED);
35 static void _ecore_wl_animator_tick_cb_end(void *data EINA_UNUSED);
36 static void _ecore_wl_animator_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED);
37 static Eina_Bool _ecore_wl_animator_window_add(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED);
38 static void _ecore_wl_signal_exit(void);
39 static void _ecore_wl_signal_exit_free(void *data EINA_UNUSED, void *event);
40 static void _ecore_wl_init_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED);
41 
42 /* local variables */
43 static int _ecore_wl_init_count = 0;
44 static Eina_Bool _ecore_wl_animator_busy = EINA_FALSE;
45 static Eina_Bool _ecore_wl_fatal_error = EINA_FALSE;
46 Eina_Bool _ecore_wl_server_mode = EINA_FALSE;
47 
48 static const struct wl_registry_listener _ecore_wl_registry_listener =
49 {
50    _ecore_wl_cb_handle_global,
51    _ecore_wl_cb_handle_global_remove
52 };
53 
54 static const struct wl_callback_listener _ecore_wl_sync_listener =
55 {
56    _ecore_wl_sync_callback
57 };
58 
59 static const struct wl_callback_listener _ecore_wl_init_sync_listener =
60 {
61    _ecore_wl_init_callback
62 };
63 
64 static const struct wl_callback_listener _ecore_wl_anim_listener =
65 {
66    _ecore_wl_animator_callback
67 };
68 
69 static void
xdg_shell_ping(void * data EINA_UNUSED,struct xdg_shell * shell,uint32_t serial)70 xdg_shell_ping(void *data EINA_UNUSED, struct xdg_shell *shell, uint32_t serial)
71 {
72    xdg_shell_pong(shell, serial);
73 }
74 
75 static const struct xdg_shell_listener xdg_shell_listener =
76 {
77    xdg_shell_ping,
78 };
79 
80 /* external variables */
81 int _ecore_wl_log_dom = -1;
82 Ecore_Wl_Display *_ecore_wl_disp = NULL;
83 
84 EAPI int ECORE_WL_EVENT_MOUSE_IN = 0;
85 EAPI int ECORE_WL_EVENT_MOUSE_OUT = 0;
86 EAPI int ECORE_WL_EVENT_FOCUS_IN = 0;
87 EAPI int ECORE_WL_EVENT_FOCUS_OUT = 0;
88 EAPI int ECORE_WL_EVENT_WINDOW_CONFIGURE = 0;
89 EAPI int ECORE_WL_EVENT_DND_ENTER = 0;
90 EAPI int ECORE_WL_EVENT_DND_POSITION = 0;
91 EAPI int ECORE_WL_EVENT_DND_LEAVE = 0;
92 EAPI int ECORE_WL_EVENT_DND_DROP = 0;
93 EAPI int ECORE_WL_EVENT_DND_OFFER = 0;
94 EAPI int ECORE_WL_EVENT_DND_END = 0;
95 EAPI int ECORE_WL_EVENT_DATA_SOURCE_TARGET = 0;
96 EAPI int ECORE_WL_EVENT_DATA_SOURCE_SEND = 0;
97 EAPI int ECORE_WL_EVENT_SELECTION_DATA_READY = 0;
98 EAPI int ECORE_WL_EVENT_DATA_SOURCE_CANCELLED = 0;
99 EAPI int ECORE_WL_EVENT_INTERFACES_BOUND = 0;
100 
101 static void
_ecore_wl_init_callback(void * data,struct wl_callback * callback,uint32_t serial EINA_UNUSED)102 _ecore_wl_init_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED)
103 {
104    Ecore_Wl_Display *ewd = data;
105 
106    wl_callback_destroy(callback);
107    ewd->init_done = EINA_TRUE;
108 }
109 
110 static void
_ecore_wl_init_wait(void)111 _ecore_wl_init_wait(void)
112 {
113    int ret;
114    while (!_ecore_wl_disp->init_done)
115      {
116         ret = wl_display_dispatch(_ecore_wl_disp->wl.display);
117         if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
118           {
119              /* raise exit signal */
120              ERR("Wayland socket error: %s", strerror(errno));
121              abort();
122              break;
123           }
124      }
125 }
126 
127 EAPI int
ecore_wl_init(const char * name)128 ecore_wl_init(const char *name)
129 {
130    struct wl_callback *callback;
131    LOGFN;
132 
133    if (++_ecore_wl_init_count != 1) return _ecore_wl_init_count;
134 
135    if (!eina_init()) return --_ecore_wl_init_count;
136 
137    _ecore_wl_log_dom =
138      eina_log_domain_register("ecore_wl", ECORE_WL_DEFAULT_LOG_COLOR);
139    if (_ecore_wl_log_dom < 0)
140      {
141         EINA_LOG_ERR("Cannot create a log domain for Ecore Wayland");
142         goto exit_eina;
143      }
144 
145    if (!ecore_init())
146      {
147         ERR("Could not initialize ecore");
148         goto exit_ecore;
149      }
150 
151    if (!ecore_event_init())
152      {
153         ERR("Could not initialize ecore_event");
154         goto exit_ecore_event;
155      }
156 
157    ECORE_WL_EVENT_MOUSE_IN = ecore_event_type_new();
158    ECORE_WL_EVENT_MOUSE_OUT = ecore_event_type_new();
159    ECORE_WL_EVENT_FOCUS_IN = ecore_event_type_new();
160    ECORE_WL_EVENT_FOCUS_OUT = ecore_event_type_new();
161    ECORE_WL_EVENT_WINDOW_CONFIGURE = ecore_event_type_new();
162    ECORE_WL_EVENT_DND_ENTER = ecore_event_type_new();
163    ECORE_WL_EVENT_DND_POSITION = ecore_event_type_new();
164    ECORE_WL_EVENT_DND_LEAVE = ecore_event_type_new();
165    ECORE_WL_EVENT_DND_DROP = ecore_event_type_new();
166    ECORE_WL_EVENT_DND_OFFER = ecore_event_type_new();
167    ECORE_WL_EVENT_DND_END = ecore_event_type_new();
168    ECORE_WL_EVENT_DATA_SOURCE_TARGET = ecore_event_type_new();
169    ECORE_WL_EVENT_DATA_SOURCE_SEND = ecore_event_type_new();
170    ECORE_WL_EVENT_SELECTION_DATA_READY = ecore_event_type_new();
171    ECORE_WL_EVENT_DATA_SOURCE_CANCELLED = ecore_event_type_new();
172    ECORE_WL_EVENT_INTERFACES_BOUND = ecore_event_type_new();
173 
174    if (!(_ecore_wl_disp = calloc(1, sizeof(Ecore_Wl_Display))))
175      {
176         ERR("Could not allocate memory for Ecore_Wl_Display structure");
177         goto exit_ecore_disp;
178      }
179 
180    if (!(_ecore_wl_disp->wl.display = wl_display_connect(name)))
181      {
182         ERR("Could not connect to Wayland display");
183         goto exit_ecore_disp_connect;
184      }
185 
186    _ecore_wl_disp->fd = wl_display_get_fd(_ecore_wl_disp->wl.display);
187 
188    _ecore_wl_disp->fd_hdl =
189      ecore_main_fd_handler_add(_ecore_wl_disp->fd,
190                                ECORE_FD_READ | ECORE_FD_WRITE | ECORE_FD_ERROR,
191                                _ecore_wl_cb_handle_data, _ecore_wl_disp,
192                                NULL, NULL);
193 
194    _ecore_wl_disp->idle_enterer =
195      ecore_idle_enterer_add(_ecore_wl_cb_idle_enterer, _ecore_wl_disp);
196 
197    _ecore_wl_disp->wl.registry =
198      wl_display_get_registry(_ecore_wl_disp->wl.display);
199    wl_registry_add_listener(_ecore_wl_disp->wl.registry,
200                             &_ecore_wl_registry_listener, _ecore_wl_disp);
201 
202    if (!_ecore_wl_xkb_init(_ecore_wl_disp))
203      {
204         ERR("Could not initialize XKB");
205         goto exit_ecore_disp_connect;
206      }
207 
208    _ecore_wl_window_init();
209    _ecore_wl_events_init();
210 
211    _ecore_wl_disp->init_done = EINA_TRUE;
212    if (!_ecore_wl_server_mode)
213      {
214         _ecore_wl_disp->init_done = EINA_FALSE;
215         callback = wl_display_sync(_ecore_wl_disp->wl.display);
216         wl_callback_add_listener(callback, &_ecore_wl_init_sync_listener,
217                                  _ecore_wl_disp);
218      }
219 
220    return _ecore_wl_init_count;
221 
222 exit_ecore_disp_connect:
223    free(_ecore_wl_disp);
224 
225 exit_ecore_disp:
226    ecore_event_shutdown();
227 
228 exit_ecore_event:
229    ecore_shutdown();
230 
231 exit_ecore:
232    eina_log_domain_unregister(_ecore_wl_log_dom);
233    _ecore_wl_log_dom = -1;
234 
235 exit_eina:
236    eina_shutdown();
237    return --_ecore_wl_init_count;
238 }
239 
240 EAPI int
ecore_wl_shutdown(void)241 ecore_wl_shutdown(void)
242 {
243    LOGFN;
244 
245    return _ecore_wl_shutdown(EINA_TRUE);
246 }
247 
248 EAPI void
ecore_wl_flush(void)249 ecore_wl_flush(void)
250 {
251    if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display)) return;
252    wl_display_flush(_ecore_wl_disp->wl.display);
253 }
254 
255 EAPI void
ecore_wl_sync(void)256 ecore_wl_sync(void)
257 {
258    int ret;
259    if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display)) return;
260    _ecore_wl_sync_wait(_ecore_wl_disp);
261    while (_ecore_wl_disp->sync_ref_count > 0)
262      {
263         ret = wl_display_dispatch(_ecore_wl_disp->wl.display);
264         if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
265           {
266              /* raise exit signal */
267              ERR("Wayland socket error: %s", strerror(errno));
268              abort();
269              break;
270           }
271      }
272 }
273 
274 EAPI struct wl_shm *
ecore_wl_shm_get(void)275 ecore_wl_shm_get(void)
276 {
277    if (!_ecore_wl_disp) return NULL;
278 
279    _ecore_wl_init_wait();
280 
281    return _ecore_wl_disp->wl.shm;
282 }
283 
284 EAPI struct wl_display *
ecore_wl_display_get(void)285 ecore_wl_display_get(void)
286 {
287    if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display))
288      return NULL;
289    return _ecore_wl_disp->wl.display;
290 }
291 
292 EAPI Eina_Inlist *
ecore_wl_globals_get(void)293 ecore_wl_globals_get(void)
294 {
295    if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display))
296      return NULL;
297 
298    _ecore_wl_init_wait();
299 
300    return _ecore_wl_disp->globals;
301 }
302 
303 EAPI struct wl_registry *
ecore_wl_registry_get(void)304 ecore_wl_registry_get(void)
305 {
306    if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display))
307      return NULL;
308    return _ecore_wl_disp->wl.registry;
309 }
310 
311 struct wl_compositor *
_ecore_wl_compositor_get(void)312 _ecore_wl_compositor_get(void)
313 {
314    if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display))
315      return NULL;
316 
317    _ecore_wl_init_wait();
318 
319    return _ecore_wl_disp->wl.compositor;
320 }
321 
322 struct wl_subcompositor *
_ecore_wl_subcompositor_get(void)323 _ecore_wl_subcompositor_get(void)
324 {
325    if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display))
326      return NULL;
327 
328    _ecore_wl_init_wait();
329 
330    return _ecore_wl_disp->wl.subcompositor;
331 }
332 
333 EAPI void
ecore_wl_screen_size_get(int * w,int * h)334 ecore_wl_screen_size_get(int *w, int *h)
335 {
336    Ecore_Wl_Output *out;
337    Eina_Inlist *tmp;
338    int ow = 0, oh = 0;
339 
340    LOGFN;
341 
342    if (w) *w = 0;
343    if (h) *h = 0;
344 
345    if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display)) return;
346 
347    _ecore_wl_init_wait();
348 
349    // the first sync is in case registry replies are not back yet
350    if (!_ecore_wl_disp->output)
351      {
352         // second sync is in case bound object replies in registry are not back
353         ecore_wl_sync();
354         if (!_ecore_wl_disp->output) ecore_wl_sync();
355      }
356 
357    EINA_INLIST_FOREACH_SAFE(_ecore_wl_disp->outputs, tmp, out)
358      {
359         switch (out->transform)
360           {
361            case WL_OUTPUT_TRANSFORM_90:
362            case WL_OUTPUT_TRANSFORM_270:
363            case WL_OUTPUT_TRANSFORM_FLIPPED_90:
364            case WL_OUTPUT_TRANSFORM_FLIPPED_270:
365              /* Swap width and height */
366              ow += out->allocation.h;
367              oh += out->allocation.w;
368              break;
369            default:
370              ow += out->allocation.w;
371              oh += out->allocation.h;
372           }
373      }
374 
375    if (w) *w = ow;
376    if (h) *h = oh;
377 }
378 
379 /* @since 1.2 */
380 EAPI void
ecore_wl_pointer_xy_get(int * x,int * y)381 ecore_wl_pointer_xy_get(int *x, int *y)
382 {
383    LOGFN;
384 
385    _ecore_wl_input_pointer_xy_get(x, y);
386 }
387 
388 EAPI int
ecore_wl_dpi_get(void)389 ecore_wl_dpi_get(void)
390 {
391    int w, mw;
392 
393    LOGFN;
394 
395    if (!_ecore_wl_disp) return 0;
396 
397    _ecore_wl_init_wait();
398 
399    if (!_ecore_wl_disp->output) return 75;
400 
401    mw = _ecore_wl_disp->output->mw;
402    if (mw <= 0) return 75;
403 
404    w = _ecore_wl_disp->output->allocation.w;
405    /* FIXME: NB: Hrrrmmm, need to verify this. xorg code is using a different
406     * formula to calc this */
407    return (((w * 254) / mw) + 5) / 10;
408 }
409 
410 EAPI void
ecore_wl_display_iterate(void)411 ecore_wl_display_iterate(void)
412 {
413    int ret;
414    if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display)) return;
415    if (!_ecore_wl_server_mode)
416      {
417         ret = wl_display_dispatch(_ecore_wl_disp->wl.display);
418         if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
419           {
420              /* raise exit signal */
421              ERR("Wayland socket error: %s", strerror(errno));
422              abort();
423           }
424      }
425 }
426 
427 /* @since 1.8 */
428 EAPI Eina_Bool
ecore_wl_animator_source_set(Ecore_Animator_Source source)429 ecore_wl_animator_source_set(Ecore_Animator_Source source)
430 {
431    LOGFN;
432 
433    if (_ecore_wl_server_mode) return EINA_FALSE;
434 
435    /* FIXME: check existing source. If custom, disable anim_callbacks */
436 
437    /* based on the animator source we are using, setup or destroy callbacks */
438    switch (source)
439      {
440       case ECORE_ANIMATOR_SOURCE_CUSTOM:
441         ecore_animator_custom_source_tick_begin_callback_set
442           (_ecore_wl_animator_tick_cb_begin, NULL);
443         ecore_animator_custom_source_tick_end_callback_set
444           (_ecore_wl_animator_tick_cb_end, NULL);
445         break;
446       case ECORE_ANIMATOR_SOURCE_TIMER:
447         ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL);
448         ecore_animator_custom_source_tick_end_callback_set(NULL, NULL);
449         break;
450       default:
451         break;
452      }
453 
454    /* set the source of the animator */
455    ecore_animator_source_set(source);
456 
457    return EINA_TRUE;
458 }
459 
460 EAPI struct wl_cursor *
ecore_wl_cursor_get(const char * cursor_name)461 ecore_wl_cursor_get(const char *cursor_name)
462 {
463    if ((!_ecore_wl_disp) || (!_ecore_wl_disp->cursor_theme))
464      return NULL;
465 
466    return wl_cursor_theme_get_cursor(_ecore_wl_disp->cursor_theme,
467                                      cursor_name);
468 }
469 
470 EAPI void
ecore_wl_server_mode_set(Eina_Bool on)471 ecore_wl_server_mode_set(Eina_Bool on)
472 {
473    _ecore_wl_server_mode = on;
474 }
475 
476 /* local functions */
477 static int
_ecore_wl_shutdown(Eina_Bool close)478 _ecore_wl_shutdown(Eina_Bool close)
479 {
480    LOGFN;
481 
482    if (_ecore_wl_init_count < 1)
483      {
484         ERR("Ecore_Wayland Shutdown called without Ecore_Wayland Init");
485         return 0;
486      }
487 
488    if (--_ecore_wl_init_count != 0) return _ecore_wl_init_count;
489    if (!_ecore_wl_disp) return _ecore_wl_init_count;
490 
491    ecore_event_type_flush(ECORE_WL_EVENT_MOUSE_IN,
492                           ECORE_WL_EVENT_MOUSE_OUT,
493                           ECORE_WL_EVENT_FOCUS_IN,
494                           ECORE_WL_EVENT_FOCUS_OUT,
495                           ECORE_WL_EVENT_WINDOW_CONFIGURE,
496                           ECORE_WL_EVENT_DND_ENTER,
497                           ECORE_WL_EVENT_DND_POSITION,
498                           ECORE_WL_EVENT_DND_LEAVE,
499                           ECORE_WL_EVENT_DND_DROP,
500                           ECORE_WL_EVENT_DND_OFFER,
501                           ECORE_WL_EVENT_DND_END,
502                           ECORE_WL_EVENT_DATA_SOURCE_TARGET,
503                           ECORE_WL_EVENT_DATA_SOURCE_SEND,
504                           ECORE_WL_EVENT_SELECTION_DATA_READY,
505                           ECORE_WL_EVENT_DATA_SOURCE_CANCELLED,
506                           ECORE_WL_EVENT_INTERFACES_BOUND);
507 
508    _ecore_wl_events_shutdown();
509    _ecore_wl_window_shutdown();
510 
511    if (_ecore_wl_disp->fd_hdl)
512      ecore_main_fd_handler_del(_ecore_wl_disp->fd_hdl);
513    if (_ecore_wl_disp->idle_enterer)
514       ecore_idle_enterer_del(_ecore_wl_disp->idle_enterer);
515 
516    if ((close) && (!_ecore_wl_fatal_error))
517      {
518         Ecore_Wl_Output *out;
519         Ecore_Wl_Input *in;
520         Ecore_Wl_Global *global;
521         Eina_Inlist *tmp;
522 
523         EINA_INLIST_FOREACH_SAFE(_ecore_wl_disp->outputs, tmp, out)
524           _ecore_wl_output_del(out);
525 
526         EINA_INLIST_FOREACH_SAFE(_ecore_wl_disp->inputs, tmp, in)
527           _ecore_wl_input_del(in);
528 
529         EINA_INLIST_FOREACH_SAFE(_ecore_wl_disp->globals, tmp, global)
530           {
531              _ecore_wl_disp->globals =
532                eina_inlist_remove(_ecore_wl_disp->globals,
533                                   EINA_INLIST_GET(global));
534              free(global->interface);
535              free(global);
536           }
537 
538         _ecore_wl_xkb_shutdown(_ecore_wl_disp);
539 
540         if (_ecore_wl_disp->wl.session_recovery)
541           zwp_e_session_recovery_destroy(_ecore_wl_disp->wl.session_recovery);
542 #ifdef USE_IVI_SHELL
543         if (_ecore_wl_disp->wl.ivi_application)
544           ivi_application_destroy(_ecore_wl_disp->wl.ivi_application);
545 #endif
546         if (_ecore_wl_disp->wl.xdg_shell)
547           xdg_shell_destroy(_ecore_wl_disp->wl.xdg_shell);
548         if (_ecore_wl_disp->wl.shell)
549           wl_shell_destroy(_ecore_wl_disp->wl.shell);
550         if (_ecore_wl_disp->wl.shm) wl_shm_destroy(_ecore_wl_disp->wl.shm);
551         if (_ecore_wl_disp->wl.data_device_manager)
552           wl_data_device_manager_destroy(_ecore_wl_disp->wl.data_device_manager);
553         if (_ecore_wl_disp->wl.compositor)
554           wl_compositor_destroy(_ecore_wl_disp->wl.compositor);
555         if (_ecore_wl_disp->wl.subcompositor)
556           wl_subcompositor_destroy(_ecore_wl_disp->wl.subcompositor);
557         if (_ecore_wl_disp->cursor_theme)
558           wl_cursor_theme_destroy(_ecore_wl_disp->cursor_theme);
559         if (_ecore_wl_disp->wl.display)
560           {
561              wl_registry_destroy(_ecore_wl_disp->wl.registry);
562              wl_display_flush(_ecore_wl_disp->wl.display);
563              wl_display_disconnect(_ecore_wl_disp->wl.display);
564           }
565         free(_ecore_wl_disp);
566      }
567 
568    ecore_event_shutdown();
569    ecore_shutdown();
570 
571    eina_log_domain_unregister(_ecore_wl_log_dom);
572    _ecore_wl_log_dom = -1;
573    eina_shutdown();
574 
575    return _ecore_wl_init_count;
576 }
577 
578 static Eina_Bool
_ecore_wl_cb_idle_enterer(void * data)579 _ecore_wl_cb_idle_enterer(void *data)
580 {
581    Ecore_Wl_Display *ewd;
582    int ret = 0;
583 
584    if (_ecore_wl_fatal_error) return ECORE_CALLBACK_CANCEL;
585 
586    if (!(ewd = data)) return ECORE_CALLBACK_RENEW;
587 
588    ret = wl_display_get_error(ewd->wl.display);
589    if (ret < 0) goto err;
590 
591    ret = wl_display_dispatch_pending(ewd->wl.display);
592    if (ret < 0) goto err;
593 
594    ret = wl_display_flush(ewd->wl.display);
595    if ((ret < 0) && (errno == EAGAIN))
596      ecore_main_fd_handler_active_set(ewd->fd_hdl,
597                                       (ECORE_FD_READ | ECORE_FD_WRITE));
598 
599    return ECORE_CALLBACK_RENEW;
600 
601 err:
602    if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
603      {
604         _ecore_wl_fatal_error = EINA_TRUE;
605 
606         /* raise exit signal */
607         ERR("Wayland socket error: %s", strerror(errno));
608         _ecore_wl_signal_exit();
609 
610         return ECORE_CALLBACK_CANCEL;
611      }
612 
613    return ECORE_CALLBACK_RENEW;
614 }
615 
616 static Eina_Bool
_ecore_wl_cb_handle_data(void * data,Ecore_Fd_Handler * hdl)617 _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl)
618 {
619    Ecore_Wl_Display *ewd;
620    int ret = 0;
621 
622    /* LOGFN; */
623 
624    if (_ecore_wl_fatal_error) return ECORE_CALLBACK_CANCEL;
625 
626    if (!(ewd = data)) return ECORE_CALLBACK_RENEW;
627 
628    if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_ERROR))
629      {
630         ERR("Received error on wayland display fd");
631         _ecore_wl_fatal_error = EINA_TRUE;
632         _ecore_wl_signal_exit();
633 
634         return ECORE_CALLBACK_CANCEL;
635      }
636 
637    /* wl_display_dispatch_pending(ewd->wl.display); */
638 
639    if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_READ))
640      ret = wl_display_dispatch(ewd->wl.display);
641    else if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_WRITE))
642      {
643         ret = wl_display_flush(ewd->wl.display);
644         if (ret == 0)
645           ecore_main_fd_handler_active_set(hdl, ECORE_FD_READ);
646      }
647 
648    if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
649      {
650         _ecore_wl_fatal_error = EINA_TRUE;
651 
652         /* raise exit signal */
653         _ecore_wl_signal_exit();
654 
655         return ECORE_CALLBACK_CANCEL;
656      }
657 
658    return ECORE_CALLBACK_RENEW;
659 }
660 
661 static void
_ecore_wl_cb_handle_global(void * data,struct wl_registry * registry,unsigned int id,const char * interface,unsigned int version)662 _ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned int id, const char *interface, unsigned int version)
663 {
664    Ecore_Wl_Display *ewd;
665    Ecore_Wl_Global *global;
666 
667    LOGFN;
668 
669    ewd = data;
670 
671    if (!(global = calloc(1, sizeof(Ecore_Wl_Global)))) return;
672 
673    global->id = id;
674    global->interface = strdup(interface);
675    global->version = version;
676    ewd->globals = eina_inlist_append(ewd->globals, EINA_INLIST_GET(global));
677 
678    if (!strcmp(interface, "wl_compositor"))
679      {
680         ewd->wl.compositor =
681           wl_registry_bind(registry, id, &wl_compositor_interface, 3);
682      }
683    else if (!strcmp(interface, "wl_subcompositor"))
684      {
685         ewd->wl.subcompositor =
686            wl_registry_bind(registry, id, &wl_subcompositor_interface, 1);
687      }
688    else if (!strcmp(interface, "wl_output"))
689      _ecore_wl_output_add(ewd, id);
690    else if (!strcmp(interface, "wl_seat"))
691      _ecore_wl_input_add(ewd, id);
692    else if (!strcmp(interface, "zwp_e_session_recovery") && getenv("EFL_WAYLAND_SESSION_RECOVERY"))
693      {
694         ewd->wl.session_recovery =
695           wl_registry_bind(registry, id, &zwp_e_session_recovery_interface, 1);
696      }
697 #ifdef USE_IVI_SHELL
698    else if (!strcmp(interface, "ivi_application"))
699      {
700         ewd->wl.ivi_application =
701           wl_registry_bind(registry, id, &ivi_application_interface, 1);
702      }
703 #endif
704    else if (!strcmp(interface, "xdg_shell") && !getenv("EFL_WAYLAND_DONT_USE_XDG_SHELL"))
705      {
706         Eina_Hash *h;
707         Eina_Iterator *it;
708         Ecore_Wl_Window *win;
709 
710         ewd->wl.xdg_shell =
711           wl_registry_bind(registry, id, &xdg_shell_interface, 1);
712         xdg_shell_use_unstable_version(ewd->wl.xdg_shell, XDG_VERSION);
713         xdg_shell_add_listener(ewd->wl.xdg_shell, &xdg_shell_listener,
714                                ewd->wl.display);
715         h = _ecore_wl_window_hash_get();
716         it = eina_hash_iterator_data_new(h);
717         EINA_ITERATOR_FOREACH(it, win)
718           if (win->surface)
719             _ecore_wl_window_shell_surface_init(win);
720      }
721    else if (!strcmp(interface, "wl_shell"))
722      {
723         ewd->wl.shell =
724           wl_registry_bind(registry, id, &wl_shell_interface, 1);
725      }
726    else if (!strcmp(interface, "wl_shm"))
727      {
728         ewd->wl.shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
729 
730         if (ewd->input)
731           _ecore_wl_input_setup(ewd->input);
732         else if (!ewd->cursor_theme)
733           {
734              ewd->cursor_theme =
735                wl_cursor_theme_load(NULL, ECORE_WL_DEFAULT_CURSOR_SIZE,
736                                     ewd->wl.shm);
737           }
738      }
739    else if (!strcmp(interface, "wl_data_device_manager"))
740      {
741         ewd->wl.data_device_manager =
742           wl_registry_bind(registry, id, &wl_data_device_manager_interface, 1);
743      }
744 
745    if ((ewd->wl.compositor) && (ewd->wl.shm) &&
746        ((ewd->wl.shell) || (ewd->wl.xdg_shell)))
747      {
748         Ecore_Wl_Event_Interfaces_Bound *ev;
749 
750         if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Interfaces_Bound))))
751           return;
752 
753         ev->compositor = (ewd->wl.compositor != NULL);
754         ev->shm = (ewd->wl.shm != NULL);
755         ev->shell = ((ewd->wl.shell != NULL) || (ewd->wl.xdg_shell != NULL));
756         ev->output = (ewd->output != NULL);
757         ev->seat = (ewd->input != NULL);
758         ev->data_device_manager = (ewd->wl.data_device_manager != NULL);
759         ev->subcompositor = (ewd->wl.subcompositor != NULL);
760 
761         ecore_event_add(ECORE_WL_EVENT_INTERFACES_BOUND, ev, NULL, NULL);
762      }
763 }
764 
765 static void
_ecore_wl_cb_handle_global_remove(void * data,struct wl_registry * registry EINA_UNUSED,unsigned int id)766 _ecore_wl_cb_handle_global_remove(void *data, struct wl_registry *registry EINA_UNUSED, unsigned int id)
767 {
768    Ecore_Wl_Display *ewd;
769    Ecore_Wl_Global *global;
770    Eina_Inlist *tmp;
771 
772    LOGFN;
773 
774    ewd = data;
775 
776    EINA_INLIST_FOREACH_SAFE(ewd->globals, tmp, global)
777      {
778         if (global->id != id) continue;
779         ewd->globals =
780           eina_inlist_remove(ewd->globals, EINA_INLIST_GET(global));
781         free(global->interface);
782         free(global);
783      }
784 }
785 
786 static Eina_Bool
_ecore_wl_xkb_init(Ecore_Wl_Display * ewd)787 _ecore_wl_xkb_init(Ecore_Wl_Display *ewd)
788 {
789    LOGFN;
790 
791    if (!(ewd->xkb.context = xkb_context_new(0)))
792      return EINA_FALSE;
793 
794    return EINA_TRUE;
795 }
796 
797 static Eina_Bool
_ecore_wl_xkb_shutdown(Ecore_Wl_Display * ewd)798 _ecore_wl_xkb_shutdown(Ecore_Wl_Display *ewd)
799 {
800    LOGFN;
801 
802    xkb_context_unref(ewd->xkb.context);
803 
804    return EINA_TRUE;
805 }
806 
807 static void
_ecore_wl_sync_callback(void * data,struct wl_callback * callback,uint32_t serial EINA_UNUSED)808 _ecore_wl_sync_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED)
809 {
810    Ecore_Wl_Display *ewd = data;
811 
812    ewd->sync_ref_count--;
813    wl_callback_destroy(callback);
814 }
815 
816 static void
_ecore_wl_sync_wait(Ecore_Wl_Display * ewd)817 _ecore_wl_sync_wait(Ecore_Wl_Display *ewd)
818 {
819    struct wl_callback *callback;
820 
821    ewd->sync_ref_count++;
822    callback = wl_display_sync(ewd->wl.display);
823    wl_callback_add_listener(callback, &_ecore_wl_sync_listener, ewd);
824 }
825 
826 static void
_ecore_wl_animator_tick_cb_begin(void * data EINA_UNUSED)827 _ecore_wl_animator_tick_cb_begin(void *data EINA_UNUSED)
828 {
829    Eina_Hash *windows;
830 
831    _ecore_wl_animator_busy = EINA_TRUE;
832 
833    windows = _ecore_wl_window_hash_get();
834    eina_hash_foreach(windows, _ecore_wl_animator_window_add, NULL);
835 }
836 
837 static void
_ecore_wl_animator_tick_cb_end(void * data EINA_UNUSED)838 _ecore_wl_animator_tick_cb_end(void *data EINA_UNUSED)
839 {
840    _ecore_wl_animator_busy = EINA_FALSE;
841 }
842 
843 static void
_ecore_wl_animator_callback(void * data,struct wl_callback * callback,uint32_t serial EINA_UNUSED)844 _ecore_wl_animator_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED)
845 {
846    Ecore_Wl_Window *win;
847 
848    if (!(win = data)) return;
849 
850    ecore_animator_custom_tick();
851 
852    wl_callback_destroy(callback);
853    win->anim_callback = NULL;
854 
855    if (_ecore_wl_animator_busy)
856      {
857         win->anim_callback = wl_surface_frame(win->surface);
858         wl_callback_add_listener(win->anim_callback,
859                                  &_ecore_wl_anim_listener, win);
860         ecore_wl_window_commit(win);
861      }
862 }
863 
864 static Eina_Bool
_ecore_wl_animator_window_add(const Eina_Hash * hash EINA_UNUSED,const void * key EINA_UNUSED,void * data,void * fdata EINA_UNUSED)865 _ecore_wl_animator_window_add(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
866 {
867    Ecore_Wl_Window *win;
868 
869    if (!(win = data)) return EINA_TRUE;
870    if (!win->surface) return EINA_TRUE;
871    if (win->anim_callback) return EINA_TRUE;
872 
873    win->anim_callback = wl_surface_frame(win->surface);
874    wl_callback_add_listener(win->anim_callback, &_ecore_wl_anim_listener, win);
875    ecore_wl_window_commit(win);
876 
877    return EINA_TRUE;
878 }
879 
880 static void
_ecore_wl_signal_exit(void)881 _ecore_wl_signal_exit(void)
882 {
883    Ecore_Event_Signal_Exit *ev;
884 
885    if (!(ev = calloc(1, sizeof(Ecore_Event_Signal_Exit))))
886      return;
887 
888    ev->quit = 1;
889    ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, ev,
890                    _ecore_wl_signal_exit_free, NULL);
891 }
892 
893 static void
_ecore_wl_signal_exit_free(void * data EINA_UNUSED,void * event)894 _ecore_wl_signal_exit_free(void *data EINA_UNUSED, void *event)
895 {
896    free(event);
897 }
898