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