]> Pileus Git - ~andy/gtk/blob - gdk/broadway/gdkwindow-broadway.c
GdkBroadwayDisplay: initialize GError before using it
[~andy/gtk] / gdk / broadway / gdkwindow-broadway.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3  * Josh MacDonald, Ryan Lortie
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 /*
20  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
21  * file for a list of people on the GTK+ Team.  See the ChangeLog
22  * files for a list of changes.  These files are distributed with
23  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
24  */
25
26 #include "config.h"
27
28 #include "gdkwindow-broadway.h"
29 #include "gdkscreen-broadway.h"
30
31 #include "gdkwindow.h"
32 #include "gdkwindowimpl.h"
33 #include "gdkdisplay-broadway.h"
34 #include "gdkprivate-broadway.h"
35 #include "gdkinternals.h"
36 #include "gdkdeviceprivate.h"
37 #include "gdkeventsource.h"
38
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <netinet/in.h>
43 #include <unistd.h>
44
45 /* Forward declarations */
46 static void     gdk_window_broadway_set_background     (GdkWindow      *window,
47                                                    cairo_pattern_t *pattern);
48
49 static void        gdk_window_impl_broadway_finalize   (GObject            *object);
50
51 static const cairo_user_data_key_t gdk_broadway_cairo_key;
52
53 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
54   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
55    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
56
57 #define WINDOW_IS_TOPLEVEL(window)                   \
58   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
59    GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
60    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
61
62 struct _GdkBroadwayWindow {
63   GdkWindow parent;
64 };
65
66 struct _GdkBroadwayWindowClass {
67   GdkWindowClass parent_class;
68 };
69
70 G_DEFINE_TYPE (GdkBroadwayWindow, gdk_broadway_window, GDK_TYPE_WINDOW)
71
72 static void
73 gdk_broadway_window_class_init (GdkBroadwayWindowClass *broadway_window_class)
74 {
75 }
76
77 static void
78 gdk_broadway_window_init (GdkBroadwayWindow *broadway_window)
79 {
80 }
81
82 G_DEFINE_TYPE (GdkWindowImplBroadway,
83                gdk_window_impl_broadway,
84                GDK_TYPE_WINDOW_IMPL)
85
86 static void
87 diff_surfaces (cairo_surface_t *surface,
88                cairo_surface_t *old_surface)
89 {
90   guint8 *data, *old_data;
91   guint32 *line, *old_line;
92   int w, h, stride, old_stride;
93   int x, y;
94
95   data = cairo_image_surface_get_data (surface);
96   old_data = cairo_image_surface_get_data (old_surface);
97
98   w = cairo_image_surface_get_width (surface);
99   h = cairo_image_surface_get_height (surface);
100
101   stride = cairo_image_surface_get_stride (surface);
102   old_stride = cairo_image_surface_get_stride (old_surface);
103
104   for (y = 0; y < h; y++)
105     {
106       line = (guint32 *)data;
107       old_line = (guint32 *)old_data;
108
109       for (x = 0; x < w; x++)
110         {
111           if ((*line & 0xffffff) == (*old_line & 0xffffff))
112             *old_line = 0;
113           else
114             *old_line = *line | 0xff000000;
115           line ++;
116           old_line ++;
117         }
118
119       data += stride;
120       old_data += old_stride;
121     }
122 }
123
124 static guint dirty_flush_id = 0;
125
126 static void
127 window_data_send (BroadwayOutput *output, GdkWindowImplBroadway *impl)
128 {
129   cairo_t *cr;
130
131   if (impl->surface == NULL)
132     return;
133
134   if (impl->last_synced)
135     {
136       diff_surfaces (impl->surface,
137                      impl->last_surface);
138       broadway_output_put_rgba (output, impl->id, 0, 0,
139                                 cairo_image_surface_get_width (impl->last_surface),
140                                 cairo_image_surface_get_height (impl->last_surface),
141                                 cairo_image_surface_get_stride (impl->last_surface),
142                                 cairo_image_surface_get_data (impl->last_surface));
143     }
144   else
145     {
146       impl->last_synced = TRUE;
147       broadway_output_put_rgb (output, impl->id, 0, 0,
148                                cairo_image_surface_get_width (impl->surface),
149                                cairo_image_surface_get_height (impl->surface),
150                                cairo_image_surface_get_stride (impl->surface),
151                                cairo_image_surface_get_data (impl->surface));
152     }
153
154   broadway_output_surface_flush (output, impl->id);
155
156   cr = cairo_create (impl->last_surface);
157   cairo_set_source_surface (cr, impl->surface, 0, 0);
158   cairo_paint (cr);
159   cairo_destroy (cr);
160 }
161
162 static gboolean
163 dirty_flush_idle (gpointer data)
164 {
165   GList *l;
166   GdkBroadwayDisplay *display;
167   BroadwayOutput *output;
168
169   dirty_flush_id = 0;
170
171   display = GDK_BROADWAY_DISPLAY (gdk_display_get_default ());
172   output = display->output;
173   if (output == NULL)
174     return FALSE;
175
176   for (l = display->toplevels; l != NULL; l = l->next)
177     {
178       GdkWindowImplBroadway *impl = l->data;
179
180       if (impl->dirty)
181         {
182           impl->dirty = FALSE;
183           window_data_send (display->output, impl);
184         }
185     }
186
187   gdk_display_flush (GDK_DISPLAY (display));
188
189   return FALSE;
190 }
191
192 static void
193 queue_dirty_flush (GdkBroadwayDisplay *display)
194 {
195   if (dirty_flush_id == 0 && display->output != NULL)
196     dirty_flush_id = gdk_threads_add_idle (dirty_flush_idle, NULL);
197 }
198
199 void
200 _gdk_broadway_resync_windows (void)
201 {
202   GdkBroadwayDisplay *display;
203   GList *l;
204
205   dirty_flush_id = 0;
206
207   display = GDK_BROADWAY_DISPLAY (gdk_display_get_default ());
208
209   /* First create all windows */
210   for (l = display->toplevels; l != NULL; l = l->next)
211     {
212       GdkWindowImplBroadway *impl = l->data;
213       GdkWindow *window;
214
215       window = impl->wrapper;
216
217       if (impl->id == 0)
218         continue; /* Skip root */
219
220       impl->dirty = FALSE;
221       impl->last_synced = FALSE;
222       broadway_output_new_surface (display->output,
223                                    impl->id,
224                                    window->x,
225                                    window->y,
226                                    window->width,
227                                    window->height,
228                                    window->window_type == GDK_WINDOW_TEMP);
229     }
230
231   /* Then do everything that may reference other windows */
232   for (l = display->toplevels; l != NULL; l = l->next)
233     {
234       GdkWindowImplBroadway *impl = l->data;
235
236       if (impl->id == 0)
237         continue; /* Skip root */
238
239       if (impl->transient_for)
240         broadway_output_set_transient_for (display->output, impl->id, impl->transient_for);
241       /* Can't check GDK_WINDOW_IS_MAPPED here, because that doesn't correctly handle
242          withdrawn windows like menus */
243       if (impl->visible)
244         {
245           broadway_output_show_surface (display->output, impl->id);
246           window_data_send (display->output, impl);
247         }
248     }
249
250   gdk_display_flush (GDK_DISPLAY (display));
251 }
252
253 static void
254 gdk_window_impl_broadway_init (GdkWindowImplBroadway *impl)
255 {
256   impl->toplevel_window_type = -1;
257   impl->device_cursor = g_hash_table_new_full (NULL, NULL, NULL,
258                                                (GDestroyNotify) g_object_unref);
259 }
260
261 static void
262 gdk_window_impl_broadway_finalize (GObject *object)
263 {
264   GdkWindow *wrapper;
265   GdkWindowImplBroadway *impl;
266   GdkBroadwayDisplay *broadway_display;
267
268   g_return_if_fail (GDK_IS_WINDOW_IMPL_BROADWAY (object));
269
270   impl = GDK_WINDOW_IMPL_BROADWAY (object);
271
272   wrapper = impl->wrapper;
273
274   _gdk_broadway_window_grab_check_destroy (wrapper);
275
276   broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (impl->wrapper));
277
278   if (broadway_display->mouse_in_toplevel == GDK_WINDOW (wrapper))
279     {
280       /* TODO: Send leave + enter event, update cursors, etc */
281       broadway_display->mouse_in_toplevel = NULL;
282     }
283
284   g_hash_table_remove (broadway_display->id_ht, GINT_TO_POINTER(impl->id));
285
286   if (impl->cursor)
287     g_object_unref (impl->cursor);
288
289   g_hash_table_destroy (impl->device_cursor);
290
291   broadway_display->toplevels = g_list_remove (broadway_display->toplevels, impl);
292
293   G_OBJECT_CLASS (gdk_window_impl_broadway_parent_class)->finalize (object);
294 }
295
296 void
297 _gdk_broadway_screen_init_root_window (GdkScreen * screen)
298 {
299   GdkWindow *window;
300   GdkWindowImplBroadway *impl;
301   GdkBroadwayScreen *broadway_screen;
302
303   broadway_screen = GDK_BROADWAY_SCREEN (screen);
304
305   g_assert (broadway_screen->root_window == NULL);
306
307   broadway_screen->root_window = g_object_new (GDK_TYPE_BROADWAY_WINDOW, NULL);
308
309   window = broadway_screen->root_window;
310   window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_BROADWAY, NULL);
311   window->impl_window = window;
312   window->visual = gdk_screen_get_system_visual (screen);
313
314   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
315
316   impl->screen = screen;
317   impl->wrapper = window;
318
319   window->window_type = GDK_WINDOW_ROOT;
320   window->depth = 24;
321
322   window->x = 0;
323   window->y = 0;
324   window->abs_x = 0;
325   window->abs_y = 0;
326   window->width = gdk_screen_get_width (screen);
327   window->height = gdk_screen_get_height (screen);
328   window->viewable = TRUE;
329
330   _gdk_window_update_size (broadway_screen->root_window);
331 }
332
333 void
334 _gdk_broadway_display_create_window_impl (GdkDisplay    *display,
335                                           GdkWindow     *window,
336                                           GdkWindow     *real_parent,
337                                           GdkScreen     *screen,
338                                           GdkEventMask   event_mask,
339                                           GdkWindowAttr *attributes,
340                                           gint           attributes_mask)
341 {
342   GdkWindowImplBroadway *impl;
343   GdkBroadwayDisplay *broadway_display;
344   static int current_id = 1; /* 0 is the root window */
345
346   broadway_display = GDK_BROADWAY_DISPLAY (display);
347
348   impl = g_object_new (GDK_TYPE_WINDOW_IMPL_BROADWAY, NULL);
349   window->impl = (GdkWindowImpl *)impl;
350   impl->id = current_id++;
351   g_hash_table_insert (broadway_display->id_ht, GINT_TO_POINTER(impl->id), window);
352   impl->wrapper = window;
353
354   impl->screen = screen;
355
356   g_assert (window->window_type == GDK_WINDOW_TOPLEVEL ||
357             window->window_type == GDK_WINDOW_TEMP);
358   g_assert (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT);
359
360   broadway_display->toplevels = g_list_prepend (broadway_display->toplevels, impl);
361
362   if (broadway_display->output)
363     broadway_output_new_surface (broadway_display->output,
364                                  impl->id,
365                                  window->x,
366                                  window->y,
367                                  window->width,
368                                  window->height,
369                                  window->window_type == GDK_WINDOW_TEMP);
370 }
371
372 void
373 _gdk_broadway_window_resize_surface (GdkWindow *window)
374 {
375   GdkWindowImplBroadway *impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
376   cairo_surface_t *old, *last_old;
377
378   if (impl->surface)
379     {
380       old = impl->surface;
381       last_old = impl->last_surface;
382
383       impl->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
384                                                   gdk_window_get_width (impl->wrapper),
385                                                   gdk_window_get_height (impl->wrapper));
386       impl->last_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
387                                                        gdk_window_get_width (impl->wrapper),
388                                                        gdk_window_get_height (impl->wrapper));
389
390       cairo_surface_destroy (old);
391       cairo_surface_destroy (last_old);
392     }
393
394   if (impl->ref_surface)
395     {
396       cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key,
397                                    NULL, NULL);
398       impl->ref_surface = NULL;
399     }
400
401   gdk_window_invalidate_rect (window, NULL, TRUE);
402 }
403
404 static void
405 ref_surface_destroyed (void *data)
406 {
407   GdkWindowImplBroadway *impl = data;
408
409   impl->ref_surface = NULL;
410 }
411
412 static cairo_surface_t *
413 gdk_window_broadway_ref_cairo_surface (GdkWindow *window)
414 {
415   GdkWindowImplBroadway *impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
416   cairo_t *cr;
417   int w, h;
418
419   if (GDK_IS_WINDOW_IMPL_BROADWAY (window) &&
420       GDK_WINDOW_DESTROYED (impl->wrapper))
421     return NULL;
422
423   w = gdk_window_get_width (impl->wrapper);
424   h = gdk_window_get_height (impl->wrapper);
425
426   /* Create actual backing store if missing */
427   if (!impl->surface)
428     {
429       impl->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
430       impl->last_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
431
432       cr = cairo_create (impl->surface);
433       cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
434       cairo_rectangle (cr, 0, 0, w, h);
435       cairo_fill (cr);
436       cairo_destroy (cr);
437
438       cr = cairo_create (impl->last_surface);
439       cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
440       cairo_rectangle (cr, 0, 0, w, h);
441       cairo_fill (cr);
442       cairo_destroy (cr);
443     }
444
445   /* Create a destroyable surface referencing the real one */
446   if (!impl->ref_surface)
447     {
448       impl->ref_surface =
449         cairo_surface_create_for_rectangle (impl->surface,
450                                             0, 0,
451                                             w, h);
452       if (impl->ref_surface)
453         cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key,
454                                      impl, ref_surface_destroyed);
455     }
456   else
457     cairo_surface_reference (impl->ref_surface);
458
459   return impl->ref_surface;
460 }
461
462 static void
463 _gdk_broadway_window_destroy (GdkWindow *window,
464                               gboolean   recursing,
465                               gboolean   foreign_destroy)
466 {
467   GdkWindowImplBroadway *impl;
468   GdkBroadwayDisplay *broadway_display;
469
470   g_return_if_fail (GDK_IS_WINDOW (window));
471
472   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
473
474   _gdk_broadway_selection_window_destroyed (window);
475   _gdk_broadway_window_grab_check_destroy (window);
476
477   if (impl->ref_surface)
478     {
479       cairo_surface_finish (impl->ref_surface);
480       cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key,
481                                    NULL, NULL);
482     }
483
484   if (impl->surface)
485     {
486       cairo_surface_destroy (impl->surface);
487       impl->surface = NULL;
488       cairo_surface_destroy (impl->last_surface);
489       impl->last_surface = NULL;
490     }
491
492   broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window));
493   g_hash_table_remove (broadway_display->id_ht, GINT_TO_POINTER(impl->id));
494
495   if (broadway_display->output)
496     broadway_output_destroy_surface (broadway_display->output,
497                                      impl->id);
498 }
499
500 static cairo_surface_t *
501 gdk_window_broadway_resize_cairo_surface (GdkWindow       *window,
502                                           cairo_surface_t *surface,
503                                           gint             width,
504                                           gint             height)
505 {
506   /* Image surfaces cannot be resized */
507   cairo_surface_destroy (surface);
508
509   return NULL;
510 }
511
512 static void
513 gdk_broadway_window_destroy_foreign (GdkWindow *window)
514 {
515 }
516
517 /* This function is called when the XWindow is really gone.
518  */
519 static void
520 gdk_broadway_window_destroy_notify (GdkWindow *window)
521 {
522   if (!GDK_WINDOW_DESTROYED (window))
523     {
524       if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
525         g_warning ("GdkWindow %p unexpectedly destroyed", window);
526
527       _gdk_window_destroy (window, TRUE);
528     }
529
530   g_object_unref (window);
531 }
532
533 static void
534 gdk_window_broadway_show (GdkWindow *window, gboolean already_mapped)
535 {
536   GdkWindowImplBroadway *impl;
537   GdkBroadwayDisplay *broadway_display;
538
539   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
540   impl->visible = TRUE;
541
542   if (window->event_mask & GDK_STRUCTURE_MASK)
543     _gdk_make_event (GDK_WINDOW (window), GDK_MAP, NULL, FALSE);
544
545   if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
546     _gdk_make_event (GDK_WINDOW (window), GDK_MAP, NULL, FALSE);
547
548   broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window));
549   if (broadway_display->output)
550     {
551       broadway_output_show_surface (broadway_display->output, impl->id);
552       queue_dirty_flush (broadway_display);
553     }
554 }
555
556 static void
557 gdk_window_broadway_hide (GdkWindow *window)
558 {
559   GdkWindowImplBroadway *impl;
560   GdkBroadwayDisplay *broadway_display;
561
562   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
563   impl->visible = FALSE;
564
565   if (window->event_mask & GDK_STRUCTURE_MASK)
566     _gdk_make_event (GDK_WINDOW (window), GDK_UNMAP, NULL, FALSE);
567
568   if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
569     _gdk_make_event (GDK_WINDOW (window), GDK_UNMAP, NULL, FALSE);
570
571   broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window));
572   if (broadway_display->output)
573     {
574       broadway_output_hide_surface (broadway_display->output, impl->id);
575       queue_dirty_flush (broadway_display);
576     }
577
578   if (broadway_display->mouse_in_toplevel == window)
579     {
580       /* TODO: Send leave + enter event, update cursors, etc */
581       broadway_display->mouse_in_toplevel = NULL;
582     }
583
584   _gdk_window_clear_update_area (window);
585 }
586
587 static void
588 gdk_window_broadway_withdraw (GdkWindow *window)
589 {
590   gdk_window_broadway_hide (window);
591 }
592
593 static void
594 gdk_window_broadway_move_resize (GdkWindow *window,
595                                  gboolean   with_move,
596                                  gint       x,
597                                  gint       y,
598                                  gint       width,
599                                  gint       height)
600 {
601   GdkWindowImplBroadway *impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
602   GdkBroadwayDisplay *broadway_display;
603   gboolean changed, size_changed;;
604   gboolean with_resize;
605
606   size_changed = changed = FALSE;
607
608   broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window));
609   if (with_move)
610     {
611       changed = TRUE;
612       window->x = x;
613       window->y = y;
614     }
615
616   with_resize = FALSE;
617   if (width > 0 || height > 0)
618     {
619       with_resize = TRUE;
620       if (width < 1)
621         width = 1;
622
623       if (height < 1)
624         height = 1;
625
626       if (width != window->width ||
627           height != window->height)
628         {
629           changed = TRUE;
630           size_changed = TRUE;
631
632           /* Resize clears the content */
633           impl->dirty = TRUE;
634           impl->last_synced = FALSE;
635
636           window->width = width;
637           window->height = height;
638           _gdk_broadway_window_resize_surface (window);
639         }
640     }
641
642   if (changed)
643     {
644       GdkEvent *event;
645       GList *node;
646
647       if (broadway_display->output != NULL)
648         {
649           broadway_output_move_resize_surface (broadway_display->output,
650                                                impl->id,
651                                                with_move, window->x, window->y,
652                                                with_resize, window->width, window->height);
653           queue_dirty_flush (broadway_display);
654           if (size_changed)
655             window->resize_count++;
656         }
657
658       event = gdk_event_new (GDK_CONFIGURE);
659       event->configure.window = g_object_ref (window);
660       event->configure.x = window->x;
661       event->configure.y = window->y;
662       event->configure.width = window->width;
663       event->configure.height = window->height;
664
665       gdk_event_set_device (event, GDK_DISPLAY_OBJECT (broadway_display)->core_pointer);
666
667       node = _gdk_event_queue_append (GDK_DISPLAY_OBJECT (broadway_display), event);
668       _gdk_windowing_got_event (GDK_DISPLAY_OBJECT (broadway_display), node, event,
669                                 _gdk_display_get_next_serial (GDK_DISPLAY (broadway_display)) - 1);
670     }
671 }
672
673 static gboolean
674 gdk_window_broadway_reparent (GdkWindow *window,
675                               GdkWindow *new_parent,
676                               gint       x,
677                               gint       y)
678 {
679   return FALSE;
680 }
681
682 static void
683 gdk_window_broadway_raise (GdkWindow *window)
684 {
685 }
686
687 static void
688 gdk_window_broadway_restack_under (GdkWindow *window,
689                                    GList *native_siblings /* in requested order, first is bottom-most */)
690 {
691 }
692
693 static void
694 gdk_window_broadway_restack_toplevel (GdkWindow *window,
695                                       GdkWindow *sibling,
696                                       gboolean   above)
697 {
698 }
699
700 static void
701 gdk_window_broadway_lower (GdkWindow *window)
702 {
703 }
704
705
706 static void
707 gdk_broadway_window_focus (GdkWindow *window,
708                            guint32    timestamp)
709 {
710 }
711
712 static void
713 gdk_broadway_window_set_type_hint (GdkWindow        *window,
714                                    GdkWindowTypeHint hint)
715 {
716 }
717
718 static GdkWindowTypeHint
719 gdk_broadway_window_get_type_hint (GdkWindow *window)
720 {
721   return GDK_WINDOW_TYPE_HINT_NORMAL;
722 }
723
724 static void
725 gdk_broadway_window_set_modal_hint (GdkWindow *window,
726                                     gboolean   modal)
727 {
728 }
729
730 static void
731 gdk_broadway_window_set_skip_taskbar_hint (GdkWindow *window,
732                                            gboolean   skips_taskbar)
733 {
734 }
735
736 static void
737 gdk_broadway_window_set_skip_pager_hint (GdkWindow *window,
738                                          gboolean   skips_pager)
739 {
740 }
741
742 static void
743 gdk_broadway_window_set_urgency_hint (GdkWindow *window,
744                                       gboolean   urgent)
745 {
746 }
747
748 static void
749 gdk_broadway_window_set_geometry_hints (GdkWindow         *window,
750                                         const GdkGeometry *geometry,
751                                         GdkWindowHints     geom_mask)
752 {
753 }
754
755 static void
756 gdk_broadway_window_set_title (GdkWindow   *window,
757                                const gchar *title)
758 {
759 }
760
761 static void
762 gdk_broadway_window_set_role (GdkWindow   *window,
763                               const gchar *role)
764 {
765 }
766
767 static void
768 gdk_broadway_window_set_startup_id (GdkWindow   *window,
769                                     const gchar *startup_id)
770 {
771 }
772
773 static void
774 gdk_broadway_window_set_transient_for (GdkWindow *window,
775                                        GdkWindow *parent)
776 {
777   GdkBroadwayDisplay *display;
778   GdkWindowImplBroadway *impl;
779   int parent_id;
780
781   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
782
783   parent_id = 0;
784   if (parent)
785     parent_id = GDK_WINDOW_IMPL_BROADWAY (parent->impl)->id;
786
787   impl->transient_for = parent_id;
788
789   display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (impl->wrapper));
790   if (display->output)
791     {
792       broadway_output_set_transient_for (display->output, impl->id, impl->transient_for);
793       gdk_display_flush (GDK_DISPLAY (display));
794     }
795 }
796
797 static void
798 gdk_window_broadway_set_background (GdkWindow      *window,
799                                     cairo_pattern_t *pattern)
800 {
801   return;
802 }
803
804 static void
805 gdk_window_broadway_set_device_cursor (GdkWindow *window,
806                                        GdkDevice *device,
807                                        GdkCursor *cursor)
808 {
809   GdkWindowImplBroadway *impl;
810
811   g_return_if_fail (GDK_IS_WINDOW (window));
812   g_return_if_fail (GDK_IS_DEVICE (device));
813
814   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
815
816   if (!cursor)
817     g_hash_table_remove (impl->device_cursor, device);
818   else
819     {
820       _gdk_broadway_cursor_update_theme (cursor);
821       g_hash_table_replace (impl->device_cursor,
822                             device, gdk_cursor_ref (cursor));
823     }
824
825   if (!GDK_WINDOW_DESTROYED (window))
826     GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
827 }
828
829 GdkCursor *
830 _gdk_broadway_window_get_cursor (GdkWindow *window)
831 {
832   GdkWindowImplBroadway *impl;
833
834   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
835
836   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
837
838   return impl->cursor;
839 }
840
841 static void
842 gdk_window_broadway_get_geometry (GdkWindow *window,
843                                   gint      *x,
844                                   gint      *y,
845                                   gint      *width,
846                                   gint      *height)
847 {
848   GdkWindowImplBroadway *impl;
849
850   g_return_if_fail (GDK_IS_WINDOW (window));
851
852   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
853
854   /* TODO: These should really roundtrip to the client to get the current data */
855
856   if (x)
857     *x = impl->wrapper->x;
858   if (y)
859     *y = impl->wrapper->y;
860   if (width)
861     *width = impl->wrapper->width;
862   if (height)
863     *height = impl->wrapper->height;
864
865 }
866
867 static gint
868 gdk_window_broadway_get_root_coords (GdkWindow *window,
869                                      gint       x,
870                                      gint       y,
871                                      gint      *root_x,
872                                      gint      *root_y)
873 {
874   GdkWindowImplBroadway *impl;
875
876   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
877
878   if (root_x)
879     *root_x = x + impl->wrapper->x;
880   if (root_y)
881     *root_y = y + impl->wrapper->y;
882
883   return 1;
884 }
885
886 static void
887 gdk_broadway_window_get_root_origin (GdkWindow *window,
888                                      gint      *x,
889                                      gint      *y)
890 {
891   GdkWindowImplBroadway *impl;
892
893   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
894
895   /* TODO: This should take wm frame into account */
896
897   if (x)
898     *x = impl->wrapper->x;
899
900   if (y)
901     *y = impl->wrapper->x;
902 }
903
904 static void
905 gdk_broadway_window_get_frame_extents (GdkWindow    *window,
906                                        GdkRectangle *rect)
907 {
908   g_return_if_fail (rect != NULL);
909
910   /* TODO: This should take wm frame into account */
911
912   rect->x = window->x;
913   rect->y = window->y;
914   rect->width = window->width;
915   rect->height = window->height;
916 }
917
918 static gboolean
919 gdk_window_broadway_get_device_state (GdkWindow       *window,
920                                       GdkDevice       *device,
921                                       gint            *x,
922                                       gint            *y,
923                                       GdkModifierType *mask)
924 {
925   GdkWindow *child;
926
927   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
928
929   if (GDK_WINDOW_DESTROYED (window))
930     return FALSE;
931
932   GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
933                                               NULL, &child,
934                                               NULL, NULL,
935                                               x, y, mask);
936   return child != NULL;
937 }
938
939 static GdkEventMask
940 gdk_window_broadway_get_events (GdkWindow *window)
941 {
942   if (GDK_WINDOW_DESTROYED (window))
943     return 0;
944
945   return 0;
946 }
947
948 static void
949 gdk_window_broadway_set_events (GdkWindow    *window,
950                                 GdkEventMask  event_mask)
951 {
952   if (!GDK_WINDOW_DESTROYED (window))
953     {
954     }
955 }
956
957 static void
958 gdk_window_broadway_shape_combine_region (GdkWindow       *window,
959                                           const cairo_region_t *shape_region,
960                                           gint             offset_x,
961                                           gint             offset_y)
962 {
963 }
964
965 static void
966 gdk_window_broadway_input_shape_combine_region (GdkWindow       *window,
967                                                 const cairo_region_t *shape_region,
968                                                 gint             offset_x,
969                                                 gint             offset_y)
970 {
971 }
972
973
974 static void
975 gdk_broadway_window_set_override_redirect (GdkWindow *window,
976                                            gboolean override_redirect)
977 {
978 }
979
980 static void
981 gdk_broadway_window_set_accept_focus (GdkWindow *window,
982                                       gboolean accept_focus)
983 {
984   accept_focus = accept_focus != FALSE;
985
986   if (window->accept_focus != accept_focus)
987     {
988       window->accept_focus = accept_focus;
989     }
990 }
991
992 static void
993 gdk_broadway_window_set_focus_on_map (GdkWindow *window,
994                                       gboolean focus_on_map)
995 {
996   focus_on_map = focus_on_map != FALSE;
997
998   if (window->focus_on_map != focus_on_map)
999     {
1000       window->focus_on_map = focus_on_map;
1001     }
1002 }
1003
1004
1005 static void
1006 gdk_broadway_window_set_icon_list (GdkWindow *window,
1007                                    GList     *pixbufs)
1008 {
1009 }
1010
1011 static void
1012 gdk_broadway_window_set_icon_name (GdkWindow   *window,
1013                                    const gchar *name)
1014 {
1015   if (GDK_WINDOW_DESTROYED (window) ||
1016       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1017     return;
1018
1019   g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
1020                       GUINT_TO_POINTER (name != NULL));
1021 }
1022
1023 static void
1024 gdk_broadway_window_iconify (GdkWindow *window)
1025 {
1026   if (GDK_WINDOW_DESTROYED (window) ||
1027       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1028     return;
1029 }
1030
1031 static void
1032 gdk_broadway_window_deiconify (GdkWindow *window)
1033 {
1034   if (GDK_WINDOW_DESTROYED (window) ||
1035       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1036     return;
1037 }
1038
1039 static void
1040 gdk_broadway_window_stick (GdkWindow *window)
1041 {
1042   if (GDK_WINDOW_DESTROYED (window) ||
1043       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1044     return;
1045
1046 }
1047
1048 static void
1049 gdk_broadway_window_unstick (GdkWindow *window)
1050 {
1051   if (GDK_WINDOW_DESTROYED (window) ||
1052       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1053     return;
1054
1055 }
1056
1057 static void
1058 gdk_broadway_window_maximize (GdkWindow *window)
1059 {
1060   if (GDK_WINDOW_DESTROYED (window) ||
1061       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1062     return;
1063
1064 }
1065
1066 static void
1067 gdk_broadway_window_unmaximize (GdkWindow *window)
1068 {
1069   if (GDK_WINDOW_DESTROYED (window) ||
1070       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1071     return;
1072
1073 }
1074
1075 static void
1076 gdk_broadway_window_fullscreen (GdkWindow *window)
1077 {
1078   if (GDK_WINDOW_DESTROYED (window) ||
1079       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1080     return;
1081
1082 }
1083
1084 static void
1085 gdk_broadway_window_unfullscreen (GdkWindow *window)
1086 {
1087   if (GDK_WINDOW_DESTROYED (window) ||
1088       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1089     return;
1090
1091 }
1092
1093 static void
1094 gdk_broadway_window_set_keep_above (GdkWindow *window,
1095                                     gboolean   setting)
1096 {
1097   g_return_if_fail (GDK_IS_WINDOW (window));
1098
1099   if (GDK_WINDOW_DESTROYED (window) ||
1100       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1101     return;
1102
1103 }
1104
1105 static void
1106 gdk_broadway_window_set_keep_below (GdkWindow *window, gboolean setting)
1107 {
1108   g_return_if_fail (GDK_IS_WINDOW (window));
1109
1110   if (GDK_WINDOW_DESTROYED (window) ||
1111       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1112     return;
1113
1114 }
1115
1116 static GdkWindow *
1117 gdk_broadway_window_get_group (GdkWindow *window)
1118 {
1119   if (GDK_WINDOW_DESTROYED (window) ||
1120       !WINDOW_IS_TOPLEVEL (window))
1121     return NULL;
1122
1123   return window;
1124 }
1125
1126 static void
1127 gdk_broadway_window_set_group (GdkWindow *window,
1128                                GdkWindow *leader)
1129 {
1130 }
1131
1132 static void
1133 gdk_broadway_window_set_decorations (GdkWindow      *window,
1134                                      GdkWMDecoration decorations)
1135 {
1136   if (GDK_WINDOW_DESTROYED (window) ||
1137       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1138     return;
1139
1140 }
1141
1142 static gboolean
1143 gdk_broadway_window_get_decorations (GdkWindow       *window,
1144                                      GdkWMDecoration *decorations)
1145 {
1146   gboolean result = FALSE;
1147
1148   if (GDK_WINDOW_DESTROYED (window) ||
1149       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1150     return FALSE;
1151
1152   return result;
1153 }
1154
1155 static void
1156 gdk_broadway_window_set_functions (GdkWindow    *window,
1157                                    GdkWMFunction functions)
1158 {
1159   g_return_if_fail (GDK_IS_WINDOW (window));
1160
1161   if (GDK_WINDOW_DESTROYED (window) ||
1162       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1163     return;
1164 }
1165
1166 static cairo_region_t *
1167 gdk_broadway_window_get_shape (GdkWindow *window)
1168 {
1169   return NULL;
1170 }
1171
1172 static cairo_region_t *
1173 gdk_broadway_window_get_input_shape (GdkWindow *window)
1174 {
1175   return NULL;
1176 }
1177
1178
1179 static gboolean
1180 gdk_window_broadway_set_static_gravities (GdkWindow *window,
1181                                           gboolean   use_static)
1182 {
1183   return TRUE;
1184 }
1185
1186 typedef struct _MoveResizeData MoveResizeData;
1187
1188 struct _MoveResizeData
1189 {
1190   GdkDisplay *display;
1191
1192   GdkWindow *moveresize_window;
1193   GdkWindow *moveresize_emulation_window;
1194   gboolean is_resize;
1195   GdkWindowEdge resize_edge;
1196   gint moveresize_button;
1197   gint moveresize_x;
1198   gint moveresize_y;
1199   gint moveresize_orig_x;
1200   gint moveresize_orig_y;
1201   gint moveresize_orig_width;
1202   gint moveresize_orig_height;
1203   long moveresize_process_time;
1204   BroadwayInputMsg *moveresize_pending_event;
1205 };
1206
1207 static MoveResizeData *
1208 get_move_resize_data (GdkDisplay *display,
1209                       gboolean    create)
1210 {
1211   MoveResizeData *mv_resize;
1212   static GQuark move_resize_quark = 0;
1213
1214   if (!move_resize_quark)
1215     move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
1216
1217   mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
1218
1219   if (!mv_resize && create)
1220     {
1221       mv_resize = g_new0 (MoveResizeData, 1);
1222       mv_resize->display = display;
1223
1224       g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
1225     }
1226
1227   return mv_resize;
1228 }
1229
1230 static void
1231 update_pos (MoveResizeData *mv_resize,
1232             gint            new_root_x,
1233             gint            new_root_y)
1234 {
1235   gint dx, dy;
1236
1237   dx = new_root_x - mv_resize->moveresize_x;
1238   dy = new_root_y - mv_resize->moveresize_y;
1239
1240   if (mv_resize->is_resize)
1241     {
1242       gint x, y, w, h;
1243
1244       x = mv_resize->moveresize_orig_x;
1245       y = mv_resize->moveresize_orig_y;
1246
1247       w = mv_resize->moveresize_orig_width;
1248       h = mv_resize->moveresize_orig_height;
1249
1250       switch (mv_resize->resize_edge)
1251         {
1252         case GDK_WINDOW_EDGE_NORTH_WEST:
1253           x += dx;
1254           y += dy;
1255           w -= dx;
1256           h -= dy;
1257           break;
1258         case GDK_WINDOW_EDGE_NORTH:
1259           y += dy;
1260           h -= dy;
1261           break;
1262         case GDK_WINDOW_EDGE_NORTH_EAST:
1263           y += dy;
1264           h -= dy;
1265           w += dx;
1266           break;
1267         case GDK_WINDOW_EDGE_SOUTH_WEST:
1268           h += dy;
1269           x += dx;
1270           w -= dx;
1271           break;
1272         case GDK_WINDOW_EDGE_SOUTH_EAST:
1273           w += dx;
1274           h += dy;
1275           break;
1276         case GDK_WINDOW_EDGE_SOUTH:
1277           h += dy;
1278           break;
1279         case GDK_WINDOW_EDGE_EAST:
1280           w += dx;
1281           break;
1282         case GDK_WINDOW_EDGE_WEST:
1283           x += dx;
1284           w -= dx;
1285           break;
1286         }
1287
1288       x = MAX (x, 0);
1289       y = MAX (y, 0);
1290       w = MAX (w, 1);
1291       h = MAX (h, 1);
1292
1293       gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
1294     }
1295   else
1296     {
1297       gint x, y;
1298
1299       x = mv_resize->moveresize_orig_x + dx;
1300       y = mv_resize->moveresize_orig_y + dy;
1301
1302       gdk_window_move (mv_resize->moveresize_window, x, y);
1303     }
1304 }
1305
1306 static void
1307 finish_drag (MoveResizeData *mv_resize)
1308 {
1309   gdk_window_destroy (mv_resize->moveresize_emulation_window);
1310   mv_resize->moveresize_emulation_window = NULL;
1311   g_object_unref (mv_resize->moveresize_window);
1312   mv_resize->moveresize_window = NULL;
1313
1314   if (mv_resize->moveresize_pending_event)
1315     {
1316       g_free (mv_resize->moveresize_pending_event);
1317       mv_resize->moveresize_pending_event = NULL;
1318     }
1319 }
1320
1321 static gboolean
1322 moveresize_lookahead (GdkDisplay *display,
1323                       MoveResizeData *mv_resize,
1324                       BroadwayInputMsg *event)
1325 {
1326   GdkBroadwayDisplay *broadway_display;
1327   BroadwayInputMsg *message;
1328   GList *l;
1329
1330   broadway_display = GDK_BROADWAY_DISPLAY (display);
1331   for (l = broadway_display->input_messages; l != NULL; l = l->next)
1332     {
1333       message = l->data;
1334       if (message->base.type == 'm')
1335         return FALSE;
1336       if (message->base.type == 'b')
1337         return FALSE;
1338     }
1339
1340   return TRUE;
1341 }
1342
1343 gboolean
1344 _gdk_broadway_moveresize_handle_event (GdkDisplay *display,
1345                                        BroadwayInputMsg *event)
1346 {
1347   guint button_mask = 0;
1348   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
1349
1350   if (!mv_resize || !mv_resize->moveresize_window)
1351     return FALSE;
1352
1353   button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
1354
1355   switch (event->base.type)
1356     {
1357     case 'm':
1358       if (mv_resize->moveresize_window->resize_count > 0)
1359         {
1360           if (mv_resize->moveresize_pending_event)
1361             *mv_resize->moveresize_pending_event = *event;
1362           else
1363             mv_resize->moveresize_pending_event =
1364               g_memdup (event, sizeof (BroadwayInputMsg));
1365
1366           break;
1367         }
1368       if (!moveresize_lookahead (display, mv_resize, event))
1369         break;
1370
1371       update_pos (mv_resize,
1372                   event->pointer.root_x,
1373                   event->pointer.root_y);
1374
1375       /* This should never be triggered in normal cases, but in the
1376        * case where the drag started without an implicit grab being
1377        * in effect, we could miss the release if it occurs before
1378        * we grab the pointer; this ensures that we will never
1379        * get a permanently stuck grab.
1380        */
1381       if ((event->pointer.state & button_mask) == 0)
1382         finish_drag (mv_resize);
1383       break;
1384
1385     case 'B':
1386       update_pos (mv_resize,
1387                   event->pointer.root_x,
1388                   event->pointer.root_y);
1389
1390       if (event->button.button == mv_resize->moveresize_button)
1391         finish_drag (mv_resize);
1392       break;
1393     }
1394   return TRUE;
1395 }
1396
1397 gboolean
1398 _gdk_broadway_moveresize_configure_done (GdkDisplay *display,
1399                                          GdkWindow  *window)
1400 {
1401   BroadwayInputMsg *tmp_event;
1402   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
1403
1404   if (!mv_resize || window != mv_resize->moveresize_window)
1405     return FALSE;
1406
1407   if (mv_resize->moveresize_pending_event)
1408     {
1409       tmp_event = mv_resize->moveresize_pending_event;
1410       mv_resize->moveresize_pending_event = NULL;
1411       _gdk_broadway_moveresize_handle_event (display, tmp_event);
1412       g_free (tmp_event);
1413     }
1414
1415   return TRUE;
1416 }
1417
1418 static void
1419 create_moveresize_window (MoveResizeData *mv_resize,
1420                           guint32         timestamp)
1421 {
1422   GdkWindowAttr attributes;
1423   gint attributes_mask;
1424   GdkGrabStatus status;
1425
1426   g_assert (mv_resize->moveresize_emulation_window == NULL);
1427
1428   attributes.x = -100;
1429   attributes.y = -100;
1430   attributes.width = 10;
1431   attributes.height = 10;
1432   attributes.window_type = GDK_WINDOW_TEMP;
1433   attributes.wclass = GDK_INPUT_ONLY;
1434   attributes.override_redirect = TRUE;
1435   attributes.event_mask = 0;
1436
1437   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
1438
1439   mv_resize->moveresize_emulation_window =
1440     gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
1441                     &attributes,
1442                     attributes_mask);
1443
1444   gdk_window_show (mv_resize->moveresize_emulation_window);
1445
1446   status = gdk_pointer_grab (mv_resize->moveresize_emulation_window,
1447                              FALSE,
1448                              GDK_BUTTON_RELEASE_MASK |
1449                              GDK_POINTER_MOTION_MASK,
1450                              NULL,
1451                              NULL,
1452                              timestamp);
1453
1454   if (status != GDK_GRAB_SUCCESS)
1455     {
1456       /* If this fails, some other client has grabbed the window
1457        * already.
1458        */
1459       finish_drag (mv_resize);
1460     }
1461
1462   mv_resize->moveresize_process_time = 0;
1463 }
1464
1465 static void
1466 gdk_broadway_window_begin_resize_drag (GdkWindow     *window,
1467                                        GdkWindowEdge  edge,
1468                                        GdkDevice     *device,
1469                                        gint           button,
1470                                        gint           root_x,
1471                                        gint           root_y,
1472                                        guint32        timestamp)
1473 {
1474   GdkBroadwayDisplay *broadway_display;
1475   MoveResizeData *mv_resize;
1476
1477   if (GDK_WINDOW_DESTROYED (window) ||
1478       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1479     return;
1480
1481   /* We need a connection to be able to get mouse events, if not, punt */
1482   broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window));
1483   if (!broadway_display->output)
1484     return;
1485
1486   mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
1487
1488   mv_resize->is_resize = TRUE;
1489   mv_resize->moveresize_button = button;
1490   mv_resize->resize_edge = edge;
1491   mv_resize->moveresize_x = root_x;
1492   mv_resize->moveresize_y = root_y;
1493   mv_resize->moveresize_window = g_object_ref (window);
1494
1495   gdk_window_get_origin (mv_resize->moveresize_window,
1496                          &mv_resize->moveresize_orig_x,
1497                          &mv_resize->moveresize_orig_y);
1498   mv_resize->moveresize_orig_width = gdk_window_get_width (window);
1499   mv_resize->moveresize_orig_height = gdk_window_get_height (window);
1500
1501   create_moveresize_window (mv_resize, timestamp);
1502 }
1503
1504 static void
1505 gdk_broadway_window_begin_move_drag (GdkWindow *window,
1506                                      GdkDevice *device,
1507                                      gint       button,
1508                                      gint       root_x,
1509                                      gint       root_y,
1510                                      guint32    timestamp)
1511 {
1512   if (GDK_WINDOW_DESTROYED (window) ||
1513       !WINDOW_IS_TOPLEVEL (window))
1514     return;
1515
1516 }
1517
1518 static void
1519 gdk_broadway_window_enable_synchronized_configure (GdkWindow *window)
1520 {
1521   if (!GDK_IS_WINDOW_IMPL_BROADWAY (window->impl))
1522     return;
1523 }
1524
1525 static void
1526 gdk_broadway_window_configure_finished (GdkWindow *window)
1527 {
1528   if (!WINDOW_IS_TOPLEVEL (window))
1529     return;
1530 }
1531
1532 static gboolean
1533 gdk_broadway_window_beep (GdkWindow *window)
1534 {
1535   return FALSE;
1536 }
1537
1538 static void
1539 gdk_broadway_window_set_opacity (GdkWindow *window,
1540                                  gdouble    opacity)
1541 {
1542   g_return_if_fail (GDK_IS_WINDOW (window));
1543
1544   if (GDK_WINDOW_DESTROYED (window) ||
1545       !WINDOW_IS_TOPLEVEL (window))
1546     return;
1547
1548   if (opacity < 0)
1549     opacity = 0;
1550   else if (opacity > 1)
1551     opacity = 1;
1552 }
1553
1554 static void
1555 gdk_broadway_window_set_composited (GdkWindow *window,
1556                                     gboolean   composited)
1557 {
1558 }
1559
1560 static void
1561 gdk_broadway_window_process_updates_recurse (GdkWindow *window,
1562                                              cairo_region_t *region)
1563 {
1564   GdkWindowImplBroadway *impl;
1565
1566   _gdk_window_process_updates_recurse (window, region);
1567
1568   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
1569   impl->dirty = TRUE;
1570   queue_dirty_flush (GDK_BROADWAY_DISPLAY (gdk_window_get_display (window)));
1571 }
1572
1573 void
1574 _gdk_broadway_display_before_process_all_updates (GdkDisplay *display)
1575 {
1576 }
1577
1578 void
1579 _gdk_broadway_display_after_process_all_updates (GdkDisplay *display)
1580 {
1581 }
1582
1583 gboolean
1584 _gdk_broadway_window_queue_antiexpose (GdkWindow *window,
1585                                        cairo_region_t *area)
1586 {
1587   return TRUE;
1588 }
1589
1590 static void
1591 copy_region (cairo_surface_t *surface,
1592              cairo_region_t *area,
1593              gint            dx,
1594              gint            dy)
1595 {
1596   cairo_t *cr;
1597
1598   cr = cairo_create (surface);
1599
1600   gdk_cairo_region (cr, area);
1601   cairo_clip (cr);
1602
1603   /* NB: This is a self-copy and Cairo doesn't support that yet.
1604    * So we do a litle trick.
1605    */
1606   cairo_push_group (cr);
1607
1608   cairo_set_source_surface (cr, surface, dx, dy);
1609   cairo_paint (cr);
1610
1611   cairo_pop_group_to_source (cr);
1612   cairo_paint (cr);
1613
1614   cairo_destroy (cr);
1615 }
1616
1617 void
1618 _gdk_broadway_window_translate (GdkWindow      *window,
1619                                 cairo_region_t *area,
1620                                 gint            dx,
1621                                 gint            dy)
1622 {
1623   GdkWindowImplBroadway *impl;
1624   GdkBroadwayDisplay *broadway_display;
1625   int n_rects, i;
1626   BroadwayRect *rects;
1627   cairo_rectangle_int_t rect;
1628
1629   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
1630
1631   if (impl->surface)
1632     {
1633       copy_region (impl->surface, area, dx, dy);
1634       broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window));
1635       if (GDK_WINDOW_IMPL_BROADWAY (impl)->last_synced &&
1636           broadway_display->output)
1637         {
1638           copy_region (impl->last_surface, area, dx, dy);
1639           n_rects = cairo_region_num_rectangles (area);
1640           rects = g_new (BroadwayRect, n_rects);
1641           for (i = 0; i < n_rects; i++)
1642             {
1643               cairo_region_get_rectangle (area, i, &rect);
1644               rects[i].x = rect.x;
1645               rects[i].y = rect.y;
1646               rects[i].width = rect.width;
1647               rects[i].height = rect.height;
1648             }
1649           broadway_output_copy_rectangles (broadway_display->output,
1650                                            GDK_WINDOW_IMPL_BROADWAY (impl)->id,
1651                                            rects, n_rects, dx, dy);
1652           queue_dirty_flush (broadway_display);
1653           g_free (rects);
1654         }
1655     }
1656 }
1657
1658 guint32
1659 gdk_broadway_get_last_seen_time (GdkWindow  *window)
1660 {
1661   GdkDisplay *display;
1662
1663   display = gdk_window_get_display (window);
1664   _gdk_broadway_display_consume_all_input (display);
1665   return (guint32) GDK_BROADWAY_DISPLAY (display)->last_seen_time;
1666 }
1667
1668 static void
1669 gdk_window_impl_broadway_class_init (GdkWindowImplBroadwayClass *klass)
1670 {
1671   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1672   GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
1673
1674   object_class->finalize = gdk_window_impl_broadway_finalize;
1675
1676   impl_class->ref_cairo_surface = gdk_window_broadway_ref_cairo_surface;
1677   impl_class->show = gdk_window_broadway_show;
1678   impl_class->hide = gdk_window_broadway_hide;
1679   impl_class->withdraw = gdk_window_broadway_withdraw;
1680   impl_class->set_events = gdk_window_broadway_set_events;
1681   impl_class->get_events = gdk_window_broadway_get_events;
1682   impl_class->raise = gdk_window_broadway_raise;
1683   impl_class->lower = gdk_window_broadway_lower;
1684   impl_class->restack_under = gdk_window_broadway_restack_under;
1685   impl_class->restack_toplevel = gdk_window_broadway_restack_toplevel;
1686   impl_class->move_resize = gdk_window_broadway_move_resize;
1687   impl_class->set_background = gdk_window_broadway_set_background;
1688   impl_class->reparent = gdk_window_broadway_reparent;
1689   impl_class->set_device_cursor = gdk_window_broadway_set_device_cursor;
1690   impl_class->get_geometry = gdk_window_broadway_get_geometry;
1691   impl_class->get_root_coords = gdk_window_broadway_get_root_coords;
1692   impl_class->get_device_state = gdk_window_broadway_get_device_state;
1693   impl_class->shape_combine_region = gdk_window_broadway_shape_combine_region;
1694   impl_class->input_shape_combine_region = gdk_window_broadway_input_shape_combine_region;
1695   impl_class->set_static_gravities = gdk_window_broadway_set_static_gravities;
1696   impl_class->queue_antiexpose = _gdk_broadway_window_queue_antiexpose;
1697   impl_class->translate = _gdk_broadway_window_translate;
1698   impl_class->destroy = _gdk_broadway_window_destroy;
1699   impl_class->destroy_foreign = gdk_broadway_window_destroy_foreign;
1700   impl_class->resize_cairo_surface = gdk_window_broadway_resize_cairo_surface;
1701   impl_class->get_shape = gdk_broadway_window_get_shape;
1702   impl_class->get_input_shape = gdk_broadway_window_get_input_shape;
1703   impl_class->beep = gdk_broadway_window_beep;
1704
1705   impl_class->focus = gdk_broadway_window_focus;
1706   impl_class->set_type_hint = gdk_broadway_window_set_type_hint;
1707   impl_class->get_type_hint = gdk_broadway_window_get_type_hint;
1708   impl_class->set_modal_hint = gdk_broadway_window_set_modal_hint;
1709   impl_class->set_skip_taskbar_hint = gdk_broadway_window_set_skip_taskbar_hint;
1710   impl_class->set_skip_pager_hint = gdk_broadway_window_set_skip_pager_hint;
1711   impl_class->set_urgency_hint = gdk_broadway_window_set_urgency_hint;
1712   impl_class->set_geometry_hints = gdk_broadway_window_set_geometry_hints;
1713   impl_class->set_title = gdk_broadway_window_set_title;
1714   impl_class->set_role = gdk_broadway_window_set_role;
1715   impl_class->set_startup_id = gdk_broadway_window_set_startup_id;
1716   impl_class->set_transient_for = gdk_broadway_window_set_transient_for;
1717   impl_class->get_root_origin = gdk_broadway_window_get_root_origin;
1718   impl_class->get_frame_extents = gdk_broadway_window_get_frame_extents;
1719   impl_class->set_override_redirect = gdk_broadway_window_set_override_redirect;
1720   impl_class->set_accept_focus = gdk_broadway_window_set_accept_focus;
1721   impl_class->set_focus_on_map = gdk_broadway_window_set_focus_on_map;
1722   impl_class->set_icon_list = gdk_broadway_window_set_icon_list;
1723   impl_class->set_icon_name = gdk_broadway_window_set_icon_name;
1724   impl_class->iconify = gdk_broadway_window_iconify;
1725   impl_class->deiconify = gdk_broadway_window_deiconify;
1726   impl_class->stick = gdk_broadway_window_stick;
1727   impl_class->unstick = gdk_broadway_window_unstick;
1728   impl_class->maximize = gdk_broadway_window_maximize;
1729   impl_class->unmaximize = gdk_broadway_window_unmaximize;
1730   impl_class->fullscreen = gdk_broadway_window_fullscreen;
1731   impl_class->unfullscreen = gdk_broadway_window_unfullscreen;
1732   impl_class->set_keep_above = gdk_broadway_window_set_keep_above;
1733   impl_class->set_keep_below = gdk_broadway_window_set_keep_below;
1734   impl_class->get_group = gdk_broadway_window_get_group;
1735   impl_class->set_group = gdk_broadway_window_set_group;
1736   impl_class->set_decorations = gdk_broadway_window_set_decorations;
1737   impl_class->get_decorations = gdk_broadway_window_get_decorations;
1738   impl_class->set_functions = gdk_broadway_window_set_functions;
1739   impl_class->set_functions = gdk_broadway_window_set_functions;
1740   impl_class->begin_resize_drag = gdk_broadway_window_begin_resize_drag;
1741   impl_class->begin_move_drag = gdk_broadway_window_begin_move_drag;
1742   impl_class->enable_synchronized_configure = gdk_broadway_window_enable_synchronized_configure;
1743   impl_class->configure_finished = gdk_broadway_window_configure_finished;
1744   impl_class->set_opacity = gdk_broadway_window_set_opacity;
1745   impl_class->set_composited = gdk_broadway_window_set_composited;
1746   impl_class->destroy_notify = gdk_broadway_window_destroy_notify;
1747   impl_class->register_dnd = _gdk_broadway_window_register_dnd;
1748   impl_class->drag_begin = _gdk_broadway_window_drag_begin;
1749   impl_class->process_updates_recurse = gdk_broadway_window_process_updates_recurse;
1750   impl_class->sync_rendering = _gdk_broadway_window_sync_rendering;
1751   impl_class->simulate_key = _gdk_broadway_window_simulate_key;
1752   impl_class->simulate_button = _gdk_broadway_window_simulate_button;
1753   impl_class->get_property = _gdk_broadway_window_get_property;
1754   impl_class->change_property = _gdk_broadway_window_change_property;
1755   impl_class->delete_property = _gdk_broadway_window_delete_property;
1756   impl_class->get_drag_protocol = _gdk_broadway_window_get_drag_protocol;
1757 }