17 # define alloca __builtin_alloca
19 # define alloca __alloca
20 # elif defined _MSC_VER
22 # define alloca _alloca
23 # elif !defined HAVE_ALLOCA
27 void *alloca (size_t);
32 #include "ecore_wl_private.h"
33 #include <subsurface-client-protocol.h>
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);
46 static int _ecore_wl_init_count = 0;
47 static const struct wl_registry_listener _ecore_wl_registry_listener =
49 _ecore_wl_cb_handle_global,
50 NULL // handle_global_remove
53 static const struct wl_callback_listener _ecore_wl_sync_listener =
55 _ecore_wl_sync_callback
58 /* external variables */
59 int _ecore_wl_log_dom = -1;
60 Ecore_Wl_Display *_ecore_wl_disp = NULL;
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;
78 * @defgroup Ecore_Wl_Init_Group Wayland Library Init and Shutdown Functions
80 * Functions that start and shutdown the Ecore Wayland Library.
84 * Initialize the Wayland display connection to the given display.
86 * @param name Display target name. if @c NULL, the default display is
88 * @return The number of times the library has been initialized without being
89 * shut down. 0 is returned if an error occurs.
91 * @ingroup Ecore_Wl_Init_Group
94 ecore_wl_init(const char *name)
96 LOGFN(__FILE__, __LINE__, __FUNCTION__);
98 if (++_ecore_wl_init_count != 1) return _ecore_wl_init_count;
100 if (!eina_init()) return --_ecore_wl_init_count;
103 eina_log_domain_register("ecore_wl", ECORE_WL_DEFAULT_LOG_COLOR);
104 if (_ecore_wl_log_dom < 0)
106 EINA_LOG_ERR("Cannot create a log domain for Ecore Wayland");
108 return --_ecore_wl_init_count;
113 ERR("Could not initialize ecore");
114 eina_log_domain_unregister(_ecore_wl_log_dom);
115 _ecore_wl_log_dom = -1;
117 return --_ecore_wl_init_count;
120 if (!ecore_event_init())
122 ERR("Could not initialize ecore_event");
123 eina_log_domain_unregister(_ecore_wl_log_dom);
124 _ecore_wl_log_dom = -1;
127 return --_ecore_wl_init_count;
130 if (!ECORE_WL_EVENT_MOUSE_IN)
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();
148 if (!(_ecore_wl_disp = malloc(sizeof(Ecore_Wl_Display))))
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();
156 return --_ecore_wl_init_count;
159 memset(_ecore_wl_disp, 0, sizeof(Ecore_Wl_Display));
161 if (!(_ecore_wl_disp->wl.display = wl_display_connect(name)))
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();
169 return --_ecore_wl_init_count;
172 _ecore_wl_disp->fd = wl_display_get_fd(_ecore_wl_disp->wl.display);
174 _ecore_wl_disp->fd_hdl =
175 ecore_main_fd_handler_add(_ecore_wl_disp->fd,
177 _ecore_wl_cb_handle_data, _ecore_wl_disp,
180 _ecore_wl_disp->idle_enterer =
181 ecore_idle_enterer_add(_ecore_wl_cb_idle_enterer, _ecore_wl_disp);
183 wl_list_init(&_ecore_wl_disp->inputs);
184 wl_list_init(&_ecore_wl_disp->outputs);
185 wl_list_init(&_ecore_wl_disp->globals);
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);
192 wl_display_dispatch(_ecore_wl_disp->wl.display);
194 if (!_ecore_wl_xkb_init(_ecore_wl_disp))
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();
203 return --_ecore_wl_init_count;
206 _ecore_wl_window_init();
208 return _ecore_wl_init_count;
212 * Shuts down the Ecore Wayland Library
214 * In shutting down the library, the Wayland display connection is terminated
215 * and any event handlers for it are removed.
217 * @return The number of times the library has been initialized without
220 * @ingroup Ecore_Wl_Init_Group
223 ecore_wl_shutdown(void)
225 LOGFN(__FILE__, __LINE__, __FUNCTION__);
227 return _ecore_wl_shutdown(EINA_TRUE);
231 * @defgroup Ecore_Wl_Flush_Group Wayland Synchronization Functions
233 * Functions that ensure that all commands which have been issued by the
234 * Ecore Wayland library have been sent to the server.
238 * Sends all Wayland commands to the Wayland Display.
240 * @ingroup Ecore_Wl_Flush_Group
246 // LOGFN(__FILE__, __LINE__, __FUNCTION__);
248 wl_display_flush(_ecore_wl_disp->wl.display);
252 * Flushes the command buffer and waits until all requests have been
253 * processed by the server.
255 * @ingroup Ecore_Wl_Flush_Group
261 // LOGFN(__FILE__, __LINE__, __FUNCTION__);
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);
269 * @defgroup Ecore_Wl_Display_Group Wayland Display Functions
271 * Functions that set and retrieve various information about the Wayland Display.
275 * Retrieves the Wayland Shm Interface used for the current Wayland connection.
277 * @return The current wayland shm interface
279 * @ingroup Ecore_Wl_Display_Group
283 ecore_wl_shm_get(void)
285 return _ecore_wl_disp->wl.shm;
289 * Retrieves the Wayland Display Interface used for the current Wayland connection.
291 * @return The current wayland display interface
293 * @ingroup Ecore_Wl_Display_Group
296 EAPI struct wl_display *
297 ecore_wl_display_get(void)
299 return _ecore_wl_disp->wl.display;
302 EAPI struct wl_list *
303 ecore_wl_globals_get(void)
305 return &(_ecore_wl_disp->globals);
308 EAPI struct wl_registry *
309 ecore_wl_registry_get(void)
311 return _ecore_wl_disp->wl.registry;
315 * Retrieves the size of the current screen.
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.
320 * @ingroup Ecore_Wl_Display_Group
324 ecore_wl_screen_size_get(int *w, int *h)
326 LOGFN(__FILE__, __LINE__, __FUNCTION__);
331 if (!_ecore_wl_disp->output)
334 if (!_ecore_wl_disp->output) return;
336 switch (_ecore_wl_disp->output->transform)
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;
347 if (w) *w = _ecore_wl_disp->output->allocation.w;
348 if (h) *h = _ecore_wl_disp->output->allocation.h;
354 ecore_wl_pointer_xy_get(int *x, int *y)
356 LOGFN(__FILE__, __LINE__, __FUNCTION__);
358 _ecore_wl_input_pointer_xy_get(x, y);
362 * Return the screen DPI
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.
368 * @return the general screen DPI (dots/pixels per inch).
373 ecore_wl_dpi_get(void)
377 LOGFN(__FILE__, __LINE__, __FUNCTION__);
379 if (!_ecore_wl_disp->output) return 75;
381 mw = _ecore_wl_disp->output->mw;
382 if (mw <= 0) return 75;
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;
391 ecore_wl_display_iterate(void)
393 wl_display_dispatch(_ecore_wl_disp->wl.display);
397 * Retrieves the requested cursor from the cursor theme
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
404 EAPI struct wl_cursor *
405 ecore_wl_cursor_get(const char *cursor_name)
407 if ((!_ecore_wl_disp) || (!_ecore_wl_disp->cursor_theme))
410 return wl_cursor_theme_get_cursor(_ecore_wl_disp->cursor_theme,
414 /* local functions */
416 _ecore_wl_shutdown(Eina_Bool close)
418 LOGFN(__FILE__, __LINE__, __FUNCTION__);
420 if (--_ecore_wl_init_count != 0) return _ecore_wl_init_count;
421 if (!_ecore_wl_disp) return _ecore_wl_init_count;
423 _ecore_wl_window_shutdown();
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);
432 Ecore_Wl_Output *out, *tout;
433 Ecore_Wl_Input *in, *tin;
434 Ecore_Wl_Global *global, *tglobal;
436 wl_list_for_each_safe(out, tout, &_ecore_wl_disp->outputs, link)
437 _ecore_wl_output_del(out);
439 wl_list_for_each_safe(in, tin, &_ecore_wl_disp->inputs, link)
440 _ecore_wl_input_del(in);
442 wl_list_for_each_safe(global, tglobal, &_ecore_wl_disp->globals, link)
444 wl_list_remove(&global->link);
445 free(global->interface);
449 _ecore_wl_xkb_shutdown(_ecore_wl_disp);
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_compositor_destroy(_ecore_wl_disp->wl.subcompositor);
460 if (_ecore_wl_disp->wl.display)
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);
466 free(_ecore_wl_disp);
469 ecore_event_shutdown();
472 eina_log_domain_unregister(_ecore_wl_log_dom);
473 _ecore_wl_log_dom = -1;
476 return _ecore_wl_init_count;
480 _ecore_wl_cb_idle_enterer(void *data)
482 Ecore_Wl_Display *ewd;
485 if (!(ewd = data)) return ECORE_CALLBACK_RENEW;
487 ret = wl_display_flush(ewd->wl.display);
488 if ((ret < 0) && (errno == EAGAIN))
490 ecore_main_fd_handler_active_set(ewd->fd_hdl,
491 (ECORE_FD_READ | ECORE_FD_WRITE));
495 /* FIXME: need do error processing? */
498 return ECORE_CALLBACK_RENEW;
502 _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl)
504 Ecore_Wl_Display *ewd;
507 /* LOGFN(__FILE__, __LINE__, __FUNCTION__); */
509 if (!(ewd = data)) return ECORE_CALLBACK_RENEW;
511 /* FIXME: This should also catch ECORE_FD_ERROR and exit */
513 /* wl_display_dispatch_pending(ewd->wl.display); */
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))
519 ret = wl_display_flush(ewd->wl.display);
521 ecore_main_fd_handler_active_set(hdl, ECORE_FD_READ);
522 else if ((ret == -1) && (errno != EAGAIN))
524 /* FIXME: need do error processing? */
528 return ECORE_CALLBACK_RENEW;
532 _ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned int id, const char *interface, unsigned int version __UNUSED__)
534 Ecore_Wl_Display *ewd;
535 Ecore_Wl_Global *global;
537 LOGFN(__FILE__, __LINE__, __FUNCTION__);
541 global = malloc(sizeof(*global));
543 memset(global, 0, sizeof(Ecore_Wl_Global));
546 global->interface = strdup(interface);
547 global->version = version;
548 wl_list_insert(ewd->globals.prev, &global->link);
550 if (!strcmp(interface, "wl_compositor"))
553 wl_registry_bind(registry, id, &wl_compositor_interface, 1);
555 else if (!strcmp(interface, "wl_subcompositor"))
557 ewd->wl.subcompositor =
558 wl_registry_bind(registry, id, &wl_subcompositor_interface, 1);
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"))
567 wl_registry_bind(registry, id, &wl_shell_interface, 1);
569 else if (!strcmp(interface, "wl_shm"))
571 ewd->wl.shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
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);
577 else if (!strcmp(interface, "wl_data_device_manager"))
579 ewd->wl.data_device_manager =
580 wl_registry_bind(registry, id, &wl_data_device_manager_interface, 1);
583 if ((ewd->wl.compositor) && (ewd->wl.shm) && (ewd->wl.shell))
585 Ecore_Wl_Event_Interfaces_Bound *ev;
587 if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Interfaces_Bound))))
590 ev->compositor = (ewd->wl.compositor != NULL);
591 ev->shm = (ewd->wl.shm != NULL);
592 ev->shell = (ewd->wl.shell != NULL);
594 ecore_event_add(ECORE_WL_EVENT_INTERFACES_BOUND, ev, NULL, NULL);
599 _ecore_wl_xkb_init(Ecore_Wl_Display *ewd)
601 LOGFN(__FILE__, __LINE__, __FUNCTION__);
603 if (!(ewd->xkb.context = xkb_context_new(0)))
610 _ecore_wl_xkb_shutdown(Ecore_Wl_Display *ewd)
612 LOGFN(__FILE__, __LINE__, __FUNCTION__);
614 xkb_context_unref(ewd->xkb.context);
619 struct wl_data_source *
620 _ecore_wl_create_data_source(Ecore_Wl_Display *ewd)
622 return wl_data_device_manager_create_data_source(ewd->wl.data_device_manager);
626 _ecore_wl_sync_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED)
628 Ecore_Wl_Display *ewd = data;
630 ewd->sync_ref_count--;
631 wl_callback_destroy(callback);
635 _ecore_wl_sync_wait(Ecore_Wl_Display *ewd)
637 struct wl_callback *callback;
639 ewd->sync_ref_count++;
640 callback = wl_display_sync(ewd->wl.display);
641 wl_callback_add_listener(callback, &_ecore_wl_sync_listener, ewd);