]> Pileus Git - ~andy/gtk/blob - gdk/wayland/gdkwindow-wayland.c
15cef9f4a5306ba152183c311d75c2a18b559c18
[~andy/gtk] / gdk / wayland / gdkwindow-wayland.c
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 "gdkprivate-wayland.h"
30 #include "gdkinternals.h"
31 #include "gdkdeviceprivate.h"
32
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <sys/mman.h>
37 #include <errno.h>
38
39 #include <wayland-egl.h>
40
41 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
42   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
43    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
44
45 #define WINDOW_IS_TOPLEVEL(window)                   \
46   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
47    GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
48    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
49
50 /* Return whether time1 is considered later than time2 as far as xserver
51  * time is concerned.  Accounts for wraparound.
52  */
53 #define XSERVER_TIME_IS_LATER(time1, time2)                        \
54   ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
55     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
56   )
57
58 typedef struct _GdkWaylandWindow GdkWaylandWindow;
59 typedef struct _GdkWaylandWindowClass GdkWaylandWindowClass;
60
61 struct _GdkWaylandWindow {
62   GdkWindow parent;
63 };
64
65 struct _GdkWaylandWindowClass {
66   GdkWindowClass parent_class;
67 };
68
69 G_DEFINE_TYPE (GdkWaylandWindow, gdk_wayland_window, GDK_TYPE_WINDOW)
70
71 static void
72 gdk_wayland_window_class_init (GdkWaylandWindowClass *wayland_window_class)
73 {
74 }
75
76 static void
77 gdk_wayland_window_init (GdkWaylandWindow *wayland_window)
78 {
79 }
80
81 #define GDK_TYPE_WINDOW_IMPL_WAYLAND              (_gdk_window_impl_wayland_get_type ())
82 #define GDK_WINDOW_IMPL_WAYLAND(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWayland))
83 #define GDK_WINDOW_IMPL_WAYLAND_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWaylandClass))
84 #define GDK_IS_WINDOW_IMPL_WAYLAND(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WINDOW_IMPL_WAYLAND))
85 #define GDK_IS_WINDOW_IMPL_WAYLAND_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_WAYLAND))
86 #define GDK_WINDOW_IMPL_WAYLAND_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWaylandClass))
87
88 typedef struct _GdkWindowImplWayland GdkWindowImplWayland;
89 typedef struct _GdkWindowImplWaylandClass GdkWindowImplWaylandClass;
90
91 struct _GdkWindowImplWayland
92 {
93   GdkWindowImpl parent_instance;
94
95   GdkWindow *wrapper;
96
97   GdkCursor *cursor;
98
99   gint8 toplevel_window_type;
100
101   struct wl_surface *surface;
102   struct wl_shell_surface *shell_surface;
103   unsigned int mapped : 1;
104   GdkWindow *transient_for;
105   GdkWindowTypeHint hint;
106
107   /* The surface which is being "drawn to" to */
108   cairo_surface_t *cairo_surface;
109
110   /* The surface that was the last surface the Wayland buffer from which was attached
111    * to the Wayland surface. It will be the same as cairo_surface after a call
112    * to gdk_wayland_window_attach_image. But after a call to
113    * gdk_wayland_window_update_size and then
114    * gdk_wayland_window_ref_cairo_surface the above pointer will be different.
115    */
116   cairo_surface_t *server_surface;
117
118   uint32_t resize_edges;
119
120   int focus_count;
121
122   gulong map_serial;    /* Serial of last transition from unmapped */
123
124   cairo_surface_t *icon_pixmap;
125   cairo_surface_t *icon_mask;
126
127   /* Time of most recent user interaction. */
128   gulong user_time;
129
130   GdkGeometry geometry_hints;
131   GdkWindowHints geometry_mask;
132
133   struct wl_seat *grab_input_seat;
134   guint32 grab_time;
135
136   gboolean fullscreen;
137   int saved_width, saved_height; /* before going fullscreen */
138 };
139
140 struct _GdkWindowImplWaylandClass
141 {
142   GdkWindowImplClass parent_class;
143 };
144
145 G_DEFINE_TYPE (GdkWindowImplWayland, _gdk_window_impl_wayland, GDK_TYPE_WINDOW_IMPL)
146
147 static void
148 _gdk_window_impl_wayland_init (GdkWindowImplWayland *impl)
149 {
150   impl->toplevel_window_type = -1;
151 }
152
153 void
154 _gdk_wayland_window_add_focus (GdkWindow *window)
155 {
156   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
157
158   impl->focus_count++;
159   if (impl->focus_count == 1)
160     gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FOCUSED);
161 }
162
163 void
164 _gdk_wayland_window_remove_focus (GdkWindow *window)
165 {
166   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
167
168   impl->focus_count--;
169   if (impl->focus_count == 0)
170     gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FOCUSED, 0);
171 }
172
173 /**
174  * gdk_wayland_window_update_size:
175  * @drawable: a #GdkDrawableImplWayland.
176  * 
177  * Updates the state of the drawable (in particular the drawable's
178  * cairo surface) when its size has changed.
179  **/
180 static void
181 gdk_wayland_window_update_size (GdkWindow *window,
182                                 int32_t width, int32_t height, uint32_t edges)
183 {
184   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
185   GdkRectangle area;
186   cairo_region_t *region;
187
188   if (impl->cairo_surface)
189     {
190       cairo_surface_destroy (impl->cairo_surface);
191       impl->cairo_surface = NULL;
192     }
193
194   window->width = width;
195   window->height = height;
196   impl->resize_edges = edges;
197
198   area.x = 0;
199   area.y = 0;
200   area.width = window->width;
201   area.height = window->height;
202
203   region = cairo_region_create_rectangle (&area);
204   _gdk_window_invalidate_for_expose (window, region);
205   cairo_region_destroy (region);
206 }
207
208 GdkWindow *
209 _gdk_wayland_screen_create_root_window (GdkScreen *screen,
210                                         int width, int height)
211 {
212   GdkWindow *window;
213   GdkWindowImplWayland *impl;
214
215   window = _gdk_display_create_window (gdk_screen_get_display (screen));
216   window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL);
217   window->impl_window = window;
218   window->visual = gdk_screen_get_system_visual (screen);
219
220   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
221
222   impl->wrapper = GDK_WINDOW (window);
223
224   window->window_type = GDK_WINDOW_ROOT;
225   window->depth = 32;
226
227   window->x = 0;
228   window->y = 0;
229   window->abs_x = 0;
230   window->abs_y = 0;
231   window->width = width;
232   window->height = height;
233   window->viewable = TRUE;
234
235   /* see init_randr_support() in gdkscreen-wayland.c */
236   window->event_mask = GDK_STRUCTURE_MASK;
237
238   return window;
239 }
240
241 static const gchar *
242 get_default_title (void)
243 {
244   const char *title;
245
246   title = g_get_application_name ();
247   if (!title)
248     title = g_get_prgname ();
249   if (!title)
250     title = "";
251
252   return title;
253 }
254
255 void
256 _gdk_wayland_display_create_window_impl (GdkDisplay    *display,
257                                          GdkWindow     *window,
258                                          GdkWindow     *real_parent,
259                                          GdkScreen     *screen,
260                                          GdkEventMask   event_mask,
261                                          GdkWindowAttr *attributes,
262                                          gint           attributes_mask)
263 {
264   GdkWindowImplWayland *impl;
265   const char *title;
266
267   impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL);
268   window->impl = GDK_WINDOW_IMPL (impl);
269   impl->wrapper = GDK_WINDOW (window);
270
271   if (window->width > 65535 ||
272       window->height > 65535)
273     {
274       g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
275
276       if (window->width > 65535)
277         window->width = 65535;
278       if (window->height > 65535)
279         window->height = 65535;
280     }
281
282   g_object_ref (window);
283
284   switch (GDK_WINDOW_TYPE (window))
285     {
286     case GDK_WINDOW_TOPLEVEL:
287     case GDK_WINDOW_TEMP:
288       if (attributes_mask & GDK_WA_TITLE)
289         title = attributes->title;
290       else
291         title = get_default_title ();
292
293       gdk_window_set_title (window, title);
294       break;
295
296     case GDK_WINDOW_CHILD:
297     default:
298       break;
299     }
300
301   if (attributes_mask & GDK_WA_TYPE_HINT)
302     gdk_window_set_type_hint (window, attributes->type_hint);
303 }
304
305 static const cairo_user_data_key_t gdk_wayland_cairo_key;
306
307 typedef struct _GdkWaylandCairoSurfaceData {
308   gpointer buf;
309   size_t buf_length;
310   struct wl_shm_pool *pool;
311   struct wl_buffer *buffer;
312   GdkWaylandDisplay *display;
313   int32_t width, height;
314 } GdkWaylandCairoSurfaceData;
315
316 static void
317 gdk_wayland_window_attach_image (GdkWindow *window)
318 {
319   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
320   GdkWaylandCairoSurfaceData *data;
321   int32_t server_width, server_height, dx, dy;
322
323   if (GDK_WINDOW_DESTROYED (window))
324     return;
325
326   /* The "drawn to" Cairo surface is the same as the Cairo surface from which
327    * we are driving the buffer for the Wayland surface. Therefore we don't
328    * need to do anything here
329    */
330   if (impl->server_surface == impl->cairo_surface)
331     return;
332
333   /* The wayland surface is attached to a buffer that is from the old "drawn
334    * to" surface. Unref the surface and restore the state.
335    */
336   if (impl->server_surface)
337     {
338       data = cairo_surface_get_user_data (impl->server_surface,
339                                           &gdk_wayland_cairo_key);
340
341       /* Save the old dimensions used for the surface */
342       server_width = data->width;
343       server_height = data->height;
344
345       cairo_surface_destroy (impl->server_surface);
346     }
347   else
348     {
349       server_width = 0;
350       server_height = 0;
351     }
352
353   /* Save the current "drawn to" surface for future calls into here */
354   impl->server_surface = cairo_surface_reference (impl->cairo_surface);
355
356   /* Get a Wayland buffer from this new surface */
357   data = cairo_surface_get_user_data (impl->cairo_surface,
358                                       &gdk_wayland_cairo_key);
359
360   if (impl->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT)
361     dx = server_width - data->width;
362   else
363     dx = 0;
364
365   if (impl->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP)
366     dy = server_height - data->height;
367   else
368     dy = 0;
369
370   /* Attach this new buffer to the surface */
371   wl_surface_attach (impl->surface, data->buffer, dx, dy);
372 }
373
374 static void
375 gdk_wayland_cairo_surface_destroy (void *p)
376 {
377   GdkWaylandCairoSurfaceData *data = p;
378
379   if (data->buffer)
380     wl_buffer_destroy (data->buffer);
381
382   if (data->pool)
383     wl_shm_pool_destroy (data->pool);
384
385   munmap (data->buf, data->buf_length);
386   g_free (data);
387 }
388
389
390 static struct wl_shm_pool *
391 _create_shm_pool (struct wl_shm  *shm,
392                   int             width,
393                   int             height,
394                   size_t         *buf_length,
395                   void          **data_out)
396 {
397   char filename[] = "/tmp/wayland-shm-XXXXXX";
398   struct wl_shm_pool *pool;
399   int fd, size, stride;
400   void *data;
401
402   fd = mkstemp (filename);
403   if (fd < 0) {
404       g_critical (G_STRLOC ": Unable to create temporary file (%s): %s",
405                   filename, g_strerror (errno));
406       return NULL;
407   }
408   stride = width * 4;
409   size = stride * height;
410   if (ftruncate (fd, size) < 0) {
411       g_critical (G_STRLOC ": Truncating temporary file failed: %s",
412                   g_strerror (errno));
413       close(fd);
414       return NULL;
415   }
416
417   data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
418   unlink (filename);
419
420   if (data == MAP_FAILED) {
421       g_critical (G_STRLOC ": mmap'ping temporary file failed: %s",
422                   g_strerror (errno));
423       close(fd);
424       return NULL;
425   }
426
427   pool = wl_shm_create_pool(shm, fd, size);
428
429   close (fd);
430
431   *data_out = data;
432   *buf_length = size;
433
434   return pool;
435 }
436
437 static cairo_surface_t *
438 gdk_wayland_create_cairo_surface (GdkWaylandDisplay *display,
439                                   int width, int height)
440 {
441   GdkWaylandCairoSurfaceData *data;
442   cairo_surface_t *surface = NULL;
443   cairo_status_t status;
444   int stride;
445
446   data = g_new (GdkWaylandCairoSurfaceData, 1);
447   data->display = display;
448   data->buffer = NULL;
449   data->width = width;
450   data->height = height;
451
452   stride = width * 4;
453
454   data->pool = _create_shm_pool (display->shm,
455                                  width, height,
456                                  &data->buf_length,
457                                  &data->buf);
458
459   data->buffer = wl_shm_pool_create_buffer (data->pool, 0,
460                                             width, height,
461                                             stride, WL_SHM_FORMAT_ARGB8888);
462
463   surface = cairo_image_surface_create_for_data (data->buf,
464                                                  CAIRO_FORMAT_ARGB32,
465                                                  width,
466                                                  height,
467                                                  stride);
468
469   cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key,
470                                data, gdk_wayland_cairo_surface_destroy);
471
472   status = cairo_surface_status (surface);
473   if (status != CAIRO_STATUS_SUCCESS)
474     {
475       g_critical (G_STRLOC ": Unable to create Cairo image surface: %s",
476                   cairo_status_to_string (status));
477     }
478
479   return surface;
480 }
481
482 /* On this first call this creates a double reference - the first reference
483  * is held by the GdkWindowImplWayland struct - since unlike other backends
484  * the Cairo surface is not just a cheap wrapper around some other backing.
485  * It is the buffer itself.
486  */
487 static cairo_surface_t *
488 gdk_wayland_window_ref_cairo_surface (GdkWindow *window)
489 {
490   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
491   GdkWaylandDisplay *display_wayland =
492     GDK_WAYLAND_DISPLAY (gdk_window_get_display (impl->wrapper));
493
494   if (GDK_WINDOW_DESTROYED (impl->wrapper))
495     return NULL;
496
497   if (!impl->cairo_surface)
498     {
499       impl->cairo_surface =
500         gdk_wayland_create_cairo_surface (display_wayland,
501                                       impl->wrapper->width,
502                                       impl->wrapper->height);
503     }
504
505   cairo_surface_reference (impl->cairo_surface);
506
507   return impl->cairo_surface;
508 }
509
510
511 static void
512 gdk_window_impl_wayland_finalize (GObject *object)
513 {
514   GdkWindowImplWayland *impl;
515
516   g_return_if_fail (GDK_IS_WINDOW_IMPL_WAYLAND (object));
517
518   impl = GDK_WINDOW_IMPL_WAYLAND (object);
519
520   if (impl->cursor)
521     g_object_unref (impl->cursor);
522   if (impl->server_surface)
523     cairo_surface_destroy (impl->server_surface);
524
525   G_OBJECT_CLASS (_gdk_window_impl_wayland_parent_class)->finalize (object);
526 }
527
528 static void
529 gdk_wayland_window_configure (GdkWindow *window,
530                               int width, int height, int edges)
531 {
532   GdkDisplay *display;
533   GdkEvent *event;
534
535   display = gdk_window_get_display (window);
536
537   /* TODO: Only generate a configure event if width or height have actually
538    * changed?
539    */
540   event = gdk_event_new (GDK_CONFIGURE);
541   event->configure.window = window;
542   event->configure.send_event = FALSE;
543   event->configure.width = width;
544   event->configure.height = height;
545
546   _gdk_window_update_size (window);
547   gdk_wayland_window_update_size (window, width, height, edges);
548
549   g_object_ref(window);
550
551   _gdk_wayland_display_deliver_event (display, event);
552 }
553
554 static void
555 gdk_wayland_window_set_user_time (GdkWindow *window, guint32 user_time)
556 {
557 }
558
559 static void
560 gdk_wayland_window_map (GdkWindow *window)
561 {
562   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
563   GdkWindowImplWayland *parent;
564   GdkWaylandDisplay *wayland_display =
565     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
566
567   if (!impl->mapped)
568     {
569       if (impl->transient_for)
570         {
571           struct wl_seat *grab_input_seat = NULL;
572
573           parent = GDK_WINDOW_IMPL_WAYLAND (impl->transient_for->impl);
574
575           /* Use the device that was used for the grab as the device for
576            * the popup window setup - so this relies on GTK+ taking the
577            * grab before showing the popup window.
578            */
579           if (impl->grab_input_seat)
580             grab_input_seat = impl->grab_input_seat;
581
582           if (!grab_input_seat)
583             grab_input_seat = parent->grab_input_seat;
584
585           if (grab_input_seat &&
586               (impl->hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU ||
587                impl->hint == GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU ||
588                impl->hint == GDK_WINDOW_TYPE_HINT_COMBO))
589             {
590
591               wl_shell_surface_set_popup (impl->shell_surface,
592                                           grab_input_seat,
593                                           _gdk_wayland_display_get_serial (wayland_display),
594                                           parent->surface,
595                                           window->x, window->y, 0);
596             }
597           else
598             {
599               guint32 flags = 0;
600
601               if (impl->hint == GDK_WINDOW_TYPE_HINT_TOOLTIP)
602                 flags = WL_SHELL_SURFACE_TRANSIENT_INACTIVE;
603
604               wl_shell_surface_set_transient (impl->shell_surface, parent->surface,
605                                               window->x, window->y, flags);
606             }
607         }
608       else
609         {
610           wl_shell_surface_set_toplevel (impl->shell_surface);
611         }
612       impl->mapped = TRUE;
613     }
614 }
615
616 static void
617 shell_surface_handle_configure(void *data,
618                                struct wl_shell_surface *shell_surface,
619                                uint32_t edges,
620                                int32_t width,
621                                int32_t height)
622 {
623   GdkWindow *window = GDK_WINDOW (data);
624   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
625
626   gdk_window_constrain_size (&impl->geometry_hints,
627                              impl->geometry_mask,
628                              width,
629                              height,
630                              &width,
631                              &height);
632
633   gdk_wayland_window_configure (window, width, height, edges);
634 }
635
636 static void
637 shell_surface_popup_done (void                    *data,
638                           struct wl_shell_surface *shell_surface)
639 {
640   GdkWindow *window = GDK_WINDOW (data);
641
642   /* When the popup is complete hide the window - this really relies on the
643    * fix in https://bugzilla.gnome.org/show_bug.cgi?id=670881 to work
644    * effectively.
645    */
646   gdk_window_hide (window);
647 }
648
649 static void
650 shell_surface_ping (void                    *data,
651                     struct wl_shell_surface *shell_surface,
652                     uint32_t                 serial)
653 {
654
655   GdkWindow *window = GDK_WINDOW (data);
656   GdkWaylandDisplay *wayland_display =
657     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
658
659   _gdk_wayland_display_update_serial (wayland_display, serial);
660
661   wl_shell_surface_pong(shell_surface, serial);
662 }
663
664 static const struct wl_shell_surface_listener shell_surface_listener = {
665   shell_surface_ping,
666   shell_surface_handle_configure,
667   shell_surface_popup_done
668 };
669
670 static void
671 gdk_wayland_window_show (GdkWindow *window, gboolean already_mapped)
672 {
673   GdkDisplay *display;
674   GdkWaylandDisplay *display_wayland;
675   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
676   GdkEvent *event;
677
678   display = gdk_window_get_display (window);
679   display_wayland = GDK_WAYLAND_DISPLAY (display);
680
681   if (impl->user_time != 0 &&
682       display_wayland->user_time != 0 &&
683       XSERVER_TIME_IS_LATER (display_wayland->user_time, impl->user_time))
684     gdk_wayland_window_set_user_time (window, impl->user_time);
685
686   impl->surface = wl_compositor_create_surface(display_wayland->compositor);
687   wl_surface_set_user_data(impl->surface, window);
688
689   impl->shell_surface = wl_shell_get_shell_surface (display_wayland->shell,
690                                                     impl->surface);
691   wl_shell_surface_add_listener(impl->shell_surface,
692                                 &shell_surface_listener, window);
693
694   gdk_window_set_type_hint (window, impl->hint);  
695
696   _gdk_make_event (window, GDK_MAP, NULL, FALSE);
697   event = _gdk_make_event (window, GDK_VISIBILITY_NOTIFY, NULL, FALSE);
698   event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
699
700   if (impl->cairo_surface)
701     gdk_wayland_window_attach_image (window);
702 }
703
704 static void
705 gdk_wayland_window_hide (GdkWindow *window)
706 {
707   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
708
709   if (impl->surface)
710     {
711       if (impl->shell_surface)
712         wl_shell_surface_destroy(impl->shell_surface);
713       if (impl->surface)
714         wl_surface_destroy(impl->surface);
715       impl->shell_surface = NULL;
716       impl->surface = NULL;
717       cairo_surface_destroy(impl->server_surface);
718       impl->server_surface = NULL;
719       impl->mapped = FALSE;
720     }
721
722   _gdk_window_clear_update_area (window);
723 }
724
725 static void
726 gdk_window_wayland_withdraw (GdkWindow *window)
727 {
728   GdkWindowImplWayland *impl;
729
730   if (!window->destroyed)
731     {
732       if (GDK_WINDOW_IS_MAPPED (window))
733         gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_WITHDRAWN);
734
735       g_assert (!GDK_WINDOW_IS_MAPPED (window));
736
737       impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
738       if (impl->surface)
739         {
740           if (impl->shell_surface)
741             wl_shell_surface_destroy(impl->shell_surface);
742           if (impl->surface)
743             wl_surface_destroy(impl->surface);
744           impl->shell_surface = NULL;
745           impl->surface = NULL;
746           cairo_surface_destroy(impl->server_surface);
747           impl->server_surface = NULL;
748           impl->mapped = FALSE;
749         }
750     }
751 }
752
753 static void
754 gdk_window_wayland_set_events (GdkWindow    *window,
755                                GdkEventMask  event_mask)
756 {
757   GDK_WINDOW (window)->event_mask = event_mask;
758 }
759
760 static GdkEventMask
761 gdk_window_wayland_get_events (GdkWindow *window)
762 {
763   if (GDK_WINDOW_DESTROYED (window))
764     return 0;
765   else
766     return GDK_WINDOW (window)->event_mask;
767 }
768
769 static void
770 gdk_window_wayland_raise (GdkWindow *window)
771 {
772   /* FIXME: wl_shell_raise() */
773 }
774
775 static void
776 gdk_window_wayland_lower (GdkWindow *window)
777 {
778   /* FIXME: wl_shell_lower() */
779 }
780
781 static void
782 gdk_window_wayland_restack_under (GdkWindow *window,
783                               GList *native_siblings)
784 {
785 }
786
787 static void
788 gdk_window_wayland_restack_toplevel (GdkWindow *window,
789                                  GdkWindow *sibling,
790                                  gboolean   above)
791 {
792 }
793
794 static void
795 gdk_window_wayland_move_resize (GdkWindow *window,
796                                 gboolean   with_move,
797                                 gint       x,
798                                 gint       y,
799                                 gint       width,
800                                 gint       height)
801 {
802   if (with_move)
803     {
804       window->x = x;
805       window->y = y;
806     }
807
808   /* If this function is called with width and height = -1 then that means
809    * just move the window - don't update its size
810    */
811   if (width > 0 && height > 0)
812     gdk_wayland_window_configure (window, width, height, 0);
813 }
814
815 static void
816 gdk_window_wayland_set_background (GdkWindow      *window,
817                                cairo_pattern_t *pattern)
818 {
819 }
820
821 static gboolean
822 gdk_window_wayland_reparent (GdkWindow *window,
823                              GdkWindow *new_parent,
824                              gint       x,
825                              gint       y)
826 {
827   return FALSE;
828 }
829
830 static void
831 gdk_window_wayland_set_device_cursor (GdkWindow *window,
832                                       GdkDevice *device,
833                                       GdkCursor *cursor)
834 {
835   g_return_if_fail (GDK_IS_WINDOW (window));
836   g_return_if_fail (GDK_IS_DEVICE (device));
837
838   if (!GDK_WINDOW_DESTROYED (window))
839     GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
840 }
841
842 static void
843 gdk_window_wayland_get_geometry (GdkWindow *window,
844                                  gint      *x,
845                                  gint      *y,
846                                  gint      *width,
847                                  gint      *height)
848 {
849   if (!GDK_WINDOW_DESTROYED (window))
850     {
851       if (x)
852         *x = window->x;
853       if (y)
854         *y = window->y;
855       if (width)
856         *width = window->width;
857       if (height)
858         *height = window->height;
859     }
860 }
861
862 void
863 _gdk_wayland_window_offset (GdkWindow *window,
864                             gint      *x_out,
865                             gint      *y_out)
866 {
867   GdkWindowImplWayland *impl, *parent_impl;
868   GdkWindow *parent_window;
869   gint x_offset = 0, y_offset = 0;
870
871   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
872
873   parent_window = impl->transient_for;
874   while (parent_window)
875     {
876       parent_impl = GDK_WINDOW_IMPL_WAYLAND (parent_window->impl);
877
878       x_offset += window->x;
879       y_offset += window->y;
880
881       parent_window = parent_impl->transient_for;
882     }
883
884   *x_out = x_offset;
885   *y_out = y_offset;
886 }
887
888 static gint
889 gdk_window_wayland_get_root_coords (GdkWindow *window,
890                                 gint       x,
891                                 gint       y,
892                                 gint      *root_x,
893                                 gint      *root_y)
894 {
895   gint x_offset, y_offset;
896
897   _gdk_wayland_window_offset (window, &x_offset, &y_offset);
898
899   *root_x = x_offset + x;
900   *root_y = y_offset + y;
901
902   return 1;
903 }
904
905 static gboolean
906 gdk_window_wayland_get_device_state (GdkWindow       *window,
907                                      GdkDevice       *device,
908                                      gint            *x,
909                                      gint            *y,
910                                      GdkModifierType *mask)
911 {
912   gboolean return_val;
913
914   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
915
916   return_val = TRUE;
917
918   if (!GDK_WINDOW_DESTROYED (window))
919     {
920       GdkWindow *child;
921
922       GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
923                                                   NULL, &child,
924                                                   NULL, NULL,
925                                                   x, y, mask);
926       return_val = (child != NULL);
927     }
928
929   return return_val;
930 }
931
932 static void
933 gdk_window_wayland_shape_combine_region (GdkWindow       *window,
934                                          const cairo_region_t *shape_region,
935                                          gint             offset_x,
936                                          gint             offset_y)
937 {
938 }
939
940 static void 
941 gdk_window_wayland_input_shape_combine_region (GdkWindow       *window,
942                                                const cairo_region_t *shape_region,
943                                                gint             offset_x,
944                                                gint             offset_y)
945 {
946 }
947
948 static gboolean
949 gdk_window_wayland_set_static_gravities (GdkWindow *window,
950                                          gboolean   use_static)
951 {
952   return TRUE;
953 }
954
955 static gboolean
956 gdk_wayland_window_queue_antiexpose (GdkWindow *window,
957                                      cairo_region_t *area)
958 {
959   return FALSE;
960 }
961
962 static void
963 gdk_wayland_window_translate (GdkWindow      *window,
964                               cairo_region_t *area,
965                               gint            dx,
966                               gint            dy)
967 {
968   _gdk_window_invalidate_for_expose (window, area);
969 }
970
971 static void
972 gdk_wayland_window_destroy (GdkWindow *window,
973                             gboolean   recursing,
974                             gboolean   foreign_destroy)
975 {
976   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
977
978   g_return_if_fail (GDK_IS_WINDOW (window));
979
980   if (impl->cairo_surface)
981     {
982       cairo_surface_finish (impl->cairo_surface);
983       cairo_surface_set_user_data (impl->cairo_surface, &gdk_wayland_cairo_key,
984                                    NULL, NULL);
985     }
986
987   if (!recursing && !foreign_destroy)
988     {
989       if (impl->shell_surface)
990         wl_shell_surface_destroy(impl->shell_surface);
991       if (impl->surface)
992         wl_surface_destroy(impl->surface);
993       impl->shell_surface = NULL;
994       impl->surface = NULL;
995     }
996 }
997
998 static void
999 gdk_window_wayland_destroy_foreign (GdkWindow *window)
1000 {
1001 }
1002
1003 static cairo_surface_t *
1004 gdk_window_wayland_resize_cairo_surface (GdkWindow       *window,
1005                                          cairo_surface_t *surface,
1006                                          gint             width,
1007                                          gint             height)
1008 {
1009   return surface;
1010 }
1011
1012 static cairo_region_t *
1013 gdk_wayland_window_get_shape (GdkWindow *window)
1014 {
1015   return NULL;
1016 }
1017
1018 static cairo_region_t *
1019 gdk_wayland_window_get_input_shape (GdkWindow *window)
1020 {
1021   return NULL;
1022 }
1023
1024 static void
1025 gdk_wayland_window_focus (GdkWindow *window,
1026                           guint32    timestamp)
1027 {
1028   /* FIXME: wl_shell_focus() */
1029 }
1030
1031 static void
1032 gdk_wayland_window_set_type_hint (GdkWindow        *window,
1033                                   GdkWindowTypeHint hint)
1034 {
1035   GdkWindowImplWayland *impl;
1036
1037   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1038
1039   if (GDK_WINDOW_DESTROYED (window))
1040     return;
1041
1042   impl->hint = hint;
1043
1044   switch (hint)
1045     {
1046     case GDK_WINDOW_TYPE_HINT_MENU:
1047     case GDK_WINDOW_TYPE_HINT_TOOLBAR:
1048     case GDK_WINDOW_TYPE_HINT_UTILITY:
1049     case GDK_WINDOW_TYPE_HINT_DOCK:
1050     case GDK_WINDOW_TYPE_HINT_DESKTOP:
1051     case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
1052     case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
1053     case GDK_WINDOW_TYPE_HINT_TOOLTIP:
1054     case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
1055     case GDK_WINDOW_TYPE_HINT_COMBO:
1056     case GDK_WINDOW_TYPE_HINT_DND:
1057       break;
1058     default:
1059       g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
1060       /* Fall thru */
1061     case GDK_WINDOW_TYPE_HINT_DIALOG:
1062     case GDK_WINDOW_TYPE_HINT_NORMAL:
1063     case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
1064       if (impl->shell_surface)
1065         wl_shell_surface_set_toplevel (impl->shell_surface);
1066       break;
1067     }
1068 }
1069
1070 static GdkWindowTypeHint
1071 gdk_wayland_window_get_type_hint (GdkWindow *window)
1072 {
1073   return GDK_WINDOW_TYPE_HINT_NORMAL;
1074 }
1075
1076 void
1077 gdk_wayland_window_set_modal_hint (GdkWindow *window,
1078                                    gboolean   modal)
1079 {
1080 }
1081
1082 static void
1083 gdk_wayland_window_set_skip_taskbar_hint (GdkWindow *window,
1084                                           gboolean   skips_taskbar)
1085 {
1086 }
1087
1088 static void
1089 gdk_wayland_window_set_skip_pager_hint (GdkWindow *window,
1090                                         gboolean   skips_pager)
1091 {
1092 }
1093
1094 static void
1095 gdk_wayland_window_set_urgency_hint (GdkWindow *window,
1096                                      gboolean   urgent)
1097 {
1098 }
1099
1100 static void
1101 gdk_wayland_window_set_geometry_hints (GdkWindow         *window,
1102                                        const GdkGeometry *geometry,
1103                                        GdkWindowHints     geom_mask)
1104 {
1105   GdkWindowImplWayland *impl;
1106
1107   if (GDK_WINDOW_DESTROYED (window) ||
1108       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1109     return;
1110
1111   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1112
1113   impl->geometry_hints = *geometry;
1114   impl->geometry_mask = geom_mask;
1115
1116   /*
1117    * GDK_HINT_POS
1118    * GDK_HINT_USER_POS
1119    * GDK_HINT_USER_SIZE
1120    * GDK_HINT_MIN_SIZE
1121    * GDK_HINT_MAX_SIZE
1122    * GDK_HINT_BASE_SIZE
1123    * GDK_HINT_RESIZE_INC
1124    * GDK_HINT_ASPECT
1125    * GDK_HINT_WIN_GRAVITY
1126    */
1127 }
1128
1129 static void
1130 gdk_wayland_window_set_title (GdkWindow   *window,
1131                               const gchar *title)
1132 {
1133   g_return_if_fail (title != NULL);
1134
1135   if (GDK_WINDOW_DESTROYED (window))
1136     return;
1137 }
1138
1139 static void
1140 gdk_wayland_window_set_role (GdkWindow   *window,
1141                              const gchar *role)
1142 {
1143 }
1144
1145 static void
1146 gdk_wayland_window_set_startup_id (GdkWindow   *window,
1147                                    const gchar *startup_id)
1148 {
1149 }
1150
1151 static void
1152 gdk_wayland_window_set_transient_for (GdkWindow *window,
1153                                       GdkWindow *parent)
1154 {
1155   GdkWindowImplWayland *impl;
1156
1157   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1158   impl->transient_for = parent;
1159 }
1160
1161 static void
1162 gdk_wayland_window_get_root_origin (GdkWindow *window,
1163                                    gint      *x,
1164                                    gint      *y)
1165 {
1166   if (x)
1167     *x = 0;
1168
1169   if (y)
1170     *y = 0;
1171 }
1172
1173 static void
1174 gdk_wayland_window_get_frame_extents (GdkWindow    *window,
1175                                       GdkRectangle *rect)
1176 {
1177   rect->x = window->x;
1178   rect->y = window->y;
1179   rect->width = window->width;
1180   rect->height = window->height;
1181 }
1182
1183 static void
1184 gdk_wayland_window_set_override_redirect (GdkWindow *window,
1185                                           gboolean override_redirect)
1186 {
1187 }
1188
1189 static void
1190 gdk_wayland_window_set_accept_focus (GdkWindow *window,
1191                                      gboolean accept_focus)
1192 {
1193 }
1194
1195 static void
1196 gdk_wayland_window_set_focus_on_map (GdkWindow *window,
1197                                      gboolean focus_on_map)
1198 {
1199   focus_on_map = focus_on_map != FALSE;
1200
1201   if (window->focus_on_map != focus_on_map)
1202     {
1203       window->focus_on_map = focus_on_map;
1204
1205       if ((!GDK_WINDOW_DESTROYED (window)) &&
1206           (!window->focus_on_map) &&
1207           WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1208         gdk_wayland_window_set_user_time (window, 0);
1209     }
1210 }
1211
1212 static void
1213 gdk_wayland_window_set_icon_list (GdkWindow *window,
1214                                   GList     *pixbufs)
1215 {
1216 }
1217
1218 static void
1219 gdk_wayland_window_set_icon_name (GdkWindow   *window,
1220                                   const gchar *name)
1221 {
1222   if (GDK_WINDOW_DESTROYED (window))
1223     return;
1224 }
1225
1226 static void
1227 gdk_wayland_window_iconify (GdkWindow *window)
1228 {
1229 }
1230
1231 static void
1232 gdk_wayland_window_deiconify (GdkWindow *window)
1233 {
1234   if (GDK_WINDOW_DESTROYED (window) ||
1235       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1236     return;
1237
1238   if (GDK_WINDOW_IS_MAPPED (window))
1239     {  
1240       gdk_window_show (window);
1241     }
1242   else
1243     {
1244       /* Flip our client side flag, the real work happens on map. */
1245       gdk_synthesize_window_state (window, GDK_WINDOW_STATE_ICONIFIED, 0);
1246     }
1247 }
1248
1249 static void
1250 gdk_wayland_window_stick (GdkWindow *window)
1251 {
1252   if (GDK_WINDOW_DESTROYED (window))
1253     return;
1254 }
1255
1256 static void
1257 gdk_wayland_window_unstick (GdkWindow *window)
1258 {
1259   if (GDK_WINDOW_DESTROYED (window))
1260     return;
1261 }
1262
1263 static void
1264 gdk_wayland_window_maximize (GdkWindow *window)
1265 {
1266   if (GDK_WINDOW_DESTROYED (window))
1267     return;
1268 }
1269
1270 static void
1271 gdk_wayland_window_unmaximize (GdkWindow *window)
1272 {
1273   if (GDK_WINDOW_DESTROYED (window))
1274     return;
1275 }
1276
1277 static void
1278 gdk_wayland_window_fullscreen (GdkWindow *window)
1279 {
1280   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1281
1282   if (GDK_WINDOW_DESTROYED (window))
1283     return;
1284
1285   if (impl->fullscreen)
1286     return;
1287
1288   impl->saved_width = gdk_window_get_width (window);
1289   impl->saved_height = gdk_window_get_height (window);
1290   wl_shell_surface_set_fullscreen (impl->shell_surface,
1291                                    WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
1292                                    0,
1293                                    NULL);
1294   impl->fullscreen = TRUE;
1295 }
1296
1297 static void
1298 gdk_wayland_window_unfullscreen (GdkWindow *window)
1299 {
1300   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1301
1302   if (GDK_WINDOW_DESTROYED (window))
1303     return;
1304
1305   if (!impl->fullscreen)
1306     return;
1307
1308   wl_shell_surface_set_toplevel (impl->shell_surface);
1309   gdk_wayland_window_configure (window, impl->saved_width, impl->saved_height,
1310                                 0);
1311   impl->fullscreen = FALSE;
1312 }
1313
1314 static void
1315 gdk_wayland_window_set_keep_above (GdkWindow *window,
1316                                    gboolean   setting)
1317 {
1318   g_return_if_fail (GDK_IS_WINDOW (window));
1319
1320   if (GDK_WINDOW_DESTROYED (window))
1321     return;
1322 }
1323
1324 static void
1325 gdk_wayland_window_set_keep_below (GdkWindow *window, gboolean setting)
1326 {
1327   g_return_if_fail (GDK_IS_WINDOW (window));
1328
1329   if (GDK_WINDOW_DESTROYED (window))
1330     return;
1331 }
1332
1333 static GdkWindow *
1334 gdk_wayland_window_get_group (GdkWindow *window)
1335 {
1336   if (GDK_WINDOW_DESTROYED (window) ||
1337       !WINDOW_IS_TOPLEVEL (window))
1338     return NULL;
1339
1340   return NULL;
1341 }
1342
1343 static void
1344 gdk_wayland_window_set_group (GdkWindow *window,
1345                               GdkWindow *leader)
1346 {
1347   g_return_if_fail (GDK_IS_WINDOW (window));
1348   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1349   g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
1350 }
1351
1352 static void
1353 gdk_wayland_window_set_decorations (GdkWindow      *window,
1354                                     GdkWMDecoration decorations)
1355 {
1356 }
1357
1358 static gboolean
1359 gdk_wayland_window_get_decorations (GdkWindow       *window,
1360                                     GdkWMDecoration *decorations)
1361 {
1362   return FALSE;
1363 }
1364
1365 static void
1366 gdk_wayland_window_set_functions (GdkWindow    *window,
1367                                   GdkWMFunction functions)
1368 {
1369 }
1370
1371 static void
1372 gdk_wayland_window_begin_resize_drag (GdkWindow     *window,
1373                                       GdkWindowEdge  edge,
1374                                       GdkDevice     *device,
1375                                       gint           button,
1376                                       gint           root_x,
1377                                       gint           root_y,
1378                                       guint32        timestamp)
1379 {
1380   GdkWindowImplWayland *impl;
1381   GdkWaylandDisplay *wayland_display =
1382     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1383
1384   uint32_t grab_type;
1385
1386   if (GDK_WINDOW_DESTROYED (window) ||
1387       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1388     return;
1389
1390   switch (edge)
1391     {
1392     case GDK_WINDOW_EDGE_NORTH_WEST:
1393       grab_type = WL_SHELL_SURFACE_RESIZE_TOP_LEFT;
1394       break;
1395
1396     case GDK_WINDOW_EDGE_NORTH:
1397       grab_type = WL_SHELL_SURFACE_RESIZE_TOP;
1398       break;
1399
1400     case GDK_WINDOW_EDGE_NORTH_EAST:
1401       grab_type = WL_SHELL_SURFACE_RESIZE_RIGHT;
1402       break;
1403
1404     case GDK_WINDOW_EDGE_WEST:
1405       grab_type = WL_SHELL_SURFACE_RESIZE_LEFT;
1406       break;
1407
1408     case GDK_WINDOW_EDGE_EAST:
1409       grab_type = WL_SHELL_SURFACE_RESIZE_RIGHT;
1410       break;
1411
1412     case GDK_WINDOW_EDGE_SOUTH_WEST:
1413       grab_type = WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT;
1414       break;
1415
1416     case GDK_WINDOW_EDGE_SOUTH:
1417       grab_type = WL_SHELL_SURFACE_RESIZE_BOTTOM;
1418       break;
1419
1420     case GDK_WINDOW_EDGE_SOUTH_EAST:
1421       grab_type = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;
1422       break;
1423
1424     default:
1425       g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
1426                  edge);
1427       return;
1428     }
1429
1430   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1431
1432   wl_shell_surface_resize (impl->shell_surface,
1433                            gdk_wayland_device_get_wl_seat (device),
1434                            _gdk_wayland_display_get_serial (wayland_display),
1435                            grab_type);
1436
1437   /* This is needed since Wayland will absorb all the pointer events after the
1438    * above function - FIXME: Is this always safe..?
1439    */
1440   gdk_device_ungrab (device, timestamp);
1441 }
1442
1443 static void
1444 gdk_wayland_window_begin_move_drag (GdkWindow *window,
1445                                     GdkDevice *device,
1446                                     gint       button,
1447                                     gint       root_x,
1448                                     gint       root_y,
1449                                     guint32    timestamp)
1450 {
1451   GdkWindowImplWayland *impl;
1452   GdkWaylandDisplay *wayland_display =
1453     GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
1454
1455   if (GDK_WINDOW_DESTROYED (window) ||
1456       !WINDOW_IS_TOPLEVEL (window))
1457     return;
1458
1459   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1460
1461   wl_shell_surface_move (impl->shell_surface,
1462                          gdk_wayland_device_get_wl_seat (device),
1463                          _gdk_wayland_display_get_serial (wayland_display));
1464
1465   /* This is needed since Wayland will absorb all the pointer events after the
1466    * above function - FIXME: Is this always safe..?
1467    */
1468   gdk_device_ungrab (device, timestamp);
1469 }
1470
1471 static void
1472 gdk_wayland_window_set_opacity (GdkWindow *window,
1473                                 gdouble    opacity)
1474 {
1475 }
1476
1477 static void
1478 gdk_wayland_window_set_composited (GdkWindow *window,
1479                                    gboolean   composited)
1480 {
1481 }
1482
1483 static void
1484 gdk_wayland_window_destroy_notify (GdkWindow *window)
1485 {
1486   if (!GDK_WINDOW_DESTROYED (window))
1487     {
1488       if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1489         g_warning ("GdkWindow %p unexpectedly destroyed", window);
1490
1491       _gdk_window_destroy (window, TRUE);
1492     }
1493
1494   g_object_unref (window);
1495 }
1496
1497 static void
1498 gdk_wayland_window_process_updates_recurse (GdkWindow      *window,
1499                                             cairo_region_t *region)
1500 {
1501   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1502   cairo_rectangle_int_t rect;
1503   int i, n;
1504
1505   gdk_wayland_window_map (window);
1506
1507   if (impl->cairo_surface)
1508     gdk_wayland_window_attach_image (window);
1509
1510   n = cairo_region_num_rectangles(region);
1511   for (i = 0; i < n; i++)
1512     {
1513       cairo_region_get_rectangle (region, i, &rect);
1514       wl_surface_damage (impl->surface,
1515                          rect.x, rect.y, rect.width, rect.height);
1516       wl_surface_commit(impl->surface);
1517     }
1518
1519   _gdk_window_process_updates_recurse (window, region);
1520 }
1521
1522 static void
1523 gdk_wayland_window_sync_rendering (GdkWindow *window)
1524 {
1525 }
1526
1527 static gboolean
1528 gdk_wayland_window_simulate_key (GdkWindow      *window,
1529                                  gint            x,
1530                                  gint            y,
1531                                  guint           keyval,
1532                                  GdkModifierType modifiers,
1533                                  GdkEventType    key_pressrelease)
1534 {
1535   return FALSE;
1536 }
1537
1538 static gboolean
1539 gdk_wayland_window_simulate_button (GdkWindow      *window,
1540                                     gint            x,
1541                                     gint            y,
1542                                     guint           button, /*1..3*/
1543                                     GdkModifierType modifiers,
1544                                     GdkEventType    button_pressrelease)
1545 {
1546   return FALSE;
1547 }
1548
1549 static gboolean
1550 gdk_wayland_window_get_property (GdkWindow   *window,
1551                                  GdkAtom      property,
1552                                  GdkAtom      type,
1553                                  gulong       offset,
1554                                  gulong       length,
1555                                  gint         pdelete,
1556                                  GdkAtom     *actual_property_type,
1557                                  gint        *actual_format_type,
1558                                  gint        *actual_length,
1559                                  guchar     **data)
1560 {
1561   return FALSE;
1562 }
1563
1564 static void
1565 gdk_wayland_window_change_property (GdkWindow    *window,
1566                                     GdkAtom       property,
1567                                     GdkAtom       type,
1568                                     gint          format,
1569                                     GdkPropMode   mode,
1570                                     const guchar *data,
1571                                     gint          nelements)
1572 {
1573 }
1574
1575 static void
1576 gdk_wayland_window_delete_property (GdkWindow *window,
1577                                     GdkAtom    property)
1578 {
1579 }
1580
1581 static void
1582 _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
1583 {
1584   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1585   GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
1586
1587   object_class->finalize = gdk_window_impl_wayland_finalize;
1588
1589   impl_class->ref_cairo_surface = gdk_wayland_window_ref_cairo_surface;
1590   impl_class->show = gdk_wayland_window_show;
1591   impl_class->hide = gdk_wayland_window_hide;
1592   impl_class->withdraw = gdk_window_wayland_withdraw;
1593   impl_class->set_events = gdk_window_wayland_set_events;
1594   impl_class->get_events = gdk_window_wayland_get_events;
1595   impl_class->raise = gdk_window_wayland_raise;
1596   impl_class->lower = gdk_window_wayland_lower;
1597   impl_class->restack_under = gdk_window_wayland_restack_under;
1598   impl_class->restack_toplevel = gdk_window_wayland_restack_toplevel;
1599   impl_class->move_resize = gdk_window_wayland_move_resize;
1600   impl_class->set_background = gdk_window_wayland_set_background;
1601   impl_class->reparent = gdk_window_wayland_reparent;
1602   impl_class->set_device_cursor = gdk_window_wayland_set_device_cursor;
1603   impl_class->get_geometry = gdk_window_wayland_get_geometry;
1604   impl_class->get_root_coords = gdk_window_wayland_get_root_coords;
1605   impl_class->get_device_state = gdk_window_wayland_get_device_state;
1606   impl_class->shape_combine_region = gdk_window_wayland_shape_combine_region;
1607   impl_class->input_shape_combine_region = gdk_window_wayland_input_shape_combine_region;
1608   impl_class->set_static_gravities = gdk_window_wayland_set_static_gravities;
1609   impl_class->queue_antiexpose = gdk_wayland_window_queue_antiexpose;
1610   impl_class->translate = gdk_wayland_window_translate;
1611   impl_class->destroy = gdk_wayland_window_destroy;
1612   impl_class->destroy_foreign = gdk_window_wayland_destroy_foreign;
1613   impl_class->resize_cairo_surface = gdk_window_wayland_resize_cairo_surface;
1614   impl_class->get_shape = gdk_wayland_window_get_shape;
1615   impl_class->get_input_shape = gdk_wayland_window_get_input_shape;
1616   /* impl_class->beep */
1617
1618   impl_class->focus = gdk_wayland_window_focus;
1619   impl_class->set_type_hint = gdk_wayland_window_set_type_hint;
1620   impl_class->get_type_hint = gdk_wayland_window_get_type_hint;
1621   impl_class->set_modal_hint = gdk_wayland_window_set_modal_hint;
1622   impl_class->set_skip_taskbar_hint = gdk_wayland_window_set_skip_taskbar_hint;
1623   impl_class->set_skip_pager_hint = gdk_wayland_window_set_skip_pager_hint;
1624   impl_class->set_urgency_hint = gdk_wayland_window_set_urgency_hint;
1625   impl_class->set_geometry_hints = gdk_wayland_window_set_geometry_hints;
1626   impl_class->set_title = gdk_wayland_window_set_title;
1627   impl_class->set_role = gdk_wayland_window_set_role;
1628   impl_class->set_startup_id = gdk_wayland_window_set_startup_id;
1629   impl_class->set_transient_for = gdk_wayland_window_set_transient_for;
1630   impl_class->get_root_origin = gdk_wayland_window_get_root_origin;
1631   impl_class->get_frame_extents = gdk_wayland_window_get_frame_extents;
1632   impl_class->set_override_redirect = gdk_wayland_window_set_override_redirect;
1633   impl_class->set_accept_focus = gdk_wayland_window_set_accept_focus;
1634   impl_class->set_focus_on_map = gdk_wayland_window_set_focus_on_map;
1635   impl_class->set_icon_list = gdk_wayland_window_set_icon_list;
1636   impl_class->set_icon_name = gdk_wayland_window_set_icon_name;
1637   impl_class->iconify = gdk_wayland_window_iconify;
1638   impl_class->deiconify = gdk_wayland_window_deiconify;
1639   impl_class->stick = gdk_wayland_window_stick;
1640   impl_class->unstick = gdk_wayland_window_unstick;
1641   impl_class->maximize = gdk_wayland_window_maximize;
1642   impl_class->unmaximize = gdk_wayland_window_unmaximize;
1643   impl_class->fullscreen = gdk_wayland_window_fullscreen;
1644   impl_class->unfullscreen = gdk_wayland_window_unfullscreen;
1645   impl_class->set_keep_above = gdk_wayland_window_set_keep_above;
1646   impl_class->set_keep_below = gdk_wayland_window_set_keep_below;
1647   impl_class->get_group = gdk_wayland_window_get_group;
1648   impl_class->set_group = gdk_wayland_window_set_group;
1649   impl_class->set_decorations = gdk_wayland_window_set_decorations;
1650   impl_class->get_decorations = gdk_wayland_window_get_decorations;
1651   impl_class->set_functions = gdk_wayland_window_set_functions;
1652   impl_class->begin_resize_drag = gdk_wayland_window_begin_resize_drag;
1653   impl_class->begin_move_drag = gdk_wayland_window_begin_move_drag;
1654   impl_class->set_opacity = gdk_wayland_window_set_opacity;
1655   impl_class->set_composited = gdk_wayland_window_set_composited;
1656   impl_class->destroy_notify = gdk_wayland_window_destroy_notify;
1657   impl_class->get_drag_protocol = _gdk_wayland_window_get_drag_protocol;
1658   impl_class->register_dnd = _gdk_wayland_window_register_dnd;
1659   impl_class->drag_begin = _gdk_wayland_window_drag_begin;
1660   impl_class->process_updates_recurse = gdk_wayland_window_process_updates_recurse;
1661   impl_class->sync_rendering = gdk_wayland_window_sync_rendering;
1662   impl_class->simulate_key = gdk_wayland_window_simulate_key;
1663   impl_class->simulate_button = gdk_wayland_window_simulate_button;
1664   impl_class->get_property = gdk_wayland_window_get_property;
1665   impl_class->change_property = gdk_wayland_window_change_property;
1666   impl_class->delete_property = gdk_wayland_window_delete_property;
1667 }
1668
1669
1670 void
1671 _gdk_wayland_window_set_device_grabbed (GdkWindow      *window,
1672                                         struct wl_seat *seat,
1673                                         guint32         time_)
1674 {
1675   GdkWindowImplWayland *impl;
1676
1677   g_return_if_fail (window != NULL);
1678
1679   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1680
1681   impl->grab_input_seat = seat;
1682   impl->grab_time = time_;
1683 }
1684
1685 /**
1686  * gdk_wayland_window_get_wl_surface
1687  * @window: (type GdkWaylandWindow): a #GdkWindow
1688  *
1689  * Returns the Wayland surface of a #GdkWindow
1690  *
1691  * Returns: (transfer none): a Wayland wl_surface
1692  *
1693  * Since: 3.8
1694  */
1695 struct wl_surface *
1696 gdk_wayland_window_get_wl_surface (GdkWindow *window)
1697 {
1698   GdkWindowImplWayland *impl;
1699
1700   g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
1701
1702   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1703
1704   return impl->surface;
1705 }
1706
1707 /**
1708  * gdk_wayland_window_get_wl_shell_surface
1709  * @window: (type GdkWaylandWindow): a #GdkWindow
1710  *
1711  * Returns the Wayland shell surface of a #GdkWindow
1712  *
1713  * Returns: (transfer none): a Wayland wl_shell_surface
1714  *
1715  * Since: 3.8
1716  */
1717 struct wl_shell_surface *
1718 gdk_wayland_window_get_wl_shell_surface (GdkWindow *window)
1719 {
1720   GdkWindowImplWayland *impl;
1721
1722   g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), NULL);
1723
1724   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1725
1726   return impl->shell_surface;
1727 }