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 "gdksurface-wayland.h"
21 
22 #include "gdkdeviceprivate.h"
23 #include "gdkdisplay-wayland.h"
24 #include "gdkdragsurfaceprivate.h"
25 #include "gdkframeclockidleprivate.h"
26 #include "gdkglcontext-wayland.h"
27 #include "gdkmonitor-wayland.h"
28 #include "gdkpopupprivate.h"
29 #include "gdkprivate-wayland.h"
30 #include "gdkprivate-wayland.h"
31 #include "gdkseat-wayland.h"
32 #include "gdksurfaceprivate.h"
33 #include "gdktoplevelprivate.h"
34 #include "gdkdevice-wayland-private.h"
35 
36 #include <wayland/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 #include <netinet/in.h>
44 #include <unistd.h>
45 
46 /**
47  * GdkWaylandSurface:
48  *
49  * The Wayland implementation of `GdkSurface`.
50  *
51  * Beyond the [class@Gdk.Surface] API, the Wayland implementation offers
52  * access to the Wayland `wl_surface` object with
53  * [method@GdkWayland.WaylandSurface.get_wl_surface].
54  */
55 
56 /**
57  * GdkWaylandToplevel:
58  *
59  * The Wayland implementation of `GdkToplevel`.
60  *
61  * Beyond the [iface@Gdk.Toplevel] API, the Wayland implementation
62  * has API to set up cross-process parent-child relationships between
63  * surfaces with [method@GdkWayland.WaylandToplevel.export_handle] and
64  * [method@GdkWayland.WaylandToplevel.set_transient_for_exported].
65  */
66 
67 /**
68  * GdkWaylandPopup:
69  *
70  * The Wayland implementation of `GdkPopup`.
71  */
72 
73 #define SURFACE_IS_TOPLEVEL(surface)  TRUE
74 
75 #define MAX_WL_BUFFER_SIZE (4083) /* 4096 minus header, string argument length and NUL byte */
76 
77 typedef enum _PopupState
78 {
79   POPUP_STATE_IDLE,
80   POPUP_STATE_WAITING_FOR_REPOSITIONED,
81   POPUP_STATE_WAITING_FOR_CONFIGURE,
82   POPUP_STATE_WAITING_FOR_FRAME,
83 } PopupState;
84 
85 struct _GdkWaylandSurface
86 {
87   GdkSurface parent_instance;
88 
89   struct {
90     /* The wl_outputs that this surface currently touches */
91     GSList               *outputs;
92 
93     struct wl_surface    *wl_surface;
94 
95     struct xdg_surface *xdg_surface;
96     struct xdg_toplevel *xdg_toplevel;
97     struct xdg_popup *xdg_popup;
98 
99     /* Legacy xdg-shell unstable v6 fallback support */
100     struct zxdg_surface_v6 *zxdg_surface_v6;
101     struct zxdg_toplevel_v6 *zxdg_toplevel_v6;
102     struct zxdg_popup_v6 *zxdg_popup_v6;
103 
104     struct gtk_surface1  *gtk_surface;
105     struct wl_egl_window *egl_window;
106     struct zxdg_exported_v1 *xdg_exported;
107     struct org_kde_kwin_server_decoration *server_decoration;
108   } display_server;
109 
110   struct wl_event_queue *event_queue;
111 
112   EGLSurface egl_surface;
113 
114   uint32_t reposition_token;
115   uint32_t received_reposition_token;
116 
117   PopupState popup_state;
118 
119   unsigned int initial_configure_received : 1;
120   unsigned int has_uncommitted_ack_configure : 1;
121   unsigned int mapped : 1;
122   unsigned int awaiting_frame : 1;
123   unsigned int awaiting_frame_frozen : 1;
124   unsigned int is_drag_surface : 1;
125 
126   int pending_buffer_offset_x;
127   int pending_buffer_offset_y;
128 
129   char *title;
130 
131   struct {
132     gboolean was_set;
133 
134     char *application_id;
135     char *app_menu_path;
136     char *menubar_path;
137     char *window_object_path;
138     char *application_object_path;
139     char *unique_bus_name;
140   } application;
141 
142   GdkGeometry geometry_hints;
143   GdkSurfaceHints geometry_mask;
144 
145   GdkSeat *grab_input_seat;
146 
147   gint64 pending_frame_counter;
148   guint32 scale;
149 
150   int shadow_left;
151   int shadow_right;
152   int shadow_top;
153   int shadow_bottom;
154   gboolean shadow_dirty;
155 
156   struct wl_output *initial_fullscreen_output;
157 
158   cairo_region_t *opaque_region;
159   gboolean opaque_region_dirty;
160 
161   cairo_region_t *input_region;
162   gboolean input_region_dirty;
163 
164   GdkRectangle last_sent_window_geometry;
165   int last_sent_min_width;
166   int last_sent_min_height;
167   int last_sent_max_width;
168   int last_sent_max_height;
169 
170   int saved_width;
171   int saved_height;
172 
173   gulong parent_surface_committed_handler;
174 
175   struct {
176     GdkToplevelLayout *layout;
177   } toplevel;
178 
179   struct {
180     GdkPopupLayout *layout;
181     int unconstrained_width;
182     int unconstrained_height;
183   } popup;
184 
185   struct {
186     struct {
187       int width;
188       int height;
189       GdkToplevelState state;
190       gboolean is_resizing;
191     } toplevel;
192 
193     struct {
194       int x;
195       int y;
196       int width;
197       int height;
198       uint32_t repositioned_token;
199       gboolean has_repositioned_token;
200     } popup;
201 
202     gboolean is_initial_configure;
203 
204     uint32_t serial;
205     gboolean is_dirty;
206   } pending;
207 
208   struct {
209     GdkToplevelState unset_flags;
210     GdkToplevelState set_flags;
211   } initial_state;
212 
213   struct {
214     struct {
215       gboolean should_constrain;
216       gboolean size_is_fixed;
217     } toplevel;
218     struct {
219       int x;
220       int y;
221     } popup;
222     int configured_width;
223     int configured_height;
224     gboolean surface_geometry_dirty;
225   } next_layout;
226 
227   uint32_t last_configure_serial;
228 
229   int state_freeze_count;
230 
231   struct {
232     GdkWaylandToplevelExported callback;
233     gpointer user_data;
234     GDestroyNotify destroy_func;
235   } exported;
236 
237   struct zxdg_imported_v1 *imported_transient_for;
238   GHashTable *shortcuts_inhibitors;
239 
240   struct zwp_idle_inhibitor_v1 *idle_inhibitor;
241   size_t idle_inhibitor_refcount;
242 };
243 
244 typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
245 struct _GdkWaylandSurfaceClass
246 {
247   GdkSurfaceClass parent_class;
248 };
249 
250 G_DEFINE_TYPE (GdkWaylandSurface, gdk_wayland_surface, GDK_TYPE_SURFACE)
251 
252 struct _GdkWaylandToplevel
253 {
254   GdkWaylandSurface parent_instance;
255 
256   GdkWaylandToplevel *transient_for;
257 };
258 
259 typedef struct
260 {
261   GdkWaylandSurfaceClass parent_class;
262 } GdkWaylandToplevelClass;
263 
264 static void gdk_wayland_toplevel_iface_init (GdkToplevelInterface *iface);
265 
266 G_DEFINE_TYPE_WITH_CODE (GdkWaylandToplevel, gdk_wayland_toplevel, GDK_TYPE_WAYLAND_SURFACE,
267                          G_IMPLEMENT_INTERFACE (GDK_TYPE_TOPLEVEL,
268                                                 gdk_wayland_toplevel_iface_init))
269 
270 struct _GdkWaylandPopup
271 {
272   GdkWaylandSurface parent_instance;
273 };
274 
275 typedef struct
276 {
277   GdkWaylandSurfaceClass parent_class;
278 } GdkWaylandPopupClass;
279 
280 static void gdk_wayland_popup_iface_init (GdkPopupInterface *iface);
281 
282 G_DEFINE_TYPE_WITH_CODE (GdkWaylandPopup, gdk_wayland_popup, GDK_TYPE_WAYLAND_SURFACE,
283                          G_IMPLEMENT_INTERFACE (GDK_TYPE_POPUP,
284                                                 gdk_wayland_popup_iface_init))
285 
286 typedef struct
287 {
288   GdkWaylandSurface parent_instance;
289 } GdkWaylandDragSurface;
290 
291 typedef struct
292 {
293   GdkWaylandSurfaceClass parent_class;
294 } GdkWaylandDragSurfaceClass;
295 
296 static void gdk_wayland_drag_surface_iface_init (GdkDragSurfaceInterface *iface);
297 
298 GType gdk_wayland_drag_surface_get_type (void) G_GNUC_CONST;
299 
300 #define GDK_IS_WAYLAND_DRAG_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DRAG_SURFACE))
301 
302 #define GDK_TYPE_WAYLAND_DRAG_SURFACE (gdk_wayland_drag_surface_get_type ())
303 G_DEFINE_TYPE_WITH_CODE (GdkWaylandDragSurface, gdk_wayland_drag_surface, GDK_TYPE_WAYLAND_SURFACE,
304                          G_IMPLEMENT_INTERFACE (GDK_TYPE_DRAG_SURFACE,
305                                                 gdk_wayland_drag_surface_iface_init))
306 
307 static void gdk_wayland_surface_maybe_resize (GdkSurface *surface,
308                                               int         width,
309                                               int         height,
310                                               int         scale);
311 
312 static void gdk_wayland_surface_configure (GdkSurface *surface);
313 
314 static void maybe_set_gtk_surface_dbus_properties (GdkWaylandSurface *impl);
315 static void maybe_set_gtk_surface_modal (GdkSurface *surface);
316 
317 static void gdk_wayland_surface_sync_shadow (GdkSurface *surface);
318 static void gdk_wayland_surface_sync_input_region (GdkSurface *surface);
319 static void gdk_wayland_surface_sync_opaque_region (GdkSurface *surface);
320 
321 static void unset_transient_for_exported (GdkSurface *surface);
322 
323 static void gdk_wayland_surface_move_resize (GdkSurface *surface,
324                                              int         x,
325                                              int         y,
326                                              int         width,
327                                              int         height);
328 
329 static void update_popup_layout_state (GdkSurface     *surface,
330                                        int             x,
331                                        int             y,
332                                        int             width,
333                                        int             height,
334                                        GdkPopupLayout *layout);
335 
336 static gboolean gdk_wayland_surface_is_exported (GdkWaylandSurface *impl);
337 
338 static void configure_toplevel_geometry (GdkSurface *surface);
339 
340 static void
gdk_wayland_surface_init(GdkWaylandSurface * impl)341 gdk_wayland_surface_init (GdkWaylandSurface *impl)
342 {
343   impl->scale = 1;
344   impl->initial_fullscreen_output = NULL;
345   impl->saved_width = -1;
346   impl->saved_height = -1;
347   impl->shortcuts_inhibitors = g_hash_table_new (NULL, NULL);
348 }
349 
350 static void
gdk_wayland_surface_freeze_state(GdkSurface * surface)351 gdk_wayland_surface_freeze_state (GdkSurface *surface)
352 {
353   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
354 
355   impl->state_freeze_count++;
356 }
357 
358 static void
gdk_wayland_surface_thaw_state(GdkSurface * surface)359 gdk_wayland_surface_thaw_state (GdkSurface *surface)
360 {
361   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
362 
363   g_assert (impl->state_freeze_count > 0);
364 
365   impl->state_freeze_count--;
366 
367   if (impl->state_freeze_count > 0)
368     return;
369 
370   if (impl->pending.is_dirty)
371     gdk_wayland_surface_configure (surface);
372 
373   g_assert (!impl->display_server.xdg_popup);
374 }
375 
376 static void
_gdk_wayland_surface_save_size(GdkSurface * surface)377 _gdk_wayland_surface_save_size (GdkSurface *surface)
378 {
379   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
380 
381   if (surface->state & (GDK_TOPLEVEL_STATE_FULLSCREEN |
382                         GDK_TOPLEVEL_STATE_MAXIMIZED |
383                         GDK_TOPLEVEL_STATE_TILED))
384     return;
385 
386   if (surface->width <= 1 || surface->height <= 1)
387     return;
388 
389   impl->saved_width = surface->width - impl->shadow_left - impl->shadow_right;
390   impl->saved_height = surface->height - impl->shadow_top - impl->shadow_bottom;
391 }
392 
393 static void
_gdk_wayland_surface_clear_saved_size(GdkSurface * surface)394 _gdk_wayland_surface_clear_saved_size (GdkSurface *surface)
395 {
396   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
397 
398   if (surface->state & (GDK_TOPLEVEL_STATE_FULLSCREEN | GDK_TOPLEVEL_STATE_MAXIMIZED))
399     return;
400 
401   impl->saved_width = -1;
402   impl->saved_height = -1;
403 }
404 
405 static void
gdk_wayland_surface_update_size(GdkSurface * surface,int32_t width,int32_t height,int scale)406 gdk_wayland_surface_update_size (GdkSurface *surface,
407                                  int32_t     width,
408                                  int32_t     height,
409                                  int         scale)
410 {
411   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
412   gboolean width_changed, height_changed, scale_changed;
413 
414   width_changed = surface->width != width;
415   height_changed = surface->height != height;
416   scale_changed = impl->scale != scale;
417 
418   if (!width_changed && !height_changed && !scale_changed)
419     return;
420 
421   surface->width = width;
422   surface->height = height;
423   impl->scale = scale;
424 
425   if (impl->display_server.egl_window)
426     wl_egl_window_resize (impl->display_server.egl_window, width * scale, height * scale, 0, 0);
427   if (impl->display_server.wl_surface)
428     wl_surface_set_buffer_scale (impl->display_server.wl_surface, scale);
429 
430   gdk_surface_invalidate_rect (surface, NULL);
431 
432   if (width_changed)
433     g_object_notify (G_OBJECT (surface), "width");
434   if (height_changed)
435     g_object_notify (G_OBJECT (surface), "height");
436   if (scale_changed)
437     g_object_notify (G_OBJECT (surface), "scale-factor");
438 
439   _gdk_surface_update_size (surface);
440 }
441 
442 static const char *
get_default_title(void)443 get_default_title (void)
444 {
445   const char *title;
446 
447   title = g_get_application_name ();
448   if (!title)
449     title = g_get_prgname ();
450   if (!title)
451     title = "";
452 
453   return title;
454 }
455 
456 static void
fill_presentation_time_from_frame_time(GdkFrameTimings * timings,guint32 frame_time)457 fill_presentation_time_from_frame_time (GdkFrameTimings *timings,
458                                         guint32          frame_time)
459 {
460   /* The timestamp in a wayland frame is a msec time value that in some
461    * way reflects the time at which the server started drawing the frame.
462    * This is not useful from our perspective.
463    *
464    * However, for the DRM backend of Weston, on reasonably recent
465    * Linux, we know that the time is the
466    * clock_gettime (CLOCK_MONOTONIC) value at the vblank, and that
467    * backend starts drawing immediately after receiving the vblank
468    * notification. If we detect this, and make the assumption that the
469    * compositor will finish drawing before the next vblank, we can
470    * then determine the presentation time as the frame time we
471    * received plus one refresh interval.
472    *
473    * If a backend is using clock_gettime(CLOCK_MONOTONIC), but not
474    * picking values right at the vblank, then the presentation times
475    * we compute won't be accurate, but not really worse than then
476    * the alternative of not providing presentation times at all.
477    *
478    * The complexity here is dealing with the fact that we receive
479    * only the low 32 bits of the CLOCK_MONOTONIC value in milliseconds.
480    */
481   gint64 now_monotonic = g_get_monotonic_time ();
482   gint64 now_monotonic_msec = now_monotonic / 1000;
483   uint32_t now_monotonic_low = (uint32_t)now_monotonic_msec;
484 
485   if (frame_time - now_monotonic_low < 1000 ||
486       frame_time - now_monotonic_low > (uint32_t)-1000)
487     {
488       /* Timestamp we received is within one second of the current time.
489        */
490       gint64 last_frame_time = now_monotonic + (gint64)1000 * (gint32)(frame_time - now_monotonic_low);
491       if ((gint32)now_monotonic_low < 0 && (gint32)frame_time > 0)
492         last_frame_time += (gint64)1000 * G_GINT64_CONSTANT(0x100000000);
493       else if ((gint32)now_monotonic_low > 0 && (gint32)frame_time < 0)
494         last_frame_time -= (gint64)1000 * G_GINT64_CONSTANT(0x100000000);
495 
496       timings->presentation_time = last_frame_time + timings->refresh_interval;
497     }
498 }
499 
500 static GdkSurface *
get_popup_toplevel(GdkSurface * surface)501 get_popup_toplevel (GdkSurface *surface)
502 {
503   if (surface->parent)
504     return get_popup_toplevel (surface->parent);
505   else
506     return surface;
507 }
508 
509 static void
freeze_popup_toplevel_state(GdkSurface * surface)510 freeze_popup_toplevel_state (GdkSurface *surface)
511 {
512   GdkSurface *toplevel;
513 
514   toplevel = get_popup_toplevel (surface);
515   gdk_wayland_surface_freeze_state (toplevel);
516 }
517 
518 static void
thaw_popup_toplevel_state(GdkSurface * surface)519 thaw_popup_toplevel_state (GdkSurface *surface)
520 {
521   GdkSurface *toplevel;
522 
523   toplevel = get_popup_toplevel (surface);
524   gdk_wayland_surface_thaw_state (toplevel);
525 }
526 
527 static void
finish_pending_relayout(GdkSurface * surface)528 finish_pending_relayout (GdkSurface *surface)
529 {
530   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
531 
532   g_assert (impl->popup_state == POPUP_STATE_WAITING_FOR_FRAME);
533   impl->popup_state = POPUP_STATE_IDLE;
534 
535   thaw_popup_toplevel_state (surface);
536 }
537 
538 static void
frame_callback(void * data,struct wl_callback * callback,uint32_t time)539 frame_callback (void               *data,
540                 struct wl_callback *callback,
541                 uint32_t            time)
542 {
543   GdkSurface *surface = data;
544   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
545   GdkWaylandDisplay *display_wayland =
546     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
547   GdkFrameClock *clock = gdk_surface_get_frame_clock (surface);
548   GdkFrameTimings *timings;
549 
550   gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "wayland", "frame event");
551   GDK_DISPLAY_NOTE (GDK_DISPLAY (display_wayland), EVENTS, g_message ("frame %p", surface));
552 
553   wl_callback_destroy (callback);
554 
555   if (GDK_SURFACE_DESTROYED (surface))
556     return;
557 
558   if (!impl->awaiting_frame)
559     return;
560 
561   switch (impl->popup_state)
562     {
563     case POPUP_STATE_IDLE:
564     case POPUP_STATE_WAITING_FOR_REPOSITIONED:
565     case POPUP_STATE_WAITING_FOR_CONFIGURE:
566       break;
567     case POPUP_STATE_WAITING_FOR_FRAME:
568       finish_pending_relayout (surface);
569       break;
570     default:
571       g_assert_not_reached ();
572     }
573 
574   impl->awaiting_frame = FALSE;
575   if (impl->awaiting_frame_frozen)
576     {
577       impl->awaiting_frame_frozen = FALSE;
578       gdk_surface_thaw_updates (surface);
579     }
580 
581   timings = gdk_frame_clock_get_timings (clock, impl->pending_frame_counter);
582   impl->pending_frame_counter = 0;
583 
584   if (timings == NULL)
585     return;
586 
587   timings->refresh_interval = 16667; /* default to 1/60th of a second */
588   if (impl->display_server.outputs)
589     {
590       /* We pick a random output out of the outputs that the surface touches
591        * The rate here is in milli-hertz */
592       int refresh_rate =
593         gdk_wayland_display_get_output_refresh_rate (display_wayland,
594                                                      impl->display_server.outputs->data);
595       if (refresh_rate != 0)
596         timings->refresh_interval = G_GINT64_CONSTANT(1000000000) / refresh_rate;
597     }
598 
599   fill_presentation_time_from_frame_time (timings, time);
600 
601   timings->complete = TRUE;
602 
603 #ifdef G_ENABLE_DEBUG
604   if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
605     _gdk_frame_clock_debug_print_timings (clock, timings);
606 #endif
607 
608   if (GDK_PROFILER_IS_RUNNING)
609     _gdk_frame_clock_add_timings_to_profiler (clock, timings);
610 }
611 
612 static const struct wl_callback_listener frame_listener = {
613   frame_callback
614 };
615 
616 static void
on_frame_clock_before_paint(GdkFrameClock * clock,GdkSurface * surface)617 on_frame_clock_before_paint (GdkFrameClock *clock,
618                              GdkSurface     *surface)
619 {
620   GdkFrameTimings *timings = gdk_frame_clock_get_current_timings (clock);
621   gint64 presentation_time;
622   gint64 refresh_interval;
623 
624   if (surface->update_freeze_count > 0)
625     return;
626 
627   gdk_frame_clock_get_refresh_info (clock,
628                                     timings->frame_time,
629                                     &refresh_interval, &presentation_time);
630 
631   if (presentation_time != 0)
632     {
633       /* Assume the algorithm used by the DRM backend of Weston - it
634        * starts drawing at the next vblank after receiving the commit
635        * for this frame, and presentation occurs at the vblank
636        * after that.
637        */
638       timings->predicted_presentation_time = presentation_time + refresh_interval;
639     }
640   else
641     {
642       /* As above, but we don't actually know the phase of the vblank,
643        * so just assume that we're half way through a refresh cycle.
644        */
645       timings->predicted_presentation_time = timings->frame_time + refresh_interval / 2 + refresh_interval;
646     }
647 
648   gdk_surface_apply_state_change (surface);
649 }
650 
651 static void
configure_popup_geometry(GdkSurface * surface)652 configure_popup_geometry (GdkSurface *surface)
653 {
654   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
655   int x, y;
656   int width, height;
657 
658   x = impl->next_layout.popup.x - impl->shadow_left;
659   y = impl->next_layout.popup.y - impl->shadow_top;
660   width =
661     impl->next_layout.configured_width +
662     (impl->shadow_left + impl->shadow_right);
663   height =
664     impl->next_layout.configured_height +
665     (impl->shadow_top + impl->shadow_bottom);
666 
667   gdk_wayland_surface_move_resize (surface, x, y, width, height);
668 }
669 
670 static void
configure_drag_surface_geometry(GdkSurface * surface)671 configure_drag_surface_geometry (GdkSurface *surface)
672 {
673   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
674 
675   gdk_wayland_surface_update_size (surface,
676                                    impl->next_layout.configured_width,
677                                    impl->next_layout.configured_height,
678                                    impl->scale);
679 }
680 
681 static gboolean
gdk_wayland_surface_compute_size(GdkSurface * surface)682 gdk_wayland_surface_compute_size (GdkSurface *surface)
683 {
684   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
685 
686   if (impl->next_layout.surface_geometry_dirty)
687     {
688       if (GDK_IS_TOPLEVEL (impl))
689         configure_toplevel_geometry (surface);
690       else if (GDK_IS_POPUP (impl))
691         configure_popup_geometry (surface);
692       else if (GDK_IS_DRAG_SURFACE (impl))
693         configure_drag_surface_geometry (surface);
694 
695       impl->next_layout.surface_geometry_dirty = FALSE;
696     }
697 
698   return FALSE;
699 }
700 
701 static void
gdk_wayland_surface_request_layout(GdkSurface * surface)702 gdk_wayland_surface_request_layout (GdkSurface *surface)
703 {
704   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
705 
706   impl->next_layout.surface_geometry_dirty = TRUE;
707 }
708 
709 void
gdk_wayland_surface_request_frame(GdkSurface * surface)710 gdk_wayland_surface_request_frame (GdkSurface *surface)
711 {
712   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
713   struct wl_callback *callback;
714   GdkFrameClock *clock;
715 
716   if (impl->awaiting_frame)
717     return;
718 
719   clock = gdk_surface_get_frame_clock (surface);
720 
721   callback = wl_surface_frame (impl->display_server.wl_surface);
722   wl_proxy_set_queue ((struct wl_proxy *) callback, NULL);
723   wl_callback_add_listener (callback, &frame_listener, surface);
724   impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
725   impl->awaiting_frame = TRUE;
726 }
727 
728 gboolean
gdk_wayland_surface_has_surface(GdkSurface * surface)729 gdk_wayland_surface_has_surface (GdkSurface *surface)
730 {
731   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
732 
733   return !!impl->display_server.wl_surface;
734 }
735 
736 void
gdk_wayland_surface_commit(GdkSurface * surface)737 gdk_wayland_surface_commit (GdkSurface *surface)
738 {
739   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
740 
741   wl_surface_commit (impl->display_server.wl_surface);
742 }
743 
744 void
gdk_wayland_surface_notify_committed(GdkSurface * surface)745 gdk_wayland_surface_notify_committed (GdkSurface *surface)
746 {
747   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
748 
749   impl->has_uncommitted_ack_configure = FALSE;
750 }
751 
752 static void
on_frame_clock_after_paint(GdkFrameClock * clock,GdkSurface * surface)753 on_frame_clock_after_paint (GdkFrameClock *clock,
754                             GdkSurface    *surface)
755 {
756   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
757 
758   if (surface->update_freeze_count == 0 && impl->has_uncommitted_ack_configure)
759     {
760       gdk_wayland_surface_commit (surface);
761       gdk_wayland_surface_notify_committed (surface);
762     }
763 
764   if (impl->awaiting_frame &&
765       impl->pending_frame_counter == gdk_frame_clock_get_frame_counter (clock))
766     {
767       impl->awaiting_frame_frozen = TRUE;
768       gdk_surface_freeze_updates (surface);
769     }
770 }
771 
772 void
gdk_wayland_surface_update_scale(GdkSurface * surface)773 gdk_wayland_surface_update_scale (GdkSurface *surface)
774 {
775   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
776   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
777   guint32 scale;
778   GSList *l;
779 
780   if (display_wayland->compositor_version < WL_SURFACE_HAS_BUFFER_SCALE)
781     {
782       /* We can't set the scale on this surface */
783       return;
784     }
785 
786   scale = 1;
787   for (l = impl->display_server.outputs; l != NULL; l = l->next)
788     {
789       guint32 output_scale = gdk_wayland_display_get_output_scale (display_wayland, l->data);
790       scale = MAX (scale, output_scale);
791     }
792 
793   /* Notify app that scale changed */
794   gdk_wayland_surface_maybe_resize (surface,
795                                     surface->width, surface->height,
796                                     scale);
797 }
798 
799 static void gdk_wayland_surface_create_surface (GdkSurface *surface);
800 static void gdk_wayland_surface_set_title      (GdkSurface *surface,
801                                                 const char *title);
802 
803 GdkSurface *
_gdk_wayland_display_create_surface(GdkDisplay * display,GdkSurfaceType surface_type,GdkSurface * parent,int x,int y,int width,int height)804 _gdk_wayland_display_create_surface (GdkDisplay     *display,
805                                      GdkSurfaceType  surface_type,
806                                      GdkSurface     *parent,
807                                      int             x,
808                                      int             y,
809                                      int             width,
810                                      int             height)
811 {
812   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
813   GdkSurface *surface;
814   GdkWaylandSurface *impl;
815   GdkFrameClock *frame_clock;
816 
817   if (parent)
818     frame_clock = g_object_ref (gdk_surface_get_frame_clock (parent));
819   else
820     frame_clock = _gdk_frame_clock_idle_new ();
821 
822   switch (surface_type)
823     {
824     case GDK_SURFACE_TOPLEVEL:
825       surface = g_object_new (GDK_TYPE_WAYLAND_TOPLEVEL,
826                               "display", display,
827                               "frame-clock", frame_clock,
828                               NULL);
829       display_wayland->toplevels = g_list_prepend (display_wayland->toplevels,
830                                                    surface);
831       g_warn_if_fail (!parent);
832       break;
833     case GDK_SURFACE_POPUP:
834       surface = g_object_new (GDK_TYPE_WAYLAND_POPUP,
835                               "parent", parent,
836                               "display", display,
837                               "frame-clock", frame_clock,
838                               NULL);
839       break;
840     case GDK_SURFACE_TEMP:
841       surface = g_object_new (GDK_TYPE_WAYLAND_DRAG_SURFACE,
842                               "display", display,
843                               "frame-clock", frame_clock,
844                               NULL);
845       break;
846     default:
847       g_assert_not_reached ();
848       break;
849     }
850 
851   impl = GDK_WAYLAND_SURFACE (surface);
852 
853   if (width > 65535)
854     {
855       g_warning ("Native Surfaces wider than 65535 pixels are not supported");
856       width = 65535;
857     }
858   if (height > 65535)
859     {
860       g_warning ("Native Surfaces taller than 65535 pixels are not supported");
861       height = 65535;
862     }
863 
864   surface->x = x;
865   surface->y = y;
866   surface->width = width;
867   surface->height = height;
868 
869   g_object_ref (surface);
870 
871   /* More likely to be right than just assuming 1 */
872   if (display_wayland->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE)
873     {
874       GdkMonitor *monitor = g_list_model_get_item (gdk_display_get_monitors (display), 0);
875       if (monitor)
876         {
877           impl->scale = gdk_monitor_get_scale_factor (monitor);
878           g_object_unref (monitor);
879         }
880     }
881 
882   gdk_wayland_surface_set_title (surface, get_default_title ());
883 
884 
885   gdk_wayland_surface_create_surface (surface);
886 
887   g_signal_connect (frame_clock, "before-paint", G_CALLBACK (on_frame_clock_before_paint), surface);
888   g_signal_connect (frame_clock, "after-paint", G_CALLBACK (on_frame_clock_after_paint), surface);
889 
890   g_object_unref (frame_clock);
891 
892   return surface;
893 }
894 
895 void
gdk_wayland_surface_attach_image(GdkSurface * surface,cairo_surface_t * cairo_surface,const cairo_region_t * damage)896 gdk_wayland_surface_attach_image (GdkSurface           *surface,
897                                   cairo_surface_t      *cairo_surface,
898                                   const cairo_region_t *damage)
899 {
900   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
901   GdkWaylandDisplay *display;
902   cairo_rectangle_int_t rect;
903   int i, n;
904 
905   if (GDK_SURFACE_DESTROYED (surface))
906     return;
907 
908   g_assert (_gdk_wayland_is_shm_surface (cairo_surface));
909 
910   /* Attach this new buffer to the surface */
911   wl_surface_attach (impl->display_server.wl_surface,
912                      _gdk_wayland_shm_surface_get_wl_buffer (cairo_surface),
913                      impl->pending_buffer_offset_x,
914                      impl->pending_buffer_offset_y);
915   impl->pending_buffer_offset_x = 0;
916   impl->pending_buffer_offset_y = 0;
917 
918   /* Only set the buffer scale if supported by the compositor */
919   display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
920   if (display->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE)
921     wl_surface_set_buffer_scale (impl->display_server.wl_surface, impl->scale);
922 
923   n = cairo_region_num_rectangles (damage);
924   for (i = 0; i < n; i++)
925     {
926       cairo_region_get_rectangle (damage, i, &rect);
927       wl_surface_damage (impl->display_server.wl_surface, rect.x, rect.y, rect.width, rect.height);
928     }
929 }
930 
931 void
gdk_wayland_surface_sync(GdkSurface * surface)932 gdk_wayland_surface_sync (GdkSurface *surface)
933 {
934   gdk_wayland_surface_sync_shadow (surface);
935   gdk_wayland_surface_sync_opaque_region (surface);
936   gdk_wayland_surface_sync_input_region (surface);
937 }
938 
939 static gboolean
gdk_wayland_surface_beep(GdkSurface * surface)940 gdk_wayland_surface_beep (GdkSurface *surface)
941 {
942   gdk_wayland_display_system_bell (gdk_surface_get_display (surface),
943                                    surface);
944 
945   return TRUE;
946 }
947 
948 static void
gdk_wayland_surface_constructed(GObject * object)949 gdk_wayland_surface_constructed (GObject *object)
950 {
951   GdkSurface *surface = GDK_SURFACE (object);
952   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
953   GdkWaylandDisplay *display_wayland =
954     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
955 
956   G_OBJECT_CLASS (gdk_wayland_surface_parent_class)->constructed (object);
957 
958   impl->event_queue = wl_display_create_queue (display_wayland->wl_display);
959   display_wayland->event_queues = g_list_prepend (display_wayland->event_queues,
960                                                   impl->event_queue);
961 }
962 
963 static void
gdk_wayland_surface_dispose(GObject * object)964 gdk_wayland_surface_dispose (GObject *object)
965 {
966   GdkSurface *surface = GDK_SURFACE (object);
967   GdkWaylandSurface *impl;
968 
969   g_return_if_fail (GDK_IS_WAYLAND_SURFACE (surface));
970 
971   impl = GDK_WAYLAND_SURFACE (surface);
972 
973   if (impl->event_queue)
974     {
975       GdkWaylandDisplay *display_wayland =
976         GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
977 
978       display_wayland->event_queues =
979         g_list_remove (display_wayland->event_queues, surface);
980       g_clear_pointer (&impl->event_queue, wl_event_queue_destroy);
981     }
982 
983   G_OBJECT_CLASS (gdk_wayland_surface_parent_class)->dispose (object);
984 }
985 
986 static void
gdk_wayland_surface_finalize(GObject * object)987 gdk_wayland_surface_finalize (GObject *object)
988 {
989   GdkWaylandSurface *impl;
990 
991   g_return_if_fail (GDK_IS_WAYLAND_SURFACE (object));
992 
993   impl = GDK_WAYLAND_SURFACE (object);
994 
995   if (gdk_wayland_surface_is_exported (impl))
996     gdk_wayland_toplevel_unexport_handle (GDK_TOPLEVEL (impl));
997 
998   g_free (impl->title);
999 
1000   g_free (impl->application.application_id);
1001   g_free (impl->application.app_menu_path);
1002   g_free (impl->application.menubar_path);
1003   g_free (impl->application.window_object_path);
1004   g_free (impl->application.application_object_path);
1005   g_free (impl->application.unique_bus_name);
1006 
1007   g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
1008   g_clear_pointer (&impl->input_region, cairo_region_destroy);
1009   g_clear_pointer (&impl->shortcuts_inhibitors, g_hash_table_unref);
1010 
1011   G_OBJECT_CLASS (gdk_wayland_surface_parent_class)->finalize (object);
1012 }
1013 
1014 static gboolean
is_realized_shell_surface(GdkWaylandSurface * impl)1015 is_realized_shell_surface (GdkWaylandSurface *impl)
1016 {
1017   return (impl->display_server.xdg_surface ||
1018           impl->display_server.zxdg_surface_v6);
1019 }
1020 
1021 static gboolean
is_realized_toplevel(GdkWaylandSurface * impl)1022 is_realized_toplevel (GdkWaylandSurface *impl)
1023 {
1024   return (impl->display_server.xdg_toplevel ||
1025           impl->display_server.zxdg_toplevel_v6);
1026 }
1027 
1028 static gboolean
is_realized_popup(GdkWaylandSurface * impl)1029 is_realized_popup (GdkWaylandSurface *impl)
1030 {
1031   return (impl->display_server.xdg_popup ||
1032           impl->display_server.zxdg_popup_v6);
1033 }
1034 
1035 static void gdk_wayland_surface_show (GdkSurface *surface,
1036                                       gboolean    already_mapped);
1037 static void gdk_wayland_surface_hide (GdkSurface *surface);
1038 
1039 static void
gdk_wayland_surface_maybe_resize(GdkSurface * surface,int width,int height,int scale)1040 gdk_wayland_surface_maybe_resize (GdkSurface *surface,
1041                                   int         width,
1042                                   int         height,
1043                                   int         scale)
1044 {
1045   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1046   gboolean is_xdg_popup;
1047   gboolean is_visible;
1048 
1049   if (surface->width == width &&
1050       surface->height == height &&
1051       impl->scale == scale)
1052     return;
1053 
1054   /* For xdg_popup using an xdg_positioner, there is a race condition if
1055    * the application tries to change the size after it's mapped, but before
1056    * the initial configure is received, so hide and show the surface again
1057    * force the new size onto the compositor. See bug #772505.
1058    */
1059 
1060   is_xdg_popup = is_realized_popup (impl);
1061   is_visible = gdk_surface_get_mapped (surface);
1062 
1063   if (is_xdg_popup && is_visible && !impl->initial_configure_received)
1064     gdk_wayland_surface_hide (surface);
1065 
1066   gdk_wayland_surface_update_size (surface, width, height, scale);
1067 
1068   if (is_xdg_popup && is_visible && !impl->initial_configure_received)
1069     gdk_wayland_surface_show (surface, FALSE);
1070 }
1071 
1072 static void
gdk_wayland_surface_sync_parent(GdkSurface * surface,GdkSurface * parent)1073 gdk_wayland_surface_sync_parent (GdkSurface *surface,
1074                                  GdkSurface *parent)
1075 {
1076   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1077   GdkWaylandToplevel *toplevel = GDK_WAYLAND_TOPLEVEL (impl);
1078   GdkWaylandDisplay *display_wayland =
1079     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
1080   GdkWaylandSurface *impl_parent = NULL;
1081 
1082   g_assert (parent == NULL ||
1083             gdk_surface_get_display (surface) == gdk_surface_get_display (parent));
1084 
1085   if (!is_realized_toplevel (impl))
1086     return;
1087 
1088   if (toplevel->transient_for)
1089     impl_parent = GDK_WAYLAND_SURFACE (toplevel->transient_for);
1090   else if (parent)
1091     impl_parent = GDK_WAYLAND_SURFACE (parent);
1092 
1093   /* XXX: Is this correct? */
1094   if (impl_parent && !impl_parent->display_server.wl_surface)
1095     return;
1096 
1097   switch (display_wayland->shell_variant)
1098     {
1099     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1100       {
1101         struct xdg_toplevel *parent_toplevel;
1102 
1103         if (impl_parent)
1104           parent_toplevel = impl_parent->display_server.xdg_toplevel;
1105         else
1106           parent_toplevel = NULL;
1107 
1108         xdg_toplevel_set_parent (impl->display_server.xdg_toplevel,
1109                                  parent_toplevel);
1110         break;
1111       }
1112       break;
1113     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1114       {
1115         struct zxdg_toplevel_v6 *parent_toplevel;
1116 
1117         if (impl_parent)
1118           parent_toplevel = impl_parent->display_server.zxdg_toplevel_v6;
1119         else
1120           parent_toplevel = NULL;
1121 
1122         zxdg_toplevel_v6_set_parent (impl->display_server.zxdg_toplevel_v6,
1123                                      parent_toplevel);
1124         break;
1125       }
1126     default:
1127       g_assert_not_reached ();
1128     }
1129 }
1130 
1131 static void
gdk_wayland_surface_sync_parent_of_imported(GdkWaylandSurface * impl)1132 gdk_wayland_surface_sync_parent_of_imported (GdkWaylandSurface *impl)
1133 {
1134   if (!impl->display_server.wl_surface)
1135     return;
1136 
1137   if (!impl->imported_transient_for)
1138     return;
1139 
1140   if (!is_realized_toplevel (impl))
1141     return;
1142 
1143   zxdg_imported_v1_set_parent_of (impl->imported_transient_for,
1144                                   impl->display_server.wl_surface);
1145 }
1146 
1147 static void
gdk_wayland_surface_sync_title(GdkSurface * surface)1148 gdk_wayland_surface_sync_title (GdkSurface *surface)
1149 {
1150   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1151   GdkWaylandDisplay *display_wayland =
1152     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
1153 
1154   if (!is_realized_toplevel (impl))
1155     return;
1156 
1157   if (!impl->title)
1158     return;
1159 
1160   switch (display_wayland->shell_variant)
1161     {
1162     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1163       xdg_toplevel_set_title (impl->display_server.xdg_toplevel,
1164                               impl->title);
1165       break;
1166     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1167       zxdg_toplevel_v6_set_title (impl->display_server.zxdg_toplevel_v6,
1168                                   impl->title);
1169       break;
1170     default:
1171       g_assert_not_reached ();
1172     }
1173 }
1174 
1175 static void
gdk_wayland_surface_get_window_geometry(GdkSurface * surface,GdkRectangle * geometry)1176 gdk_wayland_surface_get_window_geometry (GdkSurface   *surface,
1177                                          GdkRectangle *geometry)
1178 {
1179   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1180 
1181   *geometry = (GdkRectangle) {
1182     .x = impl->shadow_left,
1183     .y = impl->shadow_top,
1184     .width = surface->width - (impl->shadow_left + impl->shadow_right),
1185     .height = surface->height - (impl->shadow_top + impl->shadow_bottom)
1186   };
1187 }
1188 
1189 static void gdk_wayland_surface_set_geometry_hints (GdkWaylandSurface  *impl,
1190                                                     const GdkGeometry  *geometry,
1191                                                     GdkSurfaceHints     geom_mask);
1192 
1193 static void
gdk_wayland_surface_sync_shadow(GdkSurface * surface)1194 gdk_wayland_surface_sync_shadow (GdkSurface *surface)
1195 {
1196   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1197   GdkWaylandDisplay *display_wayland =
1198     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
1199   GdkRectangle geometry;
1200 
1201   if (!is_realized_shell_surface (impl))
1202     return;
1203 
1204   gdk_wayland_surface_get_window_geometry (surface, &geometry);
1205   gdk_wayland_surface_set_geometry_hints (impl,
1206                                           &impl->geometry_hints,
1207                                           impl->geometry_mask);
1208 
1209   if (gdk_rectangle_equal (&geometry, &impl->last_sent_window_geometry))
1210     return;
1211 
1212   switch (display_wayland->shell_variant)
1213     {
1214     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1215       xdg_surface_set_window_geometry (impl->display_server.xdg_surface,
1216                                        geometry.x,
1217                                        geometry.y,
1218                                        geometry.width,
1219                                        geometry.height);
1220       break;
1221     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1222       zxdg_surface_v6_set_window_geometry (impl->display_server.zxdg_surface_v6,
1223                                            geometry.x,
1224                                            geometry.y,
1225                                            geometry.width,
1226                                            geometry.height);
1227       break;
1228     default:
1229       g_assert_not_reached ();
1230     }
1231 
1232   impl->last_sent_window_geometry = geometry;
1233 }
1234 
1235 static struct wl_region *
wl_region_from_cairo_region(GdkWaylandDisplay * display,cairo_region_t * region)1236 wl_region_from_cairo_region (GdkWaylandDisplay *display,
1237                              cairo_region_t    *region)
1238 {
1239   struct wl_region *wl_region;
1240   int i, n_rects;
1241 
1242   wl_region = wl_compositor_create_region (display->compositor);
1243   if (wl_region == NULL)
1244     return NULL;
1245 
1246   n_rects = cairo_region_num_rectangles (region);
1247   for (i = 0; i < n_rects; i++)
1248     {
1249       cairo_rectangle_int_t rect;
1250       cairo_region_get_rectangle (region, i, &rect);
1251       wl_region_add (wl_region, rect.x, rect.y, rect.width, rect.height);
1252     }
1253 
1254   return wl_region;
1255 }
1256 
1257 static void
gdk_wayland_surface_sync_opaque_region(GdkSurface * surface)1258 gdk_wayland_surface_sync_opaque_region (GdkSurface *surface)
1259 {
1260   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1261   struct wl_region *wl_region = NULL;
1262 
1263   if (!impl->display_server.wl_surface)
1264     return;
1265 
1266   if (!impl->opaque_region_dirty)
1267     return;
1268 
1269   if (impl->opaque_region != NULL)
1270     wl_region = wl_region_from_cairo_region (GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface)),
1271                                              impl->opaque_region);
1272 
1273   wl_surface_set_opaque_region (impl->display_server.wl_surface, wl_region);
1274 
1275   if (wl_region != NULL)
1276     wl_region_destroy (wl_region);
1277 
1278   impl->opaque_region_dirty = FALSE;
1279 }
1280 
1281 static void
gdk_wayland_surface_sync_input_region(GdkSurface * surface)1282 gdk_wayland_surface_sync_input_region (GdkSurface *surface)
1283 {
1284   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1285   struct wl_region *wl_region = NULL;
1286 
1287   if (!impl->display_server.wl_surface)
1288     return;
1289 
1290   if (!impl->input_region_dirty)
1291     return;
1292 
1293   if (impl->input_region != NULL)
1294     wl_region = wl_region_from_cairo_region (GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface)),
1295                                              impl->input_region);
1296 
1297   wl_surface_set_input_region (impl->display_server.wl_surface, wl_region);
1298 
1299   if (wl_region != NULL)
1300     wl_region_destroy (wl_region);
1301 
1302   impl->input_region_dirty = FALSE;
1303 }
1304 
1305 static void
surface_enter(void * data,struct wl_surface * wl_surface,struct wl_output * output)1306 surface_enter (void              *data,
1307                struct wl_surface *wl_surface,
1308                struct wl_output  *output)
1309 {
1310   GdkSurface *surface = GDK_SURFACE (data);
1311   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1312   GdkDisplay *display = gdk_surface_get_display (surface);
1313   GdkMonitor *monitor;
1314 
1315   GDK_DISPLAY_NOTE (gdk_surface_get_display (surface), EVENTS,
1316             g_message ("surface enter, surface %p output %p", surface, output));
1317 
1318   impl->display_server.outputs = g_slist_prepend (impl->display_server.outputs, output);
1319 
1320   gdk_wayland_surface_update_scale (surface);
1321 
1322   monitor = gdk_wayland_display_get_monitor_for_output (display, output);
1323   gdk_surface_enter_monitor (surface, monitor);
1324 }
1325 
1326 static void
surface_leave(void * data,struct wl_surface * wl_surface,struct wl_output * output)1327 surface_leave (void              *data,
1328                struct wl_surface *wl_surface,
1329                struct wl_output  *output)
1330 {
1331   GdkSurface *surface = GDK_SURFACE (data);
1332   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1333   GdkDisplay *display = gdk_surface_get_display (surface);
1334   GdkMonitor *monitor;
1335 
1336   GDK_DISPLAY_NOTE (gdk_surface_get_display (surface), EVENTS,
1337             g_message ("surface leave, surface %p output %p", surface, output));
1338 
1339   impl->display_server.outputs = g_slist_remove (impl->display_server.outputs, output);
1340 
1341   if (impl->display_server.outputs)
1342     gdk_wayland_surface_update_scale (surface);
1343 
1344   monitor = gdk_wayland_display_get_monitor_for_output (display, output);
1345   gdk_surface_leave_monitor (surface, monitor);
1346 }
1347 
1348 static const struct wl_surface_listener surface_listener = {
1349   surface_enter,
1350   surface_leave
1351 };
1352 
1353 static void
gdk_wayland_surface_create_surface(GdkSurface * surface)1354 gdk_wayland_surface_create_surface (GdkSurface *surface)
1355 {
1356   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1357   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
1358   struct wl_surface *wl_surface;
1359 
1360   wl_surface = wl_compositor_create_surface (display_wayland->compositor);
1361   wl_proxy_set_queue ((struct wl_proxy *) wl_surface, impl->event_queue);
1362   wl_surface_add_listener (wl_surface, &surface_listener, surface);
1363 
1364   impl->display_server.wl_surface = wl_surface;
1365 }
1366 
1367 static void
configure_toplevel_geometry(GdkSurface * surface)1368 configure_toplevel_geometry (GdkSurface *surface)
1369 {
1370   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1371   GdkDisplay *display = gdk_surface_get_display (surface);
1372   GdkMonitor *monitor;
1373   GdkRectangle monitor_geometry;
1374   int bounds_width, bounds_height;
1375   GdkToplevelSize size;
1376   GdkToplevelLayout *layout;
1377   GdkGeometry geometry;
1378   GdkSurfaceHints mask;
1379 
1380   monitor = g_list_model_get_item (gdk_display_get_monitors (display), 0);
1381   gdk_monitor_get_geometry (monitor, &monitor_geometry);
1382   g_object_unref (monitor);
1383   bounds_width = monitor_geometry.width;
1384   bounds_height = monitor_geometry.height;
1385 
1386   gdk_toplevel_size_init (&size, bounds_width, bounds_height);
1387   gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
1388   g_warn_if_fail (size.width > 0);
1389   g_warn_if_fail (size.height > 0);
1390 
1391   layout = impl->toplevel.layout;
1392   if (gdk_toplevel_layout_get_resizable (layout))
1393     {
1394       geometry.min_width = size.min_width;
1395       geometry.min_height = size.min_height;
1396       mask = GDK_HINT_MIN_SIZE;
1397     }
1398   else
1399     {
1400       geometry.max_width = geometry.min_width = size.width;
1401       geometry.max_height = geometry.min_height = size.height;
1402       mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
1403     }
1404   gdk_wayland_surface_set_geometry_hints (impl, &geometry, mask);
1405 
1406   if (size.shadow.is_valid)
1407     {
1408       impl->shadow_left = size.shadow.left;
1409       impl->shadow_right = size.shadow.right;
1410       impl->shadow_top = size.shadow.top;
1411       impl->shadow_bottom = size.shadow.bottom;
1412     }
1413 
1414   if (impl->next_layout.configured_width > 0 &&
1415       impl->next_layout.configured_height > 0)
1416     {
1417       int width, height;
1418 
1419       width = impl->next_layout.configured_width +
1420         impl->shadow_left + impl->shadow_right;
1421       height = impl->next_layout.configured_height +
1422         impl->shadow_top + impl->shadow_bottom;
1423 
1424       if (impl->next_layout.toplevel.should_constrain)
1425         {
1426           gdk_surface_constrain_size (&impl->geometry_hints,
1427                                       impl->geometry_mask,
1428                                       width, height,
1429                                       &width, &height);
1430         }
1431       gdk_wayland_surface_update_size (surface, width, height, impl->scale);
1432 
1433       if (!impl->next_layout.toplevel.size_is_fixed)
1434         {
1435           impl->next_layout.toplevel.should_constrain = FALSE;
1436           impl->next_layout.configured_width = 0;
1437           impl->next_layout.configured_height = 0;
1438         }
1439     }
1440   else
1441     {
1442       int width, height;
1443 
1444       width = size.width;
1445       height = size.height;
1446       gdk_surface_constrain_size (&geometry, mask,
1447                                   width, height,
1448                                   &width, &height);
1449       gdk_wayland_surface_update_size (surface, width, height, impl->scale);
1450     }
1451 }
1452 
1453 static void
synthesize_initial_surface_state(GdkSurface * surface,GdkToplevelState unset_flags,GdkToplevelState set_flags)1454 synthesize_initial_surface_state (GdkSurface       *surface,
1455                                   GdkToplevelState  unset_flags,
1456                                   GdkToplevelState  set_flags)
1457 {
1458   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1459 
1460   impl->initial_state.unset_flags |= unset_flags;
1461   impl->initial_state.set_flags &= ~unset_flags;
1462 
1463   impl->initial_state.set_flags |= set_flags;
1464   impl->initial_state.unset_flags &= ~set_flags;
1465 }
1466 
1467 static void
gdk_wayland_surface_configure_toplevel(GdkSurface * surface)1468 gdk_wayland_surface_configure_toplevel (GdkSurface *surface)
1469 {
1470   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1471   GdkWaylandDisplay *display_wayland =
1472     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
1473   GdkToplevelState new_state;
1474   int width, height;
1475   gboolean is_resizing;
1476   gboolean fixed_size;
1477   gboolean saved_size;
1478 
1479   new_state = impl->pending.toplevel.state;
1480   impl->pending.toplevel.state = 0;
1481 
1482   is_resizing = impl->pending.toplevel.is_resizing;
1483   impl->pending.toplevel.is_resizing = FALSE;
1484 
1485   fixed_size =
1486     new_state & (GDK_TOPLEVEL_STATE_MAXIMIZED |
1487                  GDK_TOPLEVEL_STATE_FULLSCREEN |
1488                  GDK_TOPLEVEL_STATE_TILED) ||
1489     is_resizing;
1490 
1491   width = impl->pending.toplevel.width;
1492   height = impl->pending.toplevel.height;
1493 
1494   saved_size = (width == 0 && height == 0);
1495   /* According to xdg_shell, an xdg_surface.configure with size 0x0
1496    * should be interpreted as that it is up to the client to set a
1497    * size.
1498    *
1499    * When transitioning from maximize or fullscreen state, this means
1500    * the client should configure its size back to what it was before
1501    * being maximize or fullscreen.
1502    */
1503   if (saved_size && !fixed_size)
1504     {
1505       width = impl->saved_width;
1506       height = impl->saved_height;
1507     }
1508 
1509   if (width > 0 && height > 0)
1510     {
1511       if (!saved_size)
1512         {
1513           impl->next_layout.toplevel.should_constrain = TRUE;
1514 
1515           /* Save size for next time we get 0x0 */
1516           _gdk_wayland_surface_save_size (surface);
1517         }
1518       else if (is_resizing)
1519         {
1520           impl->next_layout.toplevel.should_constrain = TRUE;
1521         }
1522       else
1523         {
1524           impl->next_layout.toplevel.should_constrain = FALSE;
1525         }
1526 
1527       impl->next_layout.toplevel.size_is_fixed = fixed_size;
1528       impl->next_layout.configured_width = width;
1529       impl->next_layout.configured_height = height;
1530     }
1531   else
1532     {
1533       impl->next_layout.toplevel.should_constrain = FALSE;
1534       impl->next_layout.toplevel.size_is_fixed = FALSE;
1535       impl->next_layout.configured_width = 0;
1536       impl->next_layout.configured_height = 0;
1537     }
1538 
1539   impl->next_layout.surface_geometry_dirty = TRUE;
1540   gdk_surface_request_layout (surface);
1541 
1542   GDK_DISPLAY_NOTE (gdk_surface_get_display (surface), EVENTS,
1543             g_message ("configure, surface %p %dx%d,%s%s%s%s",
1544                        surface, width, height,
1545                        (new_state & GDK_TOPLEVEL_STATE_FULLSCREEN) ? " fullscreen" : "",
1546                        (new_state & GDK_TOPLEVEL_STATE_MAXIMIZED) ? " maximized" : "",
1547                        (new_state & GDK_TOPLEVEL_STATE_FOCUSED) ? " focused" : "",
1548                        (new_state & GDK_TOPLEVEL_STATE_TILED) ? " tiled" : ""));
1549 
1550   gdk_surface_queue_state_change (surface, ~0 & ~new_state, new_state);
1551 
1552   switch (display_wayland->shell_variant)
1553     {
1554     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1555       xdg_surface_ack_configure (impl->display_server.xdg_surface,
1556                                  impl->pending.serial);
1557       break;
1558     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1559       zxdg_surface_v6_ack_configure (impl->display_server.zxdg_surface_v6,
1560                                      impl->pending.serial);
1561       break;
1562     default:
1563       g_assert_not_reached ();
1564     }
1565 }
1566 
1567 static void
gdk_wayland_surface_configure_popup(GdkSurface * surface)1568 gdk_wayland_surface_configure_popup (GdkSurface *surface)
1569 {
1570   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1571   GdkRectangle parent_geometry;
1572   int x, y, width, height;
1573 
1574   if (impl->display_server.xdg_popup)
1575     {
1576       xdg_surface_ack_configure (impl->display_server.xdg_surface,
1577                                  impl->pending.serial);
1578     }
1579   else if (impl->display_server.zxdg_popup_v6)
1580     {
1581       zxdg_surface_v6_ack_configure (impl->display_server.zxdg_surface_v6,
1582                                      impl->pending.serial);
1583     }
1584 
1585   if (impl->pending.popup.has_repositioned_token)
1586     impl->received_reposition_token = impl->pending.popup.repositioned_token;
1587 
1588   switch (impl->popup_state)
1589     {
1590     case POPUP_STATE_WAITING_FOR_REPOSITIONED:
1591       if (impl->received_reposition_token != impl->reposition_token)
1592         return;
1593       else
1594         gdk_surface_thaw_updates (surface);
1595       G_GNUC_FALLTHROUGH;
1596     case POPUP_STATE_WAITING_FOR_CONFIGURE:
1597       impl->popup_state = POPUP_STATE_WAITING_FOR_FRAME;
1598       break;
1599     case POPUP_STATE_IDLE:
1600     case POPUP_STATE_WAITING_FOR_FRAME:
1601       break;
1602     default:
1603       g_assert_not_reached ();
1604     }
1605 
1606   x = impl->pending.popup.x;
1607   y = impl->pending.popup.y;
1608   width = impl->pending.popup.width;
1609   height = impl->pending.popup.height;
1610 
1611   gdk_wayland_surface_get_window_geometry (surface->parent, &parent_geometry);
1612   x += parent_geometry.x;
1613   y += parent_geometry.y;
1614 
1615   update_popup_layout_state (surface,
1616                              x, y,
1617                              width, height,
1618                              impl->popup.layout);
1619 
1620   impl->next_layout.popup.x = x;
1621   impl->next_layout.popup.y = y;
1622   impl->next_layout.configured_width = width;
1623   impl->next_layout.configured_height = height;
1624   impl->next_layout.surface_geometry_dirty = TRUE;
1625   gdk_surface_request_layout (surface);
1626 }
1627 
1628 static void
maybe_notify_mapped(GdkSurface * surface)1629 maybe_notify_mapped (GdkSurface *surface)
1630 {
1631   if (surface->destroyed)
1632     return;
1633 
1634   if (!GDK_SURFACE_IS_MAPPED (surface))
1635     gdk_surface_set_is_mapped (surface, TRUE);
1636 }
1637 
1638 static void
gdk_wayland_surface_configure(GdkSurface * surface)1639 gdk_wayland_surface_configure (GdkSurface *surface)
1640 {
1641   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1642 
1643   if (!impl->initial_configure_received)
1644     {
1645       gdk_surface_thaw_updates (surface);
1646       impl->initial_configure_received = TRUE;
1647       impl->pending.is_initial_configure = TRUE;
1648       maybe_notify_mapped (surface);
1649     }
1650 
1651   impl->has_uncommitted_ack_configure = TRUE;
1652 
1653   if (is_realized_popup (impl))
1654     gdk_wayland_surface_configure_popup (surface);
1655   else if (is_realized_toplevel (impl))
1656     gdk_wayland_surface_configure_toplevel (surface);
1657   else
1658     g_warn_if_reached ();
1659 
1660   impl->last_configure_serial = impl->pending.serial;
1661 
1662   memset (&impl->pending, 0, sizeof (impl->pending));
1663 }
1664 
1665 static void
gdk_wayland_surface_handle_configure(GdkSurface * surface,uint32_t serial)1666 gdk_wayland_surface_handle_configure (GdkSurface *surface,
1667                                       uint32_t    serial)
1668 {
1669   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1670 
1671   impl->pending.is_dirty = TRUE;
1672   impl->pending.serial = serial;
1673 
1674   if (impl->state_freeze_count > 0)
1675     return;
1676 
1677   gdk_wayland_surface_configure (surface);
1678 }
1679 
1680 static void
gdk_wayland_surface_handle_configure_toplevel(GdkSurface * surface,int32_t width,int32_t height,GdkToplevelState state)1681 gdk_wayland_surface_handle_configure_toplevel (GdkSurface      *surface,
1682                                                int32_t          width,
1683                                                int32_t          height,
1684                                                GdkToplevelState  state)
1685 {
1686   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1687 
1688   impl->pending.toplevel.state |= state;
1689   impl->pending.toplevel.width = width;
1690   impl->pending.toplevel.height = height;
1691 }
1692 
1693 static void
gdk_wayland_surface_handle_close(GdkSurface * surface)1694 gdk_wayland_surface_handle_close (GdkSurface *surface)
1695 {
1696   GdkDisplay *display;
1697   GdkEvent *event;
1698 
1699   display = gdk_surface_get_display (surface);
1700 
1701   GDK_DISPLAY_NOTE (display, EVENTS, g_message ("close %p", surface));
1702 
1703   event = gdk_delete_event_new (surface);
1704 
1705   _gdk_wayland_display_deliver_event (display, event);
1706 }
1707 
1708 static void
xdg_surface_configure(void * data,struct xdg_surface * xdg_surface,uint32_t serial)1709 xdg_surface_configure (void               *data,
1710                        struct xdg_surface *xdg_surface,
1711                        uint32_t            serial)
1712 {
1713   GdkSurface *surface = GDK_SURFACE (data);
1714 
1715   gdk_wayland_surface_handle_configure (surface, serial);
1716 }
1717 
1718 static const struct xdg_surface_listener xdg_surface_listener = {
1719   xdg_surface_configure,
1720 };
1721 
1722 static void
zxdg_surface_v6_configure(void * data,struct zxdg_surface_v6 * xdg_surface,uint32_t serial)1723 zxdg_surface_v6_configure (void                   *data,
1724                            struct zxdg_surface_v6 *xdg_surface,
1725                            uint32_t                serial)
1726 {
1727   GdkSurface *surface = GDK_SURFACE (data);
1728 
1729   gdk_wayland_surface_handle_configure (surface, serial);
1730 }
1731 
1732 static const struct zxdg_surface_v6_listener zxdg_surface_v6_listener = {
1733   zxdg_surface_v6_configure,
1734 };
1735 
1736 static void
gdk_wayland_surface_create_xdg_surface_resources(GdkSurface * surface)1737 gdk_wayland_surface_create_xdg_surface_resources (GdkSurface *surface)
1738 {
1739   GdkWaylandDisplay *display =
1740     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
1741   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1742 
1743   switch (display->shell_variant)
1744     {
1745     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1746       impl->display_server.xdg_surface =
1747         xdg_wm_base_get_xdg_surface (display->xdg_wm_base,
1748                                      impl->display_server.wl_surface);
1749       wl_proxy_set_queue ((struct wl_proxy *) impl->display_server.xdg_surface,
1750                           impl->event_queue);
1751       xdg_surface_add_listener (impl->display_server.xdg_surface,
1752                                 &xdg_surface_listener,
1753                                 surface);
1754       break;
1755     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1756       impl->display_server.zxdg_surface_v6 =
1757         zxdg_shell_v6_get_xdg_surface (display->zxdg_shell_v6,
1758                                        impl->display_server.wl_surface);
1759       zxdg_surface_v6_add_listener (impl->display_server.zxdg_surface_v6,
1760                                     &zxdg_surface_v6_listener,
1761                                     surface);
1762       break;
1763     default:
1764       g_assert_not_reached ();
1765     }
1766 }
1767 
1768 static void
xdg_toplevel_configure(void * data,struct xdg_toplevel * xdg_toplevel,int32_t width,int32_t height,struct wl_array * states)1769 xdg_toplevel_configure (void                *data,
1770                         struct xdg_toplevel *xdg_toplevel,
1771                         int32_t              width,
1772                         int32_t              height,
1773                         struct wl_array     *states)
1774 {
1775   GdkSurface *surface = GDK_SURFACE (data);
1776   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1777   uint32_t *p;
1778   GdkToplevelState pending_state = 0;
1779 
1780   impl->pending.toplevel.is_resizing = FALSE;
1781 
1782   wl_array_for_each (p, states)
1783     {
1784       uint32_t state = *p;
1785 
1786       switch (state)
1787         {
1788         case XDG_TOPLEVEL_STATE_FULLSCREEN:
1789           pending_state |= GDK_TOPLEVEL_STATE_FULLSCREEN;
1790           break;
1791         case XDG_TOPLEVEL_STATE_MAXIMIZED:
1792           pending_state |= GDK_TOPLEVEL_STATE_MAXIMIZED;
1793           break;
1794         case XDG_TOPLEVEL_STATE_ACTIVATED:
1795           pending_state |= GDK_TOPLEVEL_STATE_FOCUSED;
1796           break;
1797         case XDG_TOPLEVEL_STATE_RESIZING:
1798           impl->pending.toplevel.is_resizing = TRUE;
1799           break;
1800         default:
1801           /* Unknown state */
1802           break;
1803         }
1804     }
1805 
1806   gdk_wayland_surface_handle_configure_toplevel (surface, width, height,
1807                                                  pending_state);
1808 }
1809 
1810 static void
xdg_toplevel_close(void * data,struct xdg_toplevel * xdg_toplevel)1811 xdg_toplevel_close (void                *data,
1812                     struct xdg_toplevel *xdg_toplevel)
1813 {
1814   GdkSurface *surface = GDK_SURFACE (data);
1815 
1816   gdk_wayland_surface_handle_close (surface);
1817 }
1818 
1819 static const struct xdg_toplevel_listener xdg_toplevel_listener = {
1820   xdg_toplevel_configure,
1821   xdg_toplevel_close,
1822 };
1823 
1824 static void
create_xdg_toplevel_resources(GdkSurface * surface)1825 create_xdg_toplevel_resources (GdkSurface *surface)
1826 {
1827   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1828 
1829   impl->display_server.xdg_toplevel =
1830     xdg_surface_get_toplevel (impl->display_server.xdg_surface);
1831   xdg_toplevel_add_listener (impl->display_server.xdg_toplevel,
1832                              &xdg_toplevel_listener,
1833                              surface);
1834 }
1835 
1836 static void
zxdg_toplevel_v6_configure(void * data,struct zxdg_toplevel_v6 * xdg_toplevel,int32_t width,int32_t height,struct wl_array * states)1837 zxdg_toplevel_v6_configure (void                    *data,
1838                             struct zxdg_toplevel_v6 *xdg_toplevel,
1839                             int32_t                  width,
1840                             int32_t                  height,
1841                             struct wl_array         *states)
1842 {
1843   GdkSurface *surface = GDK_SURFACE (data);
1844   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1845   uint32_t *p;
1846   GdkToplevelState pending_state = 0;
1847 
1848   impl->pending.toplevel.is_resizing = FALSE;
1849 
1850   wl_array_for_each (p, states)
1851     {
1852       uint32_t state = *p;
1853 
1854       switch (state)
1855         {
1856         case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
1857           pending_state |= GDK_TOPLEVEL_STATE_FULLSCREEN;
1858           break;
1859         case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED:
1860           pending_state |= GDK_TOPLEVEL_STATE_MAXIMIZED;
1861           break;
1862         case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED:
1863           pending_state |= GDK_TOPLEVEL_STATE_FOCUSED;
1864           break;
1865         case ZXDG_TOPLEVEL_V6_STATE_RESIZING:
1866           impl->pending.toplevel.is_resizing = TRUE;
1867           break;
1868         default:
1869           /* Unknown state */
1870           break;
1871         }
1872     }
1873 
1874   gdk_wayland_surface_handle_configure_toplevel (surface, width, height,
1875                                                  pending_state);
1876 }
1877 
1878 static void
zxdg_toplevel_v6_close(void * data,struct zxdg_toplevel_v6 * xdg_toplevel)1879 zxdg_toplevel_v6_close (void                    *data,
1880                         struct zxdg_toplevel_v6 *xdg_toplevel)
1881 {
1882   GdkSurface *surface = GDK_SURFACE (data);
1883 
1884   gdk_wayland_surface_handle_close (surface);
1885 }
1886 
1887 static const struct zxdg_toplevel_v6_listener zxdg_toplevel_v6_listener = {
1888   zxdg_toplevel_v6_configure,
1889   zxdg_toplevel_v6_close,
1890 };
1891 
1892 static void
create_zxdg_toplevel_v6_resources(GdkSurface * surface)1893 create_zxdg_toplevel_v6_resources (GdkSurface *surface)
1894 {
1895   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1896 
1897   impl->display_server.zxdg_toplevel_v6 =
1898     zxdg_surface_v6_get_toplevel (impl->display_server.zxdg_surface_v6);
1899   zxdg_toplevel_v6_add_listener (impl->display_server.zxdg_toplevel_v6,
1900                                  &zxdg_toplevel_v6_listener,
1901                                  surface);
1902 }
1903 
1904 /**
1905  * gdk_wayland_toplevel_set_application_id:
1906  * @toplevel: (type GdkWaylandToplevel): a `GdkToplevel`
1907  * @application_id: the application id for the @toplevel
1908  *
1909  * Sets the application id on a `GdkToplevel`.
1910  */
1911 void
gdk_wayland_toplevel_set_application_id(GdkToplevel * toplevel,const char * application_id)1912 gdk_wayland_toplevel_set_application_id (GdkToplevel *toplevel,
1913                                          const char  *application_id)
1914 {
1915   GdkWaylandSurface *impl;
1916   GdkWaylandDisplay *display_wayland;
1917 
1918   g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel));
1919 
1920   g_return_if_fail (application_id != NULL);
1921 
1922   if (GDK_SURFACE_DESTROYED (toplevel))
1923     return;
1924 
1925   impl = GDK_WAYLAND_SURFACE (toplevel);
1926 
1927   if (!is_realized_toplevel (impl))
1928     return;
1929 
1930   display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (toplevel)));
1931 
1932   switch (display_wayland->shell_variant)
1933     {
1934     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1935       xdg_toplevel_set_app_id (impl->display_server.xdg_toplevel,
1936                                application_id);
1937       break;
1938     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1939       zxdg_toplevel_v6_set_app_id (impl->display_server.zxdg_toplevel_v6,
1940                                    application_id);
1941       break;
1942     default:
1943       g_assert_not_reached ();
1944     }
1945 }
1946 
1947 static void
gdk_wayland_surface_create_xdg_toplevel(GdkSurface * surface)1948 gdk_wayland_surface_create_xdg_toplevel (GdkSurface *surface)
1949 {
1950   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
1951   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
1952   const char *app_id;
1953 
1954   gdk_surface_freeze_updates (surface);
1955   gdk_wayland_surface_create_xdg_surface_resources (surface);
1956 
1957   switch (display_wayland->shell_variant)
1958     {
1959     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1960       create_xdg_toplevel_resources (surface);
1961       break;
1962     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1963       create_zxdg_toplevel_v6_resources (surface);
1964       break;
1965     default:
1966       g_assert_not_reached ();
1967     }
1968 
1969   gdk_wayland_surface_sync_parent (surface, NULL);
1970   gdk_wayland_surface_sync_parent_of_imported (impl);
1971   gdk_wayland_surface_sync_title (surface);
1972 
1973   switch (display_wayland->shell_variant)
1974     {
1975     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
1976       if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_MAXIMIZED)
1977         xdg_toplevel_set_maximized (impl->display_server.xdg_toplevel);
1978       if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_MINIMIZED)
1979         xdg_toplevel_set_minimized (impl->display_server.xdg_toplevel);
1980       if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_FULLSCREEN)
1981         xdg_toplevel_set_fullscreen (impl->display_server.xdg_toplevel,
1982                                      impl->initial_fullscreen_output);
1983       break;
1984     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
1985       if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_MAXIMIZED)
1986         zxdg_toplevel_v6_set_maximized (impl->display_server.zxdg_toplevel_v6);
1987       if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_MINIMIZED)
1988         zxdg_toplevel_v6_set_minimized (impl->display_server.zxdg_toplevel_v6);
1989       if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_FULLSCREEN)
1990         zxdg_toplevel_v6_set_fullscreen (impl->display_server.zxdg_toplevel_v6,
1991                                          impl->initial_fullscreen_output);
1992       break;
1993     default:
1994       g_assert_not_reached ();
1995     }
1996 
1997   impl->initial_fullscreen_output = NULL;
1998 
1999   app_id = impl->application.application_id;
2000   if (app_id == NULL)
2001     app_id = g_get_prgname ();
2002 
2003   if (app_id == NULL)
2004     app_id = "GTK Application";
2005 
2006   gdk_wayland_toplevel_set_application_id (GDK_TOPLEVEL (impl), app_id);
2007 
2008   maybe_set_gtk_surface_dbus_properties (impl);
2009   maybe_set_gtk_surface_modal (surface);
2010 
2011   gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "wayland", "surface commit");
2012   wl_surface_commit (impl->display_server.wl_surface);
2013 }
2014 
2015 static void
gdk_wayland_surface_handle_configure_popup(GdkSurface * surface,int32_t x,int32_t y,int32_t width,int32_t height)2016 gdk_wayland_surface_handle_configure_popup (GdkSurface *surface,
2017                                             int32_t     x,
2018                                             int32_t     y,
2019                                             int32_t     width,
2020                                             int32_t     height)
2021 {
2022   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
2023 
2024   impl->pending.popup.x = x;
2025   impl->pending.popup.y = y;
2026   impl->pending.popup.width = width;
2027   impl->pending.popup.height = height;
2028 }
2029 
2030 static void
xdg_popup_configure(void * data,struct xdg_popup * xdg_popup,int32_t x,int32_t y,int32_t width,int32_t height)2031 xdg_popup_configure (void             *data,
2032                      struct xdg_popup *xdg_popup,
2033                      int32_t           x,
2034                      int32_t           y,
2035                      int32_t           width,
2036                      int32_t           height)
2037 {
2038   GdkSurface *surface = GDK_SURFACE (data);
2039 
2040   gdk_wayland_surface_handle_configure_popup (surface, x, y, width, height);
2041 }
2042 
2043 static void
xdg_popup_done(void * data,struct xdg_popup * xdg_popup)2044 xdg_popup_done (void             *data,
2045                 struct xdg_popup *xdg_popup)
2046 {
2047   GdkSurface *surface = GDK_SURFACE (data);
2048 
2049   GDK_DISPLAY_NOTE (gdk_surface_get_display (surface), EVENTS, g_message ("done %p", surface));
2050 
2051   gdk_surface_hide (surface);
2052 }
2053 
2054 static void
xdg_popup_repositioned(void * data,struct xdg_popup * xdg_popup,uint32_t token)2055 xdg_popup_repositioned (void             *data,
2056                         struct xdg_popup *xdg_popup,
2057                         uint32_t          token)
2058 {
2059   GdkSurface *surface = GDK_SURFACE (data);
2060   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
2061 
2062   GDK_DISPLAY_NOTE (gdk_surface_get_display (surface), EVENTS,
2063                     g_message ("repositioned %p", surface));
2064 
2065   if (impl->popup_state != POPUP_STATE_WAITING_FOR_REPOSITIONED)
2066     {
2067       g_warning ("Unexpected xdg_popup.repositioned event, probably buggy compositor");
2068       return;
2069     }
2070 
2071   impl->pending.popup.repositioned_token = token;
2072   impl->pending.popup.has_repositioned_token = TRUE;
2073 }
2074 
2075 static const struct xdg_popup_listener xdg_popup_listener = {
2076   xdg_popup_configure,
2077   xdg_popup_done,
2078   xdg_popup_repositioned,
2079 };
2080 
2081 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)2082 zxdg_popup_v6_configure (void                 *data,
2083                          struct zxdg_popup_v6 *xdg_popup,
2084                          int32_t               x,
2085                          int32_t               y,
2086                          int32_t               width,
2087                          int32_t               height)
2088 {
2089   GdkSurface *surface = GDK_SURFACE (data);
2090 
2091   gdk_wayland_surface_handle_configure_popup (surface, x, y, width, height);
2092 }
2093 
2094 static void
zxdg_popup_v6_done(void * data,struct zxdg_popup_v6 * xdg_popup)2095 zxdg_popup_v6_done (void                 *data,
2096                     struct zxdg_popup_v6 *xdg_popup)
2097 {
2098   GdkSurface *surface = GDK_SURFACE (data);
2099 
2100   GDK_NOTE (EVENTS,
2101             g_message ("done %p", surface));
2102 
2103   gdk_surface_hide (surface);
2104 }
2105 
2106 static const struct zxdg_popup_v6_listener zxdg_popup_v6_listener = {
2107   zxdg_popup_v6_configure,
2108   zxdg_popup_v6_done,
2109 };
2110 
2111 static enum xdg_positioner_anchor
rect_anchor_to_anchor(GdkGravity rect_anchor)2112 rect_anchor_to_anchor (GdkGravity rect_anchor)
2113 {
2114   switch (rect_anchor)
2115     {
2116     case GDK_GRAVITY_NORTH_WEST:
2117     case GDK_GRAVITY_STATIC:
2118       return XDG_POSITIONER_ANCHOR_TOP_LEFT;
2119     case GDK_GRAVITY_NORTH:
2120       return XDG_POSITIONER_ANCHOR_TOP;
2121     case GDK_GRAVITY_NORTH_EAST:
2122       return XDG_POSITIONER_ANCHOR_TOP_RIGHT;
2123     case GDK_GRAVITY_WEST:
2124       return XDG_POSITIONER_ANCHOR_LEFT;
2125     case GDK_GRAVITY_CENTER:
2126       return XDG_POSITIONER_ANCHOR_NONE;
2127     case GDK_GRAVITY_EAST:
2128       return XDG_POSITIONER_ANCHOR_RIGHT;
2129     case GDK_GRAVITY_SOUTH_WEST:
2130       return XDG_POSITIONER_ANCHOR_BOTTOM_LEFT;
2131     case GDK_GRAVITY_SOUTH:
2132       return XDG_POSITIONER_ANCHOR_BOTTOM;
2133     case GDK_GRAVITY_SOUTH_EAST:
2134       return XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT;
2135     default:
2136       g_assert_not_reached ();
2137     }
2138 }
2139 
2140 static enum xdg_positioner_gravity
surface_anchor_to_gravity(GdkGravity rect_anchor)2141 surface_anchor_to_gravity (GdkGravity rect_anchor)
2142 {
2143   switch (rect_anchor)
2144     {
2145     case GDK_GRAVITY_NORTH_WEST:
2146     case GDK_GRAVITY_STATIC:
2147       return XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT;
2148     case GDK_GRAVITY_NORTH:
2149       return XDG_POSITIONER_GRAVITY_BOTTOM;
2150     case GDK_GRAVITY_NORTH_EAST:
2151       return XDG_POSITIONER_GRAVITY_BOTTOM_LEFT;
2152     case GDK_GRAVITY_WEST:
2153       return XDG_POSITIONER_GRAVITY_RIGHT;
2154     case GDK_GRAVITY_CENTER:
2155       return XDG_POSITIONER_GRAVITY_NONE;
2156     case GDK_GRAVITY_EAST:
2157       return XDG_POSITIONER_GRAVITY_LEFT;
2158     case GDK_GRAVITY_SOUTH_WEST:
2159       return XDG_POSITIONER_GRAVITY_TOP_RIGHT;
2160     case GDK_GRAVITY_SOUTH:
2161       return XDG_POSITIONER_GRAVITY_TOP;
2162     case GDK_GRAVITY_SOUTH_EAST:
2163       return XDG_POSITIONER_GRAVITY_TOP_LEFT;
2164     default:
2165       g_assert_not_reached ();
2166     }
2167 }
2168 
2169 static enum zxdg_positioner_v6_anchor
rect_anchor_to_anchor_legacy(GdkGravity rect_anchor)2170 rect_anchor_to_anchor_legacy (GdkGravity rect_anchor)
2171 {
2172   switch (rect_anchor)
2173     {
2174     case GDK_GRAVITY_NORTH_WEST:
2175     case GDK_GRAVITY_STATIC:
2176       return (ZXDG_POSITIONER_V6_ANCHOR_TOP |
2177               ZXDG_POSITIONER_V6_ANCHOR_LEFT);
2178     case GDK_GRAVITY_NORTH:
2179       return ZXDG_POSITIONER_V6_ANCHOR_TOP;
2180     case GDK_GRAVITY_NORTH_EAST:
2181       return (ZXDG_POSITIONER_V6_ANCHOR_TOP |
2182               ZXDG_POSITIONER_V6_ANCHOR_RIGHT);
2183     case GDK_GRAVITY_WEST:
2184       return ZXDG_POSITIONER_V6_ANCHOR_LEFT;
2185     case GDK_GRAVITY_CENTER:
2186       return ZXDG_POSITIONER_V6_ANCHOR_NONE;
2187     case GDK_GRAVITY_EAST:
2188       return ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
2189     case GDK_GRAVITY_SOUTH_WEST:
2190       return (ZXDG_POSITIONER_V6_ANCHOR_BOTTOM |
2191               ZXDG_POSITIONER_V6_ANCHOR_LEFT);
2192     case GDK_GRAVITY_SOUTH:
2193       return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM;
2194     case GDK_GRAVITY_SOUTH_EAST:
2195       return (ZXDG_POSITIONER_V6_ANCHOR_BOTTOM |
2196               ZXDG_POSITIONER_V6_ANCHOR_RIGHT);
2197     default:
2198       g_assert_not_reached ();
2199     }
2200 
2201   return (ZXDG_POSITIONER_V6_ANCHOR_TOP |
2202           ZXDG_POSITIONER_V6_ANCHOR_LEFT);
2203 }
2204 
2205 static enum zxdg_positioner_v6_gravity
surface_anchor_to_gravity_legacy(GdkGravity rect_anchor)2206 surface_anchor_to_gravity_legacy (GdkGravity rect_anchor)
2207 {
2208   switch (rect_anchor)
2209     {
2210     case GDK_GRAVITY_NORTH_WEST:
2211     case GDK_GRAVITY_STATIC:
2212       return (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
2213               ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
2214     case GDK_GRAVITY_NORTH:
2215       return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM;
2216     case GDK_GRAVITY_NORTH_EAST:
2217       return (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
2218               ZXDG_POSITIONER_V6_GRAVITY_LEFT);
2219     case GDK_GRAVITY_WEST:
2220       return ZXDG_POSITIONER_V6_GRAVITY_RIGHT;
2221     case GDK_GRAVITY_CENTER:
2222       return ZXDG_POSITIONER_V6_GRAVITY_NONE;
2223     case GDK_GRAVITY_EAST:
2224       return ZXDG_POSITIONER_V6_GRAVITY_LEFT;
2225     case GDK_GRAVITY_SOUTH_WEST:
2226       return (ZXDG_POSITIONER_V6_GRAVITY_TOP |
2227               ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
2228     case GDK_GRAVITY_SOUTH:
2229       return ZXDG_POSITIONER_V6_GRAVITY_TOP;
2230     case GDK_GRAVITY_SOUTH_EAST:
2231       return (ZXDG_POSITIONER_V6_GRAVITY_TOP |
2232               ZXDG_POSITIONER_V6_GRAVITY_LEFT);
2233     default:
2234       g_assert_not_reached ();
2235     }
2236 
2237   return (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
2238           ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
2239 }
2240 
2241 void
gdk_wayland_toplevel_announce_csd(GdkToplevel * toplevel)2242 gdk_wayland_toplevel_announce_csd (GdkToplevel *toplevel)
2243 {
2244   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (toplevel)));
2245   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (toplevel);
2246 
2247   g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel));
2248 
2249   if (!display_wayland->server_decoration_manager)
2250     return;
2251   impl->display_server.server_decoration =
2252     org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
2253                                                   impl->display_server.wl_surface);
2254   if (impl->display_server.server_decoration)
2255     org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration,
2256                                                 ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT);
2257 }
2258 
2259 void
gdk_wayland_toplevel_announce_ssd(GdkToplevel * toplevel)2260 gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel)
2261 {
2262   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (toplevel)));
2263   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (toplevel);
2264 
2265   g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel));
2266 
2267   if (!display_wayland->server_decoration_manager)
2268     return;
2269   impl->display_server.server_decoration =
2270     org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
2271                                                   impl->display_server.wl_surface);
2272   if (impl->display_server.server_decoration)
2273     org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration,
2274                                                 ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER);
2275 }
2276 
2277 gboolean
gdk_wayland_toplevel_inhibit_idle(GdkToplevel * toplevel)2278 gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel)
2279 {
2280   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (toplevel)));
2281   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (toplevel);
2282 
2283   g_return_val_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel), FALSE);
2284 
2285   if (!display_wayland->idle_inhibit_manager)
2286     return FALSE;
2287 
2288   if (!impl->idle_inhibitor)
2289     {
2290       g_assert (impl->idle_inhibitor_refcount == 0);
2291       impl->idle_inhibitor =
2292         zwp_idle_inhibit_manager_v1_create_inhibitor (display_wayland->idle_inhibit_manager,
2293                                                      impl->display_server.wl_surface);
2294     }
2295   ++impl->idle_inhibitor_refcount;
2296 
2297   return TRUE;
2298 }
2299 
2300 void
gdk_wayland_toplevel_uninhibit_idle(GdkToplevel * toplevel)2301 gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel)
2302 {
2303   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (toplevel);
2304 
2305   g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel));
2306 
2307   g_assert (impl->idle_inhibitor && impl->idle_inhibitor_refcount > 0);
2308 
2309   if (--impl->idle_inhibitor_refcount == 0)
2310     {
2311       zwp_idle_inhibitor_v1_destroy (impl->idle_inhibitor);
2312       impl->idle_inhibitor = NULL;
2313     }
2314 }
2315 
2316 static void
calculate_popup_rect(GdkSurface * surface,GdkPopupLayout * layout,GdkRectangle * out_rect)2317 calculate_popup_rect (GdkSurface     *surface,
2318                       GdkPopupLayout *layout,
2319                       GdkRectangle   *out_rect)
2320 {
2321   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
2322   int width, height;
2323   GdkRectangle anchor_rect;
2324   int dx, dy;
2325   int shadow_left, shadow_right, shadow_top, shadow_bottom;
2326   int x = 0, y = 0;
2327 
2328   gdk_popup_layout_get_shadow_width (layout,
2329                                      &shadow_left,
2330                                      &shadow_right,
2331                                      &shadow_top,
2332                                      &shadow_bottom);
2333 
2334   width = (impl->popup.unconstrained_width - (shadow_left + shadow_right));
2335   height = (impl->popup.unconstrained_height - (shadow_top + shadow_bottom));
2336 
2337   anchor_rect = *gdk_popup_layout_get_anchor_rect (layout);
2338   gdk_popup_layout_get_offset (layout, &dx, &dy);
2339   anchor_rect.x += dx;
2340   anchor_rect.y += dy;
2341 
2342   switch (gdk_popup_layout_get_rect_anchor (layout))
2343     {
2344     default:
2345     case GDK_GRAVITY_STATIC:
2346     case GDK_GRAVITY_NORTH_WEST:
2347       x = anchor_rect.x;
2348       y = anchor_rect.y;
2349       break;
2350     case GDK_GRAVITY_NORTH:
2351       x = anchor_rect.x + (anchor_rect.width / 2);
2352       y = anchor_rect.y;
2353       break;
2354     case GDK_GRAVITY_NORTH_EAST:
2355       x = anchor_rect.x + anchor_rect.width;
2356       y = anchor_rect.y;
2357       break;
2358     case GDK_GRAVITY_WEST:
2359       x = anchor_rect.x;
2360       y = anchor_rect.y + (anchor_rect.height / 2);
2361       break;
2362     case GDK_GRAVITY_CENTER:
2363       x = anchor_rect.x + (anchor_rect.width / 2);
2364       y = anchor_rect.y + (anchor_rect.height / 2);
2365       break;
2366     case GDK_GRAVITY_EAST:
2367       x = anchor_rect.x + anchor_rect.width;
2368       y = anchor_rect.y + (anchor_rect.height / 2);
2369       break;
2370     case GDK_GRAVITY_SOUTH_WEST:
2371       x = anchor_rect.x;
2372       y = anchor_rect.y + anchor_rect.height;
2373       break;
2374     case GDK_GRAVITY_SOUTH:
2375       x = anchor_rect.x + (anchor_rect.width / 2);
2376       y = anchor_rect.y + anchor_rect.height;
2377       break;
2378     case GDK_GRAVITY_SOUTH_EAST:
2379       x = anchor_rect.x + anchor_rect.width;
2380       y = anchor_rect.y + anchor_rect.height;
2381       break;
2382     }
2383 
2384   switch (gdk_popup_layout_get_surface_anchor (layout))
2385     {
2386     default:
2387     case GDK_GRAVITY_STATIC:
2388     case GDK_GRAVITY_NORTH_WEST:
2389       break;
2390     case GDK_GRAVITY_NORTH:
2391       x -= width / 2;
2392       break;
2393     case GDK_GRAVITY_NORTH_EAST:
2394       x -= width;
2395       break;
2396     case GDK_GRAVITY_WEST:
2397       y -= height / 2;
2398       break;
2399     case GDK_GRAVITY_CENTER:
2400       x -= width / 2;
2401       y -= height / 2;
2402       break;
2403     case GDK_GRAVITY_EAST:
2404       x -= width;
2405       y -= height / 2;
2406       break;
2407     case GDK_GRAVITY_SOUTH_WEST:
2408       y -= height;
2409       break;
2410     case GDK_GRAVITY_SOUTH:
2411       x -= width / 2;
2412       y -= height;
2413       break;
2414     case GDK_GRAVITY_SOUTH_EAST:
2415       x -= width;
2416       y -= height;
2417       break;
2418     }
2419 
2420   *out_rect = (GdkRectangle) {
2421     .x = x,
2422     .y = y,
2423     .width = width,
2424     .height = height
2425   };
2426 }
2427 
2428 static void
update_popup_layout_state(GdkSurface * surface,int x,int y,int width,int height,GdkPopupLayout * layout)2429 update_popup_layout_state (GdkSurface     *surface,
2430                            int             x,
2431                            int             y,
2432                            int             width,
2433                            int             height,
2434                            GdkPopupLayout *layout)
2435 {
2436   GdkRectangle best_rect;
2437   GdkRectangle flipped_rect;
2438   GdkGravity rect_anchor;
2439   GdkGravity surface_anchor;
2440   GdkAnchorHints anchor_hints;
2441 
2442   rect_anchor = gdk_popup_layout_get_rect_anchor (layout);
2443   surface_anchor = gdk_popup_layout_get_surface_anchor (layout);
2444   anchor_hints = gdk_popup_layout_get_anchor_hints (layout);
2445 
2446   calculate_popup_rect (surface, layout, &best_rect);
2447 
2448   flipped_rect = best_rect;
2449 
2450   if (x != best_rect.x &&
2451       anchor_hints & GDK_ANCHOR_FLIP_X)
2452     {
2453       GdkRectangle flipped_x_rect;
2454       GdkGravity flipped_rect_anchor;
2455       GdkGravity flipped_surface_anchor;
2456       GdkPopupLayout *flipped_layout;
2457 
2458       flipped_rect_anchor = gdk_gravity_flip_horizontally (rect_anchor);
2459       flipped_surface_anchor = gdk_gravity_flip_horizontally (surface_anchor);
2460       flipped_layout = gdk_popup_layout_copy (layout);
2461       gdk_popup_layout_set_rect_anchor (flipped_layout,
2462                                         flipped_rect_anchor);
2463       gdk_popup_layout_set_surface_anchor (flipped_layout,
2464                                            flipped_surface_anchor);
2465       calculate_popup_rect (surface,
2466                             flipped_layout,
2467                             &flipped_x_rect);
2468       gdk_popup_layout_unref (flipped_layout);
2469 
2470       if (flipped_x_rect.x == x)
2471         flipped_rect.x = x;
2472     }
2473   if (y != best_rect.y &&
2474       anchor_hints & GDK_ANCHOR_FLIP_Y)
2475     {
2476       GdkRectangle flipped_y_rect;
2477       GdkGravity flipped_rect_anchor;
2478       GdkGravity flipped_surface_anchor;
2479       GdkPopupLayout *flipped_layout;
2480 
2481       flipped_rect_anchor = gdk_gravity_flip_vertically (rect_anchor);
2482       flipped_surface_anchor = gdk_gravity_flip_vertically (surface_anchor);
2483       flipped_layout = gdk_popup_layout_copy (layout);
2484       gdk_popup_layout_set_rect_anchor (flipped_layout,
2485                                         flipped_rect_anchor);
2486       gdk_popup_layout_set_surface_anchor (flipped_layout,
2487                                            flipped_surface_anchor);
2488       calculate_popup_rect (surface,
2489                             flipped_layout,
2490                             &flipped_y_rect);
2491       gdk_popup_layout_unref (flipped_layout);
2492 
2493       if (flipped_y_rect.y == y)
2494         flipped_rect.y = y;
2495     }
2496 
2497   if (flipped_rect.x != best_rect.x)
2498     {
2499       rect_anchor = gdk_gravity_flip_horizontally (rect_anchor);
2500       surface_anchor = gdk_gravity_flip_horizontally (surface_anchor);
2501     }
2502   if (flipped_rect.y != best_rect.y)
2503     {
2504       rect_anchor = gdk_gravity_flip_vertically (rect_anchor);
2505       surface_anchor = gdk_gravity_flip_vertically (surface_anchor);
2506     }
2507 
2508   surface->popup.rect_anchor = rect_anchor;
2509   surface->popup.surface_anchor = surface_anchor;
2510 }
2511 
2512 static gpointer
create_dynamic_positioner(GdkSurface * surface,int width,int height,GdkPopupLayout * layout,gboolean ack_parent_configure)2513 create_dynamic_positioner (GdkSurface     *surface,
2514                            int             width,
2515                            int             height,
2516                            GdkPopupLayout *layout,
2517                            gboolean        ack_parent_configure)
2518 {
2519   GdkSurface *parent = surface->parent;
2520   GdkWaylandSurface *parent_impl = GDK_WAYLAND_SURFACE (parent);
2521   GdkWaylandDisplay *display =
2522     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
2523   GdkRectangle geometry;
2524   uint32_t constraint_adjustment = ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE;
2525   const GdkRectangle *anchor_rect;
2526   int real_anchor_rect_x, real_anchor_rect_y;
2527   int anchor_rect_width, anchor_rect_height;
2528   int rect_anchor_dx;
2529   int rect_anchor_dy;
2530   GdkGravity rect_anchor;
2531   GdkGravity surface_anchor;
2532   GdkAnchorHints anchor_hints;
2533   GdkRectangle parent_geometry;
2534   int shadow_left;
2535   int shadow_right;
2536   int shadow_top;
2537   int shadow_bottom;
2538 
2539   gdk_popup_layout_get_shadow_width (layout,
2540                                      &shadow_left,
2541                                      &shadow_right,
2542                                      &shadow_top,
2543                                      &shadow_bottom);
2544   geometry = (GdkRectangle) {
2545     .x = shadow_left,
2546     .y = shadow_top,
2547     .width = width - (shadow_left + shadow_right),
2548     .height = height - (shadow_top + shadow_bottom),
2549   };
2550 
2551   gdk_wayland_surface_get_window_geometry (surface->parent, &parent_geometry);
2552 
2553   anchor_rect = gdk_popup_layout_get_anchor_rect (layout);
2554   real_anchor_rect_x = anchor_rect->x - parent_geometry.x;
2555   real_anchor_rect_y = anchor_rect->y - parent_geometry.y;
2556 
2557   anchor_rect_width = MAX (anchor_rect->width, 1);
2558   anchor_rect_height = MAX (anchor_rect->height, 1);
2559 
2560   gdk_popup_layout_get_offset (layout, &rect_anchor_dx, &rect_anchor_dy);
2561 
2562   rect_anchor = gdk_popup_layout_get_rect_anchor (layout);
2563   surface_anchor = gdk_popup_layout_get_surface_anchor (layout);
2564 
2565   anchor_hints = gdk_popup_layout_get_anchor_hints (layout);
2566 
2567   switch (display->shell_variant)
2568     {
2569     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
2570       {
2571         struct xdg_positioner *positioner;
2572         enum xdg_positioner_anchor anchor;
2573         enum xdg_positioner_gravity gravity;
2574 
2575         positioner = xdg_wm_base_create_positioner (display->xdg_wm_base);
2576 
2577         xdg_positioner_set_size (positioner, geometry.width, geometry.height);
2578         xdg_positioner_set_anchor_rect (positioner,
2579                                         real_anchor_rect_x,
2580                                         real_anchor_rect_y,
2581                                         anchor_rect_width,
2582                                         anchor_rect_height);
2583         xdg_positioner_set_offset (positioner, rect_anchor_dx, rect_anchor_dy);
2584 
2585         anchor = rect_anchor_to_anchor (rect_anchor);
2586         xdg_positioner_set_anchor (positioner, anchor);
2587 
2588         gravity = surface_anchor_to_gravity (surface_anchor);
2589         xdg_positioner_set_gravity (positioner, gravity);
2590 
2591         if (anchor_hints & GDK_ANCHOR_FLIP_X)
2592           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X;
2593         if (anchor_hints & GDK_ANCHOR_FLIP_Y)
2594           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y;
2595         if (anchor_hints & GDK_ANCHOR_SLIDE_X)
2596           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X;
2597         if (anchor_hints & GDK_ANCHOR_SLIDE_Y)
2598           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y;
2599         if (anchor_hints & GDK_ANCHOR_RESIZE_X)
2600           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X;
2601         if (anchor_hints & GDK_ANCHOR_RESIZE_Y)
2602           constraint_adjustment |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y;
2603         xdg_positioner_set_constraint_adjustment (positioner,
2604                                                   constraint_adjustment);
2605 
2606         if (xdg_positioner_get_version (positioner) >=
2607             XDG_POSITIONER_SET_REACTIVE_SINCE_VERSION)
2608           xdg_positioner_set_reactive (positioner);
2609 
2610         if (ack_parent_configure &&
2611             xdg_positioner_get_version (positioner) >=
2612             XDG_POSITIONER_SET_PARENT_CONFIGURE_SINCE_VERSION)
2613           {
2614             xdg_positioner_set_parent_size (positioner,
2615                                             parent_geometry.width,
2616                                             parent_geometry.height);
2617             xdg_positioner_set_parent_configure (positioner,
2618                                                  parent_impl->last_configure_serial);
2619           }
2620 
2621         return positioner;
2622       }
2623     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
2624       {
2625         struct zxdg_positioner_v6 *positioner;
2626         enum zxdg_positioner_v6_anchor anchor;
2627         enum zxdg_positioner_v6_gravity gravity;
2628 
2629         positioner = zxdg_shell_v6_create_positioner (display->zxdg_shell_v6);
2630 
2631         zxdg_positioner_v6_set_size (positioner, geometry.width, geometry.height);
2632         zxdg_positioner_v6_set_anchor_rect (positioner,
2633                                             real_anchor_rect_x,
2634                                             real_anchor_rect_y,
2635                                             anchor_rect_width,
2636                                             anchor_rect_height);
2637         zxdg_positioner_v6_set_offset (positioner,
2638                                        rect_anchor_dx,
2639                                        rect_anchor_dy);
2640 
2641         anchor = rect_anchor_to_anchor_legacy (rect_anchor);
2642         zxdg_positioner_v6_set_anchor (positioner, anchor);
2643 
2644         gravity = surface_anchor_to_gravity_legacy (surface_anchor);
2645         zxdg_positioner_v6_set_gravity (positioner, gravity);
2646 
2647         if (anchor_hints & GDK_ANCHOR_FLIP_X)
2648           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X;
2649         if (anchor_hints & GDK_ANCHOR_FLIP_Y)
2650           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y;
2651         if (anchor_hints & GDK_ANCHOR_SLIDE_X)
2652           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X;
2653         if (anchor_hints & GDK_ANCHOR_SLIDE_Y)
2654           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y;
2655         if (anchor_hints & GDK_ANCHOR_RESIZE_X)
2656           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X;
2657         if (anchor_hints & GDK_ANCHOR_RESIZE_Y)
2658           constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y;
2659         zxdg_positioner_v6_set_constraint_adjustment (positioner,
2660                                                       constraint_adjustment);
2661 
2662         return positioner;
2663       }
2664     default:
2665       g_assert_not_reached ();
2666     }
2667 
2668   g_assert_not_reached ();
2669 }
2670 
2671 static gboolean
can_map_grabbing_popup(GdkSurface * surface,GdkSurface * parent)2672 can_map_grabbing_popup (GdkSurface *surface,
2673                         GdkSurface *parent)
2674 {
2675   GdkDisplay *display = gdk_surface_get_display (surface);
2676   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
2677   GdkSurface *top_most_popup;
2678 
2679   if (!display_wayland->current_grabbing_popups)
2680     return TRUE;
2681 
2682   top_most_popup = g_list_first (display_wayland->current_grabbing_popups)->data;
2683   return top_most_popup == parent;
2684 }
2685 
2686 static gboolean
gdk_wayland_surface_create_xdg_popup(GdkSurface * surface,GdkSurface * parent,GdkWaylandSeat * grab_input_seat,int width,int height,GdkPopupLayout * layout)2687 gdk_wayland_surface_create_xdg_popup (GdkSurface     *surface,
2688                                       GdkSurface     *parent,
2689                                       GdkWaylandSeat *grab_input_seat,
2690                                       int             width,
2691                                       int             height,
2692                                       GdkPopupLayout *layout)
2693 {
2694   GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
2695   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
2696   GdkWaylandSurface *parent_impl = GDK_WAYLAND_SURFACE (parent);
2697   gpointer positioner;
2698 
2699   if (!impl->display_server.wl_surface)
2700     return FALSE;
2701 
2702   if (!is_realized_shell_surface (parent_impl))
2703     return FALSE;
2704 
2705   if (is_realized_toplevel (impl))
2706     {
2707       g_warning ("Can't map popup, already mapped as toplevel");
2708       return FALSE;
2709     }
2710   if (is_realized_popup (impl))
2711     {
2712       g_warning ("Can't map popup, already mapped");
2713       return FALSE;
2714     }
2715 
2716   if (grab_input_seat &&
2717       !can_map_grabbing_popup (surface, parent))
2718     {
2719       g_warning ("Tried to map a grabbing popup with a non-top most parent");
2720       return FALSE;
2721     }
2722 
2723   gdk_surface_freeze_updates (surface);
2724 
2725   positioner = create_dynamic_positioner (surface, width, height, layout, FALSE);
2726   gdk_wayland_surface_create_xdg_surface_resources (surface);
2727 
2728   switch (display->shell_variant)
2729     {
2730     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
2731       impl->display_server.xdg_popup =
2732         xdg_surface_get_popup (impl->display_server.xdg_surface,
2733                                parent_impl->display_server.xdg_surface,
2734                                positioner);
2735       xdg_popup_add_listener (impl->display_server.xdg_popup,
2736                               &xdg_popup_listener,
2737                               surface);
2738       xdg_positioner_destroy (positioner);
2739       break;
2740     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
2741       impl->display_server.zxdg_popup_v6 =
2742         zxdg_surface_v6_get_popup (impl->display_server.zxdg_surface_v6,
2743                                    parent_impl->display_server.zxdg_surface_v6,
2744                                    positioner);
2745       zxdg_popup_v6_add_listener (impl->display_server.zxdg_popup_v6,
2746                                   &zxdg_popup_v6_listener,
2747                                   surface);
2748       zxdg_positioner_v6_destroy (positioner);
2749       break;
2750     default:
2751       g_assert_not_reached ();
2752     }
2753 
2754   gdk_popup_layout_get_shadow_width (layout,
2755                                      &impl->shadow_left,
2756                                      &impl->shadow_right,
2757                                      &impl->shadow_top,
2758                                      &impl->shadow_bottom);
2759 
2760   if (grab_input_seat)
2761     {
2762       struct wl_seat *seat;
2763       guint32 serial;
2764 
2765       seat = gdk_wayland_seat_get_wl_seat (GDK_SEAT (grab_input_seat));
2766       serial = _gdk_wayland_seat_get_last_implicit_grab_serial (grab_input_seat, NULL);
2767 
2768       switch (display->shell_variant)
2769         {
2770         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
2771           xdg_popup_grab (impl->display_server.xdg_popup, seat, serial);
2772           break;
2773         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
2774           zxdg_popup_v6_grab (impl->display_server.zxdg_popup_v6, seat, serial);
2775           break;
2776         default:
2777           g_assert_not_reached ();
2778         }
2779     }
2780 
2781   gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "wayland", "surface commit");
2782   wl_surface_commit (impl->display_server.wl_surface);
2783 
2784   if (GDK_IS_POPUP (surface))
2785     {
2786       g_assert (impl->popup_state == POPUP_STATE_IDLE);
2787       impl->popup_state = POPUP_STATE_WAITING_FOR_CONFIGURE;
2788       freeze_popup_toplevel_state (surface);
2789     }
2790 
2791   display->current_popups = g_list_append (display->current_popups, surface);
2792   if (grab_input_seat)
2793     {
2794       display->current_grabbing_popups =
2795         g_list_prepend (display->current_grabbing_popups, surface);
2796     }
2797 
2798   return TRUE;
2799 }
2800 
2801 static GdkWaylandSeat *
find_grab_input_seat(GdkSurface * surface,GdkSurface * parent)2802 find_grab_input_seat (GdkSurface *surface,
2803                       GdkSurface *parent)
2804 {
2805   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
2806   GdkWaylandSurface *tmp_impl;
2807 
2808   /* Use the device that was used for the grab as the device for
2809    * the popup surface setup - so this relies on GTK taking the
2810    * grab before showing the popup surface.
2811    */
2812   if (impl->grab_input_seat)
2813     return GDK_WAYLAND_SEAT (impl->grab_input_seat);
2814 
2815   while (parent)
2816     {
2817       tmp_impl = GDK_WAYLAND_SURFACE (parent);
2818 
2819       if (tmp_impl->grab_input_seat)
2820         return GDK_WAYLAND_SEAT (tmp_impl->grab_input_seat);
2821 
2822       parent = parent->parent;
2823     }
2824 
2825   return NULL;
2826 }
2827 
2828 static gboolean
should_be_mapped(GdkSurface * surface)2829 should_be_mapped (GdkSurface *surface)
2830 {
2831   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
2832 
2833   /* Don't map crazy temp that GTK uses for internal X11 shenanigans. */
2834   if (GDK_IS_DRAG_SURFACE (surface) && surface->x < 0 && surface->y < 0)
2835     return FALSE;
2836 
2837   if (impl->is_drag_surface)
2838     return FALSE;
2839 
2840   return TRUE;
2841 }
2842 
2843 static void
gdk_wayland_surface_map_toplevel(GdkSurface * surface)2844 gdk_wayland_surface_map_toplevel (GdkSurface *surface)
2845 {
2846   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
2847 
2848   if (!should_be_mapped (surface))
2849     return;
2850 
2851   if (impl->mapped)
2852     return;
2853 
2854   gdk_wayland_surface_create_xdg_toplevel (surface);
2855 
2856   impl->mapped = TRUE;
2857 }
2858 
2859 static void
gdk_wayland_surface_show(GdkSurface * surface,gboolean already_mapped)2860 gdk_wayland_surface_show (GdkSurface *surface,
2861                           gboolean    already_mapped)
2862 {
2863   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
2864 
2865   if (!impl->display_server.wl_surface)
2866     gdk_wayland_surface_create_surface (surface);
2867 
2868   gdk_wayland_surface_map_toplevel (surface);
2869 }
2870 
2871 static void
unmap_popups_for_surface(GdkSurface * surface)2872 unmap_popups_for_surface (GdkSurface *surface)
2873 {
2874   GdkWaylandDisplay *display_wayland;
2875   GList *l;
2876 
2877   display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
2878   for (l = display_wayland->current_popups; l; l = l->next)
2879     {
2880        GdkSurface *popup = l->data;
2881 
2882        if (popup->parent == surface)
2883          {
2884            g_warning ("Tried to unmap the parent of a popup");
2885            gdk_surface_hide (popup);
2886 
2887            return;
2888          }
2889     }
2890 }
2891 
2892 static void
gdk_wayland_surface_hide_surface(GdkSurface * surface)2893 gdk_wayland_surface_hide_surface (GdkSurface *surface)
2894 {
2895   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
2896   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
2897 
2898   unmap_popups_for_surface (surface);
2899 
2900   if (impl->display_server.wl_surface)
2901     {
2902       if (impl->egl_surface)
2903         {
2904           eglDestroySurface (display_wayland->egl_display, impl->egl_surface);
2905           impl->egl_surface = NULL;
2906         }
2907 
2908       if (impl->display_server.egl_window)
2909         {
2910           wl_egl_window_destroy (impl->display_server.egl_window);
2911           impl->display_server.egl_window = NULL;
2912         }
2913 
2914       if (impl->display_server.xdg_toplevel)
2915         {
2916           xdg_toplevel_destroy (impl->display_server.xdg_toplevel);
2917           impl->display_server.xdg_toplevel = NULL;
2918         }
2919       else if (impl->display_server.xdg_popup)
2920         {
2921           xdg_popup_destroy (impl->display_server.xdg_popup);
2922           impl->display_server.xdg_popup = NULL;
2923           display_wayland->current_popups =
2924             g_list_remove (display_wayland->current_popups, surface);
2925           display_wayland->current_grabbing_popups =
2926             g_list_remove (display_wayland->current_grabbing_popups, surface);
2927         }
2928       if (impl->display_server.xdg_surface)
2929         {
2930           xdg_surface_destroy (impl->display_server.xdg_surface);
2931           impl->display_server.xdg_surface = NULL;
2932           if (!impl->initial_configure_received)
2933             gdk_surface_thaw_updates (surface);
2934           else
2935             impl->initial_configure_received = FALSE;
2936         }
2937 
2938       if (impl->display_server.zxdg_toplevel_v6)
2939         {
2940           zxdg_toplevel_v6_destroy (impl->display_server.zxdg_toplevel_v6);
2941           impl->display_server.zxdg_toplevel_v6 = NULL;
2942         }
2943       else if (impl->display_server.zxdg_popup_v6)
2944         {
2945           zxdg_popup_v6_destroy (impl->display_server.zxdg_popup_v6);
2946           impl->display_server.zxdg_popup_v6 = NULL;
2947           display_wayland->current_popups =
2948             g_list_remove (display_wayland->current_popups, surface);
2949           display_wayland->current_grabbing_popups =
2950             g_list_remove (display_wayland->current_grabbing_popups, surface);
2951         }
2952       if (impl->display_server.zxdg_surface_v6)
2953         {
2954           zxdg_surface_v6_destroy (impl->display_server.zxdg_surface_v6);
2955           impl->display_server.zxdg_surface_v6 = NULL;
2956           if (!impl->initial_configure_received)
2957             gdk_surface_thaw_updates (surface);
2958           else
2959             impl->initial_configure_received = FALSE;
2960         }
2961 
2962       impl->awaiting_frame = FALSE;
2963       if (impl->awaiting_frame_frozen)
2964         {
2965           impl->awaiting_frame_frozen = FALSE;
2966           gdk_surface_thaw_updates (surface);
2967         }
2968 
2969       if (GDK_IS_POPUP (surface))
2970         {
2971           switch (impl->popup_state)
2972             {
2973             case POPUP_STATE_WAITING_FOR_REPOSITIONED:
2974               gdk_surface_thaw_updates (surface);
2975               G_GNUC_FALLTHROUGH;
2976             case POPUP_STATE_WAITING_FOR_CONFIGURE:
2977             case POPUP_STATE_WAITING_FOR_FRAME:
2978               thaw_popup_toplevel_state (surface);
2979               break;
2980             case POPUP_STATE_IDLE:
2981               break;
2982             default:
2983               g_assert_not_reached ();
2984             }
2985 
2986           impl->popup_state = POPUP_STATE_IDLE;
2987         }
2988 
2989       if (impl->display_server.gtk_surface)
2990         {
2991           if (display_wayland->gtk_shell_version >=
2992               GTK_SURFACE1_RELEASE_SINCE_VERSION)
2993             gtk_surface1_release (impl->display_server.gtk_surface);
2994           else
2995             gtk_surface1_destroy (impl->display_server.gtk_surface);
2996           impl->display_server.gtk_surface = NULL;
2997           impl->application.was_set = FALSE;
2998         }
2999 
3000       wl_surface_destroy (impl->display_server.wl_surface);
3001       impl->display_server.wl_surface = NULL;
3002 
3003       g_slist_free (impl->display_server.outputs);
3004       impl->display_server.outputs = NULL;
3005 
3006       g_clear_pointer (&impl->toplevel.layout, gdk_toplevel_layout_unref);
3007       g_clear_pointer (&impl->popup.layout, gdk_popup_layout_unref);
3008     }
3009 
3010   impl->has_uncommitted_ack_configure = FALSE;
3011   impl->input_region_dirty = TRUE;
3012   impl->opaque_region_dirty = TRUE;
3013 
3014   unset_transient_for_exported (surface);
3015 
3016   impl->last_sent_window_geometry = (GdkRectangle) { 0 };
3017   impl->last_sent_min_width = 0;
3018   impl->last_sent_min_height = 0;
3019   impl->last_sent_max_width = 0;
3020   impl->last_sent_max_height = 0;
3021 
3022   _gdk_wayland_surface_clear_saved_size (surface);
3023   impl->mapped = FALSE;
3024 }
3025 
3026 static void
gdk_wayland_surface_hide(GdkSurface * surface)3027 gdk_wayland_surface_hide (GdkSurface *surface)
3028 {
3029   GdkSeat *seat;
3030 
3031   seat = gdk_display_get_default_seat (surface->display);
3032   if (seat)
3033     {
3034       if (surface->autohide)
3035         gdk_seat_ungrab (seat);
3036 
3037       gdk_wayland_seat_clear_touchpoints (GDK_WAYLAND_SEAT (seat), surface);
3038     }
3039   gdk_wayland_surface_hide_surface (surface);
3040   _gdk_surface_clear_update_area (surface);
3041 }
3042 
3043 static void
gdk_wayland_surface_move_resize(GdkSurface * surface,int x,int y,int width,int height)3044 gdk_wayland_surface_move_resize (GdkSurface *surface,
3045                                  int         x,
3046                                  int         y,
3047                                  int         width,
3048                                  int         height)
3049 {
3050   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3051 
3052   surface->x = x;
3053   surface->y = y;
3054   gdk_wayland_surface_maybe_resize (surface, width, height, impl->scale);
3055 }
3056 
3057 static gboolean
is_fallback_relayout_possible(GdkSurface * surface)3058 is_fallback_relayout_possible (GdkSurface *surface)
3059 {
3060   GList *l;
3061 
3062   for (l = surface->children; l; l = l->next)
3063     {
3064       GdkSurface *child = l->data;
3065 
3066       if (GDK_WAYLAND_SURFACE (child)->mapped)
3067         return FALSE;
3068     }
3069 
3070   return TRUE;
3071 }
3072 
3073 static gboolean gdk_wayland_surface_present_popup (GdkSurface     *surface,
3074                                                    int             width,
3075                                                    int             height,
3076                                                    GdkPopupLayout *layout);
3077 
3078 static void
queue_relayout_fallback(GdkSurface * surface,GdkPopupLayout * layout)3079 queue_relayout_fallback (GdkSurface     *surface,
3080                          GdkPopupLayout *layout)
3081 {
3082   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3083 
3084   if (!is_fallback_relayout_possible (surface))
3085     return;
3086 
3087   gdk_wayland_surface_hide_surface (surface);
3088   gdk_wayland_surface_present_popup (surface,
3089                                      impl->popup.unconstrained_width,
3090                                      impl->popup.unconstrained_height,
3091                                      layout);
3092 }
3093 
3094 static void
do_queue_relayout(GdkSurface * surface,int width,int height,GdkPopupLayout * layout)3095 do_queue_relayout (GdkSurface     *surface,
3096                    int             width,
3097                    int             height,
3098                    GdkPopupLayout *layout)
3099 {
3100   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3101   struct xdg_positioner *positioner;
3102 
3103   g_assert (is_realized_popup (impl));
3104   g_assert (impl->popup_state == POPUP_STATE_IDLE ||
3105             impl->popup_state == POPUP_STATE_WAITING_FOR_FRAME);
3106 
3107   g_clear_pointer (&impl->popup.layout, gdk_popup_layout_unref);
3108   impl->popup.layout = gdk_popup_layout_copy (layout);
3109   impl->popup.unconstrained_width = width;
3110   impl->popup.unconstrained_height = height;
3111 
3112   if (!impl->display_server.xdg_popup ||
3113       xdg_popup_get_version (impl->display_server.xdg_popup) <
3114       XDG_POPUP_REPOSITION_SINCE_VERSION)
3115     {
3116       g_warning_once ("Compositor doesn't support moving popups, "
3117                       "relying on remapping");
3118       queue_relayout_fallback (surface, layout);
3119 
3120       return;
3121     }
3122 
3123   positioner = create_dynamic_positioner (surface,
3124                                           width, height, layout,
3125                                           TRUE);
3126   xdg_popup_reposition (impl->display_server.xdg_popup,
3127                         positioner,
3128                         ++impl->reposition_token);
3129   xdg_positioner_destroy (positioner);
3130 
3131   gdk_surface_freeze_updates (surface);
3132 
3133   switch (impl->popup_state)
3134     {
3135     case POPUP_STATE_IDLE:
3136       freeze_popup_toplevel_state (surface);
3137       break;
3138     case POPUP_STATE_WAITING_FOR_FRAME:
3139       break;
3140     case POPUP_STATE_WAITING_FOR_CONFIGURE:
3141     case POPUP_STATE_WAITING_FOR_REPOSITIONED:
3142     default:
3143       g_assert_not_reached ();
3144     }
3145 
3146   impl->popup_state = POPUP_STATE_WAITING_FOR_REPOSITIONED;
3147 }
3148 
3149 static gboolean
is_relayout_finished(GdkSurface * surface)3150 is_relayout_finished (GdkSurface *surface)
3151 {
3152   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3153 
3154   if (!impl->initial_configure_received)
3155     return FALSE;
3156 
3157   if (impl->reposition_token != impl->received_reposition_token)
3158     return FALSE;
3159 
3160   return TRUE;
3161 }
3162 
3163 static void
gdk_wayland_surface_map_popup(GdkSurface * surface,int width,int height,GdkPopupLayout * layout)3164 gdk_wayland_surface_map_popup (GdkSurface     *surface,
3165                                int             width,
3166                                int             height,
3167                                GdkPopupLayout *layout)
3168 {
3169   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3170   GdkSurface *parent;
3171   GdkWaylandSeat *grab_input_seat;
3172 
3173   parent = surface->parent;
3174   if (!parent)
3175     {
3176       g_warning ("Couldn't map as surface %p as popup because it doesn't have a parent",
3177                  surface);
3178       return;
3179     }
3180 
3181   if (surface->autohide)
3182     grab_input_seat = find_grab_input_seat (surface, parent);
3183   else
3184     grab_input_seat = NULL;
3185 
3186   if (!gdk_wayland_surface_create_xdg_popup (surface,
3187                                              parent,
3188                                              grab_input_seat,
3189                                              width, height,
3190                                              layout))
3191     return;
3192 
3193   impl->popup.layout = gdk_popup_layout_copy (layout);
3194   impl->popup.unconstrained_width = width;
3195   impl->popup.unconstrained_height = height;
3196   impl->mapped = TRUE;
3197 }
3198 
3199 static void
show_popup(GdkSurface * surface,int width,int height,GdkPopupLayout * layout)3200 show_popup (GdkSurface     *surface,
3201             int             width,
3202             int             height,
3203             GdkPopupLayout *layout)
3204 {
3205   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3206 
3207   if (!impl->display_server.wl_surface)
3208     gdk_wayland_surface_create_surface (surface);
3209 
3210   gdk_wayland_surface_map_popup (surface, width, height, layout);
3211 }
3212 
3213 typedef struct
3214 {
3215   int width;
3216   int height;
3217   GdkPopupLayout *layout;
3218 } GrabPrepareData;
3219 
3220 static void
show_grabbing_popup(GdkSeat * seat,GdkSurface * surface,gpointer user_data)3221 show_grabbing_popup (GdkSeat    *seat,
3222                      GdkSurface *surface,
3223                      gpointer    user_data)
3224 {
3225   GrabPrepareData *data = user_data;
3226 
3227   show_popup (surface, data->width, data->height, data->layout);
3228 }
3229 
3230 static void
reposition_popup(GdkSurface * surface,int width,int height,GdkPopupLayout * layout)3231 reposition_popup (GdkSurface     *surface,
3232                   int             width,
3233                   int             height,
3234                   GdkPopupLayout *layout)
3235 {
3236   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3237 
3238   switch (impl->popup_state)
3239     {
3240     case POPUP_STATE_IDLE:
3241     case POPUP_STATE_WAITING_FOR_FRAME:
3242       do_queue_relayout (surface, width, height, layout);
3243       break;
3244     case POPUP_STATE_WAITING_FOR_REPOSITIONED:
3245     case POPUP_STATE_WAITING_FOR_CONFIGURE:
3246       g_warn_if_reached ();
3247       break;
3248     default:
3249       g_assert_not_reached ();
3250     }
3251 }
3252 
3253 static gboolean
gdk_wayland_surface_present_popup(GdkSurface * surface,int width,int height,GdkPopupLayout * layout)3254 gdk_wayland_surface_present_popup (GdkSurface     *surface,
3255                                    int             width,
3256                                    int             height,
3257                                    GdkPopupLayout *layout)
3258 {
3259   GdkWaylandDisplay *display_wayland =
3260     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
3261   GdkWaylandSurface *impl;
3262 
3263   impl = GDK_WAYLAND_SURFACE (surface);
3264 
3265   if (!impl->mapped)
3266     {
3267       if (surface->autohide)
3268         {
3269           GdkSeat *seat;
3270 
3271           seat = gdk_display_get_default_seat (surface->display);
3272           if (seat)
3273             {
3274               GrabPrepareData data;
3275               GdkGrabStatus result;
3276 
3277               data = (GrabPrepareData) {
3278                 .width = width,
3279                 .height = height,
3280                 .layout = layout,
3281               };
3282 
3283               result = gdk_seat_grab (seat,
3284                                       surface,
3285                                       GDK_SEAT_CAPABILITY_ALL,
3286                                       TRUE,
3287                                       NULL, NULL,
3288                                       show_grabbing_popup, &data);
3289               if (result != GDK_GRAB_SUCCESS)
3290                 {
3291                   const char *grab_status[] = {
3292                     "success", "already grabbed", "invalid time",
3293                     "not viewable", "frozen", "failed"
3294                   };
3295                   g_warning ("Grab failed: %s", grab_status[result]);
3296                 }
3297             }
3298         }
3299       else
3300         {
3301           show_popup (surface, width, height, layout);
3302         }
3303     }
3304   else
3305     {
3306       if (impl->popup.unconstrained_width == width &&
3307           impl->popup.unconstrained_height == height &&
3308           gdk_popup_layout_equal (impl->popup.layout, layout))
3309         return TRUE;
3310 
3311       reposition_popup (surface, width, height, layout);
3312     }
3313 
3314   while (impl->display_server.xdg_popup && !is_relayout_finished (surface))
3315     wl_display_dispatch_queue (display_wayland->wl_display, impl->event_queue);
3316 
3317   if (impl->display_server.xdg_popup)
3318     {
3319       gdk_surface_invalidate_rect (surface, NULL);
3320       return TRUE;
3321     }
3322   else
3323     {
3324       return FALSE;
3325     }
3326 }
3327 
3328 static void
gdk_wayland_surface_get_geometry(GdkSurface * surface,int * x,int * y,int * width,int * height)3329 gdk_wayland_surface_get_geometry (GdkSurface *surface,
3330                                   int        *x,
3331                                   int        *y,
3332                                   int        *width,
3333                                   int        *height)
3334 {
3335   if (!GDK_SURFACE_DESTROYED (surface))
3336     {
3337       if (x)
3338         *x = surface->x;
3339       if (y)
3340         *y = surface->y;
3341       if (width)
3342         *width = surface->width;
3343       if (height)
3344         *height = surface->height;
3345     }
3346 }
3347 
3348 static void
gdk_wayland_surface_get_root_coords(GdkSurface * surface,int x,int y,int * root_x,int * root_y)3349 gdk_wayland_surface_get_root_coords (GdkSurface *surface,
3350                                      int         x,
3351                                      int         y,
3352                                      int        *root_x,
3353                                      int        *root_y)
3354 {
3355   /*
3356    * Wayland does not have a global coordinate space shared between surfaces. In
3357    * fact, for regular toplevels, we have no idea where our surfaces are
3358    * positioned, relatively.
3359    *
3360    * However, there are some cases like popups and subsurfaces where we do have
3361    * some amount of control over the placement of our surface, and we can
3362    * semi-accurately control the x/y position of these surfaces, if they are
3363    * relative to another surface.
3364    *
3365    * To pretend we have something called a root coordinate space, assume all
3366    * parent-less surfaces are positioned in (0, 0), and all relative positioned
3367    * popups and subsurfaces are placed within this fake root coordinate space.
3368    *
3369    * For example a 200x200 large toplevel surface will have the position (0, 0).
3370    * If a popup positioned in the middle of the toplevel will have the fake
3371    * position (100,100). Furthermore, if a positioned is placed in the middle
3372    * that popup, will have the fake position (150,150), even though it has the
3373    * relative position (50,50). These three surfaces would make up one single
3374    * fake root coordinate space.
3375    */
3376 
3377   if (root_x)
3378     *root_x = surface->x + x;
3379 
3380   if (root_y)
3381     *root_y = surface->y + y;
3382 }
3383 
3384 static gboolean
gdk_wayland_surface_get_device_state(GdkSurface * surface,GdkDevice * device,double * x,double * y,GdkModifierType * mask)3385 gdk_wayland_surface_get_device_state (GdkSurface       *surface,
3386                                       GdkDevice        *device,
3387                                       double           *x,
3388                                       double           *y,
3389                                       GdkModifierType  *mask)
3390 {
3391   if (GDK_SURFACE_DESTROYED (surface))
3392     return FALSE;
3393 
3394   gdk_wayland_device_query_state (device, surface, x, y, mask);
3395 
3396   return *x >= 0 && *y >= 0 && *x < surface->width && *y < surface->height;
3397 }
3398 
3399 static void
gdk_wayland_surface_set_input_region(GdkSurface * surface,cairo_region_t * input_region)3400 gdk_wayland_surface_set_input_region (GdkSurface     *surface,
3401                                       cairo_region_t *input_region)
3402 {
3403   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3404 
3405   if (GDK_SURFACE_DESTROYED (surface))
3406     return;
3407 
3408   g_clear_pointer (&impl->input_region, cairo_region_destroy);
3409 
3410   if (input_region)
3411     impl->input_region = cairo_region_copy (input_region);
3412 
3413   impl->input_region_dirty = TRUE;
3414 }
3415 
3416 static void
gdk_wayland_surface_destroy(GdkSurface * surface,gboolean foreign_destroy)3417 gdk_wayland_surface_destroy (GdkSurface *surface,
3418                              gboolean    foreign_destroy)
3419 {
3420   GdkWaylandDisplay *display;
3421   GdkFrameClock *frame_clock;
3422 
3423   g_return_if_fail (GDK_IS_SURFACE (surface));
3424 
3425   /* Wayland surfaces can't be externally destroyed; we may possibly
3426    * eventually want to use this path at display close-down
3427    */
3428   g_return_if_fail (!foreign_destroy);
3429 
3430   gdk_wayland_surface_hide_surface (surface);
3431 
3432   frame_clock = gdk_surface_get_frame_clock (surface);
3433   g_signal_handlers_disconnect_by_func (frame_clock, on_frame_clock_before_paint, surface);
3434   g_signal_handlers_disconnect_by_func (frame_clock, on_frame_clock_after_paint, surface);
3435 
3436   display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
3437   display->toplevels = g_list_remove (display->toplevels, surface);
3438 }
3439 
3440 static void
gdk_wayland_surface_focus(GdkSurface * surface,guint32 timestamp)3441 gdk_wayland_surface_focus (GdkSurface *surface,
3442                            guint32     timestamp)
3443 {
3444   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3445 
3446   if (!impl->display_server.gtk_surface)
3447     return;
3448 
3449   if (timestamp == GDK_CURRENT_TIME)
3450     {
3451       GdkWaylandDisplay *display_wayland =
3452         GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
3453 
3454       if (display_wayland->startup_notification_id)
3455         {
3456           if (display_wayland->xdg_activation)
3457             {
3458               xdg_activation_v1_activate (display_wayland->xdg_activation,
3459                                           display_wayland->startup_notification_id,
3460                                           impl->display_server.wl_surface);
3461             }
3462           else if (display_wayland->gtk_shell_version >= 3)
3463             {
3464               gtk_surface1_request_focus (impl->display_server.gtk_surface,
3465                                           display_wayland->startup_notification_id);
3466             }
3467 
3468           g_clear_pointer (&display_wayland->startup_notification_id, g_free);
3469         }
3470     }
3471   else
3472     gtk_surface1_present (impl->display_server.gtk_surface, timestamp);
3473 }
3474 
3475 static void
gtk_surface_configure(void * data,struct gtk_surface1 * gtk_surface,struct wl_array * states)3476 gtk_surface_configure (void                *data,
3477                        struct gtk_surface1 *gtk_surface,
3478                        struct wl_array     *states)
3479 {
3480   GdkSurface *surface = GDK_SURFACE (data);
3481   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3482   GdkToplevelState new_state = 0;
3483   uint32_t *p;
3484 
3485   wl_array_for_each (p, states)
3486     {
3487       uint32_t state = *p;
3488 
3489       switch (state)
3490         {
3491         case GTK_SURFACE1_STATE_TILED:
3492           new_state |= GDK_TOPLEVEL_STATE_TILED;
3493           break;
3494 
3495         /* Since v2 */
3496         case GTK_SURFACE1_STATE_TILED_TOP:
3497           new_state |= (GDK_TOPLEVEL_STATE_TILED | GDK_TOPLEVEL_STATE_TOP_TILED);
3498           break;
3499         case GTK_SURFACE1_STATE_TILED_RIGHT:
3500           new_state |= (GDK_TOPLEVEL_STATE_TILED | GDK_TOPLEVEL_STATE_RIGHT_TILED);
3501           break;
3502         case GTK_SURFACE1_STATE_TILED_BOTTOM:
3503           new_state |= (GDK_TOPLEVEL_STATE_TILED | GDK_TOPLEVEL_STATE_BOTTOM_TILED);
3504           break;
3505         case GTK_SURFACE1_STATE_TILED_LEFT:
3506           new_state |= (GDK_TOPLEVEL_STATE_TILED | GDK_TOPLEVEL_STATE_LEFT_TILED);
3507           break;
3508         default:
3509           /* Unknown state */
3510           break;
3511         }
3512     }
3513 
3514   impl->pending.toplevel.state |= new_state;
3515 }
3516 
3517 static void
gtk_surface_configure_edges(void * data,struct gtk_surface1 * gtk_surface,struct wl_array * edge_constraints)3518 gtk_surface_configure_edges (void                *data,
3519                              struct gtk_surface1 *gtk_surface,
3520                              struct wl_array     *edge_constraints)
3521 {
3522   GdkSurface *surface = GDK_SURFACE (data);
3523   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3524   GdkToplevelState new_state = 0;
3525   uint32_t *p;
3526 
3527   wl_array_for_each (p, edge_constraints)
3528     {
3529       uint32_t constraint = *p;
3530 
3531       switch (constraint)
3532         {
3533         case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_TOP:
3534           new_state |= GDK_TOPLEVEL_STATE_TOP_RESIZABLE;
3535           break;
3536         case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_RIGHT:
3537           new_state |= GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE;
3538           break;
3539         case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_BOTTOM:
3540           new_state |= GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE;
3541           break;
3542         case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_LEFT:
3543           new_state |= GDK_TOPLEVEL_STATE_LEFT_RESIZABLE;
3544           break;
3545         default:
3546           /* Unknown state */
3547           break;
3548         }
3549     }
3550 
3551   impl->pending.toplevel.state |= new_state;
3552 }
3553 
3554 static const struct gtk_surface1_listener gtk_surface_listener = {
3555   gtk_surface_configure,
3556   gtk_surface_configure_edges
3557 };
3558 
3559 static void
gdk_wayland_surface_init_gtk_surface(GdkWaylandSurface * impl)3560 gdk_wayland_surface_init_gtk_surface (GdkWaylandSurface *impl)
3561 {
3562   GdkWaylandDisplay *display =
3563     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (impl)));
3564 
3565   if (impl->display_server.gtk_surface != NULL)
3566     return;
3567   if (!is_realized_toplevel (impl))
3568     return;
3569   if (display->gtk_shell == NULL)
3570     return;
3571 
3572   impl->display_server.gtk_surface =
3573     gtk_shell1_get_gtk_surface (display->gtk_shell,
3574                                 impl->display_server.wl_surface);
3575   wl_proxy_set_queue ((struct wl_proxy *) impl->display_server.gtk_surface,
3576                       impl->event_queue);
3577   gdk_wayland_surface_set_geometry_hints (impl,
3578                                           &impl->geometry_hints,
3579                                           impl->geometry_mask);
3580   gtk_surface1_add_listener (impl->display_server.gtk_surface,
3581                              &gtk_surface_listener,
3582                              impl);
3583 }
3584 
3585 static void
maybe_set_gtk_surface_modal(GdkSurface * surface)3586 maybe_set_gtk_surface_modal (GdkSurface *surface)
3587 {
3588   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3589 
3590   gdk_wayland_surface_init_gtk_surface (impl);
3591   if (impl->display_server.gtk_surface == NULL)
3592     return;
3593 
3594   if (surface->modal_hint)
3595     gtk_surface1_set_modal (impl->display_server.gtk_surface);
3596   else
3597     gtk_surface1_unset_modal (impl->display_server.gtk_surface);
3598 
3599 }
3600 
3601 static void
gdk_wayland_surface_set_modal_hint(GdkSurface * surface,gboolean modal)3602 gdk_wayland_surface_set_modal_hint (GdkSurface *surface,
3603                                     gboolean    modal)
3604 {
3605   surface->modal_hint = modal;
3606   maybe_set_gtk_surface_modal (surface);
3607 }
3608 
3609 static void
gdk_wayland_surface_set_geometry_hints(GdkWaylandSurface * impl,const GdkGeometry * geometry,GdkSurfaceHints geom_mask)3610 gdk_wayland_surface_set_geometry_hints (GdkWaylandSurface  *impl,
3611                                         const GdkGeometry  *geometry,
3612                                         GdkSurfaceHints     geom_mask)
3613 {
3614   GdkWaylandDisplay *display_wayland;
3615   int min_width, min_height;
3616   int max_width, max_height;
3617 
3618   if (GDK_SURFACE_DESTROYED (impl) ||
3619       !SURFACE_IS_TOPLEVEL (impl))
3620     return;
3621 
3622   display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (impl)));
3623 
3624   impl->geometry_hints = *geometry;
3625   impl->geometry_mask = geom_mask;
3626 
3627   if (!is_realized_toplevel (impl))
3628     return;
3629 
3630   if (geom_mask & GDK_HINT_MIN_SIZE)
3631     {
3632       min_width = MAX (0, (geometry->min_width -
3633                            (impl->shadow_left + impl->shadow_right)));
3634       min_height = MAX (0, (geometry->min_height -
3635                             (impl->shadow_top + impl->shadow_bottom)));
3636     }
3637   else
3638     {
3639       min_width = 0;
3640       min_height = 0;
3641     }
3642 
3643   if (geom_mask & GDK_HINT_MAX_SIZE)
3644     {
3645       max_width = MAX (0, (geometry->max_width -
3646                            (impl->shadow_left + impl->shadow_right)));
3647       max_height = MAX (0, (geometry->max_height -
3648                             (impl->shadow_top + impl->shadow_bottom)));
3649     }
3650   else
3651     {
3652       max_width = 0;
3653       max_height = 0;
3654     }
3655 
3656   if (impl->last_sent_min_width == min_width &&
3657       impl->last_sent_min_height == min_height &&
3658       impl->last_sent_max_width == max_width &&
3659       impl->last_sent_max_height == max_height)
3660     return;
3661 
3662   switch (display_wayland->shell_variant)
3663     {
3664     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
3665       xdg_toplevel_set_min_size (impl->display_server.xdg_toplevel,
3666                                  min_width, min_height);
3667       xdg_toplevel_set_max_size (impl->display_server.xdg_toplevel,
3668                                  max_width, max_height);
3669       break;
3670     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
3671       zxdg_toplevel_v6_set_min_size (impl->display_server.zxdg_toplevel_v6,
3672                                      min_width, min_height);
3673       zxdg_toplevel_v6_set_max_size (impl->display_server.zxdg_toplevel_v6,
3674                                      max_width, max_height);
3675       break;
3676     default:
3677       g_assert_not_reached ();
3678     }
3679 
3680   impl->last_sent_min_width = min_width;
3681   impl->last_sent_min_height = min_height;
3682   impl->last_sent_max_width = max_width;
3683   impl->last_sent_max_height = max_height;
3684 }
3685 
3686 static void
gdk_wayland_surface_set_title(GdkSurface * surface,const char * title)3687 gdk_wayland_surface_set_title (GdkSurface  *surface,
3688                                const char *title)
3689 {
3690   GdkWaylandSurface *impl;
3691   const char *end;
3692   gsize title_length;
3693 
3694   g_return_if_fail (title != NULL);
3695 
3696   if (GDK_SURFACE_DESTROYED (surface))
3697     return;
3698 
3699   impl = GDK_WAYLAND_SURFACE (surface);
3700 
3701   if (g_strcmp0 (impl->title, title) == 0)
3702     return;
3703 
3704   g_free (impl->title);
3705 
3706   title_length = MIN (strlen (title), MAX_WL_BUFFER_SIZE);
3707   if (g_utf8_validate (title, title_length, &end))
3708     {
3709       impl->title = g_malloc (end - title + 1);
3710       memcpy (impl->title, title, end - title);
3711       impl->title[end - title] = '\0';
3712     }
3713   else
3714     {
3715       impl->title = g_utf8_make_valid (title, title_length);
3716       g_warning ("Invalid utf8 passed to gdk_surface_set_title: '%s'", title);
3717     }
3718 
3719   gdk_wayland_surface_sync_title (surface);
3720 }
3721 
3722 static void
gdk_wayland_surface_set_startup_id(GdkSurface * surface,const char * startup_id)3723 gdk_wayland_surface_set_startup_id (GdkSurface  *surface,
3724                                     const char *startup_id)
3725 {
3726 }
3727 
3728 static gboolean
check_transient_for_loop(GdkWaylandToplevel * toplevel,GdkWaylandToplevel * parent)3729 check_transient_for_loop (GdkWaylandToplevel *toplevel,
3730                           GdkWaylandToplevel *parent)
3731 {
3732   while (parent)
3733     {
3734       if (parent->transient_for == toplevel)
3735         return TRUE;
3736       parent = parent->transient_for;
3737     }
3738   return FALSE;
3739 }
3740 
3741 static void
gdk_wayland_toplevel_set_transient_for(GdkWaylandToplevel * toplevel,GdkSurface * parent)3742 gdk_wayland_toplevel_set_transient_for (GdkWaylandToplevel *toplevel,
3743                                         GdkSurface         *parent)
3744 {
3745   g_return_if_fail (!parent || GDK_IS_WAYLAND_TOPLEVEL (parent));
3746   g_return_if_fail (!parent ||
3747                     gdk_surface_get_display (GDK_SURFACE (toplevel)) == gdk_surface_get_display (parent));
3748 
3749   if (parent)
3750     {
3751       GdkWaylandToplevel *parent_toplevel = GDK_WAYLAND_TOPLEVEL (parent);
3752 
3753       if (check_transient_for_loop (toplevel, parent_toplevel))
3754         {
3755           g_warning ("Setting %p transient for %p would create a loop",
3756                      toplevel, parent);
3757           return;
3758         }
3759     }
3760 
3761   unset_transient_for_exported (GDK_SURFACE (toplevel));
3762 
3763   if (parent)
3764     toplevel->transient_for = GDK_WAYLAND_TOPLEVEL (parent);
3765   else
3766     toplevel->transient_for = NULL;
3767 
3768   gdk_wayland_surface_sync_parent (GDK_SURFACE (toplevel), NULL);
3769 }
3770 
3771 static void
gdk_wayland_surface_minimize(GdkSurface * surface)3772 gdk_wayland_surface_minimize (GdkSurface *surface)
3773 {
3774   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3775   GdkWaylandDisplay *display_wayland;
3776 
3777   if (GDK_SURFACE_DESTROYED (surface) ||
3778       !SURFACE_IS_TOPLEVEL (surface))
3779     return;
3780 
3781   if (!is_realized_toplevel (GDK_WAYLAND_SURFACE (surface)))
3782     return;
3783 
3784   /* FIXME: xdg_toplevel does not come with a minimized state that we can
3785    * query or get notified of. This means we cannot implement the full
3786    * GdkSurface API, and our state will not reflect minimization.
3787    */
3788   display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
3789   switch (display_wayland->shell_variant)
3790     {
3791     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
3792       xdg_toplevel_set_minimized (impl->display_server.xdg_toplevel);
3793       break;
3794     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
3795       zxdg_toplevel_v6_set_minimized (impl->display_server.zxdg_toplevel_v6);
3796       break;
3797     default:
3798       g_assert_not_reached ();
3799     }
3800 }
3801 
3802 static void
gdk_wayland_surface_maximize(GdkSurface * surface)3803 gdk_wayland_surface_maximize (GdkSurface *surface)
3804 {
3805   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3806 
3807   if (GDK_SURFACE_DESTROYED (surface))
3808     return;
3809 
3810   _gdk_wayland_surface_save_size (surface);
3811 
3812   if (is_realized_toplevel (impl))
3813     {
3814       GdkWaylandDisplay *display_wayland =
3815         GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
3816 
3817       switch (display_wayland->shell_variant)
3818         {
3819         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
3820           xdg_toplevel_set_maximized (impl->display_server.xdg_toplevel);
3821           break;
3822         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
3823           zxdg_toplevel_v6_set_maximized (impl->display_server.zxdg_toplevel_v6);
3824           break;
3825         default:
3826           g_assert_not_reached ();
3827         }
3828     }
3829   else
3830     {
3831       synthesize_initial_surface_state (surface, 0, GDK_TOPLEVEL_STATE_MAXIMIZED);
3832     }
3833 }
3834 
3835 static void
gdk_wayland_surface_unmaximize(GdkSurface * surface)3836 gdk_wayland_surface_unmaximize (GdkSurface *surface)
3837 {
3838   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3839 
3840   if (GDK_SURFACE_DESTROYED (surface))
3841     return;
3842 
3843   if (is_realized_toplevel (impl))
3844     {
3845       GdkWaylandDisplay *display_wayland =
3846         GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
3847 
3848       switch (display_wayland->shell_variant)
3849         {
3850         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
3851           xdg_toplevel_unset_maximized (impl->display_server.xdg_toplevel);
3852           break;
3853         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
3854           zxdg_toplevel_v6_unset_maximized (impl->display_server.zxdg_toplevel_v6);
3855           break;
3856         default:
3857           g_assert_not_reached ();
3858         }
3859     }
3860   else
3861     {
3862       synthesize_initial_surface_state (surface, GDK_TOPLEVEL_STATE_MAXIMIZED, 0);
3863     }
3864 }
3865 
3866 static void
gdk_wayland_surface_fullscreen_on_monitor(GdkSurface * surface,GdkMonitor * monitor)3867 gdk_wayland_surface_fullscreen_on_monitor (GdkSurface *surface,
3868                                            GdkMonitor *monitor)
3869 {
3870   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3871   struct wl_output *output = ((GdkWaylandMonitor *)monitor)->output;
3872 
3873   if (GDK_SURFACE_DESTROYED (surface))
3874     return;
3875 
3876   _gdk_wayland_surface_save_size (surface);
3877 
3878   if (is_realized_toplevel (impl))
3879     {
3880       GdkWaylandDisplay *display_wayland =
3881         GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
3882 
3883       switch (display_wayland->shell_variant)
3884         {
3885         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
3886           xdg_toplevel_set_fullscreen (impl->display_server.xdg_toplevel,
3887                                        output);
3888           break;
3889         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
3890           zxdg_toplevel_v6_set_fullscreen (impl->display_server.zxdg_toplevel_v6,
3891                                            output);
3892           break;
3893         default:
3894           g_assert_not_reached ();
3895         }
3896     }
3897   else
3898     {
3899       synthesize_initial_surface_state (surface, 0, GDK_TOPLEVEL_STATE_FULLSCREEN);
3900       impl->initial_fullscreen_output = output;
3901     }
3902 }
3903 
3904 static void
gdk_wayland_surface_fullscreen(GdkSurface * surface)3905 gdk_wayland_surface_fullscreen (GdkSurface *surface)
3906 {
3907   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3908 
3909   if (GDK_SURFACE_DESTROYED (surface))
3910     return;
3911 
3912   impl->initial_fullscreen_output = NULL;
3913 
3914   _gdk_wayland_surface_save_size (surface);
3915 
3916   if (is_realized_toplevel (impl))
3917     {
3918       GdkWaylandDisplay *display_wayland =
3919         GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
3920 
3921       switch (display_wayland->shell_variant)
3922         {
3923         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
3924           xdg_toplevel_set_fullscreen (impl->display_server.xdg_toplevel,
3925                                        NULL);
3926           break;
3927         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
3928           zxdg_toplevel_v6_set_fullscreen (impl->display_server.zxdg_toplevel_v6,
3929                                            NULL);
3930           break;
3931         default:
3932           g_assert_not_reached ();
3933         }
3934     }
3935   else
3936     {
3937       synthesize_initial_surface_state (surface, 0, GDK_TOPLEVEL_STATE_FULLSCREEN);
3938     }
3939 }
3940 
3941 static void
gdk_wayland_surface_unfullscreen(GdkSurface * surface)3942 gdk_wayland_surface_unfullscreen (GdkSurface *surface)
3943 {
3944   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
3945 
3946   if (GDK_SURFACE_DESTROYED (surface))
3947     return;
3948 
3949   impl->initial_fullscreen_output = NULL;
3950 
3951   if (is_realized_toplevel (impl))
3952     {
3953       GdkWaylandDisplay *display_wayland =
3954         GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
3955 
3956       switch (display_wayland->shell_variant)
3957         {
3958         case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
3959           xdg_toplevel_unset_fullscreen (impl->display_server.xdg_toplevel);
3960           break;
3961         case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
3962           zxdg_toplevel_v6_unset_fullscreen (impl->display_server.zxdg_toplevel_v6);
3963           break;
3964         default:
3965           g_assert_not_reached ();
3966         }
3967     }
3968   else
3969     {
3970       synthesize_initial_surface_state (surface, GDK_TOPLEVEL_STATE_FULLSCREEN, 0);
3971     }
3972 }
3973 
3974 static void
gdk_wayland_toplevel_begin_resize(GdkToplevel * toplevel,GdkSurfaceEdge edge,GdkDevice * device,int button,double x,double y,guint32 timestamp)3975 gdk_wayland_toplevel_begin_resize (GdkToplevel    *toplevel,
3976                                    GdkSurfaceEdge  edge,
3977                                    GdkDevice      *device,
3978                                    int             button,
3979                                    double          x,
3980                                    double          y,
3981                                    guint32         timestamp)
3982 {
3983   GdkSurface *surface = GDK_SURFACE (toplevel);
3984   GdkWaylandSurface *impl;
3985   GdkWaylandDisplay *display_wayland;
3986   GdkEventSequence *sequence;
3987   uint32_t resize_edges, serial;
3988 
3989   if (GDK_SURFACE_DESTROYED (surface) ||
3990       !SURFACE_IS_TOPLEVEL (surface))
3991     return;
3992 
3993   switch (edge)
3994     {
3995     case GDK_SURFACE_EDGE_NORTH_WEST:
3996       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_LEFT;
3997       break;
3998 
3999     case GDK_SURFACE_EDGE_NORTH:
4000       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP;
4001       break;
4002 
4003     case GDK_SURFACE_EDGE_NORTH_EAST:
4004       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_RIGHT;
4005       break;
4006 
4007     case GDK_SURFACE_EDGE_WEST:
4008       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT;
4009       break;
4010 
4011     case GDK_SURFACE_EDGE_EAST:
4012       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT;
4013       break;
4014 
4015     case GDK_SURFACE_EDGE_SOUTH_WEST:
4016       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_LEFT;
4017       break;
4018 
4019     case GDK_SURFACE_EDGE_SOUTH:
4020       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM;
4021       break;
4022 
4023     case GDK_SURFACE_EDGE_SOUTH_EAST:
4024       resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_RIGHT;
4025       break;
4026 
4027     default:
4028       g_warning ("gdk_toplevel_begin_resize: bad resize edge %d!", edge);
4029       return;
4030     }
4031 
4032   impl = GDK_WAYLAND_SURFACE (surface);
4033   display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
4034 
4035   if (!is_realized_toplevel (impl))
4036     return;
4037 
4038   serial = _gdk_wayland_seat_get_last_implicit_grab_serial (GDK_WAYLAND_SEAT (gdk_device_get_seat (device)),
4039                                                             &sequence);
4040 
4041   switch (display_wayland->shell_variant)
4042     {
4043     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4044       xdg_toplevel_resize (impl->display_server.xdg_toplevel,
4045                            gdk_wayland_device_get_wl_seat (device),
4046                            serial, resize_edges);
4047       break;
4048     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4049       zxdg_toplevel_v6_resize (impl->display_server.zxdg_toplevel_v6,
4050                                gdk_wayland_device_get_wl_seat (device),
4051                                serial, resize_edges);
4052       break;
4053     default:
4054       g_assert_not_reached ();
4055     }
4056 
4057   if (sequence)
4058     gdk_wayland_device_unset_touch_grab (device, sequence);
4059 }
4060 
4061 static void
gdk_wayland_toplevel_begin_move(GdkToplevel * toplevel,GdkDevice * device,int button,double x,double y,guint32 timestamp)4062 gdk_wayland_toplevel_begin_move (GdkToplevel *toplevel,
4063                                  GdkDevice   *device,
4064                                  int          button,
4065                                  double       x,
4066                                  double       y,
4067                                  guint32      timestamp)
4068 {
4069   GdkSurface *surface = GDK_SURFACE (toplevel);
4070   GdkWaylandSurface *impl;
4071   GdkWaylandDisplay *display_wayland;
4072   GdkEventSequence *sequence;
4073   uint32_t serial;
4074 
4075   if (GDK_SURFACE_DESTROYED (surface) ||
4076       !SURFACE_IS_TOPLEVEL (surface))
4077     return;
4078 
4079   impl = GDK_WAYLAND_SURFACE (surface);
4080   display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
4081 
4082   if (!is_realized_toplevel (impl))
4083     return;
4084 
4085   serial = _gdk_wayland_seat_get_last_implicit_grab_serial (GDK_WAYLAND_SEAT (gdk_device_get_seat (device)),
4086                                                             &sequence);
4087   switch (display_wayland->shell_variant)
4088     {
4089     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4090       xdg_toplevel_move (impl->display_server.xdg_toplevel,
4091                          gdk_wayland_device_get_wl_seat (device),
4092                          serial);
4093       break;
4094     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4095       zxdg_toplevel_v6_move (impl->display_server.zxdg_toplevel_v6,
4096                              gdk_wayland_device_get_wl_seat (device),
4097                              serial);
4098       break;
4099     default:
4100       g_assert_not_reached ();
4101     }
4102 
4103   if (sequence)
4104     gdk_wayland_device_unset_touch_grab (device, sequence);
4105 }
4106 
4107 static void
gdk_wayland_surface_destroy_notify(GdkSurface * surface)4108 gdk_wayland_surface_destroy_notify (GdkSurface *surface)
4109 {
4110   if (!GDK_SURFACE_DESTROYED (surface))
4111     {
4112       g_warning ("GdkSurface %p unexpectedly destroyed", surface);
4113       _gdk_surface_destroy (surface, TRUE);
4114     }
4115 
4116   g_object_unref (surface);
4117 }
4118 
4119 static int
gdk_wayland_surface_get_scale_factor(GdkSurface * surface)4120 gdk_wayland_surface_get_scale_factor (GdkSurface *surface)
4121 {
4122   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
4123 
4124   if (GDK_SURFACE_DESTROYED (surface))
4125     return 1;
4126 
4127   return impl->scale;
4128 }
4129 
4130 static void
gdk_wayland_surface_set_opaque_region(GdkSurface * surface,cairo_region_t * region)4131 gdk_wayland_surface_set_opaque_region (GdkSurface     *surface,
4132                                        cairo_region_t *region)
4133 {
4134   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
4135 
4136   if (GDK_SURFACE_DESTROYED (surface))
4137     return;
4138 
4139   g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
4140   impl->opaque_region = cairo_region_reference (region);
4141   impl->opaque_region_dirty = TRUE;
4142 }
4143 
4144 static gboolean
gdk_wayland_surface_show_window_menu(GdkSurface * surface,GdkEvent * event)4145 gdk_wayland_surface_show_window_menu (GdkSurface *surface,
4146                                       GdkEvent   *event)
4147 {
4148   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
4149   GdkWaylandDisplay *display_wayland =
4150     GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
4151   GdkSeat *seat;
4152   struct wl_seat *wl_seat;
4153   double x, y;
4154   uint32_t serial;
4155 
4156   GdkEventType event_type = gdk_event_get_event_type (event);
4157   switch ((guint) event_type)
4158     {
4159     case GDK_BUTTON_PRESS:
4160     case GDK_BUTTON_RELEASE:
4161     case GDK_TOUCH_BEGIN:
4162     case GDK_TOUCH_END:
4163       break;
4164     default:
4165       return FALSE;
4166     }
4167 
4168   if (!is_realized_toplevel (impl))
4169     return FALSE;
4170 
4171   seat = gdk_event_get_seat (event);
4172   wl_seat = gdk_wayland_seat_get_wl_seat (seat);
4173   gdk_event_get_position (event, &x, &y);
4174 
4175   serial = _gdk_wayland_seat_get_implicit_grab_serial (seat, event);
4176 
4177   switch (display_wayland->shell_variant)
4178     {
4179     case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
4180       xdg_toplevel_show_window_menu (impl->display_server.xdg_toplevel,
4181                                      wl_seat, serial, x, y);
4182       break;
4183     case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
4184       zxdg_toplevel_v6_show_window_menu (impl->display_server.zxdg_toplevel_v6,
4185                                          wl_seat, serial, x, y);
4186       break;
4187     default:
4188       g_assert_not_reached ();
4189     }
4190 
4191   return TRUE;
4192 }
4193 
4194 static gboolean
translate_gesture(GdkTitlebarGesture gesture,enum gtk_surface1_gesture * out_gesture)4195 translate_gesture (GdkTitlebarGesture         gesture,
4196                    enum gtk_surface1_gesture *out_gesture)
4197 {
4198   switch (gesture)
4199     {
4200     case GDK_TITLEBAR_GESTURE_DOUBLE_CLICK:
4201       *out_gesture = GTK_SURFACE1_GESTURE_DOUBLE_CLICK;
4202       break;
4203 
4204     case GDK_TITLEBAR_GESTURE_RIGHT_CLICK:
4205       *out_gesture = GTK_SURFACE1_GESTURE_RIGHT_CLICK;
4206       break;
4207 
4208     case GDK_TITLEBAR_GESTURE_MIDDLE_CLICK:
4209       *out_gesture = GTK_SURFACE1_GESTURE_MIDDLE_CLICK;
4210       break;
4211 
4212     default:
4213       g_warning ("Not handling unknown titlebar gesture %u", gesture);
4214       return FALSE;
4215     }
4216 
4217   return TRUE;
4218 }
4219 
4220 static gboolean
gdk_wayland_surface_titlebar_gesture(GdkSurface * surface,GdkTitlebarGesture gesture)4221 gdk_wayland_surface_titlebar_gesture (GdkSurface         *surface,
4222                                       GdkTitlebarGesture  gesture)
4223 {
4224   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
4225   struct gtk_surface1 *gtk_surface = impl->display_server.gtk_surface;
4226   enum gtk_surface1_gesture gtk_gesture;
4227   GdkSeat *seat;
4228   struct wl_seat *wl_seat;
4229   uint32_t serial;
4230 
4231   if (!gtk_surface)
4232     return FALSE;
4233 
4234   if (gtk_surface1_get_version (gtk_surface) < GTK_SURFACE1_TITLEBAR_GESTURE_SINCE_VERSION)
4235     return FALSE;
4236 
4237   if (!translate_gesture (gesture, &gtk_gesture))
4238     return FALSE;
4239 
4240   seat = gdk_display_get_default_seat (surface->display);
4241   wl_seat = gdk_wayland_seat_get_wl_seat (seat);
4242 
4243   serial = _gdk_wayland_seat_get_last_implicit_grab_serial (GDK_WAYLAND_SEAT (seat), NULL);
4244 
4245   gtk_surface1_titlebar_gesture (impl->display_server.gtk_surface,
4246                                  serial,
4247                                  wl_seat,
4248                                  gtk_gesture);
4249 
4250   return TRUE;
4251 }
4252 
4253 static gboolean
gdk_wayland_surface_supports_edge_constraints(GdkSurface * surface)4254 gdk_wayland_surface_supports_edge_constraints (GdkSurface *surface)
4255 {
4256   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
4257   struct gtk_surface1 *gtk_surface = impl->display_server.gtk_surface;
4258 
4259   if (!gtk_surface)
4260     return FALSE;
4261 
4262   return gtk_surface1_get_version (gtk_surface) >= GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION;
4263 }
4264 
4265 static void
gdk_wayland_surface_class_init(GdkWaylandSurfaceClass * klass)4266 gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
4267 {
4268   GObjectClass *object_class = G_OBJECT_CLASS (klass);
4269   GdkSurfaceClass *impl_class = GDK_SURFACE_CLASS (klass);
4270 
4271   object_class->constructed = gdk_wayland_surface_constructed;
4272   object_class->dispose = gdk_wayland_surface_dispose;
4273   object_class->finalize = gdk_wayland_surface_finalize;
4274 
4275   impl_class->hide = gdk_wayland_surface_hide;
4276   impl_class->get_geometry = gdk_wayland_surface_get_geometry;
4277   impl_class->get_root_coords = gdk_wayland_surface_get_root_coords;
4278   impl_class->get_device_state = gdk_wayland_surface_get_device_state;
4279   impl_class->set_input_region = gdk_wayland_surface_set_input_region;
4280   impl_class->destroy = gdk_wayland_surface_destroy;
4281   impl_class->beep = gdk_wayland_surface_beep;
4282 
4283   impl_class->destroy_notify = gdk_wayland_surface_destroy_notify;
4284   impl_class->drag_begin = _gdk_wayland_surface_drag_begin;
4285   impl_class->get_scale_factor = gdk_wayland_surface_get_scale_factor;
4286   impl_class->set_opaque_region = gdk_wayland_surface_set_opaque_region;
4287   impl_class->request_layout = gdk_wayland_surface_request_layout;
4288   impl_class->compute_size = gdk_wayland_surface_compute_size;
4289 }
4290 
4291 void
_gdk_wayland_surface_set_grab_seat(GdkSurface * surface,GdkSeat * seat)4292 _gdk_wayland_surface_set_grab_seat (GdkSurface *surface,
4293                                     GdkSeat    *seat)
4294 {
4295   GdkWaylandSurface *impl;
4296 
4297   g_return_if_fail (surface != NULL);
4298 
4299   impl = GDK_WAYLAND_SURFACE (surface);
4300   impl->grab_input_seat = seat;
4301 }
4302 
4303 /**
4304  * gdk_wayland_surface_get_wl_surface: (skip)
4305  * @surface: (type GdkWaylandSurface): a `GdkSurface`
4306  *
4307  * Returns the Wayland `wl_surface` of a `GdkSurface`.
4308  *
4309  * Returns: (transfer none): a Wayland `wl_surface`
4310  */
4311 struct wl_surface *
gdk_wayland_surface_get_wl_surface(GdkSurface * surface)4312 gdk_wayland_surface_get_wl_surface (GdkSurface *surface)
4313 {
4314   g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (surface), NULL);
4315 
4316   return GDK_WAYLAND_SURFACE (surface)->display_server.wl_surface;
4317 }
4318 
4319 struct wl_output *
gdk_wayland_surface_get_wl_output(GdkSurface * surface)4320 gdk_wayland_surface_get_wl_output (GdkSurface *surface)
4321 {
4322   GdkWaylandSurface *impl;
4323 
4324   g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (surface), NULL);
4325 
4326   impl = GDK_WAYLAND_SURFACE (surface);
4327   /* We pick the head of the list as this is the last entered output */
4328   if (impl->display_server.outputs)
4329     return (struct wl_output *) impl->display_server.outputs->data;
4330 
4331   return NULL;
4332 }
4333 
4334 static struct wl_egl_window *
gdk_wayland_surface_get_wl_egl_window(GdkSurface * surface)4335 gdk_wayland_surface_get_wl_egl_window (GdkSurface *surface)
4336 {
4337   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
4338 
4339   if (impl->display_server.egl_window == NULL)
4340     {
4341       impl->display_server.egl_window =
4342         wl_egl_window_create (impl->display_server.wl_surface,
4343                               surface->width * impl->scale,
4344                               surface->height * impl->scale);
4345       wl_surface_set_buffer_scale (impl->display_server.wl_surface, impl->scale);
4346     }
4347 
4348   return impl->display_server.egl_window;
4349 }
4350 
4351 EGLSurface
gdk_wayland_surface_get_egl_surface(GdkSurface * surface)4352 gdk_wayland_surface_get_egl_surface (GdkSurface *surface)
4353 {
4354   GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
4355   GdkWaylandSurface *impl;
4356   struct wl_egl_window *egl_window;
4357 
4358   g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (surface), NULL);
4359 
4360   impl = GDK_WAYLAND_SURFACE (surface);
4361 
4362   if (impl->egl_surface == NULL)
4363     {
4364       egl_window = gdk_wayland_surface_get_wl_egl_window (surface);
4365 
4366       impl->egl_surface =
4367         eglCreateWindowSurface (display->egl_display, display->egl_config, egl_window, NULL);
4368     }
4369 
4370   return impl->egl_surface;
4371 }
4372 
4373 struct gtk_surface1 *
gdk_wayland_surface_get_gtk_surface(GdkSurface * surface)4374 gdk_wayland_surface_get_gtk_surface (GdkSurface *surface)
4375 {
4376   g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (surface), NULL);
4377 
4378   return GDK_WAYLAND_SURFACE (surface)->display_server.gtk_surface;
4379 }
4380 
4381 static void
maybe_set_gtk_surface_dbus_properties(GdkWaylandSurface * impl)4382 maybe_set_gtk_surface_dbus_properties (GdkWaylandSurface *impl)
4383 {
4384   if (impl->application.was_set)
4385     return;
4386 
4387   if (impl->application.application_id == NULL &&
4388       impl->application.app_menu_path == NULL &&
4389       impl->application.menubar_path == NULL &&
4390       impl->application.window_object_path == NULL &&
4391       impl->application.application_object_path == NULL &&
4392       impl->application.unique_bus_name == NULL)
4393     return;
4394 
4395   gdk_wayland_surface_init_gtk_surface (impl);
4396   if (impl->display_server.gtk_surface == NULL)
4397     return;
4398 
4399   gtk_surface1_set_dbus_properties (impl->display_server.gtk_surface,
4400                                     impl->application.application_id,
4401                                     impl->application.app_menu_path,
4402                                     impl->application.menubar_path,
4403                                     impl->application.window_object_path,
4404                                     impl->application.application_object_path,
4405                                     impl->application.unique_bus_name);
4406   impl->application.was_set = TRUE;
4407 }
4408 
4409 void
gdk_wayland_toplevel_set_dbus_properties(GdkToplevel * toplevel,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)4410 gdk_wayland_toplevel_set_dbus_properties (GdkToplevel *toplevel,
4411                                           const char  *application_id,
4412                                           const char  *app_menu_path,
4413                                           const char  *menubar_path,
4414                                           const char  *window_object_path,
4415                                           const char  *application_object_path,
4416                                           const char *unique_bus_name)
4417 {
4418   GdkWaylandSurface *impl;
4419 
4420   g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel));
4421 
4422   impl = GDK_WAYLAND_SURFACE (toplevel);
4423 
4424   impl->application.application_id = g_strdup (application_id);
4425   impl->application.app_menu_path = g_strdup (app_menu_path);
4426   impl->application.menubar_path = g_strdup (menubar_path);
4427   impl->application.window_object_path = g_strdup (window_object_path);
4428   impl->application.application_object_path =
4429     g_strdup (application_object_path);
4430   impl->application.unique_bus_name = g_strdup (unique_bus_name);
4431 
4432   maybe_set_gtk_surface_dbus_properties (impl);
4433 }
4434 
4435 void
_gdk_wayland_surface_offset_next_wl_buffer(GdkSurface * surface,int x,int y)4436 _gdk_wayland_surface_offset_next_wl_buffer (GdkSurface *surface,
4437                                             int         x,
4438                                             int         y)
4439 {
4440   GdkWaylandSurface *impl;
4441 
4442   g_return_if_fail (GDK_IS_WAYLAND_SURFACE (surface));
4443 
4444   impl = GDK_WAYLAND_SURFACE (surface);
4445 
4446   impl->pending_buffer_offset_x = x;
4447   impl->pending_buffer_offset_y = y;
4448 }
4449 
4450 static void
xdg_exported_handle(void * data,struct zxdg_exported_v1 * zxdg_exported_v1,const char * handle)4451 xdg_exported_handle (void                    *data,
4452                      struct zxdg_exported_v1 *zxdg_exported_v1,
4453                      const char              *handle)
4454 {
4455   GdkToplevel *toplevel = data;
4456   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (toplevel);
4457 
4458   impl->exported.callback (toplevel, handle, impl->exported.user_data);
4459   if (impl->exported.destroy_func)
4460     {
4461       g_clear_pointer (&impl->exported.user_data,
4462                        impl->exported.destroy_func);
4463     }
4464 }
4465 
4466 static const struct zxdg_exported_v1_listener xdg_exported_listener = {
4467   xdg_exported_handle
4468 };
4469 
4470 /**
4471  * GdkWaylandToplevelExported:
4472  * @toplevel: (type GdkWaylandToplevel): the `GdkToplevel` that is exported
4473  * @handle: the handle
4474  * @user_data: user data that was passed to [method@GdkWayland.WaylandToplevel.export_handle]
4475  *
4476  * Callback that gets called when the handle for a surface has been
4477  * obtained from the Wayland compositor.
4478  *
4479  * This callback is used in [method@GdkWayland.WaylandToplevel.export_handle].
4480  *
4481  * The @handle can be passed to other processes, for the purpose of
4482  * marking surfaces as transient for out-of-process surfaces.
4483  */
4484 
4485 static gboolean
gdk_wayland_surface_is_exported(GdkWaylandSurface * impl)4486 gdk_wayland_surface_is_exported (GdkWaylandSurface *impl)
4487 {
4488   return !!impl->display_server.xdg_exported;
4489 }
4490 
4491 /**
4492  * gdk_wayland_toplevel_export_handle:
4493  * @toplevel: (type GdkWaylandToplevel): the `GdkToplevel` to obtain a handle for
4494  * @callback: callback to call with the handle
4495  * @user_data: (closure): user data for @callback
4496  * @destroy_func: destroy notify for @user_data
4497  *
4498  * Asynchronously obtains a handle for a surface that can be passed
4499  * to other processes.
4500  *
4501  * When the handle has been obtained, @callback will be called.
4502  *
4503  * It is an error to call this function on a surface that is already
4504  * exported.
4505  *
4506  * When the handle is no longer needed, [method@GdkWayland.WaylandToplevel.unexport_handle]
4507  * should be called to clean up resources.
4508  *
4509  * The main purpose for obtaining a handle is to mark a surface
4510  * from another surface as transient for this one, see
4511  * [method@GdkWayland.WaylandToplevel.set_transient_for_exported].
4512  *
4513  * Note that this API depends on an unstable Wayland protocol,
4514  * and thus may require changes in the future.
4515  *
4516  * Return value: %TRUE if the handle has been requested, %FALSE if
4517  *   an error occurred.
4518  */
4519 gboolean
gdk_wayland_toplevel_export_handle(GdkToplevel * toplevel,GdkWaylandToplevelExported callback,gpointer user_data,GDestroyNotify destroy_func)4520 gdk_wayland_toplevel_export_handle (GdkToplevel                *toplevel,
4521                                     GdkWaylandToplevelExported  callback,
4522                                     gpointer                    user_data,
4523                                     GDestroyNotify              destroy_func)
4524 {
4525   GdkWaylandSurface *impl;
4526   GdkWaylandDisplay *display_wayland;
4527   GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (toplevel));
4528   struct zxdg_exported_v1 *xdg_exported;
4529 
4530   g_return_val_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel), FALSE);
4531   g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
4532 
4533   impl = GDK_WAYLAND_SURFACE (toplevel);
4534   display_wayland = GDK_WAYLAND_DISPLAY (display);
4535 
4536   g_return_val_if_fail (!impl->display_server.xdg_exported, FALSE);
4537 
4538   if (!display_wayland->xdg_exporter)
4539     {
4540       g_warning ("Server is missing xdg_foreign support");
4541       return FALSE;
4542     }
4543 
4544   xdg_exported = zxdg_exporter_v1_export (display_wayland->xdg_exporter,
4545                                           impl->display_server.wl_surface);
4546   zxdg_exported_v1_add_listener (xdg_exported,  &xdg_exported_listener, impl);
4547 
4548   impl->display_server.xdg_exported = xdg_exported;
4549   impl->exported.callback = callback;
4550   impl->exported.user_data = user_data;
4551   impl->exported.destroy_func = destroy_func;
4552 
4553   return TRUE;
4554 }
4555 
4556 /**
4557  * gdk_wayland_toplevel_unexport_handle:
4558  * @toplevel: (type GdkWaylandToplevel): the `GdkToplevel` to unexport
4559  *
4560  * Destroys the handle that was obtained with
4561  * gdk_wayland_toplevel_export_handle().
4562  *
4563  * It is an error to call this function on a surface that
4564  * does not have a handle.
4565  *
4566  * Note that this API depends on an unstable Wayland protocol,
4567  * and thus may require changes in the future.
4568  */
4569 void
gdk_wayland_toplevel_unexport_handle(GdkToplevel * toplevel)4570 gdk_wayland_toplevel_unexport_handle (GdkToplevel *toplevel)
4571 {
4572   GdkWaylandSurface *impl;
4573 
4574   g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel));
4575 
4576   impl = GDK_WAYLAND_SURFACE (toplevel);
4577 
4578   g_return_if_fail (impl->display_server.xdg_exported);
4579 
4580   g_clear_pointer (&impl->display_server.xdg_exported,
4581                    zxdg_exported_v1_destroy);
4582   if (impl->exported.destroy_func)
4583     {
4584       g_clear_pointer (&impl->exported.user_data,
4585                        impl->exported.destroy_func);
4586     }
4587 }
4588 
4589 static void
unset_transient_for_exported(GdkSurface * surface)4590 unset_transient_for_exported (GdkSurface *surface)
4591 {
4592   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
4593 
4594   g_clear_pointer (&impl->imported_transient_for, zxdg_imported_v1_destroy);
4595 }
4596 
4597 static void
xdg_imported_destroyed(void * data,struct zxdg_imported_v1 * zxdg_imported_v1)4598 xdg_imported_destroyed (void                    *data,
4599                         struct zxdg_imported_v1 *zxdg_imported_v1)
4600 {
4601   GdkSurface *surface = data;
4602 
4603   unset_transient_for_exported (surface);
4604 }
4605 
4606 static const struct zxdg_imported_v1_listener xdg_imported_listener = {
4607   xdg_imported_destroyed,
4608 };
4609 
4610 /**
4611  * gdk_wayland_toplevel_set_transient_for_exported:
4612  * @toplevel: (type GdkWaylandToplevel): the `GdkToplevel` to make as transient
4613  * @parent_handle_str: an exported handle for a surface
4614  *
4615  * Marks @toplevel as transient for the surface to which the given
4616  * @parent_handle_str refers.
4617  *
4618  * Typically, the handle will originate from a
4619  * [method@GdkWayland.WaylandToplevel.export_handle] call in another process.
4620  *
4621  * Note that this API depends on an unstable Wayland protocol,
4622  * and thus may require changes in the future.
4623  *
4624  * Return value: %TRUE if the surface has been marked as transient,
4625  *   %FALSE if an error occurred.
4626  */
4627 gboolean
gdk_wayland_toplevel_set_transient_for_exported(GdkToplevel * toplevel,const char * parent_handle_str)4628 gdk_wayland_toplevel_set_transient_for_exported (GdkToplevel *toplevel,
4629                                                  const char  *parent_handle_str)
4630 {
4631   GdkWaylandSurface *impl;
4632   GdkWaylandDisplay *display_wayland;
4633   GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (toplevel));
4634 
4635   g_return_val_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel), FALSE);
4636   g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
4637 
4638   impl = GDK_WAYLAND_SURFACE (toplevel);
4639   display_wayland = GDK_WAYLAND_DISPLAY (display);
4640 
4641   if (!display_wayland->xdg_importer)
4642     {
4643       g_warning ("Server is missing xdg_foreign support");
4644       return FALSE;
4645     }
4646 
4647   gdk_wayland_toplevel_set_transient_for (GDK_WAYLAND_TOPLEVEL (impl), NULL);
4648 
4649   impl->imported_transient_for =
4650     zxdg_importer_v1_import (display_wayland->xdg_importer, parent_handle_str);
4651   zxdg_imported_v1_add_listener (impl->imported_transient_for,
4652                                  &xdg_imported_listener,
4653                                  toplevel);
4654 
4655   gdk_wayland_surface_sync_parent_of_imported (impl);
4656 
4657   return TRUE;
4658 }
4659 
4660 static struct zwp_keyboard_shortcuts_inhibitor_v1 *
gdk_wayland_surface_get_inhibitor(GdkWaylandSurface * impl,GdkSeat * gdk_seat)4661 gdk_wayland_surface_get_inhibitor (GdkWaylandSurface *impl,
4662                                    GdkSeat           *gdk_seat)
4663 {
4664   return g_hash_table_lookup (impl->shortcuts_inhibitors, gdk_seat);
4665 }
4666 
4667 /*
4668  * gdk_wayland_surface_inhibit_shortcuts:
4669  * @surface: (type GdkWaylandSurface): a `GdkSurface`
4670  * @seat: the seat to inhibit
4671  *
4672  * Inhibits the shortcuts coming from the given @seat.
4673  */
4674 void
gdk_wayland_surface_inhibit_shortcuts(GdkSurface * surface,GdkSeat * gdk_seat)4675 gdk_wayland_surface_inhibit_shortcuts (GdkSurface *surface,
4676                                        GdkSeat    *gdk_seat)
4677 {
4678   GdkWaylandSurface *impl= GDK_WAYLAND_SURFACE (surface);
4679   GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
4680   struct wl_surface *wl_surface = impl->display_server.wl_surface;
4681   struct wl_seat *seat = gdk_wayland_seat_get_wl_seat (gdk_seat);
4682   struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
4683 
4684   if (display->keyboard_shortcuts_inhibit == NULL)
4685     return;
4686 
4687   if (gdk_wayland_surface_get_inhibitor (impl, gdk_seat))
4688     return; /* Already inhibited */
4689 
4690   inhibitor =
4691       zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts (
4692           display->keyboard_shortcuts_inhibit, wl_surface, seat);
4693 
4694   g_hash_table_insert (impl->shortcuts_inhibitors, gdk_seat, inhibitor);
4695 }
4696 
4697 /*
4698  * gdk_wayland_surface_restore_shortcuts:
4699  * @surface: (type GdkWaylandSurface): a `GdkSurface`
4700  * @seat: the seat to inhibit
4701  *
4702  * Restores the shortcuts on the given @seat inhibited by calling
4703  * gdk_wayland_surface_inhibit_shortcuts().
4704  */
4705 void
gdk_wayland_surface_restore_shortcuts(GdkSurface * surface,GdkSeat * gdk_seat)4706 gdk_wayland_surface_restore_shortcuts (GdkSurface *surface,
4707                                        GdkSeat    *gdk_seat)
4708 {
4709   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
4710   struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
4711 
4712   inhibitor = gdk_wayland_surface_get_inhibitor (impl, gdk_seat);
4713   if (inhibitor == NULL)
4714     return; /* Not inhibitted */
4715 
4716   zwp_keyboard_shortcuts_inhibitor_v1_destroy (inhibitor);
4717   g_hash_table_remove (impl->shortcuts_inhibitors, gdk_seat);
4718 }
4719 
4720 GdkSurface *
create_dnd_surface(GdkDisplay * display)4721 create_dnd_surface (GdkDisplay *display)
4722 {
4723   GdkSurface *surface;
4724 
4725   surface = _gdk_wayland_display_create_surface (display,
4726                                                  GDK_SURFACE_TEMP,
4727                                                  NULL,
4728                                                  0, 0, 100, 100);
4729   GDK_WAYLAND_SURFACE (surface)->is_drag_surface = TRUE;
4730 
4731   return surface;
4732 }
4733 
4734 #define LAST_PROP 1
4735 
4736 static void
gdk_wayland_popup_init(GdkWaylandPopup * popup)4737 gdk_wayland_popup_init (GdkWaylandPopup *popup)
4738 {
4739 }
4740 
4741 static void
gdk_wayland_popup_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)4742 gdk_wayland_popup_get_property (GObject    *object,
4743                                 guint       prop_id,
4744                                 GValue     *value,
4745                                 GParamSpec *pspec)
4746 {
4747   GdkSurface *surface = GDK_SURFACE (object);
4748 
4749   switch (prop_id)
4750     {
4751     case LAST_PROP + GDK_POPUP_PROP_PARENT:
4752       g_value_set_object (value, surface->parent);
4753       break;
4754 
4755     case LAST_PROP + GDK_POPUP_PROP_AUTOHIDE:
4756       g_value_set_boolean (value, surface->autohide);
4757       break;
4758 
4759     default:
4760       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4761       break;
4762     }
4763 }
4764 
4765 static void
gdk_wayland_popup_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)4766 gdk_wayland_popup_set_property (GObject      *object,
4767                                 guint         prop_id,
4768                                 const GValue *value,
4769                                 GParamSpec   *pspec)
4770 {
4771   GdkSurface *surface = GDK_SURFACE (object);
4772 
4773   switch (prop_id)
4774     {
4775     case LAST_PROP + GDK_POPUP_PROP_PARENT:
4776       surface->parent = g_value_dup_object (value);
4777       if (surface->parent != NULL)
4778         surface->parent->children = g_list_prepend (surface->parent->children, surface);
4779       break;
4780 
4781     case LAST_PROP + GDK_POPUP_PROP_AUTOHIDE:
4782       surface->autohide = g_value_get_boolean (value);
4783       break;
4784 
4785     default:
4786       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4787       break;
4788     }
4789 }
4790 
4791 static void
gdk_wayland_popup_class_init(GdkWaylandPopupClass * class)4792 gdk_wayland_popup_class_init (GdkWaylandPopupClass *class)
4793 {
4794   GObjectClass *object_class = G_OBJECT_CLASS (class);
4795 
4796   object_class->get_property = gdk_wayland_popup_get_property;
4797   object_class->set_property = gdk_wayland_popup_set_property;
4798 
4799   gdk_popup_install_properties (object_class, 1);
4800 }
4801 
4802 static gboolean
gdk_wayland_popup_present(GdkPopup * popup,int width,int height,GdkPopupLayout * layout)4803 gdk_wayland_popup_present (GdkPopup       *popup,
4804                            int             width,
4805                            int             height,
4806                            GdkPopupLayout *layout)
4807 {
4808   return gdk_wayland_surface_present_popup (GDK_SURFACE (popup), width, height, layout);
4809 }
4810 
4811 static GdkGravity
gdk_wayland_popup_get_surface_anchor(GdkPopup * popup)4812 gdk_wayland_popup_get_surface_anchor (GdkPopup *popup)
4813 {
4814   return GDK_SURFACE (popup)->popup.surface_anchor;
4815 }
4816 
4817 static GdkGravity
gdk_wayland_popup_get_rect_anchor(GdkPopup * popup)4818 gdk_wayland_popup_get_rect_anchor (GdkPopup *popup)
4819 {
4820   return GDK_SURFACE (popup)->popup.rect_anchor;
4821 }
4822 
4823 static int
gdk_wayland_popup_get_position_x(GdkPopup * popup)4824 gdk_wayland_popup_get_position_x (GdkPopup *popup)
4825 {
4826   return GDK_SURFACE (popup)->x;
4827 }
4828 
4829 static int
gdk_wayland_popup_get_position_y(GdkPopup * popup)4830 gdk_wayland_popup_get_position_y (GdkPopup *popup)
4831 {
4832   return GDK_SURFACE (popup)->y;
4833 }
4834 
4835 static void
gdk_wayland_popup_iface_init(GdkPopupInterface * iface)4836 gdk_wayland_popup_iface_init (GdkPopupInterface *iface)
4837 {
4838   iface->present = gdk_wayland_popup_present;
4839   iface->get_surface_anchor = gdk_wayland_popup_get_surface_anchor;
4840   iface->get_rect_anchor = gdk_wayland_popup_get_rect_anchor;
4841   iface->get_position_x = gdk_wayland_popup_get_position_x;
4842   iface->get_position_y = gdk_wayland_popup_get_position_y;
4843 }
4844 
4845 static void
gdk_wayland_toplevel_init(GdkWaylandToplevel * toplevel)4846 gdk_wayland_toplevel_init (GdkWaylandToplevel *toplevel)
4847 {
4848 }
4849 
4850 static void
gdk_wayland_toplevel_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)4851 gdk_wayland_toplevel_set_property (GObject      *object,
4852                                    guint         prop_id,
4853                                    const GValue *value,
4854                                    GParamSpec   *pspec)
4855 {
4856   GdkSurface *surface = GDK_SURFACE (object);
4857   GdkWaylandToplevel *toplevel = GDK_WAYLAND_TOPLEVEL (surface);
4858 
4859   switch (prop_id)
4860     {
4861     case LAST_PROP + GDK_TOPLEVEL_PROP_TITLE:
4862       gdk_wayland_surface_set_title (surface, g_value_get_string (value));
4863       g_object_notify_by_pspec (G_OBJECT (surface), pspec);
4864       break;
4865 
4866     case LAST_PROP + GDK_TOPLEVEL_PROP_STARTUP_ID:
4867       gdk_wayland_surface_set_startup_id (surface, g_value_get_string (value));
4868       g_object_notify_by_pspec (G_OBJECT (surface), pspec);
4869       break;
4870 
4871     case LAST_PROP + GDK_TOPLEVEL_PROP_TRANSIENT_FOR:
4872       gdk_wayland_toplevel_set_transient_for (toplevel,
4873                                               g_value_get_object (value));
4874       g_object_notify_by_pspec (G_OBJECT (surface), pspec);
4875       break;
4876 
4877     case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL:
4878       gdk_wayland_surface_set_modal_hint (surface, g_value_get_boolean (value));
4879       g_object_notify_by_pspec (G_OBJECT (surface), pspec);
4880       break;
4881 
4882     case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
4883       break;
4884 
4885     case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED:
4886       break;
4887 
4888     case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
4889       break;
4890 
4891     case LAST_PROP + GDK_TOPLEVEL_PROP_FULLSCREEN_MODE:
4892       surface->fullscreen_mode = g_value_get_enum (value);
4893       g_object_notify_by_pspec (G_OBJECT (surface), pspec);
4894       break;
4895 
4896     case LAST_PROP + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED:
4897       break;
4898 
4899     default:
4900       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4901       break;
4902     }
4903 }
4904 
4905 static void
gdk_wayland_toplevel_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)4906 gdk_wayland_toplevel_get_property (GObject    *object,
4907                                    guint       prop_id,
4908                                    GValue     *value,
4909                                    GParamSpec *pspec)
4910 {
4911   GdkSurface *surface = GDK_SURFACE (object);
4912   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
4913   GdkWaylandToplevel *toplevel = GDK_WAYLAND_TOPLEVEL (surface);
4914 
4915   switch (prop_id)
4916     {
4917     case LAST_PROP + GDK_TOPLEVEL_PROP_STATE:
4918       g_value_set_flags (value, surface->state);
4919       break;
4920 
4921     case LAST_PROP + GDK_TOPLEVEL_PROP_TITLE:
4922       g_value_set_string (value, impl->title);
4923       break;
4924 
4925     case LAST_PROP + GDK_TOPLEVEL_PROP_STARTUP_ID:
4926       g_value_set_string (value, "");
4927       break;
4928 
4929     case LAST_PROP + GDK_TOPLEVEL_PROP_TRANSIENT_FOR:
4930       g_value_set_object (value, toplevel->transient_for);
4931       break;
4932 
4933     case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL:
4934       g_value_set_boolean (value, surface->modal_hint);
4935       break;
4936 
4937     case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
4938       g_value_set_pointer (value, NULL);
4939       break;
4940 
4941     case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED:
4942       break;
4943 
4944     case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
4945       break;
4946 
4947     case LAST_PROP + GDK_TOPLEVEL_PROP_FULLSCREEN_MODE:
4948       g_value_set_enum (value, surface->fullscreen_mode);
4949       break;
4950 
4951     case LAST_PROP + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED:
4952       g_value_set_boolean (value, surface->shortcuts_inhibited);
4953       break;
4954 
4955     default:
4956       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4957       break;
4958     }
4959 }
4960 
4961 static void
gdk_wayland_toplevel_class_init(GdkWaylandToplevelClass * class)4962 gdk_wayland_toplevel_class_init (GdkWaylandToplevelClass *class)
4963 {
4964   GObjectClass *object_class = G_OBJECT_CLASS (class);
4965 
4966   object_class->get_property = gdk_wayland_toplevel_get_property;
4967   object_class->set_property = gdk_wayland_toplevel_set_property;
4968 
4969   gdk_toplevel_install_properties (object_class, 1);
4970 }
4971 
4972 static void
gdk_wayland_toplevel_present(GdkToplevel * toplevel,GdkToplevelLayout * layout)4973 gdk_wayland_toplevel_present (GdkToplevel       *toplevel,
4974                               GdkToplevelLayout *layout)
4975 {
4976   GdkSurface *surface = GDK_SURFACE (toplevel);
4977   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
4978   gboolean pending_configure = FALSE;
4979   gboolean maximize;
4980   gboolean fullscreen;
4981 
4982   if (gdk_toplevel_layout_get_maximized (layout, &maximize))
4983     {
4984       if (maximize)
4985         gdk_wayland_surface_maximize (surface);
4986       else
4987         gdk_wayland_surface_unmaximize (surface);
4988       pending_configure = TRUE;
4989     }
4990 
4991   if (gdk_toplevel_layout_get_fullscreen (layout, &fullscreen))
4992     {
4993       if (fullscreen)
4994         {
4995           GdkMonitor *monitor;
4996 
4997           monitor = gdk_toplevel_layout_get_fullscreen_monitor (layout);
4998           if (monitor)
4999             gdk_wayland_surface_fullscreen_on_monitor (surface, monitor);
5000           else
5001             gdk_wayland_surface_fullscreen (surface);
5002         }
5003       else
5004         {
5005           gdk_wayland_surface_unfullscreen (surface);
5006         }
5007       pending_configure = TRUE;
5008     }
5009 
5010   g_clear_pointer (&impl->toplevel.layout, gdk_toplevel_layout_unref);
5011   impl->toplevel.layout = gdk_toplevel_layout_copy (layout);
5012 
5013   gdk_wayland_surface_show (surface, FALSE);
5014 
5015   if (!pending_configure)
5016     {
5017       impl->next_layout.surface_geometry_dirty = TRUE;
5018       gdk_surface_request_layout (surface);
5019     }
5020 }
5021 
5022 static gboolean
gdk_wayland_toplevel_minimize(GdkToplevel * toplevel)5023 gdk_wayland_toplevel_minimize (GdkToplevel *toplevel)
5024 {
5025   gdk_wayland_surface_minimize (GDK_SURFACE (toplevel));
5026 
5027   return TRUE;
5028 }
5029 
5030 static gboolean
gdk_wayland_toplevel_lower(GdkToplevel * toplevel)5031 gdk_wayland_toplevel_lower (GdkToplevel *toplevel)
5032 {
5033   return FALSE;
5034 }
5035 
5036 static void
gdk_wayland_toplevel_focus(GdkToplevel * toplevel,guint32 timestamp)5037 gdk_wayland_toplevel_focus (GdkToplevel *toplevel,
5038                             guint32      timestamp)
5039 {
5040   gdk_wayland_surface_focus (GDK_SURFACE (toplevel), timestamp);
5041 }
5042 
5043 static gboolean
gdk_wayland_toplevel_show_window_menu(GdkToplevel * toplevel,GdkEvent * event)5044 gdk_wayland_toplevel_show_window_menu (GdkToplevel *toplevel,
5045                                        GdkEvent    *event)
5046 {
5047   return gdk_wayland_surface_show_window_menu (GDK_SURFACE (toplevel), event);
5048 }
5049 
5050 static gboolean
gdk_wayland_toplevel_titlebar_gesture(GdkToplevel * toplevel,GdkTitlebarGesture gesture)5051 gdk_wayland_toplevel_titlebar_gesture (GdkToplevel        *toplevel,
5052                                        GdkTitlebarGesture  gesture)
5053 {
5054   return gdk_wayland_surface_titlebar_gesture (GDK_SURFACE (toplevel), gesture);
5055 }
5056 
5057 static gboolean
gdk_wayland_toplevel_supports_edge_constraints(GdkToplevel * toplevel)5058 gdk_wayland_toplevel_supports_edge_constraints (GdkToplevel *toplevel)
5059 {
5060   return gdk_wayland_surface_supports_edge_constraints (GDK_SURFACE (toplevel));
5061 }
5062 
5063 static void
inhibitor_active(void * data,struct zwp_keyboard_shortcuts_inhibitor_v1 * inhibitor)5064 inhibitor_active (void *data,
5065                   struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor)
5066 {
5067   GdkToplevel *toplevel = GDK_TOPLEVEL (data);
5068   GdkSurface *surface = GDK_SURFACE (toplevel);
5069 
5070   surface->shortcuts_inhibited = TRUE;
5071   g_object_notify (G_OBJECT (toplevel), "shortcuts-inhibited");
5072 }
5073 
5074 static void
inhibitor_inactive(void * data,struct zwp_keyboard_shortcuts_inhibitor_v1 * inhibitor)5075 inhibitor_inactive (void *data,
5076                     struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor)
5077 {
5078   GdkToplevel *toplevel = GDK_TOPLEVEL (data);
5079   GdkSurface *surface = GDK_SURFACE (toplevel);
5080 
5081   surface->shortcuts_inhibited = FALSE;
5082   g_object_notify (G_OBJECT (toplevel), "shortcuts-inhibited");
5083 }
5084 
5085 static const struct zwp_keyboard_shortcuts_inhibitor_v1_listener
5086 zwp_keyboard_shortcuts_inhibitor_listener = {
5087   inhibitor_active,
5088   inhibitor_inactive,
5089 };
5090 
5091 static void
gdk_wayland_toplevel_inhibit_system_shortcuts(GdkToplevel * toplevel,GdkEvent * event)5092 gdk_wayland_toplevel_inhibit_system_shortcuts (GdkToplevel *toplevel,
5093                                                GdkEvent    *event)
5094 {
5095   struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
5096   GdkSurface *surface = GDK_SURFACE (toplevel);
5097   GdkWaylandSurface *impl= GDK_WAYLAND_SURFACE (surface);
5098   GdkSeat *gdk_seat;
5099 
5100   if (surface->shortcuts_inhibited)
5101     return;
5102 
5103   gdk_seat = gdk_surface_get_seat_from_event (surface, event);
5104   gdk_wayland_surface_inhibit_shortcuts (surface, gdk_seat);
5105 
5106   inhibitor = gdk_wayland_surface_get_inhibitor (impl, gdk_seat);
5107   if (!inhibitor)
5108     return;
5109 
5110   surface->current_shortcuts_inhibited_seat = gdk_seat;
5111   zwp_keyboard_shortcuts_inhibitor_v1_add_listener
5112     (inhibitor, &zwp_keyboard_shortcuts_inhibitor_listener, toplevel);
5113 }
5114 
5115 static void
gdk_wayland_toplevel_restore_system_shortcuts(GdkToplevel * toplevel)5116 gdk_wayland_toplevel_restore_system_shortcuts (GdkToplevel *toplevel)
5117 {
5118   GdkSurface *surface = GDK_SURFACE (toplevel);
5119 
5120   gdk_wayland_surface_restore_shortcuts (surface,
5121                                          surface->current_shortcuts_inhibited_seat);
5122   surface->current_shortcuts_inhibited_seat = NULL;
5123   surface->shortcuts_inhibited = FALSE;
5124   g_object_notify (G_OBJECT (toplevel), "shortcuts-inhibited");
5125 }
5126 
5127 static void
gdk_wayland_toplevel_iface_init(GdkToplevelInterface * iface)5128 gdk_wayland_toplevel_iface_init (GdkToplevelInterface *iface)
5129 {
5130   iface->present = gdk_wayland_toplevel_present;
5131   iface->minimize = gdk_wayland_toplevel_minimize;
5132   iface->lower = gdk_wayland_toplevel_lower;
5133   iface->focus = gdk_wayland_toplevel_focus;
5134   iface->show_window_menu = gdk_wayland_toplevel_show_window_menu;
5135   iface->titlebar_gesture = gdk_wayland_toplevel_titlebar_gesture;
5136   iface->supports_edge_constraints = gdk_wayland_toplevel_supports_edge_constraints;
5137   iface->inhibit_system_shortcuts = gdk_wayland_toplevel_inhibit_system_shortcuts;
5138   iface->restore_system_shortcuts = gdk_wayland_toplevel_restore_system_shortcuts;
5139   iface->begin_resize = gdk_wayland_toplevel_begin_resize;
5140   iface->begin_move = gdk_wayland_toplevel_begin_move;
5141 }
5142 
5143 static void
gdk_wayland_drag_surface_init(GdkWaylandDragSurface * surface)5144 gdk_wayland_drag_surface_init (GdkWaylandDragSurface *surface)
5145 {
5146 }
5147 
5148 static void
gdk_wayland_drag_surface_class_init(GdkWaylandDragSurfaceClass * class)5149 gdk_wayland_drag_surface_class_init (GdkWaylandDragSurfaceClass *class)
5150 {
5151 }
5152 
5153 static gboolean
gdk_wayland_drag_surface_present(GdkDragSurface * drag_surface,int width,int height)5154 gdk_wayland_drag_surface_present (GdkDragSurface *drag_surface,
5155                                   int             width,
5156                                   int             height)
5157 {
5158   GdkSurface *surface = GDK_SURFACE (drag_surface);
5159   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
5160 
5161   gdk_wayland_surface_show (surface, FALSE);
5162 
5163   impl->next_layout.configured_width = width;
5164   impl->next_layout.configured_height = height;
5165   impl->next_layout.surface_geometry_dirty = TRUE;
5166   gdk_surface_request_layout (surface);
5167 
5168   maybe_notify_mapped (surface);
5169 
5170   return TRUE;
5171 }
5172 
5173 static void
gdk_wayland_drag_surface_iface_init(GdkDragSurfaceInterface * iface)5174 gdk_wayland_drag_surface_iface_init (GdkDragSurfaceInterface *iface)
5175 {
5176   iface->present = gdk_wayland_drag_surface_present;
5177 }
5178 
5179