]> Pileus Git - ~andy/gtk/blob - gdk/gdkwindow.c
Updated Translation
[~andy/gtk] / gdk / gdkwindow.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <config.h>
28 #include "gdkwindow.h"
29 #include "gdkinternals.h"
30 #include "gdk.h"                /* For gdk_rectangle_union() */
31 #include "gdkpixmap.h"
32 #include "gdkdrawable.h"
33 #include "gdkpixmap.h"
34 #include "gdkscreen.h"
35 #include "gdkalias.h"
36
37 #define USE_BACKING_STORE       /* Appears to work on Win32, too, now. */
38
39 typedef struct _GdkWindowPaint GdkWindowPaint;
40
41 struct _GdkWindowPaint
42 {
43   GdkRegion *region;
44   GdkPixmap *pixmap;
45   gint x_offset;
46   gint y_offset;
47   cairo_surface_t *surface;
48 };
49
50 static GdkGC *gdk_window_create_gc      (GdkDrawable     *drawable,
51                                          GdkGCValues     *values,
52                                          GdkGCValuesMask  mask);
53 static void   gdk_window_draw_rectangle (GdkDrawable     *drawable,
54                                          GdkGC           *gc,
55                                          gboolean         filled,
56                                          gint             x,
57                                          gint             y,
58                                          gint             width,
59                                          gint             height);
60 static void   gdk_window_draw_arc       (GdkDrawable     *drawable,
61                                          GdkGC           *gc,
62                                          gboolean         filled,
63                                          gint             x,
64                                          gint             y,
65                                          gint             width,
66                                          gint             height,
67                                          gint             angle1,
68                                          gint             angle2);
69 static void   gdk_window_draw_polygon   (GdkDrawable     *drawable,
70                                          GdkGC           *gc,
71                                          gboolean         filled,
72                                          GdkPoint        *points,
73                                          gint             npoints);
74 static void   gdk_window_draw_text      (GdkDrawable     *drawable,
75                                          GdkFont         *font,
76                                          GdkGC           *gc,
77                                          gint             x,
78                                          gint             y,
79                                          const gchar     *text,
80                                          gint             text_length);
81 static void   gdk_window_draw_text_wc   (GdkDrawable     *drawable,
82                                          GdkFont         *font,
83                                          GdkGC           *gc,
84                                          gint             x,
85                                          gint             y,
86                                          const GdkWChar  *text,
87                                          gint             text_length);
88 static void   gdk_window_draw_drawable  (GdkDrawable     *drawable,
89                                          GdkGC           *gc,
90                                          GdkPixmap       *src,
91                                          gint             xsrc,
92                                          gint             ysrc,
93                                          gint             xdest,
94                                          gint             ydest,
95                                          gint             width,
96                                          gint             height);
97 static void   gdk_window_draw_points    (GdkDrawable     *drawable,
98                                          GdkGC           *gc,
99                                          GdkPoint        *points,
100                                          gint             npoints);
101 static void   gdk_window_draw_segments  (GdkDrawable     *drawable,
102                                          GdkGC           *gc,
103                                          GdkSegment      *segs,
104                                          gint             nsegs);
105 static void   gdk_window_draw_lines     (GdkDrawable     *drawable,
106                                          GdkGC           *gc,
107                                          GdkPoint        *points,
108                                          gint             npoints);
109
110 static void gdk_window_draw_glyphs             (GdkDrawable      *drawable,
111                                                 GdkGC            *gc,
112                                                 PangoFont        *font,
113                                                 gint              x,
114                                                 gint              y,
115                                                 PangoGlyphString *glyphs);
116 static void gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
117                                                 GdkGC            *gc,
118                                                 PangoMatrix      *matrix,
119                                                 PangoFont        *font,
120                                                 gint              x,
121                                                 gint              y,
122                                                 PangoGlyphString *glyphs);
123
124 static void   gdk_window_draw_image     (GdkDrawable     *drawable,
125                                          GdkGC           *gc,
126                                          GdkImage        *image,
127                                          gint             xsrc,
128                                          gint             ysrc,
129                                          gint             xdest,
130                                          gint             ydest,
131                                          gint             width,
132                                          gint             height);
133
134 static void gdk_window_draw_pixbuf (GdkDrawable     *drawable,
135                                     GdkGC           *gc,
136                                     GdkPixbuf       *pixbuf,
137                                     gint             src_x,
138                                     gint             src_y,
139                                     gint             dest_x,
140                                     gint             dest_y,
141                                     gint             width,
142                                     gint             height,
143                                     GdkRgbDither     dither,
144                                     gint             x_dither,
145                                     gint             y_dither);
146
147 static void gdk_window_draw_trapezoids (GdkDrawable   *drawable,
148                                         GdkGC         *gc,
149                                         GdkTrapezoid  *trapezoids,
150                                         gint           n_trapezoids);
151
152 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
153                                            GdkImage    *image,
154                                            gint         src_x,
155                                            gint         src_y,
156                                            gint         dest_x,
157                                            gint         dest_y,
158                                            gint         width,
159                                            gint         height);
160
161 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
162
163 static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
164                                          gint            *width,
165                                          gint            *height);
166
167 static GdkVisual*   gdk_window_real_get_visual   (GdkDrawable *drawable);
168 static gint         gdk_window_real_get_depth    (GdkDrawable *drawable);
169 static GdkScreen*   gdk_window_real_get_screen   (GdkDrawable *drawable);
170 static void         gdk_window_real_set_colormap (GdkDrawable *drawable,
171                                                   GdkColormap *cmap);
172 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
173
174 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
175                                                        gint         x,
176                                                        gint         y,
177                                                        gint         width,
178                                                        gint         height,
179                                                        gint        *composite_x_offset,
180                                                        gint        *composite_y_offset);
181 static GdkRegion*   gdk_window_get_clip_region        (GdkDrawable *drawable);
182 static GdkRegion*   gdk_window_get_visible_region     (GdkDrawable *drawable);
183
184 static void gdk_window_free_paint_stack (GdkWindow *window);
185
186 static void gdk_window_init       (GdkWindowObject      *window);
187 static void gdk_window_class_init (GdkWindowObjectClass *klass);
188 static void gdk_window_finalize   (GObject              *object);
189 static void gdk_window_clear_backing_rect (GdkWindow *window,
190                                            gint       x,
191                                            gint       y,
192                                            gint       width,
193                                            gint       height);
194
195 static gpointer parent_class = NULL;
196
197 GType
198 gdk_window_object_get_type (void)
199 {
200   static GType object_type = 0;
201
202   if (!object_type)
203     object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
204                                                  "GdkWindow",
205                                                  sizeof (GdkWindowObjectClass),
206                                                  (GClassInitFunc) gdk_window_class_init,
207                                                  sizeof (GdkWindowObject),
208                                                  (GInstanceInitFunc) gdk_window_init,
209                                                  0);
210   
211   return object_type;
212 }
213
214 GType
215 _gdk_paintable_get_type (void)
216 {
217   static GType paintable_type = 0;
218
219   if (!paintable_type)
220     {
221       static const GTypeInfo paintable_info =
222       {
223         sizeof (GdkPaintableIface),  /* class_size */
224         NULL,                        /* base_init */
225         NULL,                        /* base_finalize */
226       };
227
228       paintable_type = g_type_register_static (G_TYPE_INTERFACE,
229                                                g_intern_static_string ("GdkPaintable"),
230                                                &paintable_info, 0);
231
232       g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
233     }
234
235   return paintable_type;
236 }
237
238 static void
239 gdk_window_init (GdkWindowObject *window)
240 {
241   /* 0-initialization is good for all other fields. */
242
243   window->window_type = GDK_WINDOW_CHILD;
244
245   window->state = GDK_WINDOW_STATE_WITHDRAWN;
246   
247   window->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
248 }
249
250 static void
251 gdk_window_class_init (GdkWindowObjectClass *klass)
252 {
253   GObjectClass *object_class = G_OBJECT_CLASS (klass);
254   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
255   
256   parent_class = g_type_class_peek_parent (klass);
257
258   object_class->finalize = gdk_window_finalize;
259
260   drawable_class->create_gc = gdk_window_create_gc;
261   drawable_class->draw_rectangle = gdk_window_draw_rectangle;
262   drawable_class->draw_arc = gdk_window_draw_arc;
263   drawable_class->draw_polygon = gdk_window_draw_polygon;
264   drawable_class->draw_text = gdk_window_draw_text;
265   drawable_class->draw_text_wc = gdk_window_draw_text_wc;
266   drawable_class->draw_drawable = gdk_window_draw_drawable;
267   drawable_class->draw_points = gdk_window_draw_points;
268   drawable_class->draw_segments = gdk_window_draw_segments;
269   drawable_class->draw_lines = gdk_window_draw_lines;
270   drawable_class->draw_glyphs = gdk_window_draw_glyphs;
271   drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
272   drawable_class->draw_image = gdk_window_draw_image;
273   drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
274   drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
275   drawable_class->get_depth = gdk_window_real_get_depth;
276   drawable_class->get_screen = gdk_window_real_get_screen;
277   drawable_class->get_size = gdk_window_real_get_size;
278   drawable_class->set_colormap = gdk_window_real_set_colormap;
279   drawable_class->get_colormap = gdk_window_real_get_colormap;
280   drawable_class->get_visual = gdk_window_real_get_visual;
281   drawable_class->_copy_to_image = gdk_window_copy_to_image;
282   drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
283   drawable_class->get_clip_region = gdk_window_get_clip_region;
284   drawable_class->get_visible_region = gdk_window_get_visible_region;
285   drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
286 }
287
288 static void
289 gdk_window_finalize (GObject *object)
290 {
291   GdkWindow *window = GDK_WINDOW (object);
292   GdkWindowObject *obj = (GdkWindowObject *) object;
293   
294   if (!GDK_WINDOW_DESTROYED (window))
295     {
296       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
297         {
298           g_warning ("losing last reference to undestroyed window\n");
299           _gdk_window_destroy (window, FALSE);
300         }
301       else
302         /* We use TRUE here, to keep us from actually calling
303          * XDestroyWindow() on the window
304          */
305         _gdk_window_destroy (window, TRUE);
306     }
307
308   g_object_unref (obj->impl);
309   obj->impl = NULL;
310   
311   G_OBJECT_CLASS (parent_class)->finalize (object);
312 }
313
314 static void
315 window_remove_filters (GdkWindow *window)
316 {
317   GdkWindowObject *obj = (GdkWindowObject*) window;
318
319   if (obj->filters)
320     {
321       GList *tmp_list;
322       
323       for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
324         g_free (tmp_list->data);
325     
326       g_list_free (obj->filters);
327       obj->filters = NULL;
328     }
329 }
330
331 /**
332  * _gdk_window_destroy_hierarchy:
333  * @window: a #GdkWindow
334  * @recursing: If TRUE, then this is being called because a parent
335  *            was destroyed. This generally means that the call to the 
336  *            windowing system to destroy the window can be omitted, since
337  *            it will be destroyed as a result of the parent being destroyed.
338  *            Unless @foreign_destroy.           
339  * @foreign_destroy: If TRUE, the window or a parent was destroyed by some 
340  *            external agency. The window has already been destroyed and no 
341  *            windowing system calls should be made. (This may never happen
342  *            for some windowing systems.)
343  *
344  * Internal function to destroy a window. Like gdk_window_destroy(),
345  * but does not drop the reference count created by gdk_window_new().
346  **/
347 static void
348 _gdk_window_destroy_hierarchy (GdkWindow *window,
349                                gboolean   recursing,
350                                gboolean   foreign_destroy)
351 {
352   GdkWindowObject *private;
353   GdkWindowObject *temp_private;
354   GdkWindow *temp_window;
355   GdkScreen *screen;
356   GList *children;
357   GList *tmp;
358   
359   g_return_if_fail (window != NULL);
360   
361   private = (GdkWindowObject*) window;
362   
363   if (GDK_WINDOW_DESTROYED (window))
364     return;
365     
366   switch (GDK_WINDOW_TYPE (window))
367     {
368     case GDK_WINDOW_ROOT:
369       screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
370       if (!screen->closed)
371         {
372           g_error ("attempted to destroy root window");
373           break;
374         }
375       /* else fall thru */
376     case GDK_WINDOW_TOPLEVEL:
377     case GDK_WINDOW_CHILD:
378     case GDK_WINDOW_DIALOG:
379     case GDK_WINDOW_TEMP:
380     case GDK_WINDOW_FOREIGN:
381       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
382         {
383           /* Logically, it probably makes more sense to send
384            * a "destroy yourself" message to the foreign window
385            * whether or not it's in our heirarchy; but for historical
386            * reasons, we only send "destroy yourself" messages to
387            * foreign windows in our heirarchy.
388            */
389           if (private->parent)
390             _gdk_windowing_window_destroy_foreign (window);
391
392           /* Also for historical reasons, we remove any filters
393            * on a foreign window when it or a parent is destroyed;
394            * this likely causes problems if two separate portions
395            * of code are maintaining filter lists on a foreign window.
396            */
397           window_remove_filters (window);
398         }
399       else
400         {
401           private->state |= GDK_WINDOW_STATE_WITHDRAWN;
402           
403           if (private->parent)
404             {
405               GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
406               if (parent_private->children)
407                 parent_private->children = g_list_remove (parent_private->children, window);
408             }
409
410           _gdk_window_clear_update_area (window);
411           gdk_window_free_paint_stack (window);
412           
413           if (private->bg_pixmap &&
414               private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
415               private->bg_pixmap != GDK_NO_BG)
416             {
417               g_object_unref (private->bg_pixmap);
418               private->bg_pixmap = NULL;
419             }
420           
421           if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
422             g_assert (private->children == NULL);
423           else
424             {
425               children = tmp = private->children;
426               private->children = NULL;
427               
428               while (tmp)
429                 {
430                   temp_window = tmp->data;
431                   tmp = tmp->next;
432                   
433                   temp_private = (GdkWindowObject*) temp_window;
434                   if (temp_private)
435                     _gdk_window_destroy_hierarchy (temp_window,
436                                                    TRUE, foreign_destroy);
437                 }
438               
439               g_list_free (children);
440             }
441           
442           _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
443           private->parent = NULL;
444           private->destroyed = TRUE;
445
446           window_remove_filters (window);
447
448           gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
449         }
450       break;
451     }
452 }
453
454 /**
455  * _gdk_window_destroy:
456  * @window: a #GdkWindow
457  * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
458  *            external agency. The window has already been destroyed and no
459  *            windowing system calls should be made. (This may never happen
460  *            for some windowing systems.)
461  *
462  * Internal function to destroy a window. Like gdk_window_destroy(),
463  * but does not drop the reference count created by gdk_window_new().
464  **/
465 void
466 _gdk_window_destroy (GdkWindow *window,
467                      gboolean   foreign_destroy)
468 {
469   _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
470 }
471
472 /**
473  * gdk_window_destroy:
474  * @window: a #GdkWindow
475  *
476  * Destroys the window system resources associated with @window and decrements @window's
477  * reference count. The window system resources for all children of @window are also
478  * destroyed, but the children's reference counts are not decremented.
479  *
480  * Note that a window will not be destroyed automatically when its reference count
481  * reaches zero. You must call this function yourself before that happens.
482  *
483  **/
484 void
485 gdk_window_destroy (GdkWindow *window)
486 {
487   _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
488   g_object_unref (window);
489 }
490
491 /**
492  * gdk_window_set_user_data:
493  * @window: a #GdkWindow
494  * @user_data: user data
495  *
496  * For most purposes this function is deprecated in favor of
497  * g_object_set_data(). However, for historical reasons GTK+ stores
498  * the #GtkWidget that owns a #GdkWindow as user data on the
499  * #GdkWindow. So, custom widget implementations should use
500  * this function for that. If GTK+ receives an event for a #GdkWindow,
501  * and the user data for the window is non-%NULL, GTK+ will assume the
502  * user data is a #GtkWidget, and forward the event to that widget.
503  * 
504  **/
505 void
506 gdk_window_set_user_data (GdkWindow *window,
507                           gpointer   user_data)
508 {
509   g_return_if_fail (window != NULL);
510   
511   ((GdkWindowObject*)window)->user_data = user_data;
512 }
513
514 /**
515  * gdk_window_get_user_data:
516  * @window: a #GdkWindow
517  * @data: return location for user data
518  *
519  * Retrieves the user data for @window, which is normally the widget
520  * that @window belongs to. See gdk_window_set_user_data().
521  * 
522  **/
523 void
524 gdk_window_get_user_data (GdkWindow *window,
525                           gpointer  *data)
526 {
527   g_return_if_fail (window != NULL);
528   
529   *data = ((GdkWindowObject*)window)->user_data;
530 }
531
532 /**
533  * gdk_window_get_window_type:
534  * @window: a #GdkWindow
535  * 
536  * Gets the type of the window. See #GdkWindowType.
537  * 
538  * Return value: type of window
539  **/
540 GdkWindowType
541 gdk_window_get_window_type (GdkWindow *window)
542 {
543   g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
544   
545   return GDK_WINDOW_TYPE (window);
546 }
547
548 /**
549  * gdk_window_get_position:
550  * @window: a #GdkWindow
551  * @x: X coordinate of window
552  * @y: Y coordinate of window
553  *
554  * Obtains the position of the window as reported in the
555  * most-recently-processed #GdkEventConfigure. Contrast with
556  * gdk_window_get_geometry() which queries the X server for the
557  * current window position, regardless of which events have been
558  * received or processed.
559  *
560  * The position coordinates are relative to the window's parent window.
561  * 
562  **/
563 void
564 gdk_window_get_position (GdkWindow *window,
565                          gint      *x,
566                          gint      *y)
567 {
568   GdkWindowObject *obj;
569   
570   g_return_if_fail (GDK_IS_WINDOW (window));
571   
572   obj = (GdkWindowObject*) window;
573   
574   if (x)
575     *x = obj->x;
576   if (y)
577     *y = obj->y;
578 }
579
580 /**
581  * gdk_window_get_parent:
582  * @window: a #GdkWindow
583  * 
584  * Obtains the parent of @window, as known to GDK. Does not query the
585  * X server; thus this returns the parent as passed to gdk_window_new(),
586  * not the actual parent. This should never matter unless you're using
587  * Xlib calls mixed with GDK calls on the X11 platform. It may also
588  * matter for toplevel windows, because the window manager may choose
589  * to reparent them.
590  * 
591  * Return value: parent of @window
592  **/
593 GdkWindow*
594 gdk_window_get_parent (GdkWindow *window)
595 {
596   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
597   
598   return (GdkWindow*) ((GdkWindowObject*) window)->parent;
599 }
600
601 /**
602  * gdk_window_get_toplevel:
603  * @window: a #GdkWindow
604  * 
605  * Gets the toplevel window that's an ancestor of @window.
606  * 
607  * Return value: the toplevel window containing @window
608  **/
609 GdkWindow*
610 gdk_window_get_toplevel (GdkWindow *window)
611 {
612   GdkWindowObject *obj;
613   
614   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
615
616   obj = (GdkWindowObject *)window;
617   while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
618     obj = (GdkWindowObject *)obj->parent;
619   
620   return GDK_WINDOW (obj);
621 }
622
623 /**
624  * gdk_window_get_children:
625  * @window: a #GdkWindow
626  * 
627  * Gets the list of children of @window known to GDK.
628  * This function only returns children created via GDK,
629  * so for example it's useless when used with the root window;
630  * it only returns windows an application created itself.
631  *
632  * The returned list must be freed, but the elements in the
633  * list need not be.
634  * 
635  * Return value: list of child windows inside @window
636  **/
637 GList*
638 gdk_window_get_children (GdkWindow *window)
639 {
640   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
641
642   if (GDK_WINDOW_DESTROYED (window))
643     return NULL;
644
645   return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
646 }
647
648 /**
649  * gdk_window_peek_children:
650  * @window: a #GdkWindow
651  * 
652  * Like gdk_window_get_children(), but does not copy the list of
653  * children, so the list does not need to be freed.
654  * 
655  * Return value: a reference to the list of child windows in @window
656  **/
657 GList *
658 gdk_window_peek_children (GdkWindow *window)
659 {
660   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
661
662   if (GDK_WINDOW_DESTROYED (window))
663     return NULL;
664
665   return GDK_WINDOW_OBJECT (window)->children;
666 }
667
668 /**
669  * gdk_window_add_filter:
670  * @window: a #GdkWindow
671  * @function: filter callback
672  * @data: data to pass to filter callback
673  *
674  * Adds an event filter to @window, allowing you to intercept events
675  * before they reach GDK. This is a low-level operation and makes it
676  * easy to break GDK and/or GTK+, so you have to know what you're
677  * doing. Pass %NULL for @window to get all events for all windows,
678  * instead of events for a specific window.
679  * 
680  **/
681 void          
682 gdk_window_add_filter (GdkWindow     *window,
683                        GdkFilterFunc  function,
684                        gpointer       data)
685 {
686   GdkWindowObject *private;
687   GList *tmp_list;
688   GdkEventFilter *filter;
689   
690   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
691
692   private = (GdkWindowObject*) window;
693   if (private && GDK_WINDOW_DESTROYED (window))
694     return;
695   
696   if (private)
697     tmp_list = private->filters;
698   else
699     tmp_list = _gdk_default_filters;
700   
701   while (tmp_list)
702     {
703       filter = (GdkEventFilter *)tmp_list->data;
704       if ((filter->function == function) && (filter->data == data))
705         return;
706       tmp_list = tmp_list->next;
707     }
708   
709   filter = g_new (GdkEventFilter, 1);
710   filter->function = function;
711   filter->data = data;
712   
713   if (private)
714     private->filters = g_list_append (private->filters, filter);
715   else
716     _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
717 }
718
719 /**
720  * gdk_window_remove_filter:
721  * @window: a #GdkWindow
722  * @function: previously-added filter function
723  * @data: user data for previously-added filter function
724  *
725  * Remove a filter previously added with gdk_window_add_filter().
726  * 
727  **/
728 void
729 gdk_window_remove_filter (GdkWindow     *window,
730                           GdkFilterFunc  function,
731                           gpointer       data)
732 {
733   GdkWindowObject *private;
734   GList *tmp_list, *node;
735   GdkEventFilter *filter;
736   
737   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
738
739   private = (GdkWindowObject*) window;
740   
741   if (private)
742     tmp_list = private->filters;
743   else
744     tmp_list = _gdk_default_filters;
745   
746   while (tmp_list)
747     {
748       filter = (GdkEventFilter *)tmp_list->data;
749       node = tmp_list;
750       tmp_list = tmp_list->next;
751       
752       if ((filter->function == function) && (filter->data == data))
753         {
754           if (private)
755             private->filters = g_list_remove_link (private->filters, node);
756           else
757             _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
758           g_list_free_1 (node);
759           g_free (filter);
760           
761           return;
762         }
763     }
764 }
765
766 /**
767  * gdk_screen_get_toplevel_windows:
768  * @screen: The #GdkScreen where the toplevels are located.
769  * 
770  * Obtains a list of all toplevel windows known to GDK on the screen @screen.
771  * A toplevel window is a child of the root window (see
772  * gdk_get_default_root_window()).
773  *
774  * The returned list should be freed with g_list_free(), but
775  * its elements need not be freed.
776  * 
777  * Return value: list of toplevel windows, free with g_list_free()
778  *
779  * Since: 2.2
780  **/
781 GList *
782 gdk_screen_get_toplevel_windows (GdkScreen *screen)
783 {
784   GdkWindow * root_window;
785   GList *new_list = NULL;
786   GList *tmp_list;
787   
788   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
789   
790   root_window = gdk_screen_get_root_window (screen);
791
792   tmp_list = ((GdkWindowObject *)root_window)->children;
793   while (tmp_list)
794     {
795       if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
796         new_list = g_list_prepend (new_list, tmp_list->data);
797       tmp_list = tmp_list->next;
798     }
799   
800   return new_list;
801 }
802
803 /**
804  * gdk_window_get_toplevels:
805  * 
806  * Obtains a list of all toplevel windows known to GDK on the default
807  * screen (see gdk_screen_get_toplevel_windows()).
808  * A toplevel window is a child of the root window (see
809  * gdk_get_default_root_window()).
810  *
811  * The returned list should be freed with g_list_free(), but
812  * its elements need not be freed.
813  * 
814  * Return value: list of toplevel windows, free with g_list_free()
815  **/
816 GList *
817 gdk_window_get_toplevels (void)
818 {
819   return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
820 }
821
822 /**
823  * gdk_window_is_visible:
824  * @window: a #GdkWindow
825  * 
826  * Checks whether the window has been mapped (with gdk_window_show() or
827  * gdk_window_show_unraised()).
828  * 
829  * Return value: %TRUE if the window is mapped
830  **/
831 gboolean 
832 gdk_window_is_visible (GdkWindow *window)
833 {
834   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
835   
836   return GDK_WINDOW_IS_MAPPED (window);
837 }
838
839 /**
840  * gdk_window_is_viewable:
841  * @window: a #GdkWindow
842  * 
843  * Check if the window and all ancestors of the window are
844  * mapped. (This is not necessarily "viewable" in the X sense, since
845  * we only check as far as we have GDK window parents, not to the root
846  * window.)
847  *
848  * Return value: %TRUE if the window is viewable
849  **/
850 gboolean 
851 gdk_window_is_viewable (GdkWindow *window)
852 {
853   GdkWindowObject *private = (GdkWindowObject *)window;
854   GdkScreen *screen;
855   GdkWindow *root_window;
856   
857   g_return_val_if_fail (window != NULL, FALSE);
858   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
859
860   screen = gdk_drawable_get_screen (window);
861   root_window = gdk_screen_get_root_window (screen);
862   
863   while (private && 
864          (private != (GdkWindowObject *)root_window) &&
865          (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
866     {
867       if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
868         return FALSE;
869       
870       private = (GdkWindowObject *)private->parent;
871     }
872   
873   return TRUE;
874 }
875
876 /**
877  * gdk_window_get_state:
878  * @window: a #GdkWindow
879  * 
880  * Gets the bitwise OR of the currently active window state flags,
881  * from the #GdkWindowState enumeration.
882  * 
883  * Return value: window state bitfield
884  **/
885 GdkWindowState
886 gdk_window_get_state (GdkWindow *window)
887 {
888   GdkWindowObject *private = (GdkWindowObject *)window;
889   
890   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
891   
892   return private->state;
893 }
894
895 /**
896  * gdk_window_begin_paint_rect:
897  * @window: a #GdkWindow
898  * @rectangle: rectangle you intend to draw to
899  *
900  * A convenience wrapper around gdk_window_begin_paint_region() which
901  * creates a rectangular region for you. See
902  * gdk_window_begin_paint_region() for details.
903  * 
904  **/
905 void
906 gdk_window_begin_paint_rect (GdkWindow    *window,
907                              GdkRectangle *rectangle)
908 {
909   GdkRegion *region;
910
911   g_return_if_fail (window != NULL);
912   g_return_if_fail (GDK_IS_WINDOW (window));
913
914   region = gdk_region_rectangle (rectangle);
915   gdk_window_begin_paint_region (window, region);
916   gdk_region_destroy (region);
917 }
918
919 #ifdef GDK_WINDOWING_X11
920 #include "x11/gdkx.h"
921 #endif
922
923 /**
924  * gdk_window_begin_paint_region:
925  * @window: a #GdkWindow
926  * @region: region you intend to draw to
927  *
928  * Indicates that you are beginning the process of redrawing @region.
929  * A backing store (offscreen buffer) large enough to contain @region
930  * will be created. The backing store will be initialized with the
931  * background color or background pixmap for @window. Then, all
932  * drawing operations performed on @window will be diverted to the
933  * backing store.  When you call gdk_window_end_paint(), the backing
934  * store will be copied to @window, making it visible onscreen. Only
935  * the part of @window contained in @region will be modified; that is,
936  * drawing operations are clipped to @region.
937  *
938  * The net result of all this is to remove flicker, because the user
939  * sees the finished product appear all at once when you call
940  * gdk_window_end_paint(). If you draw to @window directly without
941  * calling gdk_window_begin_paint_region(), the user may see flicker
942  * as individual drawing operations are performed in sequence.  The
943  * clipping and background-initializing features of
944  * gdk_window_begin_paint_region() are conveniences for the
945  * programmer, so you can avoid doing that work yourself.
946  *
947  * When using GTK+, the widget system automatically places calls to
948  * gdk_window_begin_paint_region() and gdk_window_end_paint() around
949  * emissions of the expose_event signal. That is, if you're writing an
950  * expose event handler, you can assume that the exposed area in
951  * #GdkEventExpose has already been cleared to the window background,
952  * is already set as the clip region, and already has a backing store.
953  * Therefore in most cases, application code need not call
954  * gdk_window_begin_paint_region(). (You can disable the automatic
955  * calls around expose events on a widget-by-widget basis by calling
956  * gtk_widget_set_double_buffered().)
957  *
958  * If you call this function multiple times before calling the
959  * matching gdk_window_end_paint(), the backing stores are pushed onto
960  * a stack. gdk_window_end_paint() copies the topmost backing store
961  * onscreen, subtracts the topmost region from all other regions in
962  * the stack, and pops the stack. All drawing operations affect only
963  * the topmost backing store in the stack. One matching call to
964  * gdk_window_end_paint() is required for each call to
965  * gdk_window_begin_paint_region().
966  * 
967  **/
968 void          
969 gdk_window_begin_paint_region (GdkWindow *window,
970                                GdkRegion *region)
971 {
972 #ifdef USE_BACKING_STORE
973   GdkWindowObject *private = (GdkWindowObject *)window;
974   GdkRectangle clip_box;
975   GdkWindowPaint *paint;
976   GSList *list;
977   
978   g_return_if_fail (window != NULL);
979   g_return_if_fail (GDK_IS_WINDOW (window));
980
981   if (GDK_WINDOW_DESTROYED (window))
982     return;
983
984   if (GDK_IS_PAINTABLE (private->impl) &&
985       GDK_PAINTABLE_GET_IFACE (private->impl)->begin_paint_region) 
986     {
987       GDK_PAINTABLE_GET_IFACE (private->impl)->begin_paint_region (GDK_PAINTABLE (private->impl), region);
988       return;
989     }
990
991   gdk_region_get_clipbox (region, &clip_box);
992
993   paint = g_new (GdkWindowPaint, 1);
994   paint->region = gdk_region_copy (region);
995   paint->x_offset = clip_box.x;
996   paint->y_offset = clip_box.y;
997   paint->pixmap =
998     gdk_pixmap_new (window,
999                     MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
1000
1001   paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
1002   cairo_surface_set_device_offset (paint->surface,
1003                                    - paint->x_offset, - paint->y_offset);
1004   
1005   for (list = private->paint_stack; list != NULL; list = list->next)
1006     {
1007       GdkWindowPaint *tmp_paint = list->data;
1008
1009       gdk_region_subtract (tmp_paint->region, paint->region);
1010     }
1011   
1012   private->paint_stack = g_slist_prepend (private->paint_stack, paint);
1013
1014   if (!gdk_region_empty (region))
1015     {
1016       gdk_window_clear_backing_rect (window,
1017                                      clip_box.x, clip_box.y,
1018                                      clip_box.width, clip_box.height);
1019     }
1020 #endif /* USE_BACKING_STORE */
1021 }
1022
1023 /**
1024  * gdk_window_end_paint:
1025  * @window: a #GdkWindow
1026  *
1027  * Indicates that the backing store created by the most recent call to
1028  * gdk_window_begin_paint_region() should be copied onscreen and
1029  * deleted, leaving the next-most-recent backing store or no backing
1030  * store at all as the active paint region. See
1031  * gdk_window_begin_paint_region() for full details. It is an error to
1032  * call this function without a matching
1033  * gdk_window_begin_paint_region() first.
1034  * 
1035  **/
1036 void
1037 gdk_window_end_paint (GdkWindow *window)
1038 {
1039 #ifdef USE_BACKING_STORE
1040   GdkWindowObject *private = (GdkWindowObject *)window;
1041   GdkWindowPaint *paint;
1042   GdkGC *tmp_gc;
1043   GdkRectangle clip_box;
1044   gint x_offset, y_offset;
1045
1046   g_return_if_fail (window != NULL);
1047   g_return_if_fail (GDK_IS_WINDOW (window));
1048
1049   if (GDK_WINDOW_DESTROYED (window))
1050     return;
1051
1052   if (GDK_IS_PAINTABLE (private->impl) &&
1053       GDK_PAINTABLE_GET_IFACE (private->impl)->end_paint) 
1054     {
1055       GDK_PAINTABLE_GET_IFACE (private->impl)->end_paint (GDK_PAINTABLE (private->impl));
1056       return;
1057     }
1058
1059   if (private->paint_stack == NULL)
1060     {
1061       g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
1062       return;
1063     }
1064
1065   paint = private->paint_stack->data;
1066   private->paint_stack = g_slist_delete_link (private->paint_stack, 
1067                                               private->paint_stack);
1068
1069   gdk_region_get_clipbox (paint->region, &clip_box);
1070
1071   tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
1072
1073   _gdk_windowing_window_get_offsets (window, &x_offset, &y_offset);
1074
1075   gdk_gc_set_clip_region (tmp_gc, paint->region);
1076   gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
1077
1078   gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
1079                      clip_box.x - paint->x_offset,
1080                      clip_box.y - paint->y_offset,
1081                      clip_box.x - x_offset, clip_box.y - y_offset,
1082                      clip_box.width, clip_box.height);
1083
1084   /* Reset clip region of the cached GdkGC */
1085   gdk_gc_set_clip_region (tmp_gc, NULL);
1086
1087   cairo_surface_destroy (paint->surface);
1088   g_object_unref (paint->pixmap);
1089   gdk_region_destroy (paint->region);
1090   g_free (paint);
1091 #endif /* USE_BACKING_STORE */
1092 }
1093
1094 static void
1095 gdk_window_free_paint_stack (GdkWindow *window)
1096 {
1097   GdkWindowObject *private = (GdkWindowObject *)window;
1098   
1099   if (private->paint_stack)
1100     {
1101       GSList *tmp_list = private->paint_stack;
1102
1103       while (tmp_list)
1104         {
1105           GdkWindowPaint *paint = tmp_list->data;
1106
1107           if (tmp_list == private->paint_stack)
1108             g_object_unref (paint->pixmap);
1109                   
1110           gdk_region_destroy (paint->region);
1111           g_free (paint);
1112
1113           tmp_list = tmp_list->next;
1114         }
1115
1116       g_slist_free (private->paint_stack);
1117       private->paint_stack = NULL;
1118     }
1119 }
1120
1121 static void
1122 gdk_window_get_offsets (GdkWindow *window,
1123                         gint      *x_offset,
1124                         gint      *y_offset)
1125 {
1126   GdkWindowObject *private = (GdkWindowObject *)window;
1127   
1128   if (private->paint_stack)
1129     {
1130       GdkWindowPaint *paint = private->paint_stack->data;
1131       *x_offset = paint->x_offset;
1132       *y_offset = paint->y_offset;
1133     }
1134   else
1135     _gdk_windowing_window_get_offsets (window, x_offset, y_offset);
1136 }
1137
1138 /**
1139  * gdk_window_get_internal_paint_info:
1140  * @window: a #GdkWindow
1141  * @real_drawable: location to store the drawable to which drawing should be 
1142  *            done.
1143  * @x_offset: location to store the X offset between coordinates in @window,
1144  *            and the underlying window system primitive coordinates for 
1145  *            *@real_drawable.
1146  * @y_offset: location to store the Y offset between coordinates in @window,
1147  *            and the underlying window system primitive coordinates for
1148  *            *@real_drawable.
1149  * 
1150  * If you bypass the GDK layer and use windowing system primitives to
1151  * draw directly onto a #GdkWindow, then you need to deal with two
1152  * details: there may be an offset between GDK coordinates and windowing
1153  * system coordinates, and GDK may have redirected drawing to a offscreen
1154  * pixmap as the result of a gdk_window_begin_paint_region() calls.
1155  * This function allows retrieving the information you need to compensate
1156  * for these effects.
1157  *
1158  * This function exposes details of the GDK implementation, and is thus
1159  * likely to change in future releases of GDK.
1160  **/
1161 void
1162 gdk_window_get_internal_paint_info (GdkWindow    *window,
1163                                     GdkDrawable **real_drawable,
1164                                     gint         *x_offset,
1165                                     gint         *y_offset)
1166 {
1167   gint x_off, y_off;
1168   
1169   GdkWindowObject *private;
1170
1171   g_return_if_fail (GDK_IS_WINDOW (window));
1172
1173   private = (GdkWindowObject *)window;
1174
1175   if (real_drawable)
1176     {
1177       if (private->paint_stack)
1178         {
1179           GdkWindowPaint *paint = private->paint_stack->data;
1180           *real_drawable = paint->pixmap;
1181         }
1182       else
1183         *real_drawable = window;
1184     }
1185
1186   gdk_window_get_offsets (window, &x_off, &y_off);
1187
1188   if (x_offset)
1189     *x_offset = x_off;
1190   if (y_offset)
1191     *y_offset = y_off;
1192 }
1193
1194 #define OFFSET_GC(gc)                                         \
1195     gint x_offset, y_offset;                                  \
1196     gint old_clip_x = gc->clip_x_origin;    \
1197     gint old_clip_y = gc->clip_y_origin;    \
1198     gint old_ts_x = gc->ts_x_origin;        \
1199     gint old_ts_y = gc->ts_y_origin;        \
1200     gdk_window_get_offsets (drawable, &x_offset, &y_offset);  \
1201     if (x_offset != 0 || y_offset != 0)                       \
1202       {                                                       \
1203         gdk_gc_set_clip_origin (gc, old_clip_x - x_offset,    \
1204                                 old_clip_y - y_offset);       \
1205         gdk_gc_set_ts_origin (gc, old_ts_x - x_offset,        \
1206                               old_ts_y - y_offset);           \
1207       }
1208
1209 #define RESTORE_GC(gc)                                      \
1210     if (x_offset != 0 || y_offset != 0)                     \
1211      {                                                      \
1212        gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
1213        gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y);       \
1214      }
1215
1216 static GdkGC *
1217 gdk_window_create_gc (GdkDrawable     *drawable,
1218                       GdkGCValues     *values,
1219                       GdkGCValuesMask  mask)
1220 {
1221   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
1222   
1223   if (GDK_WINDOW_DESTROYED (drawable))
1224     return NULL;
1225
1226   return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
1227                                  values, mask);
1228 }
1229
1230 static void
1231 gdk_window_draw_rectangle (GdkDrawable *drawable,
1232                            GdkGC       *gc,
1233                            gboolean     filled,
1234                            gint         x,
1235                            gint         y,
1236                            gint         width,
1237                            gint         height)
1238 {
1239   GdkWindowObject *private = (GdkWindowObject *)drawable;
1240   OFFSET_GC (gc);
1241
1242   if (GDK_WINDOW_DESTROYED (drawable))
1243     return;
1244   
1245   if (private->paint_stack)
1246     {
1247       GdkWindowPaint *paint = private->paint_stack->data;
1248       gdk_draw_rectangle (paint->pixmap, gc, filled,
1249                           x - x_offset, y - y_offset, width, height);
1250     }
1251   else
1252     gdk_draw_rectangle (private->impl, gc, filled,
1253                         x - x_offset, y - y_offset, width, height);
1254
1255   RESTORE_GC (gc);
1256 }
1257
1258 static void
1259 gdk_window_draw_arc (GdkDrawable *drawable,
1260                      GdkGC       *gc,
1261                      gboolean     filled,
1262                      gint         x,
1263                      gint         y,
1264                      gint         width,
1265                      gint         height,
1266                      gint         angle1,
1267                      gint         angle2)
1268 {
1269   GdkWindowObject *private = (GdkWindowObject *)drawable;
1270   OFFSET_GC (gc);
1271
1272   if (GDK_WINDOW_DESTROYED (drawable))
1273     return;
1274   
1275   if (private->paint_stack)
1276     {
1277       GdkWindowPaint *paint = private->paint_stack->data;
1278       gdk_draw_arc (paint->pixmap, gc, filled,
1279                     x - x_offset, y - y_offset,
1280                     width, height, angle1, angle2);
1281     }
1282   else
1283     gdk_draw_arc (private->impl, gc, filled,
1284                   x - x_offset, y - y_offset,
1285                   width, height, angle1, angle2);
1286   RESTORE_GC (gc);
1287 }
1288
1289 static void
1290 gdk_window_draw_polygon (GdkDrawable *drawable,
1291                          GdkGC       *gc,
1292                          gboolean     filled,
1293                          GdkPoint    *points,
1294                          gint         npoints)
1295 {
1296   GdkWindowObject *private = (GdkWindowObject *)drawable;
1297   GdkPoint *new_points;
1298   
1299   OFFSET_GC (gc);
1300
1301   if (GDK_WINDOW_DESTROYED (drawable))
1302     return;
1303   
1304   if (x_offset != 0 || y_offset != 0)
1305     {
1306       int i;
1307       
1308       new_points = g_new (GdkPoint, npoints);
1309       for (i=0; i<npoints; i++)
1310         {
1311           new_points[i].x = points[i].x - x_offset;
1312           new_points[i].y = points[i].y - y_offset;
1313         }
1314     }
1315   else
1316     new_points = points;
1317
1318   if (private->paint_stack)
1319     {
1320       GdkWindowPaint *paint = private->paint_stack->data;
1321       gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
1322
1323     }
1324   else
1325     gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
1326   
1327   if (new_points != points)
1328     g_free (new_points);
1329
1330   RESTORE_GC (gc);
1331 }
1332
1333 static void
1334 gdk_window_draw_text (GdkDrawable *drawable,
1335                       GdkFont     *font,
1336                       GdkGC       *gc,
1337                       gint         x,
1338                       gint         y,
1339                       const gchar *text,
1340                       gint         text_length)
1341 {
1342   GdkWindowObject *private = (GdkWindowObject *)drawable;
1343   OFFSET_GC (gc);
1344
1345   if (GDK_WINDOW_DESTROYED (drawable))
1346     return;
1347   
1348   if (private->paint_stack)
1349     {
1350       GdkWindowPaint *paint = private->paint_stack->data;
1351       gdk_draw_text (paint->pixmap, font, gc, 
1352                      x - x_offset, y - y_offset, text, text_length);
1353
1354     }
1355   else
1356     gdk_draw_text (private->impl, font, gc,
1357                    x - x_offset, y - y_offset, text, text_length);
1358
1359   RESTORE_GC (gc);
1360 }
1361
1362 static void
1363 gdk_window_draw_text_wc (GdkDrawable    *drawable,
1364                          GdkFont        *font,
1365                          GdkGC          *gc,
1366                          gint            x,
1367                          gint            y,
1368                          const GdkWChar *text,
1369                          gint            text_length)
1370 {
1371   GdkWindowObject *private = (GdkWindowObject *)drawable;
1372   OFFSET_GC (gc);
1373
1374   if (GDK_WINDOW_DESTROYED (drawable))
1375     return;
1376   
1377   if (private->paint_stack)
1378     {
1379       GdkWindowPaint *paint = private->paint_stack->data;
1380       gdk_draw_text_wc (paint->pixmap, font, gc, 
1381                         x - x_offset, y - y_offset, text, text_length);
1382     }
1383   else
1384     gdk_draw_text_wc (private->impl, font, gc,
1385                       x - x_offset, y - y_offset, text, text_length);
1386   
1387   RESTORE_GC (gc);
1388 }
1389
1390 static GdkDrawable*
1391 gdk_window_get_composite_drawable (GdkDrawable *drawable,
1392                                    gint         x,
1393                                    gint         y,
1394                                    gint         width,
1395                                    gint         height,
1396                                    gint        *composite_x_offset,
1397                                    gint        *composite_y_offset)
1398 {
1399   GdkWindowObject *private = (GdkWindowObject *)drawable;
1400   GSList *list;
1401   GdkPixmap *tmp_pixmap;
1402   GdkRectangle rect;
1403   GdkGC *tmp_gc;
1404   gboolean overlap_buffer;
1405
1406   _gdk_windowing_window_get_offsets (drawable,
1407                                      composite_x_offset,
1408                                      composite_y_offset);
1409   
1410   if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
1411       || private->paint_stack == NULL)
1412     {
1413       /* No backing store */
1414       return g_object_ref (drawable);
1415     }
1416
1417   /* See if the buffered part is overlapping the part we want
1418    * to get
1419    */
1420   rect.x = x;
1421   rect.y = y;
1422   rect.width = width;
1423   rect.height = height;
1424
1425   overlap_buffer = FALSE;
1426   
1427   for (list = private->paint_stack; list != NULL; list = list->next)
1428     {
1429       GdkWindowPaint *paint = list->data;
1430       GdkOverlapType overlap;
1431
1432       overlap = gdk_region_rect_in (paint->region, &rect);
1433
1434       if (overlap == GDK_OVERLAP_RECTANGLE_IN)
1435         {
1436           *composite_x_offset = paint->x_offset;
1437           *composite_y_offset = paint->y_offset;
1438           
1439           return g_object_ref (paint->pixmap);
1440         }
1441       else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
1442         {
1443           overlap_buffer = TRUE;
1444           break;
1445         }
1446     }
1447
1448   if (!overlap_buffer)
1449     return g_object_ref (drawable);
1450
1451   tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
1452   tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
1453
1454   /* Copy the current window contents */
1455   gdk_draw_drawable (tmp_pixmap,
1456                      tmp_gc,
1457                      private->impl,
1458                      x - *composite_x_offset,
1459                      y - *composite_y_offset,
1460                      0, 0,
1461                      width, height);
1462
1463   /* paint the backing stores */
1464   for (list = private->paint_stack; list != NULL; list = list->next)
1465     {
1466       GdkWindowPaint *paint = list->data;
1467
1468       gdk_gc_set_clip_region (tmp_gc, paint->region);
1469       gdk_gc_set_clip_origin (tmp_gc, -x, -y);
1470       
1471       gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
1472                          x - paint->x_offset,
1473                          y - paint->y_offset,
1474                          0, 0, width, height);
1475     }
1476
1477   /* Reset clip region of the cached GdkGC */
1478   gdk_gc_set_clip_region (tmp_gc, NULL);
1479
1480   /* Set these to location of tmp_pixmap within the window */
1481   *composite_x_offset = x;
1482   *composite_y_offset = y;
1483
1484   return tmp_pixmap;
1485 }
1486
1487 static GdkRegion*
1488 gdk_window_get_clip_region (GdkDrawable *drawable)
1489 {
1490   GdkWindowObject *private = (GdkWindowObject *)drawable;
1491   GdkRegion *result;
1492
1493   result = gdk_drawable_get_clip_region (private->impl);
1494
1495   if (private->paint_stack)
1496     {
1497       GdkRegion *paint_region = gdk_region_new ();
1498       GSList *tmp_list = private->paint_stack;
1499
1500       while (tmp_list)
1501         {
1502           GdkWindowPaint *paint = tmp_list->data;
1503           
1504           gdk_region_union (paint_region, paint->region);
1505
1506           tmp_list = tmp_list->next;
1507         }
1508
1509       gdk_region_intersect (result, paint_region);
1510       gdk_region_destroy (paint_region);
1511     }
1512
1513   return result;
1514 }
1515
1516 static GdkRegion*
1517 gdk_window_get_visible_region (GdkDrawable *drawable)
1518 {
1519   GdkWindowObject *private = (GdkWindowObject*) drawable;
1520   
1521   return gdk_drawable_get_visible_region (private->impl);
1522 }
1523
1524 static void
1525 gdk_window_draw_drawable (GdkDrawable *drawable,
1526                           GdkGC       *gc,
1527                           GdkPixmap   *src,
1528                           gint         xsrc,
1529                           gint         ysrc,
1530                           gint         xdest,
1531                           gint         ydest,
1532                           gint         width,
1533                           gint         height)
1534 {
1535   GdkWindowObject *private = (GdkWindowObject *)drawable;
1536   OFFSET_GC (gc);
1537   
1538   if (GDK_WINDOW_DESTROYED (drawable))
1539     return;
1540
1541   /* If we have a backing pixmap draw to that */
1542   if (private->paint_stack)
1543     {
1544       GdkWindowPaint *paint = private->paint_stack->data;
1545       gdk_draw_drawable (paint->pixmap, gc,
1546                          src, xsrc, ysrc,
1547                          xdest - x_offset, ydest - y_offset, width, height);
1548
1549     }
1550   else
1551     gdk_draw_drawable (private->impl, gc,
1552                        src, xsrc, ysrc,
1553                        xdest - x_offset, ydest - y_offset,
1554                        width, height);
1555
1556   RESTORE_GC (gc);
1557 }
1558
1559 static void
1560 gdk_window_draw_points (GdkDrawable *drawable,
1561                         GdkGC       *gc,
1562                         GdkPoint    *points,
1563                         gint         npoints)
1564 {
1565   GdkWindowObject *private = (GdkWindowObject *)drawable;
1566   GdkPoint *new_points;
1567   
1568   OFFSET_GC (gc);
1569
1570   if (GDK_WINDOW_DESTROYED (drawable))
1571     return;
1572   
1573   if (x_offset != 0 || y_offset != 0)
1574     {
1575       gint i;
1576
1577       new_points = g_new (GdkPoint, npoints);
1578       for (i=0; i<npoints; i++)
1579         {
1580           new_points[i].x = points[i].x - x_offset;
1581           new_points[i].y = points[i].y - y_offset;
1582         }
1583     }
1584   else
1585     new_points = points;
1586
1587   if (private->paint_stack)
1588     {
1589       GdkWindowPaint *paint = private->paint_stack->data;
1590       gdk_draw_points (paint->pixmap, gc, new_points, npoints);
1591     }
1592   else
1593     gdk_draw_points (private->impl, gc, points, npoints);
1594
1595   if (new_points != points)
1596     g_free (new_points);
1597
1598   RESTORE_GC (gc);
1599 }
1600
1601 static void
1602 gdk_window_draw_segments (GdkDrawable *drawable,
1603                           GdkGC       *gc,
1604                           GdkSegment  *segs,
1605                           gint         nsegs)
1606 {
1607   GdkWindowObject *private = (GdkWindowObject *)drawable;
1608   GdkSegment *new_segs;
1609
1610   OFFSET_GC (gc);
1611
1612   if (GDK_WINDOW_DESTROYED (drawable))
1613     return;
1614   
1615   if (x_offset != 0 || y_offset != 0)
1616     {
1617       gint i;
1618
1619       new_segs = g_new (GdkSegment, nsegs);
1620       for (i=0; i<nsegs; i++)
1621         {
1622           new_segs[i].x1 = segs[i].x1 - x_offset;
1623           new_segs[i].y1 = segs[i].y1 - y_offset;
1624           new_segs[i].x2 = segs[i].x2 - x_offset;
1625           new_segs[i].y2 = segs[i].y2 - y_offset;
1626         }
1627     }
1628   else
1629     new_segs = segs;
1630
1631   if (private->paint_stack)
1632     {
1633       GdkWindowPaint *paint = private->paint_stack->data;
1634       gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
1635     }
1636   else
1637     gdk_draw_segments (private->impl, gc, new_segs, nsegs);
1638   
1639   if (new_segs != segs)
1640     g_free (new_segs);
1641
1642   RESTORE_GC (gc);
1643 }
1644
1645 static void
1646 gdk_window_draw_lines (GdkDrawable *drawable,
1647                        GdkGC       *gc,
1648                        GdkPoint    *points,
1649                        gint         npoints)
1650 {
1651   GdkWindowObject *private = (GdkWindowObject *)drawable;
1652   GdkPoint *new_points;
1653
1654   OFFSET_GC (gc);
1655
1656   if (GDK_WINDOW_DESTROYED (drawable))
1657     return;
1658   
1659   if (x_offset != 0 || y_offset != 0)
1660     {
1661       gint i;
1662
1663       new_points = g_new (GdkPoint, npoints);
1664       for (i=0; i<npoints; i++)
1665         {
1666           new_points[i].x = points[i].x - x_offset;
1667           new_points[i].y = points[i].y - y_offset;
1668         }
1669     }
1670   else
1671     new_points = points;
1672
1673   if (private->paint_stack)
1674     {
1675       GdkWindowPaint *paint = private->paint_stack->data;
1676       gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
1677     }
1678   else
1679     gdk_draw_lines (private->impl, gc, new_points, npoints);
1680
1681   if (new_points != points)
1682     g_free (new_points);
1683
1684   RESTORE_GC (gc);
1685 }
1686
1687 static void
1688 gdk_window_draw_glyphs (GdkDrawable      *drawable,
1689                         GdkGC            *gc,
1690                         PangoFont        *font,
1691                         gint              x,
1692                         gint              y,
1693                         PangoGlyphString *glyphs)
1694 {
1695   GdkWindowObject *private = (GdkWindowObject *)drawable;
1696
1697   OFFSET_GC (gc);
1698
1699   if (GDK_WINDOW_DESTROYED (drawable))
1700     return;
1701   
1702   if (private->paint_stack)
1703     {
1704       GdkWindowPaint *paint = private->paint_stack->data;
1705
1706       gdk_draw_glyphs (paint->pixmap, gc, font, x - x_offset, y - y_offset, glyphs);
1707     }
1708   else
1709     gdk_draw_glyphs (private->impl, gc, font,
1710                      x - x_offset, y - y_offset, glyphs);
1711
1712   RESTORE_GC (gc);
1713 }
1714
1715 static void
1716 gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
1717                                     GdkGC            *gc,
1718                                     PangoMatrix      *matrix,
1719                                     PangoFont        *font,
1720                                     gint              x,
1721                                     gint              y,
1722                                     PangoGlyphString *glyphs)
1723 {
1724   GdkWindowObject *private = (GdkWindowObject *)drawable;
1725   PangoMatrix tmp_matrix;
1726
1727   OFFSET_GC (gc);
1728
1729   if (GDK_WINDOW_DESTROYED (drawable))
1730     return;
1731
1732   if (x_offset != 0 || y_offset != 0)
1733     {
1734       if (matrix)
1735         {
1736           tmp_matrix = *matrix;
1737           tmp_matrix.x0 -= x_offset;
1738           tmp_matrix.y0 -= y_offset;
1739           matrix = &tmp_matrix;
1740         }
1741       else
1742         {
1743           x -= x_offset * PANGO_SCALE;
1744           y -= y_offset * PANGO_SCALE;
1745         }
1746     }
1747   
1748   if (private->paint_stack)
1749     {
1750       GdkWindowPaint *paint = private->paint_stack->data;
1751
1752       gdk_draw_glyphs_transformed (paint->pixmap, gc, matrix, font, x, y, glyphs);
1753     }
1754   else
1755     gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
1756
1757   RESTORE_GC (gc);
1758 }
1759
1760 typedef struct {
1761   cairo_t *cr; /* if non-null, it means use this cairo context */
1762   GdkGC *gc;   /* if non-null, it means use this GC instead */
1763 } BackingRectMethod;
1764
1765 static void
1766 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
1767 {
1768   GdkWindowObject *private = (GdkWindowObject *)window;
1769
1770   if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
1771     {
1772       GdkWindowPaint tmp_paint;
1773
1774       tmp_paint = *paint;
1775       tmp_paint.x_offset += private->x;
1776       tmp_paint.y_offset += private->y;
1777
1778       x_offset_cairo += private->x;
1779       y_offset_cairo += private->y;
1780
1781       setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
1782     }
1783   else if (private->bg_pixmap &&
1784            private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1785            private->bg_pixmap != GDK_NO_BG)
1786     {
1787 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
1788  * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
1789  * pixmap destination surface, can be very slow (on the order of seconds for a
1790  * whole-screen copy).  The workaround is to use pretty much the same code that
1791  * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
1792  * a tiled GC XFillRectangle().
1793  */
1794
1795 /* Actually computing this flag is left as an exercise for the reader */
1796 #if defined (G_OS_UNIX)
1797 #  define GDK_CAIRO_REPEAT_IS_FAST 0
1798 #else
1799 #  define GDK_CAIRO_REPEAT_IS_FAST 1
1800 #endif
1801
1802 #if GDK_CAIRO_REPEAT_IS_FAST
1803       cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
1804       cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
1805       cairo_surface_destroy (surface);
1806
1807       if (x_offset_cairo != 0 || y_offset_cairo != 0)
1808         {
1809           cairo_matrix_t matrix;
1810           cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
1811           cairo_pattern_set_matrix (pattern, &matrix);
1812         }
1813
1814       cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
1815
1816       method->cr = cairo_create (paint->surface);
1817       method->gc = NULL;
1818
1819       cairo_set_source (method->cr, pattern);
1820       cairo_pattern_destroy (pattern);
1821 #else
1822       guint gc_mask;
1823       GdkGCValues gc_values;
1824
1825       gc_values.fill = GDK_TILED;
1826       gc_values.tile = private->bg_pixmap;
1827       gc_values.ts_x_origin = -x_offset_cairo;
1828       gc_values.ts_y_origin = -y_offset_cairo;
1829
1830       gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
1831
1832       method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
1833 #endif
1834     }
1835   else
1836     {
1837       method->cr = cairo_create (paint->surface);
1838
1839       gdk_cairo_set_source_color (method->cr, &private->bg_color);
1840     }
1841 }
1842
1843 static void
1844 gdk_window_clear_backing_rect (GdkWindow *window,
1845                                gint       x,
1846                                gint       y,
1847                                gint       width,
1848                                gint       height)
1849 {
1850   GdkWindowObject *private = (GdkWindowObject *)window;
1851   GdkWindowPaint *paint = private->paint_stack->data;
1852   BackingRectMethod method;
1853 #if 0
1854   GTimer *timer;
1855   double elapsed;
1856 #endif
1857
1858   if (GDK_WINDOW_DESTROYED (window))
1859     return;
1860
1861 #if 0
1862   timer = g_timer_new ();
1863 #endif
1864
1865   method.cr = NULL;
1866   method.gc = NULL;
1867   setup_backing_rect_method (&method, window, paint, 0, 0);
1868
1869   if (method.cr)
1870     {
1871       g_assert (method.gc == NULL);
1872
1873       cairo_rectangle (method.cr, x, y, width, height);
1874       cairo_clip (method.cr);
1875
1876       gdk_cairo_region (method.cr, paint->region);
1877       cairo_fill (method.cr);
1878
1879       cairo_destroy (method.cr);
1880 #if 0
1881       elapsed = g_timer_elapsed (timer, NULL);
1882       g_print ("Draw the background with Cairo: %fs\n", elapsed);
1883 #endif
1884     }
1885   else
1886     {
1887       g_assert (method.gc != NULL);
1888
1889       gdk_gc_set_clip_region (method.gc, paint->region);
1890       gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
1891       g_object_unref (method.gc);
1892
1893 #if 0
1894       elapsed = g_timer_elapsed (timer, NULL);
1895       g_print ("Draw the background with GDK: %fs\n", elapsed);
1896 #endif
1897     }
1898
1899 #if 0
1900   g_timer_destroy (timer);
1901 #endif
1902 }
1903
1904 /**
1905  * gdk_window_clear:
1906  * @window: a #GdkWindow
1907  * 
1908  * Clears an entire @window to the background color or background pixmap.
1909  **/
1910 void
1911 gdk_window_clear (GdkWindow *window)
1912 {
1913   gint width, height;
1914   
1915   g_return_if_fail (window != NULL);
1916   g_return_if_fail (GDK_IS_WINDOW (window));
1917
1918   gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
1919   
1920   gdk_window_clear_area (window, 0, 0,
1921                          width, height);
1922 }
1923
1924 /**
1925  * gdk_window_clear_area:
1926  * @window: a #GdkWindow
1927  * @x: x coordinate of rectangle to clear
1928  * @y: y coordinate of rectangle to clear
1929  * @width: width of rectangle to clear
1930  * @height: height of rectangle to clear
1931  *
1932  * Clears an area of @window to the background color or background pixmap.
1933  * 
1934  **/
1935 void
1936 gdk_window_clear_area (GdkWindow *window,
1937                        gint       x,
1938                        gint       y,
1939                        gint       width,
1940                        gint       height)
1941 {
1942   GdkWindowObject *private = (GdkWindowObject *)window;
1943
1944   g_return_if_fail (window != NULL);
1945   g_return_if_fail (GDK_IS_WINDOW (window));
1946   
1947   if (private->paint_stack)
1948     gdk_window_clear_backing_rect (window, x, y, width, height);
1949   else
1950     _gdk_windowing_window_clear_area (window, x, y, width, height);
1951 }
1952
1953 /**
1954  * gdk_window_clear_area_e:
1955  * @window: a #GdkWindow
1956  * @x: x coordinate of rectangle to clear
1957  * @y: y coordinate of rectangle to clear
1958  * @width: width of rectangle to clear
1959  * @height: height of rectangle to clear
1960  *
1961  * Like gdk_window_clear_area(), but also generates an expose event for
1962  * the cleared area.
1963  *
1964  * This function has a stupid name because it dates back to the mists
1965  * time, pre-GDK-1.0.
1966  * 
1967  **/
1968 void
1969 gdk_window_clear_area_e (GdkWindow *window,
1970                          gint       x,
1971                          gint       y,
1972                          gint       width,
1973                          gint       height)
1974 {
1975   GdkWindowObject *private = (GdkWindowObject *)window;
1976
1977   g_return_if_fail (window != NULL);
1978   g_return_if_fail (GDK_IS_WINDOW (window));
1979   
1980   if (private->paint_stack)
1981     gdk_window_clear_backing_rect (window, x, y, width, height);
1982
1983   _gdk_windowing_window_clear_area_e (window, x, y, width, height);
1984 }
1985
1986 static void
1987 gdk_window_draw_image (GdkDrawable *drawable,
1988                        GdkGC       *gc,
1989                        GdkImage    *image,
1990                        gint         xsrc,
1991                        gint         ysrc,
1992                        gint         xdest,
1993                        gint         ydest,
1994                        gint         width,
1995                        gint         height)
1996 {
1997   GdkWindowObject *private = (GdkWindowObject *)drawable;
1998
1999   OFFSET_GC (gc);
2000
2001   if (GDK_WINDOW_DESTROYED (drawable))
2002     return;
2003   
2004   if (private->paint_stack)
2005     {
2006       GdkWindowPaint *paint = private->paint_stack->data;
2007       gdk_draw_image (paint->pixmap, gc, image, xsrc, ysrc,
2008                       xdest - x_offset, ydest - y_offset,
2009                       width, height);
2010
2011     }
2012   else
2013     gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
2014                     xdest - x_offset, ydest - y_offset,
2015                     width, height);
2016
2017   RESTORE_GC (gc);
2018 }
2019
2020 static void
2021 gdk_window_draw_pixbuf (GdkDrawable     *drawable,
2022                         GdkGC           *gc,
2023                         GdkPixbuf       *pixbuf,
2024                         gint             src_x,
2025                         gint             src_y,
2026                         gint             dest_x,
2027                         gint             dest_y,
2028                         gint             width,
2029                         gint             height,
2030                         GdkRgbDither     dither,
2031                         gint             x_dither,
2032                         gint             y_dither)
2033 {
2034   GdkWindowObject *private = (GdkWindowObject *)drawable;
2035
2036   if (GDK_WINDOW_DESTROYED (drawable))
2037     return;
2038   
2039   if (gc)
2040     {
2041       OFFSET_GC (gc);
2042   
2043       if (private->paint_stack)
2044         {
2045           GdkWindowPaint *paint = private->paint_stack->data;
2046           gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
2047                            dest_x - x_offset, dest_y - y_offset,
2048                            width, height,
2049                            dither, x_dither - x_offset, y_dither - y_offset);
2050         }
2051       else
2052         gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
2053                          dest_x - x_offset, dest_y - y_offset,
2054                          width, height,
2055                          dither, x_dither, y_dither);
2056       
2057       RESTORE_GC (gc);
2058     }
2059   else
2060     {
2061       gint x_offset, y_offset;
2062       gdk_window_get_offsets (drawable, &x_offset, &y_offset);
2063       
2064       if (private->paint_stack)
2065         {
2066           GdkWindowPaint *paint = private->paint_stack->data;
2067           gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
2068                            dest_x - x_offset, dest_y - y_offset,
2069                            width, height,
2070                             dither, x_dither - x_offset, y_dither - y_offset);
2071         }
2072       else
2073         gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
2074                          dest_x - x_offset, dest_y - y_offset,
2075                          width, height,
2076                          dither, x_dither, y_dither);
2077     }
2078 }
2079
2080 static void
2081 gdk_window_draw_trapezoids (GdkDrawable   *drawable,
2082                             GdkGC         *gc,
2083                             GdkTrapezoid  *trapezoids,
2084                             gint           n_trapezoids)
2085 {
2086   GdkWindowObject *private = (GdkWindowObject *)drawable;
2087   GdkTrapezoid *new_trapezoids = NULL;
2088
2089   OFFSET_GC (gc);
2090
2091   if (GDK_WINDOW_DESTROYED (drawable))
2092     return;
2093   
2094   if (x_offset != 0 || y_offset != 0)
2095     {
2096       gint i;
2097
2098       new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
2099       for (i=0; i < n_trapezoids; i++)
2100         {
2101           new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
2102           new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
2103           new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
2104           new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
2105           new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
2106           new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
2107         }
2108
2109       trapezoids = new_trapezoids;
2110     }
2111
2112   if (private->paint_stack)
2113     {
2114       GdkWindowPaint *paint = private->paint_stack->data;
2115       gdk_draw_trapezoids (paint->pixmap, gc, trapezoids, n_trapezoids);
2116     }
2117   else
2118     gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
2119   
2120   if (new_trapezoids)
2121     g_free (new_trapezoids);
2122
2123   RESTORE_GC (gc);
2124 }
2125
2126 static void
2127 gdk_window_real_get_size (GdkDrawable *drawable,
2128                           gint *width,
2129                           gint *height)
2130 {
2131   g_return_if_fail (GDK_IS_WINDOW (drawable));
2132
2133   gdk_drawable_get_size (GDK_WINDOW_OBJECT (drawable)->impl,
2134                          width, height);
2135 }
2136
2137 static GdkVisual*
2138 gdk_window_real_get_visual (GdkDrawable *drawable)
2139 {
2140   GdkColormap *colormap;
2141
2142   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
2143
2144   colormap = gdk_drawable_get_colormap (drawable);
2145   return colormap ? gdk_colormap_get_visual (colormap) : NULL;
2146 }
2147
2148 static gint
2149 gdk_window_real_get_depth (GdkDrawable *drawable)
2150 {
2151   g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
2152
2153   return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
2154 }
2155
2156 static GdkScreen*
2157 gdk_window_real_get_screen (GdkDrawable *drawable)
2158 {
2159   return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
2160 }
2161
2162 static void
2163 gdk_window_real_set_colormap (GdkDrawable *drawable,
2164                               GdkColormap *cmap)
2165 {
2166   g_return_if_fail (GDK_IS_WINDOW (drawable));  
2167
2168   if (GDK_WINDOW_DESTROYED (drawable))
2169     return;
2170   
2171   gdk_drawable_set_colormap (((GdkWindowObject*)drawable)->impl, cmap);
2172 }
2173
2174 static GdkColormap*
2175 gdk_window_real_get_colormap (GdkDrawable *drawable)
2176 {
2177   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
2178
2179   if (GDK_WINDOW_DESTROYED (drawable))
2180     return NULL;
2181   
2182   return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
2183 }
2184                       
2185 static GdkImage*
2186 gdk_window_copy_to_image (GdkDrawable     *drawable,
2187                           GdkImage        *image,
2188                           gint             src_x,
2189                           gint             src_y,
2190                           gint             dest_x,
2191                           gint             dest_y,
2192                           gint             width,
2193                           gint             height)
2194 {
2195   gint x_offset, y_offset;
2196   
2197   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
2198   
2199   if (GDK_WINDOW_DESTROYED (drawable))
2200     return NULL;
2201
2202   /* If we're here, a composite image was not necessary, so
2203    * we can ignore the paint stack.
2204    */
2205   
2206   _gdk_windowing_window_get_offsets (drawable, &x_offset, &y_offset);
2207   
2208   return gdk_drawable_copy_to_image (((GdkWindowObject*)drawable)->impl,
2209                                      image,
2210                                      src_x - x_offset,
2211                                      src_y - y_offset,
2212                                      dest_x, dest_y,
2213                                      width, height);
2214 }
2215
2216 static cairo_surface_t *
2217 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
2218 {
2219   GdkWindowObject *private = (GdkWindowObject*) drawable;
2220   cairo_surface_t *surface;
2221
2222   if (private->paint_stack)
2223     {
2224       GdkWindowPaint *paint = private->paint_stack->data;
2225
2226       surface = paint->surface;
2227       cairo_surface_reference (surface);
2228     }
2229   else
2230     surface = _gdk_drawable_ref_cairo_surface (private->impl);
2231
2232   return surface;
2233 }
2234
2235 /* Code for dirty-region queueing
2236  */
2237 static GSList *update_windows = NULL;
2238 static guint update_idle = 0;
2239 static gboolean debug_updates = FALSE;
2240
2241 static gboolean
2242 gdk_window_update_idle (gpointer data)
2243 {
2244   GDK_THREADS_ENTER ();
2245   gdk_window_process_all_updates ();
2246   GDK_THREADS_LEAVE ();
2247   
2248   return FALSE;
2249 }
2250
2251 static void
2252 gdk_window_schedule_update (GdkWindow *window)
2253 {
2254   if (window && GDK_WINDOW_OBJECT (window)->update_freeze_count)
2255     return;
2256
2257   if (!update_idle)
2258     {
2259       update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
2260                                      gdk_window_update_idle, NULL, NULL);
2261     }
2262 }
2263
2264 static void
2265 gdk_window_process_updates_internal (GdkWindow *window)
2266 {
2267   GdkWindowObject *private = (GdkWindowObject *)window;
2268   gboolean save_region = FALSE;
2269
2270   /* If an update got queued during update processing, we can get a
2271    * window in the update queue that has an empty update_area.
2272    * just ignore it.
2273    */
2274   if (private->update_area)
2275     {
2276       GdkRegion *update_area = private->update_area;
2277       private->update_area = NULL;
2278       
2279       if (_gdk_event_func && gdk_window_is_viewable (window))
2280         {
2281           GdkRectangle window_rect;
2282           GdkRegion *expose_region;
2283           GdkRegion *window_region;
2284           gint width, height;
2285
2286           if (debug_updates)
2287             {
2288               /* Make sure we see the red invalid area before redrawing. */
2289               gdk_display_sync (gdk_drawable_get_display (window));
2290               g_usleep (70000);
2291             }
2292           
2293           save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
2294
2295           if (save_region)
2296             expose_region = gdk_region_copy (update_area);
2297           else
2298             expose_region = update_area;
2299           
2300           gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
2301
2302           window_rect.x = 0;
2303           window_rect.y = 0;
2304           window_rect.width = width;
2305           window_rect.height = height;
2306
2307           window_region = gdk_region_rectangle (&window_rect);
2308           gdk_region_intersect (expose_region,
2309                                 window_region);
2310           gdk_region_destroy (window_region);
2311           
2312           if (!gdk_region_empty (expose_region) &&
2313               (private->event_mask & GDK_EXPOSURE_MASK))
2314             {
2315               GdkEvent event;
2316               
2317               event.expose.type = GDK_EXPOSE;
2318               event.expose.window = g_object_ref (window);
2319               event.expose.send_event = FALSE;
2320               event.expose.count = 0;
2321               event.expose.region = expose_region;
2322               gdk_region_get_clipbox (expose_region, &event.expose.area);
2323               
2324               (*_gdk_event_func) (&event, _gdk_event_data);
2325               
2326               g_object_unref (window);
2327             }
2328
2329           if (expose_region != update_area)
2330             gdk_region_destroy (expose_region);
2331         }
2332       if (!save_region)
2333         gdk_region_destroy (update_area);
2334     }
2335 }
2336
2337 static void
2338 flush_all_displays (void)
2339 {
2340   GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
2341   GSList *tmp_list;
2342
2343   for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
2344     gdk_display_flush (tmp_list->data);
2345
2346   g_slist_free (displays);
2347 }
2348
2349 /* Currently it is not possible to override
2350  * gdk_window_process_all_updates in the same manner as
2351  * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
2352  * by implementing the GdkPaintable interface.  If in the future a
2353  * backend would need this, the right solution would be to add a
2354  * method to GdkDisplay that can be optionally
2355  * NULL. gdk_window_process_all_updates can then walk the list of open
2356  * displays and call the mehod.
2357  */
2358
2359 /**
2360  * gdk_window_process_all_updates:
2361  *
2362  * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
2363  * in the application.
2364  * 
2365  **/
2366 void
2367 gdk_window_process_all_updates (void)
2368 {
2369   GSList *old_update_windows = update_windows;
2370   GSList *tmp_list = update_windows;
2371
2372   if (update_idle)
2373     g_source_remove (update_idle);
2374   
2375   update_windows = NULL;
2376   update_idle = 0;
2377
2378   g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
2379   
2380   while (tmp_list)
2381     {
2382       GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
2383       
2384       if (private->update_freeze_count)
2385         update_windows = g_slist_prepend (update_windows, private);
2386       else
2387         gdk_window_process_updates_internal (tmp_list->data);
2388       
2389       g_object_unref (tmp_list->data);
2390       tmp_list = tmp_list->next;
2391     }
2392
2393   g_slist_free (old_update_windows);
2394
2395   flush_all_displays ();
2396 }
2397
2398 /**
2399  * gdk_window_process_updates:
2400  * @window: a #GdkWindow
2401  * @update_children: whether to also process updates for child windows
2402  *
2403  * Sends one or more expose events to @window. The areas in each 
2404  * expose event will cover the entire update area for the window (see
2405  * gdk_window_invalidate_region() for details). Normally GDK calls
2406  * gdk_window_process_all_updates() on your behalf, so there's no
2407  * need to call this function unless you want to force expose events
2408  * to be delivered immediately and synchronously (vs. the usual
2409  * case, where GDK delivers them in an idle handler). Occasionally
2410  * this is useful to produce nicer scrolling behavior, for example.
2411  * 
2412  **/
2413 void
2414 gdk_window_process_updates (GdkWindow *window,
2415                             gboolean   update_children)
2416 {
2417   GdkWindowObject *private = (GdkWindowObject *)window;
2418
2419   g_return_if_fail (window != NULL);
2420   g_return_if_fail (GDK_IS_WINDOW (window));
2421   
2422   if (GDK_IS_PAINTABLE (private->impl) &&
2423       GDK_PAINTABLE_GET_IFACE (private->impl)->process_updates)
2424     {
2425       GDK_PAINTABLE_GET_IFACE (private->impl)->process_updates (GDK_PAINTABLE (private->impl), update_children);
2426       return;
2427     }
2428   
2429   if (private->update_area && !private->update_freeze_count)
2430     {      
2431       gdk_window_process_updates_internal (window);
2432       update_windows = g_slist_remove (update_windows, window);
2433     }
2434
2435   if (update_children)
2436     {
2437       GList *tmp_list = private->children;
2438       while (tmp_list)
2439         {
2440           gdk_window_process_updates (tmp_list->data, TRUE);
2441           tmp_list = tmp_list->next;
2442         }
2443     }
2444 }
2445
2446 /**
2447  * gdk_window_invalidate_rect:
2448  * @window: a #GdkWindow
2449  * @rect: rectangle to invalidate
2450  * @invalidate_children: whether to also invalidate child windows
2451  *
2452  * A convenience wrapper around gdk_window_invalidate_region() which
2453  * invalidates a rectangular region. See
2454  * gdk_window_invalidate_region() for details.
2455  * 
2456  **/
2457 void
2458 gdk_window_invalidate_rect   (GdkWindow    *window,
2459                               GdkRectangle *rect,
2460                               gboolean      invalidate_children)
2461 {
2462   GdkRectangle window_rect;
2463   GdkRegion *region;
2464   GdkWindowObject *private = (GdkWindowObject *)window;
2465
2466   g_return_if_fail (window != NULL);
2467   g_return_if_fail (GDK_IS_WINDOW (window));
2468
2469   if (GDK_WINDOW_DESTROYED (window))
2470     return;
2471   
2472   if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
2473     return;
2474
2475   if (!rect)
2476     {
2477       window_rect.x = 0;
2478       window_rect.y = 0;
2479       gdk_drawable_get_size (GDK_DRAWABLE (window),
2480                              &window_rect.width,
2481                              &window_rect.height);
2482       rect = &window_rect;
2483     }
2484
2485   region = gdk_region_rectangle (rect);
2486   gdk_window_invalidate_region (window, region, invalidate_children);
2487   gdk_region_destroy (region);
2488 }
2489
2490 static void
2491 draw_ugly_color (GdkWindow *window,
2492                 GdkRegion *region)
2493 {
2494   /* Draw ugly color all over the newly-invalid region */
2495   GdkColor ugly_color = { 0, 50000, 10000, 10000 };
2496   GdkGC *ugly_gc;
2497   GdkRectangle clipbox;
2498     
2499   ugly_gc = gdk_gc_new (window);
2500   gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
2501   gdk_gc_set_clip_region (ugly_gc, region);
2502
2503   gdk_region_get_clipbox (region, &clipbox);
2504   
2505   gdk_draw_rectangle (window,
2506                       ugly_gc,
2507                       TRUE,
2508                       clipbox.x, clipbox.y,
2509                       clipbox.width, clipbox.height);
2510   
2511   g_object_unref (ugly_gc);
2512 }
2513
2514 /**
2515  * gdk_window_invalidate_maybe_recurse:
2516  * @window: a #GdkWindow
2517  * @region: a #GdkRegion
2518  * @child_func: function to use to decide if to recurse to a child,
2519  *              %NULL means never recurse.
2520  * @user_data: data passed to @child_func
2521  *
2522  * Adds @region to the update area for @window. The update area is the
2523  * region that needs to be redrawn, or "dirty region." The call
2524  * gdk_window_process_updates() sends one or more expose events to the
2525  * window, which together cover the entire update area. An
2526  * application would normally redraw the contents of @window in
2527  * response to those expose events.
2528  *
2529  * GDK will call gdk_window_process_all_updates() on your behalf
2530  * whenever your program returns to the main loop and becomes idle, so
2531  * normally there's no need to do that manually, you just need to
2532  * invalidate regions that you know should be redrawn.
2533  *
2534  * The @child_func parameter controls whether the region of
2535  * each child window that intersects @region will also be invalidated.
2536  * Only children for which @child_func returns TRUE will have the area
2537  * invalidated.
2538  **/
2539 void
2540 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
2541                                      GdkRegion *region,
2542                                      gboolean (*child_func) (GdkWindow *, gpointer),
2543                                      gpointer   user_data)
2544 {
2545   GdkWindowObject *private = (GdkWindowObject *)window;
2546   GdkRegion *visible_region;
2547   GList *tmp_list;
2548
2549   g_return_if_fail (window != NULL);
2550   g_return_if_fail (GDK_IS_WINDOW (window));
2551
2552   if (GDK_WINDOW_DESTROYED (window))
2553     return;
2554   
2555   if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
2556     return;
2557
2558   if (GDK_IS_PAINTABLE (private->impl) &&
2559       GDK_PAINTABLE_GET_IFACE (private->impl)->invalidate_maybe_recurse)
2560     {
2561       GDK_PAINTABLE_GET_IFACE (private->impl)->invalidate_maybe_recurse (GDK_PAINTABLE (private->impl), region,
2562                                                                          child_func, user_data);
2563       return;
2564     }
2565
2566   visible_region = gdk_drawable_get_visible_region (window);
2567   gdk_region_intersect (visible_region, region);
2568
2569   tmp_list = private->children;
2570   while (tmp_list)
2571     {
2572       GdkWindowObject *child = tmp_list->data;
2573       
2574       if (!child->input_only)
2575         {
2576           GdkRegion *child_region;
2577           GdkRectangle child_rect;
2578           
2579           gdk_window_get_position ((GdkWindow *)child,
2580                                    &child_rect.x, &child_rect.y);
2581           gdk_drawable_get_size ((GdkDrawable *)child,
2582                                  &child_rect.width, &child_rect.height);
2583
2584           child_region = gdk_region_rectangle (&child_rect);
2585           
2586           /* remove child area from the invalid area of the parent */
2587           if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped)
2588             gdk_region_subtract (visible_region, child_region);
2589           
2590           if (child_func && (*child_func) ((GdkWindow *)child, user_data))
2591             {
2592               gdk_region_offset (region, - child_rect.x, - child_rect.y);
2593               gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
2594               gdk_region_intersect (child_region, region);
2595               
2596               gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
2597                                                    child_region, child_func, user_data);
2598               
2599               gdk_region_offset (region, child_rect.x, child_rect.y);
2600             }
2601
2602           gdk_region_destroy (child_region);
2603         }
2604
2605       tmp_list = tmp_list->next;
2606     }
2607   
2608   if (!gdk_region_empty (visible_region))
2609     {
2610       if (debug_updates)
2611         draw_ugly_color (window, region);
2612       
2613       if (private->update_area)
2614         {
2615           gdk_region_union (private->update_area, visible_region);
2616         }
2617       else
2618         {
2619           update_windows = g_slist_prepend (update_windows, window);
2620           private->update_area = gdk_region_copy (visible_region);
2621           
2622           gdk_window_schedule_update (window);
2623         }
2624     }
2625   
2626   gdk_region_destroy (visible_region);
2627 }
2628
2629 static gboolean
2630 true_predicate (GdkWindow *window,
2631                 gpointer   user_data)
2632 {
2633   return TRUE;
2634 }
2635
2636 /**
2637  * gdk_window_invalidate_region:
2638  * @window: a #GdkWindow
2639  * @region: a #GdkRegion
2640  * @invalidate_children: %TRUE to also invalidate child windows 
2641  *
2642  * Adds @region to the update area for @window. The update area is the
2643  * region that needs to be redrawn, or "dirty region." The call
2644  * gdk_window_process_updates() sends one or more expose events to the
2645  * window, which together cover the entire update area. An
2646  * application would normally redraw the contents of @window in
2647  * response to those expose events.
2648  *
2649  * GDK will call gdk_window_process_all_updates() on your behalf
2650  * whenever your program returns to the main loop and becomes idle, so
2651  * normally there's no need to do that manually, you just need to
2652  * invalidate regions that you know should be redrawn.
2653  *
2654  * The @invalidate_children parameter controls whether the region of
2655  * each child window that intersects @region will also be invalidated.
2656  * If %FALSE, then the update area for child windows will remain
2657  * unaffected. See gdk_window_invalidate_maybe_recurse if you need
2658  * fine grained control over which children are invalidated.
2659  **/
2660 void
2661 gdk_window_invalidate_region (GdkWindow *window,
2662                               GdkRegion *region,
2663                               gboolean   invalidate_children)
2664 {
2665   gdk_window_invalidate_maybe_recurse (window, region,
2666                                        invalidate_children ?
2667                                          true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
2668                                        NULL);
2669 }
2670
2671 /**
2672  * gdk_window_get_update_area:
2673  * @window: a #GdkWindow
2674  * 
2675  * Transfers ownership of the update area from @window to the caller
2676  * of the function. That is, after calling this function, @window will
2677  * no longer have an invalid/dirty region; the update area is removed
2678  * from @window and handed to you. If a window has no update area,
2679  * gdk_window_get_update_area() returns %NULL. You are responsible for
2680  * calling gdk_region_destroy() on the returned region if it's non-%NULL.
2681  * 
2682  * Return value: the update area for @window
2683  **/
2684 GdkRegion *
2685 gdk_window_get_update_area (GdkWindow *window)
2686 {
2687   GdkWindowObject *private = (GdkWindowObject *)window;
2688   GdkRegion *tmp_region;
2689
2690   g_return_val_if_fail (window != NULL, NULL);
2691   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2692
2693   if (private->update_area)
2694     {
2695       tmp_region = private->update_area;
2696       private->update_area = NULL;
2697
2698       update_windows = g_slist_remove (update_windows, window);
2699       
2700       return tmp_region;
2701     }
2702   else
2703     return NULL;
2704 }
2705
2706 /**
2707  * _gdk_window_clear_update_area:
2708  * @window: a #GdkWindow.
2709  * 
2710  * Internal function to clear the update area for a window. This
2711  * is called when the window is hidden or destroyed.
2712  **/
2713 void
2714 _gdk_window_clear_update_area (GdkWindow *window)
2715 {
2716   GdkWindowObject *private = (GdkWindowObject *)window;
2717
2718   g_return_if_fail (window != NULL);
2719   g_return_if_fail (GDK_IS_WINDOW (window));
2720
2721   if (private->update_area)
2722     {
2723       update_windows = g_slist_remove (update_windows, window);
2724       
2725       gdk_region_destroy (private->update_area);
2726       private->update_area = NULL;
2727     }
2728 }
2729
2730 /**
2731  * gdk_window_freeze_updates:
2732  * @window: a #GdkWindow
2733  * 
2734  * Temporarily freezes a window such that it won't receive expose
2735  * events.  The window will begin receiving expose events again when
2736  * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
2737  * has been called more than once, gdk_window_thaw_updates() must be called
2738  * an equal number of times to begin processing exposes.
2739  **/
2740 void
2741 gdk_window_freeze_updates (GdkWindow *window)
2742 {
2743   GdkWindowObject *private = (GdkWindowObject *)window;
2744
2745   g_return_if_fail (window != NULL);
2746   g_return_if_fail (GDK_IS_WINDOW (window));
2747
2748   private->update_freeze_count++;
2749 }
2750
2751 /**
2752  * gdk_window_thaw_updates:
2753  * @window: a #GdkWindow
2754  * 
2755  * Thaws a window frozen with gdk_window_freeze_updates().
2756  **/
2757 void
2758 gdk_window_thaw_updates (GdkWindow *window)
2759 {
2760   GdkWindowObject *private = (GdkWindowObject *)window;
2761
2762   g_return_if_fail (window != NULL);
2763   g_return_if_fail (GDK_IS_WINDOW (window));
2764   g_return_if_fail (private->update_freeze_count > 0);
2765
2766   if (--private->update_freeze_count == 0)
2767     gdk_window_schedule_update (window);
2768 }
2769
2770 /**
2771  * gdk_window_set_debug_updates:
2772  * @setting: %TRUE to turn on update debugging
2773  *
2774  * With update debugging enabled, calls to
2775  * gdk_window_invalidate_region() clear the invalidated region of the
2776  * screen to a noticeable color, and GDK pauses for a short time
2777  * before sending exposes to windows during
2778  * gdk_window_process_updates().  The net effect is that you can see
2779  * the invalid region for each window and watch redraws as they
2780  * occur. This allows you to diagnose inefficiencies in your application.
2781  *
2782  * In essence, because the GDK rendering model prevents all flicker,
2783  * if you are redrawing the same region 400 times you may never
2784  * notice, aside from noticing a speed problem. Enabling update
2785  * debugging causes GTK to flicker slowly and noticeably, so you can
2786  * see exactly what's being redrawn when, in what order.
2787  *
2788  * The --gtk-debug=updates command line option passed to GTK+ programs
2789  * enables this debug option at application startup time. That's
2790  * usually more useful than calling gdk_window_set_debug_updates()
2791  * yourself, though you might want to use this function to enable
2792  * updates sometime after application startup time.
2793  * 
2794  **/
2795 void
2796 gdk_window_set_debug_updates (gboolean setting)
2797 {
2798   debug_updates = setting;
2799 }
2800
2801 /**
2802  * gdk_window_constrain_size:
2803  * @geometry: a #GdkGeometry structure
2804  * @flags: a mask indicating what portions of @geometry are set
2805  * @width: desired width of window
2806  * @height: desired height of the window
2807  * @new_width: location to store resulting width
2808  * @new_height: location to store resulting height
2809  * 
2810  * Constrains a desired width and height according to a 
2811  * set of geometry hints (such as minimum and maximum size).
2812  */
2813 void
2814 gdk_window_constrain_size (GdkGeometry *geometry,
2815                            guint        flags,
2816                            gint         width,
2817                            gint         height,
2818                            gint        *new_width,
2819                            gint        *new_height)
2820 {
2821   /* This routine is partially borrowed from fvwm.
2822    *
2823    * Copyright 1993, Robert Nation
2824    *     You may use this code for any purpose, as long as the original
2825    *     copyright remains in the source code and all documentation
2826    *
2827    * which in turn borrows parts of the algorithm from uwm
2828    */
2829   gint min_width = 0;
2830   gint min_height = 0;
2831   gint base_width = 0;
2832   gint base_height = 0;
2833   gint xinc = 1;
2834   gint yinc = 1;
2835   gint max_width = G_MAXINT;
2836   gint max_height = G_MAXINT;
2837   
2838 #define FLOOR(value, base)      ( ((gint) ((value) / (base))) * (base) )
2839
2840   if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
2841     {
2842       base_width = geometry->base_width;
2843       base_height = geometry->base_height;
2844       min_width = geometry->min_width;
2845       min_height = geometry->min_height;
2846     }
2847   else if (flags & GDK_HINT_BASE_SIZE)
2848     {
2849       base_width = geometry->base_width;
2850       base_height = geometry->base_height;
2851       min_width = geometry->base_width;
2852       min_height = geometry->base_height;
2853     }
2854   else if (flags & GDK_HINT_MIN_SIZE)
2855     {
2856       base_width = geometry->min_width;
2857       base_height = geometry->min_height;
2858       min_width = geometry->min_width;
2859       min_height = geometry->min_height;
2860     }
2861
2862   if (flags & GDK_HINT_MAX_SIZE)
2863     {
2864       max_width = geometry->max_width ;
2865       max_height = geometry->max_height;
2866     }
2867
2868   if (flags & GDK_HINT_RESIZE_INC)
2869     {
2870       xinc = MAX (xinc, geometry->width_inc);
2871       yinc = MAX (yinc, geometry->height_inc);
2872     }
2873   
2874   /* clamp width and height to min and max values
2875    */
2876   width = CLAMP (width, min_width, max_width);
2877   height = CLAMP (height, min_height, max_height);
2878   
2879   /* shrink to base + N * inc
2880    */
2881   width = base_width + FLOOR (width - base_width, xinc);
2882   height = base_height + FLOOR (height - base_height, yinc);
2883
2884   /* constrain aspect ratio, according to:
2885    *
2886    *                width     
2887    * min_aspect <= -------- <= max_aspect
2888    *                height    
2889    */
2890   
2891   if (flags & GDK_HINT_ASPECT &&
2892       geometry->min_aspect > 0 &&
2893       geometry->max_aspect > 0)
2894     {
2895       gint delta;
2896
2897       if (geometry->min_aspect * height > width)
2898         {
2899           delta = FLOOR (height - width / geometry->min_aspect, yinc);
2900           if (height - delta >= min_height)
2901             height -= delta;
2902           else
2903             { 
2904               delta = FLOOR (height * geometry->min_aspect - width, xinc);
2905               if (width + delta <= max_width) 
2906                 width += delta;
2907             }
2908         }
2909       
2910       if (geometry->max_aspect * height < width)
2911         {
2912           delta = FLOOR (width - height * geometry->max_aspect, xinc);
2913           if (width - delta >= min_width) 
2914             width -= delta;
2915           else
2916             {
2917               delta = FLOOR (width / geometry->max_aspect - height, yinc);
2918               if (height + delta <= max_height)
2919                 height += delta;
2920             }
2921         }
2922     }
2923
2924 #undef FLOOR
2925   
2926   *new_width = width;
2927   *new_height = height;
2928 }
2929
2930 /**
2931  * gdk_window_get_pointer:
2932  * @window: a #GdkWindow
2933  * @x: return location for X coordinate of pointer
2934  * @y: return location for Y coordinate of pointer
2935  * @mask: return location for modifier mask
2936  *
2937  * Obtains the current pointer position and modifier state.
2938  * The position is given in coordinates relative to @window.
2939  * 
2940  * Return value: the window containing the pointer (as with
2941  * gdk_window_at_pointer()), or %NULL if the window containing the
2942  * pointer isn't known to GDK
2943  **/
2944 GdkWindow*
2945 gdk_window_get_pointer (GdkWindow         *window,
2946                         gint              *x,
2947                         gint              *y,
2948                         GdkModifierType   *mask)
2949 {
2950   GdkDisplay *display;
2951   gint tmp_x, tmp_y;
2952   GdkModifierType tmp_mask;
2953   GdkWindow *child;
2954   
2955   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
2956
2957   if (window)
2958     {
2959       display = gdk_drawable_get_display (window);
2960     }
2961   else
2962     {
2963       GdkScreen *screen = gdk_screen_get_default ();
2964
2965       display = gdk_screen_get_display (screen);
2966       window = gdk_screen_get_root_window (screen);
2967       
2968       GDK_NOTE (MULTIHEAD,
2969                 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
2970                            "is not multihead safe"));
2971     }
2972
2973   child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
2974
2975   if (x)
2976     *x = tmp_x;
2977   if (y)
2978     *y = tmp_y;
2979   if (mask)
2980     *mask = tmp_mask;
2981
2982   return child;
2983 }
2984
2985 /**
2986  * gdk_window_at_pointer:
2987  * @win_x: return location for origin of the window under the pointer
2988  * @win_y: return location for origin of the window under the pointer
2989  * 
2990  * Obtains the window underneath the mouse pointer, returning the
2991  * location of that window in @win_x, @win_y. Returns %NULL if the
2992  * window under the mouse pointer is not known to GDK (if the window
2993  * belongs to another application and a #GdkWindow hasn't been created
2994  * for it with gdk_window_foreign_new())
2995  *
2996  * NOTE: For multihead-aware widgets or applications use
2997  * gdk_display_get_window_at_pointer() instead.
2998  * 
2999  * Return value: window under the mouse pointer
3000  **/
3001 GdkWindow*
3002 gdk_window_at_pointer (gint *win_x,
3003                        gint *win_y)
3004 {
3005   return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
3006 }
3007
3008 /**
3009  * gdk_get_default_root_window:
3010  * 
3011  * Obtains the root window (parent all other windows are inside)
3012  * for the default display and screen.
3013  * 
3014  * Return value: the default root window
3015  **/
3016 GdkWindow *
3017 gdk_get_default_root_window (void)
3018 {
3019   return gdk_screen_get_root_window (gdk_screen_get_default ());
3020 }
3021
3022 /**
3023  * gdk_window_foreign_new:
3024  * @anid: a native window handle.
3025  * 
3026  * Wraps a native window for the default display in a #GdkWindow.
3027  * This may fail if the window has been destroyed.
3028  *
3029  * For example in the X backend, a native window handle is an Xlib
3030  * <type>XID</type>.
3031  * 
3032  * Return value: the newly-created #GdkWindow wrapper for the 
3033  *    native window or %NULL if the window has been destroyed.
3034  **/
3035 GdkWindow *
3036 gdk_window_foreign_new (GdkNativeWindow anid)
3037 {
3038   return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
3039 }
3040
3041 #define __GDK_WINDOW_C__
3042 #include "gdkaliasdef.c"