1 /*
2  * Copyright © 2010 Intel Corporation
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <netinet/in.h>
21 #include <unistd.h>
22 
23 #include "gdk.h"
24 #include "gdkwayland.h"
25 
26 #include "gdkwindow.h"
27 #include "gdkwindowimpl.h"
28 #include "gdkdisplay-wayland.h"
29 #include "gdkglcontext-wayland.h"
30 #include "gdkframeclockprivate.h"
31 #include "gdkprivate-wayland.h"
32 #include "gdkprofilerprivate.h"
33 #include "gdkinternals.h"
34 #include "gdkdeviceprivate.h"
35 #include "gdkprivate-wayland.h"
36 #include "xdg-shell-unstable-v6-client-protocol.h"
37 
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <errno.h>
42 
43 enum {
44   COMMITTED,
45 
46   LAST_SIGNAL
47 };
48 
49 static guint signals[LAST_SIGNAL];
50 
51 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
52   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
53    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
54 
55 #define WINDOW_IS_TOPLEVEL(window)                   \
56   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
57    GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
58    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
59 
60 #define MAX_WL_BUFFER_SIZE (4083) /* 4096 minus header, string argument length and NUL byte */
61 
62 typedef struct _GdkWaylandWindow GdkWaylandWindow;
63 typedef struct _GdkWaylandWindowClass GdkWaylandWindowClass;
64 
65 struct _GdkWaylandWindow
66 {
67   GdkWindow parent;
68 };
69 
70 struct _GdkWaylandWindowClass
71 {
72   GdkWindowClass parent_class;
73 };
74 
G_DEFINE_TYPE(GdkWaylandWindow,gdk_wayland_window,GDK_TYPE_WINDOW)75 G_DEFINE_TYPE (GdkWaylandWindow, gdk_wayland_window, GDK_TYPE_WINDOW)
76 
77 static void
78 gdk_wayland_window_class_init (GdkWaylandWindowClass *wayland_window_class)
79 {
80 }
81 
82 static void
gdk_wayland_window_init(GdkWaylandWindow * wayland_window)83 gdk_wayland_window_init (GdkWaylandWindow *wayland_window)
84 {
85 }
86 
87 #define GDK_TYPE_WINDOW_IMPL_WAYLAND              (_gdk_window_impl_wayland_get_type ())
88 #define GDK_WINDOW_IMPL_WAYLAND(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWayland))
89 #define GDK_WINDOW_IMPL_WAYLAND_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWaylandClass))
90 #define GDK_IS_WINDOW_IMPL_WAYLAND(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WINDOW_IMPL_WAYLAND))
91 #define GDK_IS_WINDOW_IMPL_WAYLAND_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_WAYLAND))
92 #define GDK_WINDOW_IMPL_WAYLAND_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWaylandClass))
93 
94 typedef struct _GdkWindowImplWayland GdkWindowImplWayland;
95 typedef struct _GdkWindowImplWaylandClass GdkWindowImplWaylandClass;
96 
97 typedef enum _PositionMethod
98 {
99   POSITION_METHOD_NONE,
100   POSITION_METHOD_MOVE_RESIZE,
101   POSITION_METHOD_MOVE_TO_RECT
102 } PositionMethod;
103 
104 typedef struct _ExportedClosure
105 {
106   GdkWaylandWindowExported callback;
107   gpointer user_data;
108   GDestroyNotify destroy_func;
109 } ExportedClosure;
110 
111 struct _GdkWindowImplWayland
112 {
113   GdkWindowImpl parent_instance;
114 
115   GdkWindow *wrapper;
116 
117   struct {
118     /* The wl_outputs that this window currently touches */
119     GSList               *outputs;
120 
121     struct wl_surface    *wl_surface;
122 
123     struct xdg_surface *xdg_surface;
124     struct xdg_toplevel *xdg_toplevel;
125     struct xdg_popup *xdg_popup;
126 
127     /* Legacy xdg-shell unstable v6 fallback support */
128     struct zxdg_surface_v6 *zxdg_surface_v6;
129     struct zxdg_toplevel_v6 *zxdg_toplevel_v6;
130     struct zxdg_popup_v6 *zxdg_popup_v6;
131 
132     struct gtk_surface1  *gtk_surface;
133     struct wl_subsurface *wl_subsurface;
134     struct wl_egl_window *egl_window;
135     struct wl_egl_window *dummy_egl_window;
136     struct zxdg_exported_v1 *xdg_exported;
137     struct org_kde_kwin_server_decoration *server_decoration;
138   } display_server;
139 
140   EGLSurface egl_surface;
141   EGLSurface dummy_egl_surface;
142 
143   unsigned int initial_configure_received : 1;
144   unsigned int configuring_popup : 1;
145   unsigned int mapped : 1;
146   unsigned int use_custom_surface : 1;
147   unsigned int pending_buffer_attached : 1;
148   unsigned int pending_commit : 1;
149   unsigned int awaiting_frame : 1;
150   unsigned int using_csd : 1;
151   GdkWindowTypeHint hint;
152   GdkWindow *transient_for;
153   GdkWindow *popup_parent;
154   PositionMethod position_method;
155 
156   cairo_surface_t *staging_cairo_surface;
157   cairo_surface_t *committed_cairo_surface;
158   cairo_surface_t *backfill_cairo_surface;
159 
160   int pending_buffer_offset_x;
161   int pending_buffer_offset_y;
162 
163   int subsurface_x;
164   int subsurface_y;
165 
166   gchar *title;
167 
168   struct {
169     gboolean was_set;
170 
171     gchar *application_id;
172     gchar *app_menu_path;
173     gchar *menubar_path;
174     gchar *window_object_path;
175     gchar *application_object_path;
176     gchar *unique_bus_name;
177   } application;
178 
179   GdkGeometry geometry_hints;
180   GdkWindowHints geometry_mask;
181 
182   GdkSeat *grab_input_seat;
183 
184   gint64 pending_frame_counter;
185   guint32 scale;
186 
187   int margin_left;
188   int margin_right;
189   int margin_top;
190   int margin_bottom;
191   gboolean margin_dirty;
192 
193   int initial_fullscreen_monitor;
194 
195   cairo_region_t *opaque_region;
196   gboolean opaque_region_dirty;
197 
198   cairo_region_t *input_region;
199   gboolean input_region_dirty;
200 
201   cairo_region_t *staged_updates_region;
202 
203   int saved_width;
204   int saved_height;
205   gboolean saved_size_changed;
206 
207   int unconfigured_width;
208   int unconfigured_height;
209 
210   int fixed_size_width;
211   int fixed_size_height;
212 
213   gulong parent_surface_committed_handler;
214 
215   struct {
216     GdkRectangle rect;
217     GdkGravity rect_anchor;
218     GdkGravity window_anchor;
219     GdkAnchorHints anchor_hints;
220     gint rect_anchor_dx;
221     gint rect_anchor_dy;
222   } pending_move_to_rect;
223 
224   struct {
225     int width;
226     int height;
227     GdkWindowState state;
228   } pending;
229 
230   struct {
231     char *handle;
232     int export_count;
233     GList *closures;
234     guint idle_source_id;
235   } exported;
236 
237   struct zxdg_imported_v1 *imported_transient_for;
238   GHashTable *shortcuts_inhibitors;
239 
240   struct wl_callback *surface_callback;
241   GHashTable *frame_callback_surfaces;
242 };
243 
244 struct _GdkWindowImplWaylandClass
245 {
246   GdkWindowImplClass parent_class;
247 };
248 
249 static void gdk_wayland_window_maybe_configure (GdkWindow *window,
250                                                 int        width,
251                                                 int        height,
252                                                 int        scale);
253 
254 static void maybe_set_gtk_surface_dbus_properties (GdkWindow *window);
255 static void maybe_set_gtk_surface_modal (GdkWindow *window);
256 
257 static void gdk_window_request_transient_parent_commit (GdkWindow *window);
258 
259 static void gdk_wayland_window_sync_margin (GdkWindow *window);
260 static void gdk_wayland_window_sync_input_region (GdkWindow *window);
261 static void gdk_wayland_window_sync_opaque_region (GdkWindow *window);
262 
263 static void unset_transient_for_exported (GdkWindow *window);
264 
265 static void calculate_moved_to_rect_result (GdkWindow    *window,
266                                             int           x,
267                                             int           y,
268                                             int           width,
269                                             int           height,
270                                             GdkRectangle *flipped_rect,
271                                             GdkRectangle *final_rect,
272                                             gboolean     *flipped_x,
273                                             gboolean     *flipped_y);
274 
275 static gboolean gdk_wayland_window_is_exported (GdkWindow *window);
276 static void gdk_wayland_window_unexport (GdkWindow *window);
277 static void gdk_wayland_window_announce_decoration_mode (GdkWindow *window);
278 
279 static gboolean should_map_as_subsurface (GdkWindow *window);
280 static gboolean should_map_as_popup (GdkWindow *window);
281 
282 GType _gdk_window_impl_wayland_get_type (void);
283 
G_DEFINE_TYPE(GdkWindowImplWayland,_gdk_window_impl_wayland,GDK_TYPE_WINDOW_IMPL)284 G_DEFINE_TYPE (GdkWindowImplWayland, _gdk_window_impl_wayland, GDK_TYPE_WINDOW_IMPL)
285 
286 static void
287 _gdk_window_impl_wayland_init (GdkWindowImplWayland *impl)
288 {
289   impl->scale = 1;
290   impl->initial_fullscreen_monitor = -1;
291   impl->saved_width = -1;
292   impl->saved_height = -1;
293 }
294 
295 static void
_gdk_wayland_screen_add_orphan_dialog(GdkWindow * window)296 _gdk_wayland_screen_add_orphan_dialog (GdkWindow *window)
297 {
298   GdkWaylandDisplay *display_wayland =
299     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
300 
301   if (!g_list_find (display_wayland->orphan_dialogs, window))
302     display_wayland->orphan_dialogs =
303       g_list_prepend (display_wayland->orphan_dialogs, window);
304 }
305 
306 static void
drop_cairo_surfaces(GdkWindow * window)307 drop_cairo_surfaces (GdkWindow *window)
308 {
309   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
310 
311   g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
312   g_clear_pointer (&impl->backfill_cairo_surface, cairo_surface_destroy);
313 
314   /* We nullify this so if a buffer release comes in later, we won't
315    * try to reuse that buffer since it's no longer suitable
316    */
317   impl->committed_cairo_surface = NULL;
318 }
319 
320 static int
calculate_width_without_margin(GdkWindow * window,int width)321 calculate_width_without_margin (GdkWindow *window,
322                                 int        width)
323 {
324   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
325 
326   return width - (impl->margin_left + impl->margin_right);
327 }
328 
329 static int
calculate_height_without_margin(GdkWindow * window,int height)330 calculate_height_without_margin (GdkWindow *window,
331                                  int        height)
332 {
333   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
334 
335   return height - (impl->margin_top + impl->margin_bottom);
336 }
337 
338 static int
calculate_width_with_margin(GdkWindow * window,int width)339 calculate_width_with_margin (GdkWindow *window,
340                              int        width)
341 {
342   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
343 
344   return width + impl->margin_left + impl->margin_right;
345 }
346 
347 static int
calculate_height_with_margin(GdkWindow * window,int height)348 calculate_height_with_margin (GdkWindow *window,
349                               int        height)
350 {
351   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
352 
353   return height + impl->margin_top + impl->margin_bottom;
354 }
355 
356 static void
_gdk_wayland_window_save_size(GdkWindow * window)357 _gdk_wayland_window_save_size (GdkWindow *window)
358 {
359   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
360 
361   if (window->state & (GDK_WINDOW_STATE_FULLSCREEN |
362                        GDK_WINDOW_STATE_MAXIMIZED |
363                        GDK_WINDOW_STATE_TILED))
364     return;
365 
366   impl->saved_width = calculate_width_without_margin (window, window->width);
367   impl->saved_height = calculate_height_without_margin (window, window->height);
368 }
369 
370 static void
_gdk_wayland_window_clear_saved_size(GdkWindow * window)371 _gdk_wayland_window_clear_saved_size (GdkWindow *window)
372 {
373   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
374 
375   if (window->state & (GDK_WINDOW_STATE_FULLSCREEN |
376                        GDK_WINDOW_STATE_MAXIMIZED |
377                        GDK_WINDOW_STATE_TILED))
378     return;
379 
380   impl->saved_width = -1;
381   impl->saved_height = -1;
382 }
383 
384 /*
385  * gdk_wayland_window_update_size:
386  * @drawable: a #GdkDrawableImplWayland.
387  *
388  * Updates the state of the drawable (in particular the drawable's
389  * cairo surface) when its size has changed.
390  */
391 static void
gdk_wayland_window_update_size(GdkWindow * window,int32_t width,int32_t height,int scale)392 gdk_wayland_window_update_size (GdkWindow *window,
393                                 int32_t    width,
394                                 int32_t    height,
395                                 int        scale)
396 {
397   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
398   GdkRectangle area;
399   cairo_region_t *region;
400 
401   if ((window->width == width) &&
402       (window->height == height) &&
403       (impl->scale == scale))
404     return;
405 
406   drop_cairo_surfaces (window);
407 
408   window->width = width;
409   window->height = height;
410   impl->scale = scale;
411 
412   if (impl->display_server.egl_window)
413     wl_egl_window_resize (impl->display_server.egl_window, width * scale, height * scale, 0, 0);
414   if (impl->display_server.wl_surface)
415     wl_surface_set_buffer_scale (impl->display_server.wl_surface, scale);
416 
417   area.x = 0;
418   area.y = 0;
419   area.width = window->width;
420   area.height = window->height;
421 
422   region = cairo_region_create_rectangle (&area);
423   _gdk_window_invalidate_for_expose (window, region);
424   cairo_region_destroy (region);
425 }
426 
427 GdkWindow *
_gdk_wayland_screen_create_root_window(GdkScreen * screen,int width,int height)428 _gdk_wayland_screen_create_root_window (GdkScreen *screen,
429                                         int        width,
430                                         int        height)
431 {
432   GdkWaylandDisplay *display_wayland =
433     GDK_WAYLAND_DISPLAY (gdk_screen_get_display (screen));
434   GdkWindow *window;
435   GdkWindowImplWayland *impl;
436 
437   window = _gdk_display_create_window (GDK_DISPLAY (display_wayland));
438   window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL);
439   window->impl_window = window;
440   window->visual = gdk_screen_get_system_visual (screen);
441 
442   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
443 
444   impl->wrapper = GDK_WINDOW (window);
445 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
446   if (display_wayland->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE &&
447       gdk_screen_get_n_monitors (screen) > 0)
448     impl->scale = gdk_screen_get_monitor_scale_factor (screen, 0);
449 G_GNUC_END_IGNORE_DEPRECATIONS
450 
451   impl->using_csd = TRUE;
452 
453   /* logical 1x1 fake buffer */
454   impl->staging_cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
455                                                             impl->scale,
456                                                             impl->scale);
457 
458   cairo_surface_set_device_scale (impl->staging_cairo_surface, impl->scale, impl->scale);
459 
460   window->window_type = GDK_WINDOW_ROOT;
461   window->depth = 32;
462 
463   window->x = 0;
464   window->y = 0;
465   window->abs_x = 0;
466   window->abs_y = 0;
467   window->width = width;
468   window->height = height;
469   window->viewable = TRUE;
470 
471   /* see init_randr_support() in gdkscreen-wayland.c */
472   window->event_mask = GDK_STRUCTURE_MASK;
473 
474   return window;
475 }
476 
477 static const gchar *
get_default_title(void)478 get_default_title (void)
479 {
480   const char *title;
481 
482   title = g_get_application_name ();
483   if (!title)
484     title = g_get_prgname ();
485   if (!title)
486     title = "";
487 
488   return title;
489 }
490 
491 static void
fill_presentation_time_from_frame_time(GdkFrameTimings * timings,guint32 frame_time)492 fill_presentation_time_from_frame_time (GdkFrameTimings *timings,
493                                         guint32          frame_time)
494 {
495   /* The timestamp in a wayland frame is a msec time value that in some
496    * way reflects the time at which the server started drawing the frame.
497    * This is not useful from our perspective.
498    *
499    * However, for the DRM backend of Weston, on reasonably recent
500    * Linux, we know that the time is the
501    * clock_gettime (CLOCK_MONOTONIC) value at the vblank, and that
502    * backend starts drawing immediately after receiving the vblank
503    * notification. If we detect this, and make the assumption that the
504    * compositor will finish drawing before the next vblank, we can
505    * then determine the presentation time as the frame time we
506    * received plus one refresh interval.
507    *
508    * If a backend is using clock_gettime(CLOCK_MONOTONIC), but not
509    * picking values right at the vblank, then the presentation times
510    * we compute won't be accurate, but not really worse than then
511    * the alternative of not providing presentation times at all.
512    *
513    * The complexity here is dealing with the fact that we receive
514    * only the low 32 bits of the CLOCK_MONOTONIC value in milliseconds.
515    */
516   gint64 now_monotonic = g_get_monotonic_time ();
517   gint64 now_monotonic_msec = now_monotonic / 1000;
518   uint32_t now_monotonic_low = (uint32_t)now_monotonic_msec;
519 
520   if (frame_time - now_monotonic_low < 1000 ||
521       frame_time - now_monotonic_low > (uint32_t)-1000)
522     {
523       /* Timestamp we received is within one second of the current time.
524        */
525       gint64 last_frame_time = now_monotonic + (gint64)1000 * (gint32)(frame_time - now_monotonic_low);
526       if ((gint32)now_monotonic_low < 0 && (gint32)frame_time > 0)
527         last_frame_time += (gint64)1000 * G_GINT64_CONSTANT(0x100000000);
528       else if ((gint32)now_monotonic_low > 0 && (gint32)frame_time < 0)
529         last_frame_time -= (gint64)1000 * G_GINT64_CONSTANT(0x100000000);
530 
531       timings->presentation_time = last_frame_time + timings->refresh_interval;
532     }
533 }
534 
535 static void
read_back_cairo_surface(GdkWindow * window)536 read_back_cairo_surface (GdkWindow *window)
537 {
538   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
539   cairo_t *cr;
540   cairo_region_t *paint_region = NULL;
541 
542   if (!impl->backfill_cairo_surface)
543     goto out;
544 
545   paint_region = cairo_region_copy (window->clip_region);
546   cairo_region_subtract (paint_region, impl->staged_updates_region);
547 
548   if (cairo_region_is_empty (paint_region))
549     goto out;
550 
551   cr = cairo_create (impl->staging_cairo_surface);
552   cairo_set_source_surface (cr, impl->backfill_cairo_surface, 0, 0);
553   gdk_cairo_region (cr, paint_region);
554   cairo_clip (cr);
555   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
556   cairo_paint (cr);
557   cairo_destroy (cr);
558   cairo_surface_flush (impl->staging_cairo_surface);
559 
560 out:
561   g_clear_pointer (&paint_region, cairo_region_destroy);
562   g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
563   g_clear_pointer (&impl->backfill_cairo_surface, cairo_surface_destroy);
564 }
565 
566 static void
frame_callback(void * data,struct wl_callback * callback,uint32_t time)567 frame_callback (void               *data,
568                 struct wl_callback *callback,
569                 uint32_t            time)
570 {
571   GdkWindow *window = data;
572   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
573   GdkWaylandDisplay *display_wayland =
574     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
575   GdkFrameClock *clock = gdk_window_get_frame_clock (window);
576   GdkFrameTimings *timings;
577 
578   if (callback == impl->surface_callback)
579     {
580       impl->surface_callback = NULL;
581     }
582   else
583     {
584       GHashTableIter iter;
585       gpointer surface_callback;
586 
587       g_hash_table_iter_init (&iter, impl->frame_callback_surfaces);
588       while (g_hash_table_iter_next (&iter, NULL, &surface_callback))
589         {
590           if (callback == surface_callback)
591             {
592               g_hash_table_iter_replace (&iter, NULL);
593               break;
594             }
595         }
596     }
597   wl_callback_destroy (callback);
598 
599   if (GDK_WINDOW_DESTROYED (window))
600     return;
601 
602   if (!impl->awaiting_frame)
603     return;
604 
605   GDK_NOTE (EVENTS,
606             g_message ("frame %p", window));
607 
608   impl->awaiting_frame = FALSE;
609   _gdk_frame_clock_thaw (clock);
610 
611   timings = gdk_frame_clock_get_timings (clock, impl->pending_frame_counter);
612   impl->pending_frame_counter = 0;
613 
614   if (timings == NULL)
615     return;
616 
617   timings->refresh_interval = 16667; /* default to 1/60th of a second */
618   if (impl->display_server.outputs)
619     {
620       /* We pick a random output out of the outputs that the window touches
621        * The rate here is in milli-hertz */
622       int refresh_rate =
623         _gdk_wayland_screen_get_output_refresh_rate (display_wayland->screen,
624                                                      impl->display_server.outputs->data);
625       if (refresh_rate != 0)
626         timings->refresh_interval = G_GINT64_CONSTANT(1000000000) / refresh_rate;
627     }
628 
629   fill_presentation_time_from_frame_time (timings, time);
630 
631   timings->complete = TRUE;
632 
633 #ifdef G_ENABLE_DEBUG
634   if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
635     _gdk_frame_clock_debug_print_timings (clock, timings);
636 
637   if (gdk_profiler_is_running ())
638     _gdk_frame_clock_add_timings_to_profiler (clock, timings);
639 #endif
640 }
641 
642 static const struct wl_callback_listener frame_listener = {
643   frame_callback
644 };
645 
646 static void
on_frame_clock_before_paint(GdkFrameClock * clock,GdkWindow * window)647 on_frame_clock_before_paint (GdkFrameClock *clock,
648                              GdkWindow     *window)
649 {
650   GdkFrameTimings *timings = gdk_frame_clock_get_current_timings (clock);
651   gint64 presentation_time;
652   gint64 refresh_interval;
653 
654   if (window->update_freeze_count > 0)
655     return;
656 
657   gdk_frame_clock_get_refresh_info (clock,
658                                     timings->frame_time,
659                                     &refresh_interval, &presentation_time);
660 
661   if (presentation_time != 0)
662     {
663       /* Assume the algorithm used by the DRM backend of Weston - it
664        * starts drawing at the next vblank after receiving the commit
665        * for this frame, and presentation occurs at the vblank
666        * after that.
667        */
668       timings->predicted_presentation_time = presentation_time + refresh_interval;
669     }
670   else
671     {
672       /* As above, but we don't actually know the phase of the vblank,
673        * so just assume that we're half way through a refresh cycle.
674        */
675       timings->predicted_presentation_time = timings->frame_time + refresh_interval / 2 + refresh_interval;
676     }
677 }
678 
679 static void
on_frame_clock_after_paint(GdkFrameClock * clock,GdkWindow * window)680 on_frame_clock_after_paint (GdkFrameClock *clock,
681                             GdkWindow     *window)
682 {
683   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
684   struct wl_callback *callback;
685   GHashTableIter iter;
686   gpointer surface, surface_callback;
687 
688   if (!impl->pending_commit)
689     return;
690 
691   if (window->update_freeze_count > 0)
692     return;
693 
694   _gdk_frame_clock_freeze (clock);
695 
696   /* Before we commit a new buffer, make sure we've backfilled
697    * undrawn parts from any old committed buffer
698    */
699   if (impl->pending_buffer_attached)
700     read_back_cairo_surface (window);
701 
702   if (impl->surface_callback == NULL)
703     {
704       callback = wl_surface_frame (impl->display_server.wl_surface);
705       wl_callback_add_listener (callback, &frame_listener, window);
706       impl->surface_callback = callback;
707     }
708 
709   g_hash_table_iter_init (&iter, impl->frame_callback_surfaces);
710   while (g_hash_table_iter_next (&iter, &surface, &surface_callback))
711     {
712       if (surface_callback)
713         continue;
714 
715       callback = wl_surface_frame (surface);
716       wl_callback_add_listener (callback, &frame_listener, window);
717       g_hash_table_iter_replace (&iter, callback);
718     }
719 
720   /* From this commit forward, we can't write to the buffer,
721    * it's "live".  In the future, if we need to stage more changes
722    * we have to allocate a new staging buffer and draw to it instead.
723    *
724    * Our one saving grace is if the compositor releases the buffer
725    * before we need to stage any changes, then we can take it back and
726    * use it again.
727    */
728   wl_surface_commit (impl->display_server.wl_surface);
729 
730   if (impl->pending_buffer_attached)
731     impl->committed_cairo_surface = g_steal_pointer (&impl->staging_cairo_surface);
732 
733   impl->pending_buffer_attached = FALSE;
734   impl->pending_commit = FALSE;
735   impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
736   impl->awaiting_frame = TRUE;
737 
738   g_signal_emit (impl, signals[COMMITTED], 0);
739 }
740 
741 static void
window_update_scale(GdkWindow * window)742 window_update_scale (GdkWindow *window)
743 {
744   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
745   GdkWaylandDisplay *display_wayland =
746     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
747   guint32 scale;
748   GSList *l;
749 
750   if (display_wayland->compositor_version < WL_SURFACE_HAS_BUFFER_SCALE)
751     {
752       /* We can't set the scale on this surface */
753       return;
754     }
755 
756   scale = 1;
757   for (l = impl->display_server.outputs; l != NULL; l = l->next)
758     {
759       guint32 output_scale =
760         _gdk_wayland_screen_get_output_scale (display_wayland->screen, l->data);
761       scale = MAX (scale, output_scale);
762     }
763 
764   /* Notify app that scale changed */
765   gdk_wayland_window_maybe_configure (window, window->width, window->height, scale);
766 }
767 
768 static void
on_monitors_changed(GdkScreen * screen,GdkWindow * window)769 on_monitors_changed (GdkScreen *screen,
770                      GdkWindow *window)
771 {
772   window_update_scale (window);
773 }
774 
775 
776 static void gdk_wayland_window_create_surface (GdkWindow *window);
777 
778 void
_gdk_wayland_display_create_window_impl(GdkDisplay * display,GdkWindow * window,GdkWindow * real_parent,GdkScreen * screen,GdkEventMask event_mask,GdkWindowAttr * attributes,gint attributes_mask)779 _gdk_wayland_display_create_window_impl (GdkDisplay    *display,
780                                          GdkWindow     *window,
781                                          GdkWindow     *real_parent,
782                                          GdkScreen     *screen,
783                                          GdkEventMask   event_mask,
784                                          GdkWindowAttr *attributes,
785                                          gint           attributes_mask)
786 {
787   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
788   GdkWindowImplWayland *impl;
789   GdkFrameClock *frame_clock;
790   const char *title;
791 
792   impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL);
793   window->impl = GDK_WINDOW_IMPL (impl);
794   impl->unconfigured_width = window->width;
795   impl->unconfigured_height = window->height;
796   impl->wrapper = GDK_WINDOW (window);
797   impl->shortcuts_inhibitors = g_hash_table_new (NULL, NULL);
798   impl->using_csd = TRUE;
799   impl->surface_callback = NULL;
800   impl->frame_callback_surfaces = g_hash_table_new (NULL, NULL);
801 
802   if (window->width > 65535)
803     {
804       g_warning ("Native Windows wider than 65535 pixels are not supported");
805       window->width = 65535;
806     }
807   if (window->height > 65535)
808     {
809       g_warning ("Native Windows taller than 65535 pixels are not supported");
810       window->height = 65535;
811     }
812 
813   g_object_ref (window);
814 
815   /* More likely to be right than just assuming 1 */
816 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
817   if (display_wayland->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE &&
818       gdk_screen_get_n_monitors (screen) > 0)
819     impl->scale = gdk_screen_get_monitor_scale_factor (screen, 0);
820 G_GNUC_END_IGNORE_DEPRECATIONS
821 
822   impl->title = NULL;
823 
824   switch (GDK_WINDOW_TYPE (window))
825     {
826     case GDK_WINDOW_TOPLEVEL:
827     case GDK_WINDOW_TEMP:
828       if (attributes_mask & GDK_WA_TITLE)
829         title = attributes->title;
830       else
831         title = get_default_title ();
832 
833       gdk_window_set_title (window, title);
834       break;
835 
836     case GDK_WINDOW_CHILD:
837     default:
838       break;
839     }
840 
841   gdk_wayland_window_create_surface (window);
842 
843   if (attributes_mask & GDK_WA_TYPE_HINT)
844     gdk_window_set_type_hint (window, attributes->type_hint);
845 
846   frame_clock = gdk_window_get_frame_clock (window);
847 
848   g_signal_connect (frame_clock, "before-paint",
849                     G_CALLBACK (on_frame_clock_before_paint), window);
850   g_signal_connect (frame_clock, "after-paint",
851                     G_CALLBACK (on_frame_clock_after_paint), window);
852 
853   g_signal_connect (screen, "monitors-changed",
854                     G_CALLBACK (on_monitors_changed), window);
855 }
856 
857 static void
gdk_wayland_window_attach_image(GdkWindow * window)858 gdk_wayland_window_attach_image (GdkWindow *window)
859 {
860   GdkWaylandDisplay *display;
861   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
862 
863   if (GDK_WINDOW_DESTROYED (window))
864     return;
865 
866   g_assert (_gdk_wayland_is_shm_surface (impl->staging_cairo_surface));
867 
868   /* Attach this new buffer to the surface */
869   wl_surface_attach (impl->display_server.wl_surface,
870                      _gdk_wayland_shm_surface_get_wl_buffer (impl->staging_cairo_surface),
871                      impl->pending_buffer_offset_x,
872                      impl->pending_buffer_offset_y);
873   impl->pending_buffer_offset_x = 0;
874   impl->pending_buffer_offset_y = 0;
875 
876   /* Only set the buffer scale if supported by the compositor */
877   display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
878   if (display->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE)
879     wl_surface_set_buffer_scale (impl->display_server.wl_surface, impl->scale);
880 
881   impl->pending_buffer_attached = TRUE;
882   impl->pending_commit = TRUE;
883 }
884 
885 static const cairo_user_data_key_t gdk_wayland_window_cairo_key;
886 
887 static void
buffer_release_callback(void * _data,struct wl_buffer * wl_buffer)888 buffer_release_callback (void             *_data,
889                          struct wl_buffer *wl_buffer)
890 {
891   cairo_surface_t *cairo_surface = _data;
892   GdkWindowImplWayland *impl = cairo_surface_get_user_data (cairo_surface, &gdk_wayland_window_cairo_key);
893 
894   g_return_if_fail (GDK_IS_WINDOW_IMPL_WAYLAND (impl));
895 
896   /* The released buffer isn't the latest committed one, we have no further
897    * use for it, so clean it up.
898    */
899   if (impl->committed_cairo_surface != cairo_surface)
900     {
901       /* If this fails, then the surface buffer got reused before it was
902        * released from the compositor
903        */
904       g_warn_if_fail (impl->staging_cairo_surface != cairo_surface);
905 
906       cairo_surface_destroy (cairo_surface);
907       return;
908     }
909 
910   if (impl->staged_updates_region != NULL)
911     {
912       /* If this fails, then we're tracking staged updates on a staging surface
913        * that doesn't exist.
914        */
915       g_warn_if_fail (impl->staging_cairo_surface != NULL);
916 
917       /* If we've staged updates into a new buffer before the release for this
918        * buffer came in, then we can't reuse this buffer, so unref it. It may still
919        * be alive as a readback buffer though (via impl->backfill_cairo_surface).
920        *
921        * It's possible a staging surface was allocated but no updates were staged.
922        * If that happened, clean up that staging surface now, since the old commit
923        * buffer is available again, and reusing the old commit buffer for future
924        * updates will save having to do a read back later.
925        */
926       if (!cairo_region_is_empty (impl->staged_updates_region))
927         {
928           g_clear_pointer (&impl->committed_cairo_surface, cairo_surface_destroy);
929           return;
930         }
931       else
932         {
933           g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
934           g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
935         }
936     }
937 
938   /* Release came in, we haven't done any interim updates, so we can just use
939    * the old committed buffer again.
940    */
941   impl->staging_cairo_surface = g_steal_pointer (&impl->committed_cairo_surface);
942 }
943 
944 static const struct wl_buffer_listener buffer_listener = {
945   buffer_release_callback
946 };
947 
948 static void
gdk_wayland_window_ensure_cairo_surface(GdkWindow * window)949 gdk_wayland_window_ensure_cairo_surface (GdkWindow *window)
950 {
951   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
952 
953   /* If we are drawing using OpenGL then we only need a logical 1x1 surface. */
954   if (impl->display_server.egl_window)
955     {
956       if (impl->staging_cairo_surface &&
957           _gdk_wayland_is_shm_surface (impl->staging_cairo_surface))
958         g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
959 
960       if (!impl->staging_cairo_surface)
961         {
962           impl->staging_cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
963                                                                     impl->scale,
964                                                                     impl->scale);
965           cairo_surface_set_device_scale (impl->staging_cairo_surface,
966                                           impl->scale, impl->scale);
967         }
968     }
969   else if (!impl->staging_cairo_surface)
970     {
971       GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (impl->wrapper));
972       struct wl_buffer *buffer;
973 
974       impl->staging_cairo_surface = _gdk_wayland_display_create_shm_surface (display_wayland,
975                                                                              impl->wrapper->width,
976                                                                              impl->wrapper->height,
977                                                                              impl->scale);
978       cairo_surface_set_user_data (impl->staging_cairo_surface,
979                                    &gdk_wayland_window_cairo_key,
980                                    g_object_ref (impl),
981                                    (cairo_destroy_func_t)
982                                    g_object_unref);
983       buffer = _gdk_wayland_shm_surface_get_wl_buffer (impl->staging_cairo_surface);
984       wl_buffer_add_listener (buffer, &buffer_listener, impl->staging_cairo_surface);
985     }
986 }
987 
988 /* The cairo surface returned here uses a memory segment that's shared
989  * with the display server.  This is not a temporary buffer that gets
990  * copied to the display server, but the actual buffer the display server
991  * will ultimately end up sending to the GPU. At the time this happens
992  * impl->committed_cairo_surface gets set to impl->staging_cairo_surface, and
993  * impl->staging_cairo_surface gets nullified.
994  */
995 static cairo_surface_t *
gdk_wayland_window_ref_cairo_surface(GdkWindow * window)996 gdk_wayland_window_ref_cairo_surface (GdkWindow *window)
997 {
998   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
999 
1000   if (GDK_WINDOW_DESTROYED (impl->wrapper))
1001     return NULL;
1002 
1003   gdk_wayland_window_ensure_cairo_surface (window);
1004 
1005   cairo_surface_reference (impl->staging_cairo_surface);
1006 
1007   return impl->staging_cairo_surface;
1008 }
1009 
1010 static cairo_surface_t *
gdk_wayland_window_create_similar_image_surface(GdkWindow * window,cairo_format_t format,int width,int height)1011 gdk_wayland_window_create_similar_image_surface (GdkWindow *     window,
1012                                                  cairo_format_t  format,
1013                                                  int             width,
1014                                                  int             height)
1015 {
1016   return cairo_image_surface_create (format, width, height);
1017 }
1018 
1019 static gboolean
gdk_window_impl_wayland_begin_paint(GdkWindow * window)1020 gdk_window_impl_wayland_begin_paint (GdkWindow *window)
1021 {
1022   gdk_wayland_window_ensure_cairo_surface (window);
1023 
1024   return FALSE;
1025 }
1026 
1027 static void
gdk_window_impl_wayland_end_paint(GdkWindow * window)1028 gdk_window_impl_wayland_end_paint (GdkWindow *window)
1029 {
1030   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1031   cairo_rectangle_int_t rect;
1032   int i, n;
1033 
1034   if (!GDK_WINDOW_IS_MAPPED (window))
1035     return;
1036 
1037   if (impl->staging_cairo_surface &&
1038       _gdk_wayland_is_shm_surface (impl->staging_cairo_surface) &&
1039       !window->current_paint.use_gl &&
1040       !cairo_region_is_empty (window->current_paint.region))
1041     {
1042       gdk_wayland_window_attach_image (window);
1043 
1044       /* If there's a committed buffer pending, then track which
1045        * updates are staged until the next frame, so we can back
1046        * fill the unstaged parts of the staging buffer with the
1047        * last frame.
1048        */
1049       if (impl->committed_cairo_surface != NULL)
1050         {
1051           if (impl->staged_updates_region == NULL)
1052             {
1053               impl->staged_updates_region = cairo_region_copy (window->current_paint.region);
1054               impl->backfill_cairo_surface = cairo_surface_reference (impl->committed_cairo_surface);
1055             }
1056           else
1057             {
1058               cairo_region_union (impl->staged_updates_region, window->current_paint.region);
1059             }
1060         }
1061 
1062       n = cairo_region_num_rectangles (window->current_paint.region);
1063       for (i = 0; i < n; i++)
1064         {
1065           cairo_region_get_rectangle (window->current_paint.region, i, &rect);
1066           wl_surface_damage (impl->display_server.wl_surface, rect.x, rect.y, rect.width, rect.height);
1067         }
1068 
1069       impl->pending_commit = TRUE;
1070     }
1071 
1072   gdk_wayland_window_sync_margin (window);
1073   gdk_wayland_window_sync_opaque_region (window);
1074   gdk_wayland_window_sync_input_region (window);
1075 }
1076 
1077 static gboolean
gdk_window_impl_wayland_beep(GdkWindow * window)1078 gdk_window_impl_wayland_beep (GdkWindow *window)
1079 {
1080   gdk_wayland_display_system_bell (gdk_window_get_display (window),
1081                                    window);
1082 
1083   return TRUE;
1084 }
1085 
1086 static void
gdk_window_impl_wayland_finalize(GObject * object)1087 gdk_window_impl_wayland_finalize (GObject *object)
1088 {
1089   GdkWindowImplWayland *impl;
1090 
1091   g_return_if_fail (GDK_IS_WINDOW_IMPL_WAYLAND (object));
1092 
1093   impl = GDK_WINDOW_IMPL_WAYLAND (object);
1094 
1095   if (gdk_wayland_window_is_exported (impl->wrapper))
1096     gdk_wayland_window_unexport_handle (impl->wrapper);
1097 
1098   g_free (impl->title);
1099 
1100   g_free (impl->application.application_id);
1101   g_free (impl->application.app_menu_path);
1102   g_free (impl->application.menubar_path);
1103   g_free (impl->application.window_object_path);
1104   g_free (impl->application.application_object_path);
1105   g_free (impl->application.unique_bus_name);
1106 
1107   g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
1108   g_clear_pointer (&impl->input_region, cairo_region_destroy);
1109   g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
1110 
1111   g_clear_pointer (&impl->shortcuts_inhibitors, g_hash_table_unref);
1112   g_clear_pointer (&impl->frame_callback_surfaces, g_hash_table_unref);
1113 
1114   G_OBJECT_CLASS (_gdk_window_impl_wayland_parent_class)->finalize (object);
1115 }
1116 
1117 static void
gdk_wayland_window_configure(GdkWindow * window,int width,int height,int scale)1118 gdk_wayland_window_configure (GdkWindow *window,
1119                               int        width,
1120                               int        height,
1121                               int        scale)
1122 {
1123   GdkDisplay *display;
1124   GdkEvent *event;
1125 
1126   g_return_if_fail (width > 0);
1127   g_return_if_fail (height > 0);
1128 
1129   event = gdk_event_new (GDK_CONFIGURE);
1130   event->configure.window = g_object_ref (window);
1131   event->configure.send_event = FALSE;
1132   event->configure.width = width;
1133   event->configure.height = height;
1134 
1135   gdk_wayland_window_update_size (window, width, height, scale);
1136   _gdk_window_update_size (window);
1137 
1138   display = gdk_window_get_display (window);
1139   _gdk_wayland_display_deliver_event (display, event);
1140 }
1141 
1142 static gboolean
is_realized_shell_surface(GdkWindow * window)1143 is_realized_shell_surface (GdkWindow *window)
1144 {
1145   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1146 
1147   return (impl->display_server.xdg_surface ||
1148           impl->display_server.zxdg_surface_v6);
1149 }
1150 
1151 static gboolean
is_realized_toplevel(GdkWindow * window)1152 is_realized_toplevel (GdkWindow *window)
1153 {
1154   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1155 
1156   return (impl->display_server.xdg_toplevel ||
1157           impl->display_server.zxdg_toplevel_v6);
1158 }
1159 
1160 static gboolean
is_realized_popup(GdkWindow * window)1161 is_realized_popup (GdkWindow *window)
1162 {
1163   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1164 
1165   return (impl->display_server.xdg_popup ||
1166           impl->display_server.zxdg_popup_v6);
1167 }
1168 
1169 static gboolean
should_inhibit_resize(GdkWindow * window)1170 should_inhibit_resize (GdkWindow *window)
1171 {
1172   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1173 
1174   if (impl->display_server.wl_subsurface)
1175     return FALSE;
1176   else if (impl->use_custom_surface)
1177     return FALSE;
1178   else if (impl->hint == GDK_WINDOW_TYPE_HINT_DND)
1179     return FALSE;
1180   else if (is_realized_popup (window))
1181     return FALSE;
1182   else if (should_map_as_popup (window))
1183     return FALSE;
1184   else if (should_map_as_subsurface (window))
1185     return FALSE;
1186 
1187   /* This should now either be, or eventually be, a toplevel window,
1188    * and we should wait for the initial configure to really configure it.
1189    */
1190   return !impl->initial_configure_received;
1191 }
1192 
1193 static void
gdk_wayland_window_maybe_configure(GdkWindow * window,int width,int height,int scale)1194 gdk_wayland_window_maybe_configure (GdkWindow *window,
1195                                     int        width,
1196                                     int        height,
1197                                     int        scale)
1198 {
1199   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1200   gboolean is_xdg_popup;
1201   gboolean is_visible;
1202   gboolean size_changed;
1203 
1204   impl->unconfigured_width = calculate_width_without_margin (window, width);
1205   impl->unconfigured_height = calculate_height_without_margin (window, height);
1206 
1207   if (should_inhibit_resize (window))
1208     return;
1209 
1210   size_changed = (window->width != width || window->height != height);
1211   if (!size_changed && impl->scale == scale)
1212     return;
1213 
1214   /* For xdg_popup using an xdg_positioner, there is a race condition if
1215    * the application tries to change the size after it's mapped, but before
1216    * the initial configure is received, so hide and show the surface again
1217    * force the new size onto the compositor. See bug #772505.
1218    */
1219 
1220   is_xdg_popup = is_realized_popup (window);
1221   is_visible = gdk_window_is_visible (window);
1222 
1223   if (is_xdg_popup &&
1224       is_visible &&
1225       size_changed &&
1226       !impl->initial_configure_received &&
1227       !impl->configuring_popup)
1228     gdk_window_hide (window);
1229 
1230   gdk_wayland_window_configure (window, width, height, scale);
1231 
1232   if (is_xdg_popup &&
1233       is_visible &&
1234       size_changed &&
1235       !impl->initial_configure_received &&
1236       !impl->configuring_popup)
1237     gdk_window_show (window);
1238 }
1239 
1240 static void
gdk_wayland_window_sync_parent(GdkWindow * window,GdkWindow * parent)1241 gdk_wayland_window_sync_parent (GdkWindow *window,
1242                                 GdkWindow *parent)
1243 {
1244   GdkWaylandDisplay *display_wayland =
1245     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1246   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1247   GdkWindowImplWayland *impl_parent = NULL;
1248 
1249   g_assert (parent == NULL ||
1250             gdk_window_get_display (window) == gdk_window_get_display (parent));
1251 
1252   if (!is_realized_toplevel (window))
1253     return;
1254 
1255   if (impl->transient_for)
1256     impl_parent = GDK_WINDOW_IMPL_WAYLAND (impl->transient_for->impl);
1257   else if (parent)
1258     impl_parent = GDK_WINDOW_IMPL_WAYLAND (parent->impl);
1259 
1260   /* XXX: Is this correct? */
1261   if (impl_parent && !impl_parent->display_server.wl_surface)
1262     return;
1263 
1264   switch (display_wayland->shell_variant)
1265     {
1266     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1267       {
1268         struct xdg_toplevel *parent_toplevel;
1269 
1270         if (impl_parent)
1271           parent_toplevel = impl_parent->display_server.xdg_toplevel;
1272         else
1273           parent_toplevel = NULL;
1274 
1275         xdg_toplevel_set_parent (impl->display_server.xdg_toplevel,
1276                                  parent_toplevel);
1277         break;
1278       }
1279       break;
1280     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1281       {
1282         struct zxdg_toplevel_v6 *parent_toplevel;
1283 
1284         if (impl_parent)
1285           parent_toplevel = impl_parent->display_server.zxdg_toplevel_v6;
1286         else
1287           parent_toplevel = NULL;
1288 
1289         zxdg_toplevel_v6_set_parent (impl->display_server.zxdg_toplevel_v6,
1290                                      parent_toplevel);
1291         break;
1292       }
1293     }
1294 }
1295 
1296 static void
gdk_wayland_window_sync_parent_of_imported(GdkWindow * window)1297 gdk_wayland_window_sync_parent_of_imported (GdkWindow *window)
1298 {
1299   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1300 
1301   if (!impl->display_server.wl_surface)
1302     return;
1303 
1304   if (!impl->imported_transient_for)
1305     return;
1306 
1307   if (!is_realized_toplevel (window))
1308     return;
1309 
1310   zxdg_imported_v1_set_parent_of (impl->imported_transient_for,
1311                                   impl->display_server.wl_surface);
1312 }
1313 
1314 static void
gdk_wayland_window_update_dialogs(GdkWindow * window)1315 gdk_wayland_window_update_dialogs (GdkWindow *window)
1316 {
1317   GdkWaylandDisplay *display_wayland =
1318     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1319   GList *l;
1320 
1321   if (!display_wayland->orphan_dialogs)
1322     return;
1323 
1324   for (l = display_wayland->orphan_dialogs; l; l = l->next)
1325     {
1326       GdkWindow *w = l->data;
1327       GdkWindowImplWayland *impl;
1328 
1329       if (!GDK_IS_WINDOW_IMPL_WAYLAND(w->impl))
1330         continue;
1331 
1332       impl = GDK_WINDOW_IMPL_WAYLAND (w->impl);
1333       if (w == window)
1334 	continue;
1335       if (impl->hint != GDK_WINDOW_TYPE_HINT_DIALOG)
1336         continue;
1337       if (impl->transient_for)
1338         continue;
1339 
1340       /* Update the parent relationship only for dialogs without transients */
1341       gdk_wayland_window_sync_parent (w, window);
1342     }
1343 }
1344 
1345 static void
gdk_wayland_window_sync_title(GdkWindow * window)1346 gdk_wayland_window_sync_title (GdkWindow *window)
1347 {
1348   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1349   GdkWaylandDisplay *display_wayland =
1350     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1351 
1352   if (!is_realized_toplevel (window))
1353     return;
1354 
1355   if (!impl->title)
1356     return;
1357 
1358   switch (display_wayland->shell_variant)
1359     {
1360     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1361       xdg_toplevel_set_title (impl->display_server.xdg_toplevel,
1362                               impl->title);
1363       break;
1364     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1365       zxdg_toplevel_v6_set_title (impl->display_server.zxdg_toplevel_v6,
1366                                   impl->title);
1367       break;
1368     }
1369 }
1370 
1371 static void
gdk_wayland_window_get_window_geometry(GdkWindow * window,GdkRectangle * geometry)1372 gdk_wayland_window_get_window_geometry (GdkWindow    *window,
1373                                         GdkRectangle *geometry)
1374 {
1375   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1376 
1377   *geometry = (GdkRectangle) {
1378     .x = impl->margin_left,
1379     .y = impl->margin_top,
1380     .width = calculate_width_without_margin (window, window->width),
1381     .height = calculate_height_without_margin (window, window->height)
1382   };
1383 }
1384 
1385 static void
gdk_wayland_window_sync_margin(GdkWindow * window)1386 gdk_wayland_window_sync_margin (GdkWindow *window)
1387 {
1388   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1389   GdkWaylandDisplay *display_wayland =
1390     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1391   GdkRectangle geometry;
1392 
1393   if (!is_realized_shell_surface (window))
1394     return;
1395 
1396   gdk_wayland_window_get_window_geometry (window, &geometry);
1397 
1398   g_return_if_fail (geometry.width > 0 && geometry.height > 0);
1399 
1400   gdk_window_set_geometry_hints (window,
1401                                  &impl->geometry_hints,
1402                                  impl->geometry_mask);
1403 
1404   switch (display_wayland->shell_variant)
1405     {
1406     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1407       xdg_surface_set_window_geometry (impl->display_server.xdg_surface,
1408                                        geometry.x,
1409                                        geometry.y,
1410                                        geometry.width,
1411                                        geometry.height);
1412       break;
1413     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1414       zxdg_surface_v6_set_window_geometry (impl->display_server.zxdg_surface_v6,
1415                                            geometry.x,
1416                                            geometry.y,
1417                                            geometry.width,
1418                                            geometry.height);
1419       break;
1420     }
1421 }
1422 
1423 static struct wl_region *
wl_region_from_cairo_region(GdkWaylandDisplay * display,cairo_region_t * region)1424 wl_region_from_cairo_region (GdkWaylandDisplay *display,
1425                              cairo_region_t    *region)
1426 {
1427   struct wl_region *wl_region;
1428   int i, n_rects;
1429 
1430   wl_region = wl_compositor_create_region (display->compositor);
1431   if (wl_region == NULL)
1432     return NULL;
1433 
1434   n_rects = cairo_region_num_rectangles (region);
1435   for (i = 0; i < n_rects; i++)
1436     {
1437       cairo_rectangle_int_t rect;
1438       cairo_region_get_rectangle (region, i, &rect);
1439       wl_region_add (wl_region, rect.x, rect.y, rect.width, rect.height);
1440     }
1441 
1442   return wl_region;
1443 }
1444 
1445 static void
gdk_wayland_window_sync_opaque_region(GdkWindow * window)1446 gdk_wayland_window_sync_opaque_region (GdkWindow *window)
1447 {
1448   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1449   struct wl_region *wl_region = NULL;
1450 
1451   if (!impl->display_server.wl_surface)
1452     return;
1453 
1454   if (!impl->opaque_region_dirty)
1455     return;
1456 
1457   if (impl->opaque_region != NULL)
1458     wl_region = wl_region_from_cairo_region (GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)),
1459                                              impl->opaque_region);
1460 
1461   wl_surface_set_opaque_region (impl->display_server.wl_surface, wl_region);
1462 
1463   if (wl_region != NULL)
1464     wl_region_destroy (wl_region);
1465 
1466   impl->opaque_region_dirty = FALSE;
1467 }
1468 
1469 static void
gdk_wayland_window_sync_input_region(GdkWindow * window)1470 gdk_wayland_window_sync_input_region (GdkWindow *window)
1471 {
1472   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1473   struct wl_region *wl_region = NULL;
1474 
1475   if (!impl->display_server.wl_surface)
1476     return;
1477 
1478   if (!impl->input_region_dirty)
1479     return;
1480 
1481   if (impl->input_region != NULL)
1482     wl_region = wl_region_from_cairo_region (GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)),
1483                                              impl->input_region);
1484 
1485   wl_surface_set_input_region (impl->display_server.wl_surface, wl_region);
1486 
1487   if (wl_region != NULL)
1488     wl_region_destroy (wl_region);
1489 
1490   impl->input_region_dirty = FALSE;
1491 }
1492 
1493 static void
gdk_wayland_set_input_region_if_empty(GdkWindow * window)1494 gdk_wayland_set_input_region_if_empty (GdkWindow *window)
1495 {
1496   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1497   GdkWaylandDisplay *display;
1498   struct wl_region *empty;
1499 
1500   if (!impl->input_region_dirty)
1501     return;
1502 
1503   if (impl->input_region == NULL)
1504     return;
1505 
1506   if (!cairo_region_is_empty (impl->input_region))
1507     return;
1508 
1509   display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1510   empty = wl_compositor_create_region (display->compositor);
1511 
1512   wl_surface_set_input_region (impl->display_server.wl_surface, empty);
1513   wl_region_destroy (empty);
1514 
1515   impl->input_region_dirty = FALSE;
1516 }
1517 
1518 static void
surface_enter(void * data,struct wl_surface * wl_surface,struct wl_output * output)1519 surface_enter (void              *data,
1520                struct wl_surface *wl_surface,
1521                struct wl_output  *output)
1522 {
1523   GdkWindow *window = GDK_WINDOW (data);
1524   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1525   GdkWaylandDisplay *display_wayland =
1526     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1527   gboolean output_is_unmanaged;
1528 
1529   output_is_unmanaged =
1530     _gdk_wayland_screen_get_output_scale (display_wayland->screen, output) == 0;
1531   if (output_is_unmanaged)
1532     return;
1533 
1534   GDK_NOTE (EVENTS,
1535             g_message ("surface enter, window %p output %p", window, output));
1536 
1537   impl->display_server.outputs = g_slist_prepend (impl->display_server.outputs, output);
1538 
1539   window_update_scale (window);
1540 }
1541 
1542 static void
surface_leave(void * data,struct wl_surface * wl_surface,struct wl_output * output)1543 surface_leave (void              *data,
1544                struct wl_surface *wl_surface,
1545                struct wl_output  *output)
1546 {
1547   GdkWindow *window = GDK_WINDOW (data);
1548   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1549 
1550   GDK_NOTE (EVENTS,
1551             g_message ("surface leave, window %p output %p", window, output));
1552 
1553   impl->display_server.outputs = g_slist_remove (impl->display_server.outputs, output);
1554 
1555   if (impl->display_server.outputs)
1556     window_update_scale (window);
1557 }
1558 
1559 static const struct wl_surface_listener surface_listener = {
1560   surface_enter,
1561   surface_leave
1562 };
1563 
1564 static void
on_parent_surface_committed(GdkWindowImplWayland * parent_impl,GdkWindow * window)1565 on_parent_surface_committed (GdkWindowImplWayland *parent_impl,
1566                              GdkWindow            *window)
1567 {
1568   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1569 
1570   g_signal_handler_disconnect (parent_impl,
1571                                impl->parent_surface_committed_handler);
1572   impl->parent_surface_committed_handler = 0;
1573 
1574   wl_subsurface_set_desync (impl->display_server.wl_subsurface);
1575 
1576   /* Special case if the input region is empty, it won't change on resize */
1577   gdk_wayland_set_input_region_if_empty (window);
1578 }
1579 
1580 static void
gdk_wayland_window_set_subsurface_position(GdkWindow * window,int x,int y)1581 gdk_wayland_window_set_subsurface_position (GdkWindow *window,
1582                                             int        x,
1583                                             int        y)
1584 {
1585   GdkWindowImplWayland *impl;
1586 
1587   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1588 
1589   wl_subsurface_set_position (impl->display_server.wl_subsurface, x, y);
1590   impl->subsurface_x = x;
1591   impl->subsurface_y = y;
1592 
1593   gdk_window_request_transient_parent_commit (window);
1594 }
1595 
1596 static void
gdk_wayland_window_create_subsurface(GdkWindow * window)1597 gdk_wayland_window_create_subsurface (GdkWindow *window)
1598 {
1599   GdkWindowImplWayland *impl, *parent_impl = NULL;
1600   GdkWaylandDisplay *display_wayland;
1601 
1602   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1603 
1604   if (!impl->display_server.wl_surface)
1605     return; /* Bail out, surface and subsurface will be created later when shown */
1606 
1607   if (impl->display_server.wl_subsurface)
1608     return;
1609 
1610   if (impl->transient_for)
1611     parent_impl = GDK_WINDOW_IMPL_WAYLAND (impl->transient_for->impl);
1612 
1613   if (parent_impl && parent_impl->display_server.wl_surface)
1614     {
1615       display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1616       impl->display_server.wl_subsurface =
1617         wl_subcompositor_get_subsurface (display_wayland->subcompositor,
1618                                          impl->display_server.wl_surface, parent_impl->display_server.wl_surface);
1619 
1620       /* In order to synchronize the initial position with the initial frame
1621        * content, wait with making the subsurface desynchronized until after
1622        * the parent was committed.
1623        */
1624       impl->parent_surface_committed_handler =
1625         g_signal_connect_object (parent_impl, "committed",
1626                                  G_CALLBACK (on_parent_surface_committed),
1627                                  window, 0);
1628 
1629       gdk_wayland_window_set_subsurface_position (window,
1630                                                   window->x + window->abs_x,
1631                                                   window->y + window->abs_y);
1632     }
1633 }
1634 
1635 static void
gdk_wayland_window_create_surface(GdkWindow * window)1636 gdk_wayland_window_create_surface (GdkWindow *window)
1637 {
1638   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1639   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1640 
1641   impl->display_server.wl_surface = wl_compositor_create_surface (display_wayland->compositor);
1642   wl_surface_add_listener (impl->display_server.wl_surface, &surface_listener, window);
1643 }
1644 
1645 static gboolean
should_use_fixed_size(GdkWindowState state)1646 should_use_fixed_size (GdkWindowState state)
1647 {
1648   return state & (GDK_WINDOW_STATE_MAXIMIZED |
1649                   GDK_WINDOW_STATE_FULLSCREEN |
1650                   GDK_WINDOW_STATE_TILED);
1651 }
1652 
1653 static void
gdk_wayland_window_handle_configure(GdkWindow * window,uint32_t serial)1654 gdk_wayland_window_handle_configure (GdkWindow *window,
1655                                      uint32_t   serial)
1656 {
1657   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1658   GdkWaylandDisplay *display_wayland =
1659     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1660   GdkWindowState new_state;
1661   int width = impl->pending.width;
1662   int height = impl->pending.height;
1663   gboolean fixed_size;
1664   gboolean saved_size;
1665 
1666   if (!impl->initial_configure_received)
1667     {
1668       gdk_window_thaw_updates (window);
1669       impl->initial_configure_received = TRUE;
1670     }
1671 
1672   if (impl->display_server.xdg_popup)
1673     {
1674       xdg_surface_ack_configure (impl->display_server.xdg_surface, serial);
1675       return;
1676     }
1677   else if (impl->display_server.zxdg_popup_v6)
1678     {
1679       zxdg_surface_v6_ack_configure (impl->display_server.zxdg_surface_v6,
1680                                      serial);
1681       return;
1682     }
1683 
1684   new_state = impl->pending.state;
1685   impl->pending.state = 0;
1686 
1687   fixed_size = should_use_fixed_size (new_state);
1688 
1689   saved_size = (width == 0 && height == 0);
1690   /* According to xdg_shell, an xdg_surface.configure with size 0x0
1691    * should be interpreted as that it is up to the client to set a
1692    * size.
1693    *
1694    * When transitioning from maximize or fullscreen state, this means
1695    * the client should configure its size back to what it was before
1696    * being maximize or fullscreen.
1697    * Additionally, if we receive a manual resize request, we must prefer this
1698    * new size instead of the compositor's size hints.
1699    * In such a scenario, and without letting the compositor know about the new
1700    * size, the client has to manage all dimensions and ignore any server hints.
1701    */
1702   if (!fixed_size && (saved_size || impl->saved_size_changed))
1703     {
1704       width = impl->saved_width;
1705       height = impl->saved_height;
1706       impl->saved_size_changed = FALSE;
1707     }
1708 
1709   if (width > 0 && height > 0)
1710     {
1711       GdkWindowHints geometry_mask = impl->geometry_mask;
1712       int configure_width;
1713       int configure_height;
1714 
1715       /* Ignore size increments for maximized/fullscreen windows */
1716       if (fixed_size)
1717         geometry_mask &= ~GDK_HINT_RESIZE_INC;
1718       if (!saved_size)
1719         {
1720           /* Do not reapply contrains if we are restoring original size */
1721           gdk_window_constrain_size (&impl->geometry_hints,
1722                                      geometry_mask,
1723                                      calculate_width_with_margin (window, width),
1724                                      calculate_height_with_margin (window, height),
1725                                      &width,
1726                                      &height);
1727 
1728           /* Save size for next time we get 0x0 */
1729           _gdk_wayland_window_save_size (window);
1730         }
1731 
1732       if (saved_size)
1733         {
1734           configure_width = calculate_width_with_margin (window, width);
1735           configure_height = calculate_height_with_margin (window, height);
1736         }
1737       else
1738         {
1739           configure_width = width;
1740           configure_height = height;
1741         }
1742       gdk_wayland_window_configure (window,
1743                                     configure_width,
1744                                     configure_height,
1745                                     impl->scale);
1746     }
1747   else
1748     {
1749       int unconfigured_width;
1750       int unconfigured_height;
1751 
1752       unconfigured_width =
1753         calculate_width_with_margin (window, impl->unconfigured_width);
1754       unconfigured_height =
1755         calculate_height_with_margin (window, impl->unconfigured_height);
1756       gdk_wayland_window_configure (window,
1757                                     unconfigured_width,
1758                                     unconfigured_height,
1759                                     impl->scale);
1760     }
1761 
1762   if (fixed_size)
1763     {
1764       impl->fixed_size_width = width;
1765       impl->fixed_size_height = height;
1766     }
1767 
1768   GDK_NOTE (EVENTS,
1769             g_message ("configure, window %p %dx%d,%s%s%s%s",
1770                        window, width, height,
1771                        (new_state & GDK_WINDOW_STATE_FULLSCREEN) ? " fullscreen" : "",
1772                        (new_state & GDK_WINDOW_STATE_MAXIMIZED) ? " maximized" : "",
1773                        (new_state & GDK_WINDOW_STATE_FOCUSED) ? " focused" : "",
1774                        (new_state & GDK_WINDOW_STATE_TILED) ? " tiled" : ""));
1775 
1776   _gdk_set_window_state (window, new_state);
1777 
1778   switch (display_wayland->shell_variant)
1779     {
1780     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1781       xdg_surface_ack_configure (impl->display_server.xdg_surface, serial);
1782       break;
1783     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1784       zxdg_surface_v6_ack_configure (impl->display_server.zxdg_surface_v6,
1785                                      serial);
1786       break;
1787     }
1788 
1789   if (impl->hint != GDK_WINDOW_TYPE_HINT_DIALOG &&
1790       new_state & GDK_WINDOW_STATE_FOCUSED)
1791     gdk_wayland_window_update_dialogs (window);
1792 }
1793 
1794 static void
gdk_wayland_window_handle_configure_toplevel(GdkWindow * window,int32_t width,int32_t height,GdkWindowState state)1795 gdk_wayland_window_handle_configure_toplevel (GdkWindow     *window,
1796                                               int32_t        width,
1797                                               int32_t        height,
1798                                               GdkWindowState state)
1799 {
1800   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1801 
1802   impl->pending.state |= state;
1803   impl->pending.width = width;
1804   impl->pending.height = height;
1805 }
1806 
1807 static void
gdk_wayland_window_handle_close(GdkWindow * window)1808 gdk_wayland_window_handle_close (GdkWindow *window)
1809 {
1810   GdkDisplay *display;
1811   GdkEvent *event;
1812 
1813   GDK_NOTE (EVENTS,
1814             g_message ("close %p", window));
1815 
1816   event = gdk_event_new (GDK_DELETE);
1817   event->any.window = g_object_ref (window);
1818   event->any.send_event = TRUE;
1819 
1820   display = gdk_window_get_display (window);
1821   _gdk_wayland_display_deliver_event (display, event);
1822 }
1823 
1824 static void
xdg_surface_configure(void * data,struct xdg_surface * xdg_surface,uint32_t serial)1825 xdg_surface_configure (void               *data,
1826                        struct xdg_surface *xdg_surface,
1827                        uint32_t            serial)
1828 {
1829   GdkWindow *window = GDK_WINDOW (data);
1830 
1831   gdk_wayland_window_handle_configure (window, serial);
1832 }
1833 
1834 static const struct xdg_surface_listener xdg_surface_listener = {
1835   xdg_surface_configure,
1836 };
1837 
1838 static void
xdg_toplevel_configure(void * data,struct xdg_toplevel * xdg_toplevel,int32_t width,int32_t height,struct wl_array * states)1839 xdg_toplevel_configure (void                *data,
1840                         struct xdg_toplevel *xdg_toplevel,
1841                         int32_t              width,
1842                         int32_t              height,
1843                         struct wl_array     *states)
1844 {
1845   GdkWindow *window = GDK_WINDOW (data);
1846   uint32_t *p;
1847   GdkWindowState pending_state = 0;
1848 
1849   wl_array_for_each (p, states)
1850     {
1851       uint32_t state = *p;
1852 
1853       switch (state)
1854         {
1855         case XDG_TOPLEVEL_STATE_FULLSCREEN:
1856           pending_state |= GDK_WINDOW_STATE_FULLSCREEN;
1857           break;
1858         case XDG_TOPLEVEL_STATE_MAXIMIZED:
1859           pending_state |= GDK_WINDOW_STATE_MAXIMIZED;
1860           break;
1861         case XDG_TOPLEVEL_STATE_ACTIVATED:
1862           pending_state |= GDK_WINDOW_STATE_FOCUSED;
1863           break;
1864         case XDG_TOPLEVEL_STATE_RESIZING:
1865           break;
1866         default:
1867           /* Unknown state */
1868           break;
1869         }
1870     }
1871 
1872   gdk_wayland_window_handle_configure_toplevel (window, width, height,
1873                                                 pending_state);
1874 }
1875 
1876 static void
xdg_toplevel_close(void * data,struct xdg_toplevel * xdg_toplevel)1877 xdg_toplevel_close (void                *data,
1878                     struct xdg_toplevel *xdg_toplevel)
1879 {
1880   GdkWindow *window = GDK_WINDOW (data);
1881 
1882   gdk_wayland_window_handle_close (window);
1883 }
1884 
1885 static const struct xdg_toplevel_listener xdg_toplevel_listener = {
1886   xdg_toplevel_configure,
1887   xdg_toplevel_close,
1888 };
1889 
1890 static void
create_xdg_toplevel_resources(GdkWindow * window)1891 create_xdg_toplevel_resources (GdkWindow *window)
1892 {
1893   GdkWaylandDisplay *display_wayland =
1894     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1895   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1896 
1897   impl->display_server.xdg_surface =
1898     xdg_wm_base_get_xdg_surface (display_wayland->xdg_wm_base,
1899                                  impl->display_server.wl_surface);
1900   xdg_surface_add_listener (impl->display_server.xdg_surface,
1901                             &xdg_surface_listener,
1902                             window);
1903 
1904   impl->display_server.xdg_toplevel =
1905     xdg_surface_get_toplevel (impl->display_server.xdg_surface);
1906   xdg_toplevel_add_listener (impl->display_server.xdg_toplevel,
1907                              &xdg_toplevel_listener,
1908                              window);
1909 }
1910 
1911 static void
zxdg_surface_v6_configure(void * data,struct zxdg_surface_v6 * xdg_surface,uint32_t serial)1912 zxdg_surface_v6_configure (void                   *data,
1913                            struct zxdg_surface_v6 *xdg_surface,
1914                            uint32_t                serial)
1915 {
1916   GdkWindow *window = GDK_WINDOW (data);
1917 
1918   gdk_wayland_window_handle_configure (window, serial);
1919 }
1920 
1921 static const struct zxdg_surface_v6_listener zxdg_surface_v6_listener = {
1922   zxdg_surface_v6_configure,
1923 };
1924 
1925 static void
zxdg_toplevel_v6_configure(void * data,struct zxdg_toplevel_v6 * xdg_toplevel,int32_t width,int32_t height,struct wl_array * states)1926 zxdg_toplevel_v6_configure (void                    *data,
1927                             struct zxdg_toplevel_v6 *xdg_toplevel,
1928                             int32_t                  width,
1929                             int32_t                  height,
1930                             struct wl_array         *states)
1931 {
1932   GdkWindow *window = GDK_WINDOW (data);
1933   uint32_t *p;
1934   GdkWindowState pending_state = 0;
1935 
1936   wl_array_for_each (p, states)
1937     {
1938       uint32_t state = *p;
1939 
1940       switch (state)
1941         {
1942         case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
1943           pending_state |= GDK_WINDOW_STATE_FULLSCREEN;
1944           break;
1945         case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED:
1946           pending_state |= GDK_WINDOW_STATE_MAXIMIZED;
1947           break;
1948         case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED:
1949           pending_state |= GDK_WINDOW_STATE_FOCUSED;
1950           break;
1951         case ZXDG_TOPLEVEL_V6_STATE_RESIZING:
1952           break;
1953         default:
1954           /* Unknown state */
1955           break;
1956         }
1957     }
1958 
1959   gdk_wayland_window_handle_configure_toplevel (window, width, height,
1960                                                 pending_state);
1961 }
1962 
1963 static void
zxdg_toplevel_v6_close(void * data,struct zxdg_toplevel_v6 * xdg_toplevel)1964 zxdg_toplevel_v6_close (void                    *data,
1965                         struct zxdg_toplevel_v6 *xdg_toplevel)
1966 {
1967   GdkWindow *window = GDK_WINDOW (data);
1968 
1969   gdk_wayland_window_handle_close (window);
1970 }
1971 
1972 static const struct zxdg_toplevel_v6_listener zxdg_toplevel_v6_listener = {
1973   zxdg_toplevel_v6_configure,
1974   zxdg_toplevel_v6_close,
1975 };
1976 
1977 static void
create_zxdg_toplevel_v6_resources(GdkWindow * window)1978 create_zxdg_toplevel_v6_resources (GdkWindow *window)
1979 {
1980   GdkWaylandDisplay *display_wayland =
1981     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1982   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1983 
1984   impl->display_server.zxdg_surface_v6 =
1985     zxdg_shell_v6_get_xdg_surface (display_wayland->zxdg_shell_v6,
1986                                    impl->display_server.wl_surface);
1987   zxdg_surface_v6_add_listener (impl->display_server.zxdg_surface_v6,
1988                                 &zxdg_surface_v6_listener,
1989                                 window);
1990 
1991   impl->display_server.zxdg_toplevel_v6 =
1992     zxdg_surface_v6_get_toplevel (impl->display_server.zxdg_surface_v6);
1993   zxdg_toplevel_v6_add_listener (impl->display_server.zxdg_toplevel_v6,
1994                                  &zxdg_toplevel_v6_listener,
1995                                  window);
1996 }
1997 
1998 void
gdk_wayland_window_set_application_id(GdkWindow * window,const char * application_id)1999 gdk_wayland_window_set_application_id (GdkWindow *window, const char* application_id)
2000 {
2001   GdkWindowImplWayland *impl;
2002   GdkWaylandDisplay *display_wayland;
2003 
2004   g_return_if_fail (application_id != NULL);
2005 
2006   if (GDK_WINDOW_DESTROYED (window))
2007     return;
2008 
2009   if (!is_realized_toplevel (window))
2010     return;
2011 
2012   display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
2013   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2014 
2015   switch (display_wayland->shell_variant)
2016     {
2017     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
2018       xdg_toplevel_set_app_id (impl->display_server.xdg_toplevel,
2019                                application_id);
2020       break;
2021     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
2022       zxdg_toplevel_v6_set_app_id (impl->display_server.zxdg_toplevel_v6,
2023                                    application_id);
2024       break;
2025     }
2026 }
2027 
2028 static void
gdk_wayland_window_create_xdg_toplevel(GdkWindow * window)2029 gdk_wayland_window_create_xdg_toplevel (GdkWindow *window)
2030 {
2031   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
2032   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2033   const gchar *app_id;
2034   GdkScreen *screen = gdk_window_get_screen (window);
2035   struct wl_output *fullscreen_output = NULL;
2036 
2037 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2038   if (impl->initial_fullscreen_monitor >= 0 &&
2039       impl->initial_fullscreen_monitor < gdk_screen_get_n_monitors (screen))
2040     fullscreen_output =
2041       _gdk_wayland_screen_get_wl_output (screen,
2042                                          impl->initial_fullscreen_monitor);
2043 G_GNUC_END_IGNORE_DEPRECATIONS
2044 
2045   gdk_window_freeze_updates (window);
2046 
2047   switch (display_wayland->shell_variant)
2048     {
2049     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
2050       create_xdg_toplevel_resources (window);
2051       break;
2052     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
2053       create_zxdg_toplevel_v6_resources (window);
2054       break;
2055     }
2056 
2057   gdk_wayland_window_sync_parent (window, NULL);
2058   gdk_wayland_window_sync_parent_of_imported (window);
2059   gdk_wayland_window_sync_title (window);
2060 
2061   switch (display_wayland->shell_variant)
2062     {
2063     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
2064       if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
2065         xdg_toplevel_set_maximized (impl->display_server.xdg_toplevel);
2066       if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
2067         xdg_toplevel_set_fullscreen (impl->display_server.xdg_toplevel,
2068                                      fullscreen_output);
2069       break;
2070     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
2071       if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
2072         zxdg_toplevel_v6_set_maximized (impl->display_server.zxdg_toplevel_v6);
2073       if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
2074         zxdg_toplevel_v6_set_fullscreen (impl->display_server.zxdg_toplevel_v6,
2075                                          fullscreen_output);
2076       break;
2077     }
2078 
2079   app_id = g_get_prgname ();
2080   if (app_id == NULL)
2081     app_id = gdk_get_program_class ();
2082 
2083   gdk_wayland_window_set_application_id (window, app_id);
2084 
2085   maybe_set_gtk_surface_dbus_properties (window);
2086   maybe_set_gtk_surface_modal (window);
2087 
2088   if (impl->hint == GDK_WINDOW_TYPE_HINT_DIALOG)
2089     _gdk_wayland_screen_add_orphan_dialog (window);
2090 
2091   wl_surface_commit (impl->display_server.wl_surface);
2092 }
2093 
2094 static void
gdk_wayland_window_handle_configure_popup(GdkWindow * window,int32_t x,int32_t y,int32_t width,int32_t height)2095 gdk_wayland_window_handle_configure_popup (GdkWindow *window,
2096                                            int32_t    x,
2097                                            int32_t    y,
2098                                            int32_t    width,
2099                                            int32_t    height)
2100 {
2101   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2102   GdkRectangle flipped_rect;
2103   GdkRectangle final_rect;
2104   gboolean flipped_x;
2105   gboolean flipped_y;
2106 
2107   g_return_if_fail (impl->transient_for);
2108 
2109   if (impl->position_method != POSITION_METHOD_MOVE_TO_RECT)
2110     return;
2111 
2112   calculate_moved_to_rect_result (window, x, y, width, height,
2113                                   &flipped_rect,
2114                                   &final_rect,
2115                                   &flipped_x,
2116                                   &flipped_y);
2117 
2118   impl->position_method = POSITION_METHOD_MOVE_TO_RECT;
2119 
2120   g_signal_emit_by_name (window,
2121                          "moved-to-rect",
2122                          &flipped_rect,
2123                          &final_rect,
2124                          flipped_x,
2125                          flipped_y);
2126 }
2127 
2128 static void
xdg_popup_configure(void * data,struct xdg_popup * xdg_popup,int32_t x,int32_t y,int32_t width,int32_t height)2129 xdg_popup_configure (void             *data,
2130                      struct xdg_popup *xdg_popup,
2131                      int32_t           x,
2132                      int32_t           y,
2133                      int32_t           width,
2134                      int32_t           height)
2135 {
2136   GdkWindow *window = GDK_WINDOW (data);
2137 
2138   gdk_wayland_window_handle_configure_popup (window, x, y, width, height);
2139 }
2140 
2141 static void
xdg_popup_done(void * data,struct xdg_popup * xdg_popup)2142 xdg_popup_done (void             *data,
2143                 struct xdg_popup *xdg_popup)
2144 {
2145   GdkWindow *window = GDK_WINDOW (data);
2146 
2147   GDK_NOTE (EVENTS,
2148             g_message ("done %p", window));
2149 
2150   gdk_window_hide (window);
2151 }
2152 
2153 static const struct xdg_popup_listener xdg_popup_listener = {
2154   xdg_popup_configure,
2155   xdg_popup_done,
2156 };
2157 
2158 static void
zxdg_popup_v6_configure(void * data,struct zxdg_popup_v6 * xdg_popup,int32_t x,int32_t y,int32_t width,int32_t height)2159 zxdg_popup_v6_configure (void                 *data,
2160                          struct zxdg_popup_v6 *xdg_popup,
2161                          int32_t               x,
2162                          int32_t               y,
2163                          int32_t               width,
2164                          int32_t               height)
2165 {
2166   GdkWindow *window = GDK_WINDOW (data);
2167 
2168   gdk_wayland_window_handle_configure_popup (window, x, y, width, height);
2169 }
2170 
2171 static void
zxdg_popup_v6_done(void * data,struct zxdg_popup_v6 * xdg_popup)2172 zxdg_popup_v6_done (void                 *data,
2173                     struct zxdg_popup_v6 *xdg_popup)
2174 {
2175   GdkWindow *window = GDK_WINDOW (data);
2176 
2177   GDK_NOTE (EVENTS,
2178             g_message ("done %p", window));
2179 
2180   gdk_window_hide (window);
2181 }
2182 
2183 static const struct zxdg_popup_v6_listener zxdg_popup_v6_listener = {
2184   zxdg_popup_v6_configure,
2185   zxdg_popup_v6_done,
2186 };
2187 
2188 static enum xdg_positioner_anchor
rect_anchor_to_anchor(GdkGravity rect_anchor)2189 rect_anchor_to_anchor (GdkGravity rect_anchor)
2190 {
2191   switch (rect_anchor)
2192     {
2193     case GDK_GRAVITY_NORTH_WEST:
2194     case GDK_GRAVITY_STATIC:
2195       return XDG_POSITIONER_ANCHOR_TOP_LEFT;
2196     case GDK_GRAVITY_NORTH:
2197       return XDG_POSITIONER_ANCHOR_TOP;
2198     case GDK_GRAVITY_NORTH_EAST:
2199       return XDG_POSITIONER_ANCHOR_TOP_RIGHT;
2200     case GDK_GRAVITY_WEST:
2201       return XDG_POSITIONER_ANCHOR_LEFT;
2202     case GDK_GRAVITY_CENTER:
2203       return XDG_POSITIONER_ANCHOR_NONE;
2204     case GDK_GRAVITY_EAST:
2205       return XDG_POSITIONER_ANCHOR_RIGHT;
2206     case GDK_GRAVITY_SOUTH_WEST:
2207       return XDG_POSITIONER_ANCHOR_BOTTOM_LEFT;
2208     case GDK_GRAVITY_SOUTH:
2209       return XDG_POSITIONER_ANCHOR_BOTTOM;
2210     case GDK_GRAVITY_SOUTH_EAST:
2211       return XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT;
2212     default:
2213       g_assert_not_reached ();
2214     }
2215 }
2216 
2217 static enum xdg_positioner_gravity
window_anchor_to_gravity(GdkGravity rect_anchor)2218 window_anchor_to_gravity (GdkGravity rect_anchor)
2219 {
2220   switch (rect_anchor)
2221     {
2222     case GDK_GRAVITY_NORTH_WEST:
2223     case GDK_GRAVITY_STATIC:
2224       return XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT;
2225     case GDK_GRAVITY_NORTH:
2226       return XDG_POSITIONER_GRAVITY_BOTTOM;
2227     case GDK_GRAVITY_NORTH_EAST:
2228       return XDG_POSITIONER_GRAVITY_BOTTOM_LEFT;
2229     case GDK_GRAVITY_WEST:
2230       return XDG_POSITIONER_GRAVITY_RIGHT;
2231     case GDK_GRAVITY_CENTER:
2232       return XDG_POSITIONER_GRAVITY_NONE;
2233     case GDK_GRAVITY_EAST:
2234       return XDG_POSITIONER_GRAVITY_LEFT;
2235     case GDK_GRAVITY_SOUTH_WEST:
2236       return XDG_POSITIONER_GRAVITY_TOP_RIGHT;
2237     case GDK_GRAVITY_SOUTH:
2238       return XDG_POSITIONER_GRAVITY_TOP;
2239     case GDK_GRAVITY_SOUTH_EAST:
2240       return XDG_POSITIONER_GRAVITY_TOP_LEFT;
2241     default:
2242       g_assert_not_reached ();
2243     }
2244 }
2245 
2246 static enum zxdg_positioner_v6_anchor
rect_anchor_to_anchor_legacy(GdkGravity rect_anchor)2247 rect_anchor_to_anchor_legacy (GdkGravity rect_anchor)
2248 {
2249   switch (rect_anchor)
2250     {
2251     case GDK_GRAVITY_NORTH_WEST:
2252     case GDK_GRAVITY_STATIC:
2253       return (ZXDG_POSITIONER_V6_ANCHOR_TOP |
2254               ZXDG_POSITIONER_V6_ANCHOR_LEFT);
2255     case GDK_GRAVITY_NORTH:
2256       return ZXDG_POSITIONER_V6_ANCHOR_TOP;
2257     case GDK_GRAVITY_NORTH_EAST:
2258       return (ZXDG_POSITIONER_V6_ANCHOR_TOP |
2259               ZXDG_POSITIONER_V6_ANCHOR_RIGHT);
2260     case GDK_GRAVITY_WEST:
2261       return ZXDG_POSITIONER_V6_ANCHOR_LEFT;
2262     case GDK_GRAVITY_CENTER:
2263       return ZXDG_POSITIONER_V6_ANCHOR_NONE;
2264     case GDK_GRAVITY_EAST:
2265       return ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
2266     case GDK_GRAVITY_SOUTH_WEST:
2267       return (ZXDG_POSITIONER_V6_ANCHOR_BOTTOM |
2268               ZXDG_POSITIONER_V6_ANCHOR_LEFT);
2269     case GDK_GRAVITY_SOUTH:
2270       return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM;
2271     case GDK_GRAVITY_SOUTH_EAST:
2272       return (ZXDG_POSITIONER_V6_ANCHOR_BOTTOM |
2273               ZXDG_POSITIONER_V6_ANCHOR_RIGHT);
2274     default:
2275       g_assert_not_reached ();
2276     }
2277 }
2278 
2279 static enum zxdg_positioner_v6_gravity
window_anchor_to_gravity_legacy(GdkGravity rect_anchor)2280 window_anchor_to_gravity_legacy (GdkGravity rect_anchor)
2281 {
2282   switch (rect_anchor)
2283     {
2284     case GDK_GRAVITY_NORTH_WEST:
2285     case GDK_GRAVITY_STATIC:
2286       return (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
2287               ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
2288     case GDK_GRAVITY_NORTH:
2289       return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM;
2290     case GDK_GRAVITY_NORTH_EAST:
2291       return (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
2292               ZXDG_POSITIONER_V6_GRAVITY_LEFT);
2293     case GDK_GRAVITY_WEST:
2294       return ZXDG_POSITIONER_V6_GRAVITY_RIGHT;
2295     case GDK_GRAVITY_CENTER:
2296       return ZXDG_POSITIONER_V6_GRAVITY_NONE;
2297     case GDK_GRAVITY_EAST:
2298       return ZXDG_POSITIONER_V6_GRAVITY_LEFT;
2299     case GDK_GRAVITY_SOUTH_WEST:
2300       return (ZXDG_POSITIONER_V6_GRAVITY_TOP |
2301               ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
2302     case GDK_GRAVITY_SOUTH:
2303       return ZXDG_POSITIONER_V6_GRAVITY_TOP;
2304     case GDK_GRAVITY_SOUTH_EAST:
2305       return (ZXDG_POSITIONER_V6_GRAVITY_TOP |
2306               ZXDG_POSITIONER_V6_GRAVITY_LEFT);
2307     default:
2308       g_assert_not_reached ();
2309     }
2310 }
2311 
2312 static void
kwin_server_decoration_mode_set(void * data,struct org_kde_kwin_server_decoration * org_kde_kwin_server_decoration,uint32_t mode)2313 kwin_server_decoration_mode_set (void *data, struct org_kde_kwin_server_decoration *org_kde_kwin_server_decoration, uint32_t mode)
2314 {
2315   GdkWindow *window = GDK_WINDOW (data);
2316   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2317 
2318   if ((mode == ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER && impl->using_csd) ||
2319         (mode == ORG_KDE_KWIN_SERVER_DECORATION_MODE_CLIENT && !impl->using_csd))
2320     gdk_wayland_window_announce_decoration_mode (window);
2321 }
2322 
2323 static const struct org_kde_kwin_server_decoration_listener kwin_server_decoration_listener = {
2324   kwin_server_decoration_mode_set
2325 };
2326 
2327 static void
gdk_wayland_window_announce_decoration_mode(GdkWindow * window)2328 gdk_wayland_window_announce_decoration_mode (GdkWindow *window)
2329 {
2330   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
2331   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2332 
2333   if (!display_wayland->server_decoration_manager)
2334     return;
2335   if (!impl->display_server.server_decoration)
2336     {
2337       impl->display_server.server_decoration =
2338         org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
2339                                                                                          impl->display_server.wl_surface);
2340       org_kde_kwin_server_decoration_add_listener (impl->display_server.server_decoration,
2341                                                                                 &kwin_server_decoration_listener,
2342                                                                                 window);
2343   }
2344 
2345   if (impl->display_server.server_decoration)
2346     {
2347       if (impl->using_csd)
2348         org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration,
2349                                                                                      ORG_KDE_KWIN_SERVER_DECORATION_MODE_CLIENT);
2350       else
2351         org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration,
2352                                                                                      ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER);
2353     }
2354 }
2355 
2356 void
gdk_wayland_window_announce_csd(GdkWindow * window)2357 gdk_wayland_window_announce_csd (GdkWindow *window)
2358 {
2359   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2360 
2361   impl->using_csd = TRUE;
2362   if (impl->mapped)
2363     gdk_wayland_window_announce_decoration_mode (window);
2364 }
2365 
2366 void
gdk_wayland_window_announce_ssd(GdkWindow * window)2367 gdk_wayland_window_announce_ssd (GdkWindow *window)
2368 {
2369   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2370 
2371   impl->using_csd = FALSE;
2372   if (impl->mapped)
2373     gdk_wayland_window_announce_decoration_mode (window);
2374 }
2375 
2376 static GdkWindow *
get_real_parent_and_translate(GdkWindow * window,gint * x,gint * y)2377 get_real_parent_and_translate (GdkWindow *window,
2378                                gint      *x,
2379                                gint      *y)
2380 {
2381   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2382   GdkWindow *parent = impl->transient_for;
2383 
2384   while (parent)
2385     {
2386       GdkWindowImplWayland *parent_impl =
2387         GDK_WINDOW_IMPL_WAYLAND (parent->impl);
2388       GdkWindow *effective_parent = gdk_window_get_effective_parent (parent);
2389 
2390       if (parent == NULL || (gdk_window_has_native (parent) &&
2391            !parent_impl->display_server.wl_subsurface) ||
2392           !effective_parent)
2393         break;
2394 
2395       *x += parent->x;
2396       *y += parent->y;
2397 
2398       if (gdk_window_has_native (parent) &&
2399           parent_impl->display_server.wl_subsurface)
2400         parent = parent->transient_for;
2401       else
2402         parent = effective_parent;
2403     }
2404 
2405   return parent;
2406 }
2407 
2408 static void
translate_to_real_parent_window_geometry(GdkWindow * window,gint * x,gint * y)2409 translate_to_real_parent_window_geometry (GdkWindow  *window,
2410                                           gint       *x,
2411                                           gint       *y)
2412 {
2413   GdkWindow *parent;
2414 
2415   parent = get_real_parent_and_translate (window, x, y);
2416 
2417   if (parent != NULL) {
2418     *x -= parent->shadow_left;
2419     *y -= parent->shadow_top;
2420   }
2421 }
2422 
2423 static GdkWindow *
translate_from_real_parent_window_geometry(GdkWindow * window,gint * x,gint * y)2424 translate_from_real_parent_window_geometry (GdkWindow *window,
2425                                             gint      *x,
2426                                             gint      *y)
2427 {
2428   GdkWindow *parent;
2429   gint dx = 0;
2430   gint dy = 0;
2431 
2432   parent = get_real_parent_and_translate (window, &dx, &dy);
2433 
2434   *x -= dx;
2435   *y -= dy;
2436 
2437   if (parent != NULL) {
2438     *x += parent->shadow_left;
2439     *y += parent->shadow_top;
2440   }
2441 
2442   return parent;
2443 }
2444 
2445 static void
calculate_popup_rect(GdkWindow * window,GdkGravity rect_anchor,GdkGravity window_anchor,GdkRectangle * out_rect)2446 calculate_popup_rect (GdkWindow    *window,
2447                       GdkGravity    rect_anchor,
2448                       GdkGravity    window_anchor,
2449                       GdkRectangle *out_rect)
2450 {
2451   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2452   GdkRectangle geometry;
2453   GdkRectangle anchor_rect;
2454   int x = 0, y = 0;
2455 
2456   gdk_wayland_window_get_window_geometry (window, &geometry);
2457 
2458   anchor_rect = (GdkRectangle) {
2459     .x = (impl->pending_move_to_rect.rect.x +
2460           impl->pending_move_to_rect.rect_anchor_dx),
2461     .y = (impl->pending_move_to_rect.rect.y +
2462           impl->pending_move_to_rect.rect_anchor_dy),
2463     .width = impl->pending_move_to_rect.rect.width,
2464     .height = impl->pending_move_to_rect.rect.height
2465   };
2466 
2467   switch (rect_anchor)
2468     {
2469     case GDK_GRAVITY_STATIC:
2470     case GDK_GRAVITY_NORTH_WEST:
2471       x = anchor_rect.x;
2472       y = anchor_rect.y;
2473       break;
2474     case GDK_GRAVITY_NORTH:
2475       x = anchor_rect.x + (anchor_rect.width / 2);
2476       y = anchor_rect.y;
2477       break;
2478     case GDK_GRAVITY_NORTH_EAST:
2479       x = anchor_rect.x + anchor_rect.width;
2480       y = anchor_rect.y;
2481       break;
2482     case GDK_GRAVITY_WEST:
2483       x = anchor_rect.x;
2484       y = anchor_rect.y + (anchor_rect.height / 2);
2485       break;
2486     case GDK_GRAVITY_CENTER:
2487       x = anchor_rect.x + (anchor_rect.width / 2);
2488       y = anchor_rect.y + (anchor_rect.height / 2);
2489       break;
2490     case GDK_GRAVITY_EAST:
2491       x = anchor_rect.x + anchor_rect.width;
2492       y = anchor_rect.y + (anchor_rect.height / 2);
2493       break;
2494     case GDK_GRAVITY_SOUTH_WEST:
2495       x = anchor_rect.x;
2496       y = anchor_rect.y + anchor_rect.height;
2497       break;
2498     case GDK_GRAVITY_SOUTH:
2499       x = anchor_rect.x + (anchor_rect.width / 2);
2500       y = anchor_rect.y + anchor_rect.height;
2501       break;
2502     case GDK_GRAVITY_SOUTH_EAST:
2503       x = anchor_rect.x + anchor_rect.width;
2504       y = anchor_rect.y + anchor_rect.height;
2505       break;
2506     }
2507 
2508   switch (window_anchor)
2509     {
2510     case GDK_GRAVITY_STATIC:
2511     case GDK_GRAVITY_NORTH_WEST:
2512       break;
2513     case GDK_GRAVITY_NORTH:
2514       x -= geometry.width / 2;
2515       break;
2516     case GDK_GRAVITY_NORTH_EAST:
2517       x -= geometry.width;
2518       break;
2519     case GDK_GRAVITY_WEST:
2520       y -= geometry.height / 2;
2521       break;
2522     case GDK_GRAVITY_CENTER:
2523       x -= geometry.width / 2;
2524       y -= geometry.height / 2;
2525       break;
2526     case GDK_GRAVITY_EAST:
2527       x -= geometry.width;
2528       y -= geometry.height / 2;
2529       break;
2530     case GDK_GRAVITY_SOUTH_WEST:
2531       y -= geometry.height;
2532       break;
2533     case GDK_GRAVITY_SOUTH:
2534       x -= geometry.width / 2;
2535       y -= geometry.height;
2536       break;
2537     case GDK_GRAVITY_SOUTH_EAST:
2538       x -= geometry.width;
2539       y -= geometry.height;
2540       break;
2541     }
2542 
2543   *out_rect = (GdkRectangle) {
2544     .x = x,
2545     .y = y,
2546     .width = geometry.width,
2547     .height = geometry.height
2548   };
2549 }
2550 
2551 static GdkGravity
flip_anchor_horizontally(GdkGravity anchor)2552 flip_anchor_horizontally (GdkGravity anchor)
2553 {
2554   switch (anchor)
2555     {
2556     case GDK_GRAVITY_STATIC:
2557     case GDK_GRAVITY_NORTH_WEST:
2558       return GDK_GRAVITY_NORTH_EAST;
2559     case GDK_GRAVITY_NORTH:
2560       return GDK_GRAVITY_NORTH;
2561     case GDK_GRAVITY_NORTH_EAST:
2562       return GDK_GRAVITY_NORTH_WEST;
2563     case GDK_GRAVITY_WEST:
2564       return GDK_GRAVITY_EAST;
2565     case GDK_GRAVITY_CENTER:
2566       return GDK_GRAVITY_CENTER;
2567     case GDK_GRAVITY_EAST:
2568       return GDK_GRAVITY_WEST;
2569     case GDK_GRAVITY_SOUTH_WEST:
2570       return GDK_GRAVITY_SOUTH_EAST;
2571     case GDK_GRAVITY_SOUTH:
2572       return GDK_GRAVITY_SOUTH;
2573     case GDK_GRAVITY_SOUTH_EAST:
2574       return GDK_GRAVITY_SOUTH_WEST;
2575     }
2576 
2577   g_assert_not_reached ();
2578 }
2579 
2580 static GdkGravity
flip_anchor_vertically(GdkGravity anchor)2581 flip_anchor_vertically (GdkGravity anchor)
2582 {
2583   switch (anchor)
2584     {
2585     case GDK_GRAVITY_STATIC:
2586     case GDK_GRAVITY_NORTH_WEST:
2587       return GDK_GRAVITY_SOUTH_WEST;
2588     case GDK_GRAVITY_NORTH:
2589       return GDK_GRAVITY_SOUTH;
2590     case GDK_GRAVITY_NORTH_EAST:
2591       return GDK_GRAVITY_SOUTH_EAST;
2592     case GDK_GRAVITY_WEST:
2593       return GDK_GRAVITY_WEST;
2594     case GDK_GRAVITY_CENTER:
2595       return GDK_GRAVITY_CENTER;
2596     case GDK_GRAVITY_EAST:
2597       return GDK_GRAVITY_EAST;
2598     case GDK_GRAVITY_SOUTH_WEST:
2599       return GDK_GRAVITY_NORTH_WEST;
2600     case GDK_GRAVITY_SOUTH:
2601       return GDK_GRAVITY_NORTH;
2602     case GDK_GRAVITY_SOUTH_EAST:
2603       return GDK_GRAVITY_NORTH_EAST;
2604     }
2605 
2606   g_assert_not_reached ();
2607 }
2608 
2609 static void
calculate_moved_to_rect_result(GdkWindow * window,int x,int y,int width,int height,GdkRectangle * flipped_rect,GdkRectangle * final_rect,gboolean * flipped_x,gboolean * flipped_y)2610 calculate_moved_to_rect_result (GdkWindow    *window,
2611                                 int           x,
2612                                 int           y,
2613                                 int           width,
2614                                 int           height,
2615                                 GdkRectangle *flipped_rect,
2616                                 GdkRectangle *final_rect,
2617                                 gboolean     *flipped_x,
2618                                 gboolean     *flipped_y)
2619 {
2620   GdkWindowImplWayland *impl;
2621   GdkWindow *parent;
2622   gint window_x, window_y;
2623   gint window_width, window_height;
2624   GdkRectangle best_rect;
2625 
2626   g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
2627   g_return_if_fail (GDK_IS_WINDOW_IMPL_WAYLAND (window->impl));
2628 
2629   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2630 
2631   parent = translate_from_real_parent_window_geometry (window, &x, &y);
2632   *final_rect = (GdkRectangle) {
2633     .x = x,
2634     .y = y,
2635     .width = width,
2636     .height = height,
2637   };
2638 
2639   window_x = parent->x + x;
2640   window_y = parent->y + y;
2641   window_width = width + window->shadow_left + window->shadow_right;
2642   window_height = height + window->shadow_top + window->shadow_bottom;
2643 
2644   impl->configuring_popup = TRUE;
2645   gdk_window_move_resize (window,
2646                           window_x, window_y,
2647                           window_width, window_height);
2648   impl->configuring_popup = FALSE;
2649 
2650   calculate_popup_rect (window,
2651                         impl->pending_move_to_rect.rect_anchor,
2652                         impl->pending_move_to_rect.window_anchor,
2653                         &best_rect);
2654 
2655   *flipped_rect = best_rect;
2656 
2657   if (x != best_rect.x &&
2658       impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_X)
2659     {
2660       GdkRectangle flipped_x_rect;
2661       GdkGravity flipped_rect_anchor;
2662       GdkGravity flipped_window_anchor;
2663 
2664       flipped_rect_anchor =
2665         flip_anchor_horizontally (impl->pending_move_to_rect.rect_anchor);
2666       flipped_window_anchor =
2667         flip_anchor_horizontally (impl->pending_move_to_rect.window_anchor),
2668       calculate_popup_rect (window,
2669                             flipped_rect_anchor,
2670                             flipped_window_anchor,
2671                             &flipped_x_rect);
2672 
2673       if (flipped_x_rect.x == x)
2674         flipped_rect->x = x;
2675     }
2676   if (y != best_rect.y &&
2677       impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_Y)
2678     {
2679       GdkRectangle flipped_y_rect;
2680       GdkGravity flipped_rect_anchor;
2681       GdkGravity flipped_window_anchor;
2682 
2683       flipped_rect_anchor =
2684         flip_anchor_vertically (impl->pending_move_to_rect.rect_anchor);
2685       flipped_window_anchor =
2686         flip_anchor_vertically (impl->pending_move_to_rect.window_anchor),
2687       calculate_popup_rect (window,
2688                             flipped_rect_anchor,
2689                             flipped_window_anchor,
2690                             &flipped_y_rect);
2691 
2692       if (flipped_y_rect.y == y)
2693         flipped_rect->y = y;
2694     }
2695 
2696   *flipped_x = flipped_rect->x != best_rect.x;
2697   *flipped_y = flipped_rect->y != best_rect.y;
2698 }
2699 
2700 static gpointer
create_dynamic_positioner(GdkWindow * window)2701 create_dynamic_positioner (GdkWindow *window)
2702 {
2703   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2704   GdkWaylandDisplay *display =
2705     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
2706   GdkRectangle geometry;
2707   uint32_t constraint_adjustment = ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE;
2708   gint real_anchor_rect_x, real_anchor_rect_y;
2709   gint anchor_rect_width, anchor_rect_height;
2710 
2711   gdk_wayland_window_get_window_geometry (window, &geometry);
2712 
2713   real_anchor_rect_x = impl->pending_move_to_rect.rect.x;
2714   real_anchor_rect_y = impl->pending_move_to_rect.rect.y;
2715   translate_to_real_parent_window_geometry (window,
2716                                             &real_anchor_rect_x,
2717                                             &real_anchor_rect_y);
2718 
2719   anchor_rect_width = impl->pending_move_to_rect.rect.width;
2720   anchor_rect_height = impl->pending_move_to_rect.rect.height;
2721 
2722   switch (display->shell_variant)
2723     {
2724     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
2725       {
2726         struct xdg_positioner *positioner;
2727         enum xdg_positioner_anchor anchor;
2728         enum xdg_positioner_gravity gravity;
2729 
2730         positioner = xdg_wm_base_create_positioner (display->xdg_wm_base);
2731 
2732         xdg_positioner_set_size (positioner, geometry.width, geometry.height);
2733         xdg_positioner_set_anchor_rect (positioner,
2734                                         real_anchor_rect_x,
2735                                         real_anchor_rect_y,
2736                                         anchor_rect_width,
2737                                         anchor_rect_height);
2738         xdg_positioner_set_offset (positioner,
2739                                    impl->pending_move_to_rect.rect_anchor_dx,
2740                                    impl->pending_move_to_rect.rect_anchor_dy);
2741 
2742         anchor = rect_anchor_to_anchor (impl->pending_move_to_rect.rect_anchor);
2743         xdg_positioner_set_anchor (positioner, anchor);
2744 
2745         gravity = window_anchor_to_gravity (impl->pending_move_to_rect.window_anchor);
2746         xdg_positioner_set_gravity (positioner, gravity);
2747 
2748         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_X)
2749           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X;
2750         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_Y)
2751           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y;
2752         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_SLIDE_X)
2753           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X;
2754         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_SLIDE_Y)
2755           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y;
2756         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_RESIZE_X)
2757           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X;
2758         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_RESIZE_Y)
2759           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y;
2760         xdg_positioner_set_constraint_adjustment (positioner,
2761                                                   constraint_adjustment);
2762 
2763         return positioner;
2764       }
2765     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
2766       {
2767         struct zxdg_positioner_v6 *positioner;
2768         enum zxdg_positioner_v6_anchor anchor;
2769         enum zxdg_positioner_v6_gravity gravity;
2770 
2771         positioner = zxdg_shell_v6_create_positioner (display->zxdg_shell_v6);
2772 
2773         zxdg_positioner_v6_set_size (positioner, geometry.width, geometry.height);
2774         zxdg_positioner_v6_set_anchor_rect (positioner,
2775                                             real_anchor_rect_x,
2776                                             real_anchor_rect_y,
2777                                             anchor_rect_width,
2778                                             anchor_rect_height);
2779         zxdg_positioner_v6_set_offset (positioner,
2780                                        impl->pending_move_to_rect.rect_anchor_dx,
2781                                        impl->pending_move_to_rect.rect_anchor_dy);
2782 
2783         anchor = rect_anchor_to_anchor_legacy (impl->pending_move_to_rect.rect_anchor);
2784         zxdg_positioner_v6_set_anchor (positioner, anchor);
2785 
2786         gravity = window_anchor_to_gravity_legacy (impl->pending_move_to_rect.window_anchor);
2787         zxdg_positioner_v6_set_gravity (positioner, gravity);
2788 
2789         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_X)
2790           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X;
2791         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_Y)
2792           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y;
2793         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_SLIDE_X)
2794           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X;
2795         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_SLIDE_Y)
2796           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y;
2797         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_RESIZE_X)
2798           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X;
2799         if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_RESIZE_Y)
2800           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y;
2801         zxdg_positioner_v6_set_constraint_adjustment (positioner,
2802                                                       constraint_adjustment);
2803 
2804         return positioner;
2805       }
2806     }
2807 
2808   g_assert_not_reached ();
2809 }
2810 
2811 static gpointer
create_simple_positioner(GdkWindow * window,GdkWindow * parent)2812 create_simple_positioner (GdkWindow *window,
2813                           GdkWindow *parent)
2814 {
2815   GdkWaylandDisplay *display =
2816     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
2817   GdkRectangle geometry;
2818   GdkRectangle parent_geometry;
2819   int parent_x, parent_y;
2820 
2821   gdk_wayland_window_get_window_geometry (window, &geometry);
2822 
2823   parent_x = parent->x;
2824   parent_y = parent->y;
2825 
2826   gdk_wayland_window_get_window_geometry (parent, &parent_geometry);
2827   parent_x += parent_geometry.x;
2828   parent_y += parent_geometry.y;
2829 
2830   switch (display->shell_variant)
2831     {
2832     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
2833       {
2834         struct xdg_positioner *positioner;
2835 
2836         positioner = xdg_wm_base_create_positioner (display->xdg_wm_base);
2837         xdg_positioner_set_size (positioner, geometry.width, geometry.height);
2838         xdg_positioner_set_anchor_rect (positioner,
2839                                         (window->x + geometry.x) - parent_x,
2840                                         (window->y + geometry.y) - parent_y,
2841                                         1, 1);
2842         xdg_positioner_set_anchor (positioner,
2843                                    XDG_POSITIONER_ANCHOR_TOP_LEFT);
2844         xdg_positioner_set_gravity (positioner,
2845                                     XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
2846 
2847         return positioner;
2848       }
2849     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
2850       {
2851         struct zxdg_positioner_v6 *positioner;
2852 
2853         positioner = zxdg_shell_v6_create_positioner (display->zxdg_shell_v6);
2854         zxdg_positioner_v6_set_size (positioner, geometry.width, geometry.height);
2855         zxdg_positioner_v6_set_anchor_rect (positioner,
2856                                             (window->x + geometry.x) - parent_x,
2857                                             (window->y + geometry.y) - parent_y,
2858                                             1, 1);
2859         zxdg_positioner_v6_set_anchor (positioner,
2860                                        (ZXDG_POSITIONER_V6_ANCHOR_TOP |
2861                                         ZXDG_POSITIONER_V6_ANCHOR_LEFT));
2862         zxdg_positioner_v6_set_gravity (positioner,
2863                                         (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
2864                                          ZXDG_POSITIONER_V6_GRAVITY_RIGHT));
2865 
2866         return positioner;
2867       }
2868     }
2869 
2870   g_assert_not_reached ();
2871 }
2872 
2873 static void
gdk_wayland_window_create_xdg_popup(GdkWindow * window,GdkWindow * parent,struct wl_seat * seat)2874 gdk_wayland_window_create_xdg_popup (GdkWindow      *window,
2875                                      GdkWindow      *parent,
2876                                      struct wl_seat *seat)
2877 {
2878   GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
2879   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2880   GdkWindowImplWayland *parent_impl = GDK_WINDOW_IMPL_WAYLAND (parent->impl);
2881   gpointer positioner;
2882   GdkSeat *gdk_seat;
2883   guint32 serial;
2884 
2885   if (!impl->display_server.wl_surface)
2886     return;
2887 
2888   if (!is_realized_shell_surface (parent))
2889     return;
2890 
2891   if (is_realized_toplevel (window))
2892     {
2893       g_warning ("Can't map popup, already mapped as toplevel");
2894       return;
2895     }
2896   if (is_realized_popup (window))
2897     {
2898       g_warning ("Can't map popup, already mapped");
2899       return;
2900     }
2901   if ((display->current_popups &&
2902        g_list_last (display->current_popups)->data != parent) ||
2903       (!display->current_popups &&
2904        !is_realized_toplevel (parent)))
2905     {
2906       g_warning ("Tried to map a popup with a non-top most parent");
2907       return;
2908     }
2909 
2910   gdk_window_freeze_updates (window);
2911 
2912   if (impl->position_method == POSITION_METHOD_MOVE_TO_RECT)
2913     positioner = create_dynamic_positioner (window);
2914   else
2915     positioner = create_simple_positioner (window, parent);
2916 
2917   switch (display->shell_variant)
2918     {
2919     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
2920       impl->display_server.xdg_surface =
2921         xdg_wm_base_get_xdg_surface (display->xdg_wm_base,
2922                                      impl->display_server.wl_surface);
2923       xdg_surface_add_listener (impl->display_server.xdg_surface,
2924                                 &xdg_surface_listener,
2925                                 window);
2926       impl->display_server.xdg_popup =
2927         xdg_surface_get_popup (impl->display_server.xdg_surface,
2928                                parent_impl->display_server.xdg_surface,
2929                                positioner);
2930       xdg_popup_add_listener (impl->display_server.xdg_popup,
2931                               &xdg_popup_listener,
2932                               window);
2933       xdg_positioner_destroy (positioner);
2934       break;
2935     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
2936       impl->display_server.zxdg_surface_v6 =
2937         zxdg_shell_v6_get_xdg_surface (display->zxdg_shell_v6,
2938                                        impl->display_server.wl_surface);
2939       zxdg_surface_v6_add_listener (impl->display_server.zxdg_surface_v6,
2940                                     &zxdg_surface_v6_listener,
2941                                     window);
2942       impl->display_server.zxdg_popup_v6 =
2943         zxdg_surface_v6_get_popup (impl->display_server.zxdg_surface_v6,
2944                                    parent_impl->display_server.zxdg_surface_v6,
2945                                    positioner);
2946       zxdg_popup_v6_add_listener (impl->display_server.zxdg_popup_v6,
2947                                   &zxdg_popup_v6_listener,
2948                                   window);
2949       zxdg_positioner_v6_destroy (positioner);
2950       break;
2951     }
2952 
2953   if (seat)
2954     {
2955       gdk_seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
2956       serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_seat, NULL);
2957 
2958       switch (display->shell_variant)
2959         {
2960         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
2961           xdg_popup_grab (impl->display_server.xdg_popup, seat, serial);
2962           break;
2963         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
2964           zxdg_popup_v6_grab (impl->display_server.zxdg_popup_v6, seat, serial);
2965           break;
2966         }
2967     }
2968 
2969   wl_surface_commit (impl->display_server.wl_surface);
2970 
2971   impl->popup_parent = parent;
2972   display->current_popups = g_list_append (display->current_popups, window);
2973 }
2974 
2975 static struct wl_seat *
find_grab_input_seat(GdkWindow * window,GdkWindow * transient_for)2976 find_grab_input_seat (GdkWindow *window, GdkWindow *transient_for)
2977 {
2978   GdkWindow *attached_grab_window;
2979   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2980   GdkWindowImplWayland *tmp_impl;
2981 
2982   /* Use the device that was used for the grab as the device for
2983    * the popup window setup - so this relies on GTK+ taking the
2984    * grab before showing the popup window.
2985    */
2986   if (impl->grab_input_seat)
2987     return gdk_wayland_seat_get_wl_seat (impl->grab_input_seat);
2988 
2989   /* HACK: GtkMenu grabs a special window known as the "grab transfer window"
2990    * and then transfers the grab over to the correct window later. Look for
2991    * this window when taking the grab to know it's correct.
2992    *
2993    * See: associate_menu_grab_transfer_window in gtkmenu.c
2994    */
2995   attached_grab_window = g_object_get_data (G_OBJECT (window), "gdk-attached-grab-window");
2996   if (attached_grab_window)
2997     {
2998       tmp_impl = GDK_WINDOW_IMPL_WAYLAND (attached_grab_window->impl);
2999       if (tmp_impl->grab_input_seat)
3000         return gdk_wayland_seat_get_wl_seat (tmp_impl->grab_input_seat);
3001     }
3002 
3003   while (transient_for)
3004     {
3005       tmp_impl = GDK_WINDOW_IMPL_WAYLAND (transient_for->impl);
3006 
3007       if (tmp_impl->grab_input_seat)
3008         return gdk_wayland_seat_get_wl_seat (tmp_impl->grab_input_seat);
3009 
3010       transient_for = tmp_impl->transient_for;
3011     }
3012 
3013   return NULL;
3014 }
3015 
3016 static gboolean
should_be_mapped(GdkWindow * window)3017 should_be_mapped (GdkWindow *window)
3018 {
3019   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3020 
3021   /* Don't map crazy temp that GTK+ uses for internal X11 shenanigans. */
3022   if (window->window_type == GDK_WINDOW_TEMP && window->x < 0 && window->y < 0)
3023     return FALSE;
3024 
3025   if (impl->hint == GDK_WINDOW_TYPE_HINT_DND)
3026     return FALSE;
3027 
3028   return TRUE;
3029 }
3030 
3031 static gboolean
should_map_as_popup(GdkWindow * window)3032 should_map_as_popup (GdkWindow *window)
3033 {
3034   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3035 
3036   /* Ideally, popup would be temp windows with a parent and grab */
3037   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
3038     {
3039       /* If a temp window has a parent and a grab, we can use a popup */
3040       if (impl->transient_for)
3041         {
3042           if (impl->grab_input_seat)
3043             return TRUE;
3044         }
3045     }
3046 
3047   /* Yet we need to keep the window type hint tests for compatibility */
3048   switch (impl->hint)
3049     {
3050     case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
3051     case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
3052     case GDK_WINDOW_TYPE_HINT_COMBO:
3053       return TRUE;
3054 
3055     default:
3056       break;
3057     }
3058 
3059   if (impl->position_method == POSITION_METHOD_MOVE_TO_RECT)
3060     return TRUE;
3061 
3062   return FALSE;
3063 }
3064 
3065 static gboolean
should_map_as_subsurface(GdkWindow * window)3066 should_map_as_subsurface (GdkWindow *window)
3067 {
3068   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3069 
3070   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_SUBSURFACE)
3071     return TRUE;
3072 
3073   if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_TEMP)
3074     return FALSE;
3075 
3076   /* if we want a popup, we do not want a subsurface */
3077   if (should_map_as_popup (window))
3078     return FALSE;
3079 
3080   if (impl->transient_for)
3081     {
3082       GdkWindowImplWayland *impl_parent;
3083 
3084       impl_parent = GDK_WINDOW_IMPL_WAYLAND (impl->transient_for->impl);
3085       /* subsurface require that the parent is mapped */
3086       if (impl_parent->mapped)
3087         return TRUE;
3088       else
3089         g_warning ("Couldn't map window %p as subsurface because its parent is not mapped.",
3090                    window);
3091 
3092     }
3093 
3094   return FALSE;
3095 }
3096 
3097 /* Get the window that can be used as a parent for a popup, i.e. a xdg_toplevel
3098  * or xdg_popup. If the window is not, traverse up the transiency parents until
3099  * we find one.
3100  */
3101 static GdkWindow *
get_popup_parent(GdkWindow * window)3102 get_popup_parent (GdkWindow *window)
3103 {
3104   while (window)
3105     {
3106       GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3107 
3108       if (is_realized_popup (window) || is_realized_toplevel (window))
3109         return window;
3110 
3111       window = impl->transient_for;
3112     }
3113 
3114   return NULL;
3115 }
3116 
3117 static void
gdk_wayland_window_map(GdkWindow * window)3118 gdk_wayland_window_map (GdkWindow *window)
3119 {
3120   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3121   GdkWindow *transient_for = NULL;
3122 
3123   if (!should_be_mapped (window))
3124     return;
3125 
3126   if (impl->mapped || impl->use_custom_surface)
3127     return;
3128 
3129   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
3130     {
3131       if (!impl->transient_for)
3132         {
3133           g_message ("Window %p is a temporary window without parent, "
3134                      "application will not be able to position it on screen.",
3135                      window);
3136         }
3137     }
3138 
3139   if (should_map_as_subsurface (window))
3140     {
3141       if (impl->transient_for)
3142         gdk_wayland_window_create_subsurface (window);
3143       else
3144         g_warning ("Couldn't map window %p as susburface yet because it doesn't have a parent",
3145                    window);
3146     }
3147   else if (should_map_as_popup (window))
3148     {
3149       gboolean create_fallback = FALSE;
3150       struct wl_seat *grab_input_seat;
3151 
3152       /* Popup menus can appear without a transient parent, which means they
3153        * cannot be positioned properly on Wayland. This attempts to guess the
3154        * surface they should be positioned with by finding the surface beneath
3155        * the device that created the grab for the popup window.
3156        */
3157       if (!impl->transient_for && impl->hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU)
3158         {
3159           GdkDevice *grab_device = NULL;
3160 
3161           /* The popup menu window is not the grabbed window. This may mean
3162            * that a "transfer window" (see gtkmenu.c) is used, and we need
3163            * to find that window to get the grab device. If so is the case
3164            * the "transfer window" can be retrieved via the
3165            * "gdk-attached-grab-window" associated data field.
3166            */
3167           if (!impl->grab_input_seat)
3168             {
3169               GdkWindow *attached_grab_window =
3170                 g_object_get_data (G_OBJECT (window),
3171                                    "gdk-attached-grab-window");
3172               if (attached_grab_window)
3173                 {
3174                   GdkWindowImplWayland *attached_impl =
3175                     GDK_WINDOW_IMPL_WAYLAND (attached_grab_window->impl);
3176                   grab_device = gdk_seat_get_pointer (attached_impl->grab_input_seat);
3177                   transient_for =
3178                     gdk_device_get_window_at_position (grab_device,
3179                                                        NULL, NULL);
3180                 }
3181             }
3182           else
3183             {
3184               grab_device = gdk_seat_get_pointer (impl->grab_input_seat);
3185               transient_for =
3186                 gdk_device_get_window_at_position (grab_device, NULL, NULL);
3187             }
3188 
3189           if (transient_for)
3190             transient_for = get_popup_parent (gdk_window_get_effective_toplevel (transient_for));
3191 
3192           /* If the position was not explicitly set, start the popup at the
3193            * position of the device that holds the grab.
3194            */
3195           if (impl->position_method == POSITION_METHOD_NONE && grab_device)
3196             gdk_window_get_device_position (transient_for, grab_device,
3197                                             &window->x, &window->y, NULL);
3198         }
3199       else
3200         {
3201           transient_for = gdk_window_get_effective_toplevel (impl->transient_for);
3202           transient_for = get_popup_parent (transient_for);
3203         }
3204 
3205       if (!transient_for)
3206         {
3207           g_warning ("Couldn't map as window %p as popup because it doesn't have a parent",
3208                      window);
3209 
3210           create_fallback = TRUE;
3211         }
3212       else
3213         {
3214           grab_input_seat = find_grab_input_seat (window, transient_for);
3215         }
3216 
3217       if (!create_fallback)
3218         {
3219           gdk_wayland_window_create_xdg_popup (window,
3220                                                transient_for,
3221                                                grab_input_seat);
3222         }
3223       else
3224         {
3225           gdk_wayland_window_create_xdg_toplevel (window);
3226           gdk_wayland_window_announce_decoration_mode (window);
3227         }
3228     }
3229   else
3230     {
3231       gdk_wayland_window_create_xdg_toplevel (window);
3232       gdk_wayland_window_announce_decoration_mode (window);
3233     }
3234 
3235   impl->mapped = TRUE;
3236 }
3237 
3238 static void
gdk_wayland_window_show(GdkWindow * window,gboolean already_mapped)3239 gdk_wayland_window_show (GdkWindow *window,
3240                          gboolean   already_mapped)
3241 {
3242   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3243 
3244   if (!impl->display_server.wl_surface)
3245     gdk_wayland_window_create_surface (window);
3246 
3247   gdk_wayland_window_map (window);
3248 
3249   _gdk_make_event (window, GDK_MAP, NULL, FALSE);
3250 
3251   if (impl->staging_cairo_surface &&
3252       _gdk_wayland_is_shm_surface (impl->staging_cairo_surface))
3253     gdk_wayland_window_attach_image (window);
3254 }
3255 
3256 static void
unmap_subsurface(GdkWindow * window)3257 unmap_subsurface (GdkWindow *window)
3258 {
3259   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3260   GdkWindowImplWayland *parent_impl;
3261 
3262   g_return_if_fail (impl->display_server.wl_subsurface);
3263   g_return_if_fail (impl->transient_for);
3264 
3265   parent_impl = GDK_WINDOW_IMPL_WAYLAND (impl->transient_for->impl);
3266   wl_subsurface_destroy (impl->display_server.wl_subsurface);
3267   if (impl->parent_surface_committed_handler)
3268     {
3269       g_signal_handler_disconnect (parent_impl,
3270                                    impl->parent_surface_committed_handler);
3271       impl->parent_surface_committed_handler = 0;
3272     }
3273   impl->display_server.wl_subsurface = NULL;
3274 }
3275 
3276 static void
unmap_popups_for_window(GdkWindow * window)3277 unmap_popups_for_window (GdkWindow *window)
3278 {
3279   GdkWaylandDisplay *display_wayland;
3280   GList *l;
3281 
3282   display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
3283   for (l = display_wayland->current_popups; l; l = l->next)
3284     {
3285        GdkWindow *popup = l->data;
3286        GdkWindowImplWayland *popup_impl = GDK_WINDOW_IMPL_WAYLAND (popup->impl);
3287 
3288        if (popup_impl->popup_parent == window)
3289          {
3290            g_warning ("Tried to unmap the parent of a popup");
3291            gdk_window_hide (popup);
3292 
3293            return;
3294          }
3295     }
3296 }
3297 
3298 static void
gdk_wayland_window_hide_surface(GdkWindow * window)3299 gdk_wayland_window_hide_surface (GdkWindow *window)
3300 {
3301   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
3302   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3303 
3304   unmap_popups_for_window (window);
3305 
3306   if (impl->display_server.wl_surface)
3307     {
3308       if (impl->dummy_egl_surface)
3309         {
3310           eglDestroySurface (display_wayland->egl_display, impl->dummy_egl_surface);
3311           impl->dummy_egl_surface = NULL;
3312         }
3313 
3314       if (impl->display_server.dummy_egl_window)
3315         {
3316           wl_egl_window_destroy (impl->display_server.dummy_egl_window);
3317           impl->display_server.dummy_egl_window = NULL;
3318         }
3319 
3320       if (impl->egl_surface)
3321         {
3322           eglDestroySurface (display_wayland->egl_display, impl->egl_surface);
3323           impl->egl_surface = NULL;
3324         }
3325 
3326       if (impl->display_server.egl_window)
3327         {
3328           wl_egl_window_destroy (impl->display_server.egl_window);
3329           impl->display_server.egl_window = NULL;
3330         }
3331 
3332       if (impl->display_server.xdg_toplevel)
3333         {
3334           xdg_toplevel_destroy (impl->display_server.xdg_toplevel);
3335           impl->display_server.xdg_toplevel = NULL;
3336         }
3337       else if (impl->display_server.xdg_popup)
3338         {
3339           xdg_popup_destroy (impl->display_server.xdg_popup);
3340           impl->display_server.xdg_popup = NULL;
3341           display_wayland->current_popups =
3342             g_list_remove (display_wayland->current_popups, window);
3343 
3344           if (impl->position_method == POSITION_METHOD_MOVE_TO_RECT)
3345             {
3346               window->x = 0;
3347               window->y = 0;
3348             }
3349         }
3350       if (impl->display_server.xdg_surface)
3351         {
3352           xdg_surface_destroy (impl->display_server.xdg_surface);
3353           impl->display_server.xdg_surface = NULL;
3354           if (!impl->initial_configure_received)
3355             gdk_window_thaw_updates (window);
3356           else
3357             impl->initial_configure_received = FALSE;
3358         }
3359 
3360       if (impl->display_server.zxdg_toplevel_v6)
3361         {
3362           zxdg_toplevel_v6_destroy (impl->display_server.zxdg_toplevel_v6);
3363           impl->display_server.zxdg_toplevel_v6 = NULL;
3364         }
3365       else if (impl->display_server.zxdg_popup_v6)
3366         {
3367           zxdg_popup_v6_destroy (impl->display_server.zxdg_popup_v6);
3368           impl->display_server.zxdg_popup_v6 = NULL;
3369           display_wayland->current_popups =
3370             g_list_remove (display_wayland->current_popups, window);
3371 
3372           if (impl->position_method == POSITION_METHOD_MOVE_TO_RECT)
3373             {
3374               window->x = 0;
3375               window->y = 0;
3376             }
3377         }
3378       if (impl->display_server.zxdg_surface_v6)
3379         {
3380           zxdg_surface_v6_destroy (impl->display_server.zxdg_surface_v6);
3381           impl->display_server.zxdg_surface_v6 = NULL;
3382           if (!impl->initial_configure_received)
3383             gdk_window_thaw_updates (window);
3384           else
3385             impl->initial_configure_received = FALSE;
3386         }
3387 
3388       if (impl->display_server.wl_subsurface)
3389         unmap_subsurface (window);
3390 
3391       if (impl->awaiting_frame)
3392         {
3393           GdkFrameClock *frame_clock;
3394 
3395           impl->awaiting_frame = FALSE;
3396           frame_clock = gdk_window_get_frame_clock (window);
3397           if (frame_clock)
3398             _gdk_frame_clock_thaw (frame_clock);
3399         }
3400 
3401       if (impl->display_server.gtk_surface)
3402         {
3403           if (display_wayland->gtk_shell_version >=
3404               GTK_SURFACE1_RELEASE_SINCE_VERSION)
3405             gtk_surface1_release (impl->display_server.gtk_surface);
3406           else
3407             gtk_surface1_destroy (impl->display_server.gtk_surface);
3408           impl->display_server.gtk_surface = NULL;
3409           impl->application.was_set = FALSE;
3410         }
3411 
3412       if (impl->display_server.server_decoration)
3413         {
3414           org_kde_kwin_server_decoration_release (impl->display_server.server_decoration);
3415           impl->display_server.server_decoration = NULL;
3416         }
3417 
3418       wl_surface_destroy (impl->display_server.wl_surface);
3419       impl->display_server.wl_surface = NULL;
3420       impl->surface_callback = NULL;
3421 
3422       g_slist_free (impl->display_server.outputs);
3423       impl->display_server.outputs = NULL;
3424 
3425       if (impl->hint == GDK_WINDOW_TYPE_HINT_DIALOG && !impl->transient_for)
3426         display_wayland->orphan_dialogs =
3427           g_list_remove (display_wayland->orphan_dialogs, window);
3428     }
3429 
3430   unset_transient_for_exported (window);
3431 
3432   _gdk_wayland_window_clear_saved_size (window);
3433   drop_cairo_surfaces (window);
3434   impl->pending_commit = FALSE;
3435   impl->mapped = FALSE;
3436 }
3437 
3438 static void
gdk_wayland_window_hide(GdkWindow * window)3439 gdk_wayland_window_hide (GdkWindow *window)
3440 {
3441   gdk_wayland_window_hide_surface (window);
3442   _gdk_window_clear_update_area (window);
3443 }
3444 
3445 static void
gdk_window_wayland_withdraw(GdkWindow * window)3446 gdk_window_wayland_withdraw (GdkWindow *window)
3447 {
3448   if (!window->destroyed)
3449     {
3450       if (GDK_WINDOW_IS_MAPPED (window))
3451         gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_WITHDRAWN);
3452 
3453       g_assert (!GDK_WINDOW_IS_MAPPED (window));
3454 
3455       gdk_wayland_window_hide_surface (window);
3456     }
3457 }
3458 
3459 static void
gdk_window_wayland_set_events(GdkWindow * window,GdkEventMask event_mask)3460 gdk_window_wayland_set_events (GdkWindow    *window,
3461                                GdkEventMask  event_mask)
3462 {
3463   GDK_WINDOW (window)->event_mask = event_mask;
3464 }
3465 
3466 static GdkEventMask
gdk_window_wayland_get_events(GdkWindow * window)3467 gdk_window_wayland_get_events (GdkWindow *window)
3468 {
3469   if (GDK_WINDOW_DESTROYED (window))
3470     return 0;
3471   else
3472     return GDK_WINDOW (window)->event_mask;
3473 }
3474 
3475 static void
gdk_window_wayland_raise(GdkWindow * window)3476 gdk_window_wayland_raise (GdkWindow *window)
3477 {
3478 }
3479 
3480 static void
gdk_window_wayland_lower(GdkWindow * window)3481 gdk_window_wayland_lower (GdkWindow *window)
3482 {
3483 }
3484 
3485 static void
gdk_window_wayland_restack_under(GdkWindow * window,GList * native_siblings)3486 gdk_window_wayland_restack_under (GdkWindow *window,
3487                                   GList     *native_siblings)
3488 {
3489 }
3490 
3491 static void
gdk_window_wayland_restack_toplevel(GdkWindow * window,GdkWindow * sibling,gboolean above)3492 gdk_window_wayland_restack_toplevel (GdkWindow *window,
3493                                      GdkWindow *sibling,
3494                                      gboolean   above)
3495 {
3496 }
3497 
3498 static void
gdk_window_request_transient_parent_commit(GdkWindow * window)3499 gdk_window_request_transient_parent_commit (GdkWindow *window)
3500 {
3501   GdkWindowImplWayland *window_impl, *impl;
3502   GdkFrameClock *frame_clock;
3503 
3504   window_impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3505 
3506   if (!window_impl->transient_for)
3507     return;
3508 
3509   impl = GDK_WINDOW_IMPL_WAYLAND (window_impl->transient_for->impl);
3510 
3511   if (!impl->display_server.wl_surface || impl->pending_commit)
3512     return;
3513 
3514   frame_clock = gdk_window_get_frame_clock (window_impl->transient_for);
3515 
3516   if (!frame_clock)
3517     return;
3518 
3519   impl->pending_commit = TRUE;
3520   gdk_frame_clock_request_phase (frame_clock,
3521                                  GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
3522 }
3523 
3524 static void
gdk_window_wayland_move_resize(GdkWindow * window,gboolean with_move,gint x,gint y,gint width,gint height)3525 gdk_window_wayland_move_resize (GdkWindow *window,
3526                                 gboolean   with_move,
3527                                 gint       x,
3528                                 gint       y,
3529                                 gint       width,
3530                                 gint       height)
3531 {
3532   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3533 
3534   if (with_move)
3535     {
3536       /* Each toplevel has in its own "root" coordinate system */
3537       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_TOPLEVEL)
3538         {
3539           window->x = x;
3540           window->y = y;
3541           impl->position_method = POSITION_METHOD_MOVE_RESIZE;
3542 
3543           if (impl->display_server.wl_subsurface &&
3544 	      (x + window->abs_x != impl->subsurface_x ||
3545 	       y + window->abs_y != impl->subsurface_y))
3546             {
3547               gdk_wayland_window_set_subsurface_position (window,
3548                                                           x + window->abs_x,
3549                                                           y + window->abs_y);
3550             }
3551         }
3552     }
3553 
3554   if (window->state & (GDK_WINDOW_STATE_FULLSCREEN |
3555                        GDK_WINDOW_STATE_MAXIMIZED |
3556                        GDK_WINDOW_STATE_TILED))
3557     {
3558       impl->saved_width = width;
3559       impl->saved_height = height;
3560       impl->saved_size_changed = (width > 0 && height > 0);
3561     }
3562 
3563   /* If this function is called with width and height = -1 then that means
3564    * just move the window - don't update its size
3565    */
3566   if (width > 0 && height > 0)
3567     {
3568       if (!should_use_fixed_size (window->state) ||
3569           (width == impl->fixed_size_width &&
3570            height == impl->fixed_size_height))
3571         {
3572           gdk_wayland_window_maybe_configure (window,
3573                                               width,
3574                                               height,
3575                                               impl->scale);
3576         }
3577       else if (!should_inhibit_resize (window))
3578         {
3579           gdk_wayland_window_configure (window,
3580                                         window->width,
3581                                         window->height,
3582                                         impl->scale);
3583         }
3584     }
3585 }
3586 
3587 /* Avoid zero width/height as this is a protocol error */
3588 static void
sanitize_anchor_rect(GdkWindow * window,GdkRectangle * rect)3589 sanitize_anchor_rect (GdkWindow    *window,
3590                       GdkRectangle *rect)
3591 {
3592   gint original_width = rect->width;
3593   gint original_height = rect->height;
3594 
3595   rect->width  = MAX (1, rect->width);
3596   rect->height = MAX (1, rect->height);
3597   rect->x = MAX (rect->x + original_width - rect->width, 0);
3598   rect->y = MAX (rect->y + original_height - rect->height, 0);
3599 }
3600 
3601 static void
gdk_window_wayland_move_to_rect(GdkWindow * window,const GdkRectangle * rect,GdkGravity rect_anchor,GdkGravity window_anchor,GdkAnchorHints anchor_hints,gint rect_anchor_dx,gint rect_anchor_dy)3602 gdk_window_wayland_move_to_rect (GdkWindow          *window,
3603                                  const GdkRectangle *rect,
3604                                  GdkGravity          rect_anchor,
3605                                  GdkGravity          window_anchor,
3606                                  GdkAnchorHints      anchor_hints,
3607                                  gint                rect_anchor_dx,
3608                                  gint                rect_anchor_dy)
3609 {
3610   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3611 
3612   impl->pending_move_to_rect.rect = *rect;
3613   sanitize_anchor_rect (window, &impl->pending_move_to_rect.rect);
3614 
3615   impl->pending_move_to_rect.rect_anchor = rect_anchor;
3616   impl->pending_move_to_rect.window_anchor = window_anchor;
3617   impl->pending_move_to_rect.anchor_hints = anchor_hints;
3618   impl->pending_move_to_rect.rect_anchor_dx = rect_anchor_dx;
3619   impl->pending_move_to_rect.rect_anchor_dy = rect_anchor_dy;
3620 
3621   impl->position_method = POSITION_METHOD_MOVE_TO_RECT;
3622 }
3623 
3624 static void
gdk_window_wayland_set_background(GdkWindow * window,cairo_pattern_t * pattern)3625 gdk_window_wayland_set_background (GdkWindow       *window,
3626                                    cairo_pattern_t *pattern)
3627 {
3628 }
3629 
3630 static gboolean
gdk_window_wayland_reparent(GdkWindow * window,GdkWindow * new_parent,gint x,gint y)3631 gdk_window_wayland_reparent (GdkWindow *window,
3632                              GdkWindow *new_parent,
3633                              gint       x,
3634                              gint       y)
3635 {
3636   return FALSE;
3637 }
3638 
3639 static void
gdk_window_wayland_set_device_cursor(GdkWindow * window,GdkDevice * device,GdkCursor * cursor)3640 gdk_window_wayland_set_device_cursor (GdkWindow *window,
3641                                       GdkDevice *device,
3642                                       GdkCursor *cursor)
3643 {
3644   g_return_if_fail (GDK_IS_WINDOW (window));
3645   g_return_if_fail (GDK_IS_DEVICE (device));
3646 
3647   if (!GDK_WINDOW_DESTROYED (window))
3648     GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
3649 }
3650 
3651 static void
gdk_window_wayland_get_geometry(GdkWindow * window,gint * x,gint * y,gint * width,gint * height)3652 gdk_window_wayland_get_geometry (GdkWindow *window,
3653                                  gint      *x,
3654                                  gint      *y,
3655                                  gint      *width,
3656                                  gint      *height)
3657 {
3658   if (!GDK_WINDOW_DESTROYED (window))
3659     {
3660       if (x)
3661         *x = window->x;
3662       if (y)
3663         *y = window->y;
3664       if (width)
3665         *width = window->width;
3666       if (height)
3667         *height = window->height;
3668     }
3669 }
3670 
3671 static void
gdk_window_wayland_get_root_coords(GdkWindow * window,gint x,gint y,gint * root_x,gint * root_y)3672 gdk_window_wayland_get_root_coords (GdkWindow *window,
3673                                     gint       x,
3674                                     gint       y,
3675                                     gint      *root_x,
3676                                     gint      *root_y)
3677 {
3678   /*
3679    * Wayland does not have a global coordinate space shared between surfaces. In
3680    * fact, for regular toplevels, we have no idea where our surfaces are
3681    * positioned, relatively.
3682    *
3683    * However, there are some cases like popups and subsurfaces where we do have
3684    * some amount of control over the placement of our window, and we can
3685    * semi-accurately control the x/y position of these windows, if they are
3686    * relative to another surface.
3687    *
3688    * To pretend we have something called a root coordinate space, assume all
3689    * parent-less windows are positioned in (0, 0), and all relative positioned
3690    * popups and subsurfaces are placed within this fake root coordinate space.
3691    *
3692    * For example a 200x200 large toplevel window will have the position (0, 0).
3693    * If a popup positioned in the middle of the toplevel will have the fake
3694    * position (100,100). Furthermore, if a positioned is placed in the middle
3695    * that popup, will have the fake position (150,150), even though it has the
3696    * relative position (50,50). These three windows would make up one single
3697    * fake root coordinate space.
3698    */
3699 
3700   if (root_x)
3701     *root_x = window->x + x;
3702 
3703   if (root_y)
3704     *root_y = window->y + y;
3705 }
3706 
3707 static gboolean
gdk_window_wayland_get_device_state(GdkWindow * window,GdkDevice * device,gdouble * x,gdouble * y,GdkModifierType * mask)3708 gdk_window_wayland_get_device_state (GdkWindow       *window,
3709                                      GdkDevice       *device,
3710                                      gdouble         *x,
3711                                      gdouble         *y,
3712                                      GdkModifierType *mask)
3713 {
3714   gboolean return_val;
3715 
3716   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
3717 
3718   return_val = TRUE;
3719 
3720   if (!GDK_WINDOW_DESTROYED (window))
3721     {
3722       GdkWindow *child;
3723 
3724       GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
3725                                                   NULL, &child,
3726                                                   NULL, NULL,
3727                                                   x, y, mask);
3728       return_val = (child != NULL);
3729     }
3730 
3731   return return_val;
3732 }
3733 
3734 static void
gdk_window_wayland_shape_combine_region(GdkWindow * window,const cairo_region_t * shape_region,gint offset_x,gint offset_y)3735 gdk_window_wayland_shape_combine_region (GdkWindow            *window,
3736                                          const cairo_region_t *shape_region,
3737                                          gint                  offset_x,
3738                                          gint                  offset_y)
3739 {
3740 }
3741 
3742 static void
gdk_window_wayland_input_shape_combine_region(GdkWindow * window,const cairo_region_t * shape_region,gint offset_x,gint offset_y)3743 gdk_window_wayland_input_shape_combine_region (GdkWindow            *window,
3744                                                const cairo_region_t *shape_region,
3745                                                gint                  offset_x,
3746                                                gint                  offset_y)
3747 {
3748   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3749 
3750   if (GDK_WINDOW_DESTROYED (window))
3751     return;
3752 
3753   g_clear_pointer (&impl->input_region, cairo_region_destroy);
3754 
3755   if (shape_region)
3756     {
3757       impl->input_region = cairo_region_copy (shape_region);
3758       cairo_region_translate (impl->input_region, offset_x, offset_y);
3759     }
3760 
3761   impl->input_region_dirty = TRUE;
3762 }
3763 
3764 static void
gdk_wayland_window_destroy(GdkWindow * window,gboolean recursing,gboolean foreign_destroy)3765 gdk_wayland_window_destroy (GdkWindow *window,
3766                             gboolean   recursing,
3767                             gboolean   foreign_destroy)
3768 {
3769   g_return_if_fail (GDK_IS_WINDOW (window));
3770 
3771   /* Wayland windows can't be externally destroyed; we may possibly
3772    * eventually want to use this path at display close-down
3773    */
3774   g_return_if_fail (!foreign_destroy);
3775 
3776   gdk_wayland_window_hide_surface (window);
3777 }
3778 
3779 static void
gdk_window_wayland_destroy_foreign(GdkWindow * window)3780 gdk_window_wayland_destroy_foreign (GdkWindow *window)
3781 {
3782 }
3783 
3784 static cairo_region_t *
gdk_wayland_window_get_shape(GdkWindow * window)3785 gdk_wayland_window_get_shape (GdkWindow *window)
3786 {
3787   return NULL;
3788 }
3789 
3790 static cairo_region_t *
gdk_wayland_window_get_input_shape(GdkWindow * window)3791 gdk_wayland_window_get_input_shape (GdkWindow *window)
3792 {
3793   return NULL;
3794 }
3795 
3796 static void
gdk_wayland_window_focus(GdkWindow * window,guint32 timestamp)3797 gdk_wayland_window_focus (GdkWindow *window,
3798                           guint32    timestamp)
3799 {
3800   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3801 
3802   if (!impl->display_server.gtk_surface)
3803     return;
3804 
3805   if (timestamp == GDK_CURRENT_TIME)
3806     {
3807       GdkWaylandDisplay *display_wayland =
3808         GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
3809 
3810       if (display_wayland->gtk_shell_version >= 3)
3811         {
3812           gtk_surface1_request_focus (impl->display_server.gtk_surface,
3813                                       display_wayland->startup_notification_id);
3814           g_clear_pointer (&display_wayland->startup_notification_id, g_free);
3815         }
3816     }
3817   else
3818     gtk_surface1_present (impl->display_server.gtk_surface, timestamp);
3819 }
3820 
3821 static void
gdk_wayland_window_set_type_hint(GdkWindow * window,GdkWindowTypeHint hint)3822 gdk_wayland_window_set_type_hint (GdkWindow         *window,
3823                                   GdkWindowTypeHint  hint)
3824 {
3825   GdkWindowImplWayland *impl;
3826 
3827   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3828 
3829   if (GDK_WINDOW_DESTROYED (window))
3830     return;
3831 
3832   impl->hint = hint;
3833 }
3834 
3835 static GdkWindowTypeHint
gdk_wayland_window_get_type_hint(GdkWindow * window)3836 gdk_wayland_window_get_type_hint (GdkWindow *window)
3837 {
3838   GdkWindowImplWayland *impl;
3839 
3840   if (GDK_WINDOW_DESTROYED (window))
3841     return GDK_WINDOW_TYPE_HINT_NORMAL;
3842 
3843   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3844 
3845   return impl->hint;
3846 }
3847 
3848 static void
gtk_surface_configure(void * data,struct gtk_surface1 * gtk_surface,struct wl_array * states)3849 gtk_surface_configure (void                *data,
3850                        struct gtk_surface1 *gtk_surface,
3851                        struct wl_array     *states)
3852 {
3853   GdkWindow *window = GDK_WINDOW (data);
3854   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3855   GdkWindowState new_state = 0;
3856   uint32_t *p;
3857 
3858   wl_array_for_each (p, states)
3859     {
3860       uint32_t state = *p;
3861 
3862       switch (state)
3863         {
3864         case GTK_SURFACE1_STATE_TILED:
3865           new_state |= GDK_WINDOW_STATE_TILED;
3866           break;
3867 
3868         /* Since v2 */
3869         case GTK_SURFACE1_STATE_TILED_TOP:
3870           new_state |= (GDK_WINDOW_STATE_TILED | GDK_WINDOW_STATE_TOP_TILED);
3871           break;
3872         case GTK_SURFACE1_STATE_TILED_RIGHT:
3873           new_state |= (GDK_WINDOW_STATE_TILED | GDK_WINDOW_STATE_RIGHT_TILED);
3874           break;
3875         case GTK_SURFACE1_STATE_TILED_BOTTOM:
3876           new_state |= (GDK_WINDOW_STATE_TILED | GDK_WINDOW_STATE_BOTTOM_TILED);
3877           break;
3878         case GTK_SURFACE1_STATE_TILED_LEFT:
3879           new_state |= (GDK_WINDOW_STATE_TILED | GDK_WINDOW_STATE_LEFT_TILED);
3880           break;
3881         default:
3882           /* Unknown state */
3883           break;
3884         }
3885     }
3886 
3887   impl->pending.state |= new_state;
3888 }
3889 
3890 static void
gtk_surface_configure_edges(void * data,struct gtk_surface1 * gtk_surface,struct wl_array * edge_constraints)3891 gtk_surface_configure_edges (void                *data,
3892                              struct gtk_surface1 *gtk_surface,
3893                              struct wl_array     *edge_constraints)
3894 {
3895   GdkWindow *window = GDK_WINDOW (data);
3896   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3897   GdkWindowState new_state = 0;
3898   uint32_t *p;
3899 
3900   wl_array_for_each (p, edge_constraints)
3901     {
3902       uint32_t constraint = *p;
3903 
3904       switch (constraint)
3905         {
3906         case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_TOP:
3907           new_state |= GDK_WINDOW_STATE_TOP_RESIZABLE;
3908           break;
3909         case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_RIGHT:
3910           new_state |= GDK_WINDOW_STATE_RIGHT_RESIZABLE;
3911           break;
3912         case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_BOTTOM:
3913           new_state |= GDK_WINDOW_STATE_BOTTOM_RESIZABLE;
3914           break;
3915         case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_LEFT:
3916           new_state |= GDK_WINDOW_STATE_LEFT_RESIZABLE;
3917           break;
3918         default:
3919           /* Unknown state */
3920           break;
3921         }
3922     }
3923 
3924   impl->pending.state |= new_state;
3925 }
3926 
3927 static const struct gtk_surface1_listener gtk_surface_listener = {
3928   gtk_surface_configure,
3929   gtk_surface_configure_edges
3930 };
3931 
3932 static void
gdk_wayland_window_init_gtk_surface(GdkWindow * window)3933 gdk_wayland_window_init_gtk_surface (GdkWindow *window)
3934 {
3935   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3936   GdkWaylandDisplay *display =
3937     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
3938 
3939   if (impl->display_server.gtk_surface != NULL)
3940     return;
3941   if (!is_realized_toplevel (window))
3942     return;
3943   if (display->gtk_shell == NULL)
3944     return;
3945 
3946   impl->display_server.gtk_surface =
3947     gtk_shell1_get_gtk_surface (display->gtk_shell,
3948                                 impl->display_server.wl_surface);
3949   gdk_window_set_geometry_hints (window,
3950                                  &impl->geometry_hints,
3951                                  impl->geometry_mask);
3952   gtk_surface1_add_listener (impl->display_server.gtk_surface,
3953                              &gtk_surface_listener,
3954                              window);
3955 }
3956 
3957 static void
maybe_set_gtk_surface_modal(GdkWindow * window)3958 maybe_set_gtk_surface_modal (GdkWindow *window)
3959 {
3960   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3961 
3962   gdk_wayland_window_init_gtk_surface (window);
3963   if (impl->display_server.gtk_surface == NULL)
3964     return;
3965 
3966   if (window->modal_hint)
3967     gtk_surface1_set_modal (impl->display_server.gtk_surface);
3968   else
3969     gtk_surface1_unset_modal (impl->display_server.gtk_surface);
3970 
3971 }
3972 
3973 static void
gdk_wayland_window_set_modal_hint(GdkWindow * window,gboolean modal)3974 gdk_wayland_window_set_modal_hint (GdkWindow *window,
3975                                    gboolean   modal)
3976 {
3977   window->modal_hint = modal;
3978   maybe_set_gtk_surface_modal (window);
3979 }
3980 
3981 static void
gdk_wayland_window_set_skip_taskbar_hint(GdkWindow * window,gboolean skips_taskbar)3982 gdk_wayland_window_set_skip_taskbar_hint (GdkWindow *window,
3983                                           gboolean   skips_taskbar)
3984 {
3985 }
3986 
3987 static void
gdk_wayland_window_set_skip_pager_hint(GdkWindow * window,gboolean skips_pager)3988 gdk_wayland_window_set_skip_pager_hint (GdkWindow *window,
3989                                         gboolean   skips_pager)
3990 {
3991 }
3992 
3993 static void
gdk_wayland_window_set_urgency_hint(GdkWindow * window,gboolean urgent)3994 gdk_wayland_window_set_urgency_hint (GdkWindow *window,
3995                                      gboolean   urgent)
3996 {
3997 }
3998 
3999 static void
gdk_wayland_window_set_geometry_hints(GdkWindow * window,const GdkGeometry * geometry,GdkWindowHints geom_mask)4000 gdk_wayland_window_set_geometry_hints (GdkWindow         *window,
4001                                        const GdkGeometry *geometry,
4002                                        GdkWindowHints     geom_mask)
4003 {
4004   GdkWaylandDisplay *display_wayland;
4005   GdkWindowImplWayland *impl;
4006   int min_width = 0, min_height = 0, max_width = 0, max_height = 0;
4007 
4008   if (GDK_WINDOW_DESTROYED (window) ||
4009       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4010     return;
4011 
4012   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4013   display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4014 
4015   impl->geometry_hints = *geometry;
4016   impl->geometry_mask = geom_mask;
4017 
4018   if (!is_realized_toplevel (window))
4019     return;
4020 
4021   if (geom_mask & GDK_HINT_MIN_SIZE)
4022     {
4023       min_width =
4024         MAX (0, calculate_width_without_margin (window, geometry->min_width));
4025       min_height =
4026         MAX (0, calculate_height_without_margin (window, geometry->min_height));
4027     }
4028 
4029   if (geom_mask & GDK_HINT_MAX_SIZE)
4030     {
4031       max_width =
4032         MAX (0, calculate_width_without_margin (window, geometry->max_width));
4033       max_height =
4034         MAX (0, calculate_height_without_margin (window, geometry->max_height));
4035     }
4036 
4037   switch (display_wayland->shell_variant)
4038     {
4039     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4040       xdg_toplevel_set_min_size (impl->display_server.xdg_toplevel,
4041                                  min_width, min_height);
4042       xdg_toplevel_set_max_size (impl->display_server.xdg_toplevel,
4043                                  max_width, max_height);
4044       break;
4045     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4046       zxdg_toplevel_v6_set_min_size (impl->display_server.zxdg_toplevel_v6,
4047                                      min_width, min_height);
4048       zxdg_toplevel_v6_set_max_size (impl->display_server.zxdg_toplevel_v6,
4049                                      max_width, max_height);
4050       break;
4051     }
4052 }
4053 
4054 static void
gdk_wayland_window_set_title(GdkWindow * window,const gchar * title)4055 gdk_wayland_window_set_title (GdkWindow   *window,
4056                               const gchar *title)
4057 {
4058   GdkWindowImplWayland *impl;
4059   const char *end;
4060   g_return_if_fail (title != NULL);
4061 
4062   if (GDK_WINDOW_DESTROYED (window))
4063     return;
4064 
4065   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4066 
4067   if (g_strcmp0 (impl->title, title) == 0)
4068     return;
4069 
4070   g_free (impl->title);
4071 
4072   g_utf8_validate (title, MAX_WL_BUFFER_SIZE, &end);
4073   impl->title = g_malloc (end - title + 1);
4074   memcpy (impl->title, title, end - title);
4075   impl->title[end - title] = '\0';
4076 
4077   gdk_wayland_window_sync_title (window);
4078 }
4079 
4080 static void
gdk_wayland_window_set_role(GdkWindow * window,const gchar * role)4081 gdk_wayland_window_set_role (GdkWindow   *window,
4082                              const gchar *role)
4083 {
4084 }
4085 
4086 static void
gdk_wayland_window_set_startup_id(GdkWindow * window,const gchar * startup_id)4087 gdk_wayland_window_set_startup_id (GdkWindow   *window,
4088                                    const gchar *startup_id)
4089 {
4090 }
4091 
4092 static gboolean
check_transient_for_loop(GdkWindow * window,GdkWindow * parent)4093 check_transient_for_loop (GdkWindow *window,
4094                           GdkWindow *parent)
4095 {
4096   while (parent)
4097     {
4098       GdkWindowImplWayland *impl;
4099 
4100       if (!GDK_IS_WINDOW_IMPL_WAYLAND(parent->impl))
4101         return FALSE;
4102 
4103       impl = GDK_WINDOW_IMPL_WAYLAND (parent->impl);
4104       if (impl->transient_for == window)
4105         return TRUE;
4106       parent = impl->transient_for;
4107     }
4108   return FALSE;
4109 }
4110 
4111 static void
gdk_wayland_window_set_transient_for(GdkWindow * window,GdkWindow * parent)4112 gdk_wayland_window_set_transient_for (GdkWindow *window,
4113                                       GdkWindow *parent)
4114 {
4115   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4116   GdkWaylandDisplay *display_wayland =
4117     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4118   GdkWindow *previous_parent;
4119   gboolean was_subsurface = FALSE;
4120 
4121   g_assert (parent == NULL ||
4122             gdk_window_get_display (window) == gdk_window_get_display (parent));
4123 
4124   if (check_transient_for_loop (window, parent))
4125     {
4126       g_warning ("Setting %p transient for %p would create a loop", window, parent);
4127       return;
4128     }
4129 
4130   unset_transient_for_exported (window);
4131 
4132   if (impl->display_server.wl_subsurface)
4133     {
4134       was_subsurface = TRUE;
4135       unmap_subsurface (window);
4136     }
4137 
4138   previous_parent = impl->transient_for;
4139   impl->transient_for = parent;
4140 
4141   if (impl->hint == GDK_WINDOW_TYPE_HINT_DIALOG)
4142     {
4143       if (!parent)
4144         _gdk_wayland_screen_add_orphan_dialog (window);
4145       else if (!previous_parent)
4146         display_wayland->orphan_dialogs =
4147           g_list_remove (display_wayland->orphan_dialogs, window);
4148     }
4149 
4150   gdk_wayland_window_sync_parent (window, NULL);
4151 
4152   if (was_subsurface && parent)
4153     gdk_wayland_window_create_subsurface (window);
4154 }
4155 
4156 static void
gdk_wayland_window_get_frame_extents(GdkWindow * window,GdkRectangle * rect)4157 gdk_wayland_window_get_frame_extents (GdkWindow    *window,
4158                                       GdkRectangle *rect)
4159 {
4160   *rect = (GdkRectangle) {
4161     .x = window->x,
4162     .y = window->y,
4163     .width = window->width,
4164     .height = window->height
4165   };
4166 }
4167 
4168 static void
gdk_wayland_window_set_override_redirect(GdkWindow * window,gboolean override_redirect)4169 gdk_wayland_window_set_override_redirect (GdkWindow *window,
4170                                           gboolean   override_redirect)
4171 {
4172 }
4173 
4174 static void
gdk_wayland_window_set_accept_focus(GdkWindow * window,gboolean accept_focus)4175 gdk_wayland_window_set_accept_focus (GdkWindow *window,
4176                                      gboolean   accept_focus)
4177 {
4178 }
4179 
4180 static void
gdk_wayland_window_set_focus_on_map(GdkWindow * window,gboolean focus_on_map)4181 gdk_wayland_window_set_focus_on_map (GdkWindow *window,
4182                                      gboolean focus_on_map)
4183 {
4184 }
4185 
4186 static void
gdk_wayland_window_set_icon_list(GdkWindow * window,GList * pixbufs)4187 gdk_wayland_window_set_icon_list (GdkWindow *window,
4188                                   GList     *pixbufs)
4189 {
4190 }
4191 
4192 static void
gdk_wayland_window_set_icon_name(GdkWindow * window,const gchar * name)4193 gdk_wayland_window_set_icon_name (GdkWindow   *window,
4194                                   const gchar *name)
4195 {
4196   if (GDK_WINDOW_DESTROYED (window))
4197     return;
4198 }
4199 
4200 static void
gdk_wayland_window_iconify(GdkWindow * window)4201 gdk_wayland_window_iconify (GdkWindow *window)
4202 {
4203   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4204   GdkWaylandDisplay *display_wayland;
4205 
4206   if (GDK_WINDOW_DESTROYED (window) ||
4207       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4208     return;
4209 
4210   if (!is_realized_toplevel (window))
4211     return;
4212 
4213   display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4214   switch (display_wayland->shell_variant)
4215     {
4216     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4217       xdg_toplevel_set_minimized (impl->display_server.xdg_toplevel);
4218       break;
4219     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4220       zxdg_toplevel_v6_set_minimized (impl->display_server.zxdg_toplevel_v6);
4221       break;
4222     }
4223 }
4224 
4225 static void
gdk_wayland_window_deiconify(GdkWindow * window)4226 gdk_wayland_window_deiconify (GdkWindow *window)
4227 {
4228   if (GDK_WINDOW_DESTROYED (window) ||
4229       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4230     return;
4231 
4232   if (GDK_WINDOW_IS_MAPPED (window))
4233     gdk_window_show (window);
4234   else
4235     /* Flip our client side flag, the real work happens on map. */
4236     gdk_synthesize_window_state (window, GDK_WINDOW_STATE_ICONIFIED, 0);
4237 }
4238 
4239 static void
gdk_wayland_window_stick(GdkWindow * window)4240 gdk_wayland_window_stick (GdkWindow *window)
4241 {
4242 }
4243 
4244 static void
gdk_wayland_window_unstick(GdkWindow * window)4245 gdk_wayland_window_unstick (GdkWindow *window)
4246 {
4247 }
4248 
4249 static void
gdk_wayland_window_maximize(GdkWindow * window)4250 gdk_wayland_window_maximize (GdkWindow *window)
4251 {
4252   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4253 
4254   if (GDK_WINDOW_DESTROYED (window))
4255     return;
4256 
4257   _gdk_wayland_window_save_size (window);
4258   if (is_realized_toplevel (window))
4259     {
4260       GdkWaylandDisplay *display_wayland =
4261         GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4262 
4263       switch (display_wayland->shell_variant)
4264         {
4265         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4266           xdg_toplevel_set_maximized (impl->display_server.xdg_toplevel);
4267           break;
4268         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4269           zxdg_toplevel_v6_set_maximized (impl->display_server.zxdg_toplevel_v6);
4270           break;
4271         }
4272     }
4273   else
4274     {
4275       gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_MAXIMIZED);
4276     }
4277 }
4278 
4279 static void
gdk_wayland_window_unmaximize(GdkWindow * window)4280 gdk_wayland_window_unmaximize (GdkWindow *window)
4281 {
4282   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4283 
4284   if (GDK_WINDOW_DESTROYED (window))
4285     return;
4286 
4287   if (is_realized_toplevel (window))
4288     {
4289       GdkWaylandDisplay *display_wayland =
4290         GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4291 
4292       switch (display_wayland->shell_variant)
4293         {
4294         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4295           xdg_toplevel_unset_maximized (impl->display_server.xdg_toplevel);
4296           break;
4297         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4298           zxdg_toplevel_v6_unset_maximized (impl->display_server.zxdg_toplevel_v6);
4299           break;
4300         }
4301     }
4302   else
4303     {
4304       gdk_synthesize_window_state (window, GDK_WINDOW_STATE_MAXIMIZED, 0);
4305     }
4306 }
4307 
4308 static void
gdk_wayland_window_fullscreen_on_monitor(GdkWindow * window,gint monitor)4309 gdk_wayland_window_fullscreen_on_monitor (GdkWindow *window, gint monitor)
4310 {
4311   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4312   GdkScreen *screen = gdk_window_get_screen (window);
4313   struct wl_output *fullscreen_output =
4314     _gdk_wayland_screen_get_wl_output (screen, monitor);
4315 
4316   if (GDK_WINDOW_DESTROYED (window))
4317     return;
4318 
4319   _gdk_wayland_window_save_size (window);
4320   if (is_realized_toplevel (window))
4321     {
4322       GdkWaylandDisplay *display_wayland =
4323         GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4324 
4325       switch (display_wayland->shell_variant)
4326         {
4327         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4328           xdg_toplevel_set_fullscreen (impl->display_server.xdg_toplevel,
4329                                        fullscreen_output);
4330           break;
4331         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4332           zxdg_toplevel_v6_set_fullscreen (impl->display_server.zxdg_toplevel_v6,
4333                                            fullscreen_output);
4334           break;
4335         }
4336     }
4337   else
4338     {
4339       gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
4340       impl->initial_fullscreen_monitor = monitor;
4341     }
4342 }
4343 
4344 static void
gdk_wayland_window_fullscreen(GdkWindow * window)4345 gdk_wayland_window_fullscreen (GdkWindow *window)
4346 {
4347   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4348 
4349   if (GDK_WINDOW_DESTROYED (window))
4350     return;
4351 
4352   impl->initial_fullscreen_monitor = -1;
4353 
4354   _gdk_wayland_window_save_size (window);
4355   if (is_realized_toplevel (window))
4356     {
4357       GdkWaylandDisplay *display_wayland =
4358         GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4359 
4360       switch (display_wayland->shell_variant)
4361         {
4362         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4363           xdg_toplevel_set_fullscreen (impl->display_server.xdg_toplevel,
4364                                        NULL);
4365           break;
4366         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4367           zxdg_toplevel_v6_set_fullscreen (impl->display_server.zxdg_toplevel_v6,
4368                                            NULL);
4369           break;
4370         }
4371     }
4372   else
4373     {
4374       gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
4375     }
4376 }
4377 
4378 static void
gdk_wayland_window_unfullscreen(GdkWindow * window)4379 gdk_wayland_window_unfullscreen (GdkWindow *window)
4380 {
4381   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4382 
4383   if (GDK_WINDOW_DESTROYED (window))
4384     return;
4385 
4386   impl->initial_fullscreen_monitor = -1;
4387 
4388   if (is_realized_toplevel (window))
4389     {
4390       GdkWaylandDisplay *display_wayland =
4391         GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4392 
4393       switch (display_wayland->shell_variant)
4394         {
4395         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4396           xdg_toplevel_unset_fullscreen (impl->display_server.xdg_toplevel);
4397           break;
4398         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4399           zxdg_toplevel_v6_unset_fullscreen (impl->display_server.zxdg_toplevel_v6);
4400           break;
4401         }
4402     }
4403   else
4404     {
4405       gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
4406     }
4407 }
4408 
4409 static void
gdk_wayland_window_set_keep_above(GdkWindow * window,gboolean setting)4410 gdk_wayland_window_set_keep_above (GdkWindow *window, gboolean setting)
4411 {
4412 }
4413 
4414 static void
gdk_wayland_window_set_keep_below(GdkWindow * window,gboolean setting)4415 gdk_wayland_window_set_keep_below (GdkWindow *window, gboolean setting)
4416 {
4417 }
4418 
4419 static GdkWindow *
gdk_wayland_window_get_group(GdkWindow * window)4420 gdk_wayland_window_get_group (GdkWindow *window)
4421 {
4422   return NULL;
4423 }
4424 
4425 static void
gdk_wayland_window_set_group(GdkWindow * window,GdkWindow * leader)4426 gdk_wayland_window_set_group (GdkWindow *window,
4427                               GdkWindow *leader)
4428 {
4429 }
4430 
4431 static void
gdk_wayland_window_set_decorations(GdkWindow * window,GdkWMDecoration decorations)4432 gdk_wayland_window_set_decorations (GdkWindow       *window,
4433                                     GdkWMDecoration  decorations)
4434 {
4435 }
4436 
4437 static gboolean
gdk_wayland_window_get_decorations(GdkWindow * window,GdkWMDecoration * decorations)4438 gdk_wayland_window_get_decorations (GdkWindow       *window,
4439                                     GdkWMDecoration *decorations)
4440 {
4441   return FALSE;
4442 }
4443 
4444 static void
gdk_wayland_window_set_functions(GdkWindow * window,GdkWMFunction functions)4445 gdk_wayland_window_set_functions (GdkWindow     *window,
4446                                   GdkWMFunction  functions)
4447 {
4448 }
4449 
4450 static void
gdk_wayland_window_begin_resize_drag(GdkWindow * window,GdkWindowEdge edge,GdkDevice * device,gint button,gint root_x,gint root_y,guint32 timestamp)4451 gdk_wayland_window_begin_resize_drag (GdkWindow     *window,
4452                                       GdkWindowEdge  edge,
4453                                       GdkDevice     *device,
4454                                       gint           button,
4455                                       gint           root_x,
4456                                       gint           root_y,
4457                                       guint32        timestamp)
4458 {
4459   GdkWindowImplWayland *impl;
4460   GdkWaylandDisplay *display_wayland;
4461   GdkEventSequence *sequence;
4462   uint32_t resize_edges, serial;
4463 
4464   if (GDK_WINDOW_DESTROYED (window) ||
4465       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4466     return;
4467 
4468   switch (edge)
4469     {
4470     case GDK_WINDOW_EDGE_NORTH_WEST:
4471       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_LEFT;
4472       break;
4473 
4474     case GDK_WINDOW_EDGE_NORTH:
4475       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP;
4476       break;
4477 
4478     case GDK_WINDOW_EDGE_NORTH_EAST:
4479       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_RIGHT;
4480       break;
4481 
4482     case GDK_WINDOW_EDGE_WEST:
4483       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT;
4484       break;
4485 
4486     case GDK_WINDOW_EDGE_EAST:
4487       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT;
4488       break;
4489 
4490     case GDK_WINDOW_EDGE_SOUTH_WEST:
4491       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_LEFT;
4492       break;
4493 
4494     case GDK_WINDOW_EDGE_SOUTH:
4495       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM;
4496       break;
4497 
4498     case GDK_WINDOW_EDGE_SOUTH_EAST:
4499       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_RIGHT;
4500       break;
4501 
4502     default:
4503       g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!", edge);
4504       return;
4505     }
4506 
4507   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4508   display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4509 
4510   if (!is_realized_toplevel (window))
4511     return;
4512 
4513   serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_device_get_seat (device),
4514                                                             &sequence);
4515 
4516   switch (display_wayland->shell_variant)
4517     {
4518     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4519       xdg_toplevel_resize (impl->display_server.xdg_toplevel,
4520                            gdk_wayland_device_get_wl_seat (device),
4521                            serial, resize_edges);
4522       break;
4523     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4524       zxdg_toplevel_v6_resize (impl->display_server.zxdg_toplevel_v6,
4525                                gdk_wayland_device_get_wl_seat (device),
4526                                serial, resize_edges);
4527       break;
4528     }
4529 
4530   if (sequence)
4531     gdk_wayland_device_unset_touch_grab (device, sequence);
4532 
4533   /* This is needed since Wayland will absorb all the pointer events after the
4534    * above function - FIXME: Is this always safe..?
4535    */
4536   gdk_seat_ungrab (gdk_device_get_seat (device));
4537 }
4538 
4539 static void
gdk_wayland_window_begin_move_drag(GdkWindow * window,GdkDevice * device,gint button,gint root_x,gint root_y,guint32 timestamp)4540 gdk_wayland_window_begin_move_drag (GdkWindow *window,
4541                                     GdkDevice *device,
4542                                     gint       button,
4543                                     gint       root_x,
4544                                     gint       root_y,
4545                                     guint32    timestamp)
4546 {
4547   GdkWindowImplWayland *impl;
4548   GdkWaylandDisplay *display_wayland;
4549   GdkEventSequence *sequence;
4550   uint32_t serial;
4551 
4552   if (GDK_WINDOW_DESTROYED (window) ||
4553       !WINDOW_IS_TOPLEVEL (window))
4554     return;
4555 
4556   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4557   display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4558 
4559   if (!is_realized_toplevel (window))
4560     return;
4561 
4562   serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_device_get_seat (device),
4563                                                             &sequence);
4564   switch (display_wayland->shell_variant)
4565     {
4566     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4567       xdg_toplevel_move (impl->display_server.xdg_toplevel,
4568                          gdk_wayland_device_get_wl_seat (device),
4569                          serial);
4570       break;
4571     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4572       zxdg_toplevel_v6_move (impl->display_server.zxdg_toplevel_v6,
4573                              gdk_wayland_device_get_wl_seat (device),
4574                              serial);
4575       break;
4576     }
4577 
4578   if (sequence)
4579     gdk_wayland_device_unset_touch_grab (device, sequence);
4580 
4581   /* This is needed since Wayland will absorb all the pointer events after the
4582    * above function - FIXME: Is this always safe..?
4583    */
4584   gdk_seat_ungrab (gdk_device_get_seat (device));
4585 }
4586 
4587 static void
gdk_wayland_window_set_opacity(GdkWindow * window,gdouble opacity)4588 gdk_wayland_window_set_opacity (GdkWindow *window,
4589                                 gdouble    opacity)
4590 {
4591 }
4592 
4593 static void
gdk_wayland_window_set_composited(GdkWindow * window,gboolean composited)4594 gdk_wayland_window_set_composited (GdkWindow *window,
4595                                    gboolean   composited)
4596 {
4597 }
4598 
4599 static void
gdk_wayland_window_destroy_notify(GdkWindow * window)4600 gdk_wayland_window_destroy_notify (GdkWindow *window)
4601 {
4602   if (!GDK_WINDOW_DESTROYED (window))
4603     {
4604       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
4605         g_warning ("GdkWindow %p unexpectedly destroyed", window);
4606 
4607       _gdk_window_destroy (window, TRUE);
4608     }
4609 
4610   g_object_unref (window);
4611 }
4612 
4613 static void
gdk_wayland_window_sync_rendering(GdkWindow * window)4614 gdk_wayland_window_sync_rendering (GdkWindow *window)
4615 {
4616 }
4617 
4618 static gboolean
gdk_wayland_window_simulate_key(GdkWindow * window,gint x,gint y,guint keyval,GdkModifierType modifiers,GdkEventType key_pressrelease)4619 gdk_wayland_window_simulate_key (GdkWindow       *window,
4620                                  gint             x,
4621                                  gint             y,
4622                                  guint            keyval,
4623                                  GdkModifierType  modifiers,
4624                                  GdkEventType     key_pressrelease)
4625 {
4626   return FALSE;
4627 }
4628 
4629 static gboolean
gdk_wayland_window_simulate_button(GdkWindow * window,gint x,gint y,guint button,GdkModifierType modifiers,GdkEventType button_pressrelease)4630 gdk_wayland_window_simulate_button (GdkWindow       *window,
4631                                     gint             x,
4632                                     gint             y,
4633                                     guint            button,
4634                                     GdkModifierType  modifiers,
4635                                     GdkEventType     button_pressrelease)
4636 {
4637   return FALSE;
4638 }
4639 
4640 static gboolean
gdk_wayland_window_get_property(GdkWindow * window,GdkAtom property,GdkAtom type,gulong offset,gulong length,gint pdelete,GdkAtom * actual_property_type,gint * actual_format_type,gint * actual_length,guchar ** data)4641 gdk_wayland_window_get_property (GdkWindow   *window,
4642                                  GdkAtom      property,
4643                                  GdkAtom      type,
4644                                  gulong       offset,
4645                                  gulong       length,
4646                                  gint         pdelete,
4647                                  GdkAtom     *actual_property_type,
4648                                  gint        *actual_format_type,
4649                                  gint        *actual_length,
4650                                  guchar     **data)
4651 {
4652   return FALSE;
4653 }
4654 
4655 static void
gdk_wayland_window_change_property(GdkWindow * window,GdkAtom property,GdkAtom type,gint format,GdkPropMode mode,const guchar * data,gint nelements)4656 gdk_wayland_window_change_property (GdkWindow    *window,
4657                                     GdkAtom       property,
4658                                     GdkAtom       type,
4659                                     gint          format,
4660                                     GdkPropMode   mode,
4661                                     const guchar *data,
4662                                     gint          nelements)
4663 {
4664   if (property == gdk_atom_intern_static_string ("GDK_SELECTION"))
4665     gdk_wayland_selection_store (window, type, mode, data, nelements * (format / 8));
4666 }
4667 
4668 static void
gdk_wayland_window_delete_property(GdkWindow * window,GdkAtom property)4669 gdk_wayland_window_delete_property (GdkWindow *window,
4670                                     GdkAtom    property)
4671 {
4672 }
4673 
4674 static gint
gdk_wayland_window_get_scale_factor(GdkWindow * window)4675 gdk_wayland_window_get_scale_factor (GdkWindow *window)
4676 {
4677   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4678 
4679   if (GDK_WINDOW_DESTROYED (window))
4680     return 1;
4681 
4682   return impl->scale;
4683 }
4684 
4685 static void
gdk_wayland_window_set_opaque_region(GdkWindow * window,cairo_region_t * region)4686 gdk_wayland_window_set_opaque_region (GdkWindow      *window,
4687                                       cairo_region_t *region)
4688 {
4689   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4690 
4691   if (GDK_WINDOW_DESTROYED (window))
4692     return;
4693 
4694   g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
4695   impl->opaque_region = cairo_region_reference (region);
4696   impl->opaque_region_dirty = TRUE;
4697 }
4698 
4699 static void
gdk_wayland_window_set_shadow_width(GdkWindow * window,int left,int right,int top,int bottom)4700 gdk_wayland_window_set_shadow_width (GdkWindow *window,
4701                                      int        left,
4702                                      int        right,
4703                                      int        top,
4704                                      int        bottom)
4705 {
4706   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4707   gint new_width, new_height;
4708 
4709   if (GDK_WINDOW_DESTROYED (window))
4710     return;
4711 
4712   /* Reconfigure window to keep the same window geometry */
4713   new_width = (calculate_width_without_margin (window, window->width) +
4714                (left + right));
4715   new_height = (calculate_height_without_margin (window, window->height) +
4716                 (top + bottom));
4717   gdk_wayland_window_maybe_configure (window, new_width, new_height, impl->scale);
4718 
4719   impl->margin_left = left;
4720   impl->margin_right = right;
4721   impl->margin_top = top;
4722   impl->margin_bottom = bottom;
4723 }
4724 
4725 static gboolean
gdk_wayland_window_show_window_menu(GdkWindow * window,GdkEvent * event)4726 gdk_wayland_window_show_window_menu (GdkWindow *window,
4727                                      GdkEvent  *event)
4728 {
4729   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4730   GdkWaylandDisplay *display_wayland =
4731     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4732   struct wl_seat *seat;
4733   GdkWaylandDevice *device;
4734   GdkWindow *event_window;
4735   double x, y;
4736   uint32_t serial;
4737 
4738   switch (event->type)
4739     {
4740     case GDK_BUTTON_PRESS:
4741     case GDK_BUTTON_RELEASE:
4742     case GDK_TOUCH_BEGIN:
4743     case GDK_TOUCH_END:
4744       break;
4745     default:
4746       return FALSE;
4747     }
4748 
4749   if (!is_realized_toplevel (window))
4750     return FALSE;
4751 
4752   device = GDK_WAYLAND_DEVICE (gdk_event_get_device (event));
4753   seat = gdk_wayland_device_get_wl_seat (GDK_DEVICE (device));
4754 
4755   gdk_event_get_coords (event, &x, &y);
4756   event_window = gdk_event_get_window (event);
4757   while (gdk_window_get_window_type (event_window) != GDK_WINDOW_TOPLEVEL)
4758     {
4759       gdk_window_coords_to_parent (event_window, x, y, &x, &y);
4760       event_window = gdk_window_get_effective_parent (event_window);
4761     }
4762 
4763   serial = _gdk_wayland_device_get_implicit_grab_serial (device, event);
4764 
4765   switch (display_wayland->shell_variant)
4766     {
4767     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4768       xdg_toplevel_show_window_menu (impl->display_server.xdg_toplevel,
4769                                      seat, serial, x, y);
4770       break;
4771     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4772       zxdg_toplevel_v6_show_window_menu (impl->display_server.zxdg_toplevel_v6,
4773                                          seat, serial, x, y);
4774       break;
4775     }
4776 
4777   return TRUE;
4778 }
4779 
4780 static void
_gdk_window_impl_wayland_class_init(GdkWindowImplWaylandClass * klass)4781 _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
4782 {
4783   GObjectClass *object_class = G_OBJECT_CLASS (klass);
4784   GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
4785 
4786   object_class->finalize = gdk_window_impl_wayland_finalize;
4787 
4788   impl_class->ref_cairo_surface = gdk_wayland_window_ref_cairo_surface;
4789   impl_class->create_similar_image_surface = gdk_wayland_window_create_similar_image_surface;
4790   impl_class->show = gdk_wayland_window_show;
4791   impl_class->hide = gdk_wayland_window_hide;
4792   impl_class->withdraw = gdk_window_wayland_withdraw;
4793   impl_class->set_events = gdk_window_wayland_set_events;
4794   impl_class->get_events = gdk_window_wayland_get_events;
4795   impl_class->raise = gdk_window_wayland_raise;
4796   impl_class->lower = gdk_window_wayland_lower;
4797   impl_class->restack_under = gdk_window_wayland_restack_under;
4798   impl_class->restack_toplevel = gdk_window_wayland_restack_toplevel;
4799   impl_class->move_resize = gdk_window_wayland_move_resize;
4800   impl_class->move_to_rect = gdk_window_wayland_move_to_rect;
4801   impl_class->set_background = gdk_window_wayland_set_background;
4802   impl_class->reparent = gdk_window_wayland_reparent;
4803   impl_class->set_device_cursor = gdk_window_wayland_set_device_cursor;
4804   impl_class->get_geometry = gdk_window_wayland_get_geometry;
4805   impl_class->get_root_coords = gdk_window_wayland_get_root_coords;
4806   impl_class->get_device_state = gdk_window_wayland_get_device_state;
4807   impl_class->shape_combine_region = gdk_window_wayland_shape_combine_region;
4808   impl_class->input_shape_combine_region = gdk_window_wayland_input_shape_combine_region;
4809   impl_class->destroy = gdk_wayland_window_destroy;
4810   impl_class->destroy_foreign = gdk_window_wayland_destroy_foreign;
4811   impl_class->get_shape = gdk_wayland_window_get_shape;
4812   impl_class->get_input_shape = gdk_wayland_window_get_input_shape;
4813   impl_class->begin_paint = gdk_window_impl_wayland_begin_paint;
4814   impl_class->end_paint = gdk_window_impl_wayland_end_paint;
4815   impl_class->beep = gdk_window_impl_wayland_beep;
4816 
4817   impl_class->focus = gdk_wayland_window_focus;
4818   impl_class->set_type_hint = gdk_wayland_window_set_type_hint;
4819   impl_class->get_type_hint = gdk_wayland_window_get_type_hint;
4820   impl_class->set_modal_hint = gdk_wayland_window_set_modal_hint;
4821   impl_class->set_skip_taskbar_hint = gdk_wayland_window_set_skip_taskbar_hint;
4822   impl_class->set_skip_pager_hint = gdk_wayland_window_set_skip_pager_hint;
4823   impl_class->set_urgency_hint = gdk_wayland_window_set_urgency_hint;
4824   impl_class->set_geometry_hints = gdk_wayland_window_set_geometry_hints;
4825   impl_class->set_title = gdk_wayland_window_set_title;
4826   impl_class->set_role = gdk_wayland_window_set_role;
4827   impl_class->set_startup_id = gdk_wayland_window_set_startup_id;
4828   impl_class->set_transient_for = gdk_wayland_window_set_transient_for;
4829   impl_class->get_frame_extents = gdk_wayland_window_get_frame_extents;
4830   impl_class->set_override_redirect = gdk_wayland_window_set_override_redirect;
4831   impl_class->set_accept_focus = gdk_wayland_window_set_accept_focus;
4832   impl_class->set_focus_on_map = gdk_wayland_window_set_focus_on_map;
4833   impl_class->set_icon_list = gdk_wayland_window_set_icon_list;
4834   impl_class->set_icon_name = gdk_wayland_window_set_icon_name;
4835   impl_class->iconify = gdk_wayland_window_iconify;
4836   impl_class->deiconify = gdk_wayland_window_deiconify;
4837   impl_class->stick = gdk_wayland_window_stick;
4838   impl_class->unstick = gdk_wayland_window_unstick;
4839   impl_class->maximize = gdk_wayland_window_maximize;
4840   impl_class->unmaximize = gdk_wayland_window_unmaximize;
4841   impl_class->fullscreen = gdk_wayland_window_fullscreen;
4842   impl_class->fullscreen_on_monitor = gdk_wayland_window_fullscreen_on_monitor;
4843   impl_class->unfullscreen = gdk_wayland_window_unfullscreen;
4844   impl_class->set_keep_above = gdk_wayland_window_set_keep_above;
4845   impl_class->set_keep_below = gdk_wayland_window_set_keep_below;
4846   impl_class->get_group = gdk_wayland_window_get_group;
4847   impl_class->set_group = gdk_wayland_window_set_group;
4848   impl_class->set_decorations = gdk_wayland_window_set_decorations;
4849   impl_class->get_decorations = gdk_wayland_window_get_decorations;
4850   impl_class->set_functions = gdk_wayland_window_set_functions;
4851   impl_class->begin_resize_drag = gdk_wayland_window_begin_resize_drag;
4852   impl_class->begin_move_drag = gdk_wayland_window_begin_move_drag;
4853   impl_class->set_opacity = gdk_wayland_window_set_opacity;
4854   impl_class->set_composited = gdk_wayland_window_set_composited;
4855   impl_class->destroy_notify = gdk_wayland_window_destroy_notify;
4856   impl_class->get_drag_protocol = _gdk_wayland_window_get_drag_protocol;
4857   impl_class->register_dnd = _gdk_wayland_window_register_dnd;
4858   impl_class->drag_begin = _gdk_wayland_window_drag_begin;
4859   impl_class->sync_rendering = gdk_wayland_window_sync_rendering;
4860   impl_class->simulate_key = gdk_wayland_window_simulate_key;
4861   impl_class->simulate_button = gdk_wayland_window_simulate_button;
4862   impl_class->get_property = gdk_wayland_window_get_property;
4863   impl_class->change_property = gdk_wayland_window_change_property;
4864   impl_class->delete_property = gdk_wayland_window_delete_property;
4865   impl_class->get_scale_factor = gdk_wayland_window_get_scale_factor;
4866   impl_class->set_opaque_region = gdk_wayland_window_set_opaque_region;
4867   impl_class->set_shadow_width = gdk_wayland_window_set_shadow_width;
4868   impl_class->show_window_menu = gdk_wayland_window_show_window_menu;
4869   impl_class->create_gl_context = gdk_wayland_window_create_gl_context;
4870   impl_class->invalidate_for_new_frame = gdk_wayland_window_invalidate_for_new_frame;
4871 
4872   signals[COMMITTED] = g_signal_new ("committed",
4873                                      G_TYPE_FROM_CLASS (object_class),
4874                                      G_SIGNAL_RUN_LAST,
4875                                      0,
4876                                      NULL, NULL, NULL,
4877                                      G_TYPE_NONE, 0);
4878 }
4879 
4880 void
_gdk_wayland_window_set_grab_seat(GdkWindow * window,GdkSeat * seat)4881 _gdk_wayland_window_set_grab_seat (GdkWindow *window,
4882                                    GdkSeat   *seat)
4883 {
4884   GdkWindowImplWayland *impl;
4885 
4886   g_return_if_fail (window != NULL);
4887 
4888   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4889   impl->grab_input_seat = seat;
4890 }
4891 
4892 /**
4893  * gdk_wayland_window_get_wl_surface:
4894  * @window: (type GdkWaylandWindow): a #GdkWindow
4895  *
4896  * Returns the Wayland surface of a #GdkWindow.
4897  *
4898  * Returns: (transfer none): a Wayland wl_surface
4899  *
4900  * Since: 3.8
4901  */
4902 struct wl_surface *
gdk_wayland_window_get_wl_surface(GdkWindow * window)4903 gdk_wayland_window_get_wl_surface (GdkWindow *window)
4904 {
4905   g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
4906 
4907   return GDK_WINDOW_IMPL_WAYLAND (window->impl)->display_server.wl_surface;
4908 }
4909 
4910 struct wl_output *
gdk_wayland_window_get_wl_output(GdkWindow * window)4911 gdk_wayland_window_get_wl_output (GdkWindow *window)
4912 {
4913   GdkWindowImplWayland *impl;
4914 
4915   g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
4916 
4917   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4918   /* We pick the head of the list as this is the last entered output */
4919   if (impl->display_server.outputs)
4920     return (struct wl_output *) impl->display_server.outputs->data;
4921 
4922   return NULL;
4923 }
4924 
4925 static struct wl_egl_window *
gdk_wayland_window_get_wl_egl_window(GdkWindow * window)4926 gdk_wayland_window_get_wl_egl_window (GdkWindow *window)
4927 {
4928   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4929 
4930   if (impl->display_server.egl_window == NULL)
4931     {
4932       impl->display_server.egl_window =
4933         wl_egl_window_create (impl->display_server.wl_surface,
4934                               impl->wrapper->width * impl->scale,
4935                               impl->wrapper->height * impl->scale);
4936       wl_surface_set_buffer_scale (impl->display_server.wl_surface, impl->scale);
4937     }
4938 
4939   return impl->display_server.egl_window;
4940 }
4941 
4942 EGLSurface
gdk_wayland_window_get_egl_surface(GdkWindow * window,EGLConfig config)4943 gdk_wayland_window_get_egl_surface (GdkWindow *window,
4944                                     EGLConfig  config)
4945 {
4946   GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4947   GdkWindowImplWayland *impl;
4948   struct wl_egl_window *egl_window;
4949 
4950   g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
4951 
4952   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4953 
4954   if (impl->egl_surface == NULL)
4955     {
4956       egl_window = gdk_wayland_window_get_wl_egl_window (window);
4957 
4958       impl->egl_surface =
4959         eglCreateWindowSurface (display->egl_display, config, egl_window, NULL);
4960     }
4961 
4962   return impl->egl_surface;
4963 }
4964 
4965 EGLSurface
gdk_wayland_window_get_dummy_egl_surface(GdkWindow * window,EGLConfig config)4966 gdk_wayland_window_get_dummy_egl_surface (GdkWindow *window,
4967                                           EGLConfig  config)
4968 {
4969   GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
4970   GdkWindowImplWayland *impl;
4971 
4972   g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
4973 
4974   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
4975 
4976   if (impl->dummy_egl_surface == NULL)
4977     {
4978       impl->display_server.dummy_egl_window =
4979         wl_egl_window_create (impl->display_server.wl_surface, 1, 1);
4980 
4981       impl->dummy_egl_surface =
4982         eglCreateWindowSurface (display->egl_display, config, impl->display_server.dummy_egl_window, NULL);
4983     }
4984 
4985   return impl->dummy_egl_surface;
4986 }
4987 
4988 struct gtk_surface1 *
gdk_wayland_window_get_gtk_surface(GdkWindow * window)4989 gdk_wayland_window_get_gtk_surface (GdkWindow *window)
4990 {
4991   g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
4992 
4993   return GDK_WINDOW_IMPL_WAYLAND (window->impl)->display_server.gtk_surface;
4994 }
4995 
4996 /**
4997  * gdk_wayland_window_set_use_custom_surface:
4998  * @window: (type GdkWaylandWindow): a #GdkWindow
4999  *
5000  * Marks a #GdkWindow as a custom Wayland surface. The application is
5001  * expected to register the surface as some type of surface using
5002  * some Wayland interface.
5003  *
5004  * A good example would be writing a panel or on-screen-keyboard as an
5005  * out-of-process helper - as opposed to having those in the compositor
5006  * process. In this case the underlying surface isn’t an xdg_shell
5007  * surface and the panel or OSK client need to identify the wl_surface
5008  * as a panel or OSK to the compositor. The assumption is that the
5009  * compositor will expose a private interface to the special client
5010  * that lets the client identify the wl_surface as a panel or such.
5011  *
5012  * This function should be called before a #GdkWindow is shown. This is
5013  * best done by connecting to the #GtkWidget::realize signal:
5014  *
5015  * |[<!-- language="C" -->
5016  *   static void
5017  *   widget_realize_cb (GtkWidget *widget)
5018  *   {
5019  *     GdkWindow *window;
5020  *     struct wl_surface *surface;
5021  *     struct input_panel_surface *ip_surface;
5022  *
5023  *     window = gtk_widget_get_window (widget);
5024  *     gdk_wayland_window_set_custom_surface (window);
5025  *
5026  *     surface = gdk_wayland_window_get_wl_surface (window);
5027  *     ip_surface = input_panel_get_input_panel_surface (input_panel, surface);
5028  *     input_panel_surface_set_panel (ip_surface);
5029  *   }
5030  *
5031  *   static void
5032  *   setup_window (GtkWindow *window)
5033  *   {
5034  *     g_signal_connect (window, "realize", G_CALLBACK (widget_realize_cb), NULL);
5035  *   }
5036  * ]|
5037  *
5038  * Since: 3.10
5039  */
5040 void
gdk_wayland_window_set_use_custom_surface(GdkWindow * window)5041 gdk_wayland_window_set_use_custom_surface (GdkWindow *window)
5042 {
5043   GdkWindowImplWayland *impl;
5044 
5045   g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
5046 
5047   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5048 
5049   if (!impl->display_server.wl_surface)
5050     gdk_wayland_window_create_surface (window);
5051 
5052   impl->use_custom_surface = TRUE;
5053 }
5054 
5055 static void
maybe_set_gtk_surface_dbus_properties(GdkWindow * window)5056 maybe_set_gtk_surface_dbus_properties (GdkWindow *window)
5057 {
5058   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5059 
5060   if (impl->application.was_set)
5061     return;
5062 
5063   if (impl->application.application_id == NULL &&
5064       impl->application.app_menu_path == NULL &&
5065       impl->application.menubar_path == NULL &&
5066       impl->application.window_object_path == NULL &&
5067       impl->application.application_object_path == NULL &&
5068       impl->application.unique_bus_name == NULL)
5069     return;
5070 
5071   gdk_wayland_window_init_gtk_surface (window);
5072   if (impl->display_server.gtk_surface == NULL)
5073     return;
5074 
5075   gtk_surface1_set_dbus_properties (impl->display_server.gtk_surface,
5076                                     impl->application.application_id,
5077                                     impl->application.app_menu_path,
5078                                     impl->application.menubar_path,
5079                                     impl->application.window_object_path,
5080                                     impl->application.application_object_path,
5081                                     impl->application.unique_bus_name);
5082   impl->application.was_set = TRUE;
5083 }
5084 
5085 void
gdk_wayland_window_set_dbus_properties_libgtk_only(GdkWindow * window,const char * application_id,const char * app_menu_path,const char * menubar_path,const char * window_object_path,const char * application_object_path,const char * unique_bus_name)5086 gdk_wayland_window_set_dbus_properties_libgtk_only (GdkWindow  *window,
5087                                                     const char *application_id,
5088                                                     const char *app_menu_path,
5089                                                     const char *menubar_path,
5090                                                     const char *window_object_path,
5091                                                     const char *application_object_path,
5092                                                     const char *unique_bus_name)
5093 {
5094   GdkWindowImplWayland *impl;
5095 
5096   g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
5097 
5098   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5099 
5100   impl->application.application_id = g_strdup (application_id);
5101   impl->application.app_menu_path = g_strdup (app_menu_path);
5102   impl->application.menubar_path = g_strdup (menubar_path);
5103   impl->application.window_object_path = g_strdup (window_object_path);
5104   impl->application.application_object_path =
5105     g_strdup (application_object_path);
5106   impl->application.unique_bus_name = g_strdup (unique_bus_name);
5107 
5108   maybe_set_gtk_surface_dbus_properties (window);
5109 }
5110 
5111 void
_gdk_wayland_window_offset_next_wl_buffer(GdkWindow * window,int x,int y)5112 _gdk_wayland_window_offset_next_wl_buffer (GdkWindow *window,
5113                                            int        x,
5114                                            int        y)
5115 {
5116   GdkWindowImplWayland *impl;
5117 
5118   g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
5119 
5120   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5121 
5122   impl->pending_buffer_offset_x = x;
5123   impl->pending_buffer_offset_y = y;
5124 }
5125 
5126 static void
invoke_exported_closures(GdkWindow * window)5127 invoke_exported_closures (GdkWindow *window)
5128 {
5129   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5130   GList *l;
5131 
5132   for (l = impl->exported.closures; l; l = l->next)
5133     {
5134       ExportedClosure *closure = l->data;
5135 
5136       closure->callback (window, impl->exported.handle, closure->user_data);
5137 
5138       if (closure->destroy_func)
5139         closure->destroy_func (closure->user_data);
5140     }
5141 
5142   g_list_free_full (impl->exported.closures, g_free);
5143   impl->exported.closures = NULL;
5144 }
5145 
5146 static void
xdg_exported_handle(void * data,struct zxdg_exported_v1 * zxdg_exported_v1,const char * handle)5147 xdg_exported_handle (void                    *data,
5148                      struct zxdg_exported_v1 *zxdg_exported_v1,
5149                      const char              *handle)
5150 {
5151   GdkWindow *window = data;
5152   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5153 
5154   impl->exported.handle = g_strdup (handle);
5155 
5156   invoke_exported_closures (window);
5157 }
5158 
5159 static const struct zxdg_exported_v1_listener xdg_exported_listener = {
5160   xdg_exported_handle
5161 };
5162 
5163 /**
5164  * GdkWaylandWindowExported:
5165  * @window: the #GdkWindow that is exported
5166  * @handle: the handle
5167  * @user_data: user data that was passed to gdk_wayland_window_export_handle()
5168  *
5169  * Callback that gets called when the handle for a window has been
5170  * obtained from the Wayland compositor. The handle can be passed
5171  * to other processes, for the purpose of marking windows as transient
5172  * for out-of-process surfaces.
5173  *
5174  * Since: 3.22
5175  */
5176 
5177 static gboolean
gdk_wayland_window_is_exported(GdkWindow * window)5178 gdk_wayland_window_is_exported (GdkWindow *window)
5179 {
5180   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5181 
5182   return !!impl->display_server.xdg_exported;
5183 }
5184 
5185 static gboolean
exported_idle(gpointer user_data)5186 exported_idle (gpointer user_data)
5187 {
5188   GdkWindow *window = user_data;
5189   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5190 
5191   invoke_exported_closures (window);
5192 
5193   impl->exported.idle_source_id = 0;
5194 
5195   return G_SOURCE_REMOVE;
5196 }
5197 
5198 /**
5199  * gdk_wayland_window_export_handle:
5200  * @window: the #GdkWindow to obtain a handle for
5201  * @callback: callback to call with the handle
5202  * @user_data: user data for @callback
5203  * @destroy_func: destroy notify for @user_data
5204  *
5205  * Asynchronously obtains a handle for a surface that can be passed
5206  * to other processes. When the handle has been obtained, @callback
5207  * will be called.
5208  *
5209  * Up until 3.22.15 it was an error to call this function on a window that is
5210  * already exported. When the handle is no longer needed,
5211  * gdk_wayland_window_unexport_handle() should be called to clean up resources.
5212  *
5213  * Starting with 3.22.16, calling this function on an already exported window
5214  * will cause the callback to be invoked with the same handle as was already
5215  * invoked, from an idle callback. To unexport the window,
5216  * gdk_wayland_window_unexport_handle() must be called the same number of times
5217  * as gdk_wayland_window_export_handle() was called. Any 'exported' callback
5218  * may still be invoked until the window is unexported or destroyed.
5219  *
5220  * The main purpose for obtaining a handle is to mark a surface
5221  * from another window as transient for this one, see
5222  * gdk_wayland_window_set_transient_for_exported().
5223  *
5224  * Note that this API depends on an unstable Wayland protocol,
5225  * and thus may require changes in the future.
5226  *
5227  * Return value: %TRUE if the handle has been requested, %FALSE if
5228  *     an error occurred.
5229  *
5230  * Since: 3.22
5231  */
5232 gboolean
gdk_wayland_window_export_handle(GdkWindow * window,GdkWaylandWindowExported callback,gpointer user_data,GDestroyNotify destroy_func)5233 gdk_wayland_window_export_handle (GdkWindow                *window,
5234                                   GdkWaylandWindowExported  callback,
5235                                   gpointer                  user_data,
5236                                   GDestroyNotify            destroy_func)
5237 {
5238   GdkWindowImplWayland *impl;
5239   GdkWaylandDisplay *display_wayland;
5240   GdkDisplay *display = gdk_window_get_display (window);
5241   ExportedClosure *closure;
5242 
5243   g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), FALSE);
5244   g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
5245 
5246   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5247   display_wayland = GDK_WAYLAND_DISPLAY (display);
5248 
5249   if (!display_wayland->xdg_exporter)
5250     {
5251       g_warning ("Server is missing xdg_foreign support");
5252       return FALSE;
5253     }
5254 
5255   if (!impl->display_server.xdg_exported)
5256     {
5257       struct zxdg_exported_v1 *xdg_exported;
5258 
5259       xdg_exported = zxdg_exporter_v1_export (display_wayland->xdg_exporter,
5260                                               impl->display_server.wl_surface);
5261       zxdg_exported_v1_add_listener (xdg_exported,
5262                                      &xdg_exported_listener,
5263                                      window);
5264 
5265       impl->display_server.xdg_exported = xdg_exported;
5266     }
5267 
5268   closure = g_new0 (ExportedClosure, 1);
5269   closure->callback = callback;
5270   closure->user_data = user_data;
5271   closure->destroy_func = destroy_func;
5272 
5273   impl->exported.closures = g_list_append (impl->exported.closures, closure);
5274   impl->exported.export_count++;
5275 
5276   if (impl->exported.handle && !impl->exported.idle_source_id)
5277     impl->exported.idle_source_id = g_idle_add (exported_idle, window);
5278 
5279   return TRUE;
5280 }
5281 
5282 static void
gdk_wayland_window_unexport(GdkWindow * window)5283 gdk_wayland_window_unexport (GdkWindow *window)
5284 {
5285   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5286   GList *l;
5287 
5288   g_clear_pointer (&impl->display_server.xdg_exported,
5289                    zxdg_exported_v1_destroy);
5290 
5291   for (l = impl->exported.closures; l; l = l->next)
5292     {
5293       ExportedClosure *closure = l->data;
5294 
5295       if (closure->destroy_func)
5296         closure->destroy_func (closure->user_data);
5297     }
5298 
5299   g_list_free_full (impl->exported.closures, g_free);
5300   impl->exported.closures = NULL;
5301   g_clear_pointer (&impl->exported.handle, g_free);
5302 
5303   if (impl->exported.idle_source_id)
5304     {
5305       g_source_remove (impl->exported.idle_source_id);
5306       impl->exported.idle_source_id = 0;
5307     }
5308 }
5309 
5310 /**
5311  * gdk_wayland_window_unexport_handle:
5312  * @window: the #GdkWindow to unexport
5313  *
5314  * Destroys the handle that was obtained with
5315  * gdk_wayland_window_export_handle().
5316  *
5317  * It is an error to call this function on a window that
5318  * does not have a handle.
5319  *
5320  * Note that this API depends on an unstable Wayland protocol,
5321  * and thus may require changes in the future.
5322  *
5323  * Since: 3.22
5324  */
5325 void
gdk_wayland_window_unexport_handle(GdkWindow * window)5326 gdk_wayland_window_unexport_handle (GdkWindow *window)
5327 {
5328   GdkWindowImplWayland *impl;
5329 
5330   g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
5331 
5332   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5333 
5334   g_return_if_fail (impl->display_server.xdg_exported);
5335 
5336   impl->exported.export_count--;
5337   if (impl->exported.export_count == 0)
5338     gdk_wayland_window_unexport (window);
5339 }
5340 
5341 static void
unset_transient_for_exported(GdkWindow * window)5342 unset_transient_for_exported (GdkWindow *window)
5343 {
5344   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5345 
5346   g_clear_pointer (&impl->imported_transient_for, zxdg_imported_v1_destroy);
5347 }
5348 
5349 static void
xdg_imported_destroyed(void * data,struct zxdg_imported_v1 * zxdg_imported_v1)5350 xdg_imported_destroyed (void                    *data,
5351                         struct zxdg_imported_v1 *zxdg_imported_v1)
5352 {
5353   GdkWindow *window = data;
5354 
5355   unset_transient_for_exported (window);
5356 }
5357 
5358 static const struct zxdg_imported_v1_listener xdg_imported_listener = {
5359   xdg_imported_destroyed,
5360 };
5361 
5362 /**
5363  * gdk_wayland_window_set_transient_for_exported:
5364  * @window: the #GdkWindow to make as transient
5365  * @parent_handle_str: an exported handle for a surface
5366  *
5367  * Marks @window as transient for the surface to which the given
5368  * @parent_handle_str refers. Typically, the handle will originate
5369  * from a gdk_wayland_window_export_handle() call in another process.
5370  *
5371  * Note that this API depends on an unstable Wayland protocol,
5372  * and thus may require changes in the future.
5373  *
5374  * Return value: %TRUE if the window has been marked as transient,
5375  *     %FALSE if an error occurred.
5376  *
5377  * Since: 3.22
5378  */
5379 gboolean
gdk_wayland_window_set_transient_for_exported(GdkWindow * window,char * parent_handle_str)5380 gdk_wayland_window_set_transient_for_exported (GdkWindow *window,
5381                                                char      *parent_handle_str)
5382 {
5383   GdkWindowImplWayland *impl;
5384   GdkWaylandDisplay *display_wayland;
5385   GdkDisplay *display = gdk_window_get_display (window);
5386 
5387   g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), FALSE);
5388   g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
5389   g_return_val_if_fail (!should_map_as_subsurface (window) &&
5390                         !should_map_as_popup (window), FALSE);
5391 
5392   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5393   display_wayland = GDK_WAYLAND_DISPLAY (display);
5394 
5395   if (!display_wayland->xdg_importer)
5396     {
5397       g_warning ("Server is missing xdg_foreign support");
5398       return FALSE;
5399     }
5400 
5401   gdk_window_set_transient_for (window, NULL);
5402 
5403   impl->imported_transient_for =
5404     zxdg_importer_v1_import (display_wayland->xdg_importer, parent_handle_str);
5405   zxdg_imported_v1_add_listener (impl->imported_transient_for,
5406                                  &xdg_imported_listener,
5407                                  window);
5408 
5409   gdk_wayland_window_sync_parent_of_imported (window);
5410 
5411   return TRUE;
5412 }
5413 
5414 static struct zwp_keyboard_shortcuts_inhibitor_v1 *
gdk_wayland_window_get_inhibitor(GdkWindowImplWayland * impl,struct wl_seat * seat)5415 gdk_wayland_window_get_inhibitor (GdkWindowImplWayland *impl,
5416                                   struct wl_seat *seat)
5417 {
5418   return g_hash_table_lookup (impl->shortcuts_inhibitors, seat);
5419 }
5420 
5421 void
gdk_wayland_window_inhibit_shortcuts(GdkWindow * window,GdkSeat * gdk_seat)5422 gdk_wayland_window_inhibit_shortcuts (GdkWindow *window,
5423                                       GdkSeat   *gdk_seat)
5424 {
5425   GdkWindowImplWayland *impl= GDK_WINDOW_IMPL_WAYLAND (window->impl);
5426   GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
5427   struct wl_surface *surface = impl->display_server.wl_surface;
5428   struct wl_seat *seat = gdk_wayland_seat_get_wl_seat (gdk_seat);
5429   struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
5430 
5431   if (display->keyboard_shortcuts_inhibit == NULL)
5432     return;
5433 
5434   if (gdk_wayland_window_get_inhibitor (impl, seat))
5435     return; /* Already inhibitted */
5436 
5437   inhibitor =
5438       zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts (
5439           display->keyboard_shortcuts_inhibit, surface, seat);
5440 
5441   g_hash_table_insert (impl->shortcuts_inhibitors, seat, inhibitor);
5442 }
5443 
5444 void
gdk_wayland_window_restore_shortcuts(GdkWindow * window,GdkSeat * gdk_seat)5445 gdk_wayland_window_restore_shortcuts (GdkWindow *window,
5446                                       GdkSeat   *gdk_seat)
5447 {
5448   GdkWindowImplWayland *impl;
5449   struct wl_seat *seat;
5450   struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
5451 
5452   g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
5453   g_return_if_fail (GDK_IS_WINDOW_IMPL_WAYLAND (window->impl));
5454 
5455   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5456   seat = gdk_wayland_seat_get_wl_seat (gdk_seat);
5457 
5458   inhibitor = gdk_wayland_window_get_inhibitor (impl, seat);
5459   if (inhibitor == NULL)
5460     return; /* Not inhibitted */
5461 
5462   zwp_keyboard_shortcuts_inhibitor_v1_destroy (inhibitor);
5463   g_hash_table_remove (impl->shortcuts_inhibitors, seat);
5464 }
5465 
5466 /**
5467  * gdk_wayland_window_add_frame_callback_surface:
5468  * @window: the #GdkWindow requesting callbacks
5469  * @surface: the wl_surface to add
5470  *
5471  * Add @surface to a list of surfaces for which frame callback
5472  * listeners will get set up, additionally to the one of @window.
5473  *
5474  * This is useful when clients use subsurfaces independently of GDK.
5475  * For example if a client creates a subsurface that covers @window
5476  * entirely. If this subsurface is opaque, Wayland compositors may not
5477  * emit callbacks for the surface of @window any more.
5478  * Adding the covering subsurface via this function ensures the
5479  * @window will continue to update.
5480  *
5481  * A single callback is sufficient to trigger the next update. If more
5482  * than one are triggered, the later ones will get ignored.
5483  *
5484  * Before @surface gets destroyed it must get removed again using
5485  * gdk_wayland_window_remove_frame_callback_surface().
5486  *
5487  * Note that the client is responsible to commit the @surface.
5488  * One way to archive this is to always commit after the
5489  * #GdkSurface::after-paint signal was triggered.
5490  *
5491  * Since: 3.24.25
5492  */
5493 void
gdk_wayland_window_add_frame_callback_surface(GdkWindow * window,struct wl_surface * surface)5494 gdk_wayland_window_add_frame_callback_surface (GdkWindow         *window,
5495                                                struct wl_surface *surface)
5496 {
5497   GdkWindowImplWayland *impl;
5498 
5499   g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
5500   g_return_if_fail (GDK_IS_WINDOW_IMPL_WAYLAND (window->impl));
5501   g_return_if_fail (surface != NULL);
5502 
5503   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5504 
5505   g_hash_table_insert (impl->frame_callback_surfaces, surface, NULL);
5506 }
5507 
5508 /**
5509  * gdk_wayland_window_remove_frame_callback_surface:
5510  * @window: the #GdkWindow requesting callbacks
5511  * @surface: the surface to remove
5512  *
5513  * Remove @surface from the list of surfaces again that got added via
5514  * gdk_wayland_window_add_frame_callback_surface().
5515  *
5516  * This function must be called before @surface gets destroyed.
5517  *
5518  * Since: 3.24.25
5519  */
5520 void
gdk_wayland_window_remove_frame_callback_surface(GdkWindow * window,struct wl_surface * surface)5521 gdk_wayland_window_remove_frame_callback_surface (GdkWindow         *window,
5522                                                   struct wl_surface *surface)
5523 {
5524   GdkWindowImplWayland *impl;
5525 
5526   g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
5527   g_return_if_fail (GDK_IS_WINDOW_IMPL_WAYLAND (window->impl));
5528   g_return_if_fail (surface != NULL);
5529 
5530   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
5531 
5532   g_hash_table_remove (impl->frame_callback_surfaces, surface);
5533 }
5534