1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #include "ecore_wl2_private.h"
6 #include "efl-hints-client-protocol.h"
7 
8 static void _ecore_wl2_window_hide_send(Ecore_Wl2_Window *window);
9 
10 void
_ecore_wl2_window_semi_free(Ecore_Wl2_Window * window)11 _ecore_wl2_window_semi_free(Ecore_Wl2_Window *window)
12 {
13    if (window->xdg_popup) xdg_popup_destroy(window->xdg_popup);
14    window->xdg_popup = NULL;
15 
16    if (window->xdg_toplevel) xdg_toplevel_destroy(window->xdg_toplevel);
17    window->xdg_toplevel = NULL;
18 
19    if (window->xdg_surface) xdg_surface_destroy(window->xdg_surface);
20    window->xdg_surface = NULL;
21 
22    if (window->zxdg_popup) zxdg_popup_v6_destroy(window->zxdg_popup);
23    window->zxdg_popup = NULL;
24 
25    if (window->zxdg_toplevel) zxdg_toplevel_v6_destroy(window->zxdg_toplevel);
26    window->zxdg_toplevel = NULL;
27 
28    if (window->zxdg_surface) zxdg_surface_v6_destroy(window->zxdg_surface);
29    window->zxdg_surface = NULL;
30 
31    if (window->www_surface)
32      www_surface_destroy(window->www_surface);
33    window->www_surface = NULL;
34 
35    if (window->surface) wl_surface_destroy(window->surface);
36    window->surface = NULL;
37    window->surface_id = -1;
38 
39    if (window->callback) wl_callback_destroy(window->callback);
40    window->callback = NULL;
41 
42    window->outputs = eina_list_free(window->outputs);
43 
44    ecore_wl2_window_surface_flush(window, EINA_TRUE);
45 
46    window->commit_pending = EINA_FALSE;
47 }
48 
49 static void
_ecore_wl2_window_activate_send(Ecore_Wl2_Window * window)50 _ecore_wl2_window_activate_send(Ecore_Wl2_Window *window)
51 {
52    Ecore_Wl2_Event_Window_Activate *ev;
53 
54    ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Activate));
55    if (!ev) return;
56 
57    ev->win = window;
58    if (window->parent)
59      ev->parent_win = window->parent;
60    ev->event_win = window;
61    ecore_event_add(ECORE_WL2_EVENT_WINDOW_ACTIVATE, ev, NULL, NULL);
62 }
63 
64 static void
_ecore_wl2_window_deactivate_send(Ecore_Wl2_Window * window)65 _ecore_wl2_window_deactivate_send(Ecore_Wl2_Window *window)
66 {
67    Ecore_Wl2_Event_Window_Deactivate *ev;
68 
69    ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Deactivate));
70    if (!ev) return;
71 
72    ev->win = window;
73    if (window->parent)
74      ev->parent_win = window->parent;
75    ev->event_win = window;
76    ecore_event_add(ECORE_WL2_EVENT_WINDOW_DEACTIVATE, ev, NULL, NULL);
77 }
78 
79 static void
_ecore_wl2_window_configure_send(Ecore_Wl2_Window * win)80 _ecore_wl2_window_configure_send(Ecore_Wl2_Window *win)
81 {
82    Ecore_Wl2_Event_Window_Configure *ev;
83 
84    ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Configure));
85    if (!ev) return;
86 
87    ev->win = win;
88    ev->event_win = win;
89 
90    if ((win->set_config.geometry.w == win->def_config.geometry.w) &&
91        (win->set_config.geometry.h == win->def_config.geometry.h))
92      ev->w = ev->h = 0;
93    else if ((!win->def_config.geometry.w) && (!win->def_config.geometry.h) &&
94             (!win->def_config.fullscreen) &&
95             (!win->def_config.maximized) &&
96             ((win->def_config.fullscreen != win->req_config.fullscreen) ||
97              (win->def_config.maximized != win->req_config.maximized)))
98      ev->w = win->saved.w, ev->h = win->saved.h;
99    else
100      ev->w = win->def_config.geometry.w, ev->h = win->def_config.geometry.h;
101 
102    ev->edges = !!win->def_config.resizing;
103    if (win->def_config.fullscreen)
104      ev->states |= ECORE_WL2_WINDOW_STATE_FULLSCREEN;
105    if (win->def_config.maximized)
106      ev->states |= ECORE_WL2_WINDOW_STATE_MAXIMIZED;
107 
108    win->req_config = win->def_config;
109    ecore_event_add(ECORE_WL2_EVENT_WINDOW_CONFIGURE, ev, NULL, NULL);
110 
111    if (win->def_config.focused)
112      _ecore_wl2_window_activate_send(win);
113    else
114      _ecore_wl2_window_deactivate_send(win);
115 }
116 
117 static void
_configure_complete(Ecore_Wl2_Window * window)118 _configure_complete(Ecore_Wl2_Window *window)
119 {
120    Ecore_Wl2_Event_Window_Configure_Complete *ev;
121 
122    window->pending.configure = EINA_FALSE;
123 
124    ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Configure_Complete));
125    if (!ev) return;
126 
127    ev->win = window;
128    ecore_event_add(ECORE_WL2_EVENT_WINDOW_CONFIGURE_COMPLETE, ev, NULL, NULL);
129 
130 }
131 
132 #include "window_v6.x"
133 
134 static void
_www_surface_end_drag(void * data,struct www_surface * www_surface EINA_UNUSED)135 _www_surface_end_drag(void *data, struct www_surface *www_surface EINA_UNUSED)
136 {
137    Ecore_Wl2_Window *window = data;
138    Ecore_Wl2_Event_Window_WWW_Drag *ev;
139 
140    ev = malloc(sizeof(Ecore_Wl2_Event_Window_WWW_Drag));
141    EINA_SAFETY_ON_NULL_RETURN(ev);
142    ev->window = window;
143    ev->dragging = 0;
144 
145    ecore_event_add(_ecore_wl2_event_window_www_drag, ev, NULL, NULL);
146 }
147 
148 static void
_www_surface_start_drag(void * data,struct www_surface * www_surface EINA_UNUSED)149 _www_surface_start_drag(void *data, struct www_surface *www_surface EINA_UNUSED)
150 {
151    Ecore_Wl2_Window *window = data;
152    Ecore_Wl2_Event_Window_WWW_Drag *ev;
153 
154    ev = malloc(sizeof(Ecore_Wl2_Event_Window_WWW_Drag));
155    EINA_SAFETY_ON_NULL_RETURN(ev);
156    ev->window = window;
157    ev->dragging = 1;
158 
159    ecore_event_add(_ecore_wl2_event_window_www_drag, ev, NULL, NULL);
160 }
161 
162 static void
_www_surface_status(void * data,struct www_surface * www_surface EINA_UNUSED,int32_t x_rel,int32_t y_rel,uint32_t timestamp)163 _www_surface_status(void *data, struct www_surface *www_surface EINA_UNUSED, int32_t x_rel, int32_t y_rel, uint32_t timestamp)
164 {
165    Ecore_Wl2_Window *window = data;
166    Ecore_Wl2_Event_Window_WWW *ev;
167 
168    ev = malloc(sizeof(Ecore_Wl2_Event_Window_WWW));
169    EINA_SAFETY_ON_NULL_RETURN(ev);
170    ev->window = window;
171    ev->x_rel = x_rel;
172    ev->y_rel = y_rel;
173    ev->timestamp = timestamp;
174 
175    ecore_event_add(_ecore_wl2_event_window_www, ev, NULL, NULL);
176 }
177 
178 static struct www_surface_listener _www_surface_listener =
179 {
180    .status = _www_surface_status,
181    .start_drag = _www_surface_start_drag,
182    .end_drag = _www_surface_end_drag,
183 };
184 
185 void
_ecore_wl2_window_www_surface_init(Ecore_Wl2_Window * window)186 _ecore_wl2_window_www_surface_init(Ecore_Wl2_Window *window)
187 {
188    if (!window->surface) return;
189    if (!window->display->wl.www) return;
190    if (window->www_surface) return;
191    window->www_surface = www_create(window->display->wl.www, window->surface);
192    www_surface_set_user_data(window->www_surface, window);
193    www_surface_add_listener(window->www_surface, &_www_surface_listener,
194                             window);
195 }
196 
197 
198 static void
_xdg_surface_cb_configure(void * data,struct xdg_surface * xdg_surface EINA_UNUSED,uint32_t serial)199 _xdg_surface_cb_configure(void *data, struct xdg_surface *xdg_surface EINA_UNUSED, uint32_t serial)
200 {
201    Ecore_Wl2_Window *window;
202 
203    window = data;
204    window->def_config.serial = serial;
205 
206    if (window->pending.configure)
207      {
208         window->saved.w = window->set_config.geometry.w;
209         window->saved.h = window->set_config.geometry.h;
210      }
211    if (window->pending.configure && window->updating)
212      ERR("Window shouldn't be rendering before initial configure");
213 
214    if (!window->updating)
215      _ecore_wl2_window_configure_send(window);
216 
217    if (window->pending.configure)
218      _configure_complete(window);
219 }
220 
221 static const struct xdg_surface_listener _xdg_surface_listener =
222 {
223    _xdg_surface_cb_configure,
224 };
225 
226 static void
_xdg_toplevel_cb_configure(void * data,struct xdg_toplevel * xdg_toplevel EINA_UNUSED,int32_t width,int32_t height,struct wl_array * states)227 _xdg_toplevel_cb_configure(void *data, struct xdg_toplevel *xdg_toplevel EINA_UNUSED, int32_t width, int32_t height, struct wl_array *states)
228 {
229    Ecore_Wl2_Window *win = data;
230    uint32_t *s;
231 
232    win->def_config.maximized = EINA_FALSE;
233    win->def_config.fullscreen = EINA_FALSE;
234    win->def_config.focused = EINA_FALSE;
235    win->def_config.resizing = EINA_FALSE;
236    win->def_config.geometry.w = width;
237    win->def_config.geometry.h = height;
238 
239    wl_array_for_each(s, states)
240      {
241         switch (*s)
242           {
243            case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED:
244              win->def_config.maximized = EINA_TRUE;
245              break;
246            case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
247              win->def_config.fullscreen = EINA_TRUE;
248              break;
249            case ZXDG_TOPLEVEL_V6_STATE_RESIZING:
250              win->def_config.resizing = EINA_TRUE;
251              break;
252            case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED:
253              win->def_config.focused = EINA_TRUE;
254            default:
255              break;
256           }
257      }
258 }
259 
260 static void
_xdg_toplevel_cb_close(void * data,struct xdg_toplevel * xdg_toplevel EINA_UNUSED)261 _xdg_toplevel_cb_close(void *data, struct xdg_toplevel *xdg_toplevel EINA_UNUSED)
262 {
263    Ecore_Wl2_Window *win;
264 
265    win = data;
266    if (!win) return;
267    if (win->cb_close)
268      {
269         win->cb_close(win->cb_close_data, win);
270         win->cb_close = NULL;
271      }
272    ecore_wl2_window_free(win);
273 }
274 
275 static const struct xdg_toplevel_listener _xdg_toplevel_listener =
276 {
277    _xdg_toplevel_cb_configure,
278    _xdg_toplevel_cb_close,
279 };
280 
281 static void
_xdg_popup_cb_configure(void * data,struct xdg_popup * xdg_popup EINA_UNUSED,int32_t x EINA_UNUSED,int32_t y EINA_UNUSED,int32_t width,int32_t height)282 _xdg_popup_cb_configure(void *data, struct xdg_popup *xdg_popup EINA_UNUSED, int32_t x EINA_UNUSED, int32_t y EINA_UNUSED, int32_t width, int32_t height)
283 {
284    Ecore_Wl2_Window *win = data;
285    win->def_config.geometry.w = width;
286    win->def_config.geometry.h = height;
287 }
288 
289 static void
_xdg_popup_cb_done(void * data,struct xdg_popup * xdg_popup EINA_UNUSED)290 _xdg_popup_cb_done(void *data, struct xdg_popup *xdg_popup EINA_UNUSED)
291 {
292    Ecore_Wl2_Window *win;
293 
294    win = data;
295    if (!win) return;
296 
297    if (win->grab) _ecore_wl2_input_ungrab(win->grab);
298 
299    _ecore_wl2_window_hide_send(win);
300 }
301 
302 static const struct xdg_popup_listener _xdg_popup_listener =
303 {
304    _xdg_popup_cb_configure,
305    _xdg_popup_cb_done,
306 };
307 
308 static void
_ecore_wl2_window_xdg_popup_create(Ecore_Wl2_Window * win)309 _ecore_wl2_window_xdg_popup_create(Ecore_Wl2_Window *win)
310 {
311    int gw, gh;
312    struct xdg_positioner *pos;
313 
314    EINA_SAFETY_ON_NULL_RETURN(win->parent);
315    pos = xdg_wm_base_create_positioner(win->display->wl.xdg_wm_base);
316    if (!pos) return;
317 
318    ecore_wl2_window_geometry_get(win, NULL, NULL, &gw, &gh);
319    xdg_positioner_set_anchor_rect(pos, 0, 0, 1, 1);
320    xdg_positioner_set_size(pos, gw, gh);
321    xdg_positioner_set_anchor(pos, XDG_POSITIONER_ANCHOR_TOP_LEFT);
322    xdg_positioner_set_gravity(pos, ZXDG_POSITIONER_V6_ANCHOR_BOTTOM |
323                                   ZXDG_POSITIONER_V6_ANCHOR_RIGHT);
324 
325    win->xdg_popup = xdg_surface_get_popup(win->xdg_surface,
326                                win->parent->xdg_surface, pos);
327 
328    xdg_positioner_destroy(pos);
329    if (win->grab)
330      xdg_popup_grab(win->xdg_popup, win->grab->wl.seat,
331                         wl_display_get_serial(win->display->wl.display));
332    xdg_popup_set_user_data(win->xdg_popup, win);
333    xdg_popup_add_listener(win->xdg_popup, &_xdg_popup_listener, win);
334 
335    win->pending.configure = EINA_TRUE;
336 
337    ecore_wl2_window_commit(win, EINA_TRUE);
338 }
339 
340 static void
_window_shell_surface_create(Ecore_Wl2_Window * window)341 _window_shell_surface_create(Ecore_Wl2_Window *window)
342 {
343    if (window->xdg_surface) return;
344    window->xdg_surface =
345      xdg_wm_base_get_xdg_surface(window->display->wl.xdg_wm_base,
346                                    window->surface);
347    xdg_surface_set_user_data(window->xdg_surface, window);
348    xdg_surface_add_listener(window->xdg_surface,
349                                 &_xdg_surface_listener, window);
350 
351    window->xdg_configure_ack = xdg_surface_ack_configure;
352    window->pending.configure = EINA_TRUE;
353    if (window->display->wl.efl_hints)
354      {
355         if (window->aspect.set)
356           efl_hints_set_aspect(window->display->wl.efl_hints, window->xdg_surface,
357             window->aspect.w, window->aspect.h, window->aspect.aspect);
358         if (window->weight.set)
359           efl_hints_set_weight(window->display->wl.efl_hints, window->xdg_surface,
360             window->weight.w, window->weight.h);
361      }
362 
363    if (window->type == ECORE_WL2_WINDOW_TYPE_MENU)
364      _ecore_wl2_window_xdg_popup_create(window);
365    else
366      {
367         struct xdg_toplevel *ptop = NULL;
368 
369         window->xdg_toplevel =
370           xdg_surface_get_toplevel(window->xdg_surface);
371         xdg_toplevel_set_user_data(window->xdg_toplevel, window);
372         xdg_toplevel_add_listener(window->xdg_toplevel,
373                                       &_xdg_toplevel_listener, window);
374 
375         if (window->deferred_minimize)
376           xdg_toplevel_set_minimized(window->xdg_toplevel);
377         window->deferred_minimize = EINA_FALSE;
378 
379         if (window->title)
380           xdg_toplevel_set_title(window->xdg_toplevel, window->title);
381         if (window->class)
382           xdg_toplevel_set_app_id(window->xdg_toplevel, window->class);
383 
384         window->xdg_set_min_size = xdg_toplevel_set_min_size;
385         window->xdg_set_max_size = xdg_toplevel_set_max_size;
386 
387         if (window->parent)
388           ptop = window->parent->xdg_toplevel;
389 
390         if (ptop)
391           xdg_toplevel_set_parent(window->xdg_toplevel, ptop);
392 
393         if (window->set_config.maximized)
394           xdg_toplevel_set_maximized(window->xdg_toplevel);
395 
396         if (window->set_config.fullscreen)
397           xdg_toplevel_set_fullscreen(window->xdg_toplevel, NULL);
398      }
399 
400    ecore_wl2_window_commit(window, EINA_TRUE);
401 }
402 
403 void
_ecore_wl2_window_shell_surface_init(Ecore_Wl2_Window * window)404 _ecore_wl2_window_shell_surface_init(Ecore_Wl2_Window *window)
405 {
406    if (!window->surface) return;
407    if (window->display->wl.xdg_wm_base) _window_shell_surface_create(window);
408    if (window->display->wl.zxdg_shell) _window_v6_shell_surface_create(window);
409 
410    if (window->display->wl.session_recovery)
411      {
412         if (window->uuid)
413           {
414              int gx, gy, gw, gh;
415 
416              zwp_e_session_recovery_set_uuid(window->display->wl.session_recovery,
417                                              window->surface, window->uuid);
418 
419              ecore_wl2_window_geometry_get(window, &gx, &gy, &gw, &gh);
420              if (window->xdg_surface)
421                xdg_surface_set_window_geometry(window->xdg_surface,
422                                                gx, gy, gw, gh);
423              if (window->zxdg_surface)
424                zxdg_surface_v6_set_window_geometry(window->zxdg_surface,
425                                                    gx, gy, gw, gh);
426 
427              ecore_wl2_window_opaque_region_set(window,
428                                                 window->opaque.x,
429                                                 window->opaque.y,
430                                                 window->opaque.w,
431                                                 window->opaque.h);
432           }
433         else
434           zwp_e_session_recovery_get_uuid(window->display->wl.session_recovery, window->surface);
435      }
436 }
437 
438 static void
_surface_enter(void * data,struct wl_surface * surf EINA_UNUSED,struct wl_output * op)439 _surface_enter(void *data, struct wl_surface *surf EINA_UNUSED, struct wl_output *op)
440 {
441    Ecore_Wl2_Window *win;
442    Ecore_Wl2_Output *output;
443 
444    win = data;
445 
446    output = _ecore_wl2_output_find(win->display, op);
447    EINA_SAFETY_ON_NULL_RETURN(output);
448 
449    win->outputs = eina_list_append(win->outputs, output);
450 }
451 
452 static void
_surface_leave(void * data,struct wl_surface * surf EINA_UNUSED,struct wl_output * op)453 _surface_leave(void *data, struct wl_surface *surf EINA_UNUSED, struct wl_output *op)
454 {
455    Ecore_Wl2_Window *win;
456    Ecore_Wl2_Output *output;
457 
458    win = data;
459    output = _ecore_wl2_output_find(win->display, op);
460    EINA_SAFETY_ON_NULL_RETURN(output);
461 
462    win->outputs = eina_list_remove(win->outputs, output);
463    if (!win->outputs)
464      {
465         Ecore_Wl2_Event_Window_Offscreen *ev;
466         ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Offscreen));
467         if (ev)
468           {
469              ev->win = win;
470              ecore_event_add(ECORE_WL2_EVENT_WINDOW_OFFSCREEN, ev, NULL, NULL);
471           }
472      }
473 }
474 
475 static const struct wl_surface_listener _surface_listener =
476 {
477    _surface_enter,
478    _surface_leave,
479 };
480 
481 void
_ecore_wl2_window_surface_create(Ecore_Wl2_Window * window)482 _ecore_wl2_window_surface_create(Ecore_Wl2_Window *window)
483 {
484    if (!window->display->wl.compositor) return;
485 
486    if (!window->surface)
487      {
488         window->surface =
489           wl_compositor_create_surface(window->display->wl.compositor);
490         if (!window->surface)
491           {
492              ERR("Failed to create surface for window");
493              return;
494           }
495         wl_surface_set_user_data(window->surface, window);
496 
497         window->surface_id =
498           wl_proxy_get_id((struct wl_proxy *)window->surface);
499 
500         wl_surface_add_listener(window->surface, &_surface_listener, window);
501         if (window->display->wl.efl_aux_hints)
502           {
503              efl_aux_hints_get_supported_aux_hints(window->display->wl.efl_aux_hints, window->surface);
504              if (_ecore_wl2_display_sync_get())
505                wl_display_roundtrip(window->display->wl.display);
506           }
507      }
508 }
509 
510 static void
_ecore_wl2_window_show_send(Ecore_Wl2_Window * window)511 _ecore_wl2_window_show_send(Ecore_Wl2_Window *window)
512 {
513    Ecore_Wl2_Event_Window_Show *ev;
514 
515    ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Show));
516    if (!ev) return;
517 
518    ev->win = window;
519    if (window->parent)
520      ev->parent_win = window->parent;
521    ev->event_win = window;
522    window->visible = EINA_TRUE;
523    ecore_event_add(ECORE_WL2_EVENT_WINDOW_SHOW, ev, NULL, NULL);
524 }
525 
526 static void
_ecore_wl2_window_hide_send(Ecore_Wl2_Window * window)527 _ecore_wl2_window_hide_send(Ecore_Wl2_Window *window)
528 {
529    Ecore_Wl2_Event_Window_Hide *ev;
530 
531    ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Hide));
532    if (!ev) return;
533 
534    ev->win = window;
535    if (window->parent)
536      ev->parent_win = window->parent;
537    ev->event_win = window;
538    window->visible = EINA_FALSE;
539    ecore_event_add(ECORE_WL2_EVENT_WINDOW_HIDE, ev, NULL, NULL);
540 }
541 
542 static void
_ecore_wl2_window_create_destroy_send(Ecore_Wl2_Window * window,Eina_Bool create)543 _ecore_wl2_window_create_destroy_send(Ecore_Wl2_Window *window, Eina_Bool create)
544 {
545    Ecore_Wl2_Event_Window_Common *ev;
546 
547    ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Common));
548    if (!ev) return;
549 
550    ev->win = window;
551    if (window->parent)
552      ev->parent_win = window->parent;
553    ev->event_win = window;
554 
555    if (create) ecore_event_add(ECORE_WL2_EVENT_WINDOW_CREATE, ev, NULL, NULL);
556    else ecore_event_add(ECORE_WL2_EVENT_WINDOW_DESTROY, ev, NULL, NULL);
557 }
558 
559 EAPI Ecore_Wl2_Window *
ecore_wl2_window_new(Ecore_Wl2_Display * display,Ecore_Wl2_Window * parent,int x,int y,int w,int h)560 ecore_wl2_window_new(Ecore_Wl2_Display *display, Ecore_Wl2_Window *parent, int x, int y, int w, int h)
561 {
562    Ecore_Wl2_Window *win;
563 
564    EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL);
565    if (display->pid) CRI("CANNOT CREATE WINDOW WITH SERVER DISPLAY");
566 
567    /* try to allocate space for window structure */
568    win = calloc(1, sizeof(Ecore_Wl2_Window));
569    if (!win) return NULL;
570    display->refs++;
571 
572    win->display = display;
573    win->parent = parent;
574 
575    win->set_config.geometry.x = x;
576    win->set_config.geometry.y = y;
577    win->set_config.geometry.w = w;
578    win->set_config.geometry.h = h;
579 
580    win->opaque.x = x;
581    win->opaque.y = y;
582    win->opaque.w = w;
583    win->opaque.h = h;
584 
585    win->pending.configure = EINA_TRUE;
586    display->windows =
587      eina_inlist_append(display->windows, EINA_INLIST_GET(win));
588 
589    _ecore_wl2_window_surface_create(win);
590 
591    _ecore_wl2_window_create_destroy_send(win, EINA_TRUE);
592 
593    return win;
594 }
595 
596 EAPI void
ecore_wl2_window_close_callback_set(Ecore_Wl2_Window * window,void (* cb)(void * data,Ecore_Wl2_Window * win),void * data)597 ecore_wl2_window_close_callback_set(Ecore_Wl2_Window *window, void (*cb) (void *data, Ecore_Wl2_Window *win), void *data)
598 {
599    EINA_SAFETY_ON_NULL_RETURN(window);
600    window->cb_close = cb;
601    window->cb_close_data = data;
602 }
603 
604 EAPI struct wl_surface *
ecore_wl2_window_surface_get(Ecore_Wl2_Window * window)605 ecore_wl2_window_surface_get(Ecore_Wl2_Window *window)
606 {
607    EINA_SAFETY_ON_NULL_RETURN_VAL(window, NULL);
608 
609    _ecore_wl2_window_surface_create(window);
610 
611    return window->surface;
612 }
613 
614 EAPI int
ecore_wl2_window_surface_id_get(Ecore_Wl2_Window * window)615 ecore_wl2_window_surface_id_get(Ecore_Wl2_Window *window)
616 {
617    EINA_SAFETY_ON_NULL_RETURN_VAL(window, -1);
618    return window->surface_id;
619 }
620 
621 EAPI void
ecore_wl2_window_show(Ecore_Wl2_Window * window)622 ecore_wl2_window_show(Ecore_Wl2_Window *window)
623 {
624    EINA_SAFETY_ON_NULL_RETURN(window);
625 
626    _ecore_wl2_window_surface_create(window);
627 
628    if (window->input_set)
629      ecore_wl2_window_input_region_set(window, window->input_rect.x,
630                                        window->input_rect.y,
631                                        window->input_rect.w,
632                                        window->input_rect.h);
633    if (window->opaque_set)
634      ecore_wl2_window_opaque_region_set(window, window->opaque.x,
635                                         window->opaque.y, window->opaque.w,
636                                         window->opaque.h);
637 
638    if ((window->type != ECORE_WL2_WINDOW_TYPE_DND) &&
639        (window->type != ECORE_WL2_WINDOW_TYPE_NONE))
640      {
641         _ecore_wl2_window_shell_surface_init(window);
642         _ecore_wl2_window_www_surface_init(window);
643         _ecore_wl2_window_show_send(window);
644      }
645    else
646      _configure_complete(window);
647 }
648 
649 EAPI void
ecore_wl2_window_hide(Ecore_Wl2_Window * window)650 ecore_wl2_window_hide(Ecore_Wl2_Window *window)
651 {
652    EINA_SAFETY_ON_NULL_RETURN(window);
653 
654    _ecore_wl2_window_hide_send(window);
655 
656    if (window->commit_pending)
657      {
658         /* We've probably been hidden while an animator
659          * is ticking.  Cancel the callback.
660          */
661         window->commit_pending = EINA_FALSE;
662         if (window->callback)
663           {
664              wl_callback_destroy(window->callback);
665              window->callback = NULL;
666           }
667      }
668 
669    if (window->surface)
670      {
671         wl_surface_attach(window->surface, NULL, 0, 0);
672         ecore_wl2_window_commit(window, EINA_TRUE);
673         window->commit_pending = EINA_FALSE;
674      }
675 
676    /* The commit added a callback, disconnect it */
677    if (window->callback)
678      {
679         wl_callback_destroy(window->callback);
680         window->callback = NULL;
681      }
682 
683    window->set_config.serial = 0;
684    window->req_config.serial = 0;
685    window->def_config.serial = 0;
686    window->zxdg_configure_ack = NULL;
687    window->xdg_configure_ack = NULL;
688    window->xdg_set_min_size = NULL;
689    window->xdg_set_max_size = NULL;
690    window->zxdg_set_min_size = NULL;
691    window->zxdg_set_max_size = NULL;
692 }
693 
694 static void
_ecore_wl2_window_aux_hint_free(Ecore_Wl2_Window * win)695 _ecore_wl2_window_aux_hint_free(Ecore_Wl2_Window *win)
696 {
697    const char *supported;
698 
699    EINA_LIST_FREE(win->supported_aux_hints, supported)
700      if (supported) eina_stringshare_del(supported);
701 }
702 
703 EAPI void
ecore_wl2_window_free(Ecore_Wl2_Window * window)704 ecore_wl2_window_free(Ecore_Wl2_Window *window)
705 {
706    Ecore_Wl2_Display *display;
707    Ecore_Wl2_Input *input;
708    Ecore_Wl2_Subsurface *subsurf;
709    Eina_Inlist *tmp;
710 
711    EINA_SAFETY_ON_NULL_RETURN(window);
712 
713    if (window->visible) _ecore_wl2_window_hide_send(window);
714 
715    _ecore_wl2_window_create_destroy_send(window, EINA_FALSE);
716 
717    display = window->display;
718 
719    EINA_INLIST_FOREACH(display->inputs, input)
720       _ecore_wl2_input_window_remove(input, window);
721 
722    EINA_INLIST_FOREACH_SAFE(window->subsurfs, tmp, subsurf)
723      _ecore_wl2_subsurf_free(subsurf);
724 
725    _ecore_wl2_window_aux_hint_free(window);
726 
727    if (window->callback) wl_callback_destroy(window->callback);
728    window->callback = NULL;
729 
730    if (window->uuid && window->surface && window->display->wl.session_recovery)
731      zwp_e_session_recovery_destroy_uuid(window->display->wl.session_recovery,
732                                          window->surface, window->uuid);
733 
734    _ecore_wl2_window_semi_free(window);
735 
736    eina_stringshare_replace(&window->uuid, NULL);
737 
738    if (window->title) eina_stringshare_del(window->title);
739    if (window->class) eina_stringshare_del(window->class);
740    if (window->role) eina_stringshare_del(window->role);
741 
742    if (window->wm_rot.available_rots) free(window->wm_rot.available_rots);
743    window->wm_rot.available_rots = NULL;
744 
745    display->windows =
746      eina_inlist_remove(display->windows, EINA_INLIST_GET(window));
747 
748    ecore_wl2_display_disconnect(window->display);
749    free(window);
750 }
751 
752 EAPI void
ecore_wl2_window_move(Ecore_Wl2_Window * window,Ecore_Wl2_Input * input)753 ecore_wl2_window_move(Ecore_Wl2_Window *window, Ecore_Wl2_Input *input)
754 {
755    EINA_SAFETY_ON_NULL_RETURN(window);
756    EINA_SAFETY_ON_NULL_RETURN(window->display->inputs);
757 
758    if (!input)
759      {
760         ERR("NULL input parameter is deprecated");
761         input = EINA_INLIST_CONTAINER_GET(window->display->inputs, Ecore_Wl2_Input);
762      }
763    if (window->xdg_toplevel)
764      xdg_toplevel_move(window->xdg_toplevel, input->wl.seat,
765                            window->display->serial);
766    if (window->zxdg_toplevel)
767      zxdg_toplevel_v6_move(window->zxdg_toplevel, input->wl.seat,
768                            window->display->serial);
769    ecore_wl2_display_flush(window->display);
770 
771    _ecore_wl2_input_ungrab(input);
772 }
773 
774 EAPI void
ecore_wl2_window_resize(Ecore_Wl2_Window * window,Ecore_Wl2_Input * input,int location)775 ecore_wl2_window_resize(Ecore_Wl2_Window *window, Ecore_Wl2_Input *input, int location)
776 {
777    EINA_SAFETY_ON_NULL_RETURN(window);
778    EINA_SAFETY_ON_NULL_RETURN(window->display->inputs);
779 
780    if (!input)
781      {
782         ERR("NULL input parameter is deprecated");
783         input = EINA_INLIST_CONTAINER_GET(window->display->inputs, Ecore_Wl2_Input);
784      }
785 
786    if (window->xdg_toplevel)
787      xdg_toplevel_resize(window->xdg_toplevel, input->wl.seat,
788                              window->display->serial, location);
789    if (window->zxdg_toplevel)
790      zxdg_toplevel_v6_resize(window->zxdg_toplevel, input->wl.seat,
791                              window->display->serial, location);
792    ecore_wl2_display_flush(window->display);
793 
794    _ecore_wl2_input_ungrab(input);
795 }
796 
797 EAPI Eina_Bool
ecore_wl2_window_alpha_get(Ecore_Wl2_Window * window)798 ecore_wl2_window_alpha_get(Ecore_Wl2_Window *window)
799 {
800    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
801 
802    return window->alpha;
803 }
804 
805 EAPI void
ecore_wl2_window_alpha_set(Ecore_Wl2_Window * window,Eina_Bool alpha)806 ecore_wl2_window_alpha_set(Ecore_Wl2_Window *window, Eina_Bool alpha)
807 {
808    Ecore_Wl2_Surface *surf;
809 
810    EINA_SAFETY_ON_NULL_RETURN(window);
811 
812    if (window->alpha == alpha) return;
813 
814    window->alpha = alpha;
815    surf = window->wl2_surface;
816    if (surf)
817      ecore_wl2_surface_reconfigure(surf, surf->w, surf->h, 0, alpha);
818 }
819 
820 EAPI void
ecore_wl2_window_opaque_region_set(Ecore_Wl2_Window * window,int x,int y,int w,int h)821 ecore_wl2_window_opaque_region_set(Ecore_Wl2_Window *window, int x, int y, int w, int h)
822 {
823    int nx = 0, ny = 0, nw = 0, nh = 0;
824 
825    EINA_SAFETY_ON_NULL_RETURN(window);
826 
827    switch (window->rotation)
828      {
829       case 0:
830         nx = x;
831         ny = y;
832         nw = w;
833         nh = h;
834         break;
835       case 90:
836         nx = y;
837         ny = x;
838         nw = h;
839         nh = w;
840         break;
841       case 180:
842         nx = x;
843         ny = x + y;
844         nw = w;
845         nh = h;
846         break;
847       case 270:
848         nx = x + y;
849         ny = x;
850         nw = h;
851         nh = w;
852         break;
853       default:
854         break;
855      }
856 
857    if ((window->opaque.x == nx) && (window->opaque.y == ny) &&
858        (window->opaque.w == nw) && (window->opaque.h == nh))
859      return;
860 
861    window->opaque.x = nx;
862    window->opaque.y = ny;
863    window->opaque.w = nw;
864    window->opaque.h = nh;
865    window->opaque_set = x || y || w || h;
866    window->pending.opaque = EINA_TRUE;
867 }
868 
869 EAPI void
ecore_wl2_window_opaque_region_get(Ecore_Wl2_Window * window,int * x,int * y,int * w,int * h)870 ecore_wl2_window_opaque_region_get(Ecore_Wl2_Window *window, int *x, int *y, int *w, int *h)
871 {
872    EINA_SAFETY_ON_NULL_RETURN(window);
873 
874    if (x) *x = window->opaque.x;
875    if (y) *y = window->opaque.y;
876    if (w) *w = window->opaque.w;
877    if (h) *h = window->opaque.h;
878 }
879 
880 EAPI void
ecore_wl2_window_input_region_set(Ecore_Wl2_Window * window,int x,int y,int w,int h)881 ecore_wl2_window_input_region_set(Ecore_Wl2_Window *window, int x, int y, int w, int h)
882 {
883    int nx = 0, ny = 0, nw = 0, nh = 0;
884 
885    EINA_SAFETY_ON_NULL_RETURN(window);
886 
887    switch (window->rotation)
888      {
889       case 0:
890         nx = x;
891         ny = y;
892         nw = w;
893         nh = h;
894         break;
895       case 90:
896         nx = y;
897         ny = x;
898         nw = h;
899         nh = w;
900         break;
901       case 180:
902         nx = x;
903         ny = x + y;
904         nw = w;
905         nh = h;
906         break;
907       case 270:
908         nx = x + y;
909         ny = x;
910         nw = h;
911         nh = w;
912         break;
913       default:
914         break;
915      }
916 
917    if ((window->input_rect.x == nx) && (window->input_rect.y == ny) &&
918        (window->input_rect.w == nw) && (window->input_rect.h == nh))
919      return;
920 
921    window->input_rect.x = nx;
922    window->input_rect.y = ny;
923    window->input_rect.w = nw;
924    window->input_rect.h = nh;
925    window->input_set = x || y || w || h;
926    window->pending.input = EINA_TRUE;
927 }
928 
929 EAPI void
ecore_wl2_window_input_region_get(Ecore_Wl2_Window * window,int * x,int * y,int * w,int * h)930 ecore_wl2_window_input_region_get(Ecore_Wl2_Window *window, int *x, int *y, int *w, int *h)
931 {
932    EINA_SAFETY_ON_NULL_RETURN(window);
933 
934    if (x) *x = window->input_rect.x;
935    if (y) *y = window->input_rect.y;
936    if (w) *w = window->input_rect.w;
937    if (h) *h = window->input_rect.h;
938 }
939 
940 EAPI Eina_Bool
ecore_wl2_window_maximized_get(Ecore_Wl2_Window * window)941 ecore_wl2_window_maximized_get(Ecore_Wl2_Window *window)
942 {
943    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
944 
945    return window->set_config.maximized;
946 }
947 
948 EAPI void
ecore_wl2_window_maximized_set(Ecore_Wl2_Window * window,Eina_Bool maximized)949 ecore_wl2_window_maximized_set(Ecore_Wl2_Window *window, Eina_Bool maximized)
950 {
951    Eina_Bool prev;
952 
953    EINA_SAFETY_ON_NULL_RETURN(window);
954 
955    prev = window->set_config.maximized;
956    maximized = !!maximized;
957    if (prev == maximized) return;
958 
959    window->set_config.maximized = maximized;
960    if (window->updating)
961      {
962         window->pending.maximized = EINA_TRUE;
963         return;
964      }
965 
966    if (maximized)
967      {
968         if (!window->set_config.fullscreen)
969           window->saved = window->set_config.geometry;
970 
971         if (window->xdg_toplevel)
972           xdg_toplevel_set_maximized(window->xdg_toplevel);
973         if (window->zxdg_toplevel)
974           zxdg_toplevel_v6_set_maximized(window->zxdg_toplevel);
975      }
976    else
977      {
978         if (window->xdg_toplevel)
979           xdg_toplevel_unset_maximized(window->xdg_toplevel);
980         if (window->zxdg_toplevel)
981           zxdg_toplevel_v6_unset_maximized(window->zxdg_toplevel);
982      }
983    ecore_wl2_display_flush(window->display);
984 }
985 
986 EAPI Eina_Bool
ecore_wl2_window_fullscreen_get(Ecore_Wl2_Window * window)987 ecore_wl2_window_fullscreen_get(Ecore_Wl2_Window *window)
988 {
989    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
990 
991    return window->set_config.fullscreen;
992 }
993 
994 EAPI void
ecore_wl2_window_fullscreen_set(Ecore_Wl2_Window * window,Eina_Bool fullscreen)995 ecore_wl2_window_fullscreen_set(Ecore_Wl2_Window *window, Eina_Bool fullscreen)
996 {
997    Eina_Bool prev;
998 
999    EINA_SAFETY_ON_NULL_RETURN(window);
1000 
1001    prev = window->set_config.fullscreen;
1002    fullscreen = !!fullscreen;
1003    if (prev == fullscreen) return;
1004 
1005    window->set_config.fullscreen = fullscreen;
1006    if (window->updating)
1007      {
1008         window->pending.fullscreen = EINA_TRUE;
1009         return;
1010      }
1011 
1012    if (fullscreen)
1013      {
1014         if (!window->set_config.maximized)
1015           window->saved = window->set_config.geometry;
1016 
1017         if (window->xdg_toplevel)
1018           xdg_toplevel_set_fullscreen(window->xdg_toplevel, NULL);
1019         if (window->zxdg_toplevel)
1020           zxdg_toplevel_v6_set_fullscreen(window->zxdg_toplevel, NULL);
1021      }
1022    else
1023      {
1024         if (window->xdg_toplevel)
1025           xdg_toplevel_unset_fullscreen(window->xdg_toplevel);
1026         if (window->zxdg_toplevel)
1027           zxdg_toplevel_v6_unset_fullscreen(window->zxdg_toplevel);
1028      }
1029    ecore_wl2_display_flush(window->display);
1030 }
1031 
1032 EAPI int
ecore_wl2_window_rotation_get(Ecore_Wl2_Window * window)1033 ecore_wl2_window_rotation_get(Ecore_Wl2_Window *window)
1034 {
1035    EINA_SAFETY_ON_NULL_RETURN_VAL(window, -1);
1036 
1037    return window->rotation;
1038 }
1039 
1040 EAPI void
ecore_wl2_window_rotation_set(Ecore_Wl2_Window * window,int rotation)1041 ecore_wl2_window_rotation_set(Ecore_Wl2_Window *window, int rotation)
1042 {
1043    EINA_SAFETY_ON_NULL_RETURN(window);
1044 
1045    window->rotation = rotation;
1046 }
1047 
1048 EAPI void
ecore_wl2_window_title_set(Ecore_Wl2_Window * window,const char * title)1049 ecore_wl2_window_title_set(Ecore_Wl2_Window *window, const char *title)
1050 {
1051    EINA_SAFETY_ON_NULL_RETURN(window);
1052 
1053    eina_stringshare_replace(&window->title, title);
1054    if (!window->title) return;
1055    if (!window->xdg_toplevel && !window->zxdg_toplevel) return;
1056 
1057    if (window->xdg_toplevel)
1058      xdg_toplevel_set_title(window->xdg_toplevel, window->title);
1059    if (window->zxdg_toplevel)
1060      zxdg_toplevel_v6_set_title(window->zxdg_toplevel, window->title);
1061    ecore_wl2_display_flush(window->display);
1062 }
1063 
1064 EAPI const char *
ecore_wl2_window_title_get(Ecore_Wl2_Window * window)1065 ecore_wl2_window_title_get(Ecore_Wl2_Window *window)
1066 {
1067    EINA_SAFETY_ON_NULL_RETURN_VAL(window, NULL);
1068 
1069    return window->title ? window->title : NULL;
1070 }
1071 
1072 EAPI void
ecore_wl2_window_class_set(Ecore_Wl2_Window * window,const char * clas)1073 ecore_wl2_window_class_set(Ecore_Wl2_Window *window, const char *clas)
1074 {
1075    EINA_SAFETY_ON_NULL_RETURN(window);
1076 
1077    eina_stringshare_replace(&window->class, clas);
1078    if (!window->class) return;
1079    if (!window->xdg_toplevel && !window->zxdg_toplevel) return;
1080 
1081    if (window->xdg_toplevel)
1082      xdg_toplevel_set_app_id(window->xdg_toplevel, window->class);
1083    if (window->zxdg_toplevel)
1084      zxdg_toplevel_v6_set_app_id(window->zxdg_toplevel, window->class);
1085    ecore_wl2_display_flush(window->display);
1086 }
1087 
1088 EAPI const char *
ecore_wl2_window_class_get(Ecore_Wl2_Window * window)1089 ecore_wl2_window_class_get(Ecore_Wl2_Window *window)
1090 {
1091    EINA_SAFETY_ON_NULL_RETURN_VAL(window, NULL);
1092 
1093    return window->class ? window->class : NULL;
1094 }
1095 
1096 EAPI void
ecore_wl2_window_geometry_get(Ecore_Wl2_Window * window,int * x,int * y,int * w,int * h)1097 ecore_wl2_window_geometry_get(Ecore_Wl2_Window *window, int *x, int *y, int *w, int *h)
1098 {
1099    EINA_SAFETY_ON_NULL_RETURN(window);
1100 
1101    if (x) *x = window->set_config.geometry.x;
1102    if (y) *y = window->set_config.geometry.y;
1103    if (w) *w = window->set_config.geometry.w;
1104    if (h) *h = window->set_config.geometry.h;
1105 }
1106 
1107 EAPI void
ecore_wl2_window_geometry_set(Ecore_Wl2_Window * window,int x,int y,int w,int h)1108 ecore_wl2_window_geometry_set(Ecore_Wl2_Window *window, int x, int y, int w, int h)
1109 {
1110    EINA_SAFETY_ON_NULL_RETURN(window);
1111 
1112    if ((window->set_config.geometry.x == x) &&
1113        (window->set_config.geometry.y == y) &&
1114        (window->set_config.geometry.w == w) &&
1115        (window->set_config.geometry.h == h))
1116      return;
1117 
1118    window->set_config.geometry.x = x;
1119    window->set_config.geometry.y = y;
1120    window->set_config.geometry.w = w;
1121    window->set_config.geometry.h = h;
1122    window->pending.geom = EINA_TRUE;
1123 }
1124 
1125 EAPI void
ecore_wl2_window_iconified_set(Ecore_Wl2_Window * window,Eina_Bool iconified)1126 ecore_wl2_window_iconified_set(Ecore_Wl2_Window *window, Eina_Bool iconified)
1127 {
1128    EINA_SAFETY_ON_NULL_RETURN(window);
1129 
1130    iconified = !!iconified;
1131 
1132    if (!window->xdg_toplevel && !window->zxdg_toplevel)
1133      {
1134         window->deferred_minimize = iconified;
1135         return;
1136      }
1137 
1138    if (iconified)
1139      {
1140         if (window->xdg_toplevel)
1141           xdg_toplevel_set_minimized(window->xdg_toplevel);
1142         if (window->zxdg_toplevel)
1143           zxdg_toplevel_v6_set_minimized(window->zxdg_toplevel);
1144         ecore_wl2_display_flush(window->display);
1145      }
1146 }
1147 
1148 EAPI void
ecore_wl2_window_type_set(Ecore_Wl2_Window * window,Ecore_Wl2_Window_Type type)1149 ecore_wl2_window_type_set(Ecore_Wl2_Window *window, Ecore_Wl2_Window_Type type)
1150 {
1151    EINA_SAFETY_ON_NULL_RETURN(window);
1152    window->type = type;
1153 }
1154 
1155 EAPI void
ecore_wl2_window_popup_input_set(Ecore_Wl2_Window * window,Ecore_Wl2_Input * input)1156 ecore_wl2_window_popup_input_set(Ecore_Wl2_Window *window, Ecore_Wl2_Input *input)
1157 {
1158    EINA_SAFETY_ON_NULL_RETURN(window);
1159    EINA_SAFETY_ON_NULL_RETURN(input);
1160    EINA_SAFETY_ON_TRUE_RETURN(window->type != ECORE_WL2_WINDOW_TYPE_MENU);
1161    window->grab = input;
1162 }
1163 
1164 EAPI Ecore_Wl2_Input *
ecore_wl2_window_popup_input_get(Ecore_Wl2_Window * window)1165 ecore_wl2_window_popup_input_get(Ecore_Wl2_Window *window)
1166 {
1167    EINA_SAFETY_ON_NULL_RETURN_VAL(window, NULL);
1168 
1169    return window->grab;
1170 }
1171 
1172 EAPI Ecore_Wl2_Display *
ecore_wl2_window_display_get(const Ecore_Wl2_Window * window)1173 ecore_wl2_window_display_get(const Ecore_Wl2_Window *window)
1174 {
1175    EINA_SAFETY_ON_NULL_RETURN_VAL(window, NULL);
1176    EINA_SAFETY_ON_NULL_RETURN_VAL(window->display, NULL);
1177 
1178    if (window->display->recovering) return NULL;
1179 
1180    return window->display;
1181 }
1182 
1183 EAPI Eina_Bool
ecore_wl2_window_shell_surface_exists(Ecore_Wl2_Window * window)1184 ecore_wl2_window_shell_surface_exists(Ecore_Wl2_Window *window)
1185 {
1186    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
1187    return !!window->zxdg_surface || !!window->xdg_surface;
1188 }
1189 
1190 EAPI Eina_Bool
ecore_wl2_window_activated_get(const Ecore_Wl2_Window * window)1191 ecore_wl2_window_activated_get(const Ecore_Wl2_Window *window)
1192 {
1193    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
1194    return window->req_config.focused;
1195 }
1196 
1197 EAPI Ecore_Wl2_Output *
ecore_wl2_window_output_find(Ecore_Wl2_Window * window)1198 ecore_wl2_window_output_find(Ecore_Wl2_Window *window)
1199 {
1200    EINA_SAFETY_ON_NULL_RETURN_VAL(window, NULL);
1201 
1202    return eina_list_data_get(window->outputs);
1203 }
1204 
1205 EAPI void
ecore_wl2_window_buffer_transform_set(Ecore_Wl2_Window * window,int transform)1206 ecore_wl2_window_buffer_transform_set(Ecore_Wl2_Window *window, int transform)
1207 {
1208    EINA_SAFETY_ON_NULL_RETURN(window);
1209 
1210    wl_surface_set_buffer_transform(window->surface, transform);
1211 }
1212 
1213 EAPI void
ecore_wl2_window_wm_rotation_supported_set(Ecore_Wl2_Window * window,Eina_Bool enabled)1214 ecore_wl2_window_wm_rotation_supported_set(Ecore_Wl2_Window *window, Eina_Bool enabled)
1215 {
1216    EINA_SAFETY_ON_NULL_RETURN(window);
1217    window->wm_rot.supported = enabled;
1218 }
1219 
1220 EAPI Eina_Bool
ecore_wl2_window_wm_rotation_supported_get(Ecore_Wl2_Window * window)1221 ecore_wl2_window_wm_rotation_supported_get(Ecore_Wl2_Window *window)
1222 {
1223    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
1224    return window->wm_rot.supported;
1225 }
1226 
1227 EAPI void
ecore_wl2_window_rotation_app_set(Ecore_Wl2_Window * window,Eina_Bool set)1228 ecore_wl2_window_rotation_app_set(Ecore_Wl2_Window *window, Eina_Bool set)
1229 {
1230    EINA_SAFETY_ON_NULL_RETURN(window);
1231    window->wm_rot.app_set = set;
1232 }
1233 
1234 EAPI Eina_Bool
ecore_wl2_window_rotation_app_get(Ecore_Wl2_Window * window)1235 ecore_wl2_window_rotation_app_get(Ecore_Wl2_Window *window)
1236 {
1237    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
1238    return window->wm_rot.app_set;
1239 }
1240 
1241 EAPI void
ecore_wl2_window_preferred_rotation_set(Ecore_Wl2_Window * window,int rot)1242 ecore_wl2_window_preferred_rotation_set(Ecore_Wl2_Window *window, int rot)
1243 {
1244    EINA_SAFETY_ON_NULL_RETURN(window);
1245    window->wm_rot.preferred_rot = rot;
1246 }
1247 
1248 EAPI int
ecore_wl2_window_preferred_rotation_get(Ecore_Wl2_Window * window)1249 ecore_wl2_window_preferred_rotation_get(Ecore_Wl2_Window *window)
1250 {
1251    EINA_SAFETY_ON_NULL_RETURN_VAL(window, 0);
1252    return window->wm_rot.preferred_rot;
1253 }
1254 
1255 EAPI void
ecore_wl2_window_available_rotations_set(Ecore_Wl2_Window * window,const int * rots,unsigned int count)1256 ecore_wl2_window_available_rotations_set(Ecore_Wl2_Window *window, const int *rots, unsigned int count)
1257 {
1258    unsigned int i = 0;
1259    EINA_SAFETY_ON_NULL_RETURN(window);
1260 
1261    if (window->wm_rot.available_rots)
1262      {
1263         free(window->wm_rot.available_rots);
1264         window->wm_rot.available_rots = NULL;
1265      }
1266    window->wm_rot.count = count;
1267 
1268    if (count >= 1)
1269      {
1270         window->wm_rot.available_rots = calloc(count, sizeof(int));
1271         if (!window->wm_rot.available_rots) return;
1272 
1273         for (; i < count; i++)
1274           window->wm_rot.available_rots[i] = ((int *)rots)[i];
1275      }
1276 }
1277 
1278 EAPI Eina_Bool
ecore_wl2_window_available_rotations_get(Ecore_Wl2_Window * window,int ** rots,unsigned int * count)1279 ecore_wl2_window_available_rotations_get(Ecore_Wl2_Window *window, int **rots, unsigned int *count)
1280 {
1281    unsigned int i = 0;
1282    int *val = NULL;
1283 
1284    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
1285 
1286    *rots = NULL;
1287    *count = window->wm_rot.count;
1288 
1289    if (window->wm_rot.count >= 1)
1290      {
1291         val = calloc(window->wm_rot.count, sizeof(int));
1292         if (!val) return EINA_FALSE;
1293 
1294         for (; i < window->wm_rot.count; i++)
1295           val[i] = ((int *)window->wm_rot.available_rots)[i];
1296 
1297         *rots = val;
1298         return EINA_TRUE;
1299      }
1300 
1301    return EINA_FALSE;
1302 }
1303 
1304 EAPI void
ecore_wl2_window_rotation_change_prepare_send(Ecore_Wl2_Window * window,int rot,int w,int h,Eina_Bool resize)1305 ecore_wl2_window_rotation_change_prepare_send(Ecore_Wl2_Window *window, int rot, int w, int h, Eina_Bool resize)
1306 {
1307    Ecore_Wl2_Event_Window_Rotation_Change_Prepare *ev;
1308 
1309    EINA_SAFETY_ON_NULL_RETURN(window);
1310 
1311    ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Rotation_Change_Prepare));
1312    if (!ev) return;
1313 
1314    ev->win = window;
1315    ev->rotation = rot;
1316    ev->w = w;
1317    ev->h = h;
1318    ev->resize = resize;
1319 
1320    ecore_event_add(ECORE_WL2_EVENT_WINDOW_ROTATION_CHANGE_PREPARE, ev, NULL, NULL);
1321 }
1322 
1323 EAPI void
ecore_wl2_window_rotation_change_prepare_done_send(Ecore_Wl2_Window * window,int rot)1324 ecore_wl2_window_rotation_change_prepare_done_send(Ecore_Wl2_Window *window, int rot)
1325 {
1326    Ecore_Wl2_Event_Window_Rotation_Change_Prepare_Done *ev;
1327 
1328    EINA_SAFETY_ON_NULL_RETURN(window);
1329 
1330    ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Rotation_Change_Prepare_Done));
1331    if (!ev) return;
1332 
1333    ev->win = window;
1334    ev->rotation = rot;
1335    ev->w = 0;
1336    ev->h = 0;
1337    ev->resize = 0;
1338 
1339    ecore_event_add(ECORE_WL2_EVENT_WINDOW_ROTATION_CHANGE_PREPARE_DONE,
1340                    ev, NULL, NULL);
1341 }
1342 
1343 EAPI void
ecore_wl2_window_rotation_change_request_send(Ecore_Wl2_Window * window,int rot)1344 ecore_wl2_window_rotation_change_request_send(Ecore_Wl2_Window *window, int rot)
1345 {
1346    Ecore_Wl2_Event_Window_Rotation_Change_Request *ev;
1347 
1348    EINA_SAFETY_ON_NULL_RETURN(window);
1349 
1350    ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Rotation_Change_Request));
1351    if (!ev) return;
1352 
1353    ev->win = window;
1354    ev->rotation = rot;
1355    ev->w = 0;
1356    ev->h = 0;
1357    ev->resize = 0;
1358 
1359    ecore_event_add(ECORE_WL2_EVENT_WINDOW_ROTATION_CHANGE_REQUEST,
1360                    ev, NULL, NULL);
1361 }
1362 
1363 EAPI void
ecore_wl2_window_rotation_change_done_send(Ecore_Wl2_Window * window,int rot,int w,int h)1364 ecore_wl2_window_rotation_change_done_send(Ecore_Wl2_Window *window, int rot, int w, int h)
1365 {
1366    Ecore_Wl2_Event_Window_Rotation_Change_Done *ev;
1367 
1368    EINA_SAFETY_ON_NULL_RETURN(window);
1369 
1370    ev = calloc(1, sizeof(Ecore_Wl2_Event_Window_Rotation_Change_Done));
1371    if (!ev) return;
1372 
1373    ev->win = window;
1374    ev->rotation = rot;
1375    ev->w = w;
1376    ev->h = h;
1377    ev->resize = 0;
1378 
1379    ecore_event_add(ECORE_WL2_EVENT_WINDOW_ROTATION_CHANGE_DONE,
1380                    ev, NULL, NULL);
1381 }
1382 
1383 EAPI Eina_List *
ecore_wl2_window_aux_hints_supported_get(Ecore_Wl2_Window * win)1384 ecore_wl2_window_aux_hints_supported_get(Ecore_Wl2_Window *win)
1385 {
1386    Eina_List *res = NULL;
1387    Eina_List *ll;
1388    char *supported_hint = NULL;
1389    const char *hint = NULL;
1390 
1391    if (!win) return NULL;
1392    if (!win->surface) return NULL;
1393 
1394    EINA_LIST_FOREACH(win->supported_aux_hints, ll, supported_hint)
1395      {
1396         hint = eina_stringshare_add(supported_hint);
1397         res = eina_list_append(res, hint);
1398      }
1399    return res;
1400 }
1401 
1402 EAPI void
ecore_wl2_window_aux_hint_add(Ecore_Wl2_Window * win,int id,const char * hint,const char * val)1403 ecore_wl2_window_aux_hint_add(Ecore_Wl2_Window *win, int id, const char *hint, const char *val)
1404 {
1405    if (!win) return;
1406    if ((!win->surface) || (!win->display->wl.efl_aux_hints)) return;
1407 
1408    efl_aux_hints_add_aux_hint(win->display->wl.efl_aux_hints, win->surface, id, hint, val);
1409    ecore_wl2_display_flush(win->display);
1410 }
1411 
1412 EAPI void
ecore_wl2_window_aux_hint_change(Ecore_Wl2_Window * win,int id,const char * val)1413 ecore_wl2_window_aux_hint_change(Ecore_Wl2_Window *win, int id, const char *val)
1414 {
1415    if (!win) return;
1416    if ((!win->surface) && (!win->display->wl.efl_aux_hints)) return;
1417 
1418    efl_aux_hints_change_aux_hint(win->display->wl.efl_aux_hints, win->surface, id, val);
1419    ecore_wl2_display_flush(win->display);
1420 }
1421 
1422 EAPI void
ecore_wl2_window_aux_hint_del(Ecore_Wl2_Window * win,int id)1423 ecore_wl2_window_aux_hint_del(Ecore_Wl2_Window *win, int id)
1424 {
1425    if (!win) return;
1426    if ((!win->surface) || (!win->display->wl.efl_aux_hints)) return;
1427 
1428    efl_aux_hints_del_aux_hint(win->display->wl.efl_aux_hints, win->surface, id);
1429    ecore_wl2_display_flush(win->display);
1430 }
1431 
1432 EAPI void
ecore_wl2_window_focus_skip_set(Ecore_Wl2_Window * window,Eina_Bool focus_skip)1433 ecore_wl2_window_focus_skip_set(Ecore_Wl2_Window *window, Eina_Bool focus_skip)
1434 {
1435    EINA_SAFETY_ON_NULL_RETURN(window);
1436    window->focus_skip = focus_skip;
1437 }
1438 
1439 EAPI Eina_Bool
ecore_wl2_window_focus_skip_get(Ecore_Wl2_Window * window)1440 ecore_wl2_window_focus_skip_get(Ecore_Wl2_Window *window)
1441 {
1442    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
1443    return window->focus_skip;
1444 }
1445 
1446 EAPI void
ecore_wl2_window_role_set(Ecore_Wl2_Window * window,const char * role)1447 ecore_wl2_window_role_set(Ecore_Wl2_Window *window, const char *role)
1448 {
1449    EINA_SAFETY_ON_NULL_RETURN(window);
1450    eina_stringshare_replace(&window->role, role);
1451 }
1452 
1453 EAPI const char *
ecore_wl2_window_role_get(Ecore_Wl2_Window * window)1454 ecore_wl2_window_role_get(Ecore_Wl2_Window *window)
1455 {
1456    EINA_SAFETY_ON_NULL_RETURN_VAL(window, NULL);
1457 
1458    return window->role ? window->role : NULL;
1459 }
1460 
1461 EAPI void
ecore_wl2_window_floating_mode_set(Ecore_Wl2_Window * window,Eina_Bool floating)1462 ecore_wl2_window_floating_mode_set(Ecore_Wl2_Window *window, Eina_Bool floating)
1463 {
1464    EINA_SAFETY_ON_NULL_RETURN(window);
1465    window->floating = floating;
1466 }
1467 
1468 EAPI Eina_Bool
ecore_wl2_window_floating_mode_get(Ecore_Wl2_Window * window)1469 ecore_wl2_window_floating_mode_get(Ecore_Wl2_Window *window)
1470 {
1471    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
1472    return window->floating;
1473 }
1474 
1475 EAPI void
ecore_wl2_window_aspect_set(Ecore_Wl2_Window * window,int w,int h,unsigned int aspect)1476 ecore_wl2_window_aspect_set(Ecore_Wl2_Window *window, int w, int h, unsigned int aspect)
1477 {
1478    EINA_SAFETY_ON_NULL_RETURN(window);
1479    EINA_SAFETY_ON_TRUE_RETURN(w < 1);
1480    EINA_SAFETY_ON_TRUE_RETURN(h < 1);
1481 
1482    if ((window->aspect.aspect == aspect) && (window->aspect.w == w) &&
1483        (window->aspect.h == h))
1484      return;
1485 
1486    window->aspect.w = w;
1487    window->aspect.h = h;
1488    window->aspect.aspect = aspect;
1489    window->aspect.set = 1;
1490    if (!window->display->wl.efl_hints) return;
1491    if (window->xdg_surface)
1492      efl_hints_set_aspect(window->display->wl.efl_hints,
1493                           window->xdg_surface, w, h, aspect);
1494    ecore_wl2_display_flush(window->display);
1495 }
1496 
1497 EAPI void
ecore_wl2_window_aspect_get(Ecore_Wl2_Window * window,int * w,int * h,unsigned int * aspect)1498 ecore_wl2_window_aspect_get(Ecore_Wl2_Window *window, int *w, int *h, unsigned int *aspect)
1499 {
1500    EINA_SAFETY_ON_NULL_RETURN(window);
1501 
1502    if (w) *w = window->aspect.w;
1503    if (h) *h = window->aspect.h;
1504    if (aspect) *aspect = window->aspect.aspect;
1505 }
1506 
1507 EAPI void
ecore_wl2_window_weight_set(Ecore_Wl2_Window * window,double w,double h)1508 ecore_wl2_window_weight_set(Ecore_Wl2_Window *window, double w, double h)
1509 {
1510    int ww, hh;
1511    EINA_SAFETY_ON_NULL_RETURN(window);
1512 
1513    ww = lround(w * 100);
1514    hh = lround(h * 100);
1515 
1516    if ((window->weight.w == ww) && (window->weight.h == hh))
1517      return;
1518 
1519    window->weight.w = ww;
1520    window->weight.h = hh;
1521    window->weight.set = 1;
1522    if (!window->display->wl.efl_hints) return;
1523    if (window->xdg_surface)
1524      efl_hints_set_weight(window->display->wl.efl_hints,
1525                           window->xdg_surface, ww, hh);
1526    ecore_wl2_display_flush(window->display);
1527 }
1528 
1529 static void
_frame_cb(void * data,struct wl_callback * callback,uint32_t timestamp)1530 _frame_cb(void *data, struct wl_callback *callback, uint32_t timestamp)
1531 {
1532    Ecore_Wl2_Frame_Cb_Handle *cb;
1533    Ecore_Wl2_Window *window;
1534    Eina_Inlist *l;
1535 
1536    window = data;
1537    window->commit_pending = EINA_FALSE;
1538    wl_callback_destroy(callback);
1539    window->callback = NULL;
1540    EINA_INLIST_FOREACH_SAFE(window->frame_callbacks, l, cb)
1541      cb->cb(window, timestamp, cb->data);
1542 }
1543 
1544 static struct wl_callback_listener _frame_listener =
1545 {
1546    _frame_cb
1547 };
1548 
1549 static void
_maximized_set(Ecore_Wl2_Window * window)1550 _maximized_set(Ecore_Wl2_Window *window)
1551 {
1552    EINA_SAFETY_ON_FALSE_RETURN(window->zxdg_toplevel || window->xdg_toplevel);
1553 
1554    if (window->set_config.maximized)
1555      {
1556         window->saved = window->set_config.geometry;
1557         if (window->xdg_toplevel)
1558           xdg_toplevel_set_maximized(window->xdg_toplevel);
1559         if (window->zxdg_toplevel)
1560           zxdg_toplevel_v6_set_maximized(window->zxdg_toplevel);
1561      }
1562    else
1563      {
1564         if (window->xdg_toplevel)
1565           xdg_toplevel_unset_maximized(window->xdg_toplevel);
1566         if (window->zxdg_toplevel)
1567           zxdg_toplevel_v6_unset_maximized(window->zxdg_toplevel);
1568      }
1569 }
1570 
1571 static void
_fullscreen_set(Ecore_Wl2_Window * window)1572 _fullscreen_set(Ecore_Wl2_Window *window)
1573 {
1574    EINA_SAFETY_ON_FALSE_RETURN(window->zxdg_toplevel || window->xdg_toplevel);
1575 
1576    if (window->set_config.fullscreen)
1577      {
1578         window->saved = window->set_config.geometry;
1579         if (window->xdg_toplevel)
1580           xdg_toplevel_set_fullscreen(window->xdg_toplevel, NULL);
1581         if (window->zxdg_toplevel)
1582           zxdg_toplevel_v6_set_fullscreen(window->zxdg_toplevel, NULL);
1583      }
1584    else
1585      {
1586         if (window->xdg_toplevel)
1587           xdg_toplevel_unset_fullscreen(window->xdg_toplevel);
1588         if (window->zxdg_toplevel)
1589           zxdg_toplevel_v6_unset_fullscreen(window->zxdg_toplevel);
1590      }
1591 }
1592 
1593 static struct wl_region *
_region_create(struct wl_compositor * comp,int x,int y,int w,int h)1594 _region_create(struct wl_compositor *comp, int x, int y, int w, int h)
1595 {
1596    struct wl_region *out;
1597 
1598    out = wl_compositor_create_region(comp);
1599    if (!out)
1600      {
1601         ERR("Failed to create region");
1602         return NULL;
1603      }
1604 
1605    wl_region_add(out, x, y, w, h);
1606 
1607    return out;
1608 }
1609 
1610 static void
_regions_set(Ecore_Wl2_Window * window)1611 _regions_set(Ecore_Wl2_Window *window)
1612 {
1613    struct wl_region *region = NULL;
1614 
1615    if (window->pending.opaque)
1616      {
1617         if (window->opaque_set)
1618           {
1619              region = _region_create(window->display->wl.compositor,
1620                                      window->opaque.x, window->opaque.y,
1621                                      window->opaque.w, window->opaque.h);
1622              if (!region) return;
1623           }
1624         wl_surface_set_opaque_region(window->surface, region);
1625      }
1626 
1627    if (!window->pending.input) goto out;
1628    if (window->type == ECORE_WL2_WINDOW_TYPE_DND) goto out;
1629 
1630    if (!window->input_set)
1631      {
1632         wl_surface_set_input_region(window->surface, NULL);
1633         goto out;
1634      }
1635 
1636    if (region && (window->opaque.x == window->input_rect.x) &&
1637        (window->opaque.y == window->input_rect.y) &&
1638        (window->opaque.w == window->input_rect.w) &&
1639        (window->opaque.h == window->input_rect.h))
1640      {
1641         wl_surface_set_input_region(window->surface, region);
1642         goto out;
1643      }
1644    if (region) wl_region_destroy(region);
1645 
1646    region = _region_create(window->display->wl.compositor,
1647                            window->input_rect.x, window->input_rect.y,
1648                            window->input_rect.w, window->input_rect.h);
1649    if (!region) return;
1650    wl_surface_set_input_region(window->surface, region);
1651 
1652 out:
1653    if (region) wl_region_destroy(region);
1654 }
1655 
1656 EAPI void
ecore_wl2_window_commit(Ecore_Wl2_Window * window,Eina_Bool flush)1657 ecore_wl2_window_commit(Ecore_Wl2_Window *window, Eina_Bool flush)
1658 {
1659    EINA_SAFETY_ON_NULL_RETURN(window);
1660    EINA_SAFETY_ON_NULL_RETURN(window->surface);
1661 
1662    if (window->commit_pending)
1663      {
1664         if (window->callback)
1665           wl_callback_destroy(window->callback);
1666         window->callback = NULL;
1667         /* The elm mouse cursor bits do some harmless but weird stuff that
1668          * can hit this, silence the warning for that case only. */
1669         if (window->type != ECORE_WL2_WINDOW_TYPE_NONE)
1670           WRN("Commit before previous commit processed");
1671      }
1672    if (!window->pending.configure)
1673      {
1674         if (window->has_buffer)
1675           window->commit_pending = EINA_TRUE;
1676         window->callback = wl_surface_frame(window->surface);
1677         wl_callback_add_listener(window->callback, &_frame_listener, window);
1678         /* Dispatch any state we've been saving along the way */
1679         if (window->pending.geom)
1680           {
1681              int gx, gy, gw, gh;
1682 
1683              ecore_wl2_window_geometry_get(window, &gx, &gy, &gw, &gh);
1684              if (window->xdg_toplevel)
1685                xdg_surface_set_window_geometry(window->xdg_surface,
1686                                                gx, gy, gw, gh);
1687              if (window->zxdg_surface)
1688                zxdg_surface_v6_set_window_geometry(window->zxdg_surface,
1689                                                    gx, gy, gw, gh);
1690           }
1691         if (window->pending.opaque || window->pending.input)
1692           _regions_set(window);
1693 
1694         if (window->pending.maximized)
1695           _maximized_set(window);
1696 
1697         if (window->pending.fullscreen)
1698           _fullscreen_set(window);
1699 
1700         window->pending.geom = EINA_FALSE;
1701         window->pending.opaque = EINA_FALSE;
1702         window->pending.input = EINA_FALSE;
1703         window->pending.maximized = EINA_FALSE;
1704         window->pending.fullscreen = EINA_FALSE;
1705      }
1706 
1707    if (window->req_config.serial != window->set_config.serial)
1708      {
1709         if (window->xdg_configure_ack)
1710            window->xdg_configure_ack(window->xdg_surface,
1711                                       window->req_config.serial);
1712         if (window->zxdg_configure_ack)
1713            window->zxdg_configure_ack(window->zxdg_surface,
1714                                       window->req_config.serial);
1715         window->set_config.serial = window->req_config.serial;
1716      }
1717    if (flush)
1718      {
1719         wl_surface_commit(window->surface);
1720         ecore_wl2_display_flush(window->display);
1721      }
1722 
1723    if (!window->updating) return;
1724 
1725    window->updating = EINA_FALSE;
1726    if (window->def_config.serial != window->set_config.serial)
1727       _ecore_wl2_window_configure_send(window);
1728 }
1729 
1730 EAPI void
ecore_wl2_window_false_commit(Ecore_Wl2_Window * window)1731 ecore_wl2_window_false_commit(Ecore_Wl2_Window *window)
1732 {
1733    EINA_SAFETY_ON_NULL_RETURN(window);
1734    EINA_SAFETY_ON_NULL_RETURN(window->surface);
1735    EINA_SAFETY_ON_TRUE_RETURN(window->pending.configure);
1736    EINA_SAFETY_ON_TRUE_RETURN(window->commit_pending);
1737 
1738    window->callback = wl_surface_frame(window->surface);
1739    wl_callback_add_listener(window->callback, &_frame_listener, window);
1740    wl_surface_commit(window->surface);
1741    ecore_wl2_display_flush(window->display);
1742    if (window->has_buffer)
1743      window->commit_pending = EINA_TRUE;
1744 }
1745 
1746 EAPI Eina_Bool
ecore_wl2_window_pending_get(Ecore_Wl2_Window * window)1747 ecore_wl2_window_pending_get(Ecore_Wl2_Window *window)
1748 {
1749    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
1750 
1751    return window->commit_pending;
1752 }
1753 
1754 EAPI Ecore_Wl2_Frame_Cb_Handle *
ecore_wl2_window_frame_callback_add(Ecore_Wl2_Window * window,Ecore_Wl2_Frame_Cb cb,void * data)1755 ecore_wl2_window_frame_callback_add(Ecore_Wl2_Window *window, Ecore_Wl2_Frame_Cb cb, void *data)
1756 {
1757    Ecore_Wl2_Frame_Cb_Handle *callback;
1758 
1759    EINA_SAFETY_ON_NULL_RETURN_VAL(window, NULL);
1760    EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
1761 
1762    callback = malloc(sizeof(*callback));
1763    EINA_SAFETY_ON_NULL_RETURN_VAL(callback, NULL);
1764    callback->cb = cb;
1765    callback->data = data;
1766    callback->win = window;
1767    window->frame_callbacks =
1768      eina_inlist_append(window->frame_callbacks, EINA_INLIST_GET(callback));
1769    return callback;
1770 }
1771 
1772 EAPI void
ecore_wl2_window_frame_callback_del(Ecore_Wl2_Frame_Cb_Handle * handle)1773 ecore_wl2_window_frame_callback_del(Ecore_Wl2_Frame_Cb_Handle *handle)
1774 {
1775    EINA_SAFETY_ON_NULL_RETURN(handle);
1776 
1777    handle->win->frame_callbacks =
1778      eina_inlist_remove(handle->win->frame_callbacks, EINA_INLIST_GET(handle));
1779    free(handle);
1780 }
1781 
1782 EAPI void
ecore_wl2_window_buffer_attach(Ecore_Wl2_Window * win,void * buffer,int x,int y,Eina_Bool implicit)1783 ecore_wl2_window_buffer_attach(Ecore_Wl2_Window *win, void *buffer, int x, int y, Eina_Bool implicit)
1784 {
1785    EINA_SAFETY_ON_NULL_RETURN(win);
1786    EINA_SAFETY_ON_NULL_RETURN(win->surface);
1787 
1788    /* FIXME: Haven't given any thought to x and y since we always use 0... */
1789    if (!implicit) wl_surface_attach(win->surface, buffer, x, y);
1790    win->buffer = buffer;
1791    if (!implicit && !buffer)
1792      win->has_buffer = EINA_FALSE;
1793    else
1794      win->has_buffer = EINA_TRUE;
1795 }
1796 
1797 EAPI Eina_Bool
ecore_wl2_window_resizing_get(Ecore_Wl2_Window * window)1798 ecore_wl2_window_resizing_get(Ecore_Wl2_Window *window)
1799 {
1800    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EINA_FALSE);
1801 
1802    return window->req_config.resizing;
1803 }
1804 
1805 EAPI void
ecore_wl2_window_update_begin(Ecore_Wl2_Window * window)1806 ecore_wl2_window_update_begin(Ecore_Wl2_Window *window)
1807 {
1808    EINA_SAFETY_ON_NULL_RETURN(window);
1809    EINA_SAFETY_ON_TRUE_RETURN(window->updating);
1810 
1811    window->updating = EINA_TRUE;
1812 }
1813 
1814 EAPI void
ecore_wl2_window_damage(Ecore_Wl2_Window * window,Eina_Rectangle * rects,unsigned int count)1815 ecore_wl2_window_damage(Ecore_Wl2_Window *window, Eina_Rectangle *rects, unsigned int count)
1816 {
1817    void (*damage)(struct wl_surface *, int32_t, int32_t, int32_t, int32_t);
1818    unsigned int k;
1819    int compositor_version;
1820 
1821    EINA_SAFETY_ON_NULL_RETURN(window);
1822 
1823    compositor_version = window->display->wl.compositor_version;
1824 
1825    if (compositor_version >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
1826      damage = wl_surface_damage_buffer;
1827    else
1828      damage = wl_surface_damage;
1829 
1830    if ((rects) && (count > 0))
1831      for (k = 0; k < count; k++)
1832        damage(window->surface, rects[k].x, rects[k].y, rects[k].w, rects[k].h);
1833    else
1834      damage(window->surface, 0, 0, INT_MAX, INT_MAX);
1835 }
1836 
1837 EAPI void
ecore_wl2_window_surface_flush(Ecore_Wl2_Window * window,Eina_Bool purge)1838 ecore_wl2_window_surface_flush(Ecore_Wl2_Window *window, Eina_Bool purge)
1839 {
1840    EINA_SAFETY_ON_NULL_RETURN(window);
1841 
1842    if (!window->wl2_surface) return;
1843    ecore_wl2_surface_flush(window->wl2_surface, purge);
1844 }
1845 
1846 EAPI Ecore_Wl2_Window_Type
ecore_wl2_window_type_get(Ecore_Wl2_Window * window)1847 ecore_wl2_window_type_get(Ecore_Wl2_Window *window)
1848 {
1849    EINA_SAFETY_ON_NULL_RETURN_VAL(window, ECORE_WL2_WINDOW_TYPE_NONE);
1850    return window->type;
1851 }
1852 
1853 EAPI Ecore_Wl2_Window *
ecore_wl2_window_surface_find(struct wl_surface * surface)1854 ecore_wl2_window_surface_find(struct wl_surface *surface)
1855 {
1856    Ecore_Wl2_Display *ewd;
1857    Ecore_Wl2_Window *win;
1858 
1859    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, NULL);
1860 
1861    ewd = ecore_wl2_connected_display_get(NULL);
1862    EINA_SAFETY_ON_NULL_RETURN_VAL(ewd, NULL);
1863 
1864    win = ecore_wl2_display_window_find_by_surface(ewd, surface);
1865    return win;
1866 }
1867