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