]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkgeometry-win32.c
New file, just a quick hack of the X11 version.
[~andy/gtk] / gdk / win32 / gdkgeometry-win32.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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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 /* gdkgeometry-win32.c: emulation of 32 bit coordinates within the
21  * limits of Win32 GDI. Just a copy of the X11 version, more or less.
22  * Probably totally bogus in functionality. Just a quick hack, to
23  * get the thing to build. Need to write some test code for it.
24  * Well, need to find out what it is supposed to do first ;-)
25  *
26  * The X11 version by Owen Taylor <otaylor@redhat.com>
27  * Copyright Red Hat, Inc. 2000
28  * Win32 hack by Tor Lillqvist <tml@iki.fi>
29  */
30
31 #include "gdk.h"                /* For gdk_rectangle_intersect */
32 #include "gdkregion.h"
33 #include "gdkregion-generic.h"
34 #include "gdkinternals.h"
35 #include "gdkprivate-win32.h"
36
37 typedef struct _GdkWindowQueueItem GdkWindowQueueItem;
38 typedef struct _GdkWindowParentPos GdkWindowParentPos;
39
40 typedef enum {
41   GDK_WINDOW_QUEUE_TRANSLATE,
42   GDK_WINDOW_QUEUE_ANTIEXPOSE
43 } GdkWindowQueueType;
44
45 struct _GdkWindowQueueItem
46 {
47   GdkWindow *window;
48   gulong serial;
49   GdkWindowQueueType type;
50   union {
51     struct {
52       gint dx;
53       gint dy;
54     } translate;
55     struct {
56       GdkRegion *area;
57     } antiexpose;
58   } u;
59 };
60
61 struct _GdkWindowParentPos
62 {
63   gint x;
64   gint y;
65   gint win32_x;
66   gint win32_y;
67   GdkRectangle clip_rect;
68 };
69
70 static void gdk_window_compute_position   (GdkWindow            *window,
71                                            GdkWindowParentPos   *parent_pos,
72                                            GdkWin32PositionInfo *info);
73 static void gdk_window_compute_parent_pos (GdkWindow          *window,
74                                            GdkWindowParentPos *parent_pos);
75 static void gdk_window_premove            (GdkWindow          *window,
76                                            GdkWindowParentPos *parent_pos);
77 static void gdk_window_postmove           (GdkWindow          *window,
78                                            GdkWindowParentPos *parent_pos);
79 static void gdk_window_queue_translation  (GdkWindow          *window,
80                                            gint                dx,
81                                            gint                dy);
82 static void gdk_window_tmp_unset_bg       (GdkWindow          *window);
83 static void gdk_window_tmp_reset_bg       (GdkWindow          *window);
84 static void gdk_window_clip_changed       (GdkWindow          *window,
85                                            GdkRectangle       *old_clip,
86                                            GdkRectangle       *new_clip);
87
88 static GSList *translate_queue = NULL;
89
90 void
91 _gdk_windowing_window_get_offsets (GdkWindow *window,
92                                    gint      *x_offset,
93                                    gint      *y_offset)
94 {
95   GdkWindowWin32Data *data = GDK_WINDOW_WIN32DATA (window);
96
97   *x_offset = data->position_info.x_offset;
98   *y_offset = data->position_info.y_offset;
99 }
100
101 void
102 _gdk_window_init_position (GdkWindow *window)
103 {
104   GdkWindowWin32Data *data;
105   GdkWindowParentPos parent_pos;
106
107   g_return_if_fail (window != NULL);
108   g_return_if_fail (GDK_IS_WINDOW (window));
109
110   data = GDK_WINDOW_WIN32DATA (window);
111
112   gdk_window_compute_parent_pos (window, &parent_pos);
113   gdk_window_compute_position (window, &parent_pos, &data->position_info);
114 }
115
116 void
117 _gdk_window_move_resize_child (GdkWindow *window,
118                                gint       x,
119                                gint       y,
120                                gint       width,
121                                gint       height)
122 {
123   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
124   GdkWin32PositionInfo new_info;
125   GdkWindowParentPos parent_pos;
126   GdkWindowWin32Data *data;
127   RECT rect;
128   GList *tmp_list;
129   gint d_xoffset, d_yoffset;
130   gint dx, dy;
131   gboolean is_move;
132   gboolean is_resize;
133   
134   g_return_if_fail (window != NULL);
135   g_return_if_fail (GDK_IS_WINDOW (window));
136
137   data = GDK_WINDOW_WIN32DATA (window);
138
139   dx = x - private->x;
140   dy = y - private->y;
141   
142   is_move = dx != 0 || dy != 0;
143   is_resize = private->drawable.width != width || private->drawable.height != height;
144
145   if (!is_move && !is_resize)
146     return;
147   
148   private->x = x;
149   private->y = y;
150   private->drawable.width = width;
151   private->drawable.height = height;
152
153   gdk_window_compute_parent_pos (window, &parent_pos);
154   gdk_window_compute_position (window, &parent_pos, &new_info);
155
156   gdk_window_clip_changed (window, &data->position_info.clip_rect, &new_info.clip_rect);
157
158   parent_pos.x += private->x;
159   parent_pos.y += private->y;
160   parent_pos.win32_x += new_info.x;
161   parent_pos.win32_y += new_info.y;
162   parent_pos.clip_rect = new_info.clip_rect;
163
164   d_xoffset = new_info.x_offset - data->position_info.x_offset;
165   d_yoffset = new_info.y_offset - data->position_info.y_offset;
166   
167   if (d_xoffset != 0 || d_yoffset != 0)
168     {
169       gint new_x0, new_y0, new_x1, new_y1;
170
171       gdk_window_set_static_gravities (window, TRUE);
172
173       if (d_xoffset < 0 || d_yoffset < 0)
174         gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
175         
176       if (d_xoffset < 0)
177         {
178           new_x0 = data->position_info.x + d_xoffset;
179           new_x1 = data->position_info.x + data->position_info.width;
180         }
181       else
182         {
183           new_x0 = data->position_info.x;
184           new_x1 = data->position_info.x + new_info.width + d_xoffset;
185         }
186
187       if (d_yoffset < 0)
188         {
189           new_y0 = data->position_info.y + d_yoffset;
190           new_y1 = data->position_info.y + data->position_info.height;
191         }
192       else
193         {
194           new_y0 = data->position_info.y;
195           new_y1 = data->position_info.y + new_info.height + d_yoffset;
196         }
197       
198       if (!MoveWindow (GDK_DRAWABLE_XID (window),
199                        new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0,
200                        FALSE))
201           WIN32_API_FAILED ("MoveWindow");
202       
203       tmp_list = private->children;
204       while (tmp_list)
205         {
206           gdk_window_premove (tmp_list->data, &parent_pos);
207           tmp_list = tmp_list->next;
208         }
209
210       GetClientRect (GDK_DRAWABLE_XID (window), &rect);
211
212       if (!MoveWindow (GDK_DRAWABLE_XID (window),
213                        new_x0 + dx, new_y0 + dy,
214                        rect.right - rect.left, rect.bottom - rect.top,
215                        FALSE))
216           WIN32_API_FAILED ("MoveWindow");
217       
218       if (d_xoffset > 0 || d_yoffset > 0)
219         gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
220       
221       if (!MoveWindow (GDK_DRAWABLE_XID (window),
222                        new_info.x, new_info.y, new_info.width, new_info.height,
223                        FALSE))
224           WIN32_API_FAILED ("MoveWindow");
225       
226       if (data->position_info.no_bg)
227         gdk_window_tmp_reset_bg (window);
228
229       if (!data->position_info.mapped && new_info.mapped && private->mapped)
230         ShowWindow (GDK_DRAWABLE_XID (window), SW_SHOWNA);
231       
232       data->position_info = new_info;
233       
234       tmp_list = private->children;
235       while (tmp_list)
236         {
237           gdk_window_postmove (tmp_list->data, &parent_pos);
238           tmp_list = tmp_list->next;
239         }
240     }
241   else
242     {
243       if (is_move && is_resize)
244         gdk_window_set_static_gravities (window, FALSE);
245
246       if (data->position_info.mapped && !new_info.mapped)
247         ShowWindow (GDK_DRAWABLE_XID (window), SW_HIDE);
248       
249       tmp_list = private->children;
250       while (tmp_list)
251         {
252           gdk_window_premove (tmp_list->data, &parent_pos);
253           tmp_list = tmp_list->next;
254         }
255
256       if (is_resize)
257         {
258           if (!MoveWindow (GDK_DRAWABLE_XID (window),
259                            new_info.x, new_info.y, new_info.width, new_info.height,
260                            FALSE))
261             WIN32_API_FAILED ("MoveWindow");
262         }
263       else
264         {
265           GetClientRect (GDK_DRAWABLE_XID (window), &rect);
266           if (!MoveWindow (GDK_DRAWABLE_XID (window),
267                            new_info.x, new_info.y,
268                            rect.right - rect.left, rect.bottom - rect.top,
269                            FALSE))
270             WIN32_API_FAILED ("MoveWindow");
271         }
272
273       tmp_list = private->children;
274       while (tmp_list)
275         {
276           gdk_window_postmove (tmp_list->data, &parent_pos);
277           tmp_list = tmp_list->next;
278         }
279
280       if (data->position_info.no_bg)
281         gdk_window_tmp_reset_bg (window);
282
283       if (!data->position_info.mapped && new_info.mapped && private->mapped)
284         ShowWindow (GDK_DRAWABLE_XID (window), SW_SHOWNA);
285
286       data->position_info = new_info;
287     }
288 }
289
290 static void
291 gdk_window_compute_position (GdkWindow            *window,
292                              GdkWindowParentPos   *parent_pos,
293                              GdkWin32PositionInfo *info)
294 {
295   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
296   int parent_x_offset;
297   int parent_y_offset;
298   
299   info->big = FALSE;
300   
301   if (private->drawable.width <= 32768)
302     {
303       info->width = private->drawable.width;
304       info->x = parent_pos->x + private->x - parent_pos->win32_x;
305     }
306   else
307     {
308       info->big = TRUE;
309       info->width = 32768;
310       if (parent_pos->x + private->x < -16384)
311         {
312           if (parent_pos->x + private->x + private->drawable.width < 16384)
313             info->x = parent_pos->x + private->x + private->drawable.width - 32768 - parent_pos->win32_x;
314           else
315             info->x = -16384 - parent_pos->win32_y;
316         }
317       else
318         info->x = parent_pos->x + private->x - parent_pos->win32_x;
319     }
320
321   if (private->drawable.height <= 32768)
322     {
323       info->height = private->drawable.height;
324       info->y = parent_pos->y + private->y - parent_pos->win32_y;
325     }
326   else
327     {
328       info->big = TRUE;
329       info->height = 32768;
330       if (parent_pos->y + private->y < -16384)
331         {
332           if (parent_pos->y + private->y + private->drawable.height < 16384)
333             info->y = parent_pos->y + private->y + private->drawable.height - 32768 - parent_pos->win32_y;
334           else
335             info->y = -16384 - parent_pos->win32_y;
336         }
337       else
338         info->y = parent_pos->y + private->y - parent_pos->win32_y;
339     }
340
341   parent_x_offset = parent_pos->win32_x - parent_pos->x;
342   parent_y_offset = parent_pos->win32_y - parent_pos->y;
343   
344   info->x_offset = parent_x_offset + info->x - private->x;
345   info->y_offset = parent_y_offset + info->y - private->y;
346
347   /* We don't considering the clipping of toplevel windows and their immediate children
348    * by their parents, and simply always map those windows.
349    */
350   if (parent_pos->clip_rect.width == G_MAXINT)
351     info->mapped = TRUE;
352   /* Check if the window would wrap around into the visible space in either direction */
353   else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
354       info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
355       info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
356       info->y + info->width + parent_y_offset  > parent_pos->clip_rect.y + 65536)
357     info->mapped = FALSE;
358   else
359     info->mapped = TRUE;
360
361   info->no_bg = FALSE;
362
363   if (GDK_DRAWABLE_TYPE (private) == GDK_WINDOW_CHILD)
364     {
365       info->clip_rect.x = private->x;
366       info->clip_rect.y = private->y;
367       info->clip_rect.width = private->drawable.width;
368       info->clip_rect.height = private->drawable.height;
369       
370       gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
371
372       info->clip_rect.x -= private->x;
373       info->clip_rect.y -= private->y;
374     }
375   else
376     {
377       info->clip_rect.x = 0;
378       info->clip_rect.y = 0;
379       info->clip_rect.width = G_MAXINT;
380       info->clip_rect.height = G_MAXINT;
381     }
382 }
383
384 static void
385 gdk_window_compute_parent_pos (GdkWindow          *window,
386                                GdkWindowParentPos *parent_pos)
387 {
388   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
389   GdkWindowWin32Data *data;
390   GdkRectangle tmp_clip;
391   
392   int clip_xoffset = 0;
393   int clip_yoffset = 0;
394
395   parent_pos->x = 0;
396   parent_pos->y = 0;
397   parent_pos->win32_x = 0;
398   parent_pos->win32_y = 0;
399
400   /* We take a simple approach here and simply consider toplevel
401    * windows not to clip their children on the right/bottom, since the
402    * size of toplevel windows is not directly under our
403    * control. Clipping only really matters when scrolling and
404    * generally we aren't going to be moving the immediate child of a
405    * toplevel beyond the bounds of that toplevel.
406    *
407    * We could go ahead and recompute the clips of toplevel windows and
408    * their descendents when we receive size notification, but it would
409    * probably not be an improvement in most cases.
410    */
411   parent_pos->clip_rect.x = 0;
412   parent_pos->clip_rect.y = 0;
413   parent_pos->clip_rect.width = G_MAXINT;
414   parent_pos->clip_rect.height = G_MAXINT;
415
416   private = (GdkWindowPrivate *)private->parent;
417   while (private && private->drawable.window_type == GDK_WINDOW_CHILD)
418     {
419       data = (GdkWindowWin32Data *)private->drawable.klass_data;
420
421       tmp_clip.x = - clip_xoffset;
422       tmp_clip.y = - clip_yoffset;
423       tmp_clip.width = private->drawable.width;
424       tmp_clip.height = private->drawable.height;
425
426       gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
427
428       parent_pos->x += private->x;
429       parent_pos->y += private->y;
430       parent_pos->win32_x += data->position_info.x;
431       parent_pos->win32_y += data->position_info.y;
432
433       clip_xoffset += private->x;
434       clip_yoffset += private->y;
435
436       private = (GdkWindowPrivate *)private->parent;
437     }
438 }
439
440 static void
441 gdk_window_premove (GdkWindow          *window,
442                     GdkWindowParentPos *parent_pos)
443 {
444   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
445   GdkWindowWin32Data *data = GDK_WINDOW_WIN32DATA (window);
446   GdkWin32PositionInfo new_info;
447   GList *tmp_list;
448   gint d_xoffset, d_yoffset;
449   GdkWindowParentPos this_pos;
450   
451   gdk_window_compute_position (window, parent_pos, &new_info);
452
453   gdk_window_clip_changed (window, &data->position_info.clip_rect, &new_info.clip_rect);
454
455   this_pos.x = parent_pos->x + private->x;
456   this_pos.y = parent_pos->y + private->y;
457   this_pos.win32_x = parent_pos->win32_x + new_info.x;
458   this_pos.win32_y = parent_pos->win32_y + new_info.y;
459   this_pos.clip_rect = new_info.clip_rect;
460
461   if (data->position_info.mapped && !new_info.mapped)
462     ShowWindow (GDK_DRAWABLE_XID (window), SW_HIDE);
463
464   d_xoffset = new_info.x_offset - data->position_info.x_offset;
465   d_yoffset = new_info.y_offset - data->position_info.y_offset;
466   
467   if (d_xoffset != 0 || d_yoffset != 0)
468     {
469       gint new_x0, new_y0, new_x1, new_y1;
470
471       if (d_xoffset < 0 || d_yoffset < 0)
472         gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
473         
474       if (d_xoffset < 0)
475         {
476           new_x0 = data->position_info.x + d_xoffset;
477           new_x1 = data->position_info.x + data->position_info.width;
478         }
479       else
480         {
481           new_x0 = data->position_info.x;
482           new_x1 = data->position_info.x + new_info.width + d_xoffset;
483         }
484
485       if (d_yoffset < 0)
486         {
487           new_y0 = data->position_info.y + d_yoffset;
488           new_y1 = data->position_info.y + data->position_info.height;
489         }
490       else
491         {
492           new_y0 = data->position_info.y;
493           new_y1 = data->position_info.y + new_info.height + d_yoffset;
494         }
495
496       if (!MoveWindow (GDK_DRAWABLE_XID (window),
497                        new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0,
498                        FALSE))
499         WIN32_API_FAILED ("MoveWindow");
500     }
501
502   tmp_list = private->children;
503   while (tmp_list)
504     {
505       gdk_window_premove (tmp_list->data, &this_pos);
506       tmp_list = tmp_list->next;
507     }
508 }
509
510 static void
511 gdk_window_postmove (GdkWindow          *window,
512                      GdkWindowParentPos *parent_pos)
513 {
514   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
515   GdkWindowWin32Data *data = (GdkWindowWin32Data *)private->drawable.klass_data;
516   GdkWin32PositionInfo new_info;
517   GList *tmp_list;
518   gint d_xoffset, d_yoffset;
519   GdkWindowParentPos this_pos;
520   
521   gdk_window_compute_position (window, parent_pos, &new_info);
522
523   this_pos.x = parent_pos->x + private->x;
524   this_pos.y = parent_pos->y + private->y;
525   this_pos.win32_x = parent_pos->win32_x + new_info.x;
526   this_pos.win32_y = parent_pos->win32_y + new_info.y;
527   this_pos.clip_rect = new_info.clip_rect;
528
529   d_xoffset = new_info.x_offset - data->position_info.x_offset;
530   d_yoffset = new_info.y_offset - data->position_info.y_offset;
531   
532   if (d_xoffset != 0 || d_yoffset != 0)
533     {
534       if (d_xoffset > 0 || d_yoffset > 0)
535         gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
536         
537       if (!MoveWindow (GDK_DRAWABLE_XID (window),
538                        new_info.x, new_info.y, new_info.width, new_info.height,
539                        FALSE))
540         WIN32_API_FAILED ("MoveWindow");
541     }
542
543   if (!data->position_info.mapped && new_info.mapped && private->mapped)
544     ShowWindow (GDK_DRAWABLE_XID (window), SW_SHOWNA);
545
546   if (data->position_info.no_bg)
547     gdk_window_tmp_reset_bg (window);
548
549   data->position_info = new_info;
550
551   tmp_list = private->children;
552   while (tmp_list)
553     {
554       gdk_window_postmove (tmp_list->data, &this_pos);
555       tmp_list = tmp_list->next;
556     }
557 }
558
559 static void
560 gdk_window_queue_translation (GdkWindow *window,
561                               gint       dx,
562                               gint       dy)
563 {
564   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
565   item->window = window;
566   item->serial = GetMessageTime ();
567   item->type = GDK_WINDOW_QUEUE_TRANSLATE;
568   item->u.translate.dx = dx;
569   item->u.translate.dy = dy;
570
571   GDK_NOTE (EVENTS, g_print ("gdk_window_queue_translation %#x %d %d,%d\n",
572                              GDK_DRAWABLE_XID (window),
573                              item->serial,
574                              dx, dy));
575
576   gdk_drawable_ref (window);
577   translate_queue = g_slist_append (translate_queue, item);
578 }
579
580 gboolean
581 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
582                                         GdkRegion *area)
583 {
584   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
585
586   item->window = window;
587   item->serial = GetMessageTime ();
588   item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
589   item->u.antiexpose.area = area;
590
591   GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose %#x %d %dx%d@+%d+%d\n",
592                              GDK_DRAWABLE_XID (window),
593                              item->serial,
594                              area->extents.x2 - area->extents.x1,
595                              area->extents.y2 - area->extents.y1,
596                              area->extents.x1, area->extents.y1));
597
598   gdk_drawable_ref (window);
599   translate_queue = g_slist_append (translate_queue, item);
600
601   return TRUE;
602 }
603
604 void
605 _gdk_window_process_expose (GdkWindow    *window,
606                             gulong        serial,
607                             GdkRectangle *area)
608 {
609   GdkWindowWin32Data *data = GDK_WINDOW_WIN32DATA (window);
610   GdkRegion *invalidate_region = gdk_region_rectangle (area);
611   GdkRegion *clip_region;
612
613   GSList *tmp_list = translate_queue;
614
615   GDK_NOTE (EVENTS, g_print ("_gdk_window_process_expose %#x %d %dx%d@+%d+%d\n",
616                              GDK_DRAWABLE_XID (window), serial,
617                              area->width, area->height, area->x, area->y));
618
619   while (tmp_list)
620     {
621       GdkWindowQueueItem *item = tmp_list->data;
622       tmp_list = tmp_list->next;
623
624       if (serial < item->serial)
625         {
626           if (item->window == window)
627             {
628               if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
629                 gdk_region_offset (invalidate_region, - item->u.translate.dx, - item->u.translate.dy);
630               else              /* anti-expose */
631                 gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
632             }
633         }
634       else
635         {
636           GSList *tmp_link = translate_queue;
637           
638           translate_queue = g_slist_remove_link (translate_queue, translate_queue);
639           gdk_drawable_unref (item->window);
640
641           if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
642             gdk_region_destroy (item->u.antiexpose.area);
643           
644           g_free (item);
645           g_slist_free_1 (tmp_link);
646         }
647     }
648
649   clip_region = gdk_region_rectangle (&data->position_info.clip_rect);
650   gdk_region_intersect (invalidate_region, clip_region);
651
652   if (!gdk_region_empty (invalidate_region))
653     gdk_window_invalidate_region (window, invalidate_region, FALSE);
654
655   gdk_region_destroy (invalidate_region);
656   gdk_region_destroy (clip_region);
657 }
658
659 static void
660 gdk_window_tmp_unset_bg (GdkWindow *window)
661 {
662   /* ??? */
663 }
664
665 static void
666 gdk_window_tmp_reset_bg (GdkWindow *window)
667 {
668   /* ??? */
669 }
670
671 static void
672 gdk_window_clip_changed (GdkWindow *window, GdkRectangle *old_clip, GdkRectangle *new_clip)
673 {
674   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
675
676   GdkRegion *old_clip_region;
677   GdkRegion *new_clip_region;
678
679   if (private->input_only)
680     return;
681     
682   old_clip_region = gdk_region_rectangle (old_clip);
683   new_clip_region = gdk_region_rectangle (new_clip);
684
685   /* Trim invalid region of window to new clip rectangle
686    */
687   if (private->update_area)
688     gdk_region_intersect (private->update_area, new_clip_region);
689
690   /* Invalidate newly exposed portion of window
691    */
692   gdk_region_subtract (new_clip_region, old_clip_region);
693   if (!gdk_region_empty (new_clip_region))
694     {
695       gdk_window_tmp_unset_bg (window);
696       gdk_window_invalidate_region (window, new_clip_region, FALSE);
697     }
698
699   gdk_region_destroy (new_clip_region);
700   gdk_region_destroy (old_clip_region);
701 }
702