5 #include "ecore_wl_private.h"
7 /* local function prototypes */
8 static void _ecore_wl_window_cb_ping(void *data __UNUSED__, struct wl_shell_surface *shell_surface, unsigned int serial);
9 static void _ecore_wl_window_cb_configure(void *data, struct wl_shell_surface *shell_surface __UNUSED__, unsigned int edges, int w, int h);
10 static void _ecore_wl_window_cb_popup_done(void *data, struct wl_shell_surface *shell_surface __UNUSED__);
11 static void _ecore_wl_window_cb_surface_enter(void *data, struct wl_surface *surface, struct wl_output *output __UNUSED__);
12 static void _ecore_wl_window_cb_surface_leave(void *data, struct wl_surface *surface, struct wl_output *output __UNUSED__);
13 static void _ecore_wl_window_configure_send(Ecore_Wl_Window *win, int w, int h);
14 static char *_ecore_wl_window_id_str_get(unsigned int win_id);
17 static Eina_Hash *_windows = NULL;
19 /* wayland listeners */
20 static const struct wl_surface_listener _ecore_wl_surface_listener =
22 _ecore_wl_window_cb_surface_enter,
23 _ecore_wl_window_cb_surface_leave
26 static const struct wl_shell_surface_listener _ecore_wl_shell_surface_listener =
28 _ecore_wl_window_cb_ping,
29 _ecore_wl_window_cb_configure,
30 _ecore_wl_window_cb_popup_done
33 /* internal functions */
35 _ecore_wl_window_init(void)
38 _windows = eina_hash_string_superfast_new(NULL);
42 _ecore_wl_window_shutdown(void)
44 eina_hash_free(_windows);
49 * @defgroup Ecore_Wl_Window_Group Wayland Library Init and Shutdown Functions
51 * Functions that can be used to create a Wayland window.
55 * Creates a new window
57 * @param parent The parent window to use. If @p parent is @c 0, the root window
58 * of the default display is used.
63 * @param buffer_type The type of the buffer to be used to create a new Ecore_Wl_Window.
65 * @return The new window
67 * @ingroup Ecore_Wl_Window_Group
70 EAPI Ecore_Wl_Window *
71 ecore_wl_window_new(Ecore_Wl_Window *parent, int x, int y, int w, int h, int buffer_type)
74 static int _win_id = 1;
76 LOGFN(__FILE__, __LINE__, __FUNCTION__);
78 if (!(win = malloc(sizeof(Ecore_Wl_Window))))
80 ERR("Failed to allocate an Ecore Wayland Window");
84 memset(win, 0, sizeof(Ecore_Wl_Window));
86 win->display = _ecore_wl_disp;
88 win->allocation.x = x;
89 win->allocation.y = y;
90 win->allocation.w = w;
91 win->allocation.h = h;
92 win->saved_allocation = win->allocation;
93 win->transparent = EINA_FALSE;
94 /* win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL; */
95 win->type = ECORE_WL_WINDOW_TYPE_NONE;
96 win->buffer_type = buffer_type;
99 eina_hash_add(_windows, _ecore_wl_window_id_str_get(win->id), win);
104 * Deletes the given window
106 * @param win The given window
108 * @ingroup Ecore_Wl_Window_Group
112 ecore_wl_window_free(Ecore_Wl_Window *win)
114 Ecore_Wl_Input *input;
116 LOGFN(__FILE__, __LINE__, __FUNCTION__);
120 eina_hash_del(_windows, _ecore_wl_window_id_str_get(win->id), win);
122 wl_list_for_each(input, &_ecore_wl_disp->inputs, link)
124 if ((input->pointer_focus) && (input->pointer_focus == win))
125 input->pointer_focus = NULL;
126 if ((input->keyboard_focus) && (input->keyboard_focus == win))
127 input->keyboard_focus = NULL;
130 if (win->region.input) wl_region_destroy(win->region.input);
131 win->region.input = NULL;
132 if (win->region.opaque) wl_region_destroy(win->region.opaque);
133 win->region.opaque = NULL;
134 if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface);
135 win->shell_surface = NULL;
137 if (win->surface) wl_surface_destroy(win->surface);
140 /* HMMM, why was this disabled ? */
145 * Signals for Wayland to initiate a window move.
147 * The position requested (@p x, @p y) is not honored by Wayland because
148 * Wayland does not allow specific window placement to be set.
150 * @param win The window to move.
151 * @param x X Position
152 * @param y Y Position
154 * @ingroup Ecore_Wl_Window_Group
158 ecore_wl_window_move(Ecore_Wl_Window *win, int x, int y)
160 LOGFN(__FILE__, __LINE__, __FUNCTION__);
164 win->allocation.x = x;
165 win->allocation.y = y;
167 if (win->shell_surface)
169 Ecore_Wl_Input *input;
171 if (!(input = win->keyboard_device))
175 if (!(input = win->parent->keyboard_device))
176 input = win->parent->pointer_device;
180 if ((!input) || (!input->seat)) return;
182 wl_shell_surface_move(win->shell_surface, input->seat,
183 input->display->serial);
188 * Signals for Wayland to initiate a window resize.
190 * The size requested (@p w, @p h) is not honored by Wayland because
191 * Wayland does not allow specific window sizes to be set.
193 * @param win The window to resize.
196 * @param location The edge of the window from where the resize should start.
198 * @ingroup Ecore_Wl_Window_Group
202 ecore_wl_window_resize(Ecore_Wl_Window *win, int w, int h, int location)
204 LOGFN(__FILE__, __LINE__, __FUNCTION__);
208 if (win->type != ECORE_WL_WINDOW_TYPE_FULLSCREEN)
210 win->allocation.w = w;
211 win->allocation.h = h;
214 wl_compositor_create_region(_ecore_wl_disp->wl.compositor);
215 wl_region_add(win->region.input, win->allocation.x, win->allocation.y,
216 win->allocation.w, win->allocation.h);
219 if (!win->transparent)
222 wl_compositor_create_region(_ecore_wl_disp->wl.compositor);
223 wl_region_add(win->region.opaque, win->allocation.x, win->allocation.y,
224 win->allocation.w, win->allocation.h);
227 if (win->shell_surface)
229 Ecore_Wl_Input *input;
231 if (!(input = win->keyboard_device))
235 if (!(input = win->parent->keyboard_device))
236 input = win->parent->pointer_device;
240 if ((!input) || (!input->seat)) return;
242 wl_shell_surface_resize(win->shell_surface, input->seat,
243 input->display->serial, location);
248 ecore_wl_window_damage(Ecore_Wl_Window *win, int x, int y, int w, int h)
250 LOGFN(__FILE__, __LINE__, __FUNCTION__);
254 wl_surface_damage(win->surface, x, y, w, h);
258 ecore_wl_window_buffer_attach(Ecore_Wl_Window *win, struct wl_buffer *buffer, int x, int y)
260 LOGFN(__FILE__, __LINE__, __FUNCTION__);
264 switch (win->buffer_type)
266 case ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW:
267 win->server_allocation = win->allocation;
269 case ECORE_WL_WINDOW_BUFFER_TYPE_EGL_IMAGE:
270 case ECORE_WL_WINDOW_BUFFER_TYPE_SHM:
273 if (win->edges & 4) // resizing from the left
274 x = win->server_allocation.w - win->allocation.w;
278 if (win->edges & 1) // resizing from the top
279 y = win->server_allocation.h - win->allocation.h;
286 wl_surface_attach(win->surface, buffer, x, y);
287 wl_surface_damage(win->surface, 0, 0,
288 win->allocation.w, win->allocation.h);
290 win->server_allocation = win->allocation;
297 if (win->region.input)
299 wl_surface_set_input_region(win->surface, win->region.input);
300 wl_region_destroy(win->region.input);
301 win->region.input = NULL;
304 if (win->region.opaque)
306 wl_surface_set_opaque_region(win->surface, win->region.opaque);
307 wl_region_destroy(win->region.opaque);
308 win->region.opaque = NULL;
315 * Synonymous to "mapping" a window in Wayland System terminology.
317 * @param win The window to show.
319 * @ingroup Ecore_Wl_Window_Group
323 ecore_wl_window_show(Ecore_Wl_Window *win)
325 LOGFN(__FILE__, __LINE__, __FUNCTION__);
328 if (win->surface) return;
330 win->surface = wl_compositor_create_surface(_ecore_wl_disp->wl.compositor);
331 wl_surface_set_user_data(win->surface, win);
332 /* wl_surface_add_listener(win->surface, &_ecore_wl_surface_listener, win); */
335 wl_shell_get_shell_surface(_ecore_wl_disp->wl.shell, win->surface);
336 wl_shell_surface_add_listener(win->shell_surface,
337 &_ecore_wl_shell_surface_listener, win);
341 case ECORE_WL_WINDOW_TYPE_FULLSCREEN:
342 wl_shell_surface_set_fullscreen(win->shell_surface,
343 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
346 case ECORE_WL_WINDOW_TYPE_MAXIMIZED:
347 wl_shell_surface_set_maximized(win->shell_surface, NULL);
349 case ECORE_WL_WINDOW_TYPE_TRANSIENT:
350 wl_shell_surface_set_transient(win->shell_surface,
351 win->parent->surface,
352 win->allocation.x, win->allocation.y, 0);
354 case ECORE_WL_WINDOW_TYPE_MENU:
355 wl_shell_surface_set_popup(win->shell_surface,
356 _ecore_wl_disp->input->seat,
357 _ecore_wl_disp->serial,
358 win->parent->surface,
359 win->allocation.x, win->allocation.y, 0);
361 case ECORE_WL_WINDOW_TYPE_NONE:
362 win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL;
364 case ECORE_WL_WINDOW_TYPE_TOPLEVEL:
365 wl_shell_surface_set_toplevel(win->shell_surface);
371 /* if (win->type != ECORE_WL_WINDOW_TYPE_FULLSCREEN) */
373 /* win->region.input = */
374 /* wl_compositor_create_region(_ecore_wl_disp->wl.compositor); */
375 /* wl_region_add(win->region.input, win->allocation.x, win->allocation.y, */
376 /* win->allocation.w, win->allocation.h); */
379 /* if (!win->transparent) */
381 /* win->region.opaque = */
382 /* wl_compositor_create_region(_ecore_wl_disp->wl.compositor); */
383 /* wl_region_add(win->region.opaque, win->allocation.x, win->allocation.y, */
384 /* win->allocation.w, win->allocation.h); */
391 * Synonymous to "unmapping" a window in Wayland System terminology.
393 * @param win The window to hide.
395 * @ingroup Ecore_Wl_Window_Group
399 ecore_wl_window_hide(Ecore_Wl_Window *win)
401 LOGFN(__FILE__, __LINE__, __FUNCTION__);
404 if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface);
405 win->shell_surface = NULL;
406 if (win->surface) wl_surface_destroy(win->surface);
413 * @param win The window to raise.
415 * @ingroup Ecore_Wl_Window_Group
419 ecore_wl_window_raise(Ecore_Wl_Window *win)
421 LOGFN(__FILE__, __LINE__, __FUNCTION__);
424 if (win->shell_surface)
425 wl_shell_surface_set_toplevel(win->shell_surface);
429 ecore_wl_window_maximized_set(Ecore_Wl_Window *win, Eina_Bool maximized)
431 LOGFN(__FILE__, __LINE__, __FUNCTION__);
435 if ((win->type == ECORE_WL_WINDOW_TYPE_MAXIMIZED) == maximized) return;
436 if (win->type == ECORE_WL_WINDOW_TYPE_TOPLEVEL)
438 win->saved_allocation = win->allocation;
439 if (win->shell_surface)
440 wl_shell_surface_set_maximized(win->shell_surface, NULL);
441 win->type = ECORE_WL_WINDOW_TYPE_MAXIMIZED;
443 else if (win->type == ECORE_WL_WINDOW_TYPE_MAXIMIZED)
445 if (win->shell_surface)
446 wl_shell_surface_set_toplevel(win->shell_surface);
447 win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL;
448 _ecore_wl_window_configure_send(win, win->saved_allocation.w,
449 win->saved_allocation.h);
454 ecore_wl_window_fullscreen_set(Ecore_Wl_Window *win, Eina_Bool fullscreen)
456 LOGFN(__FILE__, __LINE__, __FUNCTION__);
459 if ((win->type == ECORE_WL_WINDOW_TYPE_FULLSCREEN) == fullscreen) return;
462 win->type = ECORE_WL_WINDOW_TYPE_FULLSCREEN;
463 win->saved_allocation = win->allocation;
464 if (win->shell_surface)
465 wl_shell_surface_set_fullscreen(win->shell_surface,
466 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
471 if (win->shell_surface)
472 wl_shell_surface_set_toplevel(win->shell_surface);
473 win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL;
474 _ecore_wl_window_configure_send(win, win->saved_allocation.w,
475 win->saved_allocation.h);
480 ecore_wl_window_transparent_set(Ecore_Wl_Window *win, Eina_Bool transparent)
482 LOGFN(__FILE__, __LINE__, __FUNCTION__);
485 win->transparent = transparent;
486 if (win->region.opaque) wl_region_destroy(win->region.opaque);
487 win->region.opaque = NULL;
488 if (!win->transparent)
491 wl_compositor_create_region(_ecore_wl_disp->wl.compositor);
492 wl_region_add(win->region.opaque, win->allocation.x, win->allocation.y,
493 win->allocation.w, win->allocation.h);
498 ecore_wl_window_update_size(Ecore_Wl_Window *win, int w, int h)
500 LOGFN(__FILE__, __LINE__, __FUNCTION__);
503 win->allocation.w = w;
504 win->allocation.h = h;
508 ecore_wl_window_update_location(Ecore_Wl_Window *win, int x, int y)
510 LOGFN(__FILE__, __LINE__, __FUNCTION__);
513 win->allocation.x = x;
514 win->allocation.y = y;
517 EAPI struct wl_surface *
518 ecore_wl_window_surface_get(Ecore_Wl_Window *win)
520 LOGFN(__FILE__, __LINE__, __FUNCTION__);
522 if (!win) return NULL;
527 EAPI struct wl_shell_surface *
528 ecore_wl_window_shell_surface_get(Ecore_Wl_Window *win)
530 LOGFN(__FILE__, __LINE__, __FUNCTION__);
532 if (!win) return NULL;
533 return win->shell_surface;
536 EAPI Ecore_Wl_Window *
537 ecore_wl_window_find(unsigned int id)
539 Ecore_Wl_Window *win = NULL;
541 win = eina_hash_find(_windows, _ecore_wl_window_id_str_get(id));
546 ecore_wl_window_type_set(Ecore_Wl_Window *win, Ecore_Wl_Window_Type type)
548 LOGFN(__FILE__, __LINE__, __FUNCTION__);
555 ecore_wl_window_pointer_set(Ecore_Wl_Window *win, struct wl_surface *surface, int hot_x, int hot_y)
557 Ecore_Wl_Input *input;
559 LOGFN(__FILE__, __LINE__, __FUNCTION__);
563 if ((input = win->pointer_device))
564 ecore_wl_input_pointer_set(input, surface, hot_x, hot_y);
568 ecore_wl_window_cursor_from_name_set(Ecore_Wl_Window *win, const char *cursor_name)
570 Ecore_Wl_Input *input;
572 LOGFN(__FILE__, __LINE__, __FUNCTION__);
576 if ((input = win->pointer_device))
577 ecore_wl_input_cursor_from_name_set(input, cursor_name);
581 ecore_wl_window_cursor_default_restore(Ecore_Wl_Window *win)
583 Ecore_Wl_Input *input;
585 LOGFN(__FILE__, __LINE__, __FUNCTION__);
589 if ((input = win->pointer_device))
590 ecore_wl_input_cursor_default_restore(input);
595 ecore_wl_window_parent_set(Ecore_Wl_Window *win, Ecore_Wl_Window *parent)
597 LOGFN(__FILE__, __LINE__, __FUNCTION__);
599 win->parent = parent;
602 /* local functions */
604 _ecore_wl_window_cb_ping(void *data __UNUSED__, struct wl_shell_surface *shell_surface, unsigned int serial)
606 if (!shell_surface) return;
607 wl_shell_surface_pong(shell_surface, serial);
611 _ecore_wl_window_cb_configure(void *data, struct wl_shell_surface *shell_surface __UNUSED__, unsigned int edges, int w, int h)
613 Ecore_Wl_Window *win;
615 LOGFN(__FILE__, __LINE__, __FUNCTION__);
617 if (!(win = data)) return;
619 if ((w <= 0) || (h <= 0)) return;
621 if ((win->allocation.w != w) || (win->allocation.h != h))
624 if (win->region.input) wl_region_destroy(win->region.input);
625 win->region.input = NULL;
626 if (win->region.opaque) wl_region_destroy(win->region.opaque);
627 win->region.opaque = NULL;
629 _ecore_wl_window_configure_send(win, w, h);
634 _ecore_wl_window_cb_popup_done(void *data, struct wl_shell_surface *shell_surface __UNUSED__)
636 Ecore_Wl_Window *win;
638 LOGFN(__FILE__, __LINE__, __FUNCTION__);
640 if (!shell_surface) return;
641 if (!(win = data)) return;
642 ecore_wl_input_ungrab(win->pointer_device);
646 _ecore_wl_window_cb_surface_enter(void *data, struct wl_surface *surface, struct wl_output *output __UNUSED__)
648 Ecore_Wl_Window *win;
650 LOGFN(__FILE__, __LINE__, __FUNCTION__);
652 if (!surface) return;
653 if (!(win = data)) return;
657 _ecore_wl_window_cb_surface_leave(void *data, struct wl_surface *surface, struct wl_output *output __UNUSED__)
659 Ecore_Wl_Window *win;
661 LOGFN(__FILE__, __LINE__, __FUNCTION__);
663 if (!surface) return;
664 if (!(win = data)) return;
668 _ecore_wl_window_configure_send(Ecore_Wl_Window *win, int w, int h)
670 Ecore_Wl_Event_Window_Configure *ev;
672 LOGFN(__FILE__, __LINE__, __FUNCTION__);
674 if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Window_Configure)))) return;
676 ev->event_win = win->id;
677 ev->x = win->allocation.x;
678 ev->y = win->allocation.y;
681 ecore_event_add(ECORE_WL_EVENT_WINDOW_CONFIGURE, ev, NULL, NULL);
685 _ecore_wl_window_id_str_get(unsigned int win_id)
687 const char *vals = "qWeRtYuIoP5$&<~";
692 id[0] = vals[(val >> 28) & 0xf];
693 id[1] = vals[(val >> 24) & 0xf];
694 id[2] = vals[(val >> 20) & 0xf];
695 id[3] = vals[(val >> 16) & 0xf];
696 id[4] = vals[(val >> 12) & 0xf];
697 id[5] = vals[(val >> 8) & 0xf];
698 id[6] = vals[(val >> 4) & 0xf];
699 id[7] = vals[(val) & 0xf];