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