5 #include "ecore_wl2_private.h"
7 #include "linux-dmabuf-unstable-v1-client-protocol.h"
8 #include "efl-hints-client-protocol.h"
10 #ifdef HAVE_SYS_INOTIFY_H
11 # include <sys/inotify.h>
14 static Eina_Hash *_server_displays = NULL;
15 static Eina_Hash *_client_displays = NULL;
17 static Eina_Bool _cb_connect_idle(void *data);
18 static Eina_Bool _cb_connect_data(void *data, Ecore_Fd_Handler *hdl);
19 static Eina_Bool _ecore_wl2_display_connect(Ecore_Wl2_Display *ewd, Eina_Bool sync);
20 // TIZEN_ONLY(20171129): thread-safety for wl
21 static void _ecore_wl_cb_awake(void *data);
22 // End of TIZEN_ONLY(20171129)
23 static void _ecore_wl2_display_sync_add(Ecore_Wl2_Display *ewd);
25 // TIZEN_ONLY(20190430): support client appinfo
26 static pid_t _base_resolution_pid = 0;
27 static uint32_t _base_resolution_w = 0;
28 static uint32_t _base_resolution_h = 0;
32 _display_event_free(void *d, void *event)
34 ecore_wl2_display_disconnect(d);
39 _ecore_wl2_display_event(Ecore_Wl2_Display *ewd, int event)
41 Ecore_Wl2_Event_Connect *ev;
43 ev = calloc(1, sizeof(Ecore_Wl2_Event_Connect));
44 EINA_SAFETY_ON_NULL_RETURN(ev);
47 ecore_event_add(event, ev, _display_event_free, ewd);
51 _ecore_wl2_display_signal_exit(void)
53 Ecore_Event_Signal_Exit *ev;
55 ev = calloc(1, sizeof(Ecore_Event_Signal_Exit));
59 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, ev, NULL, NULL);
63 _dmabuf_cb_format(void *data EINA_UNUSED, struct zwp_linux_dmabuf_v1 *dmabuf EINA_UNUSED, uint32_t format EINA_UNUSED)
65 /* It would be awfully nice if this actually happened */
68 static const struct zwp_linux_dmabuf_v1_listener _dmabuf_listener =
75 _xdg_shell_cb_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
77 xdg_wm_base_pong(shell, serial);
78 ecore_wl2_display_flush(data);
81 static const struct xdg_wm_base_listener _xdg_shell_listener =
87 _zxdg_shell_cb_ping(void *data, struct zxdg_shell_v6 *shell, uint32_t serial)
89 zxdg_shell_v6_pong(shell, serial);
90 ecore_wl2_display_flush(data);
93 static const struct zxdg_shell_v6_listener _zxdg_shell_listener =
99 _session_recovery_create_uuid(void *data EINA_UNUSED, struct zwp_e_session_recovery *session_recovery EINA_UNUSED, struct wl_surface *surface, const char *uuid)
101 Ecore_Wl2_Window *win;
103 /* surface may have been destroyed */
104 if (!surface) return;
105 win = wl_surface_get_user_data(surface);
107 eina_stringshare_replace(&win->uuid, uuid);
110 static const struct zwp_e_session_recovery_listener _session_listener =
112 _session_recovery_create_uuid,
116 _aux_hints_supported_aux_hints(void *data, struct efl_aux_hints *aux_hints EINA_UNUSED, struct wl_surface *surface_resource, struct wl_array *hints, uint32_t num_hints)
118 Ecore_Wl2_Display *ewd = data;
119 struct wl_surface *surface = surface_resource;
120 Ecore_Wl2_Window *win = NULL;
123 const char *hint = NULL;
125 Ecore_Wl2_Event_Aux_Hint_Supported *ev;
127 if (!surface) return;
128 win = _ecore_wl2_display_window_surface_find(ewd, surface_resource);
132 str = calloc(num_hints, sizeof(char *));
135 while ((const char *)p < ((const char *)hints->data + hints->size))
137 str[i] = (char *)eina_stringshare_add(p);
141 for (i = 0; i < num_hints; i++)
143 hint = eina_stringshare_add(str[i]);
144 win->supported_aux_hints =
145 eina_list_append(win->supported_aux_hints, hint);
149 for (i = 0; i < num_hints; i++)
153 eina_stringshare_del(str[i]);
160 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Aux_Hint_Supported)))) return;
164 ecore_event_add(ECORE_WL2_EVENT_AUX_HINT_SUPPORTED, ev,
165 _display_event_free, ewd);
169 _aux_hints_allowed_aux_hint(void *data, struct efl_aux_hints *aux_hints EINA_UNUSED, struct wl_surface *surface_resource, int id)
171 struct wl_surface *surface = surface_resource;
172 Ecore_Wl2_Window *win = NULL;
173 Ecore_Wl2_Display *ewd = data;
174 Ecore_Wl2_Event_Aux_Hint_Allowed *ev;
176 if (!surface) return;
177 win = _ecore_wl2_display_window_surface_find(ewd, surface_resource);
180 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Aux_Hint_Allowed)))) return;
185 ecore_event_add(ECORE_WL2_EVENT_AUX_HINT_ALLOWED, ev,
186 _display_event_free, ewd);
190 _cb_aux_message_free(void *data EINA_UNUSED, void *event)
192 Ecore_Wl2_Event_Aux_Message *ev;
196 ecore_wl2_display_disconnect(ev->display);
197 eina_stringshare_del(ev->key);
198 eina_stringshare_del(ev->val);
199 EINA_LIST_FREE(ev->options, str)
200 eina_stringshare_del(str);
205 _aux_hints_aux_message(void *data, struct efl_aux_hints *aux_hints EINA_UNUSED, struct wl_surface *surface_resource, const char *key, const char *val, struct wl_array *options)
207 Ecore_Wl2_Window *win = NULL;
208 Ecore_Wl2_Event_Aux_Message *ev;
209 char *p = NULL, *str = NULL;
210 Eina_List *opt_list = NULL;
211 Ecore_Wl2_Display *ewd = data;
213 if (!surface_resource) return;
214 win = _ecore_wl2_display_window_surface_find(ewd, surface_resource);
217 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Aux_Message)))) return;
219 if ((options) && (options->size))
222 while ((const char *)p < ((const char *)options->data + options->size))
224 str = (char *)eina_stringshare_add(p);
225 opt_list = eina_list_append(opt_list, str);
231 ev->key = eina_stringshare_add(key);
232 ev->val = eina_stringshare_add(val);
233 ev->options = opt_list;
237 ecore_event_add(ECORE_WL2_EVENT_AUX_MESSAGE, ev, _cb_aux_message_free, NULL);
240 static const struct efl_aux_hints_listener _aux_hints_listener =
242 _aux_hints_supported_aux_hints,
243 _aux_hints_allowed_aux_hint,
244 _aux_hints_aux_message,
247 // TIZEN_ONLY : To use tizen protocols
249 _tizen_policy_conformant_area_send(Ecore_Wl2_Window *win, uint32_t conformant_part, uint32_t state)
251 Ecore_Wl2_Event_Conformant_Change *ev;
253 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Conformant_Change)))) return;
255 ev->part_type = conformant_part;
257 ecore_event_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, ev, NULL, NULL);
261 _tizen_policy_cb_conformant(void *data, struct tizen_policy *tizen_policy EINA_UNUSED, struct wl_surface *surface_resource, uint32_t is_conformant)
263 Ecore_Wl2_Display *ewd = data;
264 Ecore_Wl2_Window *win = NULL;
266 if (!surface_resource) return;
267 win = ecore_wl2_display_window_find_by_surface(ewd, surface_resource);
269 win->conformant = is_conformant;
273 _tizen_policy_cb_conformant_area(void *data, struct tizen_policy *tizen_policy EINA_UNUSED, struct wl_surface *surface_resource, uint32_t conformant_part, uint32_t state, int32_t x, int32_t y, int32_t w, int32_t h)
275 Ecore_Wl2_Display *ewd = data;
276 Ecore_Wl2_Window *win = NULL;
277 int org_x, org_y, org_w, org_h;
278 Eina_Bool changed = EINA_FALSE;
279 Ecore_Wl2_Indicator_State ind_state;
280 Ecore_Wl2_Virtual_Keyboard_State kbd_state;
281 Ecore_Wl2_Clipboard_State clip_state;
283 if (!surface_resource) return;
284 win = ecore_wl2_display_window_find_by_surface(ewd, surface_resource);
287 if (conformant_part == TIZEN_POLICY_CONFORMANT_PART_INDICATOR)
289 ecore_wl2_window_indicator_geometry_get(win, &org_x, &org_y, &org_w, &org_h);
290 if ((org_x != x) || (org_y != y) || (org_w != w) || (org_h != h))
292 ecore_wl2_window_indicator_geometry_set(win, x, y, w, h);
296 /* The given state is based on the visibility value of indicator.
297 * Thus we need to add 1 to it before comparing with indicator state.
299 ind_state = ecore_wl2_window_indicator_state_get(win);
300 if ((state + 1) != ind_state)
302 ecore_wl2_window_indicator_state_set(win, state + 1);
306 else if (conformant_part == TIZEN_POLICY_CONFORMANT_PART_KEYBOARD)
308 ecore_wl2_window_keyboard_geometry_get(win, &org_x, &org_y, &org_w, &org_h);
309 if ((org_x != x) || (org_y != y) || (org_w != w) || (org_h != h))
311 ecore_wl2_window_keyboard_geometry_set(win, x, y, w, h);
315 /* The given state is based on the visibility value of virtual keyboard window.
316 * Thus we need to add 1 to it before comparing with keyboard state.
318 kbd_state = ecore_wl2_window_keyboard_state_get(win);
319 if ((state + 1) != (kbd_state))
321 ecore_wl2_window_keyboard_state_set(win, state + 1);
325 else if (conformant_part == TIZEN_POLICY_CONFORMANT_PART_CLIPBOARD)
327 ecore_wl2_window_clipboard_geometry_get(win, &org_x, &org_y, &org_w, &org_h);
328 if ((org_x != x) || (org_y != y) || (org_w != w) || (org_h != h))
330 ecore_wl2_window_clipboard_geometry_set(win, x, y, w, h);
334 /* The given state is based on the visibility value of clipboard window.
335 * Thus we need to add 1 to it before comparing with clipboard state.
337 clip_state = ecore_wl2_window_clipboard_state_get(win);
338 if ((state + 1) != clip_state)
340 ecore_wl2_window_clipboard_state_set(win, state + 1);
346 _tizen_policy_conformant_area_send(win, conformant_part, state);
350 _tizen_policy_cb_notification_done(void *data EINA_UNUSED, struct tizen_policy *tizen_policy EINA_UNUSED, struct wl_surface *surface EINA_UNUSED, int32_t level EINA_UNUSED, uint32_t state EINA_UNUSED)
355 _tizen_policy_cb_transient_for_done(void *data EINA_UNUSED, struct tizen_policy *tizen_policy EINA_UNUSED, uint32_t child_id EINA_UNUSED)
360 _tizen_policy_cb_window_screen_mode_done(void *data EINA_UNUSED, struct tizen_policy *tizen_policy EINA_UNUSED, struct wl_surface *surface EINA_UNUSED, uint32_t mode EINA_UNUSED, uint32_t state EINA_UNUSED)
365 _tizen_policy_cb_iconify_state_changed(void *data, struct tizen_policy *tizen_policy EINA_UNUSED, struct wl_surface *surface_resource, uint32_t iconified, uint32_t force)
367 Ecore_Wl2_Display *ewd = data;
368 Ecore_Wl2_Window *win = NULL;
369 Ecore_Wl2_Event_Window_Iconify_State_Change *ev = NULL;
371 if (!surface_resource) return;
373 win = ecore_wl2_display_window_find_by_surface(ewd, surface_resource);
376 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Iconify_State_Change)))) return;
378 ev->iconified = iconified;
381 ecore_event_add(ECORE_WL2_EVENT_WINDOW_ICONIFY_STATE_CHANGE, ev, NULL, NULL);
384 void _window_aux_hint_free(Ecore_Wl2_Window *win)
386 const char *supported;
388 EINA_LIST_FREE(win->supported_aux_hints, supported)
389 if (supported) eina_stringshare_del(supported);
393 _tizen_policy_cb_supported_aux_hints(void *data, struct tizen_policy *tizen_policy EINA_UNUSED, struct wl_surface *surface_resource, struct wl_array *hints, uint32_t num_hints)
395 /* 20171112 : this can be replaced with efl_aux_hints procotol */
397 Ecore_Wl2_Display *ewd = data;
398 Ecore_Wl2_Window *win = NULL;
401 const char *hint = NULL;
404 if (!surface_resource) return;
406 win = ecore_wl2_display_window_find_by_surface(ewd, surface_resource);
410 str = calloc(num_hints, sizeof(char *));
413 _window_aux_hint_free(win);
415 while ((const char *)p < ((const char *)hints->data + hints->size))
417 str[i] = (char *)eina_stringshare_add(p);
421 for (i = 0; i < num_hints; i++)
423 hint = eina_stringshare_add(str[i]);
424 win->supported_aux_hints =
425 eina_list_append(win->supported_aux_hints, hint);
429 for (i = 0; i < num_hints; i++)
433 eina_stringshare_del(str[i]);
442 _tizen_policy_cb_allowed_aux_hint(void *data, struct tizen_policy *tizen_policy EINA_UNUSED, struct wl_surface *surface_resource, int id)
444 /* 20171112 : this can be replaced with efl_aux_hints procotol */
446 struct wl_surface *surface = surface_resource;
447 Ecore_Wl2_Window *win = NULL;
448 Ecore_Wl2_Display *ewd = data;
449 Ecore_Wl2_Event_Aux_Hint_Allowed *ev;
451 if (!surface) return;
452 win = _ecore_wl2_display_window_surface_find(ewd, surface_resource);
455 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Aux_Hint_Allowed)))) return;
460 ecore_event_add(ECORE_WL2_EVENT_AUX_HINT_ALLOWED, ev, _display_event_free, ewd);
464 _tizen_policy_cb_aux_message(void *data EINA_UNUSED, struct tizen_policy *tizen_policy EINA_UNUSED, struct wl_surface *surface_resource, const char *key, const char *val, struct wl_array *options)
466 /* 20171112 : this can be replaced with efl_aux_hints procotol */
468 Ecore_Wl2_Window *win = NULL;
469 Ecore_Wl2_Event_Aux_Message *ev;
470 char *p = NULL, *str = NULL;
471 Eina_List *opt_list = NULL;
472 Ecore_Wl2_Display *ewd = data;
474 if (!surface_resource) return;
475 win = _ecore_wl2_display_window_surface_find(ewd, surface_resource);
478 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Aux_Message)))) return;
480 if ((options) && (options->size))
483 while ((const char *)p < ((const char *)options->data + options->size))
485 str = (char *)eina_stringshare_add(p);
486 opt_list = eina_list_append(opt_list, str);
492 ev->key = eina_stringshare_add(key);
493 ev->val = eina_stringshare_add(val);
494 ev->options = opt_list;
498 ecore_event_add(ECORE_WL2_EVENT_AUX_MESSAGE, ev, _cb_aux_message_free, NULL);
502 _tizen_policy_cb_conformant_region(void *data EINA_UNUSED, struct tizen_policy *tizen_policy EINA_UNUSED, struct wl_surface *surface EINA_UNUSED, uint32_t conformant_part EINA_UNUSED, uint32_t state EINA_UNUSED, int32_t x EINA_UNUSED, int32_t y EINA_UNUSED, int32_t w EINA_UNUSED, int32_t h EINA_UNUSED, uint32_t serial EINA_UNUSED)
506 // TIZEN_ONLY(20220923) - for interactive move resize
508 _cb_interactive_move_resize_done_free(void *data EINA_UNUSED, void *event)
514 _tizen_policy_cb_interactive_move_done(void *data, struct tizen_policy *tizen_policy EINA_UNUSED, struct wl_surface *surface, int32_t x, int32_t y, uint32_t w, uint32_t h, int32_t angle)
516 Ecore_Wl2_Window *win = NULL;
517 Ecore_Wl2_Event_Window_Interactive_Move_Done *ev;
518 Ecore_Wl2_Display *ewd = data;
520 if (!surface) return;
521 win = _ecore_wl2_display_window_surface_find(ewd, surface);
524 ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Interactive_Move_Done));
534 ecore_event_add(ECORE_WL2_EVENT_WINDOW_INTERACTIVE_MOVE_DONE, ev, _cb_interactive_move_resize_done_free, NULL);
538 _tizen_policy_cb_interactive_resize_done(void *data, struct tizen_policy *tizen_policy EINA_UNUSED, struct wl_surface *surface, int32_t x, int32_t y, uint32_t w, uint32_t h, int32_t angle)
540 Ecore_Wl2_Window *win = NULL;
541 Ecore_Wl2_Event_Window_Interactive_Resize_Done *ev;
542 Ecore_Wl2_Display *ewd = data;
544 if (!surface) return;
545 win = _ecore_wl2_display_window_surface_find(ewd, surface);
548 ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Interactive_Resize_Done));
558 ecore_event_add(ECORE_WL2_EVENT_WINDOW_INTERACTIVE_RESIZE_DONE, ev, _cb_interactive_move_resize_done_free, NULL);
560 ecore_wl2_window_resize_request_unset(win);
564 static const struct tizen_policy_listener _tizen_policy_listener =
566 _tizen_policy_cb_conformant,
567 _tizen_policy_cb_conformant_area,
568 _tizen_policy_cb_notification_done,
569 _tizen_policy_cb_transient_for_done,
570 _tizen_policy_cb_window_screen_mode_done,
571 _tizen_policy_cb_iconify_state_changed,
572 _tizen_policy_cb_supported_aux_hints,
573 _tizen_policy_cb_allowed_aux_hint,
574 _tizen_policy_cb_aux_message,
575 _tizen_policy_cb_conformant_region,
576 _tizen_policy_cb_interactive_move_done,
577 _tizen_policy_cb_interactive_resize_done
580 // TIZEN_ONLY(20190430): support client appinfo
582 _tizen_appinfo_cb_base_output_resolution_done(void *data, struct tizen_launch_appinfo *tz_appinfo EINA_UNUSED, uint32_t pid, uint32_t width, uint32_t height)
584 Ecore_Wl2_Display *ewd = data;
587 if ((unsigned int)_base_resolution_pid != pid)
589 ERR("tzappinfo_cb_size_get_done pid is different. pid: %d / width: %d / height: %d appinfo_pid: %d", pid, width, height, _base_resolution_pid);
593 if (_base_resolution_w != width) _base_resolution_w = width;
594 if (_base_resolution_h != height) _base_resolution_h = height;
597 static const struct tizen_launch_appinfo_listener _tizen_launch_appinfo_listener =
599 _tizen_appinfo_cb_base_output_resolution_done,
604 _tizen_policy_ext_cb_active_angle(void *data, struct tizen_policy_ext *tizen_policy_ext EINA_UNUSED, uint32_t angle)
606 Ecore_Wl2_Display *ewd = data;
607 ewd->active_angle = angle;
610 static const struct tizen_policy_ext_listener _tizen_policy_ext_listener =
612 _tizen_policy_ext_cb_active_angle,
616 _tizen_effect_cb_start(void *data EINA_UNUSED, struct tizen_effect *tizen_effect EINA_UNUSED, struct wl_surface *surface_resource, unsigned int type)
618 struct wl_surface *surface = surface_resource;
619 Ecore_Wl2_Window *win = NULL;
620 Ecore_Wl2_Event_Effect_Start *ev;
622 if (!surface) return;
623 win = ecore_wl2_window_surface_find(surface);
626 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Effect_Start)))) return;
629 ecore_event_add(ECORE_WL2_EVENT_EFFECT_START, ev, NULL, NULL);
633 _tizen_effect_cb_end(void *data EINA_UNUSED, struct tizen_effect *tizen_effect EINA_UNUSED, struct wl_surface *surface_resource, unsigned int type)
635 struct wl_surface *surface = surface_resource;
636 Ecore_Wl2_Window *win = NULL;
637 Ecore_Wl2_Event_Effect_End *ev;
639 if (!surface) return;
640 win = ecore_wl2_window_surface_find(surface);
643 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Effect_End)))) return;
646 ecore_event_add(ECORE_WL2_EVENT_EFFECT_END, ev, NULL, NULL);
649 static const struct tizen_effect_listener _tizen_effect_listener =
651 _tizen_effect_cb_start,
652 _tizen_effect_cb_end,
656 _tizen_indicator_cb_flick(void *data, struct tizen_indicator *tizen_indicator EINA_UNUSED, struct wl_surface *surface_resource, int type)
658 Ecore_Wl2_Window *win = NULL;
659 Ecore_Wl2_Display *ewd = data;
660 Ecore_Wl2_Event_Indicator_Flick *ev;
662 if (!surface_resource) return;
663 win = _ecore_wl2_display_window_surface_find(ewd, surface_resource);
666 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Indicator_Flick)))) return;
670 ecore_event_add(ECORE_WL2_EVENT_INDICATOR_FLICK, ev, NULL, NULL);
673 static const struct tizen_indicator_listener _tizen_indicator_listener =
675 _tizen_indicator_cb_flick,
679 _tizen_clipboard_cb_data_selected(void *data, struct tizen_clipboard *tizen_clipboard EINA_UNUSED, struct wl_surface *surface)
681 Ecore_Wl2_Window *win = NULL;
682 Ecore_Wl2_Display *ewd = data;
683 Ecore_Wl2_Event_Clipboard_Data_Selected *ev;
685 if (!surface) return;
686 win = _ecore_wl2_display_window_surface_find(ewd, surface);
689 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Clipboard_Data_Selected)))) return;
692 ecore_event_add(ECORE_WL2_EVENT_CLIPBOARD_DATA_SELECTED, ev, NULL, NULL);
696 _tizen_clipboard_cb_allowed_data_only(void *data, struct tizen_clipboard *tizen_clipboard EINA_UNUSED, uint32_t allowed)
698 Ecore_Wl2_Display *ewd = NULL;
699 Ecore_Wl2_Input *input = NULL;
702 input = ecore_wl2_input_default_input_get(ewd);
706 input->is_data_only = EINA_TRUE;
708 input->is_data_only = EINA_FALSE;
711 static const struct tizen_clipboard_listener _tizen_clipboard_listener =
713 _tizen_clipboard_cb_data_selected,
714 _tizen_clipboard_cb_allowed_data_only,
718 //TIZEN_ONLY(20171115): support output transform
720 _tizen_screen_rotation_cb_ignore_output_transform(void *data EINA_UNUSED, struct tizen_screen_rotation *tizen_screen_rotation EINA_UNUSED, struct wl_surface *surface, uint32_t ignore)
722 Ecore_Wl2_Window *win = NULL;
723 Ecore_Wl2_Event_Ignore_Output_Transform *ev;
725 if (!surface) return;
726 win = ecore_wl2_window_surface_find(surface);
729 _ecore_wl2_window_ignore_output_transform_set(win, ignore);
731 if (!(ev = calloc(1, sizeof(Ecore_Wl2_Event_Ignore_Output_Transform)))) return;
734 ev->ignore = (ignore) ? EINA_TRUE : EINA_FALSE;
735 ecore_event_add(ECORE_WL2_EVENT_IGNORE_OUTPUT_TRANSFORM, ev, NULL, NULL);
738 static const struct tizen_screen_rotation_listener _tizen_screen_rotation_listener =
740 _tizen_screen_rotation_cb_ignore_output_transform,
744 _tizen_move_resize_cb_geometry_done(void *data EINA_UNUSED, struct tizen_move_resize *tz_moveresize EINA_UNUSED, struct wl_surface *surface EINA_UNUSED, uint32_t serial EINA_UNUSED, int32_t x EINA_UNUSED, int32_t y EINA_UNUSED, int32_t w EINA_UNUSED, int32_t h EINA_UNUSED, uint32_t err EINA_UNUSED)
746 /* to be implemented*/
749 static const struct tizen_move_resize_listener _tizen_move_resize_listener =
751 _tizen_move_resize_cb_geometry_done,
755 //TIZEN_ONLY(20230312): support wtz_screen
757 _wtz_screen_cb_size(void *data, struct wtz_screen *screen EINA_UNUSED, uint32_t width, uint32_t height)
759 Ecore_Wl2_Display *ewd = data;
760 Ecore_Wl2_Screen *ews;
764 ews = _ecore_wl2_display_screen_get(ewd);
767 _ecore_wl2_screen_size_set(ews, width, height);
771 _wtz_screen_cb_name(void *data, struct wtz_screen *screen EINA_UNUSED, const char *name)
773 Ecore_Wl2_Display *ewd = data;
774 Ecore_Wl2_Screen *ews;
778 ews = _ecore_wl2_display_screen_get(ewd);
781 _ecore_wl2_screen_name_set(ews, name);
785 _wtz_screen_cb_capabilities(void *data, struct wtz_screen *screen EINA_UNUSED, struct wl_array *capabilities)
787 Ecore_Wl2_Display *ewd = data;
788 Ecore_Wl2_Screen *ews;
794 ews = _ecore_wl2_display_screen_get(ewd);
797 if ((capabilities) && (capabilities->size))
799 p = capabilities->data;
800 while ((const uint32_t *)p < ((const uint32_t *)capabilities->data + capabilities->size))
802 switch ((uint32_t) *p)
804 case WTZ_SCREEN_CAPABILITY_SPLITSCREEN :
805 capability |= ECORE_WL2_SCREEN_CAPABILITY_SPLITSCREEN;
812 _ecore_wl2_screen_capability_set(ews, capability);
815 static const struct wtz_screen_listener _wtz_screen_listener =
817 .size = _wtz_screen_cb_size,
818 .name = _wtz_screen_cb_name,
819 .capabilities = _wtz_screen_cb_capabilities,
824 _cb_global_event_free(void *data EINA_UNUSED, void *event)
826 Ecore_Wl2_Event_Global *ev;
829 eina_stringshare_del(ev->interface);
830 ecore_wl2_display_disconnect(ev->display);
835 _cb_global_add(void *data, struct wl_registry *registry, unsigned int id, const char *interface, unsigned int version)
837 Ecore_Wl2_Display *ewd;
838 Ecore_Wl2_Event_Global *ev;
840 int client_version = 1;
843 //TIZEN_ONLY(2023): ecore_Wl2: improved Wayland issues handling
846 EINA_LOG_ERR("No data provided for global add event");
853 /* test to see if we have already added this global to our hash */
854 if (!eina_hash_find(ewd->globals, &id))
856 Ecore_Wl2_Global *global;
858 /* allocate space for new global */
859 global = calloc(1, sizeof(Ecore_Wl2_Global));
863 global->interface = eina_stringshare_add(interface);
864 global->version = version;
866 /* add this global to our hash */
867 if (!eina_hash_add(ewd->globals, &global->id, global))
869 eina_stringshare_del(global->interface);
876 if (!strcmp(interface, "wl_compositor"))
878 Ecore_Wl2_Window *window;
879 ewd->wl.compositor_version = MIN(version, 4);
881 wl_registry_bind(registry, id, &wl_compositor_interface,
882 ewd->wl.compositor_version);
884 //TIZEN_ONLY(2023): ecore_wl2: improved Wayland issues handling
885 if (ewd->wl.compositor == NULL)
887 EINA_LOG_ERR("Failed to bind wl_compositor");
892 EINA_INLIST_FOREACH(ewd->windows, window)
893 _ecore_wl2_window_surface_create(window);
895 else if (!strcmp(interface, "wl_subcompositor"))
897 ewd->wl.subcompositor =
898 wl_registry_bind(registry, id, &wl_subcompositor_interface, 1);
900 else if (!strcmp(interface, "wl_shm"))
903 wl_registry_bind(registry, id, &wl_shm_interface, 1);
905 else if (!strcmp(interface, "zwp_linux_dmabuf_v1") && (version >= 2))
908 wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, 2);
909 zwp_linux_dmabuf_v1_add_listener(ewd->wl.dmabuf, &_dmabuf_listener, ewd);
910 _ecore_wl2_buffer_test(ewd);
911 _ecore_wl2_display_sync_add(ewd);
913 else if (!strcmp(interface, "wl_data_device_manager"))
915 ewd->wl.data_device_manager_version = MIN(version, 3);
916 ewd->wl.data_device_manager =
917 wl_registry_bind(registry, id, &wl_data_device_manager_interface, ewd->wl.data_device_manager_version);
919 else if ((eina_streq(interface, "www")) &&
920 (getenv("EFL_WAYLAND_ENABLE_WWW")))
922 Ecore_Wl2_Window *window;
924 ewd->wl.www = wl_registry_bind(registry, id, &www_interface, 1);
925 EINA_INLIST_FOREACH(ewd->windows, window)
926 _ecore_wl2_window_www_surface_init(window);
928 else if ((!strcmp(interface, "zwp_e_session_recovery")) &&
929 (!no_session_recovery))
931 ewd->wl.session_recovery =
932 wl_registry_bind(registry, id,
933 &zwp_e_session_recovery_interface, 1);
934 zwp_e_session_recovery_add_listener(ewd->wl.session_recovery,
935 &_session_listener, ewd);
937 else if (!strcmp(interface, "efl_aux_hints"))
939 Ecore_Wl2_Window *window;
940 ewd->wl.efl_aux_hints =
941 wl_registry_bind(registry, id,
942 &efl_aux_hints_interface, 1);
943 efl_aux_hints_add_listener(ewd->wl.efl_aux_hints, &_aux_hints_listener, ewd);
944 EINA_INLIST_FOREACH(ewd->windows, window)
945 if (window->surface) efl_aux_hints_get_supported_aux_hints(ewd->wl.efl_aux_hints, window->surface);
947 else if (!strcmp(interface, "zwp_teamwork"))
950 wl_registry_bind(registry, id,
951 &zwp_teamwork_interface, EFL_TEAMWORK_VERSION);
953 else if (!strcmp(interface, "wl_output"))
954 _ecore_wl2_output_add(ewd, id);
955 else if (!strcmp(interface, "wl_seat"))
956 _ecore_wl2_input_add(ewd, id, version);
957 else if (!strcmp(interface, "efl_hints"))
959 Ecore_Wl2_Window *window;
961 ewd->wl.efl_hints = wl_registry_bind(registry, id, &efl_hints_interface, MIN(version, 2));
962 EINA_INLIST_FOREACH(ewd->windows, window)
964 if (!window->xdg_surface) continue;
965 if (window->aspect.set)
966 efl_hints_set_aspect(window->display->wl.efl_hints, window->xdg_surface,
967 window->aspect.w, window->aspect.h, window->aspect.aspect);
968 if (window->weight.set)
969 efl_hints_set_weight(window->display->wl.efl_hints,
970 window->xdg_surface, window->weight.w, window->weight.h);
973 // TIZEN_ONLY : To use tizen protocols
974 else if (!strcmp(interface, "tizen_policy"))
979 client_version = version;
982 wl_registry_bind(registry, id, &tizen_policy_interface, client_version);
983 if (ewd->wl.tz_policy)
984 tizen_policy_add_listener(ewd->wl.tz_policy, &_tizen_policy_listener, ewd);
986 else if (!strcmp(interface, "tizen_policy_ext"))
991 client_version = version;
993 ewd->wl.tz_policy_ext =
994 wl_registry_bind(registry, id, &tizen_policy_ext_interface, client_version);
995 if (ewd->wl.tz_policy_ext)
996 tizen_policy_ext_add_listener(ewd->wl.tz_policy_ext, &_tizen_policy_ext_listener, ewd);
998 else if (!strcmp(interface, "tizen_surface"))
1001 wl_registry_bind(registry, id, &tizen_surface_interface, 1);
1003 else if (!strcmp(interface, "tizen_effect"))
1006 wl_registry_bind(registry, id, &tizen_effect_interface, 1);
1007 if (ewd->wl.tz_effect)
1008 tizen_effect_add_listener(ewd->wl.tz_effect, &_tizen_effect_listener, ewd->wl.display);
1010 else if (!strcmp(interface, "tizen_indicator"))
1012 ewd->wl.tz_indicator =
1013 wl_registry_bind(registry, id, &tizen_indicator_interface, 1);
1014 if (ewd->wl.tz_indicator)
1015 tizen_indicator_add_listener(ewd->wl.tz_indicator, &_tizen_indicator_listener, ewd);
1017 else if (!strcmp(interface, "tizen_clipboard"))
1022 client_version = version;
1024 ewd->wl.tz_clipboard =
1025 wl_registry_bind(registry, id, &tizen_clipboard_interface, client_version);
1027 if (ewd->wl.tz_clipboard)
1028 tizen_clipboard_add_listener(ewd->wl.tz_clipboard, &_tizen_clipboard_listener, ewd);
1030 // TIZEN_ONLY(20171107): support a tizen_keyrouter interface
1031 else if (!strcmp(interface, "tizen_keyrouter"))
1033 _ecore_wl2_keyrouter_setup(ewd, id, version);
1036 // TIZEN_ONLY(20171109): support a tizen_input_device_manager interface
1037 else if (!strcmp(interface, "tizen_input_device_manager"))
1039 _ecore_wl2_input_device_manager_setup(ewd, id, version);
1042 //TIZEN_ONLY(20171115): support output transform
1043 else if (!strcmp(interface, "tizen_screen_rotation"))
1045 ewd->wl.tz_screen_rotation =
1046 wl_registry_bind(registry, id, &tizen_screen_rotation_interface, 1);
1047 if (ewd->wl.tz_screen_rotation)
1048 tizen_screen_rotation_add_listener(ewd->wl.tz_screen_rotation, &_tizen_screen_rotation_listener, ewd->wl.display);
1051 //TIZEN_ONLY(20180810): support client driven move resize
1052 else if (!strcmp(interface, "tizen_move_resize"))
1054 ewd->wl.tz_moveresize =
1055 wl_registry_bind(registry, id, &tizen_move_resize_interface, 1);
1056 if (ewd->wl.tz_moveresize)
1057 tizen_move_resize_add_listener(ewd->wl.tz_moveresize, &_tizen_move_resize_listener, ewd->wl.display);
1060 // TIZEN_ONLY(20190430): support client appinfo
1061 else if (!strcmp(interface, "tizen_launch_appinfo"))
1063 ewd->wl.tz_appinfo =
1064 wl_registry_bind(registry, id, &tizen_launch_appinfo_interface, 1);
1065 if (ewd->wl.tz_appinfo)
1066 tizen_launch_appinfo_add_listener(ewd->wl.tz_appinfo, &_tizen_launch_appinfo_listener, ewd->wl.display);
1069 //TIZEN_ONLY(20200626): support tizen_renderer
1070 else if (!strcmp(interface, "tizen_renderer"))
1072 ewd->wl.tz_renderer =
1073 wl_registry_bind(registry, id, &tizen_renderer_interface, 1);
1076 //TIZEN_ONLY(20230312): support wtz_screen
1077 else if (!strcmp(interface, "wtz_screen"))
1079 if (ewd->wl.wtz_scr)
1081 // TODO : support multi wtz_screen
1085 wl_registry_bind(registry, id, &wtz_screen_interface, 1);
1086 if (ewd->wl.wtz_scr)
1087 wtz_screen_add_listener(ewd->wl.wtz_scr, &_wtz_screen_listener, ewd);
1090 // TIZEN_ONLY(20230801) : support zwp relative pointer protocol
1091 else if (!strcmp(interface, "zwp_relative_pointer_manager_v1"))
1093 ewd->wl.relative_pointer_manager =
1094 wl_registry_bind(registry, id,
1095 &zwp_relative_pointer_manager_v1_interface, version);
1098 // TIZEN_ONLY(20230801) : support zwp pointer constraints protocol
1099 else if (!strcmp(interface, "zwp_pointer_constraints_v1"))
1101 ewd->wl.pointer_constraints =
1102 wl_registry_bind(registry, id,
1103 &zwp_pointer_constraints_v1_interface, version);
1109 /* allocate space for event structure */
1110 ev = calloc(1, sizeof(Ecore_Wl2_Event_Global));
1116 ev->version = version;
1117 ev->interface = eina_stringshare_add(interface);
1119 /* raise an event saying a new global has been added */
1120 ecore_event_add(ECORE_WL2_EVENT_GLOBAL_ADDED, ev,
1121 _cb_global_event_free, NULL);
1124 //TIZEN_ONLY(2023): ecore_wl2: improved Wayland issues handlin
1126 EINA_LOG_ERR("Failed to create global for registry : %p, id: %d, interface: %s, version: %d", registry, id, interface, version);
1131 _cb_global_remove(void *data, struct wl_registry *registry EINA_UNUSED, unsigned int id)
1133 Ecore_Wl2_Display *ewd;
1134 Ecore_Wl2_Global *global;
1135 Ecore_Wl2_Event_Global *ev;
1139 /* try to find this global in our hash */
1140 global = eina_hash_find(ewd->globals, &id);
1141 if (!global) return;
1143 /* allocate space for event structure */
1144 ev = calloc(1, sizeof(Ecore_Wl2_Event_Global));
1150 ev->version = global->version;
1151 ev->interface = eina_stringshare_add(global->interface);
1153 /* raise an event saying a global has been removed */
1154 ecore_event_add(ECORE_WL2_EVENT_GLOBAL_REMOVED, ev,
1155 _cb_global_event_free, NULL);
1157 /* delete this global from our hash */
1158 if (ewd->globals) eina_hash_del_by_key(ewd->globals, &id);
1161 static const struct wl_registry_listener _registry_listener =
1168 _cb_create_data(void *data, Ecore_Fd_Handler *hdl EINA_UNUSED)
1170 Ecore_Wl2_Display *ewd = data;
1171 struct wl_event_loop *loop;
1173 loop = wl_display_get_event_loop(ewd->wl.display);
1174 wl_event_loop_dispatch(loop, 0);
1176 /* wl_display_flush_clients(ewd->wl.display); */
1178 return ECORE_CALLBACK_RENEW;
1182 _cb_create_prepare(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
1184 Ecore_Wl2_Display *ewd = data;
1186 wl_display_flush_clients(ewd->wl.display);
1190 _recovery_timer(Ecore_Wl2_Display *ewd)
1192 if (!_ecore_wl2_display_connect(ewd, 1))
1195 ewd->recovery_timer = NULL;
1200 _ecore_wl2_display_globals_cleanup(Ecore_Wl2_Display *ewd)
1202 if (ewd->wl.session_recovery)
1203 zwp_e_session_recovery_destroy(ewd->wl.session_recovery);
1204 if (ewd->wl.www) www_destroy(ewd->wl.www);
1205 if (ewd->wl.xdg_wm_base) xdg_wm_base_destroy(ewd->wl.xdg_wm_base);
1206 if (ewd->wl.zxdg_shell) zxdg_shell_v6_destroy(ewd->wl.zxdg_shell);
1207 if (ewd->wl.shm) wl_shm_destroy(ewd->wl.shm);
1208 if (ewd->wl.data_device_manager)
1209 wl_data_device_manager_destroy(ewd->wl.data_device_manager);
1210 if (ewd->wl.compositor) wl_compositor_destroy(ewd->wl.compositor);
1211 if (ewd->wl.subcompositor) wl_subcompositor_destroy(ewd->wl.subcompositor);
1212 if (ewd->wl.dmabuf) zwp_linux_dmabuf_v1_destroy(ewd->wl.dmabuf);
1213 if (ewd->wl.efl_aux_hints) efl_aux_hints_destroy(ewd->wl.efl_aux_hints);
1214 if (ewd->wl.efl_hints) efl_hints_destroy(ewd->wl.efl_hints);
1218 if (ewd->wl.tz_policy) tizen_policy_destroy(ewd->wl.tz_policy);
1219 if (ewd->wl.tz_policy_ext) tizen_policy_ext_destroy(ewd->wl.tz_policy_ext);
1220 if (ewd->wl.tz_surf) tizen_surface_destroy(ewd->wl.tz_surf);
1221 if (ewd->wl.tz_effect) tizen_effect_destroy(ewd->wl.tz_effect);
1222 if (ewd->wl.tz_indicator) tizen_indicator_destroy(ewd->wl.tz_indicator);
1223 if (ewd->wl.tz_clipboard) tizen_clipboard_destroy(ewd->wl.tz_clipboard);
1224 if (ewd->wl.tz_screen_rotation) tizen_screen_rotation_destroy(ewd->wl.tz_screen_rotation);
1225 if (ewd->wl.tz_moveresize) tizen_move_resize_destroy(ewd->wl.tz_moveresize);
1226 if (ewd->wl.tz_video) tizen_video_destroy(ewd->wl.tz_video);
1227 if (ewd->wl.tz_renderer) tizen_renderer_destroy(ewd->wl.tz_renderer);
1228 if (ewd->wl.wtz_scr) wtz_screen_destroy(ewd->wl.wtz_scr);
1229 if (ewd->wl.relative_pointer_manager)
1230 zwp_relative_pointer_manager_v1_destroy(ewd->wl.relative_pointer_manager);
1231 if (ewd->wl.pointer_constraints)
1232 zwp_pointer_constraints_v1_destroy(ewd->wl.pointer_constraints);
1235 if (ewd->wl.registry) wl_registry_destroy(ewd->wl.registry);
1239 _recovery_timer_add(Ecore_Wl2_Display *ewd)
1241 Eina_Inlist *tmp, *tmp2;
1242 Ecore_Wl2_Output *output;
1243 Ecore_Wl2_Input *input;
1244 Ecore_Wl2_Window *window;
1246 eina_hash_free_buckets(ewd->globals);
1247 ecore_idle_enterer_del(ewd->idle_enterer);
1248 ewd->idle_enterer = NULL;
1250 // TIZEN_ONLY(20171129): thread-safety for wl
1251 ecore_main_awake_handler_del(_ecore_wl_cb_awake);
1252 // End of TIZEN_ONLY(20171129)
1253 ecore_main_fd_handler_del(ewd->fd_hdl);
1256 ewd->shell_done = EINA_FALSE;
1257 ewd->sync_done = EINA_FALSE;
1258 ewd->recovering = EINA_TRUE;
1260 _ecore_wl2_display_globals_cleanup(ewd);
1262 memset(&ewd->wl, 0, sizeof(ewd->wl));
1263 EINA_INLIST_FOREACH_SAFE(ewd->inputs, tmp, input)
1264 _ecore_wl2_input_del(input);
1266 EINA_INLIST_FOREACH_SAFE(ewd->outputs, tmp, output)
1267 _ecore_wl2_output_del(output);
1269 EINA_INLIST_FOREACH_SAFE(ewd->windows, tmp, window)
1271 Ecore_Wl2_Subsurface *subsurf;
1273 EINA_INLIST_FOREACH_SAFE(window->subsurfs, tmp2, subsurf)
1274 _ecore_wl2_subsurf_unmap(subsurf);
1275 _ecore_wl2_window_semi_free(window);
1276 window->set_config.serial = 0;
1277 window->req_config.serial = 0;
1278 window->xdg_configure_ack = NULL;
1279 window->xdg_set_min_size = NULL;
1280 window->xdg_set_max_size = NULL;
1281 window->zxdg_configure_ack = NULL;
1282 window->zxdg_set_min_size = NULL;
1283 window->zxdg_set_max_size = NULL;
1286 ewd->recovery_timer =
1287 ecore_timer_add(0.5, (Ecore_Task_Cb)_recovery_timer, ewd);
1288 _ecore_wl2_display_event(ewd, ECORE_WL2_EVENT_DISCONNECT);
1292 _begin_recovery_maybe(Ecore_Wl2_Display *ewd, int code)
1294 if ((_server_displays || (code != EPROTO)) && ewd->wl.session_recovery)// && (errno == EPIPE))
1295 _recovery_timer_add(ewd);
1296 else if (!_server_displays)
1298 ERR("Wayland Socket Error: %s", eina_error_msg_get(errno));
1299 _ecore_wl2_display_signal_exit();
1303 // TIZEN_ONLY(20171129): thread-safety for wl
1305 _ecore_wl_cb_pre_handle_data(void *data, Ecore_Fd_Handler *hdl EINA_UNUSED)
1307 Ecore_Wl2_Display *ewd = (Ecore_Wl2_Display *)data;
1309 EINA_SAFETY_ON_NULL_RETURN(ewd);
1311 if (ewd->prepare_read) return;
1314 while (wl_display_prepare_read(ewd->wl.display) != 0)
1316 ret = wl_display_dispatch_pending(ewd->wl.display);
1319 ERR("Wayland Display Dispatch Pending Failed");
1324 wl_display_flush(ewd->wl.display);
1326 ewd->prepare_read = EINA_TRUE;
1330 _ecore_wl_cb_awake(void *data)
1332 Ecore_Wl2_Display *ewd = (Ecore_Wl2_Display *)data;
1334 EINA_SAFETY_ON_NULL_RETURN(ewd);
1335 EINA_SAFETY_ON_NULL_RETURN(ewd->fd_hdl);
1337 if (!ewd->prepare_read) return;
1339 ewd->prepare_read = EINA_FALSE;
1341 if (ecore_main_fd_handler_active_get(ewd->fd_hdl, ECORE_FD_ERROR))
1343 ERR("[ecore_wl_cb_awake] Received error on wayland display fd");
1344 wl_display_cancel_read(ewd->wl.display);
1348 if (ecore_main_fd_handler_active_get(ewd->fd_hdl, ECORE_FD_READ))
1349 wl_display_read_events(ewd->wl.display);
1351 wl_display_cancel_read(ewd->wl.display);
1353 // End of TIZEN_ONLY(20171129)
1356 _cb_connect_data(void *data, Ecore_Fd_Handler *hdl)
1358 // TIZEN_ONLY(20171129): thread-safety for wl
1359 Ecore_Wl2_Display *ewd = (Ecore_Wl2_Display *)data;
1362 EINA_SAFETY_ON_NULL_RETURN_VAL(ewd, ECORE_CALLBACK_CANCEL);
1363 EINA_SAFETY_ON_NULL_RETURN_VAL(ewd->fd_hdl, ECORE_CALLBACK_CANCEL);
1365 if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_ERROR))
1367 ERR("Received error on wayland display fd");
1371 if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_READ))
1372 ret = wl_display_dispatch_pending(ewd->wl.display);
1373 else if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_WRITE))
1375 ret = wl_display_flush(ewd->wl.display);
1377 ecore_main_fd_handler_active_set(hdl, ECORE_FD_READ);
1380 if ((ret < 0) && (errno != EAGAIN) && (errno != EINVAL))
1383 return ECORE_CALLBACK_RENEW;
1387 _begin_recovery_maybe(ewd, errno);
1389 return ECORE_CALLBACK_CANCEL;
1390 // End of TIZEN_ONLY(20171129)
1394 _cb_globals_hash_del(void *data)
1396 Ecore_Wl2_Global *global;
1400 eina_stringshare_del(global->interface);
1406 _cb_connect_idle(void *data)
1408 Ecore_Wl2_Display *ewd = data;
1411 ret = wl_display_get_error(ewd->wl.display);
1413 if (ret < 0) goto err;
1415 ret = wl_display_dispatch_pending(ewd->wl.display);
1417 if (ret < 0) goto err;
1419 return ECORE_CALLBACK_RENEW;
1422 if ((ret < 0) && (code != EAGAIN))
1424 ewd->idle_enterer = NULL;
1425 _begin_recovery_maybe(ewd, code);
1427 return ECORE_CALLBACK_CANCEL;
1430 return ECORE_CALLBACK_RENEW;
1433 static Ecore_Wl2_Global *
1434 _ecore_wl2_global_find(Ecore_Wl2_Display *ewd, const char *interface)
1437 Ecore_Wl2_Global *global = NULL, *g = NULL;
1439 itr = eina_hash_iterator_data_new(ewd->globals);
1440 if (!itr) return NULL;
1442 EINA_ITERATOR_FOREACH(itr, g)
1444 if (!strcmp(g->interface, interface))
1451 eina_iterator_free(itr);
1456 _ecore_wl2_shell_bind(Ecore_Wl2_Display *ewd)
1458 Ecore_Wl2_Global *global = NULL;
1460 const char *shells[] =
1467 if (ewd->shell_done) return;
1469 for (itr = shells; *itr != NULL; itr++)
1471 global = _ecore_wl2_global_find(ewd, *itr);
1472 if (!global) continue;
1476 if (!global) return;
1478 if (!strcmp(global->interface, "xdg_wm_base"))
1480 ewd->wl.xdg_wm_base =
1481 wl_registry_bind(ewd->wl.registry, global->id,
1482 &xdg_wm_base_interface, 1);
1483 xdg_wm_base_add_listener(ewd->wl.xdg_wm_base,
1484 &_xdg_shell_listener, ewd);
1485 ewd->shell_done = EINA_TRUE;
1487 else if (!strcmp(global->interface, "zxdg_shell_v6"))
1489 ewd->wl.zxdg_shell =
1490 wl_registry_bind(ewd->wl.registry, global->id,
1491 &zxdg_shell_v6_interface, 1);
1492 zxdg_shell_v6_add_listener(ewd->wl.zxdg_shell,
1493 &_zxdg_shell_listener, ewd);
1494 ewd->shell_done = EINA_TRUE;
1499 _cb_sync_done(void *data, struct wl_callback *cb, uint32_t serial EINA_UNUSED)
1501 Ecore_Wl2_Event_Sync_Done *ev;
1502 Ecore_Wl2_Display *ewd;
1505 if (--ewd->syncs) return;
1506 if (ewd->sync_done) return;
1508 ewd->sync_done = EINA_TRUE;
1510 _ecore_wl2_shell_bind(ewd);
1512 wl_callback_destroy(cb);
1513 ecore_wl2_display_flush(ewd);
1515 ev = calloc(1, sizeof(Ecore_Wl2_Event_Sync_Done));
1520 ecore_event_add(ECORE_WL2_EVENT_SYNC_DONE, ev, _display_event_free, ewd);
1523 static const struct wl_callback_listener _sync_listener =
1528 // TIZEN_ONLY(20171110): wait until sync done is called in ecore_wl2_display_sync
1530 _cb_tz_sync_done(void *data, struct wl_callback *cb, uint32_t serial EINA_UNUSED)
1532 Ecore_Wl2_Display *ewd;
1536 ewd->sync_ref_count--;
1538 wl_callback_destroy(cb);
1541 static const struct wl_callback_listener _tz_sync_listener =
1547 _ecore_wl2_disconnected(int error)
1549 if (error == EPIPE ||
1550 error == ECONNRESET)
1557 _ecore_wl2_signal_exit(void)
1559 Ecore_Event_Signal_Exit *ev;
1561 if (!(ev = calloc(1, sizeof(Ecore_Event_Signal_Exit))))
1565 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, ev, NULL, NULL);
1569 _ecore_wl2_display_dispatch_error(Ecore_Wl2_Display *ewd)
1571 uint32_t ecode = 0, id = 0;
1572 const struct wl_interface *intf = NULL;
1576 /* write out message about protocol error */
1577 ecode = wl_display_get_protocol_error(ewd->wl.display, &intf, &id);
1580 ERR("Wayland Client: Got protocol error %u on interface %s"
1581 " (object %u)\n", ecode, intf->name, id);
1583 /* raise exit signal */
1584 last_err = wl_display_get_error(ewd->wl.display);
1585 if (_ecore_wl2_disconnected(errno) || _ecore_wl2_disconnected(last_err))
1588 if (last_err) _err = last_err;
1589 str = eina_error_msg_get(_err);
1590 ERR("Disconnected from a wayland compositor : error:(%d) %s", _err, str);
1591 _ecore_wl2_signal_exit();
1596 str = eina_error_msg_get(errno);
1597 ERR("wayland socket error:(%d) %s", errno, str);
1603 ecore_wl2_display_sync(Ecore_Wl2_Display *display)
1605 //TIZEN_ONLY(20230428) Improved safety of ecore_wl2_display_sync
1606 struct wl_callback *cb = NULL;
1611 EINA_SAFETY_ON_NULL_RETURN(display);
1612 EINA_SAFETY_ON_NULL_RETURN(display->wl.display);
1614 display->sync_ref_count++;
1615 cb = wl_display_sync(display->wl.display);
1616 //TIZEN_ONLY(20230428) Improved safety of ecore_wl2_display_sync
1619 errno = wl_display_get_error(display->wl.display);
1620 ERR("Disconnected from a wayland compositor : %s", eina_error_msg_get(errno));
1621 _ecore_wl2_signal_exit();
1625 wl_callback_add_listener(cb, &_tz_sync_listener, display);
1627 while (display->sync_ref_count > 0)
1629 last_dpy_err = wl_display_get_error(display->wl.display);
1630 if (_ecore_wl2_disconnected(last_dpy_err))
1632 errno = last_dpy_err;
1633 ERR("Disconnected from a wayland compositor : %s", eina_error_msg_get(errno));
1634 _ecore_wl2_signal_exit();
1637 ret = wl_display_dispatch(display->wl.display);
1638 if ((ret < 0) && (errno != EAGAIN))
1640 _ecore_wl2_display_dispatch_error(display);
1647 //TIZEN_ONLY(20171108): add a new API to ecore_wl2_sync
1649 ecore_wl2_sync(void)
1651 Ecore_Wl2_Display *ewd;
1653 ewd = ecore_wl2_connected_display_get(NULL);
1656 ecore_wl2_display_sync(ewd);
1661 _ecore_wl2_display_sync_add(Ecore_Wl2_Display *ewd)
1663 struct wl_callback *cb;
1666 cb = wl_display_sync(ewd->wl.display);
1667 wl_callback_add_listener(cb, &_sync_listener, ewd);
1670 #define RUN_WM_READY_FILE "/run/.wm_ready"
1673 _ecore_wl2_display_wait(Ecore_Wl2_Display *ewd)
1680 unsigned char buf[128];
1681 struct inotify_event *event;
1683 fd = inotify_init();
1684 if (fd == -1) return EINA_FALSE;
1686 wd = inotify_add_watch(fd, RUN_WM_READY_FILE, IN_MODIFY | IN_CREATE);
1693 if (access(RUN_WM_READY_FILE, F_OK) == 0)
1695 ERR("The server is ready");
1696 inotify_rm_watch(fd, wd);
1701 ERR("Wait for the server to be ready.[fd: %d, wd: %d", fd, wd);
1702 size = read(fd, buf, sizeof(buf));
1703 while ((i + sizeof(struct inotify_event)) <= size)
1705 event = (struct inotify_event *)&buf[i];
1706 event_size = sizeof(struct inotify_event) + event->len;
1707 if ((event_size + i) > size || (event_size + i) <= 0) break;
1709 if (event->mask & IN_CREATE | event->mask & IN_MODIFY) break;
1712 inotify_rm_watch(fd, wd);
1718 _ecore_wl2_display_connect(Ecore_Wl2_Display *ewd, Eina_Bool sync)
1720 /* try to connect to wayland display with this name */
1721 ewd->wl.display = wl_display_connect(ewd->name);
1722 if (!ewd->wl.display) {
1723 #ifdef HAVE_SYS_INOTIFY_H
1724 if (!_ecore_wl2_display_wait(ewd)) return EINA_FALSE;
1726 ewd->wl.display = wl_display_connect(ewd->name);
1727 ERR("Server is ready, wl.display is created %p", ewd->wl.display);
1733 ewd->recovering = EINA_FALSE;
1735 ewd->wl.registry = wl_display_get_registry(ewd->wl.display);
1736 wl_registry_add_listener(ewd->wl.registry, &_registry_listener, ewd);
1738 _ecore_wl2_display_sync_add(ewd);
1742 /* NB: If we are connecting (as a client), then we will need to setup
1743 * a callback for display_sync and wait for it to complete. There is no
1744 * other option here as we need the compositor, shell, etc, to be setup
1745 * before we can allow a user to make use of the API functions */
1746 while (!ewd->sync_done)
1750 ret = wl_display_dispatch(ewd->wl.display);
1751 if ((ret < 0) && (errno != EAGAIN))
1753 ERR("Received Fatal Error on Wayland Display");
1755 wl_registry_destroy(ewd->wl.registry);
1762 ecore_main_fd_handler_add(wl_display_get_fd(ewd->wl.display),
1763 ECORE_FD_READ | ECORE_FD_WRITE | ECORE_FD_ERROR,
1764 _cb_connect_data, ewd, NULL, NULL);
1766 // TIZEN_ONLY(20180109): check null condition
1769 ERR("Fail to add ecore fd(%d, wl.display) handler", wl_display_get_fd(ewd->wl.display));
1772 wl_registry_destroy(ewd->wl.registry);
1773 wl_display_disconnect(ewd->wl.display);
1774 ewd->wl.registry = NULL;
1775 ewd->wl.display = NULL;
1779 // End of TIZEN_ONLY(20180109)
1781 ewd->idle_enterer = ecore_idle_enterer_add(_cb_connect_idle, ewd);
1782 // TIZEN_ONLY(20171129): thread-safety for wl
1783 ecore_main_fd_handler_prepare_callback_set
1784 (ewd->fd_hdl, _ecore_wl_cb_pre_handle_data, ewd);
1786 ecore_main_awake_handler_add(_ecore_wl_cb_awake, ewd);
1787 // End of TIZEN_ONLY(20171129)
1788 _ecore_wl2_display_event(ewd, ECORE_WL2_EVENT_CONNECT);
1793 _ecore_wl2_display_cleanup(Ecore_Wl2_Display *ewd)
1795 Ecore_Wl2_Output *output;
1796 Ecore_Wl2_Input *input;
1799 if (ewd->xkb_context) xkb_context_unref(ewd->xkb_context);
1801 /* free each input */
1802 EINA_INLIST_FOREACH_SAFE(ewd->inputs, tmp, input)
1803 _ecore_wl2_input_del(input);
1805 /* free each output */
1806 EINA_INLIST_FOREACH_SAFE(ewd->outputs, tmp, output)
1807 _ecore_wl2_output_del(output);
1809 if (ewd->idle_enterer) ecore_idle_enterer_del(ewd->idle_enterer);
1811 // TIZEN_ONLY(20171129): thread-safety for wl
1812 ecore_main_awake_handler_del(_ecore_wl_cb_awake);
1813 // End of TIZEN_ONLY(20171129)
1815 if (ewd->fd_hdl) ecore_main_fd_handler_del(ewd->fd_hdl);
1817 eina_hash_free(ewd->globals);
1819 //TIZEN_ONLY(20230312): support wtz_screen
1821 _ecore_wl2_screen_del(ewd->screen);
1824 _ecore_wl2_display_globals_cleanup(ewd);
1828 _ecore_wl2_display_window_surface_find(Ecore_Wl2_Display *display, struct wl_surface *wl_surface)
1830 Ecore_Wl2_Window *window;
1832 if ((!display) || (!wl_surface)) return NULL;
1834 EINA_INLIST_FOREACH(display->windows, window)
1836 if ((window->surface) &&
1837 (window->surface == wl_surface))
1844 EAPI Ecore_Wl2_Display *
1845 ecore_wl2_display_create(const char *name)
1847 Ecore_Wl2_Display *ewd;
1848 struct wl_event_loop *loop;
1850 if (!_server_displays)
1851 _server_displays = eina_hash_string_superfast_new(NULL);
1855 /* someone wants to create a server with a specific display */
1857 /* check hash of cached server displays for this name */
1858 ewd = eina_hash_find(_server_displays, name);
1859 if (ewd) goto found;
1862 /* allocate space for display structure */
1863 ewd = calloc(1, sizeof(Ecore_Wl2_Display));
1864 if (!ewd) return NULL;
1867 ewd->pid = getpid();
1869 /* try to create new wayland display */
1870 ewd->wl.display = wl_display_create();
1871 if (!ewd->wl.display)
1873 ERR("Could not create wayland display");
1881 n = wl_display_add_socket_auto(ewd->wl.display);
1884 ERR("Failed to add display socket");
1888 ewd->name = strdup(n);
1892 if (wl_display_add_socket(ewd->wl.display, name))
1894 ERR("Failed to add display socket");
1898 ewd->name = strdup(name);
1901 setenv("WAYLAND_DISPLAY", ewd->name, 1);
1902 DBG("WAYLAND_DISPLAY: %s", ewd->name);
1904 loop = wl_display_get_event_loop(ewd->wl.display);
1907 ecore_main_fd_handler_add(wl_event_loop_get_fd(loop),
1908 ECORE_FD_READ | ECORE_FD_ERROR,
1909 _cb_create_data, ewd, NULL, NULL);
1911 ecore_main_fd_handler_prepare_callback_set(ewd->fd_hdl,
1912 _cb_create_prepare, ewd);
1914 /* add this new server display to hash */
1915 eina_hash_add(_server_displays, ewd->name, ewd);
1920 wl_display_destroy(ewd->wl.display);
1932 _ecore_wl2_display_sync_get(void)
1934 return !_server_displays || !eina_hash_population(_server_displays);
1937 EAPI Ecore_Wl2_Display *
1938 ecore_wl2_display_connect(const char *name)
1940 Ecore_Wl2_Display *ewd;
1942 Eina_Bool hash_create = !_client_displays;
1944 if (!_client_displays)
1945 _client_displays = eina_hash_string_superfast_new(NULL);
1949 /* client wants to connect to default display */
1950 n = getenv("WAYLAND_DISPLAY");
1951 if (!n) n = "wayland-0";
1953 /* we have a default wayland display */
1955 /* check hash of cached client displays for this name */
1956 ewd = eina_hash_find(_client_displays, n);
1957 if (ewd) goto found;
1961 /* client wants to connect to specific display */
1963 /* check hash of cached client displays for this name */
1964 ewd = eina_hash_find(_client_displays, name);
1965 if (ewd) goto found;
1968 /* allocate space for display structure */
1969 ewd = calloc(1, sizeof(Ecore_Wl2_Display));
1970 if (!ewd) return NULL;
1975 ewd->name = strdup(name);
1977 ewd->name = strdup(n);
1979 ewd->globals = eina_hash_int32_new(_cb_globals_hash_del);
1981 ewd->xkb_context = xkb_context_new(0);
1982 if (!ewd->xkb_context) goto context_err;
1984 /* check server display hash and match on pid. If match, skip sync */
1985 if (!_ecore_wl2_display_connect(ewd, _ecore_wl2_display_sync_get()))
1988 /* add this new client display to hash */
1989 eina_hash_add(_client_displays, ewd->name, ewd);
1994 xkb_context_unref(ewd->xkb_context);
1995 ewd->xkb_context = NULL;
2000 eina_hash_free(ewd->globals);
2007 eina_hash_free(_client_displays);
2008 _client_displays = NULL;
2018 ecore_wl2_display_disconnect(Ecore_Wl2_Display *display)
2020 EINA_SAFETY_ON_NULL_RETURN(display);
2025 ret = wl_display_dispatch_pending(display->wl.display);
2029 if (display->refs == 0)
2031 _ecore_wl2_display_cleanup(display);
2033 wl_display_disconnect(display->wl.display);
2035 /* remove this client display from hash */
2036 eina_hash_del_by_key(_client_displays, display->name);
2038 free(display->name);
2044 ecore_wl2_display_destroy(Ecore_Wl2_Display *display)
2046 EINA_SAFETY_ON_NULL_RETURN(display);
2049 if (display->refs == 0)
2051 /* this ensures that things like wl_registry are destroyed
2052 * before we destroy the actual wl_display */
2053 _ecore_wl2_display_cleanup(display);
2055 wl_display_destroy(display->wl.display);
2057 /* remove this client display from hash */
2058 eina_hash_del_by_key(_server_displays, display->name);
2059 ecore_timer_del(display->recovery_timer);
2061 free(display->name);
2067 ecore_wl2_display_terminate(Ecore_Wl2_Display *display)
2069 EINA_SAFETY_ON_NULL_RETURN(display);
2070 wl_display_terminate(display->wl.display);
2073 EAPI struct wl_display *
2074 ecore_wl2_display_get(Ecore_Wl2_Display *display)
2076 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2077 return display->wl.display;
2080 // TIZEN_ONLY(20190807): Retrieve the existing native wayland display
2082 ecore_wl2_display_native_get(Ecore_Wl2_Display *display)
2084 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2085 return (void *)display->wl.display;
2089 EAPI struct wl_shm *
2090 ecore_wl2_display_shm_get(Ecore_Wl2_Display *display)
2092 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2093 return display->wl.shm;
2097 ecore_wl2_display_dmabuf_get(Ecore_Wl2_Display *display)
2099 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2100 return display->wl.dmabuf;
2103 EAPI Eina_Iterator *
2104 ecore_wl2_display_globals_get(Ecore_Wl2_Display *display)
2106 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2107 EINA_SAFETY_ON_NULL_RETURN_VAL(display->globals, NULL);
2109 return eina_hash_iterator_data_new(display->globals);
2113 ecore_wl2_display_screen_size_get(Ecore_Wl2_Display *display, int *w, int *h)
2115 Ecore_Wl2_Output *output;
2117 // TIZEN_ONLY(20190430): support client appinfo
2121 EINA_SAFETY_ON_NULL_RETURN(display);
2126 // TIZEN_ONLY(20220407): Gets the screen size of all screens
2127 EINA_INLIST_FOREACH(display->outputs, output)
2129 switch (output->transform)
2131 case WL_OUTPUT_TRANSFORM_90:
2132 case WL_OUTPUT_TRANSFORM_270:
2133 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
2134 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
2135 ow = output->geometry.h;
2136 oh = output->geometry.w;
2139 ow = output->geometry.w;
2140 oh = output->geometry.h;
2146 EINA_INLIST_FOREACH(display->outputs, output)
2148 switch (output->transform)
2150 case WL_OUTPUT_TRANSFORM_90:
2151 case WL_OUTPUT_TRANSFORM_270:
2152 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
2153 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
2154 ow += output->geometry.h;
2155 oh += output->geometry.w;
2158 ow += output->geometry.w;
2159 oh += output->geometry.h;
2166 // TIZEN_ONLY(20190430): support client appinfo
2167 if (display->wl.tz_appinfo)
2170 if (_base_resolution_pid != pid) _base_resolution_pid = pid;
2172 tizen_launch_appinfo_get_base_output_resolution(display->wl.tz_appinfo, pid);
2173 ecore_wl2_display_sync(display);
2175 if (_base_resolution_w <= 0 || _base_resolution_h <= 0)
2176 goto without_tz_appinfo;
2178 if (w) *w = _base_resolution_w;
2179 if (h) *h = _base_resolution_h;
2181 INF("ecore_wl2_display_screen_size_get called, pid: %d / width: %d / height: %d / b_res_w: %d / b_res_h: %d",
2182 pid, (w? *w : -1), (h? *h : -1), _base_resolution_w, _base_resolution_h);
2192 // TIZEN_ONLY(20220407): Gets the screen size of all screens
2194 ecore_wl2_display_all_screens_size_get(Ecore_Wl2_Display *display, int *w, int *h)
2196 Ecore_Wl2_Output *output;
2199 EINA_SAFETY_ON_NULL_RETURN(display);
2204 EINA_INLIST_FOREACH(display->outputs, output)
2206 switch (output->transform)
2208 case WL_OUTPUT_TRANSFORM_90:
2209 case WL_OUTPUT_TRANSFORM_270:
2210 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
2211 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
2212 ow += output->geometry.h;
2213 oh += output->geometry.w;
2216 ow += output->geometry.w;
2217 oh += output->geometry.h;
2222 // TODO: Need to consider a base resolution of appinfo
2229 EAPI Ecore_Wl2_Window *
2230 ecore_wl2_display_window_find(Ecore_Wl2_Display *display, unsigned int id)
2232 Ecore_Wl2_Window *window;
2234 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2236 EINA_INLIST_FOREACH(display->windows, window)
2237 if (window->id == (int)id) return window;
2242 EAPI struct wl_registry *
2243 ecore_wl2_display_registry_get(Ecore_Wl2_Display *display)
2245 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2247 return display->wl.registry;
2251 ecore_wl2_display_compositor_version_get(Ecore_Wl2_Display *display)
2253 EINA_SAFETY_ON_NULL_RETURN_VAL(display, 0);
2255 return display->wl.compositor_version;
2258 EAPI Eina_Iterator *
2259 ecore_wl2_display_inputs_get(Ecore_Wl2_Display *display)
2261 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2262 EINA_SAFETY_ON_TRUE_RETURN_VAL(display->pid, NULL);
2263 return eina_inlist_iterator_new(display->inputs);
2266 EAPI Ecore_Wl2_Input *
2267 ecore_wl2_display_input_find(const Ecore_Wl2_Display *display, unsigned int id)
2269 Ecore_Wl2_Input *input;
2271 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2272 EINA_SAFETY_ON_TRUE_RETURN_VAL(display->pid, NULL);
2273 EINA_INLIST_FOREACH(display->inputs, input)
2274 if (input->id == id) return input;
2278 EAPI Ecore_Wl2_Input *
2279 ecore_wl2_display_input_find_by_name(const Ecore_Wl2_Display *display, const char *name)
2281 Ecore_Wl2_Input *input;
2283 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2284 EINA_SAFETY_ON_TRUE_RETURN_VAL(display->pid, NULL);
2285 EINA_INLIST_FOREACH(display->inputs, input)
2286 if (eina_streq(input->name, name)) return input;
2291 ecore_wl2_display_sync_is_done(const Ecore_Wl2_Display *display)
2293 EINA_SAFETY_ON_NULL_RETURN_VAL(display, EINA_FALSE);
2294 return display->sync_done;
2298 ecore_wl2_display_name_get(const Ecore_Wl2_Display *display)
2300 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2301 return display->name;
2305 ecore_wl2_display_flush(Ecore_Wl2_Display *display)
2309 EINA_SAFETY_ON_NULL_RETURN(display);
2311 ret = wl_display_flush(display->wl.display);
2312 if (ret >= 0) return;
2317 ecore_main_fd_handler_active_set(display->fd_hdl,
2318 (ECORE_FD_READ | ECORE_FD_WRITE));
2322 _begin_recovery_maybe(display, code);
2325 EAPI Ecore_Wl2_Window *
2326 ecore_wl2_display_window_find_by_surface(Ecore_Wl2_Display *display, struct wl_surface *surface)
2328 return _ecore_wl2_display_window_surface_find(display, surface);
2331 EAPI Ecore_Wl2_Display *
2332 ecore_wl2_connected_display_get(const char *name)
2334 Ecore_Wl2_Display *ewd;
2336 EINA_SAFETY_ON_NULL_RETURN_VAL(_client_displays, NULL);
2342 /* client wants to connected to default display */
2343 n = getenv("WAYLAND_DISPLAY");
2344 if (!n) n = "wayland-0";
2346 /* we have a default wayland display */
2348 /* check hash of cached client displays for this name */
2349 ewd = eina_hash_find(_client_displays, n);
2353 /* client wants to connect to specific display */
2355 /* check hash of cached client displays for this name */
2356 ewd = eina_hash_find(_client_displays, name);
2362 EAPI struct wl_compositor *
2363 ecore_wl2_display_compositor_get(Ecore_Wl2_Display *display)
2365 EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
2366 return display->wl.compositor;