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