1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #include "ecore_wl_private.h"
6 #include "xdg-shell-client-protocol.h"
7 #include "session-recovery-client-protocol.h"
8 
9 /* local function prototypes */
10 static void _ecore_wl_window_cb_ping(void *data EINA_UNUSED, struct wl_shell_surface *shell_surface, unsigned int serial);
11 static void _ecore_wl_window_cb_configure(void *data, struct wl_shell_surface *shell_surface EINA_UNUSED, unsigned int edges, int w, int h);
12 static void _ecore_wl_window_cb_popup_done(void *data, struct wl_shell_surface *shell_surface EINA_UNUSED);
13 static void _ecore_wl_window_configure_send(Ecore_Wl_Window *win, int w, int h, int edges);
14 static char *_ecore_wl_window_id_str_get(unsigned int win_id);
15 static void _ecore_xdg_handle_surface_configure(void *data, struct xdg_surface *xdg_surface, int32_t width, int32_t height,struct wl_array *states, uint32_t serial);
16 static void _ecore_xdg_handle_surface_delete(void *data, struct xdg_surface *xdg_surface);
17 static void _ecore_xdg_handle_popup_done(void *data, struct xdg_popup *xdg_popup);
18 static void _ecore_session_recovery_uuid(void *data, struct zwp_e_session_recovery *session_recovery, const char *uuid);
19 
20 /* local variables */
21 static Eina_Hash *_windows = NULL;
22 
23 /* wayland listeners */
24 static const struct wl_shell_surface_listener _ecore_wl_shell_surface_listener =
25 {
26    _ecore_wl_window_cb_ping,
27    _ecore_wl_window_cb_configure,
28    _ecore_wl_window_cb_popup_done
29 };
30 
31 static const struct xdg_surface_listener _ecore_xdg_surface_listener =
32 {
33    _ecore_xdg_handle_surface_configure,
34    _ecore_xdg_handle_surface_delete,
35 };
36 
37 static const struct xdg_popup_listener _ecore_xdg_popup_listener =
38 {
39    _ecore_xdg_handle_popup_done,
40 };
41 
42 static const struct zwp_e_session_recovery_listener _ecore_session_recovery_listener =
43 {
44    _ecore_session_recovery_uuid,
45 };
46 
47 /* internal functions */
48 void
_ecore_wl_window_init(void)49 _ecore_wl_window_init(void)
50 {
51    if (!_windows)
52      _windows = eina_hash_string_superfast_new(NULL);
53 }
54 
55 void
_ecore_wl_window_shutdown(void)56 _ecore_wl_window_shutdown(void)
57 {
58    eina_hash_free(_windows);
59    _windows = NULL;
60 }
61 
62 Eina_Hash *
_ecore_wl_window_hash_get(void)63 _ecore_wl_window_hash_get(void)
64 {
65    return _windows;
66 }
67 
68 void
_ecore_wl_window_shell_surface_init(Ecore_Wl_Window * win)69 _ecore_wl_window_shell_surface_init(Ecore_Wl_Window *win)
70 {
71 #ifdef USE_IVI_SHELL
72    char *env;
73 #endif
74 
75    if ((win->type == ECORE_WL_WINDOW_TYPE_DND) ||
76        (win->type == ECORE_WL_WINDOW_TYPE_NONE)) return;
77 #ifdef USE_IVI_SHELL
78    if ((!win->ivi_surface) && (_ecore_wl_disp->wl.ivi_application))
79      {
80         if (win->parent && win->parent->ivi_surface)
81           win->ivi_surface_id = win->parent->ivi_surface_id + 1;
82         else if ((env = getenv("ECORE_IVI_SURFACE_ID")))
83           win->ivi_surface_id = atoi(env);
84         else
85           win->ivi_surface_id = IVI_SURFACE_ID + getpid();
86 
87         win->ivi_surface =
88           ivi_application_surface_create(_ecore_wl_disp->wl.ivi_application,
89                                          win->ivi_surface_id, win->surface);
90      }
91 
92    if (!win->ivi_surface)
93      {
94 #endif
95         if (_ecore_wl_disp->wl.xdg_shell)
96           {
97              if (win->xdg_surface) return;
98              win->xdg_surface =
99                xdg_shell_get_xdg_surface(_ecore_wl_disp->wl.xdg_shell,
100                                          win->surface);
101              if (!win->xdg_surface) return;
102              if (win->title)
103                xdg_surface_set_title(win->xdg_surface, win->title);
104              if (win->class_name)
105                xdg_surface_set_app_id(win->xdg_surface, win->class_name);
106              xdg_surface_set_user_data(win->xdg_surface, win);
107              xdg_surface_add_listener(win->xdg_surface,
108                                       &_ecore_xdg_surface_listener, win);
109           }
110         else if (_ecore_wl_disp->wl.shell)
111           {
112              if (win->shell_surface) return;
113              win->shell_surface =
114                wl_shell_get_shell_surface(_ecore_wl_disp->wl.shell,
115                                           win->surface);
116              if (!win->shell_surface) return;
117 
118              if (win->title)
119                wl_shell_surface_set_title(win->shell_surface, win->title);
120 
121              if (win->class_name)
122                wl_shell_surface_set_class(win->shell_surface, win->class_name);
123           }
124 
125         if (win->shell_surface)
126           wl_shell_surface_add_listener(win->shell_surface,
127                                         &_ecore_wl_shell_surface_listener, win);
128 #ifdef USE_IVI_SHELL
129      }
130 #endif
131 
132    /* trap for valid shell surface */
133    if ((!win->xdg_surface) && (!win->shell_surface)) return;
134 
135    switch (win->type)
136      {
137       case ECORE_WL_WINDOW_TYPE_FULLSCREEN:
138         if (win->xdg_surface)
139           xdg_surface_set_fullscreen(win->xdg_surface, NULL);
140         else if (win->shell_surface)
141           wl_shell_surface_set_fullscreen(win->shell_surface,
142                                           WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
143                                           0, NULL);
144         break;
145       case ECORE_WL_WINDOW_TYPE_MAXIMIZED:
146         if (win->xdg_surface)
147           xdg_surface_set_maximized(win->xdg_surface);
148         else if (win->shell_surface)
149           wl_shell_surface_set_maximized(win->shell_surface, NULL);
150         break;
151       case ECORE_WL_WINDOW_TYPE_TRANSIENT:
152         if (win->xdg_surface)
153           xdg_surface_set_parent(win->xdg_surface, win->parent->xdg_surface);
154         else if (win->shell_surface)
155           wl_shell_surface_set_transient(win->shell_surface,
156                                          win->parent->surface,
157                                          win->allocation.x,
158                                          win->allocation.y, 0);
159         break;
160       case ECORE_WL_WINDOW_TYPE_MENU:
161         if (win->xdg_surface)
162           {
163              win->xdg_popup =
164                xdg_shell_get_xdg_popup(_ecore_wl_disp->wl.xdg_shell,
165                                        win->surface,
166                                        win->parent->surface,
167                                        _ecore_wl_disp->input->seat,
168                                        _ecore_wl_disp->serial,
169                                        win->allocation.x, win->allocation.y);
170              if (!win->xdg_popup) return;
171              xdg_popup_set_user_data(win->xdg_popup, win);
172              xdg_popup_add_listener(win->xdg_popup,
173                                     &_ecore_xdg_popup_listener, win);
174           }
175         else if (win->shell_surface)
176           wl_shell_surface_set_popup(win->shell_surface,
177                                      _ecore_wl_disp->input->seat,
178                                      _ecore_wl_disp->serial,
179                                      win->parent->surface,
180                                      win->allocation.x, win->allocation.y, 0);
181         break;
182       case ECORE_WL_WINDOW_TYPE_TOPLEVEL:
183         if (win->xdg_surface)
184           xdg_surface_set_parent(win->xdg_surface, NULL);
185         else if (win->shell_surface)
186           wl_shell_surface_set_toplevel(win->shell_surface);
187         break;
188       default:
189         break;
190      }
191 }
192 
193 EAPI Ecore_Wl_Window *
ecore_wl_window_new(Ecore_Wl_Window * parent,int x,int y,int w,int h,int buffer_type)194 ecore_wl_window_new(Ecore_Wl_Window *parent, int x, int y, int w, int h, int buffer_type)
195 {
196    Ecore_Wl_Window *win;
197    static int _win_id = 1;
198 
199    LOGFN;
200 
201    if (!(win = calloc(1, sizeof(Ecore_Wl_Window))))
202      {
203         ERR("Failed to allocate an Ecore Wayland Window");
204         return NULL;
205      }
206 
207    win->display = _ecore_wl_disp;
208    win->parent = parent;
209    win->allocation.x = x;
210    win->allocation.y = y;
211    win->allocation.w = w;
212    win->allocation.h = h;
213    win->saved.w = w;
214    win->saved.h = h;
215    win->transparent = EINA_FALSE;
216    win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL;
217    win->buffer_type = buffer_type;
218    win->id = _win_id++;
219    win->rotation = 0;
220 
221    win->opaque.x = x;
222    win->opaque.y = y;
223    win->opaque.w = w;
224    win->opaque.h = h;
225 
226    win->title = NULL;
227    win->class_name = NULL;
228 
229    eina_hash_add(_windows, _ecore_wl_window_id_str_get(win->id), win);
230 
231    return win;
232 }
233 
234 EAPI void
ecore_wl_window_free(Ecore_Wl_Window * win)235 ecore_wl_window_free(Ecore_Wl_Window *win)
236 {
237    Ecore_Wl_Input *input;
238 
239    LOGFN;
240 
241    EINA_SAFETY_ON_NULL_RETURN(win);
242 
243    eina_hash_del(_windows, _ecore_wl_window_id_str_get(win->id), win);
244 
245    EINA_INLIST_FOREACH(_ecore_wl_disp->inputs, input)
246      {
247         if ((input->pointer_focus) && (input->pointer_focus == win))
248           input->pointer_focus = NULL;
249         if ((input->keyboard_focus) && (input->keyboard_focus == win))
250           {
251              input->keyboard_focus = NULL;
252              ecore_timer_del(input->repeat.tmr);
253              input->repeat.tmr = NULL;
254           }
255      }
256 
257    if (win->anim_callback) wl_callback_destroy(win->anim_callback);
258    win->anim_callback = NULL;
259 
260    if (win->subsurfs) _ecore_wl_subsurfs_del_all(win);
261 
262 #ifdef USE_IVI_SHELL
263    if (win->ivi_surface) ivi_surface_destroy(win->ivi_surface);
264    win->ivi_surface = NULL;
265 #endif
266    if (win->xdg_surface) xdg_surface_destroy(win->xdg_surface);
267    win->xdg_surface = NULL;
268    if (win->xdg_popup) xdg_popup_destroy(win->xdg_popup);
269    win->xdg_popup = NULL;
270 
271    if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface);
272    win->shell_surface = NULL;
273    if (win->surface) wl_surface_destroy(win->surface);
274    win->surface = NULL;
275 
276    if (win->title) eina_stringshare_del(win->title);
277    if (win->class_name) eina_stringshare_del(win->class_name);
278 
279    /* HMMM, why was this disabled ? */
280    free(win);
281 }
282 
283 EAPI void
ecore_wl_window_move(Ecore_Wl_Window * win,int x,int y)284 ecore_wl_window_move(Ecore_Wl_Window *win, int x, int y)
285 {
286    Ecore_Wl_Input *input;
287 
288    LOGFN;
289 
290    EINA_SAFETY_ON_NULL_RETURN(win);
291 
292    input = win->keyboard_device;
293    ecore_wl_window_update_location(win, x, y);
294 
295    if ((!input) && (win->parent))
296      {
297         if (!(input = win->parent->keyboard_device))
298           input = win->parent->pointer_device;
299      }
300 
301    if ((!input) || (!input->seat)) return;
302 
303    _ecore_wl_input_grab_release(input, win);
304 
305    if (win->xdg_surface)
306      xdg_surface_move(win->xdg_surface, input->seat, input->display->serial);
307    else if (win->shell_surface)
308      wl_shell_surface_move(win->shell_surface, input->seat,
309                            input->display->serial);
310 }
311 
312 EAPI void
ecore_wl_window_resize(Ecore_Wl_Window * win,int w EINA_UNUSED,int h EINA_UNUSED,int location)313 ecore_wl_window_resize(Ecore_Wl_Window *win, int w EINA_UNUSED, int h EINA_UNUSED, int location)
314 {
315    Ecore_Wl_Input *input;
316 
317    LOGFN;
318 
319    EINA_SAFETY_ON_NULL_RETURN(win);
320 
321    input = win->keyboard_device;
322 
323    if ((!input) && (win->parent))
324      {
325         if (!(input = win->parent->keyboard_device))
326           input = win->parent->pointer_device;
327      }
328 
329    if ((!input) || (!input->seat)) return;
330 
331    _ecore_wl_input_grab_release(input, win);
332 
333    if (win->xdg_surface)
334      xdg_surface_resize(win->xdg_surface, input->seat,
335                         input->display->serial, location);
336    else if (win->shell_surface)
337      wl_shell_surface_resize(win->shell_surface, input->seat,
338                              input->display->serial, location);
339 }
340 
341 EAPI void
ecore_wl_window_damage(Ecore_Wl_Window * win,int x,int y,int w,int h)342 ecore_wl_window_damage(Ecore_Wl_Window *win, int x, int y, int w, int h)
343 {
344    LOGFN;
345 
346    EINA_SAFETY_ON_NULL_RETURN(win);
347 
348    if (win->surface) wl_surface_damage(win->surface, x, y, w, h);
349 }
350 
351 EAPI void
ecore_wl_window_commit(Ecore_Wl_Window * win)352 ecore_wl_window_commit(Ecore_Wl_Window *win)
353 {
354    LOGFN;
355 
356    EINA_SAFETY_ON_NULL_RETURN(win);
357 
358    if ((win->surface))// && (win->has_buffer))
359      wl_surface_commit(win->surface);
360 }
361 
362 EAPI void
ecore_wl_window_buffer_attach(Ecore_Wl_Window * win,struct wl_buffer * buffer,int x,int y)363 ecore_wl_window_buffer_attach(Ecore_Wl_Window *win, struct wl_buffer *buffer, int x, int y)
364 {
365    LOGFN;
366 
367    EINA_SAFETY_ON_NULL_RETURN(win);
368 
369    switch (win->buffer_type)
370      {
371       case ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW:
372         break;
373       case ECORE_WL_WINDOW_BUFFER_TYPE_EGL_IMAGE:
374       case ECORE_WL_WINDOW_BUFFER_TYPE_SHM:
375         if (win->surface)
376           {
377              win->has_buffer = (buffer != NULL);
378 
379              /* if (buffer) */
380              wl_surface_attach(win->surface, buffer, x, y);
381              wl_surface_damage(win->surface, 0, 0,
382                                win->allocation.w, win->allocation.h);
383              ecore_wl_window_commit(win);
384           }
385         break;
386       default:
387         return;
388      }
389 }
390 
391 EAPI struct wl_surface *
ecore_wl_window_surface_create(Ecore_Wl_Window * win)392 ecore_wl_window_surface_create(Ecore_Wl_Window *win)
393 {
394    LOGFN;
395 
396    EINA_SAFETY_ON_NULL_RETURN_VAL(win, NULL);
397 
398    char uuid[37];
399 
400    if (win->surface) return win->surface;
401    win->surface = wl_compositor_create_surface(_ecore_wl_compositor_get());
402    if (!win->surface) return NULL;
403 
404    if (_ecore_wl_disp->wl.session_recovery && getenv("EFL_WAYLAND_SESSION_RECOVERY"))
405      {
406         zwp_e_session_recovery_add_listener(_ecore_wl_disp->wl.session_recovery,
407                                       &_ecore_session_recovery_listener, win);
408         if (!uuid_is_null(win->uuid))
409           {
410              uuid_unparse(win->uuid, uuid);
411              zwp_e_session_recovery_provide_uuid(_ecore_wl_disp->wl.session_recovery, uuid);
412           }
413      }
414    win->surface_id = wl_proxy_get_id((struct wl_proxy *)win->surface);
415    return win->surface;
416 }
417 
418 EAPI void
ecore_wl_window_show(Ecore_Wl_Window * win)419 ecore_wl_window_show(Ecore_Wl_Window *win)
420 {
421    LOGFN;
422 
423    if (!win) return;
424 
425    ecore_wl_window_surface_create(win);
426 
427    _ecore_wl_window_shell_surface_init(win);
428 }
429 
430 EAPI void
ecore_wl_window_hide(Ecore_Wl_Window * win)431 ecore_wl_window_hide(Ecore_Wl_Window *win)
432 {
433    LOGFN;
434 
435    EINA_SAFETY_ON_NULL_RETURN(win);
436 
437    if (win->xdg_surface) xdg_surface_destroy(win->xdg_surface);
438    win->xdg_surface = NULL;
439 
440    if (win->xdg_popup) xdg_popup_destroy(win->xdg_popup);
441    win->xdg_popup = NULL;
442 
443    if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface);
444    win->shell_surface = NULL;
445 
446    if (win->surface) wl_surface_destroy(win->surface);
447    win->surface = NULL;
448 }
449 
450 EAPI void
ecore_wl_window_raise(Ecore_Wl_Window * win)451 ecore_wl_window_raise(Ecore_Wl_Window *win)
452 {
453    LOGFN;
454 
455    EINA_SAFETY_ON_NULL_RETURN(win);
456 
457    /* FIXME: This should raise the xdg surface also */
458    if (win->shell_surface)
459      wl_shell_surface_set_toplevel(win->shell_surface);
460 }
461 
462 EAPI void
ecore_wl_window_maximized_set(Ecore_Wl_Window * win,Eina_Bool maximized)463 ecore_wl_window_maximized_set(Ecore_Wl_Window *win, Eina_Bool maximized)
464 {
465    Eina_Bool prev;
466 
467    LOGFN;
468 
469    EINA_SAFETY_ON_NULL_RETURN(win);
470 
471    prev = win->maximized;
472    maximized = !!maximized;
473    if (prev == maximized) return;
474 
475    if (maximized)
476      {
477         if (win->xdg_surface)
478           xdg_surface_set_maximized(win->xdg_surface);
479         else if (win->shell_surface)
480           wl_shell_surface_set_maximized(win->shell_surface, NULL);
481         win->type = ECORE_WL_WINDOW_TYPE_MAXIMIZED;
482      }
483    else
484      {
485         if (win->xdg_surface)
486           xdg_surface_unset_maximized(win->xdg_surface);
487         else if (win->shell_surface)
488           wl_shell_surface_set_toplevel(win->shell_surface);
489         win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL;
490      }
491    win->maximized = maximized;
492 }
493 
494 EAPI Eina_Bool
ecore_wl_window_maximized_get(Ecore_Wl_Window * win)495 ecore_wl_window_maximized_get(Ecore_Wl_Window *win)
496 {
497    LOGFN;
498 
499    EINA_SAFETY_ON_NULL_RETURN_VAL(win, EINA_FALSE);
500 
501    return win->maximized;
502 }
503 
504 EAPI void
ecore_wl_window_fullscreen_set(Ecore_Wl_Window * win,Eina_Bool fullscreen)505 ecore_wl_window_fullscreen_set(Ecore_Wl_Window *win, Eina_Bool fullscreen)
506 {
507    Eina_Bool prev;
508 
509    LOGFN;
510 
511    EINA_SAFETY_ON_NULL_RETURN(win);
512 
513    prev = win->fullscreen;
514    fullscreen = !!fullscreen;
515    if (prev == fullscreen) return;
516 
517    if (fullscreen)
518      {
519         win->type = ECORE_WL_WINDOW_TYPE_FULLSCREEN;
520 
521         if (win->xdg_surface)
522           xdg_surface_set_fullscreen(win->xdg_surface, NULL);
523 
524         if (win->shell_surface)
525           wl_shell_surface_set_fullscreen(win->shell_surface,
526                                           WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
527                                           0, NULL);
528      }
529    else
530      {
531         if (win->xdg_surface)
532           xdg_surface_unset_fullscreen(win->xdg_surface);
533         else if (win->shell_surface)
534           wl_shell_surface_set_toplevel(win->shell_surface);
535 
536         win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL;
537      }
538    win->fullscreen = fullscreen;
539 }
540 
541 EAPI Eina_Bool
ecore_wl_window_fullscreen_get(Ecore_Wl_Window * win)542 ecore_wl_window_fullscreen_get(Ecore_Wl_Window *win)
543 {
544    LOGFN;
545 
546    EINA_SAFETY_ON_NULL_RETURN_VAL(win, EINA_FALSE);
547 
548    return win->fullscreen;
549 }
550 
551 EAPI void
ecore_wl_window_transparent_set(Ecore_Wl_Window * win,Eina_Bool transparent)552 ecore_wl_window_transparent_set(Ecore_Wl_Window *win, Eina_Bool transparent)
553 {
554    LOGFN;
555 
556    EINA_SAFETY_ON_NULL_RETURN(win);
557 
558    win->transparent = transparent;
559    if (!win->transparent)
560      ecore_wl_window_opaque_region_set(win, win->opaque.x, win->opaque.y,
561                                        win->opaque.w, win->opaque.h);
562    else
563      ecore_wl_window_opaque_region_set(win, win->opaque.x, win->opaque.y, 0, 0);
564 }
565 
566 EAPI Eina_Bool
ecore_wl_window_alpha_get(Ecore_Wl_Window * win)567 ecore_wl_window_alpha_get(Ecore_Wl_Window *win)
568 {
569    LOGFN;
570 
571    EINA_SAFETY_ON_NULL_RETURN_VAL(win, EINA_FALSE);
572 
573    return win->alpha;
574 }
575 
576 EAPI void
ecore_wl_window_alpha_set(Ecore_Wl_Window * win,Eina_Bool alpha)577 ecore_wl_window_alpha_set(Ecore_Wl_Window *win, Eina_Bool alpha)
578 {
579    LOGFN;
580 
581    EINA_SAFETY_ON_NULL_RETURN(win);
582 
583    win->alpha = alpha;
584    if (!win->alpha)
585      ecore_wl_window_opaque_region_set(win, win->opaque.x, win->opaque.y,
586                                        win->opaque.w, win->opaque.h);
587    else
588      ecore_wl_window_opaque_region_set(win, win->opaque.x, win->opaque.y, 0, 0);
589 }
590 
591 EAPI Eina_Bool
ecore_wl_window_transparent_get(Ecore_Wl_Window * win)592 ecore_wl_window_transparent_get(Ecore_Wl_Window *win)
593 {
594    LOGFN;
595 
596    EINA_SAFETY_ON_NULL_RETURN_VAL(win, EINA_FALSE);
597 
598    return win->transparent;
599 }
600 
601 EAPI void
ecore_wl_window_update_size(Ecore_Wl_Window * win,int w,int h)602 ecore_wl_window_update_size(Ecore_Wl_Window *win, int w, int h)
603 {
604    LOGFN;
605 
606    EINA_SAFETY_ON_NULL_RETURN(win);
607 
608    win->allocation.w = w;
609    win->allocation.h = h;
610    if ((!ecore_wl_window_maximized_get(win)) && (!win->fullscreen))
611      {
612         win->saved.w = w;
613         win->saved.h = h;
614      }
615 
616    if (win->xdg_surface)
617      xdg_surface_set_window_geometry(win->xdg_surface,
618                                      win->allocation.x, win->allocation.y,
619                                      win->allocation.w, win->allocation.h);
620 }
621 
622 EAPI void
ecore_wl_window_update_location(Ecore_Wl_Window * win,int x,int y)623 ecore_wl_window_update_location(Ecore_Wl_Window *win, int x, int y)
624 {
625    LOGFN;
626 
627    EINA_SAFETY_ON_NULL_RETURN(win);
628 
629    win->allocation.x = x;
630    win->allocation.y = y;
631 
632    if (win->xdg_surface)
633      xdg_surface_set_window_geometry(win->xdg_surface,
634                                      win->allocation.x, win->allocation.y,
635                                      win->allocation.w, win->allocation.h);
636 }
637 
638 EAPI struct wl_surface *
ecore_wl_window_surface_get(Ecore_Wl_Window * win)639 ecore_wl_window_surface_get(Ecore_Wl_Window *win)
640 {
641    LOGFN;
642 
643    EINA_SAFETY_ON_NULL_RETURN_VAL(win, NULL);
644 
645    return win->surface;
646 }
647 
648 /* @since 1.2 */
649 EAPI struct wl_shell_surface *
ecore_wl_window_shell_surface_get(Ecore_Wl_Window * win)650 ecore_wl_window_shell_surface_get(Ecore_Wl_Window *win)
651 {
652    LOGFN;
653 
654    EINA_SAFETY_ON_NULL_RETURN_VAL(win, NULL);
655 
656    return win->shell_surface;
657 }
658 
659 /* @since 1.11 */
660 EAPI struct xdg_surface *
ecore_wl_window_xdg_surface_get(Ecore_Wl_Window * win)661 ecore_wl_window_xdg_surface_get(Ecore_Wl_Window *win)
662 {
663    LOGFN;
664 
665    EINA_SAFETY_ON_NULL_RETURN_VAL(win, NULL);
666 
667    return win->xdg_surface;
668 }
669 
670 EAPI Ecore_Wl_Window *
ecore_wl_window_find(unsigned int id)671 ecore_wl_window_find(unsigned int id)
672 {
673    Ecore_Wl_Window *win = NULL;
674 
675    if (!_windows) return NULL;
676    win = eina_hash_find(_windows, _ecore_wl_window_id_str_get(id));
677    return win;
678 }
679 
680 EAPI void
ecore_wl_window_type_set(Ecore_Wl_Window * win,Ecore_Wl_Window_Type type)681 ecore_wl_window_type_set(Ecore_Wl_Window *win, Ecore_Wl_Window_Type type)
682 {
683    LOGFN;
684 
685    EINA_SAFETY_ON_NULL_RETURN(win);
686 
687    win->type = type;
688 }
689 
690 EAPI void
ecore_wl_window_pointer_set(Ecore_Wl_Window * win,struct wl_surface * surface,int hot_x,int hot_y)691 ecore_wl_window_pointer_set(Ecore_Wl_Window *win, struct wl_surface *surface, int hot_x, int hot_y)
692 {
693    Ecore_Wl_Input *input;
694 
695    LOGFN;
696 
697    EINA_SAFETY_ON_NULL_RETURN(win);
698 
699    win->pointer.surface = surface;
700    win->pointer.hot_x = hot_x;
701    win->pointer.hot_y = hot_y;
702    win->pointer.set = EINA_TRUE;
703 
704    if ((input = win->pointer_device))
705      ecore_wl_input_pointer_set(input, surface, hot_x, hot_y);
706 }
707 
708 EAPI void
ecore_wl_window_cursor_from_name_set(Ecore_Wl_Window * win,const char * cursor_name)709 ecore_wl_window_cursor_from_name_set(Ecore_Wl_Window *win, const char *cursor_name)
710 {
711    Ecore_Wl_Input *input;
712 
713    LOGFN;
714 
715    EINA_SAFETY_ON_NULL_RETURN(win);
716 
717    win->pointer.set = EINA_FALSE;
718 
719    if (!(input = win->pointer_device))
720      return;
721 
722    eina_stringshare_replace(&win->cursor_name, cursor_name);
723 
724    if ((input->cursor_name) && (strcmp(input->cursor_name, win->cursor_name)))
725      ecore_wl_input_cursor_from_name_set(input, cursor_name);
726 }
727 
728 EAPI void
ecore_wl_window_cursor_default_restore(Ecore_Wl_Window * win)729 ecore_wl_window_cursor_default_restore(Ecore_Wl_Window *win)
730 {
731    Ecore_Wl_Input *input;
732 
733    LOGFN;
734 
735    EINA_SAFETY_ON_NULL_RETURN(win);
736 
737    win->pointer.set = EINA_FALSE;
738 
739    if ((input = win->pointer_device))
740      ecore_wl_input_cursor_default_restore(input);
741 }
742 
743 /* @since 1.2 */
744 EAPI void
ecore_wl_window_parent_set(Ecore_Wl_Window * win,Ecore_Wl_Window * parent)745 ecore_wl_window_parent_set(Ecore_Wl_Window *win, Ecore_Wl_Window *parent)
746 {
747    LOGFN;
748 
749    EINA_SAFETY_ON_NULL_RETURN(win);
750 
751    win->parent = parent;
752 }
753 
754 /* @since 1.12 */
755 EAPI void
ecore_wl_window_iconified_set(Ecore_Wl_Window * win,Eina_Bool iconified)756 ecore_wl_window_iconified_set(Ecore_Wl_Window *win, Eina_Bool iconified)
757 {
758    Eina_Bool prev;
759    struct wl_array states;
760    uint32_t *s;
761 
762    LOGFN;
763 
764    EINA_SAFETY_ON_NULL_RETURN(win);
765 
766    prev = win->minimized;
767    iconified = !!iconified;
768    if (prev == iconified) return;
769 
770    if (iconified)
771      {
772         if (win->xdg_surface)
773           xdg_surface_set_minimized(win->xdg_surface);
774         else if (win->shell_surface)
775           {
776              /* TODO: handle case of iconifying a wl_shell surface */
777           }
778      }
779    else
780      {
781         if (win->xdg_surface)
782           {
783              wl_array_init(&states);
784              s = wl_array_add(&states, sizeof(*s));
785              *s = XDG_SURFACE_STATE_ACTIVATED;
786              _ecore_xdg_handle_surface_configure(win, win->xdg_surface, win->saved.w, win->saved.h, &states, 0);
787              wl_array_release(&states);
788           }
789         else if (win->shell_surface)
790           wl_shell_surface_set_toplevel(win->shell_surface);
791 
792         win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL;
793      }
794 
795    win->minimized = iconified;
796 }
797 
798 EAPI Eina_Bool
ecore_wl_window_iconified_get(Ecore_Wl_Window * win)799 ecore_wl_window_iconified_get(Ecore_Wl_Window *win)
800 {
801    LOGFN;
802 
803    EINA_SAFETY_ON_NULL_RETURN_VAL(win, EINA_FALSE);
804 
805    return win->minimized;
806 }
807 
808 EAPI Ecore_Wl_Window *
ecore_wl_window_surface_find(struct wl_surface * surface)809 ecore_wl_window_surface_find(struct wl_surface *surface)
810 {
811    Eina_Iterator *itr;
812    Ecore_Wl_Window *win = NULL;
813    void *data;
814 
815    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, NULL);
816 
817    itr = eina_hash_iterator_data_new(_windows);
818    while (eina_iterator_next(itr, &data))
819      {
820         if (((Ecore_Wl_Window *)data)->surface == surface)
821           {
822              win = data;
823              break;
824           }
825      }
826 
827    eina_iterator_free(itr);
828 
829    return win;
830 }
831 
832 /* @since 1.8 */
833 EAPI void
ecore_wl_window_input_region_set(Ecore_Wl_Window * win,int x,int y,int w,int h)834 ecore_wl_window_input_region_set(Ecore_Wl_Window *win, int x, int y, int w, int h)
835 {
836    LOGFN;
837 
838    EINA_SAFETY_ON_NULL_RETURN(win);
839 
840    win->input.x = x;
841    win->input.y = y;
842    win->input.w = w;
843    win->input.h = h;
844 
845    if (win->type != ECORE_WL_WINDOW_TYPE_DND)
846      {
847         struct wl_region *region;
848 
849         region = wl_compositor_create_region(_ecore_wl_compositor_get());
850         if (!region) return;
851 
852         switch (win->rotation)
853           {
854            case 0:
855              wl_region_add(region, x, y, w, h);
856              break;
857            case 180:
858              wl_region_add(region, x, x + y, w, h);
859              break;
860            case 90:
861              wl_region_add(region, y, x, h, w);
862              break;
863            case 270:
864              wl_region_add(region, x + y, x, h, w);
865              break;
866           }
867 
868         wl_surface_set_input_region(win->surface, region);
869         wl_region_destroy(region);
870      }
871 }
872 
873 /* @since 1.8 */
874 EAPI void
ecore_wl_window_opaque_region_set(Ecore_Wl_Window * win,int x,int y,int w,int h)875 ecore_wl_window_opaque_region_set(Ecore_Wl_Window *win, int x, int y, int w, int h)
876 {
877    struct wl_region *region;
878 
879    LOGFN;
880 
881    EINA_SAFETY_ON_NULL_RETURN(win);
882 
883    win->opaque.x = x;
884    win->opaque.y = y;
885    win->opaque.w = w;
886    win->opaque.h = h;
887 
888    if ((win->transparent) || (win->alpha)) return;
889 
890    region = wl_compositor_create_region(_ecore_wl_compositor_get());
891    if (!region) return;
892 
893    switch (win->rotation)
894      {
895       case 0:
896         wl_region_add(region, x, y, w, h);
897         break;
898       case 180:
899         wl_region_add(region, x, x + y, w, h);
900         break;
901       case 90:
902         wl_region_add(region, y, x, h, w);
903         break;
904       case 270:
905         wl_region_add(region, x + y, x, h, w);
906         break;
907      }
908 
909    wl_surface_set_opaque_region(win->surface, region);
910    wl_region_destroy(region);
911 }
912 
913 /* @since 1.8 */
914 EAPI void
ecore_wl_window_rotation_set(Ecore_Wl_Window * win,int rotation)915 ecore_wl_window_rotation_set(Ecore_Wl_Window *win, int rotation)
916 {
917    LOGFN;
918 
919    EINA_SAFETY_ON_NULL_RETURN(win);
920 
921    win->rotation = rotation;
922 }
923 
924 /* @since 1.8 */
925 EAPI int
ecore_wl_window_rotation_get(Ecore_Wl_Window * win)926 ecore_wl_window_rotation_get(Ecore_Wl_Window *win)
927 {
928    LOGFN;
929 
930    EINA_SAFETY_ON_NULL_RETURN_VAL(win, 0);
931 
932    return win->rotation;
933 }
934 
935 /* @since 1.8 */
936 EAPI int
ecore_wl_window_id_get(Ecore_Wl_Window * win)937 ecore_wl_window_id_get(Ecore_Wl_Window *win)
938 {
939    LOGFN;
940 
941    EINA_SAFETY_ON_NULL_RETURN_VAL(win, 0);
942 
943    return win->id;
944 }
945 
946 /* @since 1.8 */
947 EAPI int
ecore_wl_window_surface_id_get(Ecore_Wl_Window * win)948 ecore_wl_window_surface_id_get(Ecore_Wl_Window *win)
949 {
950    LOGFN;
951 
952    EINA_SAFETY_ON_NULL_RETURN_VAL(win, 0);
953 
954    return win->surface_id;
955 }
956 
957 /* @since 1.8 */
958 EAPI void
ecore_wl_window_title_set(Ecore_Wl_Window * win,const char * title)959 ecore_wl_window_title_set(Ecore_Wl_Window *win, const char *title)
960 {
961    LOGFN;
962 
963    EINA_SAFETY_ON_NULL_RETURN(win);
964 
965    eina_stringshare_replace(&win->title, title);
966 
967    if ((win->xdg_surface) && (win->title))
968      xdg_surface_set_title(win->xdg_surface, win->title);
969    else if ((win->shell_surface) && (win->title))
970      wl_shell_surface_set_title(win->shell_surface, win->title);
971 }
972 
973 /* @since 1.8 */
974 EAPI void
ecore_wl_window_class_name_set(Ecore_Wl_Window * win,const char * class_name)975 ecore_wl_window_class_name_set(Ecore_Wl_Window *win, const char *class_name)
976 {
977    LOGFN;
978 
979    EINA_SAFETY_ON_NULL_RETURN(win);
980 
981    eina_stringshare_replace(&win->class_name, class_name);
982 
983    if ((win->xdg_surface) && (win->class_name))
984      xdg_surface_set_app_id(win->xdg_surface, win->class_name);
985    else if ((win->shell_surface) && (win->class_name))
986      wl_shell_surface_set_class(win->shell_surface, win->class_name);
987 }
988 
989 /* @since 1.8 */
990 /* Maybe we need an ecore_wl_window_pointer_get() too */
991 EAPI Ecore_Wl_Input *
ecore_wl_window_keyboard_get(Ecore_Wl_Window * win)992 ecore_wl_window_keyboard_get(Ecore_Wl_Window *win)
993 {
994    LOGFN;
995 
996    EINA_SAFETY_ON_NULL_RETURN_VAL(win, 0);
997 
998    return win->keyboard_device;
999 }
1000 
1001 
1002 /* local functions */
1003 static void
_ecore_wl_window_cb_ping(void * data EINA_UNUSED,struct wl_shell_surface * shell_surface,unsigned int serial)1004 _ecore_wl_window_cb_ping(void *data EINA_UNUSED, struct wl_shell_surface *shell_surface, unsigned int serial)
1005 {
1006    if (!shell_surface) return;
1007    wl_shell_surface_pong(shell_surface, serial);
1008 }
1009 
1010 static void
_ecore_wl_window_cb_configure(void * data,struct wl_shell_surface * shell_surface EINA_UNUSED,unsigned int edges,int w,int h)1011 _ecore_wl_window_cb_configure(void *data, struct wl_shell_surface *shell_surface EINA_UNUSED, unsigned int edges, int w, int h)
1012 {
1013    Ecore_Wl_Window *win;
1014 
1015    LOGFN;
1016 
1017    if (!(win = data)) return;
1018 
1019    if ((w <= 0) || (h <= 0)) return;
1020 
1021    if ((win->allocation.w != w) || (win->allocation.h != h))
1022      _ecore_wl_window_configure_send(win, w, h, edges);
1023 }
1024 
1025 static void
_ecore_xdg_handle_surface_configure(void * data,struct xdg_surface * xdg_surface EINA_UNUSED,int32_t width,int32_t height,struct wl_array * states,uint32_t serial)1026 _ecore_xdg_handle_surface_configure(void *data, struct xdg_surface *xdg_surface EINA_UNUSED, int32_t width, int32_t height, struct wl_array *states, uint32_t serial)
1027 {
1028    Ecore_Wl_Window *win;
1029    uint32_t *p;
1030 
1031    LOGFN;
1032 
1033    if (!(win = data)) return;
1034 
1035    win->maximized = EINA_FALSE;
1036    win->fullscreen = EINA_FALSE;
1037    win->resizing = EINA_FALSE;
1038    win->focused = EINA_FALSE;
1039 
1040    wl_array_for_each(p, states)
1041      {
1042         uint32_t state = *p;
1043         switch (state)
1044           {
1045            case XDG_SURFACE_STATE_MAXIMIZED:
1046              win->maximized = EINA_TRUE;
1047              break;
1048            case XDG_SURFACE_STATE_FULLSCREEN:
1049              win->fullscreen = EINA_TRUE;
1050              break;
1051            case XDG_SURFACE_STATE_RESIZING:
1052              win->resizing = EINA_TRUE;
1053              break;
1054            case XDG_SURFACE_STATE_ACTIVATED:
1055              win->focused = EINA_TRUE;
1056              win->minimized = EINA_FALSE;
1057              break;
1058            default:
1059              break;
1060           }
1061      }
1062    if ((width > 0) && (height > 0))
1063      _ecore_wl_window_configure_send(win, width, height, 0);
1064 
1065    if (win->xdg_surface)
1066      xdg_surface_ack_configure(win->xdg_surface, serial);
1067 }
1068 
1069 static void
_ecore_xdg_handle_surface_delete(void * data,struct xdg_surface * xdg_surface EINA_UNUSED)1070 _ecore_xdg_handle_surface_delete(void *data, struct xdg_surface *xdg_surface EINA_UNUSED)
1071 {
1072    Ecore_Wl_Window *win;
1073 
1074    LOGFN;
1075 
1076    if (!(win = data)) return;
1077    ecore_wl_window_free(win);
1078 }
1079 
1080 static void
_ecore_wl_window_cb_popup_done(void * data,struct wl_shell_surface * shell_surface)1081 _ecore_wl_window_cb_popup_done(void *data, struct wl_shell_surface *shell_surface)
1082 {
1083    Ecore_Wl_Window *win;
1084 
1085    LOGFN;
1086 
1087    if (!shell_surface) return;
1088    if (!(win = data)) return;
1089    ecore_wl_input_ungrab(win->pointer_device);
1090 }
1091 
1092 static void
_ecore_xdg_handle_popup_done(void * data,struct xdg_popup * xdg_popup)1093 _ecore_xdg_handle_popup_done(void *data, struct xdg_popup *xdg_popup)
1094 {
1095    Ecore_Wl_Window *win;
1096 
1097    LOGFN;
1098 
1099    if (!xdg_popup) return;
1100    if (!(win = data)) return;
1101    ecore_wl_input_ungrab(win->pointer_device);
1102 }
1103 
1104 static void
_ecore_session_recovery_uuid(void * data EINA_UNUSED,struct zwp_e_session_recovery * session_recovery,const char * uuid)1105 _ecore_session_recovery_uuid(void *data EINA_UNUSED, struct zwp_e_session_recovery *session_recovery, const char *uuid)
1106 {
1107    Ecore_Wl_Window *win;
1108    char uuid_string[37];
1109 
1110    LOGFN;
1111 
1112    if (!(win = data)) return;
1113    if (!session_recovery) return;
1114    uuid_parse(uuid, win->uuid);
1115 
1116    uuid_unparse(win->uuid, uuid_string);
1117    DBG("UUID event received from compositor with UUID: %s\n", uuid_string);
1118 }
1119 
1120 static void
_ecore_wl_window_configure_send(Ecore_Wl_Window * win,int w,int h,int edges)1121 _ecore_wl_window_configure_send(Ecore_Wl_Window *win, int w, int h, int edges)
1122 {
1123    Ecore_Wl_Event_Window_Configure *ev;
1124 
1125    LOGFN;
1126 
1127    if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Window_Configure)))) return;
1128    ev->win = win->id;
1129    ev->event_win = win->id;
1130    ev->x = win->allocation.x;
1131    ev->y = win->allocation.y;
1132    ev->w = w;
1133    ev->h = h;
1134    ev->edges = edges;
1135 
1136    ecore_event_add(ECORE_WL_EVENT_WINDOW_CONFIGURE, ev, NULL, NULL);
1137 }
1138 
1139 static char *
_ecore_wl_window_id_str_get(unsigned int win_id)1140 _ecore_wl_window_id_str_get(unsigned int win_id)
1141 {
1142    const char *vals = "qWeRtYuIoP5$&<~";
1143    static char id[9];
1144    unsigned int val;
1145 
1146    val = win_id;
1147    id[0] = vals[(val >> 28) & 0xf];
1148    id[1] = vals[(val >> 24) & 0xf];
1149    id[2] = vals[(val >> 20) & 0xf];
1150    id[3] = vals[(val >> 16) & 0xf];
1151    id[4] = vals[(val >> 12) & 0xf];
1152    id[5] = vals[(val >> 8) & 0xf];
1153    id[6] = vals[(val >> 4) & 0xf];
1154    id[7] = vals[(val) & 0xf];
1155    id[8] = 0;
1156 
1157    return id;
1158 }
1159