]> Pileus Git - ~andy/gtk/blob - gdk/wayland/gdkwindow-wayland.c
wayland: Remove some fprintf debug messages
[~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, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17  * 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include <netinet/in.h>
23 #include <unistd.h>
24
25 #include "gdk.h"
26 #include "gdkwayland.h"
27
28 #include "gdkwindow.h"
29 #include "gdkwindowimpl.h"
30 #include "gdkdisplay-wayland.h"
31 #include "gdkscreen-wayland.h"
32 #include "gdkprivate-wayland.h"
33 #include "gdkinternals.h"
34 #include "gdkwindow-wayland.h"
35 #include "gdkdeviceprivate.h"
36
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40
41 #include <wayland-egl.h>
42
43 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
44   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
45    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
46
47 #define WINDOW_IS_TOPLEVEL(window)                   \
48   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
49    GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
50    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
51
52 /* Return whether time1 is considered later than time2 as far as xserver
53  * time is concerned.  Accounts for wraparound.
54  */
55 #define XSERVER_TIME_IS_LATER(time1, time2)                        \
56   ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
57     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
58   )
59
60 typedef struct _GdkWaylandWindow GdkWaylandWindow;
61 typedef struct _GdkWaylandWindowClass GdkWaylandWindowClass;
62
63 struct _GdkWaylandWindow {
64   GdkWindow parent;
65 };
66
67 struct _GdkWaylandWindowClass {
68   GdkWindowClass parent_class;
69 };
70
71 G_DEFINE_TYPE (GdkWaylandWindow, _gdk_wayland_window, GDK_TYPE_WINDOW)
72
73 static void
74 _gdk_wayland_window_class_init (GdkWaylandWindowClass *wayland_window_class)
75 {
76 }
77
78 static void
79 _gdk_wayland_window_init (GdkWaylandWindow *wayland_window)
80 {
81 }
82
83 #define GDK_TYPE_WINDOW_IMPL_WAYLAND              (_gdk_window_impl_wayland_get_type ())
84 #define GDK_WINDOW_IMPL_WAYLAND(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWayland))
85 #define GDK_WINDOW_IMPL_WAYLAND_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWaylandClass))
86 #define GDK_IS_WINDOW_IMPL_WAYLAND(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WINDOW_IMPL_WAYLAND))
87 #define GDK_IS_WINDOW_IMPL_WAYLAND_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_WAYLAND))
88 #define GDK_WINDOW_IMPL_WAYLAND_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWaylandClass))
89
90 typedef struct _GdkWindowImplWayland GdkWindowImplWayland;
91 typedef struct _GdkWindowImplWaylandClass GdkWindowImplWaylandClass;
92
93 struct _GdkWindowImplWayland
94 {
95   GdkWindowImpl parent_instance;
96
97   GdkWindow *wrapper;
98
99   GdkToplevelWayland *toplevel; /* Toplevel-specific information */
100   GdkCursor *cursor;
101   GHashTable *device_cursor;
102
103   gint8 toplevel_window_type;
104
105   struct wl_surface *surface;
106   unsigned int mapped : 1;
107
108   cairo_surface_t *cairo_surface;
109   cairo_surface_t *server_surface;
110   GLuint texture;
111 };
112
113 struct _GdkWindowImplWaylandClass
114 {
115   GdkWindowImplClass parent_class;
116 };
117
118 G_DEFINE_TYPE (GdkWindowImplWayland, _gdk_window_impl_wayland, GDK_TYPE_WINDOW_IMPL)
119
120 static void
121 _gdk_window_impl_wayland_init (GdkWindowImplWayland *impl)
122 {
123   impl->toplevel_window_type = -1;
124   impl->device_cursor = g_hash_table_new_full (NULL, NULL, NULL,
125                                                (GDestroyNotify) gdk_cursor_unref);
126 }
127
128 GdkToplevelWayland *
129 _gdk_wayland_window_get_toplevel (GdkWindow *window)
130 {
131   GdkWindowImplWayland *impl;
132
133   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
134
135   if (!WINDOW_IS_TOPLEVEL (window))
136     return NULL;
137
138   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
139
140   if (!impl->toplevel)
141     impl->toplevel = g_new0 (GdkToplevelWayland, 1);
142
143   return impl->toplevel;
144 }
145
146 /**
147  * _gdk_wayland_window_update_size:
148  * @drawable: a #GdkDrawableImplWayland.
149  * 
150  * Updates the state of the drawable (in particular the drawable's
151  * cairo surface) when its size has changed.
152  **/
153 void
154 _gdk_wayland_window_update_size (GdkWindow *window)
155 {
156   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
157   GdkRectangle area;
158   cairo_region_t *region;
159
160   if (impl->cairo_surface)
161     {
162       cairo_surface_destroy (impl->cairo_surface);
163       impl->cairo_surface = NULL;
164     }
165
166   area.x = 0;
167   area.y = 0;
168   area.width = window->width;
169   area.height = window->height;
170
171   region = cairo_region_create_rectangle (&area);
172   _gdk_window_invalidate_for_expose (window, region);
173   cairo_region_destroy (region);
174 }
175
176 GdkWindow *
177 _gdk_wayland_screen_create_root_window (GdkScreen *screen,
178                                         int width, int height)
179 {
180   GdkWindow *window;
181   GdkWindowImplWayland *impl;
182
183   window = _gdk_display_create_window (gdk_screen_get_display (screen));
184   window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL);
185   window->impl_window = window;
186   window->visual = gdk_screen_get_system_visual (screen);
187
188   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
189
190   impl->wrapper = GDK_WINDOW (window);
191
192   window->window_type = GDK_WINDOW_ROOT;
193   window->depth = 32;
194
195   window->x = 0;
196   window->y = 0;
197   window->abs_x = 0;
198   window->abs_y = 0;
199   window->width = width;
200   window->height = height;
201   window->viewable = TRUE;
202
203   /* see init_randr_support() in gdkscreen-wayland.c */
204   window->event_mask = GDK_STRUCTURE_MASK;
205
206   return window;
207 }
208
209 static const gchar *
210 get_default_title (void)
211 {
212   const char *title;
213
214   title = g_get_application_name ();
215   if (!title)
216     title = g_get_prgname ();
217   if (!title)
218     title = "";
219
220   return title;
221 }
222
223 void
224 _gdk_wayland_display_create_window_impl (GdkDisplay    *display,
225                                          GdkWindow     *window,
226                                          GdkWindow     *real_parent,
227                                          GdkScreen     *screen,
228                                          GdkEventMask   event_mask,
229                                          GdkWindowAttr *attributes,
230                                          gint           attributes_mask)
231 {
232   GdkWindowImplWayland *impl;
233   const char *title;
234
235   impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL);
236   window->impl = GDK_WINDOW_IMPL (impl);
237   impl->wrapper = GDK_WINDOW (window);
238
239   if (window->width > 65535 ||
240       window->height > 65535)
241     {
242       g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
243
244       if (window->width > 65535)
245         window->width = 65535;
246       if (window->height > 65535)
247         window->height = 65535;
248     }
249
250   g_object_ref (window);
251
252   switch (GDK_WINDOW_TYPE (window))
253     {
254     case GDK_WINDOW_TOPLEVEL:
255     case GDK_WINDOW_TEMP:
256       if (attributes_mask & GDK_WA_TITLE)
257         title = attributes->title;
258       else
259         title = get_default_title ();
260
261       gdk_window_set_title (window, title);
262       break;
263
264     case GDK_WINDOW_CHILD:
265     default:
266       break;
267     }
268
269   if (attributes_mask & GDK_WA_TYPE_HINT)
270     gdk_window_set_type_hint (window, attributes->type_hint);
271 }
272
273 static void
274 gdk_toplevel_wayland_free_contents (GdkDisplay *display,
275                                 GdkToplevelWayland *toplevel)
276 {
277   if (toplevel->icon_pixmap)
278     {
279       cairo_surface_destroy (toplevel->icon_pixmap);
280       toplevel->icon_pixmap = NULL;
281     }
282   if (toplevel->icon_mask)
283     {
284       cairo_surface_destroy (toplevel->icon_mask);
285       toplevel->icon_mask = NULL;
286     }
287 }
288
289 static const cairo_user_data_key_t gdk_wayland_cairo_key;
290
291 typedef struct _GdkWaylandCairoSurfaceData {
292   EGLImageKHR image;
293   GLuint texture;
294   struct wl_egl_pixmap *pixmap;
295   struct wl_buffer *buffer;
296   GdkDisplayWayland *display;
297 } GdkWaylandCairoSurfaceData;
298
299 static void
300 gdk_wayland_window_attach_image (GdkWindow *window)
301 {
302   GdkDisplayWayland *display =
303     GDK_DISPLAY_WAYLAND (gdk_window_get_display (window));
304   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
305   GdkWaylandCairoSurfaceData *data;
306   struct wl_buffer *buffer;
307
308   if (GDK_WINDOW_DESTROYED (window))
309     return;
310
311   if (impl->server_surface == impl->cairo_surface)
312     return;
313
314   cairo_surface_reference (impl->cairo_surface);
315   if (impl->server_surface)
316     cairo_surface_destroy (impl->server_surface);
317   impl->server_surface = impl->cairo_surface;
318
319   data = cairo_surface_get_user_data (impl->cairo_surface,
320                                       &gdk_wayland_cairo_key);
321   if (!data->buffer)
322     data->buffer =
323       wl_egl_pixmap_create_buffer(display->native_display, data->pixmap);
324
325   wl_surface_attach (impl->surface, data->buffer, 0, 0);
326 }
327
328 static void
329 gdk_window_impl_wayland_finalize (GObject *object)
330 {
331   GdkWindowImplWayland *impl;
332
333   g_return_if_fail (GDK_IS_WINDOW_IMPL_WAYLAND (object));
334
335   impl = GDK_WINDOW_IMPL_WAYLAND (object);
336
337   g_free (impl->toplevel);
338
339   if (impl->cursor)
340     gdk_cursor_unref (impl->cursor);
341   if (impl->server_surface)
342     cairo_surface_destroy (impl->server_surface);
343
344   g_hash_table_destroy (impl->device_cursor);
345
346   G_OBJECT_CLASS (_gdk_window_impl_wayland_parent_class)->finalize (object);
347 }
348
349 static void
350 gdk_wayland_cairo_surface_destroy (void *p)
351 {
352   GdkWaylandCairoSurfaceData *data = p;
353
354   data->display->destroy_image (data->display->egl_display, data->image);
355   cairo_device_acquire(data->display->cairo_device);
356   glDeleteTextures(1, &data->texture);
357   cairo_device_release(data->display->cairo_device);
358   if (data->buffer)
359     wl_buffer_destroy(data->buffer);
360   g_free(data);
361 }
362
363 static cairo_surface_t *
364 gdk_wayland_create_cairo_surface (GdkDisplayWayland *display,
365                                   int width, int height)
366 {
367   GdkWaylandCairoSurfaceData *data;
368   cairo_surface_t *surface;
369   struct wl_visual *visual;
370
371   data = g_new (GdkWaylandCairoSurfaceData, 1);
372   data->display = display;
373   data->buffer = NULL;
374   visual = wl_display_get_premultiplied_argb_visual(display->wl_display);
375   data->pixmap =
376     wl_egl_pixmap_create(display->native_display, width, height, visual, 0);
377   data->image =
378     display->create_image(display->egl_display, NULL, EGL_NATIVE_PIXMAP_KHR,
379                           (EGLClientBuffer) data->pixmap, NULL);
380
381   glGenTextures(1, &data->texture);
382   glBindTexture(GL_TEXTURE_2D, data->texture);
383   display->image_target_texture_2d(GL_TEXTURE_2D, data->image);
384
385   surface = cairo_gl_surface_create_for_texture(display->cairo_device,
386                                                 CAIRO_CONTENT_COLOR_ALPHA,
387                                                 data->texture, width, height);
388
389   cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key,
390                                data, gdk_wayland_cairo_surface_destroy);
391
392   if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
393     fprintf (stderr, "create gl surface failed\n");
394
395   return surface;
396 }
397
398 static cairo_surface_t *
399 gdk_wayland_window_ref_cairo_surface (GdkWindow *window)
400 {
401   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
402   GdkDisplayWayland *display_wayland =
403     GDK_DISPLAY_WAYLAND (gdk_window_get_display (impl->wrapper));
404
405   if (GDK_WINDOW_DESTROYED (impl->wrapper))
406     return NULL;
407
408   if (!impl->cairo_surface)
409     {
410       impl->cairo_surface =
411         gdk_wayland_create_cairo_surface (display_wayland,
412                                       impl->wrapper->width,
413                                       impl->wrapper->height);
414     }
415
416   cairo_surface_reference (impl->cairo_surface);
417
418   return impl->cairo_surface;
419 }
420
421 static void
422 gdk_wayland_window_set_user_time (GdkWindow *window, guint32 user_time)
423 {
424 }
425
426 static void
427 gdk_wayland_window_show (GdkWindow *window, gboolean already_mapped)
428 {
429   GdkDisplay *display;
430   GdkDisplayWayland *display_wayland;
431   GdkToplevelWayland *toplevel;
432   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
433   GdkEvent *event;
434
435   display = gdk_window_get_display (window);
436   display_wayland = GDK_DISPLAY_WAYLAND (display);
437
438   if (WINDOW_IS_TOPLEVEL (window))
439     {
440       toplevel = _gdk_wayland_window_get_toplevel (window);
441
442       if (toplevel->user_time != 0 &&
443               display_wayland->user_time != 0 &&
444           XSERVER_TIME_IS_LATER (display_wayland->user_time, toplevel->user_time))
445         gdk_wayland_window_set_user_time (window, display_wayland->user_time);
446     }
447
448   impl->surface = wl_compositor_create_surface(display_wayland->compositor);
449   wl_surface_set_user_data(impl->surface, window);
450
451   _gdk_make_event (window, GDK_MAP, NULL, FALSE);
452   event = _gdk_make_event (window, GDK_VISIBILITY_NOTIFY, NULL, FALSE);
453   event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
454
455   if (impl->cairo_surface)
456     gdk_wayland_window_attach_image (window);
457 }
458
459 static void
460 gdk_wayland_window_hide (GdkWindow *window)
461 {
462   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
463
464   if (impl->surface)
465     {
466       wl_surface_destroy(impl->surface);
467       impl->surface = NULL;
468       cairo_surface_destroy(impl->server_surface);
469       impl->server_surface = NULL;
470       impl->mapped = FALSE;
471     }
472
473   _gdk_window_clear_update_area (window);
474 }
475
476 static void
477 gdk_window_wayland_withdraw (GdkWindow *window)
478 {
479   GdkWindowImplWayland *impl;
480
481   if (!window->destroyed)
482     {
483       if (GDK_WINDOW_IS_MAPPED (window))
484         gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_WITHDRAWN);
485
486       g_assert (!GDK_WINDOW_IS_MAPPED (window));
487
488       impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
489       if (impl->surface)
490         {
491           wl_surface_destroy(impl->surface);
492           impl->surface = NULL;
493           cairo_surface_destroy(impl->server_surface);
494           impl->server_surface = NULL;
495           impl->mapped = FALSE;
496         }
497     }
498 }
499
500 static void
501 gdk_window_wayland_set_events (GdkWindow    *window,
502                                GdkEventMask  event_mask)
503 {
504   GDK_WINDOW (window)->event_mask = event_mask;
505 }
506
507 static GdkEventMask
508 gdk_window_wayland_get_events (GdkWindow *window)
509 {
510   if (GDK_WINDOW_DESTROYED (window))
511     return 0;
512   else
513     return GDK_WINDOW (window)->event_mask;
514 }
515
516 static void
517 gdk_window_wayland_raise (GdkWindow *window)
518 {
519   /* FIXME: wl_shell_raise() */
520 }
521
522 static void
523 gdk_window_wayland_lower (GdkWindow *window)
524 {
525   /* FIXME: wl_shell_lower() */
526 }
527
528 static void
529 gdk_window_wayland_restack_under (GdkWindow *window,
530                               GList *native_siblings)
531 {
532 }
533
534 static void
535 gdk_window_wayland_restack_toplevel (GdkWindow *window,
536                                  GdkWindow *sibling,
537                                  gboolean   above)
538 {
539 }
540
541 static void
542 gdk_window_wayland_move_resize (GdkWindow *window,
543                                 gboolean   with_move,
544                                 gint       x,
545                                 gint       y,
546                                 gint       width,
547                                 gint       height)
548 {
549   window->x = x;
550   window->y = y;
551   if (width > 0)
552     window->width = width;
553   if (height > 0)
554     window->height = height;
555
556   _gdk_wayland_window_update_size (window);
557 }
558
559 static void
560 gdk_window_wayland_set_background (GdkWindow      *window,
561                                cairo_pattern_t *pattern)
562 {
563 }
564
565 static gboolean
566 gdk_window_wayland_reparent (GdkWindow *window,
567                              GdkWindow *new_parent,
568                              gint       x,
569                              gint       y)
570 {
571   return FALSE;
572 }
573
574 static void
575 gdk_window_wayland_set_device_cursor (GdkWindow *window,
576                                       GdkDevice *device,
577                                       GdkCursor *cursor)
578 {
579   GdkWindowImplWayland *impl;
580
581   g_return_if_fail (GDK_IS_WINDOW (window));
582   g_return_if_fail (GDK_IS_DEVICE (device));
583
584   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
585
586   if (!cursor)
587     g_hash_table_remove (impl->device_cursor, device);
588   else
589     {
590       g_hash_table_replace (impl->device_cursor,
591                             device, gdk_cursor_ref (cursor));
592     }
593
594   if (!GDK_WINDOW_DESTROYED (window))
595     GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
596 }
597
598 static void
599 gdk_window_wayland_get_geometry (GdkWindow *window,
600                                  gint      *x,
601                                  gint      *y,
602                                  gint      *width,
603                                  gint      *height)
604 {
605   if (!GDK_WINDOW_DESTROYED (window))
606     {
607       if (x)
608         *x = window->x;
609       if (y)
610         *y = window->y;
611       if (width)
612         *width = window->width;
613       if (height)
614         *height = window->height;
615     }
616 }
617
618 static gint
619 gdk_window_wayland_get_root_coords (GdkWindow *window,
620                                 gint       x,
621                                 gint       y,
622                                 gint      *root_x,
623                                 gint      *root_y)
624 {
625   /* We can't do this. */
626   if (root_x)
627     *root_x = 0;
628   if (root_y)
629     *root_y = 0;
630
631   return 1;
632 }
633
634 static gboolean
635 gdk_window_wayland_get_device_state (GdkWindow       *window,
636                                      GdkDevice       *device,
637                                      gint            *x,
638                                      gint            *y,
639                                      GdkModifierType *mask)
640 {
641   gboolean return_val;
642
643   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
644
645   return_val = TRUE;
646
647   if (!GDK_WINDOW_DESTROYED (window))
648     {
649       GdkWindow *child;
650
651       GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
652                                                   NULL, &child,
653                                                   NULL, NULL,
654                                                   x, y, mask);
655       return_val = (child != NULL);
656     }
657
658   return return_val;
659 }
660
661 static void
662 gdk_window_wayland_shape_combine_region (GdkWindow       *window,
663                                          const cairo_region_t *shape_region,
664                                          gint             offset_x,
665                                          gint             offset_y)
666 {
667 }
668
669 static void 
670 gdk_window_wayland_input_shape_combine_region (GdkWindow       *window,
671                                                const cairo_region_t *shape_region,
672                                                gint             offset_x,
673                                                gint             offset_y)
674 {
675 }
676
677 static gboolean
678 gdk_window_wayland_set_static_gravities (GdkWindow *window,
679                                          gboolean   use_static)
680 {
681   return TRUE;
682 }
683
684 static gboolean
685 gdk_wayland_window_queue_antiexpose (GdkWindow *window,
686                                      cairo_region_t *area)
687 {
688   return FALSE;
689 }
690
691 static void
692 gdk_wayland_window_translate (GdkWindow      *window,
693                               cairo_region_t *area,
694                               gint            dx,
695                               gint            dy)
696 {
697   cairo_surface_t *surface;
698   cairo_t *cr;
699
700   surface = gdk_wayland_window_ref_cairo_surface (window->impl_window);
701   cr = cairo_create (surface);
702   cairo_surface_destroy (surface);
703
704   gdk_cairo_region (cr, area);
705   cairo_clip (cr);
706   cairo_set_source_surface (cr, cairo_get_target (cr), dx, dy);
707   cairo_push_group (cr);
708   cairo_paint (cr);
709   cairo_pop_group_to_source (cr);
710   cairo_paint (cr);
711   cairo_destroy (cr);
712 }
713
714 static void
715 gdk_wayland_window_destroy (GdkWindow *window,
716                             gboolean   recursing,
717                             gboolean   foreign_destroy)
718 {
719   GdkToplevelWayland *toplevel;
720   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
721
722   g_return_if_fail (GDK_IS_WINDOW (window));
723
724   toplevel = _gdk_wayland_window_get_toplevel (window);
725   if (toplevel)
726     gdk_toplevel_wayland_free_contents (gdk_window_get_display (window),
727                                         toplevel);
728
729   if (impl->cairo_surface)
730     {
731       cairo_surface_finish (impl->cairo_surface);
732       cairo_surface_set_user_data (impl->cairo_surface, &gdk_wayland_cairo_key,
733                                    NULL, NULL);
734     }
735
736   if (impl->texture)
737     glDeleteTextures(1, &impl->texture);
738
739   if (!recursing && !foreign_destroy)
740     {
741       if (GDK_WINDOW_IMPL_WAYLAND (window->impl)->surface)
742         wl_surface_destroy(GDK_WINDOW_IMPL_WAYLAND (window->impl)->surface);
743     }
744 }
745
746 static void
747 gdk_window_wayland_destroy_foreign (GdkWindow *window)
748 {
749 }
750
751 static cairo_surface_t *
752 gdk_window_wayland_resize_cairo_surface (GdkWindow       *window,
753                                          cairo_surface_t *surface,
754                                          gint             width,
755                                          gint             height)
756 {
757   return surface;
758 }
759
760 static cairo_region_t *
761 gdk_wayland_window_get_shape (GdkWindow *window)
762 {
763   return NULL;
764 }
765
766 static cairo_region_t *
767 gdk_wayland_window_get_input_shape (GdkWindow *window)
768 {
769   return NULL;
770 }
771
772 static void
773 gdk_wayland_window_focus (GdkWindow *window,
774                           guint32    timestamp)
775 {
776   /* FIXME: wl_shell_focus() */
777 }
778
779 static void
780 gdk_wayland_window_set_type_hint (GdkWindow        *window,
781                                   GdkWindowTypeHint hint)
782 {
783   if (GDK_WINDOW_DESTROYED (window))
784     return;
785
786   switch (hint)
787     {
788     case GDK_WINDOW_TYPE_HINT_DIALOG:
789     case GDK_WINDOW_TYPE_HINT_MENU:
790     case GDK_WINDOW_TYPE_HINT_TOOLBAR:
791     case GDK_WINDOW_TYPE_HINT_UTILITY:
792     case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
793     case GDK_WINDOW_TYPE_HINT_DOCK:
794     case GDK_WINDOW_TYPE_HINT_DESKTOP:
795     case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
796     case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
797     case GDK_WINDOW_TYPE_HINT_TOOLTIP:
798     case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
799     case GDK_WINDOW_TYPE_HINT_COMBO:
800     case GDK_WINDOW_TYPE_HINT_DND:
801       break;
802     default:
803       g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
804       /* Fall thru */
805     case GDK_WINDOW_TYPE_HINT_NORMAL:
806       break;
807     }
808 }
809
810 static GdkWindowTypeHint
811 gdk_wayland_window_get_type_hint (GdkWindow *window)
812 {
813   return GDK_WINDOW_TYPE_HINT_NORMAL;
814 }
815
816 void
817 gdk_wayland_window_set_modal_hint (GdkWindow *window,
818                                    gboolean   modal)
819 {
820 }
821
822 static void
823 gdk_wayland_window_set_skip_taskbar_hint (GdkWindow *window,
824                                           gboolean   skips_taskbar)
825 {
826 }
827
828 static void
829 gdk_wayland_window_set_skip_pager_hint (GdkWindow *window,
830                                         gboolean   skips_pager)
831 {
832 }
833
834 static void
835 gdk_wayland_window_set_urgency_hint (GdkWindow *window,
836                                      gboolean   urgent)
837 {
838 }
839
840 static void
841 gdk_wayland_window_set_geometry_hints (GdkWindow         *window,
842                                        const GdkGeometry *geometry,
843                                        GdkWindowHints     geom_mask)
844 {
845   if (GDK_WINDOW_DESTROYED (window) ||
846       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
847     return;
848
849   /*
850    * GDK_HINT_POS
851    * GDK_HINT_USER_POS
852    * GDK_HINT_USER_SIZE
853    * GDK_HINT_MIN_SIZE
854    * GDK_HINT_MAX_SIZE
855    * GDK_HINT_BASE_SIZE
856    * GDK_HINT_RESIZE_INC
857    * GDK_HINT_ASPECT
858    * GDK_HINT_WIN_GRAVITY
859    */
860 }
861
862 static void
863 gdk_wayland_window_set_title (GdkWindow   *window,
864                               const gchar *title)
865 {
866   g_return_if_fail (title != NULL);
867
868   if (GDK_WINDOW_DESTROYED (window))
869     return;
870 }
871
872 static void
873 gdk_wayland_window_set_role (GdkWindow   *window,
874                              const gchar *role)
875 {
876 }
877
878 static void
879 gdk_wayland_window_set_startup_id (GdkWindow   *window,
880                                    const gchar *startup_id)
881 {
882 }
883
884 static void
885 gdk_wayland_window_set_transient_for (GdkWindow *window,
886                                       GdkWindow *parent)
887 {
888 }
889
890 static void
891 gdk_wayland_window_get_root_origin (GdkWindow *window,
892                                    gint      *x,
893                                    gint      *y)
894 {
895   if (x)
896     *x = 0;
897
898   if (y)
899     *y = 0;
900 }
901
902 static void
903 gdk_wayland_window_get_frame_extents (GdkWindow    *window,
904                                       GdkRectangle *rect)
905 {
906   rect->x = window->x;
907   rect->y = window->y;
908   rect->width = window->width;
909   rect->height = window->height;
910 }
911
912 static void
913 gdk_wayland_window_set_override_redirect (GdkWindow *window,
914                                           gboolean override_redirect)
915 {
916 }
917
918 static void
919 gdk_wayland_window_set_accept_focus (GdkWindow *window,
920                                      gboolean accept_focus)
921 {
922 }
923
924 static void
925 gdk_wayland_window_set_focus_on_map (GdkWindow *window,
926                                      gboolean focus_on_map)
927 {
928   focus_on_map = focus_on_map != FALSE;
929
930   if (window->focus_on_map != focus_on_map)
931     {
932       window->focus_on_map = focus_on_map;
933
934       if ((!GDK_WINDOW_DESTROYED (window)) &&
935           (!window->focus_on_map) &&
936           WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
937         gdk_wayland_window_set_user_time (window, 0);
938     }
939 }
940
941 static void
942 gdk_wayland_window_set_icon_list (GdkWindow *window,
943                                   GList     *pixbufs)
944 {
945 }
946
947 static void
948 gdk_wayland_window_set_icon_name (GdkWindow   *window,
949                                   const gchar *name)
950 {
951   if (GDK_WINDOW_DESTROYED (window))
952     return;
953 }
954
955 static void
956 gdk_wayland_window_iconify (GdkWindow *window)
957 {
958 }
959
960 static void
961 gdk_wayland_window_deiconify (GdkWindow *window)
962 {
963   if (GDK_WINDOW_DESTROYED (window) ||
964       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
965     return;
966
967   if (GDK_WINDOW_IS_MAPPED (window))
968     {  
969       gdk_window_show (window);
970     }
971   else
972     {
973       /* Flip our client side flag, the real work happens on map. */
974       gdk_synthesize_window_state (window, GDK_WINDOW_STATE_ICONIFIED, 0);
975     }
976 }
977
978 static void
979 gdk_wayland_window_stick (GdkWindow *window)
980 {
981   if (GDK_WINDOW_DESTROYED (window))
982     return;
983 }
984
985 static void
986 gdk_wayland_window_unstick (GdkWindow *window)
987 {
988   if (GDK_WINDOW_DESTROYED (window))
989     return;
990 }
991
992 static void
993 gdk_wayland_window_maximize (GdkWindow *window)
994 {
995   if (GDK_WINDOW_DESTROYED (window))
996     return;
997 }
998
999 static void
1000 gdk_wayland_window_unmaximize (GdkWindow *window)
1001 {
1002   if (GDK_WINDOW_DESTROYED (window))
1003     return;
1004 }
1005
1006 static void
1007 gdk_wayland_window_fullscreen (GdkWindow *window)
1008 {
1009   if (GDK_WINDOW_DESTROYED (window))
1010     return;
1011 }
1012
1013 static void
1014 gdk_wayland_window_unfullscreen (GdkWindow *window)
1015 {
1016   if (GDK_WINDOW_DESTROYED (window))
1017     return;
1018 }
1019
1020 static void
1021 gdk_wayland_window_set_keep_above (GdkWindow *window,
1022                                    gboolean   setting)
1023 {
1024   g_return_if_fail (GDK_IS_WINDOW (window));
1025
1026   if (GDK_WINDOW_DESTROYED (window))
1027     return;
1028 }
1029
1030 static void
1031 gdk_wayland_window_set_keep_below (GdkWindow *window, gboolean setting)
1032 {
1033   g_return_if_fail (GDK_IS_WINDOW (window));
1034
1035   if (GDK_WINDOW_DESTROYED (window))
1036     return;
1037 }
1038
1039 static GdkWindow *
1040 gdk_wayland_window_get_group (GdkWindow *window)
1041 {
1042   if (GDK_WINDOW_DESTROYED (window) ||
1043       !WINDOW_IS_TOPLEVEL (window))
1044     return NULL;
1045
1046   return NULL;
1047 }
1048
1049 static void
1050 gdk_wayland_window_set_group (GdkWindow *window,
1051                               GdkWindow *leader)
1052 {
1053   g_return_if_fail (GDK_IS_WINDOW (window));
1054   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1055   g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
1056 }
1057
1058 static void
1059 gdk_wayland_window_set_decorations (GdkWindow      *window,
1060                                     GdkWMDecoration decorations)
1061 {
1062 }
1063
1064 static gboolean
1065 gdk_wayland_window_get_decorations (GdkWindow       *window,
1066                                     GdkWMDecoration *decorations)
1067 {
1068   return FALSE;
1069 }
1070
1071 static void
1072 gdk_wayland_window_set_functions (GdkWindow    *window,
1073                                   GdkWMFunction functions)
1074 {
1075 }
1076
1077 static void
1078 gdk_wayland_window_begin_resize_drag (GdkWindow     *window,
1079                                       GdkWindowEdge  edge,
1080                                       gint           button,
1081                                       gint           root_x,
1082                                       gint           root_y,
1083                                       guint32        timestamp)
1084 {
1085   GdkDisplay *display = gdk_window_get_display (window);
1086   GdkDeviceManager *dm;
1087   GdkWindowImplWayland *impl;
1088   GdkDevice *device;
1089   uint32_t grab_type;
1090
1091   if (GDK_WINDOW_DESTROYED (window) ||
1092       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1093     return;
1094
1095   switch (edge)
1096     {
1097     case GDK_WINDOW_EDGE_NORTH_WEST:
1098       grab_type = WL_SHELL_RESIZE_TOP_LEFT;
1099       break;
1100
1101     case GDK_WINDOW_EDGE_NORTH:
1102       grab_type = WL_SHELL_RESIZE_TOP;
1103       break;
1104
1105     case GDK_WINDOW_EDGE_NORTH_EAST:
1106       grab_type = WL_SHELL_RESIZE_RIGHT;
1107       break;
1108
1109     case GDK_WINDOW_EDGE_WEST:
1110       grab_type = WL_SHELL_RESIZE_LEFT;
1111       break;
1112
1113     case GDK_WINDOW_EDGE_EAST:
1114       grab_type = WL_SHELL_RESIZE_RIGHT;
1115       break;
1116
1117     case GDK_WINDOW_EDGE_SOUTH_WEST:
1118       grab_type = WL_SHELL_RESIZE_BOTTOM_LEFT;
1119       break;
1120
1121     case GDK_WINDOW_EDGE_SOUTH:
1122       grab_type = WL_SHELL_RESIZE_BOTTOM;
1123       break;
1124
1125     case GDK_WINDOW_EDGE_SOUTH_EAST:
1126       grab_type = WL_SHELL_RESIZE_BOTTOM_RIGHT;
1127       break;
1128
1129     default:
1130       g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
1131                  edge);
1132       return;
1133     }
1134
1135   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1136   dm = gdk_display_get_device_manager (display);
1137   device = gdk_device_manager_get_client_pointer (dm);
1138
1139   wl_shell_resize(GDK_DISPLAY_WAYLAND (display)->shell, impl->surface,
1140                   _gdk_wayland_device_get_device (device),
1141                   timestamp, grab_type);
1142 }
1143
1144 static void
1145 gdk_wayland_window_begin_move_drag (GdkWindow *window,
1146                                     gint       button,
1147                                     gint       root_x,
1148                                     gint       root_y,
1149                                     guint32    timestamp)
1150 {
1151   GdkDisplay *display = gdk_window_get_display (window);
1152   GdkDeviceManager *dm;
1153   GdkWindowImplWayland *impl;
1154   GdkDevice *device;
1155
1156   if (GDK_WINDOW_DESTROYED (window) ||
1157       !WINDOW_IS_TOPLEVEL (window))
1158     return;
1159
1160   impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1161
1162   dm = gdk_display_get_device_manager (display);
1163   device = gdk_device_manager_get_client_pointer (dm);
1164
1165   wl_shell_move(GDK_DISPLAY_WAYLAND (display)->shell, impl->surface,
1166                 _gdk_wayland_device_get_device (device), timestamp);
1167 }
1168
1169 static void
1170 gdk_wayland_window_enable_synchronized_configure (GdkWindow *window)
1171 {
1172 }
1173
1174 static void
1175 gdk_wayland_window_configure_finished (GdkWindow *window)
1176 {
1177   if (!WINDOW_IS_TOPLEVEL (window))
1178     return;
1179
1180   if (!GDK_IS_WINDOW_IMPL_WAYLAND (window->impl))
1181     return;
1182 }
1183
1184 static void
1185 gdk_wayland_window_set_opacity (GdkWindow *window,
1186                                 gdouble    opacity)
1187 {
1188 }
1189
1190 static void
1191 gdk_wayland_window_set_composited (GdkWindow *window,
1192                                    gboolean   composited)
1193 {
1194 }
1195
1196 static void
1197 gdk_wayland_window_destroy_notify (GdkWindow *window)
1198 {
1199   if (!GDK_WINDOW_DESTROYED (window))
1200     {
1201       if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1202         g_warning ("GdkWindow %p unexpectedly destroyed", window);
1203
1204       _gdk_window_destroy (window, TRUE);
1205     }
1206
1207   g_object_unref (window);
1208 }
1209
1210 static void
1211 gdk_wayland_window_process_updates_recurse (GdkWindow *window,
1212                                             cairo_region_t *region)
1213 {
1214   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
1215   cairo_rectangle_int_t rect;
1216   int i, n;
1217
1218   if (impl->cairo_surface)
1219     gdk_wayland_window_attach_image (window);
1220
1221   if (!impl->mapped)
1222     {
1223       wl_surface_map_toplevel (impl->surface);
1224       impl->mapped = TRUE;
1225     }
1226
1227   n = cairo_region_num_rectangles(region);
1228   for (i = 0; i < n; i++)
1229     {
1230       cairo_region_get_rectangle (region, i, &rect);
1231       wl_surface_damage (impl->surface,
1232                          rect.x, rect.y, rect.width, rect.height);
1233     }
1234
1235   _gdk_window_process_updates_recurse (window, region);
1236 }
1237
1238 static void
1239 gdk_wayland_window_sync_rendering (GdkWindow *window)
1240 {
1241 }
1242
1243 static gboolean
1244 gdk_wayland_window_simulate_key (GdkWindow      *window,
1245                                  gint            x,
1246                                  gint            y,
1247                                  guint           keyval,
1248                                  GdkModifierType modifiers,
1249                                  GdkEventType    key_pressrelease)
1250 {
1251   return FALSE;
1252 }
1253
1254 static gboolean
1255 gdk_wayland_window_simulate_button (GdkWindow      *window,
1256                                     gint            x,
1257                                     gint            y,
1258                                     guint           button, /*1..3*/
1259                                     GdkModifierType modifiers,
1260                                     GdkEventType    button_pressrelease)
1261 {
1262   return FALSE;
1263 }
1264
1265 static gboolean
1266 gdk_wayland_window_get_property (GdkWindow   *window,
1267                                  GdkAtom      property,
1268                                  GdkAtom      type,
1269                                  gulong       offset,
1270                                  gulong       length,
1271                                  gint         pdelete,
1272                                  GdkAtom     *actual_property_type,
1273                                  gint        *actual_format_type,
1274                                  gint        *actual_length,
1275                                  guchar     **data)
1276 {
1277   return FALSE;
1278 }
1279
1280 static void
1281 gdk_wayland_window_change_property (GdkWindow    *window,
1282                                     GdkAtom       property,
1283                                     GdkAtom       type,
1284                                     gint          format,
1285                                     GdkPropMode   mode,
1286                                     const guchar *data,
1287                                     gint          nelements)
1288 {
1289 }
1290
1291 static void
1292 gdk_wayland_window_delete_property (GdkWindow *window,
1293                                     GdkAtom    property)
1294 {
1295 }
1296
1297 static void
1298 _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
1299 {
1300   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1301   GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
1302
1303   object_class->finalize = gdk_window_impl_wayland_finalize;
1304
1305   impl_class->ref_cairo_surface = gdk_wayland_window_ref_cairo_surface;
1306   impl_class->show = gdk_wayland_window_show;
1307   impl_class->hide = gdk_wayland_window_hide;
1308   impl_class->withdraw = gdk_window_wayland_withdraw;
1309   impl_class->set_events = gdk_window_wayland_set_events;
1310   impl_class->get_events = gdk_window_wayland_get_events;
1311   impl_class->raise = gdk_window_wayland_raise;
1312   impl_class->lower = gdk_window_wayland_lower;
1313   impl_class->restack_under = gdk_window_wayland_restack_under;
1314   impl_class->restack_toplevel = gdk_window_wayland_restack_toplevel;
1315   impl_class->move_resize = gdk_window_wayland_move_resize;
1316   impl_class->set_background = gdk_window_wayland_set_background;
1317   impl_class->reparent = gdk_window_wayland_reparent;
1318   impl_class->set_device_cursor = gdk_window_wayland_set_device_cursor;
1319   impl_class->get_geometry = gdk_window_wayland_get_geometry;
1320   impl_class->get_root_coords = gdk_window_wayland_get_root_coords;
1321   impl_class->get_device_state = gdk_window_wayland_get_device_state;
1322   impl_class->shape_combine_region = gdk_window_wayland_shape_combine_region;
1323   impl_class->input_shape_combine_region = gdk_window_wayland_input_shape_combine_region;
1324   impl_class->set_static_gravities = gdk_window_wayland_set_static_gravities;
1325   impl_class->queue_antiexpose = gdk_wayland_window_queue_antiexpose;
1326   impl_class->translate = gdk_wayland_window_translate;
1327   impl_class->destroy = gdk_wayland_window_destroy;
1328   impl_class->destroy_foreign = gdk_window_wayland_destroy_foreign;
1329   impl_class->resize_cairo_surface = gdk_window_wayland_resize_cairo_surface;
1330   impl_class->get_shape = gdk_wayland_window_get_shape;
1331   impl_class->get_input_shape = gdk_wayland_window_get_input_shape;
1332   /* impl_class->beep */
1333
1334   impl_class->focus = gdk_wayland_window_focus;
1335   impl_class->set_type_hint = gdk_wayland_window_set_type_hint;
1336   impl_class->get_type_hint = gdk_wayland_window_get_type_hint;
1337   impl_class->set_modal_hint = gdk_wayland_window_set_modal_hint;
1338   impl_class->set_skip_taskbar_hint = gdk_wayland_window_set_skip_taskbar_hint;
1339   impl_class->set_skip_pager_hint = gdk_wayland_window_set_skip_pager_hint;
1340   impl_class->set_urgency_hint = gdk_wayland_window_set_urgency_hint;
1341   impl_class->set_geometry_hints = gdk_wayland_window_set_geometry_hints;
1342   impl_class->set_title = gdk_wayland_window_set_title;
1343   impl_class->set_role = gdk_wayland_window_set_role;
1344   impl_class->set_startup_id = gdk_wayland_window_set_startup_id;
1345   impl_class->set_transient_for = gdk_wayland_window_set_transient_for;
1346   impl_class->get_root_origin = gdk_wayland_window_get_root_origin;
1347   impl_class->get_frame_extents = gdk_wayland_window_get_frame_extents;
1348   impl_class->set_override_redirect = gdk_wayland_window_set_override_redirect;
1349   impl_class->set_accept_focus = gdk_wayland_window_set_accept_focus;
1350   impl_class->set_focus_on_map = gdk_wayland_window_set_focus_on_map;
1351   impl_class->set_icon_list = gdk_wayland_window_set_icon_list;
1352   impl_class->set_icon_name = gdk_wayland_window_set_icon_name;
1353   impl_class->iconify = gdk_wayland_window_iconify;
1354   impl_class->deiconify = gdk_wayland_window_deiconify;
1355   impl_class->stick = gdk_wayland_window_stick;
1356   impl_class->unstick = gdk_wayland_window_unstick;
1357   impl_class->maximize = gdk_wayland_window_maximize;
1358   impl_class->unmaximize = gdk_wayland_window_unmaximize;
1359   impl_class->fullscreen = gdk_wayland_window_fullscreen;
1360   impl_class->unfullscreen = gdk_wayland_window_unfullscreen;
1361   impl_class->set_keep_above = gdk_wayland_window_set_keep_above;
1362   impl_class->set_keep_below = gdk_wayland_window_set_keep_below;
1363   impl_class->get_group = gdk_wayland_window_get_group;
1364   impl_class->set_group = gdk_wayland_window_set_group;
1365   impl_class->set_decorations = gdk_wayland_window_set_decorations;
1366   impl_class->get_decorations = gdk_wayland_window_get_decorations;
1367   impl_class->set_functions = gdk_wayland_window_set_functions;
1368   impl_class->begin_resize_drag = gdk_wayland_window_begin_resize_drag;
1369   impl_class->begin_move_drag = gdk_wayland_window_begin_move_drag;
1370   impl_class->enable_synchronized_configure = gdk_wayland_window_enable_synchronized_configure;
1371   impl_class->configure_finished = gdk_wayland_window_configure_finished;
1372   impl_class->set_opacity = gdk_wayland_window_set_opacity;
1373   impl_class->set_composited = gdk_wayland_window_set_composited;
1374   impl_class->destroy_notify = gdk_wayland_window_destroy_notify;
1375   impl_class->get_drag_protocol = _gdk_wayland_window_get_drag_protocol;
1376   impl_class->register_dnd = _gdk_wayland_window_register_dnd;
1377   impl_class->drag_begin = _gdk_wayland_window_drag_begin;
1378   impl_class->process_updates_recurse = gdk_wayland_window_process_updates_recurse;
1379   impl_class->sync_rendering = gdk_wayland_window_sync_rendering;
1380   impl_class->simulate_key = gdk_wayland_window_simulate_key;
1381   impl_class->simulate_button = gdk_wayland_window_simulate_button;
1382   impl_class->get_property = gdk_wayland_window_get_property;
1383   impl_class->change_property = gdk_wayland_window_change_property;
1384   impl_class->delete_property = gdk_wayland_window_delete_property;
1385 }