]> Pileus Git - ~andy/gtk/blob - gdk/broadway/gdkwindow-broadway.c
[broadway] Make broadway build with new gdk-backend setup
[~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, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "config.h"
29
30 #include "gdkwindow-broadway.h"
31 #include "gdkscreen-broadway.h"
32
33 #include "gdkwindow.h"
34 #include "gdkwindowimpl.h"
35 #include "gdkdisplay-broadway.h"
36 #include "gdkprivate-broadway.h"
37 #include "gdkinternals.h"
38 #include "gdkdeviceprivate.h"
39 #include "gdkeventsource.h"
40
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <netinet/in.h>
45 #include <unistd.h>
46
47 /* Forward declarations */
48 static void     gdk_window_broadway_set_background     (GdkWindow      *window,
49                                                    cairo_pattern_t *pattern);
50
51 static void        gdk_window_impl_broadway_finalize   (GObject            *object);
52
53 static const cairo_user_data_key_t gdk_broadway_cairo_key;
54
55 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
56   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
57    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
58
59 #define WINDOW_IS_TOPLEVEL(window)                   \
60   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
61    GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
62    GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
63
64 struct _GdkBroadwayWindow {
65   GdkWindow parent;
66 };
67
68 struct _GdkBroadwayWindowClass {
69   GdkWindowClass parent_class;
70 };
71
72 G_DEFINE_TYPE (GdkBroadwayWindow, gdk_broadway_window, GDK_TYPE_WINDOW)
73
74 static void
75 gdk_broadway_window_class_init (GdkBroadwayWindowClass *broadway_window_class)
76 {
77 }
78
79 static void
80 gdk_broadway_window_init (GdkBroadwayWindow *broadway_window)
81 {
82 }
83
84 G_DEFINE_TYPE (GdkWindowImplBroadway,
85                gdk_window_impl_broadway,
86                GDK_TYPE_WINDOW_IMPL)
87
88 static void
89 diff_surfaces (cairo_surface_t *surface,
90                cairo_surface_t *old_surface)
91 {
92   guint8 *data, *old_data;
93   guint32 *line, *old_line;
94   int w, h, stride, old_stride;
95   int x, y;
96
97   data = cairo_image_surface_get_data (surface);
98   old_data = cairo_image_surface_get_data (old_surface);
99
100   w = cairo_image_surface_get_width (surface);
101   h = cairo_image_surface_get_height (surface);
102
103   stride = cairo_image_surface_get_stride (surface);
104   old_stride = cairo_image_surface_get_stride (old_surface);
105
106   for (y = 0; y < h; y++)
107     {
108       line = (guint32 *)data;
109       old_line = (guint32 *)old_data;
110
111       for (x = 0; x < w; x++)
112         {
113           if ((*line & 0xffffff) == (*old_line & 0xffffff))
114             *old_line = 0;
115           else
116             *old_line = *line | 0xff000000;
117           line ++;
118           old_line ++;
119         }
120
121       data += stride;
122       old_data += old_stride;
123     }
124 }
125
126 static guint dirty_flush_id = 0;
127
128 static void
129 window_data_send (BroadwayOutput *output, GdkWindowImplBroadway *impl)
130 {
131   cairo_t *cr;
132
133   if (impl->surface == NULL)
134     return;
135
136   if (impl->last_synced)
137     {
138       diff_surfaces (impl->surface,
139                      impl->last_surface);
140       broadway_output_put_rgba (output, impl->id, 0, 0,
141                                 cairo_image_surface_get_width (impl->last_surface),
142                                 cairo_image_surface_get_height (impl->last_surface),
143                                 cairo_image_surface_get_stride (impl->last_surface),
144                                 cairo_image_surface_get_data (impl->last_surface));
145     }
146   else
147     {
148       impl->last_synced = TRUE;
149       broadway_output_put_rgb (output, impl->id, 0, 0,
150                                cairo_image_surface_get_width (impl->surface),
151                                cairo_image_surface_get_height (impl->surface),
152                                cairo_image_surface_get_stride (impl->surface),
153                                cairo_image_surface_get_data (impl->surface));
154     }
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   if (!broadway_output_flush (display->output))
188     {
189       broadway_output_free (display->output);
190       display->output = NULL;
191     }
192
193   return FALSE;
194 }
195
196 static void
197 queue_dirty_flush (GdkBroadwayDisplay *display)
198 {
199   if (dirty_flush_id == 0 && display->output != NULL)
200     dirty_flush_id = gdk_threads_add_idle (dirty_flush_idle, NULL);
201 }
202
203 void
204 _gdk_broadway_resync_windows (void)
205 {
206   GdkBroadwayDisplay *display;
207   GList *l;
208
209   dirty_flush_id = 0;
210
211   display = GDK_BROADWAY_DISPLAY (gdk_display_get_default ());
212
213   for (l = display->toplevels; l != NULL; l = l->next)
214     {
215       GdkWindowImplBroadway *impl = l->data;
216       GdkWindow *window;
217
218       window = impl->wrapper;
219
220       if (impl->id == 0)
221         continue; /* Skip root */
222
223       impl->dirty = FALSE;
224       impl->last_synced = FALSE;
225       broadway_output_new_surface (display->output,
226                                    impl->id,
227                                    window->x,
228                                    window->y,
229                                    window->width,
230                                    window->height);
231       if (GDK_WINDOW_IS_MAPPED (window))
232         {
233           broadway_output_show_surface (display->output, impl->id);
234           window_data_send (display->output, impl);
235         }
236     }
237
238   broadway_output_flush (display->output);
239 }
240
241 static void
242 gdk_window_impl_broadway_init (GdkWindowImplBroadway *impl)
243 {
244   impl->toplevel_window_type = -1;
245   impl->device_cursor = g_hash_table_new_full (NULL, NULL, NULL,
246                                                (GDestroyNotify) gdk_cursor_unref);
247 }
248
249 static void
250 gdk_window_impl_broadway_finalize (GObject *object)
251 {
252   GdkWindow *wrapper;
253   GdkWindowImplBroadway *impl;
254   GdkBroadwayDisplay *broadway_display;
255
256   g_return_if_fail (GDK_IS_WINDOW_IMPL_BROADWAY (object));
257
258   impl = GDK_WINDOW_IMPL_BROADWAY (object);
259
260   wrapper = impl->wrapper;
261
262   broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (impl->wrapper));
263
264   if (broadway_display->mouse_in_toplevel == GDK_WINDOW (wrapper))
265     {
266       /* TODO: Send leave + enter event, update cursors, etc */
267       broadway_display->mouse_in_toplevel = NULL;
268     }
269
270   g_hash_table_remove (broadway_display->id_ht, GINT_TO_POINTER(impl->id));
271
272   if (impl->cursor)
273     gdk_cursor_unref (impl->cursor);
274
275   g_hash_table_destroy (impl->device_cursor);
276
277   broadway_display->toplevels = g_list_remove (broadway_display->toplevels, impl);
278
279   G_OBJECT_CLASS (gdk_window_impl_broadway_parent_class)->finalize (object);
280 }
281
282 void
283 _gdk_broadway_screen_init_root_window (GdkScreen * screen)
284 {
285   GdkWindow *window;
286   GdkWindowImplBroadway *impl;
287   GdkBroadwayScreen *broadway_screen;
288
289   broadway_screen = GDK_BROADWAY_SCREEN (screen);
290
291   g_assert (broadway_screen->root_window == NULL);
292
293   broadway_screen->root_window = g_object_new (GDK_TYPE_BROADWAY_WINDOW, NULL);
294
295   window = broadway_screen->root_window;
296   window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_BROADWAY, NULL);
297   window->impl_window = window;
298   window->visual = gdk_screen_get_system_visual (screen);
299
300   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
301
302   impl->screen = screen;
303   impl->wrapper = window;
304
305   window->window_type = GDK_WINDOW_ROOT;
306   window->depth = 24;
307
308   window->x = 0;
309   window->y = 0;
310   window->abs_x = 0;
311   window->abs_y = 0;
312   window->width = gdk_screen_get_width (screen);
313   window->height = gdk_screen_get_height (screen);
314   window->viewable = TRUE;
315
316   _gdk_window_update_size (broadway_screen->root_window);
317 }
318
319 void
320 _gdk_broadway_display_create_window_impl (GdkDisplay    *display,
321                                           GdkWindow     *window,
322                                           GdkWindow     *real_parent,
323                                           GdkScreen     *screen,
324                                           GdkEventMask   event_mask,
325                                           GdkWindowAttr *attributes,
326                                           gint           attributes_mask)
327 {
328   GdkWindowImplBroadway *impl;
329   GdkBroadwayScreen *broadway_screen;
330   GdkBroadwayDisplay *broadway_display;
331   static int current_id = 1; /* 0 is the root window */
332
333   broadway_display = GDK_BROADWAY_DISPLAY (display);
334   broadway_screen = GDK_BROADWAY_SCREEN (screen);
335
336   impl = g_object_new (GDK_TYPE_WINDOW_IMPL_BROADWAY, NULL);
337   window->impl = (GdkWindowImpl *)impl;
338   impl->id = current_id++;
339   g_hash_table_insert (broadway_display->id_ht, GINT_TO_POINTER(impl->id), window);
340   impl->wrapper = window;
341
342   impl->screen = screen;
343
344   g_assert (window->window_type == GDK_WINDOW_TOPLEVEL ||
345             window->window_type == GDK_WINDOW_TEMP);
346   g_assert (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT);
347
348   broadway_display->toplevels = g_list_prepend (broadway_display->toplevels, impl);
349
350   /* Instead of window manager placement we have this mini hack
351      so that the main/first window is not covered in the demos. */
352   if (impl->id > 1 && window->window_type == GDK_WINDOW_TOPLEVEL)
353     {
354       window->x = 100;
355       window->y = 20;
356     }
357
358   if (broadway_display->output)
359     broadway_output_new_surface (broadway_display->output,
360                                  impl->id,
361                                  window->x,
362                                  window->y,
363                                  window->width,
364                                  window->height);
365 }
366
367 static void
368 resize_surface (GdkWindow *window)
369 {
370   GdkWindowImplBroadway *impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
371   cairo_surface_t *old, *last_old;
372
373   if (impl->surface)
374     {
375       old = impl->surface;
376       last_old = impl->last_surface;
377
378       impl->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
379                                                   gdk_window_get_width (impl->wrapper),
380                                                   gdk_window_get_height (impl->wrapper));
381       impl->last_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
382                                                        gdk_window_get_width (impl->wrapper),
383                                                        gdk_window_get_height (impl->wrapper));
384
385       { cairo_t *cr;
386       cr = cairo_create (impl->surface);
387       cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
388       cairo_rectangle (cr, 0, 0, 1000, 1000);
389       cairo_fill (cr);
390       cairo_destroy (cr);
391       }
392
393       cairo_surface_destroy (old);
394       cairo_surface_destroy (last_old);
395     }
396
397   if (impl->ref_surface)
398     {
399       cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key,
400                                    NULL, NULL);
401       impl->ref_surface = NULL;
402     }
403 }
404
405 static void
406 ref_surface_destroyed (void *data)
407 {
408   GdkWindowImplBroadway *impl = data;
409
410   impl->ref_surface = NULL;
411 }
412
413 static cairo_surface_t *
414 gdk_window_broadway_ref_cairo_surface (GdkWindow *window)
415 {
416   GdkWindowImplBroadway *impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
417   cairo_t *cr;
418   int w, h;
419
420   if (GDK_IS_WINDOW_IMPL_BROADWAY (window) &&
421       GDK_WINDOW_DESTROYED (impl->wrapper))
422     return NULL;
423
424   w = gdk_window_get_width (impl->wrapper);
425   h = gdk_window_get_height (impl->wrapper);
426
427   /* Create actual backing store if missing */
428   if (!impl->surface)
429     {
430       impl->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
431       impl->last_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
432
433       cr = cairo_create (impl->surface);
434       cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
435       cairo_rectangle (cr, 0, 0, w, h);
436       cairo_fill (cr);
437       cairo_destroy (cr);
438
439       cr = cairo_create (impl->last_surface);
440       cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
441       cairo_rectangle (cr, 0, 0, w, h);
442       cairo_fill (cr);
443       cairo_destroy (cr);
444     }
445
446   /* Create a destroyable surface referencing the real one */
447   if (!impl->ref_surface)
448     {
449       impl->ref_surface =
450         cairo_surface_create_for_rectangle (impl->surface,
451                                             0, 0,
452                                             w, h);
453       if (impl->ref_surface)
454         cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key,
455                                      impl, ref_surface_destroyed);
456     }
457   else
458     cairo_surface_reference (impl->ref_surface);
459
460   return impl->ref_surface;
461 }
462
463 static void
464 _gdk_broadway_window_destroy (GdkWindow *window,
465                               gboolean   recursing,
466                               gboolean   foreign_destroy)
467 {
468   GdkWindowImplBroadway *impl;
469   GdkBroadwayDisplay *broadway_display;
470
471   g_return_if_fail (GDK_IS_WINDOW (window));
472
473   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
474
475   _gdk_selection_window_destroyed (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   if (broadway_display->output)
494     broadway_output_destroy_surface (broadway_display->output,
495                                      impl->id);
496 }
497
498 static cairo_surface_t *
499 gdk_window_broadway_resize_cairo_surface (GdkWindow       *window,
500                                           cairo_surface_t *surface,
501                                           gint             width,
502                                           gint             height)
503 {
504   /* Image surfaces cannot be resized */
505   cairo_surface_destroy (surface);
506
507   return NULL;
508 }
509
510 static void
511 gdk_broadway_window_destroy_foreign (GdkWindow *window)
512 {
513 }
514
515 /* This function is called when the XWindow is really gone.
516  */
517 static void
518 gdk_broadway_window_destroy_notify (GdkWindow *window)
519 {
520   GdkWindowImplBroadway *window_impl;
521
522   window_impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
523
524   if (!GDK_WINDOW_DESTROYED (window))
525     {
526       if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
527         g_warning ("GdkWindow %p unexpectedly destroyed", window);
528
529       _gdk_window_destroy (window, TRUE);
530     }
531
532   g_object_unref (window);
533 }
534
535 static void
536 gdk_window_broadway_show (GdkWindow *window, gboolean already_mapped)
537 {
538   GdkWindowImplBroadway *impl;
539   GdkBroadwayDisplay *broadway_display;
540
541   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
542
543   if (window->event_mask & GDK_STRUCTURE_MASK)
544     _gdk_make_event (GDK_WINDOW (window), GDK_MAP, NULL, FALSE);
545
546   if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
547     _gdk_make_event (GDK_WINDOW (window), GDK_MAP, NULL, FALSE);
548
549   broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window));
550   if (broadway_display->output)
551     {
552       broadway_output_show_surface (broadway_display->output, impl->id);
553       queue_dirty_flush (broadway_display);
554     }
555 }
556
557 static void
558 gdk_window_broadway_hide (GdkWindow *window)
559 {
560   GdkWindowImplBroadway *impl;
561   GdkBroadwayDisplay *broadway_display;
562
563   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
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;
604
605   changed = FALSE;
606
607   broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window));
608   if (with_move)
609     {
610       changed = TRUE;
611       window->x = x;
612       window->y = y;
613       if (broadway_display->output != NULL)
614         {
615           broadway_output_move_surface (broadway_display->output,
616                                         impl->id, x, y);
617           queue_dirty_flush (broadway_display);
618         }
619     }
620
621
622   if (width > 0 || height > 0)
623     {
624       if (width < 1)
625         width = 1;
626
627       if (height < 1)
628         height = 1;
629
630       if (width != window->width ||
631           height != window->height)
632         {
633           changed = TRUE;
634
635           /* Resize clears the content */
636           impl->dirty = TRUE;
637           impl->last_synced = FALSE;
638
639           broadway_output_resize_surface (broadway_display->output,
640                                           impl->id, width, height);
641           queue_dirty_flush (broadway_display);
642
643           window->width = width;
644           window->height = height;
645           resize_surface (window);
646           gdk_window_invalidate_rect (window, NULL, TRUE);
647         }
648     }
649
650   if (changed)
651     {
652       GdkEvent *event;
653       GList *node;
654
655       event = gdk_event_new (GDK_CONFIGURE);
656       event->configure.window = g_object_ref (window);
657       event->configure.x = window->x;
658       event->configure.y = window->y;
659       event->configure.width = window->width;
660       event->configure.height = window->height;
661
662       gdk_event_set_device (event, GDK_DISPLAY_OBJECT (broadway_display)->core_pointer);
663
664       node = _gdk_event_queue_append (GDK_DISPLAY_OBJECT (broadway_display), event);
665       _gdk_windowing_got_event (GDK_DISPLAY_OBJECT (broadway_display), node, event, 0);
666     }
667 }
668
669 static gboolean
670 gdk_window_broadway_reparent (GdkWindow *window,
671                          GdkWindow *new_parent,
672                          gint       x,
673                          gint       y)
674 {
675   return FALSE;
676 }
677
678 static void
679 gdk_window_broadway_raise (GdkWindow *window)
680 {
681 }
682
683 static void
684 gdk_window_broadway_restack_under (GdkWindow *window,
685                               GList *native_siblings /* in requested order, first is bottom-most */)
686 {
687 }
688
689 static void
690 gdk_window_broadway_restack_toplevel (GdkWindow *window,
691                                  GdkWindow *sibling,
692                                  gboolean   above)
693 {
694 }
695
696 static void
697 gdk_window_broadway_lower (GdkWindow *window)
698 {
699 }
700
701
702 static void
703 gdk_broadway_window_focus (GdkWindow *window,
704                            guint32    timestamp)
705 {
706 }
707
708 static void
709 gdk_broadway_window_set_type_hint (GdkWindow        *window,
710                                    GdkWindowTypeHint hint)
711 {
712 }
713
714 static GdkWindowTypeHint
715 gdk_broadway_window_get_type_hint (GdkWindow *window)
716 {
717   return GDK_WINDOW_TYPE_HINT_NORMAL;
718 }
719
720 static void
721 gdk_broadway_window_set_modal_hint (GdkWindow *window,
722                                     gboolean   modal)
723 {
724 }
725
726 static void
727 gdk_broadway_window_set_skip_taskbar_hint (GdkWindow *window,
728                                            gboolean   skips_taskbar)
729 {
730 }
731
732 static void
733 gdk_broadway_window_set_skip_pager_hint (GdkWindow *window,
734                                          gboolean   skips_pager)
735 {
736 }
737
738 static void
739 gdk_broadway_window_set_urgency_hint (GdkWindow *window,
740                                       gboolean   urgent)
741 {
742 }
743
744 static void
745 gdk_broadway_window_set_geometry_hints (GdkWindow         *window,
746                                         const GdkGeometry *geometry,
747                                         GdkWindowHints     geom_mask)
748 {
749 }
750
751 static void
752 gdk_broadway_window_set_title (GdkWindow   *window,
753                                const gchar *title)
754 {
755 }
756
757 static void
758 gdk_broadway_window_set_role (GdkWindow   *window,
759                               const gchar *role)
760 {
761 }
762
763 static void
764 gdk_broadway_window_set_startup_id (GdkWindow   *window,
765                                     const gchar *startup_id)
766 {
767 }
768
769 static void
770 gdk_broadway_window_set_transient_for (GdkWindow *window,
771                                        GdkWindow *parent)
772 {
773 }
774
775 static void
776 gdk_window_broadway_set_background (GdkWindow      *window,
777                                     cairo_pattern_t *pattern)
778 {
779   return;
780 }
781
782 static void
783 gdk_window_broadway_set_device_cursor (GdkWindow *window,
784                                        GdkDevice *device,
785                                        GdkCursor *cursor)
786 {
787   GdkWindowImplBroadway *impl;
788
789   g_return_if_fail (GDK_IS_WINDOW (window));
790   g_return_if_fail (GDK_IS_DEVICE (device));
791
792   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
793
794   if (!cursor)
795     g_hash_table_remove (impl->device_cursor, device);
796   else
797     {
798       _gdk_broadway_cursor_update_theme (cursor);
799       g_hash_table_replace (impl->device_cursor,
800                             device, gdk_cursor_ref (cursor));
801     }
802
803   if (!GDK_WINDOW_DESTROYED (window))
804     GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
805 }
806
807 GdkCursor *
808 _gdk_broadway_window_get_cursor (GdkWindow *window)
809 {
810   GdkWindowImplBroadway *impl;
811
812   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
813
814   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
815
816   return impl->cursor;
817 }
818
819 static void
820 gdk_window_broadway_get_geometry (GdkWindow *window,
821                                   gint      *x,
822                                   gint      *y,
823                                   gint      *width,
824                                   gint      *height)
825 {
826 }
827
828 static gint
829 gdk_window_broadway_get_root_coords (GdkWindow *window,
830                                 gint       x,
831                                 gint       y,
832                                 gint      *root_x,
833                                 gint      *root_y)
834 {
835   if (root_x)
836     *root_x = x;
837   if (root_y)
838     *root_y = y;
839
840   return 1;
841 }
842
843 static void
844 gdk_broadway_window_get_root_origin (GdkWindow *window,
845                                      gint      *x,
846                                      gint      *y)
847 {
848   if (x)
849     *x = 0;
850
851   if (y)
852     *y = 0;
853 }
854
855 static void
856 gdk_broadway_window_get_frame_extents (GdkWindow    *window,
857                                        GdkRectangle *rect)
858 {
859   g_return_if_fail (rect != NULL);
860
861   rect->x = window->x;
862   rect->y = window->y;
863   rect->width = window->width;
864   rect->height = window->height;
865 }
866
867 static gboolean
868 gdk_window_broadway_get_device_state (GdkWindow       *window,
869                                       GdkDevice       *device,
870                                       gint            *x,
871                                       gint            *y,
872                                       GdkModifierType *mask)
873 {
874   *x = 0;
875   *y = 0;
876   *mask = 0;
877   return FALSE;
878 }
879
880 static GdkEventMask
881 gdk_window_broadway_get_events (GdkWindow *window)
882 {
883   if (GDK_WINDOW_DESTROYED (window))
884     return 0;
885
886   return 0;
887 }
888
889 static void
890 gdk_window_broadway_set_events (GdkWindow    *window,
891                                 GdkEventMask  event_mask)
892 {
893   if (!GDK_WINDOW_DESTROYED (window))
894     {
895     }
896 }
897
898 static void
899 gdk_window_broadway_shape_combine_region (GdkWindow       *window,
900                                           const cairo_region_t *shape_region,
901                                           gint             offset_x,
902                                           gint             offset_y)
903 {
904 }
905
906 static void
907 gdk_window_broadway_input_shape_combine_region (GdkWindow       *window,
908                                                 const cairo_region_t *shape_region,
909                                                 gint             offset_x,
910                                                 gint             offset_y)
911 {
912 }
913
914
915 static void
916 gdk_broadway_window_set_override_redirect (GdkWindow *window,
917                                            gboolean override_redirect)
918 {
919 }
920
921 static void
922 gdk_broadway_window_set_accept_focus (GdkWindow *window,
923                                       gboolean accept_focus)
924 {
925   accept_focus = accept_focus != FALSE;
926
927   if (window->accept_focus != accept_focus)
928     {
929       window->accept_focus = accept_focus;
930     }
931 }
932
933 static void
934 gdk_broadway_window_set_focus_on_map (GdkWindow *window,
935                                       gboolean focus_on_map)
936 {
937   focus_on_map = focus_on_map != FALSE;
938
939   if (window->focus_on_map != focus_on_map)
940     {
941       window->focus_on_map = focus_on_map;
942     }
943 }
944
945
946 static void
947 gdk_broadway_window_set_icon_list (GdkWindow *window,
948                                    GList     *pixbufs)
949 {
950 }
951
952 static void
953 gdk_broadway_window_set_icon_name (GdkWindow   *window, 
954                                    const gchar *name)
955 {
956   GdkDisplay *display;
957
958   if (GDK_WINDOW_DESTROYED (window) ||
959       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
960     return;
961
962   display = gdk_window_get_display (window);
963
964   g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
965                       GUINT_TO_POINTER (name != NULL));
966 }
967
968 static void
969 gdk_broadway_window_iconify (GdkWindow *window)
970 {
971   if (GDK_WINDOW_DESTROYED (window) ||
972       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
973     return;
974 }
975
976 static void
977 gdk_broadway_window_deiconify (GdkWindow *window)
978 {
979   if (GDK_WINDOW_DESTROYED (window) ||
980       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
981     return;
982 }
983
984 static void
985 gdk_broadway_window_stick (GdkWindow *window)
986 {
987   if (GDK_WINDOW_DESTROYED (window) ||
988       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
989     return;
990
991 }
992
993 static void
994 gdk_broadway_window_unstick (GdkWindow *window)
995 {
996   if (GDK_WINDOW_DESTROYED (window) ||
997       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
998     return;
999
1000 }
1001
1002 static void
1003 gdk_broadway_window_maximize (GdkWindow *window)
1004 {
1005   if (GDK_WINDOW_DESTROYED (window) ||
1006       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1007     return;
1008
1009 }
1010
1011 static void
1012 gdk_broadway_window_unmaximize (GdkWindow *window)
1013 {
1014   if (GDK_WINDOW_DESTROYED (window) ||
1015       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1016     return;
1017
1018 }
1019
1020 static void
1021 gdk_broadway_window_fullscreen (GdkWindow *window)
1022 {
1023   if (GDK_WINDOW_DESTROYED (window) ||
1024       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1025     return;
1026
1027 }
1028
1029 static void
1030 gdk_broadway_window_unfullscreen (GdkWindow *window)
1031 {
1032   if (GDK_WINDOW_DESTROYED (window) ||
1033       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1034     return;
1035
1036 }
1037
1038 static void
1039 gdk_broadway_window_set_keep_above (GdkWindow *window,
1040                                     gboolean   setting)
1041 {
1042   g_return_if_fail (GDK_IS_WINDOW (window));
1043
1044   if (GDK_WINDOW_DESTROYED (window) ||
1045       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1046     return;
1047
1048 }
1049
1050 static void
1051 gdk_broadway_window_set_keep_below (GdkWindow *window, gboolean setting)
1052 {
1053   g_return_if_fail (GDK_IS_WINDOW (window));
1054
1055   if (GDK_WINDOW_DESTROYED (window) ||
1056       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1057     return;
1058
1059 }
1060
1061 static GdkWindow *
1062 gdk_broadway_window_get_group (GdkWindow *window)
1063 {
1064   if (GDK_WINDOW_DESTROYED (window) ||
1065       !WINDOW_IS_TOPLEVEL (window))
1066     return NULL;
1067
1068   return window;
1069 }
1070
1071 static void
1072 gdk_broadway_window_set_group (GdkWindow *window,
1073                                GdkWindow *leader)
1074 {
1075 }
1076
1077 static void
1078 gdk_broadway_window_set_decorations (GdkWindow      *window,
1079                                      GdkWMDecoration decorations)
1080 {
1081   if (GDK_WINDOW_DESTROYED (window) ||
1082       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1083     return;
1084
1085 }
1086
1087 static gboolean
1088 gdk_broadway_window_get_decorations (GdkWindow       *window,
1089                                      GdkWMDecoration *decorations)
1090 {
1091   gboolean result = FALSE;
1092
1093   if (GDK_WINDOW_DESTROYED (window) ||
1094       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1095     return FALSE;
1096
1097   return result;
1098 }
1099
1100 static void
1101 gdk_broadway_window_set_functions (GdkWindow    *window,
1102                                    GdkWMFunction functions)
1103 {
1104   g_return_if_fail (GDK_IS_WINDOW (window));
1105
1106   if (GDK_WINDOW_DESTROYED (window) ||
1107       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1108     return;
1109 }
1110
1111 static cairo_region_t *
1112 gdk_broadway_window_get_shape (GdkWindow *window)
1113 {
1114   return NULL;
1115 }
1116
1117 static cairo_region_t *
1118 gdk_broadway_window_get_input_shape (GdkWindow *window)
1119 {
1120   return NULL;
1121 }
1122
1123
1124 static gboolean
1125 gdk_window_broadway_set_static_gravities (GdkWindow *window,
1126                                           gboolean   use_static)
1127 {
1128   return TRUE;
1129 }
1130
1131 static void
1132 gdk_broadway_window_begin_resize_drag (GdkWindow     *window,
1133                               GdkWindowEdge  edge,
1134                               gint           button,
1135                               gint           root_x,
1136                               gint           root_y,
1137                               guint32        timestamp)
1138 {
1139   if (GDK_WINDOW_DESTROYED (window) ||
1140       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1141     return;
1142
1143 }
1144
1145 static void
1146 gdk_broadway_window_begin_move_drag (GdkWindow *window,
1147                                      gint       button,
1148                                      gint       root_x,
1149                                      gint       root_y,
1150                                      guint32    timestamp)
1151 {
1152   if (GDK_WINDOW_DESTROYED (window) ||
1153       !WINDOW_IS_TOPLEVEL (window))
1154     return;
1155
1156 }
1157
1158 static void
1159 gdk_broadway_window_enable_synchronized_configure (GdkWindow *window)
1160 {
1161   if (!GDK_IS_WINDOW_IMPL_BROADWAY (window->impl))
1162     return;
1163 }
1164
1165 static void
1166 gdk_broadway_window_configure_finished (GdkWindow *window)
1167 {
1168   if (!WINDOW_IS_TOPLEVEL (window))
1169     return;
1170 }
1171
1172 static gboolean
1173 gdk_broadway_window_beep (GdkWindow *window)
1174 {
1175   return FALSE;
1176 }
1177
1178 static void
1179 gdk_broadway_window_set_opacity (GdkWindow *window,
1180                                  gdouble    opacity)
1181 {
1182   GdkDisplay *display;
1183
1184   g_return_if_fail (GDK_IS_WINDOW (window));
1185
1186   if (GDK_WINDOW_DESTROYED (window) ||
1187       !WINDOW_IS_TOPLEVEL (window))
1188     return;
1189
1190   display = gdk_window_get_display (window);
1191
1192   if (opacity < 0)
1193     opacity = 0;
1194   else if (opacity > 1)
1195     opacity = 1;
1196
1197 }
1198
1199 static void
1200 gdk_broadway_window_set_composited (GdkWindow *window,
1201                                      gboolean   composited)
1202 {
1203 }
1204
1205 static void
1206 gdk_broadway_window_process_updates_recurse (GdkWindow *window,
1207                                              cairo_region_t *region)
1208 {
1209   GdkWindowImplBroadway *impl;
1210
1211   _gdk_window_process_updates_recurse (window, region);
1212
1213   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
1214   impl->dirty = TRUE;
1215   queue_dirty_flush (GDK_BROADWAY_DISPLAY (gdk_window_get_display (window)));
1216 }
1217
1218 void
1219 _gdk_broadway_display_before_process_all_updates (GdkDisplay *display)
1220 {
1221 }
1222
1223 void
1224 _gdk_broadway_display_after_process_all_updates (GdkDisplay *display)
1225 {
1226 }
1227
1228 gboolean
1229 _gdk_broadway_window_queue_antiexpose (GdkWindow *window,
1230                                        cairo_region_t *area)
1231 {
1232   return TRUE;
1233 }
1234
1235 static void
1236 copy_region (cairo_surface_t *surface,
1237              cairo_region_t *area,
1238              gint            dx,
1239              gint            dy)
1240 {
1241   cairo_t *cr;
1242
1243   cr = cairo_create (surface);
1244
1245   gdk_cairo_region (cr, area);
1246   cairo_clip (cr);
1247
1248   /* NB: This is a self-copy and Cairo doesn't support that yet.
1249    * So we do a litle trick.
1250    */
1251   cairo_push_group (cr);
1252
1253   cairo_set_source_surface (cr, surface, dx, dy);
1254   cairo_paint (cr);
1255
1256   cairo_pop_group_to_source (cr);
1257   cairo_paint (cr);
1258
1259   cairo_destroy (cr);
1260 }
1261
1262 void
1263 _gdk_broadway_window_translate (GdkWindow      *window,
1264                                 cairo_region_t *area,
1265                                 gint            dx,
1266                                 gint            dy)
1267 {
1268   GdkWindowImplBroadway *impl;
1269   GdkBroadwayDisplay *broadway_display;
1270   int n_rects, i;
1271   BroadwayRect *rects;
1272   cairo_rectangle_int_t rect;
1273
1274   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
1275
1276   if (impl->surface)
1277     {
1278       copy_region (impl->surface, area, dx, dy);
1279       if (GDK_WINDOW_IMPL_BROADWAY (impl)->last_synced)
1280         {
1281           copy_region (impl->last_surface, area, dx, dy);
1282           n_rects = cairo_region_num_rectangles (area);
1283           rects = g_new (BroadwayRect, n_rects);
1284           for (i = 0; i < n_rects; i++)
1285             {
1286               cairo_region_get_rectangle (area, i, &rect);
1287               rects[i].x = rect.x;
1288               rects[i].y = rect.y;
1289               rects[i].width = rect.width;
1290               rects[i].height = rect.height;
1291             }
1292           broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window));
1293           broadway_output_copy_rectangles (broadway_display->output,
1294                                            GDK_WINDOW_IMPL_BROADWAY (impl)->id,
1295                                            rects, n_rects, dx, dy);
1296           queue_dirty_flush (broadway_display);
1297           g_free (rects);
1298         }
1299     }
1300 }
1301
1302 static void
1303 gdk_window_impl_broadway_class_init (GdkWindowImplBroadwayClass *klass)
1304 {
1305   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1306   GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
1307
1308   object_class->finalize = gdk_window_impl_broadway_finalize;
1309
1310   impl_class->ref_cairo_surface = gdk_window_broadway_ref_cairo_surface;
1311   impl_class->show = gdk_window_broadway_show;
1312   impl_class->hide = gdk_window_broadway_hide;
1313   impl_class->withdraw = gdk_window_broadway_withdraw;
1314   impl_class->set_events = gdk_window_broadway_set_events;
1315   impl_class->get_events = gdk_window_broadway_get_events;
1316   impl_class->raise = gdk_window_broadway_raise;
1317   impl_class->lower = gdk_window_broadway_lower;
1318   impl_class->restack_under = gdk_window_broadway_restack_under;
1319   impl_class->restack_toplevel = gdk_window_broadway_restack_toplevel;
1320   impl_class->move_resize = gdk_window_broadway_move_resize;
1321   impl_class->set_background = gdk_window_broadway_set_background;
1322   impl_class->reparent = gdk_window_broadway_reparent;
1323   impl_class->set_device_cursor = gdk_window_broadway_set_device_cursor;
1324   impl_class->get_geometry = gdk_window_broadway_get_geometry;
1325   impl_class->get_root_coords = gdk_window_broadway_get_root_coords;
1326   impl_class->get_device_state = gdk_window_broadway_get_device_state;
1327   impl_class->shape_combine_region = gdk_window_broadway_shape_combine_region;
1328   impl_class->input_shape_combine_region = gdk_window_broadway_input_shape_combine_region;
1329   impl_class->set_static_gravities = gdk_window_broadway_set_static_gravities;
1330   impl_class->queue_antiexpose = _gdk_broadway_window_queue_antiexpose;
1331   impl_class->translate = _gdk_broadway_window_translate;
1332   impl_class->destroy = _gdk_broadway_window_destroy;
1333   impl_class->destroy_foreign = gdk_broadway_window_destroy_foreign;
1334   impl_class->resize_cairo_surface = gdk_window_broadway_resize_cairo_surface;
1335   impl_class->get_shape = gdk_broadway_window_get_shape;
1336   impl_class->get_input_shape = gdk_broadway_window_get_input_shape;
1337   impl_class->beep = gdk_broadway_window_beep;
1338
1339   impl_class->focus = gdk_broadway_window_focus;
1340   impl_class->set_type_hint = gdk_broadway_window_set_type_hint;
1341   impl_class->get_type_hint = gdk_broadway_window_get_type_hint;
1342   impl_class->set_modal_hint = gdk_broadway_window_set_modal_hint;
1343   impl_class->set_skip_taskbar_hint = gdk_broadway_window_set_skip_taskbar_hint;
1344   impl_class->set_skip_pager_hint = gdk_broadway_window_set_skip_pager_hint;
1345   impl_class->set_urgency_hint = gdk_broadway_window_set_urgency_hint;
1346   impl_class->set_geometry_hints = gdk_broadway_window_set_geometry_hints;
1347   impl_class->set_title = gdk_broadway_window_set_title;
1348   impl_class->set_role = gdk_broadway_window_set_role;
1349   impl_class->set_startup_id = gdk_broadway_window_set_startup_id;
1350   impl_class->set_transient_for = gdk_broadway_window_set_transient_for;
1351   impl_class->get_root_origin = gdk_broadway_window_get_root_origin;
1352   impl_class->get_frame_extents = gdk_broadway_window_get_frame_extents;
1353   impl_class->set_override_redirect = gdk_broadway_window_set_override_redirect;
1354   impl_class->set_accept_focus = gdk_broadway_window_set_accept_focus;
1355   impl_class->set_focus_on_map = gdk_broadway_window_set_focus_on_map;
1356   impl_class->set_icon_list = gdk_broadway_window_set_icon_list;
1357   impl_class->set_icon_name = gdk_broadway_window_set_icon_name;
1358   impl_class->iconify = gdk_broadway_window_iconify;
1359   impl_class->deiconify = gdk_broadway_window_deiconify;
1360   impl_class->stick = gdk_broadway_window_stick;
1361   impl_class->unstick = gdk_broadway_window_unstick;
1362   impl_class->maximize = gdk_broadway_window_maximize;
1363   impl_class->unmaximize = gdk_broadway_window_unmaximize;
1364   impl_class->fullscreen = gdk_broadway_window_fullscreen;
1365   impl_class->unfullscreen = gdk_broadway_window_unfullscreen;
1366   impl_class->set_keep_above = gdk_broadway_window_set_keep_above;
1367   impl_class->set_keep_below = gdk_broadway_window_set_keep_below;
1368   impl_class->get_group = gdk_broadway_window_get_group;
1369   impl_class->set_group = gdk_broadway_window_set_group;
1370   impl_class->set_decorations = gdk_broadway_window_set_decorations;
1371   impl_class->get_decorations = gdk_broadway_window_get_decorations;
1372   impl_class->set_functions = gdk_broadway_window_set_functions;
1373   impl_class->set_functions = gdk_broadway_window_set_functions;
1374   impl_class->begin_resize_drag = gdk_broadway_window_begin_resize_drag;
1375   impl_class->begin_move_drag = gdk_broadway_window_begin_move_drag;
1376   impl_class->enable_synchronized_configure = gdk_broadway_window_enable_synchronized_configure;
1377   impl_class->configure_finished = gdk_broadway_window_configure_finished;
1378   impl_class->set_opacity = gdk_broadway_window_set_opacity;
1379   impl_class->set_composited = gdk_broadway_window_set_composited;
1380   impl_class->destroy_notify = gdk_broadway_window_destroy_notify;
1381   impl_class->register_dnd = _gdk_broadway_window_register_dnd;
1382   impl_class->drag_begin = _gdk_broadway_window_drag_begin;
1383   impl_class->process_updates_recurse = gdk_broadway_window_process_updates_recurse;
1384   impl_class->sync_rendering = _gdk_broadway_window_sync_rendering;
1385   impl_class->simulate_key = _gdk_broadway_window_simulate_key;
1386   impl_class->simulate_button = _gdk_broadway_window_simulate_button;
1387   impl_class->get_property = _gdk_broadway_window_get_property;
1388   impl_class->change_property = _gdk_broadway_window_change_property;
1389   impl_class->delete_property = _gdk_broadway_window_delete_property;
1390 }