1/*
2 * Copyright © 2010 Intel Corporation
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19
20#include <netinet/in.h>
21#include <unistd.h>
22
23#include "gdk.h"
24#include "gdkwayland.h"
25
26#include "gdkwindow.h"
27#include "gdkwindowimpl.h"
28#include "gdkdisplay-wayland.h"
29#include "gdkglcontext-wayland.h"
30#include "gdkframeclockprivate.h"
31#include "gdkprivate-wayland.h"
32#include "gdkinternals.h"
33#include "gdkdeviceprivate.h"
34
35#include <stdlib.h>
36#include <stdio.h>
37#include <string.h>
38#include <errno.h>
39
40enum {
41 COMMITTED,
42
43 LAST_SIGNAL
44};
45
46static guint signals[LAST_SIGNAL];
47
48/*
49 * Define GNOME additional states to xdg-shell
50 * The current reserved range for GNOME is 0x1000 - 0x1FFF
51 */
52
53#define XDG_SURFACE_STATE_GNOME_TILED 0x1000
54
55#define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
56 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
57 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
58
59#define WINDOW_IS_TOPLEVEL(window) \
60 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
61 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
62 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
63
64#define MAX_WL_BUFFER_SIZE (4083) /* 4096 minus header, string argument length and NUL byte */
65
66typedef struct _GdkWaylandWindow GdkWaylandWindow;
67typedef struct _GdkWaylandWindowClass GdkWaylandWindowClass;
68
69struct _GdkWaylandWindow
70{
71 GdkWindow parent;
72};
73
74struct _GdkWaylandWindowClass
75{
76 GdkWindowClass parent_class;
77};
78
79G_DEFINE_TYPE (GdkWaylandWindow, gdk_wayland_window, GDK_TYPE_WINDOW)
80
81static void
82gdk_wayland_window_class_init (GdkWaylandWindowClass *wayland_window_class)
83{
84}
85
86static void
87gdk_wayland_window_init (GdkWaylandWindow *wayland_window)
88{
89}
90
91#define GDK_TYPE_WINDOW_IMPL_WAYLAND (_gdk_window_impl_wayland_get_type ())
92#define GDK_WINDOW_IMPL_WAYLAND(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWayland))
93#define GDK_WINDOW_IMPL_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWaylandClass))
94#define GDK_IS_WINDOW_IMPL_WAYLAND(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WINDOW_IMPL_WAYLAND))
95#define GDK_IS_WINDOW_IMPL_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_WAYLAND))
96#define GDK_WINDOW_IMPL_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWaylandClass))
97
98typedef struct _GdkWindowImplWayland GdkWindowImplWayland;
99typedef struct _GdkWindowImplWaylandClass GdkWindowImplWaylandClass;
100
101struct _GdkWindowImplWayland
102{
103 GdkWindowImpl parent_instance;
104
105 GdkWindow *wrapper;
106
107 struct {
108 /* The wl_outputs that this window currently touches */
109 GSList *outputs;
110
111 struct wl_surface *wl_surface;
112 struct xdg_surface *xdg_surface;
113 struct xdg_popup *xdg_popup;
114 struct gtk_surface1 *gtk_surface;
115 struct wl_subsurface *wl_subsurface;
116 struct wl_egl_window *egl_window;
117 struct wl_egl_window *dummy_egl_window;
118 } display_server;
119
120 EGLSurface egl_surface;
121 EGLSurface dummy_egl_surface;
122
123 unsigned int mapped : 1;
124 unsigned int use_custom_surface : 1;
125 unsigned int pending_buffer_attached : 1;
126 unsigned int pending_commit : 1;
127 unsigned int awaiting_frame : 1;
128 unsigned int position_set : 1;
129 GdkWindowTypeHint hint;
130 GdkWindow *transient_for;
131
132 cairo_surface_t *staging_cairo_surface;
133 cairo_surface_t *committed_cairo_surface;
134 cairo_surface_t *backfill_cairo_surface;
135
136 int pending_buffer_offset_x;
137 int pending_buffer_offset_y;
138
139 gchar *title;
140
141 struct {
142 gboolean was_set;
143
144 gchar *application_id;
145 gchar *app_menu_path;
146 gchar *menubar_path;
147 gchar *window_object_path;
148 gchar *application_object_path;
149 gchar *unique_bus_name;
150 } application;
151
152 GdkGeometry geometry_hints;
153 GdkWindowHints geometry_mask;
154
155 GdkSeat *grab_input_seat;
156
157 gint64 pending_frame_counter;
158 guint32 scale;
159
160 int margin_left;
161 int margin_right;
162 int margin_top;
163 int margin_bottom;
164
165 int initial_fullscreen_monitor;
166
167 cairo_region_t *opaque_region;
168 cairo_region_t *input_region;
169 cairo_region_t *staged_updates_region;
170
171 int saved_width;
172 int saved_height;
173
174 gulong parent_surface_committed_handler;
175};
176
177struct _GdkWindowImplWaylandClass
178{
179 GdkWindowImplClass parent_class;
180};
181
182static void gdk_wayland_window_maybe_configure (GdkWindow *window,
183 int width,
184 int height,
185 int scale);
186
187static void maybe_set_gtk_surface_dbus_properties (GdkWindow *window);
188static void maybe_set_gtk_surface_modal (GdkWindow *window);
189
190static void gdk_window_request_transient_parent_commit (GdkWindow *window);
191
192GType _gdk_window_impl_wayland_get_type (void);
193
194G_DEFINE_TYPE (GdkWindowImplWayland, _gdk_window_impl_wayland, GDK_TYPE_WINDOW_IMPL)
195
196static void
197_gdk_window_impl_wayland_init (GdkWindowImplWayland *impl)
198{
199 impl->scale = 1;
200 impl->initial_fullscreen_monitor = -1;
201 impl->saved_width = -1;
202 impl->saved_height = -1;
203}
204
205static void
206_gdk_wayland_screen_add_orphan_dialog (GdkWindow *window)
207{
208 GdkWaylandDisplay *display_wayland =
209 GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
210
211 if (!g_list_find (display_wayland->orphan_dialogs, window))
212 display_wayland->orphan_dialogs =
213 g_list_prepend (display_wayland->orphan_dialogs, window);
214}
215
216static void
217drop_cairo_surfaces (GdkWindow *window)
218{
219 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
220
221 g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
222 g_clear_pointer (&impl->backfill_cairo_surface, cairo_surface_destroy);
223
224 /* We nullify this so if a buffer release comes in later, we won't
225 * try to reuse that buffer since it's no longer suitable
226 */
227 impl->committed_cairo_surface = NULL;
228}
229
230static void
231_gdk_wayland_window_save_size (GdkWindow *window)
232{
233 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
234
235 if (window->state & (GDK_WINDOW_STATE_FULLSCREEN | GDK_WINDOW_STATE_MAXIMIZED))
236 return;
237
238 impl->saved_width = window->width - impl->margin_left - impl->margin_right;
239 impl->saved_height = window->height - impl->margin_top - impl->margin_bottom;
240}
241
242static void
243_gdk_wayland_window_clear_saved_size (GdkWindow *window)
244{
245 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
246
247 if (window->state & (GDK_WINDOW_STATE_FULLSCREEN | GDK_WINDOW_STATE_MAXIMIZED))
248 return;
249
250 impl->saved_width = -1;
251 impl->saved_height = -1;
252}
253
254/*
255 * gdk_wayland_window_update_size:
256 * @drawable: a #GdkDrawableImplWayland.
257 *
258 * Updates the state of the drawable (in particular the drawable's
259 * cairo surface) when its size has changed.
260 */
261static void
262gdk_wayland_window_update_size (GdkWindow *window,
263 int32_t width,
264 int32_t height,
265 int scale)
266{
267 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
268 GdkRectangle area;
269 cairo_region_t *region;
270
271 if ((window->width == width) &&
272 (window->height == height) &&
273 (impl->scale == scale))
274 return;
275
276 drop_cairo_surfaces (window);
277
278 window->width = width;
279 window->height = height;
280 impl->scale = scale;
281
282 if (impl->display_server.egl_window)
283 {
284 wl_egl_window_resize (impl->display_server.egl_window,
285 width * scale,
286 height * scale,
287 0, 0);
288 wl_surface_set_buffer_scale (impl->display_server.wl_surface, scale);
289 }
290
291 area.x = 0;
292 area.y = 0;
293 area.width = window->width;
294 area.height = window->height;
295
296 region = cairo_region_create_rectangle (&area);
297 _gdk_window_invalidate_for_expose (window, region);
298 cairo_region_destroy (region);
299}
300
301GdkWindow *
302_gdk_wayland_screen_create_root_window (GdkScreen *screen,
303 int width,
304 int height)
305{
306 GdkWaylandDisplay *display_wayland =
307 GDK_WAYLAND_DISPLAY (gdk_screen_get_display (screen));
308 GdkWindow *window;
309 GdkWindowImplWayland *impl;
310
311 window = _gdk_display_create_window (GDK_DISPLAY (display_wayland));
312 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL);
313 window->impl_window = window;
314 window->visual = gdk_screen_get_system_visual (screen);
315
316 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
317
318 impl->wrapper = GDK_WINDOW (window);
319 if (display_wayland->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE &&
320 gdk_screen_get_n_monitors (screen) > 0)
321 impl->scale = gdk_screen_get_monitor_scale_factor (screen, 0);
322
323 /* logical 1x1 fake buffer */
324 impl->staging_cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
325 impl->scale,
326 impl->scale);
327
328 cairo_surface_set_device_scale (impl->staging_cairo_surface, impl->scale, impl->scale);
329
330 window->window_type = GDK_WINDOW_ROOT;
331 window->depth = 32;
332
333 window->x = 0;
334 window->y = 0;
335 window->abs_x = 0;
336 window->abs_y = 0;
337 window->width = width;
338 window->height = height;
339 window->viewable = TRUE;
340
341 /* see init_randr_support() in gdkscreen-wayland.c */
342 window->event_mask = GDK_STRUCTURE_MASK;
343
344 return window;
345}
346
347static const gchar *
348get_default_title (void)
349{
350 const char *title;
351
352 title = g_get_application_name ();
353 if (!title)
354 title = g_get_prgname ();
355 if (!title)
356 title = "";
357
358 return title;
359}
360
361static void
362fill_presentation_time_from_frame_time (GdkFrameTimings *timings,
363 guint32 frame_time)
364{
365 /* The timestamp in a wayland frame is a msec time value that in some
366 * way reflects the time at which the server started drawing the frame.
367 * This is not useful from our perspective.
368 *
369 * However, for the DRM backend of Weston, on reasonably recent
370 * Linux, we know that the time is the
371 * clock_gettime (CLOCK_MONOTONIC) value at the vblank, and that
372 * backend starts drawing immediately after receiving the vblank
373 * notification. If we detect this, and make the assumption that the
374 * compositor will finish drawing before the next vblank, we can
375 * then determine the presentation time as the frame time we
376 * received plus one refresh interval.
377 *
378 * If a backend is using clock_gettime(CLOCK_MONOTONIC), but not
379 * picking values right at the vblank, then the presentation times
380 * we compute won't be accurate, but not really worse than then
381 * the alternative of not providing presentation times at all.
382 *
383 * The complexity here is dealing with the fact that we receive
384 * only the low 32 bits of the CLOCK_MONOTONIC value in milliseconds.
385 */
386 gint64 now_monotonic = g_get_monotonic_time ();
387 gint64 now_monotonic_msec = now_monotonic / 1000;
388 uint32_t now_monotonic_low = (uint32_t)now_monotonic_msec;
389
390 if (frame_time - now_monotonic_low < 1000 ||
391 frame_time - now_monotonic_low > (uint32_t)-1000)
392 {
393 /* Timestamp we received is within one second of the current time.
394 */
395 gint64 last_frame_time = now_monotonic + (gint64)1000 * (gint32)(frame_time - now_monotonic_low);
396 if ((gint32)now_monotonic_low < 0 && (gint32)frame_time > 0)
397 last_frame_time += (gint64)1000 * G_GINT64_CONSTANT(0x100000000);
398 else if ((gint32)now_monotonic_low > 0 && (gint32)frame_time < 0)
399 last_frame_time -= (gint64)1000 * G_GINT64_CONSTANT(0x100000000);
400
401 timings->presentation_time = last_frame_time + timings->refresh_interval;
402 }
403}
404
405static void
406read_back_cairo_surface (GdkWindow *window)
407{
408 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
409 cairo_t *cr;
410 cairo_region_t *paint_region = NULL;
411
412 if (!impl->backfill_cairo_surface)
413 goto out;
414
415 paint_region = cairo_region_copy (window->clip_region);
416 cairo_region_subtract (paint_region, impl->staged_updates_region);
417
418 if (cairo_region_is_empty (paint_region))
419 goto out;
420
421 cr = cairo_create (impl->staging_cairo_surface);
422 cairo_set_source_surface (cr, impl->backfill_cairo_surface, 0, 0);
423 gdk_cairo_region (cr, paint_region);
424 cairo_clip (cr);
425 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
426 cairo_paint (cr);
427 cairo_destroy (cr);
428 cairo_surface_flush (impl->staging_cairo_surface);
429
430out:
431 g_clear_pointer (&paint_region, cairo_region_destroy);
432 g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
433 g_clear_pointer (&impl->backfill_cairo_surface, cairo_surface_destroy);
434}
435
436static void
437frame_callback (void *data,
438 struct wl_callback *callback,
439 uint32_t time)
440{
441 GdkWindow *window = data;
442 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
443 GdkWaylandDisplay *display_wayland =
444 GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
445 GdkFrameClock *clock = gdk_window_get_frame_clock (window);
446 GdkFrameTimings *timings;
447
448 GDK_NOTE (EVENTS,
449 g_message ("frame %p", window));
450
451 wl_callback_destroy (callback);
452
453 if (GDK_WINDOW_DESTROYED (window))
454 return;
455
456 if (!impl->awaiting_frame)
457 return;
458
459 impl->awaiting_frame = FALSE;
460 _gdk_frame_clock_thaw (clock);
461
462 timings = gdk_frame_clock_get_timings (clock, impl->pending_frame_counter);
463 impl->pending_frame_counter = 0;
464
465 if (timings == NULL)
466 return;
467
468 timings->refresh_interval = 16667; /* default to 1/60th of a second */
469 if (impl->display_server.outputs)
470 {
471 /* We pick a random output out of the outputs that the window touches
472 * The rate here is in milli-hertz */
473 int refresh_rate =
474 _gdk_wayland_screen_get_output_refresh_rate (display_wayland->screen,
475 impl->display_server.outputs->data);
476 if (refresh_rate != 0)
477 timings->refresh_interval = G_GINT64_CONSTANT(1000000000) / refresh_rate;
478 }
479
480 fill_presentation_time_from_frame_time (timings, time);
481
482 timings->complete = TRUE;
483
484#ifdef G_ENABLE_DEBUG
485 if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
486 _gdk_frame_clock_debug_print_timings (clock, timings);
487#endif
488}
489
490static const struct wl_callback_listener frame_listener = {
491 frame_callback
492};
493
494static void
495on_frame_clock_before_paint (GdkFrameClock *clock,
496 GdkWindow *window)
497{
498 GdkFrameTimings *timings = gdk_frame_clock_get_current_timings (clock);
499 gint64 presentation_time;
500 gint64 refresh_interval;
501
502 gdk_frame_clock_get_refresh_info (clock,
503 timings->frame_time,
504 &refresh_interval, &presentation_time);
505
506 if (presentation_time != 0)
507 {
508 /* Assume the algorithm used by the DRM backend of Weston - it
509 * starts drawing at the next vblank after receiving the commit
510 * for this frame, and presentation occurs at the vblank
511 * after that.
512 */
513 timings->predicted_presentation_time = presentation_time + refresh_interval;
514 }
515 else
516 {
517 /* As above, but we don't actually know the phase of the vblank,
518 * so just assume that we're half way through a refresh cycle.
519 */
520 timings->predicted_presentation_time = timings->frame_time + refresh_interval / 2 + refresh_interval;
521 }
522}
523
524static void
525on_frame_clock_after_paint (GdkFrameClock *clock,
526 GdkWindow *window)
527{
528 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
529 struct wl_callback *callback;
530
531 if (!impl->pending_commit)
532 return;
533
534 callback = wl_surface_frame (impl->display_server.wl_surface);
535 wl_callback_add_listener (callback, &frame_listener, window);
536 _gdk_frame_clock_freeze (clock);
537
538 /* Before we commit a new buffer, make sure we've backfilled
539 * undrawn parts from any old committed buffer
540 */
541 if (impl->pending_buffer_attached)
542 read_back_cairo_surface (window);
543
544 /* From this commit forward, we can't write to the buffer,
545 * it's "live". In the future, if we need to stage more changes
546 * we have to allocate a new staging buffer and draw to it instead.
547 *
548 * Our one saving grace is if the compositor releases the buffer
549 * before we need to stage any changes, then we can take it back and
550 * use it again.
551 */
552 wl_surface_commit (impl->display_server.wl_surface);
553
554 if (impl->pending_buffer_attached)
555 impl->committed_cairo_surface = g_steal_pointer (&impl->staging_cairo_surface);
556
557 impl->pending_buffer_attached = FALSE;
558 impl->pending_commit = FALSE;
559 impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
560 impl->awaiting_frame = TRUE;
561
562 g_signal_emit (impl, signals[COMMITTED], 0);
563}
564
565static void
566window_update_scale (GdkWindow *window)
567{
568 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
569 GdkWaylandDisplay *display_wayland =
570 GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
571 guint32 scale;
572 GSList *l;
573
574 if (display_wayland->compositor_version < WL_SURFACE_HAS_BUFFER_SCALE)
575 {
576 /* We can't set the scale on this surface */
577 return;
578 }
579
580 scale = 1;
581 for (l = impl->display_server.outputs; l != NULL; l = l->next)
582 {
583 guint32 output_scale =
584 _gdk_wayland_screen_get_output_scale (display_wayland->screen, l->data);
585 scale = MAX (scale, output_scale);
586 }
587
588 /* Notify app that scale changed */
589 gdk_wayland_window_maybe_configure (window, window->width, window->height, scale);
590}
591
592static void
593on_monitors_changed (GdkScreen *screen,
594 GdkWindow *window)
595{
596 window_update_scale (window);
597}
598
599
600static void gdk_wayland_window_create_surface (GdkWindow *window);
601
602void
603_gdk_wayland_display_create_window_impl (GdkDisplay *display,
604 GdkWindow *window,
605 GdkWindow *real_parent,
606 GdkScreen *screen,
607 GdkEventMask event_mask,
608 GdkWindowAttr *attributes,
609 gint attributes_mask)
610{
611 GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
612 GdkWindowImplWayland *impl;
613 GdkFrameClock *frame_clock;
614 const char *title;
615
616 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL);
617 window->impl = GDK_WINDOW_IMPL (impl);
618 impl->wrapper = GDK_WINDOW (window);
619
620 if (window->width > 65535)
621 {
622 g_warning ("Native Windows wider than 65535 pixels are not supported");
623 window->width = 65535;
624 }
625 if (window->height > 65535)
626 {
627 g_warning ("Native Windows taller than 65535 pixels are not supported");
628 window->height = 65535;
629 }
630
631 g_object_ref (window);
632
633 /* More likely to be right than just assuming 1 */
634 if (display_wayland->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE &&
635 gdk_screen_get_n_monitors (screen) > 0)
636 impl->scale = gdk_screen_get_monitor_scale_factor (screen, 0);
637
638 impl->title = NULL;
639
640 switch (GDK_WINDOW_TYPE (window))
641 {
642 case GDK_WINDOW_TOPLEVEL:
643 case GDK_WINDOW_TEMP:
644 if (attributes_mask & GDK_WA_TITLE)
645 title = attributes->title;
646 else
647 title = get_default_title ();
648
649 gdk_window_set_title (window, title);
650 break;
651
652 case GDK_WINDOW_CHILD:
653 default:
654 break;
655 }
656
657 gdk_wayland_window_create_surface (window);
658
659 if (attributes_mask & GDK_WA_TYPE_HINT)
660 gdk_window_set_type_hint (window, attributes->type_hint);
661
662 frame_clock = gdk_window_get_frame_clock (window);
663
664 g_signal_connect (frame_clock, "before-paint",
665 G_CALLBACK (on_frame_clock_before_paint), window);
666 g_signal_connect (frame_clock, "after-paint",
667 G_CALLBACK (on_frame_clock_after_paint), window);
668
669 g_signal_connect (screen, "monitors-changed",
670 G_CALLBACK (on_monitors_changed), window);
671}
672
673static void
674gdk_wayland_window_attach_image (GdkWindow *window)
675{
676 GdkWaylandDisplay *display;
677 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
678
679 if (GDK_WINDOW_DESTROYED (window))
680 return;
681
682 g_assert (_gdk_wayland_is_shm_surface (impl->staging_cairo_surface));
683
684 /* Attach this new buffer to the surface */
685 wl_surface_attach (impl->display_server.wl_surface,
686 _gdk_wayland_shm_surface_get_wl_buffer (impl->staging_cairo_surface),
687 impl->pending_buffer_offset_x,
688 impl->pending_buffer_offset_y);
689 impl->pending_buffer_offset_x = 0;
690 impl->pending_buffer_offset_y = 0;
691
692 /* Only set the buffer scale if supported by the compositor */
693 display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
694 if (display->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE)
695 wl_surface_set_buffer_scale (impl->display_server.wl_surface, impl->scale);
696
697 impl->pending_buffer_attached = TRUE;
698 impl->pending_commit = TRUE;
699}
700
701static const cairo_user_data_key_t gdk_wayland_window_cairo_key;
702
703static void
704buffer_release_callback (void *_data,
705 struct wl_buffer *wl_buffer)
706{
707 cairo_surface_t *cairo_surface = _data;
708 GdkWindowImplWayland *impl = cairo_surface_get_user_data (cairo_surface, &gdk_wayland_window_cairo_key);
709
710 g_return_if_fail (GDK_IS_WINDOW_IMPL_WAYLAND (impl));
711
712 /* The released buffer isn't the latest committed one, we have no further
713 * use for it, so clean it up.
714 */
715 if (impl->committed_cairo_surface != cairo_surface)
716 {
717 /* If this fails, then the surface buffer got reused before it was
718 * released from the compositor
719 */
720 g_warn_if_fail (impl->staging_cairo_surface != cairo_surface);
721
722 cairo_surface_destroy (cairo_surface);
723 return;
724 }
725
726 if (impl->staged_updates_region != NULL)
727 {
728 /* If this fails, then we're tracking staged updates on a staging surface
729 * that doesn't exist.
730 */
731 g_warn_if_fail (impl->staging_cairo_surface != NULL);
732
733 /* If we've staged updates into a new buffer before the release for this
734 * buffer came in, then we can't reuse this buffer, so unref it. It may still
735 * be alive as a readback buffer though (via impl->backfill_cairo_surface).
736 *
737 * It's possible a staging surface was allocated but no updates were staged.
738 * If that happened, clean up that staging surface now, since the old commit
739 * buffer is available again, and reusing the old commit buffer for future
740 * updates will save having to do a read back later.
741 */
742 if (!cairo_region_is_empty (impl->staged_updates_region))
743 {
744 g_clear_pointer (&impl->committed_cairo_surface, cairo_surface_destroy);
745 return;
746 }
747 else
748 {
749 g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
750 g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
751 }
752 }
753
754 /* Release came in, we haven't done any interim updates, so we can just use
755 * the old committed buffer again.
756 */
757 impl->staging_cairo_surface = g_steal_pointer (&impl->committed_cairo_surface);
758}
759
760static const struct wl_buffer_listener buffer_listener = {
761 buffer_release_callback
762};
763
764static void
765gdk_wayland_window_ensure_cairo_surface (GdkWindow *window)
766{
767 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
768
769 /* If we are drawing using OpenGL then we only need a logical 1x1 surface. */
770 if (impl->display_server.egl_window)
771 {
772 if (impl->staging_cairo_surface &&
773 _gdk_wayland_is_shm_surface (impl->staging_cairo_surface))
774 cairo_surface_destroy (impl->staging_cairo_surface);
775
776 impl->staging_cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
777 impl->scale,
778 impl->scale);
779 cairo_surface_set_device_scale (impl->staging_cairo_surface,
780 impl->scale, impl->scale);
781 }
782 else if (!impl->staging_cairo_surface)
783 {
784 GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (impl->wrapper));
785 struct wl_buffer *buffer;
786
787 impl->staging_cairo_surface = _gdk_wayland_display_create_shm_surface (display_wayland,
788 impl->wrapper->width,
789 impl->wrapper->height,
790 impl->scale);
791 cairo_surface_set_user_data (impl->staging_cairo_surface,
792 &gdk_wayland_window_cairo_key,
793 g_object_ref (impl),
794 (cairo_destroy_func_t)
795 g_object_unref);
796 buffer = _gdk_wayland_shm_surface_get_wl_buffer (impl->staging_cairo_surface);
797 wl_buffer_add_listener (buffer, &buffer_listener, impl->staging_cairo_surface);
798 }
799}
800
801/* The cairo surface returned here uses a memory segment that's shared
802 * with the display server. This is not a temporary buffer that gets
803 * copied to the display server, but the actual buffer the display server
804 * will ultimately end up sending to the GPU. At the time this happens
805 * impl->committed_cairo_surface gets set to impl->staging_cairo_surface, and
806 * impl->staging_cairo_surface gets nullified.
807 */
808static cairo_surface_t *
809gdk_wayland_window_ref_cairo_surface (GdkWindow *window)
810{
811 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
812
813 if (GDK_WINDOW_DESTROYED (impl->wrapper))
814 return NULL;
815
816 gdk_wayland_window_ensure_cairo_surface (window);
817
818 cairo_surface_reference (impl->staging_cairo_surface);
819
820 return impl->staging_cairo_surface;
821}
822
823static cairo_surface_t *
824gdk_wayland_window_create_similar_image_surface (GdkWindow * window,
825 cairo_format_t format,
826 int width,
827 int height)
828{
829 return cairo_image_surface_create (format, width, height);
830}
831
832static gboolean
833gdk_window_impl_wayland_begin_paint (GdkWindow *window)
834{
835 gdk_wayland_window_ensure_cairo_surface (window);
836
837 return FALSE;
838}
839
840static void
841gdk_window_impl_wayland_end_paint (GdkWindow *window)
842{
843 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
844 cairo_rectangle_int_t rect;
845 int i, n;
846
847 if (!window->current_paint.use_gl &&
848 !cairo_region_is_empty (window->current_paint.region))
849 {
850 gdk_wayland_window_attach_image (window);
851
852 /* If there's a committed buffer pending, then track which
853 * updates are staged until the next frame, so we can back
854 * fill the unstaged parts of the staging buffer with the
855 * last frame.
856 */
857 if (impl->committed_cairo_surface != NULL)
858 {
859 if (impl->staged_updates_region == NULL)
860 {
861 impl->staged_updates_region = cairo_region_copy (window->current_paint.region);
862 impl->backfill_cairo_surface = cairo_surface_reference (impl->committed_cairo_surface);
863 }
864 else
865 {
866 cairo_region_union (impl->staged_updates_region, window->current_paint.region);
867 }
868 }
869
870 n = cairo_region_num_rectangles (window->current_paint.region);
871 for (i = 0; i < n; i++)
872 {
873 cairo_region_get_rectangle (window->current_paint.region, i, &rect);
874 wl_surface_damage (impl->display_server.wl_surface, rect.x, rect.y, rect.width, rect.height);
875 }
876
877 impl->pending_commit = TRUE;
878 }
879}
880
881static gboolean
882gdk_window_impl_wayland_beep (GdkWindow *window)
883{
884 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
885 GdkWaylandDisplay *display_wayland =
886 GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
887
888 if (!display_wayland->gtk_shell)
889 return FALSE;
890
891 gtk_shell1_system_bell (display_wayland->gtk_shell,
892 impl->display_server.gtk_surface);
893
894 return TRUE;
895}
896
897static void
898gdk_window_impl_wayland_finalize (GObject *object)
899{
900 GdkWindowImplWayland *impl;
901
902 g_return_if_fail (GDK_IS_WINDOW_IMPL_WAYLAND (object));
903
904 impl = GDK_WINDOW_IMPL_WAYLAND (object);
905
906 g_free (impl->title);
907
908 g_free (impl->application.application_id);
909 g_free (impl->application.app_menu_path);
910 g_free (impl->application.menubar_path);
911 g_free (impl->application.window_object_path);
912 g_free (impl->application.application_object_path);
913 g_free (impl->application.unique_bus_name);
914
915 g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
916 g_clear_pointer (&impl->input_region, cairo_region_destroy);
917 g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
918
919 G_OBJECT_CLASS (_gdk_window_impl_wayland_parent_class)->finalize (object);
920}
921
922static void
923gdk_wayland_window_configure (GdkWindow *window,
924 int width,
925 int height,
926 int scale)
927{
928 GdkDisplay *display;
929 GdkEvent *event;
930
931 event = gdk_event_new (GDK_CONFIGURE);
932 event->configure.window = g_object_ref (window);
933 event->configure.send_event = FALSE;
934 event->configure.width = width;
935 event->configure.height = height;
936
937 gdk_wayland_window_update_size (window, width, height, scale);
938 _gdk_window_update_size (window);
939
940 display = gdk_window_get_display (window);
941 _gdk_wayland_display_deliver_event (display, event);
942}
943
944static void
945gdk_wayland_window_maybe_configure (GdkWindow *window,
946 int width,
947 int height,
948 int scale)
949{
950 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
951
952 if (window->width == width &&
953 window->height == height &&
954 impl->scale == scale)
955 return;
956
957 gdk_wayland_window_configure (window, width, height, scale);
958}
959
960static void
961gdk_wayland_window_sync_parent (GdkWindow *window,
962 GdkWindow *parent)
963{
964 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
965 GdkWindowImplWayland *impl_parent = NULL;
966 struct xdg_surface *parent_surface;
967
968 g_assert (parent == NULL ||
969 gdk_window_get_display (window) == gdk_window_get_display (parent));
970
971 if (!impl->display_server.xdg_surface)
972 return;
973
974 if (impl->transient_for)
975 impl_parent = GDK_WINDOW_IMPL_WAYLAND (impl->transient_for->impl);
976 else if (parent)
977 impl_parent = GDK_WINDOW_IMPL_WAYLAND (parent->impl);
978
979 if (impl_parent)
980 {
981 /* XXX: Is this correct? */
982 if (!impl_parent->display_server.wl_surface)
983 return;
984
985 parent_surface = impl_parent->display_server.xdg_surface;
986 }
987 else
988 parent_surface = NULL;
989
990 xdg_surface_set_parent (impl->display_server.xdg_surface, parent_surface);
991}
992
993static void
994gdk_wayland_window_update_dialogs (GdkWindow *window)
995{
996 GdkWaylandDisplay *display_wayland =
997 GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
998 GList *l;
999
1000 if (!display_wayland->orphan_dialogs)
1001 return;
1002
1003 for (l = display_wayland->orphan_dialogs; l; l = l->next)
1004 {
1005 GdkWindow *w = l->data;
1006 GdkWindowImplWayland *impl;
1007
1008 if (!GDK_IS_WINDOW_IMPL_WAYLAND(w->impl))
1009 continue;
1010
1011 impl = GDK_WINDOW_IMPL_WAYLAND (w->impl);
1012 if (w == window)
1013 continue;
1014 if (impl->hint != GDK_WINDOW_TYPE_HINT_DIALOG)
1015 continue;
1016 if (impl->transient_for)
1017 continue;
1018
1019 /* Update the parent relationship only for dialogs without transients */
1020 gdk_wayland_window_sync_parent (w, window);
1021 }
1022}
1023
1024static void
1025gdk_wayland_window_sync_title (GdkWindow *window)
1026{
1027 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1028
1029 if (!impl->display_server.xdg_surface)
1030 return;
1031
1032 if (!impl->title)
1033 return;
1034
1035 xdg_surface_set_title (impl->display_server.xdg_surface, impl->title);
1036}
1037
1038static void
1039gdk_wayland_window_sync_margin (GdkWindow *window)
1040{
1041 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1042 gint x, y, width, height;
1043
1044 if (!impl->display_server.xdg_surface)
1045 return;
1046
1047 x = impl->margin_left;
1048 y = impl->margin_top;
1049 width = window->width - (impl->margin_left + impl->margin_right);
1050 height = window->height - (impl->margin_top + impl->margin_bottom);
1051
1052 xdg_surface_set_window_geometry (impl->display_server.xdg_surface, x, y, width, height);
1053}
1054
1055static struct wl_region *
1056wl_region_from_cairo_region (GdkWaylandDisplay *display,
1057 cairo_region_t *region)
1058{
1059 struct wl_region *wl_region;
1060 int i, n_rects;
1061
1062 wl_region = wl_compositor_create_region (display->compositor);
1063 if (wl_region == NULL)
1064 return NULL;
1065
1066 n_rects = cairo_region_num_rectangles (region);
1067 for (i = 0; i < n_rects; i++)
1068 {
1069 cairo_rectangle_int_t rect;
1070 cairo_region_get_rectangle (region, i, &rect);
1071 wl_region_add (wl_region, rect.x, rect.y, rect.width, rect.height);
1072 }
1073
1074 return wl_region;
1075}
1076
1077static void
1078gdk_wayland_window_sync_opaque_region (GdkWindow *window)
1079{
1080 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1081 struct wl_region *wl_region = NULL;
1082
1083 if (!impl->display_server.wl_surface)
1084 return;
1085
1086 if (impl->opaque_region != NULL)
1087 wl_region = wl_region_from_cairo_region (GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)),
1088 impl->opaque_region);
1089
1090 wl_surface_set_opaque_region (impl->display_server.wl_surface, wl_region);
1091
1092 if (wl_region != NULL)
1093 wl_region_destroy (wl_region);
1094}
1095
1096static void
1097gdk_wayland_window_sync_input_region (GdkWindow *window)
1098{
1099 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1100 struct wl_region *wl_region = NULL;
1101
1102 if (!impl->display_server.wl_surface)
1103 return;
1104
1105 if (impl->input_region != NULL)
1106 wl_region = wl_region_from_cairo_region (GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)),
1107 impl->input_region);
1108
1109 wl_surface_set_input_region (impl->display_server.wl_surface, wl_region);
1110
1111 if (wl_region != NULL)
1112 wl_region_destroy (wl_region);
1113}
1114
1115static void
1116surface_enter (void *data,
1117 struct wl_surface *wl_surface,
1118 struct wl_output *output)
1119{
1120 GdkWindow *window = GDK_WINDOW (data);
1121 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1122
1123 GDK_NOTE (EVENTS,
1124 g_message ("surface enter, window %p output %p", window, output));
1125
1126 impl->display_server.outputs = g_slist_prepend (impl->display_server.outputs, output);
1127
1128 window_update_scale (window);
1129}
1130
1131static void
1132surface_leave (void *data,
1133 struct wl_surface *wl_surface,
1134 struct wl_output *output)
1135{
1136 GdkWindow *window = GDK_WINDOW (data);
1137 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1138
1139 GDK_NOTE (EVENTS,
1140 g_message ("surface leave, window %p output %p", window, output));
1141
1142 impl->display_server.outputs = g_slist_remove (impl->display_server.outputs, output);
1143
1144 window_update_scale (window);
1145}
1146
1147static const struct wl_surface_listener surface_listener = {
1148 surface_enter,
1149 surface_leave
1150};
1151
1152static void
1153on_parent_surface_committed (GdkWindowImplWayland *parent_impl,
1154 GdkWindow *window)
1155{
1156 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1157
1158 g_signal_handler_disconnect (parent_impl,
1159 impl->parent_surface_committed_handler);
1160 impl->parent_surface_committed_handler = 0;
1161
1162 wl_subsurface_set_desync (impl->display_server.wl_subsurface);
1163}
1164
1165static void
1166gdk_wayland_window_create_subsurface (GdkWindow *window)
1167{
1168 GdkWindowImplWayland *impl, *parent_impl = NULL;
1169 GdkWaylandDisplay *display_wayland;
1170
1171 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1172
1173 if (!impl->display_server.wl_surface)
1174 return; /* Bail out, surface and subsurface will be created later when shown */
1175
1176 if (impl->display_server.wl_subsurface)
1177 return;
1178
1179 if (impl->transient_for)
1180 parent_impl = GDK_WINDOW_IMPL_WAYLAND (impl->transient_for->impl);
1181
1182 if (parent_impl)
1183 {
1184 display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1185 impl->display_server.wl_subsurface =
1186 wl_subcompositor_get_subsurface (display_wayland->subcompositor,
1187 impl->display_server.wl_surface, parent_impl->display_server.wl_surface);
1188 wl_subsurface_set_position (impl->display_server.wl_subsurface, window->x, window->y);
1189
1190 /* In order to synchronize the initial position with the initial frame
1191 * content, wait with making the subsurface desynchronized until after
1192 * the parent was committed.
1193 */
1194 impl->parent_surface_committed_handler =
1195 g_signal_connect_object (parent_impl, "committed",
1196 G_CALLBACK (on_parent_surface_committed),
1197 window, 0);
1198 gdk_window_request_transient_parent_commit (window);
1199 }
1200}
1201
1202static void
1203gdk_wayland_window_create_surface (GdkWindow *window)
1204{
1205 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1206 GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1207
1208 impl->display_server.wl_surface = wl_compositor_create_surface (display_wayland->compositor);
1209 wl_surface_add_listener (impl->display_server.wl_surface, &surface_listener, window);
1210
1211 gdk_wayland_window_sync_opaque_region (window);
1212 gdk_wayland_window_sync_input_region (window);
1213}
1214
1215static void
1216xdg_surface_configure (void *data,
1217 struct xdg_surface *xdg_surface,
1218 int32_t width,
1219 int32_t height,
1220 struct wl_array *states,
1221 uint32_t serial)
1222{
1223 GdkWindow *window = GDK_WINDOW (data);
1224 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1225 GdkWindowState new_state = 0;
1226 gboolean maximized_or_fullscreen;
1227 uint32_t *p;
1228
1229 wl_array_for_each (p, states)
1230 {
1231 uint32_t state = *p;
1232 switch (state)
1233 {
1234 case XDG_SURFACE_STATE_FULLSCREEN:
1235 new_state |= GDK_WINDOW_STATE_FULLSCREEN;
1236 break;
1237 case XDG_SURFACE_STATE_MAXIMIZED:
1238 new_state |= GDK_WINDOW_STATE_MAXIMIZED;
1239 break;
1240 case XDG_SURFACE_STATE_ACTIVATED:
1241 new_state |= GDK_WINDOW_STATE_FOCUSED;
1242 break;
1243 case XDG_SURFACE_STATE_RESIZING:
1244 break;
1245 /* GNOME additional states to xdg-shell */
1246 case XDG_SURFACE_STATE_GNOME_TILED:
1247 new_state |= GDK_WINDOW_STATE_TILED;
1248 break;
1249 default:
1250 /* Unknown state */
1251 break;
1252 }
1253 }
1254
1255 maximized_or_fullscreen =
1256 new_state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN);
1257
1258 /* According to xdg_shell, an xdg_surface.configure with size 0x0
1259 * should be interpreted as that it is up to the client to set a
1260 * size.
1261 *
1262 * When transitioning from maximize or fullscreen state, this means
1263 * the client should configure its size back to what it was before
1264 * being maximize or fullscreen.
1265 */
1266 if (width == 0 && height == 0 && !maximized_or_fullscreen)
1267 {
1268 width = impl->saved_width;
1269 height = impl->saved_height;
1270 }
1271
1272 if (width > 0 && height > 0)
1273 {
1274 GdkWindowHints geometry_mask = impl->geometry_mask;
1275
1276 /* Ignore size increments for maximized/fullscreen windows */
1277 if (maximized_or_fullscreen)
1278 geometry_mask &= ~GDK_HINT_RESIZE_INC;
1279
1280 gdk_window_constrain_size (&impl->geometry_hints,
1281 geometry_mask,
1282 width + impl->margin_left + impl->margin_right,
1283 height + impl->margin_top + impl->margin_bottom,
1284 &width,
1285 &height);
1286
1287 /* Save size for next time we get 0x0 */
1288 _gdk_wayland_window_save_size (window);
1289
1290 gdk_wayland_window_configure (window, width, height, impl->scale);
1291 }
1292
1293 GDK_NOTE (EVENTS,
1294 g_message ("configure, window %p %dx%d,%s%s%s%s",
1295 window, width, height,
1296 (new_state & GDK_WINDOW_STATE_FULLSCREEN) ? " fullscreen" : "",
1297 (new_state & GDK_WINDOW_STATE_MAXIMIZED) ? " maximized" : "",
1298 (new_state & GDK_WINDOW_STATE_FOCUSED) ? " focused" : "",
1299 (new_state & GDK_WINDOW_STATE_TILED) ? " tiled" : ""));
1300
1301 _gdk_set_window_state (window, new_state);
1302 gdk_wayland_window_sync_margin (window);
1303 xdg_surface_ack_configure (xdg_surface, serial);
1304 if (impl->hint != GDK_WINDOW_TYPE_HINT_DIALOG &&
1305 new_state & GDK_WINDOW_STATE_FOCUSED)
1306 gdk_wayland_window_update_dialogs (window);
1307}
1308
1309static void
1310xdg_surface_close (void *data,
1311 struct xdg_surface *xdg_surface)
1312{
1313 GdkWindow *window = GDK_WINDOW (data);
1314 GdkDisplay *display;
1315 GdkEvent *event;
1316
1317 GDK_NOTE (EVENTS,
1318 g_message ("close %p", window));
1319
1320 event = gdk_event_new (GDK_DELETE);
1321 event->any.window = g_object_ref (window);
1322 event->any.send_event = TRUE;
1323
1324 display = gdk_window_get_display (window);
1325 _gdk_wayland_display_deliver_event (display, event);
1326}
1327
1328static const struct xdg_surface_listener xdg_surface_listener = {
1329 xdg_surface_configure,
1330 xdg_surface_close,
1331};
1332
1333static void
1334gdk_wayland_window_create_xdg_surface (GdkWindow *window)
1335{
1336 GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1337 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1338 const gchar *app_id;
1339 GdkScreen *screen = gdk_window_get_screen (window);
1340 struct wl_output *fullscreen_output = NULL;
1341 if (impl->initial_fullscreen_monitor >= 0 &&
1342 impl->initial_fullscreen_monitor < gdk_screen_get_n_monitors (screen))
1343 fullscreen_output = _gdk_wayland_screen_get_wl_output (screen, impl->initial_fullscreen_monitor);
1344
1345 impl->display_server.xdg_surface = xdg_shell_get_xdg_surface (display_wayland->xdg_shell, impl->display_server.wl_surface);
1346 xdg_surface_add_listener (impl->display_server.xdg_surface, &xdg_surface_listener, window);
1347
1348 gdk_wayland_window_sync_parent (window, NULL);
1349 gdk_wayland_window_sync_title (window);
1350 gdk_wayland_window_sync_margin (window);
1351
1352 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1353 xdg_surface_set_maximized (impl->display_server.xdg_surface);
1354 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1355 xdg_surface_set_fullscreen (impl->display_server.xdg_surface, fullscreen_output);
1356
1357 app_id = g_get_prgname ();
1358 if (app_id == NULL)
1359 app_id = gdk_get_program_class ();
1360
1361 xdg_surface_set_app_id (impl->display_server.xdg_surface, app_id);
1362
1363 maybe_set_gtk_surface_dbus_properties (window);
1364 maybe_set_gtk_surface_modal (window);
1365
1366 if (impl->hint == GDK_WINDOW_TYPE_HINT_DIALOG)
1367 _gdk_wayland_screen_add_orphan_dialog (window);
1368}
1369
1370static void
1371xdg_popup_done (void *data,
1372 struct xdg_popup *xdg_popup)
1373{
1374 GdkWindow *window = GDK_WINDOW (data);
1375
1376 GDK_NOTE (EVENTS,
1377 g_message ("done %p", window));
1378
1379 gdk_window_hide (window);
1380}
1381
1382static const struct xdg_popup_listener xdg_popup_listener = {
1383 xdg_popup_done,
1384};
1385
1386/**
1387 * gdk_wayland_window_get_fake_root_coords:
1388 * @window: A #GdkWindow
1389 * @x_out: (out): The X offset of this window
1390 * @y_out: (out): The Y offset of this window
1391 *
1392 * Wayland does not have a global coordinate space shared between
1393 * surfaces. In fact, for regular toplevels, we have no idea where
1394 * our surfaces are positioned, relatively.
1395 *
1396 * However, there are some cases like popups and subsurfaces where
1397 * we do have some amount of control over the placement of our
1398 * window, and we can semi-accurately control the x/y position of
1399 * these windows, if they are relative to another surface.
1400 *
1401 * GTK+ loves to position "relative" popups like menus in root
1402 * window coordinates, since it was built for display servers that
1403 * have queryable absolute coordinate spaces. In these cases, GTK+
1404 * might ask for the root coordinates of a widget window, add a
1405 * few values, and then call gdk_window_move() with that absolute
1406 * value.
1407 *
1408 * In Wayland, we have to "reverse-engineer" this use, and figure
1409 * out the root coordinates from the relative position, and the
1410 * relative position from the root coordinates.
1411 *
1412 * We invent a coordinate space called the "fake root coordinate"
1413 * space in which a toplevel is always at 0,0, and all popups are
1414 * relative to that space.
1415 *
1416 * gdk_wayland_window_get_fake_root_coords() gives you the
1417 * position of a #GdkWindow in "fake root" coordinates.
1418 */
1419static void
1420gdk_wayland_window_get_fake_root_coords (GdkWindow *window,
1421 gint *x_out,
1422 gint *y_out)
1423{
1424 gint x_offset = 0, y_offset = 0;
1425
1426 while (window)
1427 {
1428 GdkWindowImplWayland *impl;
1429
1430 x_offset += window->x;
1431 y_offset += window->y;
1432
1433 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1434 window = impl->transient_for;
1435 }
1436
1437 *x_out = x_offset;
1438 *y_out = y_offset;
1439}
1440
1441static void
1442gdk_wayland_window_create_xdg_popup (GdkWindow *window,
1443 GdkWindow *parent,
1444 struct wl_seat *seat)
1445{
1446 GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1447 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1448 GdkWindowImplWayland *parent_impl = GDK_WINDOW_IMPL_WAYLAND (parent->impl);
1449 GdkSeat *gdk_seat;
1450 guint32 serial;
1451 int x, y;
1452 int parent_x, parent_y;
1453
1454 if (!impl->display_server.wl_surface)
1455 return;
1456
1457 if (!parent_impl->display_server.wl_surface)
1458 return;
1459
1460 gdk_seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
1461 gdk_wayland_window_get_fake_root_coords (parent, &parent_x, &parent_y);
1462
1463 x = window->x - parent_x;
1464 y = window->y - parent_y;
1465 serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_seat, NULL);
1466
1467 impl->display_server.xdg_popup = xdg_shell_get_xdg_popup (display->xdg_shell,
1468 impl->display_server.wl_surface,
1469 parent_impl->display_server.wl_surface,
1470 seat, serial,
1471 x, y);
1472
1473 xdg_popup_add_listener (impl->display_server.xdg_popup, &xdg_popup_listener, window);
1474}
1475
1476static struct wl_seat *
1477find_grab_input_seat (GdkWindow *window, GdkWindow *transient_for)
1478{
1479 GdkWindow *attached_grab_window;
1480 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1481 GdkWindowImplWayland *tmp_impl;
1482
1483 /* Use the device that was used for the grab as the device for
1484 * the popup window setup - so this relies on GTK+ taking the
1485 * grab before showing the popup window.
1486 */
1487 if (impl->grab_input_seat)
1488 return gdk_wayland_seat_get_wl_seat (impl->grab_input_seat);
1489
1490 /* HACK: GtkMenu grabs a special window known as the "grab transfer window"
1491 * and then transfers the grab over to the correct window later. Look for
1492 * this window when taking the grab to know it's correct.
1493 *
1494 * See: associate_menu_grab_transfer_window in gtkmenu.c
1495 */
1496 attached_grab_window = g_object_get_data (G_OBJECT (window), "gdk-attached-grab-window");
1497 if (attached_grab_window)
1498 {
1499 tmp_impl = GDK_WINDOW_IMPL_WAYLAND (attached_grab_window->impl);
1500 if (tmp_impl->grab_input_seat)
1501 return gdk_wayland_seat_get_wl_seat (tmp_impl->grab_input_seat);
1502 }
1503
1504 while (transient_for)
1505 {
1506 tmp_impl = GDK_WINDOW_IMPL_WAYLAND (transient_for->impl);
1507
1508 if (tmp_impl->grab_input_seat)
1509 return gdk_wayland_seat_get_wl_seat (tmp_impl->grab_input_seat);
1510
1511 transient_for = tmp_impl->transient_for;
1512 }
1513
1514 return NULL;
1515}
1516
1517static struct wl_seat *
1518find_default_input_seat (GdkWindow *window)
1519{
1520 GdkDisplay *display;
1521 GdkSeat *seat;
1522
1523 display = gdk_window_get_display (window);
1524 seat = gdk_display_get_default_seat (display);
1525
1526 return gdk_wayland_seat_get_wl_seat (seat);
1527}
1528
1529static gboolean
1530should_be_mapped (GdkWindow *window)
1531{
1532 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1533
1534 /* Don't map crazy temp that GTK+ uses for internal X11 shenanigans. */
1535 if (window->window_type == GDK_WINDOW_TEMP && window->x < 0 && window->y < 0)
1536 return FALSE;
1537
1538 if (impl->hint == GDK_WINDOW_TYPE_HINT_DND)
1539 return FALSE;
1540
1541 return TRUE;
1542}
1543
1544static gboolean
1545should_map_as_popup (GdkWindow *window)
1546{
1547 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1548
1549 /* Ideally, popup would be temp windows with a parent and grab */
1550 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
1551 {
1552 /* If a temp window has a parent and a grab, we can use a popup */
1553 if (impl->transient_for)
1554 {
1555 if (impl->grab_input_seat)
1556 return TRUE;
1557 }
1558 else
1559 g_message ("Window %p is a temporary window without parent, "
1560 "application will not be able to position it on screen.",
1561 window);
1562 }
1563
1564 /* Yet we need to keep the window type hint tests for compatibility */
1565 switch (impl->hint)
1566 {
1567 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
1568 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
1569 case GDK_WINDOW_TYPE_HINT_COMBO:
1570 return TRUE;
1571
1572 case GDK_WINDOW_TYPE_HINT_UTILITY:
1573 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_TEMP)
1574 return TRUE;
1575 break;
1576
1577 default:
1578 break;
1579 }
1580
1581 return FALSE;
1582}
1583
1584static gboolean
1585should_map_as_subsurface (GdkWindow *window)
1586{
1587 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1588
1589 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_SUBSURFACE)
1590 return TRUE;
1591
1592 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_TEMP)
1593 return FALSE;
1594
1595 /* if we want a popup, we do not want a subsurface */
1596 if (should_map_as_popup (window))
1597 return FALSE;
1598
1599 if (impl->transient_for)
1600 {
1601 GdkWindowImplWayland *impl_parent;
1602
1603 impl_parent = GDK_WINDOW_IMPL_WAYLAND (impl->transient_for->impl);
1604 /* subsurface require that the parent is mapped */
1605 if (impl_parent->mapped)
1606 return TRUE;
1607 else
1608 g_warning ("Couldn't map window %p as susburface because its parent is not mapped.",
1609 window);
1610
1611 }
1612
1613 return FALSE;
1614}
1615
1616/* Get the window that can be used as a parent for a popup, i.e. a xdg_surface
1617 * or xdg_popup. If the window is not, traverse up the transiency parents until
1618 * we find one.
1619 */
1620static GdkWindow *
1621get_popup_parent (GdkWindow *window)
1622{
1623 while (window)
1624 {
1625 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1626
1627 if (impl->display_server.xdg_popup || impl->display_server.xdg_surface)
1628 return window;
1629
1630 window = impl->transient_for;
1631 }
1632
1633 return NULL;
1634}
1635
1636static void
1637gdk_wayland_window_map (GdkWindow *window)
1638{
1639 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1640 GdkWindow *transient_for = NULL;
1641
1642 if (!should_be_mapped (window))
1643 return;
1644
1645 if (impl->mapped || impl->use_custom_surface)
1646 return;
1647
1648 if (should_map_as_subsurface (window))
1649 {
1650 if (impl->transient_for)
1651 gdk_wayland_window_create_subsurface (window);
1652 else
1653 g_warning ("Couldn't map window %p as susburface yet because it doesn't have a parent",
1654 window);
1655 }
1656 else if (should_map_as_popup (window))
1657 {
1658 gboolean create_fallback = FALSE;
1659 struct wl_seat *grab_input_seat;
1660
1661 /* Popup menus can appear without a transient parent, which means they
1662 * cannot be positioned properly on Wayland. This attempts to guess the
1663 * surface they should be positioned with by finding the surface beneath
1664 * the device that created the grab for the popup window.
1665 */
1666 if (!impl->transient_for && impl->hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU)
1667 {
1668 GdkDevice *grab_device = NULL;
1669
1670 /* The popup menu window is not the grabbed window. This may mean
1671 * that a "transfer window" (see gtkmenu.c) is used, and we need
1672 * to find that window to get the grab device. If so is the case
1673 * the "transfer window" can be retrieved via the
1674 * "gdk-attached-grab-window" associated data field.
1675 */
1676 if (!impl->grab_input_seat)
1677 {
1678 GdkWindow *attached_grab_window =
1679 g_object_get_data (G_OBJECT (window),
1680 "gdk-attached-grab-window");
1681 if (attached_grab_window)
1682 {
1683 GdkWindowImplWayland *attached_impl =
1684 GDK_WINDOW_IMPL_WAYLAND (attached_grab_window->impl);
1685 grab_device = gdk_seat_get_pointer (attached_impl->grab_input_seat);
1686 transient_for =
1687 gdk_device_get_window_at_position (grab_device,
1688 NULL, NULL);
1689 }
1690 }
1691 else
1692 {
1693 grab_device = gdk_seat_get_pointer (impl->grab_input_seat);
1694 transient_for =
1695 gdk_device_get_window_at_position (grab_device, NULL, NULL);
1696 }
1697
1698 if (transient_for)
1699 transient_for = get_popup_parent (gdk_window_get_effective_toplevel (transient_for));
1700
1701 /* If the position was not explicitly set, start the popup at the
1702 * position of the device that holds the grab.
1703 */
1704 if (!impl->position_set && grab_device)
1705 gdk_window_get_device_position (transient_for, grab_device,
1706 &window->x, &window->y, NULL);
1707 }
1708 else
1709 transient_for = get_popup_parent (impl->transient_for);
1710
1711 if (!transient_for)
1712 {
1713 g_warning ("Couldn't map as window %p as popup because it doesn't have a parent",
1714 window);
1715
1716 create_fallback = TRUE;
1717 }
1718 else
1719 {
1720 grab_input_seat = find_grab_input_seat (window, transient_for);
1721
1722 if (!grab_input_seat)
1723 {
1724 g_warning ("No grabbed seat found, using the default one in "
1725 "order to map popup window %p. You may find oddities "
1726 "ahead, gdk_seat_grab() should be used to "
1727 "simultaneously grab input and show this popup",
1728 window);
1729 grab_input_seat = find_default_input_seat (window);
1730 }
1731 }
1732
1733 if (!create_fallback)
1734 {
1735 gdk_wayland_window_create_xdg_popup (window,
1736 transient_for,
1737 grab_input_seat);
1738 }
1739 else
1740 {
1741 gdk_wayland_window_create_xdg_surface (window);
1742 }
1743 }
1744 else
1745 {
1746 gdk_wayland_window_create_xdg_surface (window);
1747 }
1748
1749 impl->mapped = TRUE;
1750}
1751
1752static void
1753gdk_wayland_window_show (GdkWindow *window,
1754 gboolean already_mapped)
1755{
1756 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1757
1758 if (!impl->display_server.wl_surface)
1759 gdk_wayland_window_create_surface (window);
1760
1761 gdk_wayland_window_map (window);
1762
1763 _gdk_make_event (window, GDK_MAP, NULL, FALSE);
1764
1765 if (impl->staging_cairo_surface &&
1766 _gdk_wayland_is_shm_surface (impl->staging_cairo_surface))
1767 gdk_wayland_window_attach_image (window);
1768}
1769
1770static void
1771unmap_subsurface (GdkWindow *window)
1772{
1773 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1774 GdkWindowImplWayland *parent_impl;
1775
1776 g_return_if_fail (impl->display_server.wl_subsurface);
1777 g_return_if_fail (impl->transient_for);
1778
1779 parent_impl = GDK_WINDOW_IMPL_WAYLAND (impl->transient_for->impl);
1780 wl_subsurface_destroy (impl->display_server.wl_subsurface);
1781 if (impl->parent_surface_committed_handler)
1782 {
1783 g_signal_handler_disconnect (parent_impl,
1784 impl->parent_surface_committed_handler);
1785 impl->parent_surface_committed_handler = 0;
1786 }
1787 impl->display_server.wl_subsurface = NULL;
1788}
1789
1790static void
1791gdk_wayland_window_hide_surface (GdkWindow *window)
1792{
1793 GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1794 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1795
1796 if (impl->display_server.wl_surface)
1797 {
1798 if (impl->dummy_egl_surface)
1799 {
1800 eglDestroySurface (display_wayland->egl_display, impl->dummy_egl_surface);
1801 impl->dummy_egl_surface = NULL;
1802 }
1803
1804 if (impl->display_server.dummy_egl_window)
1805 {
1806 wl_egl_window_destroy (impl->display_server.dummy_egl_window);
1807 impl->display_server.dummy_egl_window = NULL;
1808 }
1809
1810 if (impl->egl_surface)
1811 {
1812 eglDestroySurface (display_wayland->egl_display, impl->egl_surface);
1813 impl->egl_surface = NULL;
1814 }
1815
1816 if (impl->display_server.egl_window)
1817 {
1818 wl_egl_window_destroy (impl->display_server.egl_window);
1819 impl->display_server.egl_window = NULL;
1820 }
1821
1822 if (impl->display_server.xdg_surface)
1823 {
1824 xdg_surface_destroy (impl->display_server.xdg_surface);
1825 impl->display_server.xdg_surface = NULL;
1826 }
1827 else if (impl->display_server.xdg_popup)
1828 {
1829 xdg_popup_destroy (impl->display_server.xdg_popup);
1830 impl->display_server.xdg_popup = NULL;
1831 }
1832
1833 if (impl->display_server.wl_subsurface)
1834 unmap_subsurface (window);
1835
1836 if (impl->awaiting_frame)
1837 {
1838 GdkFrameClock *frame_clock;
1839
1840 impl->awaiting_frame = FALSE;
1841 frame_clock = gdk_window_get_frame_clock (window);
1842 if (frame_clock)
1843 _gdk_frame_clock_thaw (frame_clock);
1844 }
1845
1846 if (impl->display_server.gtk_surface)
1847 {
1848 gtk_surface1_destroy (impl->display_server.gtk_surface);
1849 impl->display_server.gtk_surface = NULL;
1850 }
1851
1852 wl_surface_destroy (impl->display_server.wl_surface);
1853 impl->display_server.wl_surface = NULL;
1854
1855 g_slist_free (impl->display_server.outputs);
1856 impl->display_server.outputs = NULL;
1857
1858 if (impl->hint == GDK_WINDOW_TYPE_HINT_DIALOG && !impl->transient_for)
1859 display_wayland->orphan_dialogs =
1860 g_list_remove (display_wayland->orphan_dialogs, window);
1861 }
1862
1863 _gdk_wayland_window_clear_saved_size (window);
1864 impl->pending_commit = FALSE;
1865 impl->mapped = FALSE;
1866}
1867
1868static void
1869gdk_wayland_window_hide (GdkWindow *window)
1870{
1871 gdk_wayland_window_hide_surface (window);
1872 _gdk_window_clear_update_area (window);
1873}
1874
1875static void
1876gdk_window_wayland_withdraw (GdkWindow *window)
1877{
1878 if (!window->destroyed)
1879 {
1880 if (GDK_WINDOW_IS_MAPPED (window))
1881 gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_WITHDRAWN);
1882
1883 g_assert (!GDK_WINDOW_IS_MAPPED (window));
1884
1885 gdk_wayland_window_hide_surface (window);
1886 }
1887}
1888
1889static void
1890gdk_window_wayland_set_events (GdkWindow *window,
1891 GdkEventMask event_mask)
1892{
1893 GDK_WINDOW (window)->event_mask = event_mask;
1894}
1895
1896static GdkEventMask
1897gdk_window_wayland_get_events (GdkWindow *window)
1898{
1899 if (GDK_WINDOW_DESTROYED (window))
1900 return 0;
1901 else
1902 return GDK_WINDOW (window)->event_mask;
1903}
1904
1905static void
1906gdk_window_wayland_raise (GdkWindow *window)
1907{
1908}
1909
1910static void
1911gdk_window_wayland_lower (GdkWindow *window)
1912{
1913}
1914
1915static void
1916gdk_window_wayland_restack_under (GdkWindow *window,
1917 GList *native_siblings)
1918{
1919}
1920
1921static void
1922gdk_window_wayland_restack_toplevel (GdkWindow *window,
1923 GdkWindow *sibling,
1924 gboolean above)
1925{
1926}
1927
1928static void
1929gdk_window_request_transient_parent_commit (GdkWindow *window)
1930{
1931 GdkWindowImplWayland *window_impl, *impl;
1932 GdkFrameClock *frame_clock;
1933
1934 window_impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1935
1936 if (!window_impl->transient_for)
1937 return;
1938
1939 impl = GDK_WINDOW_IMPL_WAYLAND (window_impl->transient_for->impl);
1940
1941 if (!impl->display_server.wl_surface || impl->pending_commit)
1942 return;
1943
1944 frame_clock = gdk_window_get_frame_clock (window_impl->transient_for);
1945
1946 if (!frame_clock)
1947 return;
1948
1949 impl->pending_commit = TRUE;
1950 gdk_frame_clock_request_phase (frame_clock,
1951 GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
1952}
1953
1954static void
1955gdk_window_wayland_move_resize (GdkWindow *window,
1956 gboolean with_move,
1957 gint x,
1958 gint y,
1959 gint width,
1960 gint height)
1961{
1962 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1963
1964 if (with_move)
1965 {
1966 /* Each toplevel has in its own "root" coordinate system */
1967 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_TOPLEVEL)
1968 {
1969 window->x = x;
1970 window->y = y;
1971 impl->position_set = 1;
1972
1973 if (impl->display_server.wl_subsurface)
1974 {
1975 wl_subsurface_set_position (impl->display_server.wl_subsurface, x, y);
1976 gdk_window_request_transient_parent_commit (window);
1977 }
1978 }
1979 }
1980
1981 /* If this function is called with width and height = -1 then that means
1982 * just move the window - don't update its size
1983 */
1984 if (width > 0 && height > 0)
1985 gdk_wayland_window_maybe_configure (window, width, height, impl->scale);
1986}
1987
1988static void
1989gdk_window_wayland_set_background (GdkWindow *window,
1990 cairo_pattern_t *pattern)
1991{
1992}
1993
1994static gboolean
1995gdk_window_wayland_reparent (GdkWindow *window,
1996 GdkWindow *new_parent,
1997 gint x,
1998 gint y)
1999{
2000 return FALSE;
2001}
2002
2003static void
2004gdk_window_wayland_set_device_cursor (GdkWindow *window,
2005 GdkDevice *device,
2006 GdkCursor *cursor)
2007{
2008 g_return_if_fail (GDK_IS_WINDOW (window));
2009 g_return_if_fail (GDK_IS_DEVICE (device));
2010
2011 if (!GDK_WINDOW_DESTROYED (window))
2012 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
2013}
2014
2015static void
2016gdk_window_wayland_get_geometry (GdkWindow *window,
2017 gint *x,
2018 gint *y,
2019 gint *width,
2020 gint *height)
2021{
2022 if (!GDK_WINDOW_DESTROYED (window))
2023 {
2024 if (x)
2025 *x = window->x;
2026 if (y)
2027 *y = window->y;
2028 if (width)
2029 *width = window->width;
2030 if (height)
2031 *height = window->height;
2032 }
2033}
2034
2035static void
2036gdk_window_wayland_get_root_coords (GdkWindow *window,
2037 gint x,
2038 gint y,
2039 gint *root_x,
2040 gint *root_y)
2041{
2042 gint x_offset, y_offset;
2043
2044 gdk_wayland_window_get_fake_root_coords (window, &x_offset, &y_offset);
2045
2046 if (root_x)
2047 *root_x = x_offset + x;
2048
2049 if (root_y)
2050 *root_y = y_offset + y;
2051}
2052
2053static gboolean
2054gdk_window_wayland_get_device_state (GdkWindow *window,
2055 GdkDevice *device,
2056 gdouble *x,
2057 gdouble *y,
2058 GdkModifierType *mask)
2059{
2060 gboolean return_val;
2061
2062 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
2063
2064 return_val = TRUE;
2065
2066 if (!GDK_WINDOW_DESTROYED (window))
2067 {
2068 GdkWindow *child;
2069
2070 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
2071 NULL, &child,
2072 NULL, NULL,
2073 x, y, mask);
2074 return_val = (child != NULL);
2075 }
2076
2077 return return_val;
2078}
2079
2080static void
2081gdk_window_wayland_shape_combine_region (GdkWindow *window,
2082 const cairo_region_t *shape_region,
2083 gint offset_x,
2084 gint offset_y)
2085{
2086}
2087
2088static void
2089gdk_window_wayland_input_shape_combine_region (GdkWindow *window,
2090 const cairo_region_t *shape_region,
2091 gint offset_x,
2092 gint offset_y)
2093{
2094 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2095
2096 if (GDK_WINDOW_DESTROYED (window))
2097 return;
2098
2099 g_clear_pointer (&impl->input_region, cairo_region_destroy);
2100
2101 if (shape_region)
2102 {
2103 impl->input_region = cairo_region_copy (shape_region);
2104 cairo_region_translate (impl->input_region, offset_x, offset_y);
2105 }
2106
2107 gdk_wayland_window_sync_input_region (window);
2108}
2109
2110static void
2111gdk_wayland_window_destroy (GdkWindow *window,
2112 gboolean recursing,
2113 gboolean foreign_destroy)
2114{
2115 g_return_if_fail (GDK_IS_WINDOW (window));
2116
2117 /* Wayland windows can't be externally destroyed; we may possibly
2118 * eventually want to use this path at display close-down
2119 */
2120 g_return_if_fail (!foreign_destroy);
2121
2122 gdk_wayland_window_hide_surface (window);
2123 drop_cairo_surfaces (window);
2124}
2125
2126static void
2127gdk_window_wayland_destroy_foreign (GdkWindow *window)
2128{
2129}
2130
2131static cairo_region_t *
2132gdk_wayland_window_get_shape (GdkWindow *window)
2133{
2134 return NULL;
2135}
2136
2137static cairo_region_t *
2138gdk_wayland_window_get_input_shape (GdkWindow *window)
2139{
2140 return NULL;
2141}
2142
2143static void
2144gdk_wayland_window_focus (GdkWindow *window,
2145 guint32 timestamp)
2146{
2147 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2148
2149 if (!impl->display_server.gtk_surface)
2150 return;
2151
2152 /* We didn't have an event to fetch a time from, meaning we have nothing valid
2153 * to send. This should rather be translated to a 'needs-attention' request or
2154 * something.
2155 */
2156 if (timestamp == GDK_CURRENT_TIME)
2157 return;
2158
2159 gtk_surface1_present (impl->display_server.gtk_surface, timestamp);
2160}
2161
2162static void
2163gdk_wayland_window_set_type_hint (GdkWindow *window,
2164 GdkWindowTypeHint hint)
2165{
2166 GdkWindowImplWayland *impl;
2167
2168 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2169
2170 if (GDK_WINDOW_DESTROYED (window))
2171 return;
2172
2173 impl->hint = hint;
2174}
2175
2176static GdkWindowTypeHint
2177gdk_wayland_window_get_type_hint (GdkWindow *window)
2178{
2179 GdkWindowImplWayland *impl;
2180
2181 if (GDK_WINDOW_DESTROYED (window))
2182 return GDK_WINDOW_TYPE_HINT_NORMAL;
2183
2184 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2185
2186 return impl->hint;
2187}
2188
2189static void
2190gdk_wayland_window_init_gtk_surface (GdkWindow *window)
2191{
2192 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2193 GdkWaylandDisplay *display =
2194 GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
2195
2196 if (impl->display_server.gtk_surface != NULL)
2197 return;
2198 if (impl->display_server.xdg_surface == NULL)
2199 return;
2200 if (display->gtk_shell == NULL)
2201 return;
2202
2203 impl->display_server.gtk_surface =
2204 gtk_shell1_get_gtk_surface (display->gtk_shell,
2205 impl->display_server.wl_surface);
2206}
2207
2208static void
2209maybe_set_gtk_surface_modal (GdkWindow *window)
2210{
2211 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2212
2213 gdk_wayland_window_init_gtk_surface (window);
2214 if (impl->display_server.gtk_surface == NULL)
2215 return;
2216
2217 if (window->modal_hint)
2218 gtk_surface1_set_modal (impl->display_server.gtk_surface);
2219 else
2220 gtk_surface1_unset_modal (impl->display_server.gtk_surface);
2221
2222}
2223
2224static void
2225gdk_wayland_window_set_modal_hint (GdkWindow *window,
2226 gboolean modal)
2227{
2228 window->modal_hint = modal;
2229 maybe_set_gtk_surface_modal (window);
2230}
2231
2232static void
2233gdk_wayland_window_set_skip_taskbar_hint (GdkWindow *window,
2234 gboolean skips_taskbar)
2235{
2236}
2237
2238static void
2239gdk_wayland_window_set_skip_pager_hint (GdkWindow *window,
2240 gboolean skips_pager)
2241{
2242}
2243
2244static void
2245gdk_wayland_window_set_urgency_hint (GdkWindow *window,
2246 gboolean urgent)
2247{
2248}
2249
2250static void
2251gdk_wayland_window_set_geometry_hints (GdkWindow *window,
2252 const GdkGeometry *geometry,
2253 GdkWindowHints geom_mask)
2254{
2255 GdkWindowImplWayland *impl;
2256
2257 if (GDK_WINDOW_DESTROYED (window) ||
2258 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2259 return;
2260
2261 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2262
2263 impl->geometry_hints = *geometry;
2264 impl->geometry_mask = geom_mask;
2265}
2266
2267static void
2268gdk_wayland_window_set_title (GdkWindow *window,
2269 const gchar *title)
2270{
2271 GdkWindowImplWayland *impl;
2272 const char *end;
2273 g_return_if_fail (title != NULL);
2274
2275 if (GDK_WINDOW_DESTROYED (window))
2276 return;
2277
2278 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2279
2280 g_free (impl->title);
2281
2282 g_utf8_validate (title, MAX_WL_BUFFER_SIZE, &end);
2283 impl->title = g_malloc (end - title + 1);
2284 memcpy (impl->title, title, end - title);
2285 impl->title[end - title] = '\0';
2286
2287 gdk_wayland_window_sync_title (window);
2288}
2289
2290static void
2291gdk_wayland_window_set_role (GdkWindow *window,
2292 const gchar *role)
2293{
2294}
2295
2296static void
2297gdk_wayland_window_set_startup_id (GdkWindow *window,
2298 const gchar *startup_id)
2299{
2300}
2301
2302static gboolean
2303check_transient_for_loop (GdkWindow *window,
2304 GdkWindow *parent)
2305{
2306 while (parent)
2307 {
2308 GdkWindowImplWayland *impl;
2309
2310 if (!GDK_IS_WINDOW_IMPL_WAYLAND(parent->impl))
2311 return FALSE;
2312
2313 impl = GDK_WINDOW_IMPL_WAYLAND (parent->impl);
2314 if (impl->transient_for == window)
2315 return TRUE;
2316 parent = impl->transient_for;
2317 }
2318 return FALSE;
2319}
2320
2321static void
2322gdk_wayland_window_set_transient_for (GdkWindow *window,
2323 GdkWindow *parent)
2324{
2325 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2326 GdkWaylandDisplay *display_wayland =
2327 GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
2328 GdkWindow *previous_parent;
2329
2330 g_assert (parent == NULL ||
2331 gdk_window_get_display (window) == gdk_window_get_display (parent));
2332
2333 if (check_transient_for_loop (window, parent))
2334 {
2335 g_warning ("Setting %p transient for %p would create a loop", window, parent);
2336 return;
2337 }
2338
2339 if (impl->display_server.wl_subsurface)
2340 unmap_subsurface (window);
2341
2342 previous_parent = impl->transient_for;
2343 impl->transient_for = parent;
2344
2345 if (impl->hint == GDK_WINDOW_TYPE_HINT_DIALOG)
2346 {
2347 if (!parent)
2348 _gdk_wayland_screen_add_orphan_dialog (window);
2349 else if (!previous_parent)
2350 display_wayland->orphan_dialogs =
2351 g_list_remove (display_wayland->orphan_dialogs, window);
2352 }
2353 gdk_wayland_window_sync_parent (window, NULL);
2354 if (should_map_as_subsurface (window) &&
2355 parent && gdk_window_is_visible (window))
2356 gdk_wayland_window_create_subsurface (window);
2357}
2358
2359static void
2360gdk_wayland_window_get_frame_extents (GdkWindow *window,
2361 GdkRectangle *rect)
2362{
2363 gdk_wayland_window_get_fake_root_coords (window, &rect->x, &rect->y);
2364 rect->width = window->width;
2365 rect->height = window->height;
2366}
2367
2368static void
2369gdk_wayland_window_set_override_redirect (GdkWindow *window,
2370 gboolean override_redirect)
2371{
2372}
2373
2374static void
2375gdk_wayland_window_set_accept_focus (GdkWindow *window,
2376 gboolean accept_focus)
2377{
2378}
2379
2380static void
2381gdk_wayland_window_set_focus_on_map (GdkWindow *window,
2382 gboolean focus_on_map)
2383{
2384}
2385
2386static void
2387gdk_wayland_window_set_icon_list (GdkWindow *window,
2388 GList *pixbufs)
2389{
2390}
2391
2392static void
2393gdk_wayland_window_set_icon_name (GdkWindow *window,
2394 const gchar *name)
2395{
2396 if (GDK_WINDOW_DESTROYED (window))
2397 return;
2398}
2399
2400static void
2401gdk_wayland_window_iconify (GdkWindow *window)
2402{
2403 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2404
2405 if (GDK_WINDOW_DESTROYED (window) ||
2406 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2407 return;
2408
2409 if (!impl->display_server.xdg_surface)
2410 return;
2411
2412 xdg_surface_set_minimized (impl->display_server.xdg_surface);
2413}
2414
2415static void
2416gdk_wayland_window_deiconify (GdkWindow *window)
2417{
2418 if (GDK_WINDOW_DESTROYED (window) ||
2419 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2420 return;
2421
2422 if (GDK_WINDOW_IS_MAPPED (window))
2423 gdk_window_show (window);
2424 else
2425 /* Flip our client side flag, the real work happens on map. */
2426 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_ICONIFIED, 0);
2427}
2428
2429static void
2430gdk_wayland_window_stick (GdkWindow *window)
2431{
2432}
2433
2434static void
2435gdk_wayland_window_unstick (GdkWindow *window)
2436{
2437}
2438
2439static void
2440gdk_wayland_window_maximize (GdkWindow *window)
2441{
2442 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2443
2444 if (GDK_WINDOW_DESTROYED (window))
2445 return;
2446
2447 _gdk_wayland_window_save_size (window);
2448 if (impl->display_server.xdg_surface)
2449 xdg_surface_set_maximized (impl->display_server.xdg_surface);
2450 else
2451 gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_MAXIMIZED);
2452}
2453
2454static void
2455gdk_wayland_window_unmaximize (GdkWindow *window)
2456{
2457 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2458
2459 if (GDK_WINDOW_DESTROYED (window))
2460 return;
2461
2462 if (impl->display_server.xdg_surface)
2463 xdg_surface_unset_maximized (impl->display_server.xdg_surface);
2464 else
2465 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_MAXIMIZED, 0);
2466}
2467
2468static void
2469gdk_wayland_window_fullscreen_on_monitor (GdkWindow *window, gint monitor)
2470{
2471 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2472 GdkScreen *screen = gdk_window_get_screen (window);
2473 struct wl_output *fullscreen_output =
2474 _gdk_wayland_screen_get_wl_output (screen, monitor);
2475
2476 if (GDK_WINDOW_DESTROYED (window))
2477 return;
2478
2479 _gdk_wayland_window_save_size (window);
2480 if (impl->display_server.xdg_surface)
2481 xdg_surface_set_fullscreen (impl->display_server.xdg_surface, fullscreen_output);
2482 else {
2483 gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
2484 impl->initial_fullscreen_monitor = monitor;
2485 }
2486}
2487
2488static void
2489gdk_wayland_window_fullscreen (GdkWindow *window)
2490{
2491 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2492
2493 if (GDK_WINDOW_DESTROYED (window))
2494 return;
2495
2496 impl->initial_fullscreen_monitor = -1;
2497
2498 _gdk_wayland_window_save_size (window);
2499 if (impl->display_server.xdg_surface)
2500 xdg_surface_set_fullscreen (impl->display_server.xdg_surface, NULL);
2501 else
2502 gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
2503}
2504
2505static void
2506gdk_wayland_window_unfullscreen (GdkWindow *window)
2507{
2508 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2509
2510 if (GDK_WINDOW_DESTROYED (window))
2511 return;
2512
2513 impl->initial_fullscreen_monitor = -1;
2514
2515 if (impl->display_server.xdg_surface)
2516 xdg_surface_unset_fullscreen (impl->display_server.xdg_surface);
2517 else
2518 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
2519}
2520
2521static void
2522gdk_wayland_window_set_keep_above (GdkWindow *window, gboolean setting)
2523{
2524}
2525
2526static void
2527gdk_wayland_window_set_keep_below (GdkWindow *window, gboolean setting)
2528{
2529}
2530
2531static GdkWindow *
2532gdk_wayland_window_get_group (GdkWindow *window)
2533{
2534 return NULL;
2535}
2536
2537static void
2538gdk_wayland_window_set_group (GdkWindow *window,
2539 GdkWindow *leader)
2540{
2541}
2542
2543static void
2544gdk_wayland_window_set_decorations (GdkWindow *window,
2545 GdkWMDecoration decorations)
2546{
2547}
2548
2549static gboolean
2550gdk_wayland_window_get_decorations (GdkWindow *window,
2551 GdkWMDecoration *decorations)
2552{
2553 return FALSE;
2554}
2555
2556static void
2557gdk_wayland_window_set_functions (GdkWindow *window,
2558 GdkWMFunction functions)
2559{
2560}
2561
2562static void
2563gdk_wayland_window_begin_resize_drag (GdkWindow *window,
2564 GdkWindowEdge edge,
2565 GdkDevice *device,
2566 gint button,
2567 gint root_x,
2568 gint root_y,
2569 guint32 timestamp)
2570{
2571 GdkWindowImplWayland *impl;
2572 GdkEventSequence *sequence;
2573 uint32_t resize_edges, serial;
2574
2575 if (GDK_WINDOW_DESTROYED (window) ||
2576 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2577 return;
2578
2579 switch (edge)
2580 {
2581 case GDK_WINDOW_EDGE_NORTH_WEST:
2582 resize_edges = XDG_SURFACE_RESIZE_EDGE_TOP_LEFT;
2583 break;
2584
2585 case GDK_WINDOW_EDGE_NORTH:
2586 resize_edges = XDG_SURFACE_RESIZE_EDGE_TOP;
2587 break;
2588
2589 case GDK_WINDOW_EDGE_NORTH_EAST:
2590 resize_edges = XDG_SURFACE_RESIZE_EDGE_TOP_RIGHT;
2591 break;
2592
2593 case GDK_WINDOW_EDGE_WEST:
2594 resize_edges = XDG_SURFACE_RESIZE_EDGE_LEFT;
2595 break;
2596
2597 case GDK_WINDOW_EDGE_EAST:
2598 resize_edges = XDG_SURFACE_RESIZE_EDGE_RIGHT;
2599 break;
2600
2601 case GDK_WINDOW_EDGE_SOUTH_WEST:
2602 resize_edges = XDG_SURFACE_RESIZE_EDGE_BOTTOM_LEFT;
2603 break;
2604
2605 case GDK_WINDOW_EDGE_SOUTH:
2606 resize_edges = XDG_SURFACE_RESIZE_EDGE_BOTTOM;
2607 break;
2608
2609 case GDK_WINDOW_EDGE_SOUTH_EAST:
2610 resize_edges = XDG_SURFACE_RESIZE_EDGE_BOTTOM_RIGHT;
2611 break;
2612
2613 default:
2614 g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!", edge);
2615 return;
2616 }
2617
2618 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2619
2620 if (!impl->display_server.xdg_surface)
2621 return;
2622
2623 serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_device_get_seat (device),
2624 &sequence);
2625
2626 xdg_surface_resize (impl->display_server.xdg_surface,
2627 gdk_wayland_device_get_wl_seat (device),
2628 serial, resize_edges);
2629
2630 if (sequence)
2631 gdk_wayland_device_unset_touch_grab (device, sequence);
2632
2633 /* This is needed since Wayland will absorb all the pointer events after the
2634 * above function - FIXME: Is this always safe..?
2635 */
2636 gdk_seat_ungrab (gdk_device_get_seat (device));
2637}
2638
2639static void
2640gdk_wayland_window_begin_move_drag (GdkWindow *window,
2641 GdkDevice *device,
2642 gint button,
2643 gint root_x,
2644 gint root_y,
2645 guint32 timestamp)
2646{
2647 GdkWindowImplWayland *impl;
2648 GdkEventSequence *sequence;
2649 uint32_t serial;
2650
2651 if (GDK_WINDOW_DESTROYED (window) ||
2652 !WINDOW_IS_TOPLEVEL (window))
2653 return;
2654
2655 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2656
2657 if (!impl->display_server.xdg_surface)
2658 return;
2659
2660 serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_device_get_seat (device),
2661 &sequence);
2662 xdg_surface_move (impl->display_server.xdg_surface,
2663 gdk_wayland_device_get_wl_seat (device),
2664 serial);
2665 if (sequence)
2666 gdk_wayland_device_unset_touch_grab (device, sequence);
2667
2668 /* This is needed since Wayland will absorb all the pointer events after the
2669 * above function - FIXME: Is this always safe..?
2670 */
2671 gdk_seat_ungrab (gdk_device_get_seat (device));
2672}
2673
2674static void
2675gdk_wayland_window_set_opacity (GdkWindow *window,
2676 gdouble opacity)
2677{
2678}
2679
2680static void
2681gdk_wayland_window_set_composited (GdkWindow *window,
2682 gboolean composited)
2683{
2684}
2685
2686static void
2687gdk_wayland_window_destroy_notify (GdkWindow *window)
2688{
2689 if (!GDK_WINDOW_DESTROYED (window))
2690 {
2691 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
2692 g_warning ("GdkWindow %p unexpectedly destroyed", window);
2693
2694 _gdk_window_destroy (window, TRUE);
2695 }
2696
2697 g_object_unref (window);
2698}
2699
2700static void
2701gdk_wayland_window_sync_rendering (GdkWindow *window)
2702{
2703}
2704
2705static gboolean
2706gdk_wayland_window_simulate_key (GdkWindow *window,
2707 gint x,
2708 gint y,
2709 guint keyval,
2710 GdkModifierType modifiers,
2711 GdkEventType key_pressrelease)
2712{
2713 return FALSE;
2714}
2715
2716static gboolean
2717gdk_wayland_window_simulate_button (GdkWindow *window,
2718 gint x,
2719 gint y,
2720 guint button,
2721 GdkModifierType modifiers,
2722 GdkEventType button_pressrelease)
2723{
2724 return FALSE;
2725}
2726
2727static gboolean
2728gdk_wayland_window_get_property (GdkWindow *window,
2729 GdkAtom property,
2730 GdkAtom type,
2731 gulong offset,
2732 gulong length,
2733 gint pdelete,
2734 GdkAtom *actual_property_type,
2735 gint *actual_format_type,
2736 gint *actual_length,
2737 guchar **data)
2738{
2739 return FALSE;
2740}
2741
2742static void
2743gdk_wayland_window_change_property (GdkWindow *window,
2744 GdkAtom property,
2745 GdkAtom type,
2746 gint format,
2747 GdkPropMode mode,
2748 const guchar *data,
2749 gint nelements)
2750{
2751 if (property == gdk_atom_intern_static_string ("GDK_SELECTION"))
2752 gdk_wayland_selection_store (window, type, mode, data, nelements * (format / 8));
2753}
2754
2755static void
2756gdk_wayland_window_delete_property (GdkWindow *window,
2757 GdkAtom property)
2758{
2759}
2760
2761static gint
2762gdk_wayland_window_get_scale_factor (GdkWindow *window)
2763{
2764 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2765
2766 if (GDK_WINDOW_DESTROYED (window))
2767 return 1;
2768
2769 return impl->scale;
2770}
2771
2772static void
2773gdk_wayland_window_set_opaque_region (GdkWindow *window,
2774 cairo_region_t *region)
2775{
2776 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2777
2778 if (GDK_WINDOW_DESTROYED (window))
2779 return;
2780
2781 g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
2782 impl->opaque_region = cairo_region_reference (region);
2783 gdk_wayland_window_sync_opaque_region (window);
2784}
2785
2786static void
2787gdk_wayland_window_set_shadow_width (GdkWindow *window,
2788 int left,
2789 int right,
2790 int top,
2791 int bottom)
2792{
2793 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2794 gint new_width, new_height;
2795
2796 if (GDK_WINDOW_DESTROYED (window))
2797 return;
2798
2799 /* Reconfigure window to keep the same window geometry */
2800 new_width = window->width -
2801 (impl->margin_left + impl->margin_right) + (left + right);
2802 new_height = window->height -
2803 (impl->margin_top + impl->margin_bottom) + (top + bottom);
2804 gdk_wayland_window_maybe_configure (window, new_width, new_height, impl->scale);
2805
2806 impl->margin_left = left;
2807 impl->margin_right = right;
2808 impl->margin_top = top;
2809 impl->margin_bottom = bottom;
2810 gdk_wayland_window_sync_margin (window);
2811}
2812
2813static gboolean
2814gdk_wayland_window_show_window_menu (GdkWindow *window,
2815 GdkEvent *event)
2816{
2817 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2818 struct wl_seat *seat;
2819 GdkWaylandDevice *device;
2820 double x, y;
2821
2822 switch (event->type)
2823 {
2824 case GDK_BUTTON_PRESS:
2825 case GDK_BUTTON_RELEASE:
2826 case GDK_TOUCH_BEGIN:
2827 case GDK_TOUCH_END:
2828 break;
2829 default:
2830 return FALSE;
2831 }
2832
2833 if (!impl->display_server.xdg_surface)
2834 return FALSE;
2835
2836 device = GDK_WAYLAND_DEVICE (gdk_event_get_device (event));
2837 seat = gdk_wayland_device_get_wl_seat (GDK_DEVICE (device));
2838 gdk_event_get_coords (event, &x, &y);
2839
2840 xdg_surface_show_window_menu (impl->display_server.xdg_surface,
2841 seat,
2842 _gdk_wayland_device_get_implicit_grab_serial (device, event),
2843 x, y);
2844 return TRUE;
2845}
2846
2847static void
2848_gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
2849{
2850 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2851 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
2852
2853 object_class->finalize = gdk_window_impl_wayland_finalize;
2854
2855 impl_class->ref_cairo_surface = gdk_wayland_window_ref_cairo_surface;
2856 impl_class->create_similar_image_surface = gdk_wayland_window_create_similar_image_surface;
2857 impl_class->show = gdk_wayland_window_show;
2858 impl_class->hide = gdk_wayland_window_hide;
2859 impl_class->withdraw = gdk_window_wayland_withdraw;
2860 impl_class->set_events = gdk_window_wayland_set_events;
2861 impl_class->get_events = gdk_window_wayland_get_events;
2862 impl_class->raise = gdk_window_wayland_raise;
2863 impl_class->lower = gdk_window_wayland_lower;
2864 impl_class->restack_under = gdk_window_wayland_restack_under;
2865 impl_class->restack_toplevel = gdk_window_wayland_restack_toplevel;
2866 impl_class->move_resize = gdk_window_wayland_move_resize;
2867 impl_class->set_background = gdk_window_wayland_set_background;
2868 impl_class->reparent = gdk_window_wayland_reparent;
2869 impl_class->set_device_cursor = gdk_window_wayland_set_device_cursor;
2870 impl_class->get_geometry = gdk_window_wayland_get_geometry;
2871 impl_class->get_root_coords = gdk_window_wayland_get_root_coords;
2872 impl_class->get_device_state = gdk_window_wayland_get_device_state;
2873 impl_class->shape_combine_region = gdk_window_wayland_shape_combine_region;
2874 impl_class->input_shape_combine_region = gdk_window_wayland_input_shape_combine_region;
2875 impl_class->destroy = gdk_wayland_window_destroy;
2876 impl_class->destroy_foreign = gdk_window_wayland_destroy_foreign;
2877 impl_class->get_shape = gdk_wayland_window_get_shape;
2878 impl_class->get_input_shape = gdk_wayland_window_get_input_shape;
2879 impl_class->begin_paint = gdk_window_impl_wayland_begin_paint;
2880 impl_class->end_paint = gdk_window_impl_wayland_end_paint;
2881 impl_class->beep = gdk_window_impl_wayland_beep;
2882
2883 impl_class->focus = gdk_wayland_window_focus;
2884 impl_class->set_type_hint = gdk_wayland_window_set_type_hint;
2885 impl_class->get_type_hint = gdk_wayland_window_get_type_hint;
2886 impl_class->set_modal_hint = gdk_wayland_window_set_modal_hint;
2887 impl_class->set_skip_taskbar_hint = gdk_wayland_window_set_skip_taskbar_hint;
2888 impl_class->set_skip_pager_hint = gdk_wayland_window_set_skip_pager_hint;
2889 impl_class->set_urgency_hint = gdk_wayland_window_set_urgency_hint;
2890 impl_class->set_geometry_hints = gdk_wayland_window_set_geometry_hints;
2891 impl_class->set_title = gdk_wayland_window_set_title;
2892 impl_class->set_role = gdk_wayland_window_set_role;
2893 impl_class->set_startup_id = gdk_wayland_window_set_startup_id;
2894 impl_class->set_transient_for = gdk_wayland_window_set_transient_for;
2895 impl_class->get_frame_extents = gdk_wayland_window_get_frame_extents;
2896 impl_class->set_override_redirect = gdk_wayland_window_set_override_redirect;
2897 impl_class->set_accept_focus = gdk_wayland_window_set_accept_focus;
2898 impl_class->set_focus_on_map = gdk_wayland_window_set_focus_on_map;
2899 impl_class->set_icon_list = gdk_wayland_window_set_icon_list;
2900 impl_class->set_icon_name = gdk_wayland_window_set_icon_name;
2901 impl_class->iconify = gdk_wayland_window_iconify;
2902 impl_class->deiconify = gdk_wayland_window_deiconify;
2903 impl_class->stick = gdk_wayland_window_stick;
2904 impl_class->unstick = gdk_wayland_window_unstick;
2905 impl_class->maximize = gdk_wayland_window_maximize;
2906 impl_class->unmaximize = gdk_wayland_window_unmaximize;
2907 impl_class->fullscreen = gdk_wayland_window_fullscreen;
2908 impl_class->fullscreen_on_monitor = gdk_wayland_window_fullscreen_on_monitor;
2909 impl_class->unfullscreen = gdk_wayland_window_unfullscreen;
2910 impl_class->set_keep_above = gdk_wayland_window_set_keep_above;
2911 impl_class->set_keep_below = gdk_wayland_window_set_keep_below;
2912 impl_class->get_group = gdk_wayland_window_get_group;
2913 impl_class->set_group = gdk_wayland_window_set_group;
2914 impl_class->set_decorations = gdk_wayland_window_set_decorations;
2915 impl_class->get_decorations = gdk_wayland_window_get_decorations;
2916 impl_class->set_functions = gdk_wayland_window_set_functions;
2917 impl_class->begin_resize_drag = gdk_wayland_window_begin_resize_drag;
2918 impl_class->begin_move_drag = gdk_wayland_window_begin_move_drag;
2919 impl_class->set_opacity = gdk_wayland_window_set_opacity;
2920 impl_class->set_composited = gdk_wayland_window_set_composited;
2921 impl_class->destroy_notify = gdk_wayland_window_destroy_notify;
2922 impl_class->get_drag_protocol = _gdk_wayland_window_get_drag_protocol;
2923 impl_class->register_dnd = _gdk_wayland_window_register_dnd;
2924 impl_class->drag_begin = _gdk_wayland_window_drag_begin;
2925 impl_class->sync_rendering = gdk_wayland_window_sync_rendering;
2926 impl_class->simulate_key = gdk_wayland_window_simulate_key;
2927 impl_class->simulate_button = gdk_wayland_window_simulate_button;
2928 impl_class->get_property = gdk_wayland_window_get_property;
2929 impl_class->change_property = gdk_wayland_window_change_property;
2930 impl_class->delete_property = gdk_wayland_window_delete_property;
2931 impl_class->get_scale_factor = gdk_wayland_window_get_scale_factor;
2932 impl_class->set_opaque_region = gdk_wayland_window_set_opaque_region;
2933 impl_class->set_shadow_width = gdk_wayland_window_set_shadow_width;
2934 impl_class->show_window_menu = gdk_wayland_window_show_window_menu;
2935 impl_class->create_gl_context = gdk_wayland_window_create_gl_context;
2936 impl_class->invalidate_for_new_frame = gdk_wayland_window_invalidate_for_new_frame;
2937
2938 signals[COMMITTED] = g_signal_new ("committed",
2939 G_TYPE_FROM_CLASS (object_class),
2940 G_SIGNAL_RUN_LAST,
2941 0,
2942 NULL, NULL, NULL,
2943 G_TYPE_NONE, 0);
2944}
2945
2946void
2947_gdk_wayland_window_set_grab_seat (GdkWindow *window,
2948 GdkSeat *seat)
2949{
2950 GdkWindowImplWayland *impl;
2951
2952 g_return_if_fail (window != NULL);
2953
2954 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2955 impl->grab_input_seat = seat;
2956}
2957
2958/**
2959 * gdk_wayland_window_get_wl_surface:
2960 * @window: (type GdkWaylandWindow): a #GdkWindow
2961 *
2962 * Returns the Wayland surface of a #GdkWindow.
2963 *
2964 * Returns: (transfer none): a Wayland wl_surface
2965 *
2966 * Since: 3.8
2967 */
2968struct wl_surface *
2969gdk_wayland_window_get_wl_surface (GdkWindow *window)
2970{
2971 g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
2972
2973 return GDK_WINDOW_IMPL_WAYLAND (window->impl)->display_server.wl_surface;
2974}
2975
2976struct wl_output *
2977gdk_wayland_window_get_wl_output (GdkWindow *window)
2978{
2979 GdkWindowImplWayland *impl;
2980
2981 g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
2982
2983 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2984 /* We pick the head of the list as this is the last entered output */
2985 if (impl->display_server.outputs)
2986 return (struct wl_output *) impl->display_server.outputs->data;
2987
2988 return NULL;
2989}
2990
2991static struct wl_egl_window *
2992gdk_wayland_window_get_wl_egl_window (GdkWindow *window)
2993{
2994 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
2995
2996 if (impl->display_server.egl_window == NULL)
2997 {
2998 impl->display_server.egl_window =
2999 wl_egl_window_create (impl->display_server.wl_surface,
3000 impl->wrapper->width * impl->scale,
3001 impl->wrapper->height * impl->scale);
3002 wl_surface_set_buffer_scale (impl->display_server.wl_surface, impl->scale);
3003 }
3004
3005 return impl->display_server.egl_window;
3006}
3007
3008EGLSurface
3009gdk_wayland_window_get_egl_surface (GdkWindow *window,
3010 EGLConfig config)
3011{
3012 GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
3013 GdkWindowImplWayland *impl;
3014 struct wl_egl_window *egl_window;
3015
3016 g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
3017
3018 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3019
3020 if (impl->egl_surface == NULL)
3021 {
3022 egl_window = gdk_wayland_window_get_wl_egl_window (window);
3023
3024 impl->egl_surface =
3025 eglCreateWindowSurface (display->egl_display, config, egl_window, NULL);
3026 }
3027
3028 return impl->egl_surface;
3029}
3030
3031EGLSurface
3032gdk_wayland_window_get_dummy_egl_surface (GdkWindow *window,
3033 EGLConfig config)
3034{
3035 GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
3036 GdkWindowImplWayland *impl;
3037
3038 g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
3039
3040 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3041
3042 if (impl->dummy_egl_surface == NULL)
3043 {
3044 impl->display_server.dummy_egl_window =
3045 wl_egl_window_create (impl->display_server.wl_surface, 1, 1);
3046
3047 impl->dummy_egl_surface =
3048 eglCreateWindowSurface (display->egl_display, config, impl->display_server.dummy_egl_window, NULL);
3049 }
3050
3051 return impl->dummy_egl_surface;
3052}
3053
3054
3055/**
3056 * gdk_wayland_window_set_use_custom_surface:
3057 * @window: (type GdkWaylandWindow): a #GdkWindow
3058 *
3059 * Marks a #GdkWindow as a custom Wayland surface. The application is
3060 * expected to register the surface as some type of surface using
3061 * some Wayland interface.
3062 *
3063 * A good example would be writing a panel or on-screen-keyboard as an
3064 * out-of-process helper - as opposed to having those in the compositor
3065 * process. In this case the underlying surface isn’t an xdg_shell
3066 * surface and the panel or OSK client need to identify the wl_surface
3067 * as a panel or OSK to the compositor. The assumption is that the
3068 * compositor will expose a private interface to the special client
3069 * that lets the client identify the wl_surface as a panel or such.
3070 *
3071 * This function should be called before a #GdkWindow is shown. This is
3072 * best done by connecting to the #GtkWidget::realize signal:
3073 *
3074 * |[<!-- language="C" -->
3075 * static void
3076 * widget_realize_cb (GtkWidget *widget)
3077 * {
3078 * GdkWindow *window;
3079 * struct wl_surface *surface;
3080 * struct input_panel_surface *ip_surface;
3081 *
3082 * window = gtk_widget_get_window (widget);
3083 * gdk_wayland_window_set_custom_surface (window);
3084 *
3085 * surface = gdk_wayland_window_get_wl_surface (window);
3086 * ip_surface = input_panel_get_input_panel_surface (input_panel, surface);
3087 * input_panel_surface_set_panel (ip_surface);
3088 * }
3089 *
3090 * static void
3091 * setup_window (GtkWindow *window)
3092 * {
3093 * g_signal_connect (window, "realize", G_CALLBACK (widget_realize_cb), NULL);
3094 * }
3095 * ]|
3096 *
3097 * Since: 3.10
3098 */
3099void
3100gdk_wayland_window_set_use_custom_surface (GdkWindow *window)
3101{
3102 GdkWindowImplWayland *impl;
3103
3104 g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
3105
3106 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3107
3108 if (!impl->display_server.wl_surface)
3109 gdk_wayland_window_create_surface (window);
3110
3111 impl->use_custom_surface = TRUE;
3112}
3113
3114static void
3115maybe_set_gtk_surface_dbus_properties (GdkWindow *window)
3116{
3117 GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3118
3119 if (impl->application.was_set)
3120 return;
3121
3122 if (impl->application.application_id == NULL &&
3123 impl->application.app_menu_path == NULL &&
3124 impl->application.menubar_path == NULL &&
3125 impl->application.window_object_path == NULL &&
3126 impl->application.application_object_path == NULL &&
3127 impl->application.unique_bus_name == NULL)
3128 return;
3129
3130 gdk_wayland_window_init_gtk_surface (window);
3131 if (impl->display_server.gtk_surface == NULL)
3132 return;
3133
3134 gtk_surface1_set_dbus_properties (impl->display_server.gtk_surface,
3135 impl->application.application_id,
3136 impl->application.app_menu_path,
3137 impl->application.menubar_path,
3138 impl->application.window_object_path,
3139 impl->application.application_object_path,
3140 impl->application.unique_bus_name);
3141 impl->application.was_set = TRUE;
3142}
3143
3144void
3145gdk_wayland_window_set_dbus_properties_libgtk_only (GdkWindow *window,
3146 const char *application_id,
3147 const char *app_menu_path,
3148 const char *menubar_path,
3149 const char *window_object_path,
3150 const char *application_object_path,
3151 const char *unique_bus_name)
3152{
3153 GdkWindowImplWayland *impl;
3154
3155 g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
3156
3157 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3158
3159 impl->application.application_id = g_strdup (application_id);
3160 impl->application.app_menu_path = g_strdup (app_menu_path);
3161 impl->application.menubar_path = g_strdup (menubar_path);
3162 impl->application.window_object_path = g_strdup (window_object_path);
3163 impl->application.application_object_path =
3164 g_strdup (application_object_path);
3165 impl->application.unique_bus_name = g_strdup (unique_bus_name);
3166
3167 maybe_set_gtk_surface_dbus_properties (window);
3168}
3169
3170void
3171_gdk_wayland_window_offset_next_wl_buffer (GdkWindow *window,
3172 int x,
3173 int y)
3174{
3175 GdkWindowImplWayland *impl;
3176
3177 g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
3178
3179 impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
3180
3181 impl->pending_buffer_offset_x = x;
3182 impl->pending_buffer_offset_y = y;
3183}
3184