17 # define alloca __builtin_alloca
19 # define alloca __alloca
20 # elif defined _MSC_VER
22 # define alloca _alloca
23 # elif !defined HAVE_ALLOCA
27 void *alloca (size_t);
31 #include "ecore_wl_private.h"
33 /* local function prototypes */
34 static void _ecore_wl_window_cb_ping(void *data __UNUSED__, struct wl_shell_surface *shell_surface, unsigned int serial);
35 static void _ecore_wl_window_cb_configure(void *data, struct wl_shell_surface *shell_surface __UNUSED__, unsigned int edges, int w, int h);
36 static void _ecore_wl_window_cb_popup_done(void *data, struct wl_shell_surface *shell_surface __UNUSED__);
37 static void _ecore_wl_window_cb_surface_enter(void *data, struct wl_surface *surface, struct wl_output *output __UNUSED__);
38 static void _ecore_wl_window_cb_surface_leave(void *data, struct wl_surface *surface, struct wl_output *output __UNUSED__);
39 static void _ecore_wl_window_configure_send(Ecore_Wl_Window *win, int w, int h);
40 static char *_ecore_wl_window_id_str_get(unsigned int win_id);
43 static Eina_Hash *_windows = NULL;
45 /* wayland listeners */
46 static const struct wl_surface_listener _ecore_wl_surface_listener =
48 _ecore_wl_window_cb_surface_enter,
49 _ecore_wl_window_cb_surface_leave
52 static const struct wl_shell_surface_listener _ecore_wl_shell_surface_listener =
54 _ecore_wl_window_cb_ping,
55 _ecore_wl_window_cb_configure,
56 _ecore_wl_window_cb_popup_done
59 /* internal functions */
61 _ecore_wl_window_init(void)
64 _windows = eina_hash_string_superfast_new(NULL);
68 _ecore_wl_window_shutdown(void)
70 eina_hash_free(_windows);
75 * @defgroup Ecore_Wl_Window_Group Wayland Library Init and Shutdown Functions
77 * Functions that can be used to create a Wayland window.
81 * Creates a new window
83 * @param parent The parent window to use. If @p parent is @c 0, the root window
84 * of the default display is used.
89 * @param buffer_type The type of the buffer to be used to create a new Ecore_Wl_Window.
91 * @return The new window
93 * @ingroup Ecore_Wl_Window_Group
96 EAPI Ecore_Wl_Window *
97 ecore_wl_window_new(Ecore_Wl_Window *parent, int x, int y, int w, int h, int buffer_type)
100 static int _win_id = 1;
102 LOGFN(__FILE__, __LINE__, __FUNCTION__);
104 if (!(win = malloc(sizeof(Ecore_Wl_Window))))
106 ERR("Failed to allocate an Ecore Wayland Window");
110 memset(win, 0, sizeof(Ecore_Wl_Window));
112 win->display = _ecore_wl_disp;
113 win->parent = parent;
114 win->allocation.x = x;
115 win->allocation.y = y;
116 win->allocation.w = w;
117 win->allocation.h = h;
118 win->saved_allocation = win->allocation;
119 win->transparent = EINA_FALSE;
120 win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL;
121 win->buffer_type = buffer_type;
124 eina_hash_add(_windows, _ecore_wl_window_id_str_get(win->id), win);
129 * Deletes the given window
131 * @param win The given window
133 * @ingroup Ecore_Wl_Window_Group
137 ecore_wl_window_free(Ecore_Wl_Window *win)
139 Ecore_Wl_Input *input;
141 LOGFN(__FILE__, __LINE__, __FUNCTION__);
145 eina_hash_del(_windows, _ecore_wl_window_id_str_get(win->id), win);
147 wl_list_for_each(input, &_ecore_wl_disp->inputs, link)
149 if ((input->pointer_focus) && (input->pointer_focus == win))
150 input->pointer_focus = NULL;
151 if ((input->keyboard_focus) && (input->keyboard_focus == win))
152 input->keyboard_focus = NULL;
155 if (win->region.input) wl_region_destroy(win->region.input);
156 win->region.input = NULL;
157 if (win->region.opaque) wl_region_destroy(win->region.opaque);
158 win->region.opaque = NULL;
159 if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface);
160 win->shell_surface = NULL;
162 if (win->surface) wl_surface_destroy(win->surface);
165 /* HMMM, why was this disabled ? */
170 * Signals for Wayland to initiate a window move.
172 * The position requested (@p x, @p y) is not honored by Wayland because
173 * Wayland does not allow specific window placement to be set.
175 * @param win The window to move.
176 * @param x X Position
177 * @param y Y Position
179 * @ingroup Ecore_Wl_Window_Group
183 ecore_wl_window_move(Ecore_Wl_Window *win, int x, int y)
185 LOGFN(__FILE__, __LINE__, __FUNCTION__);
189 win->allocation.x = x;
190 win->allocation.y = y;
192 if (win->shell_surface)
194 Ecore_Wl_Input *input;
196 if (!(input = win->keyboard_device))
200 if (!(input = win->parent->keyboard_device))
201 input = win->parent->pointer_device;
205 if ((!input) || (!input->seat)) return;
207 wl_shell_surface_move(win->shell_surface, input->seat,
208 input->display->serial);
213 * Signals for Wayland to initiate a window resize.
215 * The size requested (@p w, @p h) is not honored by Wayland because
216 * Wayland does not allow specific window sizes to be set.
218 * @param win The window to resize.
221 * @param location The edge of the window from where the resize should start.
223 * @ingroup Ecore_Wl_Window_Group
227 ecore_wl_window_resize(Ecore_Wl_Window *win, int w, int h, int location)
229 LOGFN(__FILE__, __LINE__, __FUNCTION__);
233 if (win->type != ECORE_WL_WINDOW_TYPE_FULLSCREEN)
235 win->allocation.w = w;
236 win->allocation.h = h;
239 wl_compositor_create_region(_ecore_wl_disp->wl.compositor);
240 wl_region_add(win->region.input, win->allocation.x, win->allocation.y,
241 win->allocation.w, win->allocation.h);
244 if (!win->transparent)
247 wl_compositor_create_region(_ecore_wl_disp->wl.compositor);
248 wl_region_add(win->region.opaque, win->allocation.x, win->allocation.y,
249 win->allocation.w, win->allocation.h);
252 if (win->shell_surface)
254 Ecore_Wl_Input *input;
256 if (!(input = win->keyboard_device))
260 if (!(input = win->parent->keyboard_device))
261 input = win->parent->pointer_device;
265 if ((!input) || (!input->seat)) return;
267 wl_shell_surface_resize(win->shell_surface, input->seat,
268 input->display->serial, location);
273 ecore_wl_window_damage(Ecore_Wl_Window *win, int x, int y, int w, int h)
275 LOGFN(__FILE__, __LINE__, __FUNCTION__);
279 wl_surface_damage(win->surface, x, y, w, h);
283 ecore_wl_window_commit(Ecore_Wl_Window *win)
285 LOGFN(__FILE__, __LINE__, __FUNCTION__);
289 wl_surface_commit(win->surface);
293 ecore_wl_window_buffer_attach(Ecore_Wl_Window *win, struct wl_buffer *buffer, int x, int y)
295 LOGFN(__FILE__, __LINE__, __FUNCTION__);
299 switch (win->buffer_type)
301 case ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW:
302 win->server_allocation = win->allocation;
304 case ECORE_WL_WINDOW_BUFFER_TYPE_EGL_IMAGE:
305 case ECORE_WL_WINDOW_BUFFER_TYPE_SHM:
308 if (win->edges & 4) // resizing from the left
309 x = win->server_allocation.w - win->allocation.w;
313 if (win->edges & 1) // resizing from the top
314 y = win->server_allocation.h - win->allocation.h;
321 wl_surface_attach(win->surface, buffer, x, y);
322 wl_surface_damage(win->surface, 0, 0,
323 win->allocation.w, win->allocation.h);
324 wl_surface_commit(win->surface);
326 win->server_allocation = win->allocation;
333 if (win->region.input)
335 wl_surface_set_input_region(win->surface, win->region.input);
336 wl_region_destroy(win->region.input);
337 win->region.input = NULL;
340 if (win->region.opaque)
342 wl_surface_set_opaque_region(win->surface, win->region.opaque);
343 wl_region_destroy(win->region.opaque);
344 win->region.opaque = NULL;
351 * Synonymous to "mapping" a window in Wayland System terminology.
353 * @param win The window to show.
355 * @ingroup Ecore_Wl_Window_Group
359 ecore_wl_window_show(Ecore_Wl_Window *win)
361 LOGFN(__FILE__, __LINE__, __FUNCTION__);
364 if (win->surface) return;
366 win->surface = wl_compositor_create_surface(_ecore_wl_disp->wl.compositor);
367 wl_surface_set_user_data(win->surface, win);
368 /* wl_surface_add_listener(win->surface, &_ecore_wl_surface_listener, win); */
370 if (win->type != ECORE_WL_WINDOW_TYPE_NONE)
373 wl_shell_get_shell_surface(_ecore_wl_disp->wl.shell, win->surface);
374 wl_shell_surface_add_listener(win->shell_surface,
375 &_ecore_wl_shell_surface_listener, win);
380 case ECORE_WL_WINDOW_TYPE_FULLSCREEN:
381 wl_shell_surface_set_fullscreen(win->shell_surface,
382 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
385 case ECORE_WL_WINDOW_TYPE_MAXIMIZED:
386 wl_shell_surface_set_maximized(win->shell_surface, NULL);
388 case ECORE_WL_WINDOW_TYPE_TRANSIENT:
389 wl_shell_surface_set_transient(win->shell_surface,
390 win->parent->surface,
391 win->allocation.x, win->allocation.y, 0);
393 case ECORE_WL_WINDOW_TYPE_MENU:
394 wl_shell_surface_set_popup(win->shell_surface,
395 _ecore_wl_disp->input->seat,
396 _ecore_wl_disp->serial,
397 win->parent->surface,
398 win->allocation.x, win->allocation.y, 0);
400 case ECORE_WL_WINDOW_TYPE_TOPLEVEL:
401 wl_shell_surface_set_toplevel(win->shell_surface);
407 /* if (win->type != ECORE_WL_WINDOW_TYPE_FULLSCREEN) */
409 /* win->region.input = */
410 /* wl_compositor_create_region(_ecore_wl_disp->wl.compositor); */
411 /* wl_region_add(win->region.input, win->allocation.x, win->allocation.y, */
412 /* win->allocation.w, win->allocation.h); */
415 /* if (!win->transparent) */
417 /* win->region.opaque = */
418 /* wl_compositor_create_region(_ecore_wl_disp->wl.compositor); */
419 /* wl_region_add(win->region.opaque, win->allocation.x, win->allocation.y, */
420 /* win->allocation.w, win->allocation.h); */
427 * Synonymous to "unmapping" a window in Wayland System terminology.
429 * @param win The window to hide.
431 * @ingroup Ecore_Wl_Window_Group
435 ecore_wl_window_hide(Ecore_Wl_Window *win)
437 LOGFN(__FILE__, __LINE__, __FUNCTION__);
440 if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface);
441 win->shell_surface = NULL;
442 if (win->surface) wl_surface_destroy(win->surface);
449 * @param win The window to raise.
451 * @ingroup Ecore_Wl_Window_Group
455 ecore_wl_window_raise(Ecore_Wl_Window *win)
457 LOGFN(__FILE__, __LINE__, __FUNCTION__);
460 if (win->shell_surface)
461 wl_shell_surface_set_toplevel(win->shell_surface);
465 ecore_wl_window_maximized_set(Ecore_Wl_Window *win, Eina_Bool maximized)
467 LOGFN(__FILE__, __LINE__, __FUNCTION__);
471 if ((win->type == ECORE_WL_WINDOW_TYPE_MAXIMIZED) == maximized) return;
472 if (win->type == ECORE_WL_WINDOW_TYPE_TOPLEVEL)
474 win->saved_allocation = win->allocation;
475 if (win->shell_surface)
476 wl_shell_surface_set_maximized(win->shell_surface, NULL);
477 win->type = ECORE_WL_WINDOW_TYPE_MAXIMIZED;
479 else if (win->type == ECORE_WL_WINDOW_TYPE_MAXIMIZED)
481 if (win->shell_surface)
482 wl_shell_surface_set_toplevel(win->shell_surface);
483 win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL;
484 _ecore_wl_window_configure_send(win, win->saved_allocation.w,
485 win->saved_allocation.h);
491 ecore_wl_window_fullscreen_set(Ecore_Wl_Window *win, Eina_Bool fullscreen)
493 LOGFN(__FILE__, __LINE__, __FUNCTION__);
496 if ((win->type == ECORE_WL_WINDOW_TYPE_FULLSCREEN) == fullscreen) return;
499 win->type = ECORE_WL_WINDOW_TYPE_FULLSCREEN;
500 win->saved_allocation = win->allocation;
501 if (win->shell_surface)
502 wl_shell_surface_set_fullscreen(win->shell_surface,
503 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
508 if (win->shell_surface)
509 wl_shell_surface_set_toplevel(win->shell_surface);
510 win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL;
511 _ecore_wl_window_configure_send(win, win->saved_allocation.w,
512 win->saved_allocation.h);
518 ecore_wl_window_transparent_set(Ecore_Wl_Window *win, Eina_Bool transparent)
520 LOGFN(__FILE__, __LINE__, __FUNCTION__);
523 win->transparent = transparent;
524 if (win->region.opaque) wl_region_destroy(win->region.opaque);
525 win->region.opaque = NULL;
526 if (!win->transparent)
529 wl_compositor_create_region(_ecore_wl_disp->wl.compositor);
530 wl_region_add(win->region.opaque, win->allocation.x, win->allocation.y,
531 win->allocation.w, win->allocation.h);
536 ecore_wl_window_update_size(Ecore_Wl_Window *win, int w, int h)
538 LOGFN(__FILE__, __LINE__, __FUNCTION__);
541 win->allocation.w = w;
542 win->allocation.h = h;
546 ecore_wl_window_update_location(Ecore_Wl_Window *win, int x, int y)
548 LOGFN(__FILE__, __LINE__, __FUNCTION__);
551 win->allocation.x = x;
552 win->allocation.y = y;
555 EAPI struct wl_surface *
556 ecore_wl_window_surface_get(Ecore_Wl_Window *win)
558 LOGFN(__FILE__, __LINE__, __FUNCTION__);
560 if (!win) return NULL;
565 EAPI struct wl_shell_surface *
566 ecore_wl_window_shell_surface_get(Ecore_Wl_Window *win)
568 LOGFN(__FILE__, __LINE__, __FUNCTION__);
570 if (!win) return NULL;
571 return win->shell_surface;
574 EAPI Ecore_Wl_Window *
575 ecore_wl_window_find(unsigned int id)
577 Ecore_Wl_Window *win = NULL;
579 win = eina_hash_find(_windows, _ecore_wl_window_id_str_get(id));
584 ecore_wl_window_type_set(Ecore_Wl_Window *win, Ecore_Wl_Window_Type type)
586 LOGFN(__FILE__, __LINE__, __FUNCTION__);
593 ecore_wl_window_pointer_set(Ecore_Wl_Window *win, struct wl_surface *surface, int hot_x, int hot_y)
595 Ecore_Wl_Input *input;
597 LOGFN(__FILE__, __LINE__, __FUNCTION__);
601 if ((input = win->pointer_device))
602 ecore_wl_input_pointer_set(input, surface, hot_x, hot_y);
606 ecore_wl_window_cursor_from_name_set(Ecore_Wl_Window *win, const char *cursor_name)
608 Ecore_Wl_Input *input;
610 LOGFN(__FILE__, __LINE__, __FUNCTION__);
614 if ((input = win->pointer_device))
615 ecore_wl_input_cursor_from_name_set(input, cursor_name);
619 ecore_wl_window_cursor_default_restore(Ecore_Wl_Window *win)
621 Ecore_Wl_Input *input;
623 LOGFN(__FILE__, __LINE__, __FUNCTION__);
627 if ((input = win->pointer_device))
628 ecore_wl_input_cursor_default_restore(input);
633 ecore_wl_window_parent_set(Ecore_Wl_Window *win, Ecore_Wl_Window *parent)
635 LOGFN(__FILE__, __LINE__, __FUNCTION__);
637 win->parent = parent;
640 /* local functions */
642 _ecore_wl_window_cb_ping(void *data __UNUSED__, struct wl_shell_surface *shell_surface, unsigned int serial)
644 if (!shell_surface) return;
645 wl_shell_surface_pong(shell_surface, serial);
649 _ecore_wl_window_cb_configure(void *data, struct wl_shell_surface *shell_surface __UNUSED__, unsigned int edges, int w, int h)
651 Ecore_Wl_Window *win;
653 LOGFN(__FILE__, __LINE__, __FUNCTION__);
655 if (!(win = data)) return;
657 if ((w <= 0) || (h <= 0)) return;
659 if ((win->allocation.w != w) || (win->allocation.h != h))
661 if (win->type == ECORE_WL_WINDOW_TYPE_TOPLEVEL)
663 if (win->region.input) wl_region_destroy(win->region.input);
664 win->region.input = NULL;
665 if (win->region.opaque) wl_region_destroy(win->region.opaque);
666 win->region.opaque = NULL;
668 _ecore_wl_window_configure_send(win, w, h);
673 _ecore_wl_window_cb_popup_done(void *data, struct wl_shell_surface *shell_surface __UNUSED__)
675 Ecore_Wl_Window *win;
677 LOGFN(__FILE__, __LINE__, __FUNCTION__);
679 if (!shell_surface) return;
680 if (!(win = data)) return;
681 ecore_wl_input_ungrab(win->pointer_device);
685 _ecore_wl_window_cb_surface_enter(void *data, struct wl_surface *surface, struct wl_output *output __UNUSED__)
687 Ecore_Wl_Window *win;
689 LOGFN(__FILE__, __LINE__, __FUNCTION__);
691 if (!surface) return;
692 if (!(win = data)) return;
696 _ecore_wl_window_cb_surface_leave(void *data, struct wl_surface *surface, struct wl_output *output __UNUSED__)
698 Ecore_Wl_Window *win;
700 LOGFN(__FILE__, __LINE__, __FUNCTION__);
702 if (!surface) return;
703 if (!(win = data)) return;
707 _ecore_wl_window_configure_send(Ecore_Wl_Window *win, int w, int h)
709 Ecore_Wl_Event_Window_Configure *ev;
711 LOGFN(__FILE__, __LINE__, __FUNCTION__);
713 if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Window_Configure)))) return;
715 ev->event_win = win->id;
716 ev->x = win->allocation.x;
717 ev->y = win->allocation.y;
720 ecore_event_add(ECORE_WL_EVENT_WINDOW_CONFIGURE, ev, NULL, NULL);
724 _ecore_wl_window_id_str_get(unsigned int win_id)
726 const char *vals = "qWeRtYuIoP5$&<~";
731 id[0] = vals[(val >> 28) & 0xf];
732 id[1] = vals[(val >> 24) & 0xf];
733 id[2] = vals[(val >> 20) & 0xf];
734 id[3] = vals[(val >> 16) & 0xf];
735 id[4] = vals[(val >> 12) & 0xf];
736 id[5] = vals[(val >> 8) & 0xf];
737 id[6] = vals[(val >> 4) & 0xf];
738 id[7] = vals[(val) & 0xf];