From 78b56e55de95d0af0e574ee26104ba2e6acc3a89 Mon Sep 17 00:00:00 2001 From: devilhorns Date: Tue, 27 Mar 2012 02:13:34 +0000 Subject: [PATCH] Ecore_Wayland: - Comment out display_iterate during intialize (hangs compositor initialize). - Simplify ecore_wl_flush routine and avoid possible hangs in wl_display_roundtrip. - Add function (for trip ;) ) to be able to return the screen dpi. - Implement functions for input grab/ungrab. - Set root.x/y in mouse events. - Remove freeing of mouse_move event (already handled generically). - Handle setting output mm width/height (for calc of dpi). - Implement setting surface input & opaque regions. - Implement popup windows. - Implement ecore_wl_window_transparent_set function. - Implement function to allow setting Ecore_Wl_Window type. - Implement setting the wayland mouse pointer to an image (via ecore_wl_window_pointer_set). - Comment out wl_display_iterate during initialize (can cause hangs in compositor). - Simplify ecore_wl_flush (to avoid compositor hangs). git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@69644 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/ecore_wayland/Ecore_Wayland.h | 20 ++++++- src/lib/ecore_wayland/ecore_wl.c | 32 ++++++---- src/lib/ecore_wayland/ecore_wl_input.c | 86 +++++++++++++++++++-------- src/lib/ecore_wayland/ecore_wl_output.c | 6 +- src/lib/ecore_wayland/ecore_wl_window.c | 102 ++++++++++++++++++++++++++++++-- 5 files changed, 201 insertions(+), 45 deletions(-) diff --git a/src/lib/ecore_wayland/Ecore_Wayland.h b/src/lib/ecore_wayland/Ecore_Wayland.h index 7dab37c..b070164 100644 --- a/src/lib/ecore_wayland/Ecore_Wayland.h +++ b/src/lib/ecore_wayland/Ecore_Wayland.h @@ -6,6 +6,8 @@ # include # include # include // NB: already includes wayland-client.h +# include +# include # include # include @@ -77,9 +79,7 @@ struct _Ecore_Wl_Display struct { EGLDisplay display; - EGLConfig rgb_config; EGLConfig argb_config; - EGLContext rgb_context; EGLContext argb_context; } egl; @@ -93,6 +93,7 @@ struct _Ecore_Wl_Display struct xkb_desc *xkb; Ecore_Wl_Output *output; + Ecore_Wl_Input *input; PFNEGLCREATEIMAGEKHRPROC create_image; PFNEGLDESTROYIMAGEKHRPROC destroy_image; @@ -106,6 +107,7 @@ struct _Ecore_Wl_Output Ecore_Wl_Display *display; struct wl_output *output; Eina_Rectangle allocation; + int mw, mh; struct wl_list link; void (*destroy) (Ecore_Wl_Output *output, void *data); @@ -128,7 +130,7 @@ struct _Ecore_Wl_Input struct wl_list link; - /* TODO: grab */ + Ecore_Wl_Window *grab; unsigned int grab_button; Ecore_Wl_Dnd_Source *drag_source; @@ -143,6 +145,11 @@ struct _Ecore_Wl_Window struct wl_surface *surface; struct wl_shell_surface *shell_surface; + struct + { + struct wl_region *input, *opaque; + } region; + int id; int x, y; int edges; @@ -285,6 +292,10 @@ EAPI struct wl_shm *ecore_wl_shm_get(void); EAPI struct wl_display *ecore_wl_display_get(void); EAPI void ecore_wl_screen_size_get(int *w, int *h); EAPI void ecore_wl_pointer_xy_get(int *x, int *y); +EAPI int ecore_wl_dpi_get(void); + +EAPI void ecore_wl_input_grab(Ecore_Wl_Input *input, Ecore_Wl_Window *win, unsigned int button); +EAPI void ecore_wl_input_ungrab(Ecore_Wl_Input *input, unsigned int timestamp); EAPI Ecore_Wl_Window *ecore_wl_window_new(Ecore_Wl_Window *parent, int x, int y, int w, int h, int buffer_type); EAPI void ecore_wl_window_free(Ecore_Wl_Window *win); @@ -297,8 +308,11 @@ EAPI void ecore_wl_window_hide(Ecore_Wl_Window *win); EAPI void ecore_wl_window_raise(Ecore_Wl_Window *win); EAPI void ecore_wl_window_maximized_set(Ecore_Wl_Window *win, Eina_Bool maximized); EAPI void ecore_wl_window_fullscreen_set(Ecore_Wl_Window *win, Eina_Bool fullscreen); +EAPI void ecore_wl_window_transparent_set(Ecore_Wl_Window *win, Eina_Bool transparent); EAPI void ecore_wl_window_update_size(Ecore_Wl_Window *win, int w, int h); EAPI struct wl_surface *ecore_wl_window_surface_get(Ecore_Wl_Window *win); EAPI Ecore_Wl_Window *ecore_wl_window_find(unsigned int id); +EAPI void ecore_wl_window_type_set(Ecore_Wl_Window *win, Ecore_Wl_Window_Type type); +EAPI void ecore_wl_window_pointer_set(Ecore_Wl_Window *win, struct wl_buffer *buffer, int hot_x, int hot_y, unsigned int timestamp); #endif diff --git a/src/lib/ecore_wayland/ecore_wl.c b/src/lib/ecore_wayland/ecore_wl.c index 5f1b20d..754f43c 100644 --- a/src/lib/ecore_wayland/ecore_wl.c +++ b/src/lib/ecore_wayland/ecore_wl.c @@ -159,7 +159,7 @@ ecore_wl_init(const char *name) _ecore_wl_cb_handle_global, _ecore_wl_disp); /* FIXME: Process connection events ?? */ - wl_display_iterate(_ecore_wl_disp->wl.display, WL_DISPLAY_READABLE); + /* wl_display_iterate(_ecore_wl_disp->wl.display, WL_DISPLAY_READABLE); */ /* if (!_ecore_wl_egl_init(_ecore_wl_disp)) */ /* { */ @@ -233,7 +233,7 @@ ecore_wl_shutdown(void) EAPI void ecore_wl_flush(void) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); +// LOGFN(__FILE__, __LINE__, __FUNCTION__); while (_ecore_wl_disp->mask & WL_DISPLAY_WRITABLE) wl_display_iterate(_ecore_wl_disp->wl.display, WL_DISPLAY_WRITABLE); @@ -252,7 +252,10 @@ ecore_wl_sync(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); - wl_display_roundtrip(_ecore_wl_disp->wl.display); + wl_display_sync(_ecore_wl_disp->wl.display); + + //wl_display_roundtrip(_ecore_wl_disp->wl.display); + // old sync code // wl_display_iterate(_ecore_wl_disp->wl.display, WL_DISPLAY_READABLE); } @@ -318,6 +321,20 @@ ecore_wl_pointer_xy_get(int *x, int *y) _ecore_wl_input_pointer_xy_get(x, y); } +EAPI int +ecore_wl_dpi_get(void) +{ + int w, mw; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + mw = _ecore_wl_disp->output->mw; + if (mw <= 0) return 75; + + w = _ecore_wl_disp->output->allocation.w; + return (((w * 254) / mw) + 5) / 10; +} + /* local functions */ static Eina_Bool _ecore_wl_shutdown(Eina_Bool close) @@ -376,7 +393,7 @@ _ecore_wl_cb_event_mask_update(unsigned int mask, void *data) { Ecore_Wl_Display *ewd; - LOGFN(__FILE__, __LINE__, __FUNCTION__); +// LOGFN(__FILE__, __LINE__, __FUNCTION__); ewd = data; ewd->mask = mask; @@ -400,12 +417,7 @@ _ecore_wl_cb_handle_global(struct wl_display *disp, unsigned int id, const char { Ecore_Wl_Display *ewd; - LOGFN(__FILE__, __LINE__, __FUNCTION__); - - if ((!strcmp(interface, "wl_display")) || - (!strcmp(interface, "wl_drm")) || - (!strcmp(interface, "desktop_shell"))) - return; +// LOGFN(__FILE__, __LINE__, __FUNCTION__); ewd = data; diff --git a/src/lib/ecore_wayland/ecore_wl_input.c b/src/lib/ecore_wayland/ecore_wl_input.c index d44daa7..cc654a7 100644 --- a/src/lib/ecore_wayland/ecore_wl_input.c +++ b/src/lib/ecore_wayland/ecore_wl_input.c @@ -45,7 +45,6 @@ static void _ecore_wl_input_cb_data_selection(void *data, struct wl_data_device static void _ecore_wl_input_keyboard_focus_remove(Ecore_Wl_Input *input, unsigned int timestamp); static void _ecore_wl_input_pointer_focus_remove(Ecore_Wl_Input *input, unsigned int timestamp); static void _ecore_wl_input_mouse_move_send(Ecore_Wl_Input *input, unsigned int timestamp); -static void _ecore_wl_input_cb_mouse_move_free(void *data __UNUSED__, void *event); static void _ecore_wl_input_mouse_in_send(Ecore_Wl_Input *input, unsigned int timestamp); static void _ecore_wl_input_mouse_out_send(Ecore_Wl_Input *input, unsigned int timestamp); static void _ecore_wl_input_focus_in_send(Ecore_Wl_Input *input, unsigned int timestamp); @@ -83,6 +82,27 @@ static const struct wl_data_device_listener _ecore_wl_data_listener = /* local variables */ static int _pointer_x, _pointer_y; +EAPI void +ecore_wl_input_grab(Ecore_Wl_Input *input, Ecore_Wl_Window *win, unsigned int button) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + input->grab = win; + input->grab_button = button; +} + +EAPI void +ecore_wl_input_ungrab(Ecore_Wl_Input *input, unsigned int timestamp) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + input->grab = NULL; + if (input->pointer_focus) + { + printf("Ungrab: %d\n", timestamp); + } +} + void _ecore_wl_input_add(Ecore_Wl_Display *ewd, unsigned int id) { @@ -110,6 +130,7 @@ _ecore_wl_input_add(Ecore_Wl_Display *ewd, unsigned int id) input->input_device); wl_data_device_add_listener(input->data_device, &_ecore_wl_data_listener, input); + ewd->input = input; } void @@ -170,7 +191,10 @@ _ecore_wl_input_cb_button(void *data, struct wl_input_device *input_device __UNU input->timestamp = timestamp; - _ecore_wl_input_mouse_move_send(input, timestamp); + if ((input->pointer_focus) && (!input->grab) && (state)) + ecore_wl_input_grab(input, input->pointer_focus, button); + +// _ecore_wl_input_mouse_move_send(input, timestamp); if ((button >= BTN_SIDE) && (button <= BTN_BACK)) { @@ -188,6 +212,9 @@ _ecore_wl_input_cb_button(void *data, struct wl_input_device *input_device __UNU { _ecore_wl_input_mouse_up_send(input, timestamp); input->button = 0; + + if ((input->grab) && (input->grab_button == button)) + ecore_wl_input_ungrab(input, timestamp); } } } @@ -231,10 +258,13 @@ _ecore_wl_input_cb_pointer_enter(void *data, struct wl_input_device *input_devic if (!(input = data)) return; - input->sx = sx; - input->sy = sy; + /* _pointer_x = sx; */ + /* _pointer_y = sy; */ - _ecore_wl_input_mouse_move_send(input, timestamp); + /* input->sx = sx; */ + /* input->sy = sy; */ + +// _ecore_wl_input_mouse_move_send(input, timestamp); win = input->pointer_focus; if ((win) && (win->surface != surface)) @@ -250,12 +280,12 @@ _ecore_wl_input_cb_pointer_enter(void *data, struct wl_input_device *input_devic input->pointer_focus = win; win->pointer_device = input; } - if (input->button) - { - _ecore_wl_input_mouse_up_send(input, timestamp); - input->button = 0; - } - else + /* if (input->button) */ + /* { */ + /* _ecore_wl_input_mouse_up_send(input, timestamp); */ + /* input->button = 0; */ + /* } */ + /* else */ _ecore_wl_input_mouse_in_send(input, timestamp); } } @@ -448,6 +478,7 @@ _ecore_wl_input_pointer_focus_remove(Ecore_Wl_Input *input, unsigned int timesta if ((win = input->pointer_focus)) win->pointer_device = NULL; + input->pointer_focus = NULL; } @@ -455,7 +486,7 @@ static void _ecore_wl_input_mouse_move_send(Ecore_Wl_Input *input, unsigned int timestamp) { Ecore_Event_Mouse_Move *ev; - Ecore_Event *event; +// Ecore_Event *event; LOGFN(__FILE__, __LINE__, __FUNCTION__); @@ -464,6 +495,8 @@ _ecore_wl_input_mouse_move_send(Ecore_Wl_Input *input, unsigned int timestamp) ev->timestamp = timestamp; ev->x = input->sx; ev->y = input->sy; + ev->root.x = input->sx; + ev->root.y = input->sy; ev->modifiers = input->modifiers; ev->multi.device = 0; ev->multi.radius = 1; @@ -474,29 +507,24 @@ _ecore_wl_input_mouse_move_send(Ecore_Wl_Input *input, unsigned int timestamp) ev->multi.x = input->sx; ev->multi.y = input->sy; - if (input->pointer_focus) + if (input->grab) + { + ev->window = input->grab->id; + ev->event_window = input->grab->id; + } + else if (input->pointer_focus) { ev->window = input->pointer_focus->id; ev->event_window = input->pointer_focus->id; } - event = ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, - _ecore_wl_input_cb_mouse_move_free, NULL); -} - -static void -_ecore_wl_input_cb_mouse_move_free(void *data __UNUSED__, void *event) -{ - Ecore_Event_Mouse_Move *ev; - - if ((ev = event)) free(ev); + ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL); } static void _ecore_wl_input_mouse_in_send(Ecore_Wl_Input *input, unsigned int timestamp) { Ecore_Wl_Event_Mouse_In *ev; - Ecore_Event *event; LOGFN(__FILE__, __LINE__, __FUNCTION__); @@ -504,6 +532,8 @@ _ecore_wl_input_mouse_in_send(Ecore_Wl_Input *input, unsigned int timestamp) ev->x = input->sx; ev->y = input->sy; + ev->root.x = input->sx; + ev->root.y = input->sy; ev->modifiers = input->modifiers; ev->timestamp = timestamp; @@ -513,7 +543,7 @@ _ecore_wl_input_mouse_in_send(Ecore_Wl_Input *input, unsigned int timestamp) ev->event_win = input->pointer_focus->id; } - event = ecore_event_add(ECORE_WL_EVENT_MOUSE_IN, ev, NULL, NULL); + ecore_event_add(ECORE_WL_EVENT_MOUSE_IN, ev, NULL, NULL); } static void @@ -527,6 +557,8 @@ _ecore_wl_input_mouse_out_send(Ecore_Wl_Input *input, unsigned int timestamp) ev->x = input->sx; ev->y = input->sy; + ev->root.x = input->sx; + ev->root.y = input->sy; ev->modifiers = input->modifiers; ev->timestamp = timestamp; @@ -588,6 +620,8 @@ _ecore_wl_input_mouse_down_send(Ecore_Wl_Input *input, unsigned int timestamp) ev->timestamp = timestamp; ev->x = input->sx; ev->y = input->sy; + ev->root.x = input->sx; + ev->root.y = input->sy; ev->modifiers = input->modifiers; /* FIXME: Need to get these from wayland somehow */ @@ -633,6 +667,8 @@ _ecore_wl_input_mouse_up_send(Ecore_Wl_Input *input, unsigned int timestamp) ev->timestamp = timestamp; ev->x = input->sx; ev->y = input->sy; + ev->root.x = input->sx; + ev->root.y = input->sy; ev->modifiers = input->modifiers; /* FIXME: Need to get these from wayland somehow */ diff --git a/src/lib/ecore_wayland/ecore_wl_output.c b/src/lib/ecore_wayland/ecore_wl_output.c index 9f540d4..ae94c77 100644 --- a/src/lib/ecore_wayland/ecore_wl_output.c +++ b/src/lib/ecore_wayland/ecore_wl_output.c @@ -8,7 +8,7 @@ #include "Ecore_Wayland.h" /* local function prototypes */ -static void _ecore_wl_output_cb_geometry(void *data, struct wl_output *wl_output __UNUSED__, int x, int y, int w __UNUSED__, int h __UNUSED__, int subpixel __UNUSED__, const char *make __UNUSED__, const char *model __UNUSED__); +static void _ecore_wl_output_cb_geometry(void *data, struct wl_output *wl_output __UNUSED__, int x, int y, int w, int h, int subpixel __UNUSED__, const char *make __UNUSED__, const char *model __UNUSED__); static void _ecore_wl_output_cb_mode(void *data, struct wl_output *wl_output __UNUSED__, unsigned int flags, int w, int h, int refresh __UNUSED__); /* wayland listeners */ @@ -48,7 +48,7 @@ _ecore_wl_output_del(Ecore_Wl_Output *output) /* local functions */ static void -_ecore_wl_output_cb_geometry(void *data, struct wl_output *wl_output __UNUSED__, int x, int y, int w __UNUSED__, int h __UNUSED__, int subpixel __UNUSED__, const char *make __UNUSED__, const char *model __UNUSED__) +_ecore_wl_output_cb_geometry(void *data, struct wl_output *wl_output __UNUSED__, int x, int y, int w, int h, int subpixel __UNUSED__, const char *make __UNUSED__, const char *model __UNUSED__) { Ecore_Wl_Output *output; @@ -57,6 +57,8 @@ _ecore_wl_output_cb_geometry(void *data, struct wl_output *wl_output __UNUSED__, output = data; output->allocation.x = x; output->allocation.y = y; + output->mw = w; + output->mh = h; } static void diff --git a/src/lib/ecore_wayland/ecore_wl_window.c b/src/lib/ecore_wayland/ecore_wl_window.c index e8a8bfb..d4c181c 100644 --- a/src/lib/ecore_wayland/ecore_wl_window.c +++ b/src/lib/ecore_wayland/ecore_wl_window.c @@ -80,7 +80,7 @@ ecore_wl_window_new(Ecore_Wl_Window *parent, int x, int y, int w, int h, int buf win->allocation.w = w; win->allocation.h = h; win->saved_allocation = win->allocation; - win->transparent = EINA_TRUE; + win->transparent = EINA_FALSE; win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL; win->buffer_type = buffer_type; win->id = _win_id++; @@ -116,6 +116,9 @@ ecore_wl_window_free(Ecore_Wl_Window *win) input->keyboard_focus = NULL; } + if (win->region.input) wl_region_destroy(win->region.input); + if (win->region.opaque) wl_region_destroy(win->region.opaque); + if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface); win->shell_surface = NULL; @@ -150,7 +153,12 @@ ecore_wl_window_move(Ecore_Wl_Window *win, int x, int y) { Ecore_Wl_Input *input; - input = win->keyboard_device; + if (!(input = win->keyboard_device)) + { + if (win->parent) + input = win->parent->keyboard_device; + } + wl_shell_surface_move(win->shell_surface, input->input_device, input->timestamp); } @@ -178,6 +186,21 @@ ecore_wl_window_resize(Ecore_Wl_Window *win, int w, int h, int location) if (!win) return; win->allocation.w = w; win->allocation.h = h; + if (win->type != ECORE_WL_WINDOW_TYPE_FULLSCREEN) + { + win->region.input = + wl_compositor_create_region(_ecore_wl_disp->wl.compositor); + wl_region_add(win->region.input, win->allocation.x, win->allocation.y, + win->allocation.w, win->allocation.h); + } + if (!win->transparent) + { + win->region.opaque = + wl_compositor_create_region(_ecore_wl_disp->wl.compositor); + wl_region_add(win->region.opaque, win->allocation.x, win->allocation.y, + win->allocation.w, win->allocation.h); + } + if (win->shell_surface) { Ecore_Wl_Input *input; @@ -206,6 +229,23 @@ ecore_wl_window_buffer_attach(Ecore_Wl_Window *win, struct wl_buffer *buffer, in if (!win) return; if ((win->surface) && (buffer)) wl_surface_attach(win->surface, buffer, x, y); + if (win->surface) + { + if (win->region.input) + { + wl_surface_set_input_region(win->surface, win->region.input); + wl_region_destroy(win->region.input); + win->region.input = NULL; + } + if (win->region.opaque) + { + wl_surface_set_opaque_region(win->surface, win->region.opaque); + wl_region_destroy(win->region.opaque); + win->region.opaque = NULL; + } + wl_surface_damage(win->surface, 0, 0, + win->allocation.w, win->allocation.h); + } } /** @@ -227,6 +267,7 @@ ecore_wl_window_show(Ecore_Wl_Window *win) if (win->surface) return; win->surface = wl_compositor_create_surface(_ecore_wl_disp->wl.compositor); + wl_surface_set_user_data(win->surface, win); win->shell_surface = @@ -251,8 +292,8 @@ ecore_wl_window_show(Ecore_Wl_Window *win) break; case ECORE_WL_WINDOW_TYPE_MENU: wl_shell_surface_set_popup(win->shell_surface, - win->pointer_device->input_device, - win->pointer_device->timestamp, + win->parent->pointer_device->input_device, + win->parent->pointer_device->timestamp, win->parent->shell_surface, win->allocation.x, win->allocation.y, 0); break; @@ -261,6 +302,21 @@ ecore_wl_window_show(Ecore_Wl_Window *win) wl_shell_surface_set_toplevel(win->shell_surface); break; } + + if (win->type != ECORE_WL_WINDOW_TYPE_FULLSCREEN) + { + win->region.input = + wl_compositor_create_region(_ecore_wl_disp->wl.compositor); + wl_region_add(win->region.input, win->allocation.x, win->allocation.y, + win->allocation.w, win->allocation.h); + } + if (!win->transparent) + { + win->region.opaque = + wl_compositor_create_region(_ecore_wl_disp->wl.compositor); + wl_region_add(win->region.opaque, win->allocation.x, win->allocation.y, + win->allocation.w, win->allocation.h); + } } /** @@ -364,6 +420,15 @@ ecore_wl_window_fullscreen_set(Ecore_Wl_Window *win, Eina_Bool fullscreen) } EAPI void +ecore_wl_window_transparent_set(Ecore_Wl_Window *win, Eina_Bool transparent) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + win->transparent = transparent; +} + +EAPI void ecore_wl_window_update_size(Ecore_Wl_Window *win, int w, int h) { LOGFN(__FILE__, __LINE__, __FUNCTION__); @@ -393,6 +458,29 @@ ecore_wl_window_find(unsigned int id) return NULL; } +EAPI void +ecore_wl_window_type_set(Ecore_Wl_Window *win, Ecore_Wl_Window_Type type) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + win->type = type; +} + +EAPI void +ecore_wl_window_pointer_set(Ecore_Wl_Window *win, struct wl_buffer *buffer, int hot_x, int hot_y, unsigned int timestamp) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + + input = _ecore_wl_disp->input; + wl_input_device_attach(input->input_device, timestamp, + buffer, hot_x, hot_y); +} + /* local functions */ static void _ecore_wl_window_cb_configure(void *data, struct wl_shell_surface *shell_surface __UNUSED__, unsigned int timestamp, unsigned int edges, int w, int h) @@ -407,6 +495,10 @@ _ecore_wl_window_cb_configure(void *data, struct wl_shell_surface *shell_surface win->edges = edges; win->allocation.w = w; win->allocation.h = h; + if (win->region.input) wl_region_destroy(win->region.input); + win->region.input = NULL; + if (win->region.opaque) wl_region_destroy(win->region.opaque); + win->region.opaque = NULL; _ecore_wl_window_configure_send(win, w, h, timestamp); } @@ -418,7 +510,7 @@ _ecore_wl_window_cb_popup_done(void *data, struct wl_shell_surface *shell_surfac LOGFN(__FILE__, __LINE__, __FUNCTION__); if (!(win = data)) return; - /* TODO: handle popup destroy */ + ecore_wl_input_ungrab(win->pointer_device, 0); } static void -- 2.7.4