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