]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow.c
Improvements by Hans Breuer:
[~andy/gtk] / gdk / win32 / gdkwindow.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * Copyright (C) 1998-1999 Tor Lillqvist
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "config.h"
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <gdk/gdk.h>
33 #include "gdkprivate.h"
34 #include "gdkinput.h"
35
36 /* The Win API function AdjustWindowRect may return negative values
37  * resulting in obscured title bars. This helper function is coreccting it.
38  */
39 BOOL
40 SafeAdjustWindowRectEx (RECT* lpRect, 
41                         DWORD dwStyle, 
42                         BOOL bMenu, 
43                         DWORD dwExStyle)
44 {
45   if (!AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle))
46     return FALSE;
47   if (lpRect->left < 0)
48     {
49       lpRect->right -= lpRect->left;
50       lpRect->left = 0;
51     }
52   if (lpRect->top < 0)
53     {
54       lpRect->bottom -= lpRect->top;
55       lpRect->top = 0;
56     }
57   return TRUE;
58 }
59
60 /* Forward declarations */
61 static gboolean gdk_window_gravity_works (void);
62 static void     gdk_window_set_static_win_gravity (GdkWindow *window, 
63                                                    gboolean   on);
64
65 /* 
66  * The following fucntion by The Rasterman <raster@redhat.com>
67  * This function returns the X Window ID in which the x y location is in 
68  * (x and y being relative to the root window), excluding any windows listed
69  * in the GList excludes (this is a list of X Window ID's - gpointer being
70  * the Window ID).
71  * 
72  * This is primarily designed for internal gdk use - for DND for example
73  * when using a shaped icon window as the drag object - you exclude the
74  * X Window ID of the "icon" (perhaps more if excludes may be needed) and
75  * You can get back an X Window ID as to what X Window ID is infact under
76  * those X,Y co-ordinates.
77  */
78 HWND
79 gdk_window_xid_at_coords (gint     x,
80                           gint     y,
81                           GList   *excludes,
82                           gboolean excl_child)
83 {
84   POINT pt;
85   gboolean warned = FALSE;
86
87   pt.x = x;
88   pt.y = y;
89   /* This is probably not correct, just a quick hack */
90
91   if (!warned)
92     {
93       g_warning ("gdk_window_xid_at_coords probably not implemented correctly");
94       warned = TRUE;
95     }
96
97   /* XXX */
98   return WindowFromPoint (pt);
99 }
100
101 void
102 gdk_window_init (void)
103 {
104   unsigned int width;
105   unsigned int height;
106 #if 0
107   width = GetSystemMetrics (SM_CXSCREEN);
108   height = GetSystemMetrics (SM_CYSCREEN);
109 #else
110   { RECT r; /* //HB: don't obscure tray window (task bar) */
111     SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
112     width  = r.right - r.left;
113     height = r.bottom - r.top;
114   }
115 #endif
116
117   gdk_root_parent.xwindow = gdk_root_window;
118   gdk_root_parent.window_type = GDK_WINDOW_ROOT;
119   gdk_root_parent.window.user_data = NULL;
120   gdk_root_parent.width = width;
121   gdk_root_parent.height = height;
122   gdk_root_parent.children = NULL;
123   gdk_root_parent.colormap = NULL;
124   gdk_root_parent.ref_count = 1;
125
126   gdk_xid_table_insert (&gdk_root_window, &gdk_root_parent);
127 }
128
129 /* RegisterGdkClass
130  *   is a wrapper function for RegisterWindowClassEx.
131  *   It creates at least one unique class for every 
132  *   GdkWindowType. If support for single window-specific icons
133  *   is ever needed (e.g Dialog specific), every such window should
134  *   get its own class
135  */
136 ATOM
137 RegisterGdkClass(GdkWindowType wtype)
138 {
139   static ATOM klassTOPLEVEL = 0;
140   static ATOM klassDIALOG   = 0;
141   static ATOM klassCHILD    = 0;
142   static ATOM klassTEMP     = 0;
143   static HICON hAppIcon = NULL;
144   static WNDCLASSEX wcl; 
145   ATOM klass = 0;
146
147 #ifdef MULTIPLE_WINDOW_CLASSES
148 Error: Not yet implemented!
149 #endif
150
151   wcl.cbSize = sizeof(WNDCLASSEX);     
152   wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
153                   * on WM_SIZE and WM_MOVE. Flicker, Performance!
154                   */
155   wcl.lpfnWndProc = gdk_WindowProc;
156   wcl.cbClsExtra = 0;
157   wcl.cbWndExtra = 0;
158   wcl.hInstance = gdk_ProgInstance;
159   wcl.hIcon = 0;
160   /* initialize once! */
161   if (0 == hAppIcon)
162     {
163       gchar sLoc [_MAX_PATH+1];
164       HINSTANCE hInst = GetModuleHandle(NULL);
165
166       if (0 != GetModuleFileName(hInst, sLoc, _MAX_PATH))
167         {
168           hAppIcon = ExtractIcon(hInst, sLoc, 0);
169           if (0 == hAppIcon)
170             {
171               char *gdklibname = g_strdup_printf ("gdk-%s.dll", GDK_VERSION);
172
173               hAppIcon = ExtractIcon(hInst, gdklibname, 0);
174               g_free (gdklibname);
175             }
176           
177           if (0 == hAppIcon) 
178             hAppIcon = LoadIcon (NULL, IDI_APPLICATION);
179         }
180     }
181
182   wcl.lpszMenuName = NULL;
183   wcl.hIconSm = 0;
184
185   /* initialize once per class */
186 #define ONCE_PER_CLASS() \
187   wcl.hIcon = CopyIcon (hAppIcon); \
188   wcl.hIconSm = CopyIcon (hAppIcon); \
189   wcl.hbrBackground = CreateSolidBrush( RGB(0,0,0)); \
190   wcl.hCursor = LoadCursor (NULL, IDC_ARROW); 
191   
192   switch (wtype)
193   {
194     case GDK_WINDOW_TOPLEVEL:
195       if (0 == klassTOPLEVEL)
196       {
197         wcl.lpszClassName = "gdkWindowToplevel";
198
199         ONCE_PER_CLASS();
200         klassTOPLEVEL = RegisterClassEx(&wcl);
201       }
202       klass = klassTOPLEVEL;
203       break;
204     case GDK_WINDOW_CHILD:
205       if (0 == klassCHILD)
206       {
207         wcl.lpszClassName = "gdkWindowChild";
208
209         wcl.style |= CS_PARENTDC; /* MSDN: ... enhances system performance. */
210         ONCE_PER_CLASS();
211         klassCHILD = RegisterClassEx(&wcl);
212       }
213       klass = klassCHILD;
214       break;
215     case GDK_WINDOW_DIALOG:
216       if (0 == klassDIALOG)
217       {
218         wcl.lpszClassName = "gdkWindowDialog";
219         wcl.style |= CS_SAVEBITS;
220         ONCE_PER_CLASS();
221         klassDIALOG = RegisterClassEx(&wcl);
222       }
223       klass = klassDIALOG;
224       break;
225     case GDK_WINDOW_TEMP:
226       if (0 == klassTEMP)
227       {
228         wcl.lpszClassName = "gdkWindowTemp";
229         wcl.style |= CS_SAVEBITS;
230         ONCE_PER_CLASS();
231         klassTEMP = RegisterClassEx(&wcl);
232       }
233       klass = klassTEMP;
234       break;
235     case GDK_WINDOW_ROOT:
236       g_error ("cannot make windows of type GDK_WINDOW_ROOT");
237       break;
238     case GDK_WINDOW_PIXMAP:
239       g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
240       break;
241   }
242
243   return klass;
244 } /* RegisterGdkClass */
245
246
247 GdkWindow*
248 gdk_window_new (GdkWindow     *parent,
249                 GdkWindowAttr *attributes,
250                 gint           attributes_mask)
251 {
252   GdkWindow *window;
253   GdkWindowPrivate *private;
254   GdkWindowPrivate *parent_private;
255   GdkVisual *visual;
256   HANDLE xparent;
257   Visual *xvisual;
258   ATOM klass = 0;
259   DWORD dwStyle, dwExStyle;
260   RECT rect;
261   int width, height;
262   int x, y;
263   char *title;
264
265   g_return_val_if_fail (attributes != NULL, NULL);
266
267   if (!parent)
268     parent = (GdkWindow*) &gdk_root_parent;
269
270   parent_private = (GdkWindowPrivate*) parent;
271   if (parent_private->destroyed)
272     return NULL;
273
274   xparent = parent_private->xwindow;
275
276   private = g_new (GdkWindowPrivate, 1);
277   window = (GdkWindow*) private;
278
279   private->parent = parent;
280
281   private->destroyed = FALSE;
282   private->mapped = FALSE;
283   private->guffaw_gravity = FALSE;
284   private->resize_count = 0;
285   private->ref_count = 1;
286
287   private->x = (attributes_mask & GDK_WA_X) ? attributes->x : 0;
288   private->y = (attributes_mask & GDK_WA_Y) ? attributes->y : 0;
289
290   private->width = (attributes->width > 1) ? (attributes->width) : (1);
291   private->height = (attributes->height > 1) ? (attributes->height) : (1);
292   private->window_type = attributes->window_type;
293   private->extension_events = 0;
294   private->extension_events_selected = FALSE;
295
296   private->filters = NULL;
297   private->children = NULL;
298
299   window->user_data = NULL;
300
301   if (attributes_mask & GDK_WA_VISUAL)
302     visual = attributes->visual;
303   else
304     visual = gdk_visual_get_system ();
305   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
306
307   if (attributes_mask & GDK_WA_TITLE)
308     title = attributes->title;
309   else
310     title = g_get_prgname ();
311
312   private->event_mask = GDK_STRUCTURE_MASK | attributes->event_mask;
313   private->bg_type = GDK_WIN32_BG_NORMAL;
314   private->hint_flags = 0;
315   private->xcursor = NULL;
316       
317   if (parent_private && parent_private->guffaw_gravity)
318     {
319       /* XXX ??? */
320     }
321
322   if (attributes->wclass == GDK_INPUT_OUTPUT)
323     {
324       dwExStyle = 0;
325       if (attributes_mask & GDK_WA_COLORMAP)
326         private->colormap = attributes->colormap;
327       else
328         private->colormap = gdk_colormap_get_system ();
329     }
330   else
331     {
332       dwExStyle = WS_EX_TRANSPARENT;
333       private->colormap = NULL;
334       private->bg_type = GDK_WIN32_BG_TRANSPARENT;
335       private->bg_pixmap = NULL;
336     }
337
338   if (attributes_mask & GDK_WA_X)
339     x = attributes->x;
340   else
341     x = CW_USEDEFAULT;
342
343   if (attributes_mask & GDK_WA_Y)
344     y = attributes->y;
345   else if (attributes_mask & GDK_WA_X)
346     y = 100;                    /* ??? We must put it somewhere... */
347   else
348     y = 500;                    /* x is CW_USEDEFAULT, y doesn't matter then */
349
350   if (parent_private)
351     parent_private->children = g_list_prepend (parent_private->children, window);
352
353   switch (private->window_type)
354     {
355     case GDK_WINDOW_TOPLEVEL:
356       dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
357       xparent = gdk_root_window;
358       break;
359     case GDK_WINDOW_CHILD:
360       dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
361       break;
362     case GDK_WINDOW_DIALOG:
363       dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
364       dwExStyle |= WS_EX_TOPMOST; /* //HB: want this? */
365       xparent = gdk_root_window;
366       break;
367     case GDK_WINDOW_TEMP:
368       dwStyle = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
369       dwExStyle |= WS_EX_TOOLWINDOW;
370       break;
371     case GDK_WINDOW_ROOT:
372       g_error ("cannot make windows of type GDK_WINDOW_ROOT");
373       break;
374     case GDK_WINDOW_PIXMAP:
375       g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
376       break;
377     }
378
379   klass = RegisterGdkClass (private->window_type);
380   if (!klass)
381     g_error ("RegisterClassEx failed");
382
383   if (private->window_type != GDK_WINDOW_CHILD)
384     {
385       if (x == CW_USEDEFAULT)
386         {
387           rect.left = 100;
388           rect.top = 100;
389         }
390       else
391         {
392           rect.left = x;
393           rect.top = y;
394         }
395
396       rect.right = rect.left + private->width;
397       rect.bottom = rect.top + private->height;
398
399       if (!SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
400         g_warning ("gdk_window_new: AdjustWindowRectEx failed");
401
402       if (x != CW_USEDEFAULT)
403         {
404           x = rect.left;
405           y = rect.top;
406         }
407       width = rect.right - rect.left;
408       height = rect.bottom - rect.top;
409     }
410   else
411     {
412       width = private->width;
413       height = private->height;
414     }
415
416   private->xwindow =
417     CreateWindowEx (dwExStyle,
418                     MAKEINTRESOURCE(klass),
419                     title,
420                     dwStyle,
421                     x, y, 
422                     width, height,
423                     xparent,
424                     NULL,
425                     gdk_ProgInstance,
426                     NULL);
427   GDK_NOTE (MISC,
428             g_print ("gdk_window_create: %s %s %#x %#x %dx%d@+%d+%d %#x = %#x\n",
429                      (private->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
430                       (private->window_type == GDK_WINDOW_CHILD ? "CHILD" :
431                        (private->window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
432                         (private->window_type == GDK_WINDOW_TEMP ? "TEMP" :
433                          "???")))),
434                      title,
435                      dwStyle,
436                      private->event_mask,
437                      width, height, (x == CW_USEDEFAULT ? -9999 : x), y, 
438                      xparent,
439                      private->xwindow));
440
441   gdk_window_ref (window);
442   gdk_xid_table_insert (&private->xwindow, window);
443
444   if (private->colormap)
445     gdk_colormap_ref (private->colormap);
446
447   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
448                                   (attributes->cursor) :
449                                   NULL));
450
451   return window;
452 }
453
454 GdkWindow *
455 gdk_window_foreign_new (guint32 anid)
456 {
457   GdkWindow *window;
458   GdkWindowPrivate *private;
459   GdkWindowPrivate *parent_private;
460   HANDLE parent;
461   RECT rect;
462   POINT point;
463
464   private = g_new (GdkWindowPrivate, 1);
465   window = (GdkWindow*) private;
466
467   parent = GetParent ((HWND) anid);
468   private->parent = gdk_xid_table_lookup (parent);
469
470   parent_private = (GdkWindowPrivate *)private->parent;
471   
472   if (parent_private)
473     parent_private->children = g_list_prepend (parent_private->children, window);
474
475   private->xwindow = (HWND) anid;
476   GetClientRect ((HWND) anid, &rect);
477   point.x = rect.left;
478   point.y = rect.right;
479   ClientToScreen ((HWND) anid, &point);
480   if (parent != HWND_DESKTOP)
481     ScreenToClient (parent, &point);
482   private->x = point.x;
483   private->y = point.y;
484   private->width = rect.right - rect.left;
485   private->height = rect.bottom - rect.top;
486   private->resize_count = 0;
487   private->ref_count = 1;
488   private->window_type = GDK_WINDOW_FOREIGN;
489   private->destroyed = FALSE;
490   private->mapped = IsWindowVisible (private->xwindow);
491   private->guffaw_gravity = FALSE;
492   private->extension_events = 0;
493   private->extension_events_selected = FALSE;
494
495   private->colormap = NULL;
496
497   private->filters = NULL;
498   private->children = NULL;
499
500   window->user_data = NULL;
501
502   gdk_window_ref (window);
503   gdk_xid_table_insert (&private->xwindow, window);
504
505   return window;
506 }
507
508 /* Call this function when you want a window and all its children to
509  * disappear.  When xdestroy is true, a request to destroy the XWindow
510  * is sent out.  When it is false, it is assumed that the XWindow has
511  * been or will be destroyed by destroying some ancestor of this
512  * window.
513  */
514 static void
515 gdk_window_internal_destroy (GdkWindow *window,
516                              gboolean   xdestroy,
517                              gboolean   our_destroy)
518 {
519   GdkWindowPrivate *private;
520   GdkWindowPrivate *temp_private;
521   GdkWindow *temp_window;
522   GList *children;
523   GList *tmp;
524
525   g_return_if_fail (window != NULL);
526
527   private = (GdkWindowPrivate*) window;
528
529   GDK_NOTE (MISC, g_print ("gdk_window_internal_destroy %#x\n",
530                            private->xwindow));
531
532   switch (private->window_type)
533     {
534     case GDK_WINDOW_TOPLEVEL:
535     case GDK_WINDOW_CHILD:
536     case GDK_WINDOW_DIALOG:
537     case GDK_WINDOW_TEMP:
538     case GDK_WINDOW_FOREIGN:
539       if (!private->destroyed)
540         {
541           if (private->parent)
542             {
543               GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
544               if (parent_private->children)
545                 parent_private->children = g_list_remove (parent_private->children, window);
546             }
547
548           if (private->window_type != GDK_WINDOW_FOREIGN)
549             {
550               children = tmp = private->children;
551               private->children = NULL;
552
553               while (tmp)
554                 {
555                   temp_window = tmp->data;
556                   tmp = tmp->next;
557                   
558                   temp_private = (GdkWindowPrivate*) temp_window;
559                   if (temp_private)
560                     gdk_window_internal_destroy (temp_window, FALSE,
561                                                  our_destroy);
562                 }
563
564               g_list_free (children);
565             }
566
567           if (private->extension_events != 0)
568             gdk_input_window_destroy (window);
569
570           if (private->filters)
571             {
572               tmp = private->filters;
573
574               while (tmp)
575                 {
576                   g_free (tmp->data);
577                   tmp = tmp->next;
578                 }
579
580               g_list_free (private->filters);
581               private->filters = NULL;
582             }
583           
584           if (private->window_type == GDK_WINDOW_FOREIGN)
585             {
586               if (our_destroy && (private->parent != NULL))
587                 {
588                   /* It's somebody elses window, but in our hierarchy,
589                    * so reparent it to the root window, and then send
590                    * it a delete event, as if we were a WM
591                    */
592                   gdk_window_hide (window);
593                   gdk_window_reparent (window, NULL, 0, 0);
594                   
595                   /* Is this too drastic? Many (most?) applications
596                    * quit if any window receives WM_QUIT I think.
597                    * OTOH, I don't think foreign windows are much
598                    * used, so the question is maybe academic.
599                    */
600                   PostMessage (private->xwindow, WM_QUIT, 0, 0);
601                 }
602             }
603           else if (xdestroy)
604             DestroyWindow (private->xwindow);
605
606           if (private->colormap)
607             gdk_colormap_unref (private->colormap);
608
609           private->mapped = FALSE;
610           private->destroyed = TRUE;
611         }
612       break;
613
614     case GDK_WINDOW_ROOT:
615       g_error ("attempted to destroy root window");
616       break;
617
618     case GDK_WINDOW_PIXMAP:
619       g_error ("called gdk_window_destroy on a pixmap (use gdk_pixmap_unref)");
620       break;
621     }
622 }
623
624 /* Like internal_destroy, but also destroys the reference created by
625    gdk_window_new. */
626
627 void
628 gdk_window_destroy (GdkWindow *window)
629 {
630   gdk_window_internal_destroy (window, TRUE, TRUE);
631   gdk_window_unref (window);
632 }
633
634 /* This function is called when the XWindow is really gone.  */
635
636 void
637 gdk_window_destroy_notify (GdkWindow *window)
638 {
639   GdkWindowPrivate *private;
640
641   g_return_if_fail (window != NULL);
642
643   private = (GdkWindowPrivate*) window;
644
645   GDK_NOTE (EVENTS, g_print ("gdk_window_destroy_notify: %#x  %d\n",
646                              private->xwindow, private->destroyed));
647
648   if (!private->destroyed)
649     {
650       if (private->window_type == GDK_WINDOW_FOREIGN)
651         gdk_window_internal_destroy (window, FALSE, FALSE);
652       else
653         g_warning ("GdkWindow %#lx unexpectedly destroyed", private->xwindow);
654     }
655   
656   gdk_xid_table_remove (private->xwindow);
657   gdk_window_unref (window);
658 }
659
660 GdkWindow*
661 gdk_window_ref (GdkWindow *window)
662 {
663   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
664   g_return_val_if_fail (window != NULL, NULL);
665
666   private->ref_count += 1;
667
668   GDK_NOTE (MISC, g_print ("gdk_window_ref %#x %d\n",
669                            private->xwindow, private->ref_count));
670
671   return window;
672 }
673
674 void
675 gdk_window_unref (GdkWindow *window)
676 {
677   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
678   g_return_if_fail (window != NULL);
679
680   private->ref_count -= 1;
681
682   GDK_NOTE (MISC, g_print ("gdk_window_unref %#x %d%s\n",
683                            private->xwindow, private->ref_count,
684                            (private->ref_count == 0 ? " freeing" : "")));
685
686   if (private->ref_count == 0)
687     {
688       if (private->bg_type == GDK_WIN32_BG_PIXMAP && private->bg_pixmap != NULL)
689         gdk_pixmap_unref (private->bg_pixmap);
690
691       if (!private->destroyed)
692         {
693           if (private->window_type == GDK_WINDOW_FOREIGN)
694             gdk_xid_table_remove (private->xwindow);
695           else
696             g_warning ("losing last reference to undestroyed window");
697         }
698       g_dataset_destroy (window);
699       g_free (window);
700     }
701 }
702
703 void
704 gdk_window_show (GdkWindow *window)
705 {
706   GdkWindowPrivate *private;
707
708   g_return_if_fail (window != NULL);
709
710   private = (GdkWindowPrivate*) window;
711   if (!private->destroyed)
712     {
713       GDK_NOTE (MISC, g_print ("gdk_window_show: %#x\n", private->xwindow));
714
715       private->mapped = TRUE;
716       if (private->window_type == GDK_WINDOW_TEMP)
717         {
718           ShowWindow (private->xwindow, SW_SHOWNOACTIVATE);
719           SetWindowPos (private->xwindow, HWND_TOPMOST, 0, 0, 0, 0,
720                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
721 #if 0
722           ShowWindow (private->xwindow, SW_HIDE); /* Don't put on toolbar */
723 #endif
724         }
725       else
726         {
727           ShowWindow (private->xwindow, SW_SHOWNORMAL);
728           ShowWindow (private->xwindow, SW_RESTORE);
729           SetForegroundWindow (private->xwindow);
730 #if 0
731           ShowOwnedPopups (private->xwindow, TRUE);
732 #endif
733         }
734     }
735 }
736
737 void
738 gdk_window_hide (GdkWindow *window)
739 {
740   GdkWindowPrivate *private;
741
742   g_return_if_fail (window != NULL);
743
744   private = (GdkWindowPrivate*) window;
745   if (!private->destroyed)
746     {
747       GDK_NOTE (MISC, g_print ("gdk_window_hide: %#x\n", private->xwindow));
748
749       private->mapped = FALSE;
750       if (private->window_type == GDK_WINDOW_TOPLEVEL)
751         ShowOwnedPopups (private->xwindow, FALSE);
752 #if 1
753       ShowWindow (private->xwindow, SW_HIDE);
754 #elif 0
755       ShowWindow (private->xwindow, SW_MINIMIZE);
756 #else
757       CloseWindow (private->xwindow);
758 #endif
759     }
760 }
761
762 void
763 gdk_window_withdraw (GdkWindow *window)
764 {
765   GdkWindowPrivate *private;
766
767   g_return_if_fail (window != NULL);
768
769   private = (GdkWindowPrivate*) window;
770   if (!private->destroyed)
771     {
772       GDK_NOTE (MISC, g_print ("gdk_window_withdraw: %#x\n", private->xwindow));
773
774       gdk_window_hide (window); /* XXX */
775     }
776 }
777
778 void
779 gdk_window_move (GdkWindow *window,
780                  gint       x,
781                  gint       y)
782 {
783   GdkWindowPrivate *private;
784
785   g_return_if_fail (window != NULL);
786
787   private = (GdkWindowPrivate*) window;
788   if (!private->destroyed)
789     {
790       RECT rect;
791
792       GDK_NOTE (MISC, g_print ("gdk_window_move: %#x +%d+%d\n",
793                                private->xwindow, x, y));
794
795       GetClientRect (private->xwindow, &rect);
796
797       if (private->window_type != GDK_WINDOW_CHILD)
798         {
799           POINT ptTL, ptBR;
800           DWORD dwStyle;
801           DWORD dwExStyle;
802
803           ptTL.x = 0;
804           ptTL.y = 0; 
805           ClientToScreen (private->xwindow, &ptTL);
806           rect.left = x;
807           rect.top = y;
808
809           ptBR.x = rect.right;
810           ptBR.y = rect.bottom;
811           ClientToScreen (private->xwindow, &ptBR);
812           rect.right = x + ptBR.x - ptTL.x;
813           rect.bottom = y + ptBR.y - ptTL.y;
814
815           dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
816           dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
817           if (!SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
818             g_warning ("gdk_window_move: AdjustWindowRectEx failed");
819
820           x = rect.left;
821           y = rect.top;
822         }
823       else
824         {
825           private->x = x;
826           private->y = y;
827         }
828       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
829                                private->xwindow,
830                                rect.right - rect.left, rect.bottom - rect.top,
831                                x, y));
832       if (!MoveWindow (private->xwindow,
833                        x, y, rect.right - rect.left, rect.bottom - rect.top,
834                        TRUE))
835         g_warning ("gdk_window_move: MoveWindow failed");
836     }
837 }
838
839 void
840 gdk_window_resize (GdkWindow *window,
841                    gint       width,
842                    gint       height)
843 {
844   GdkWindowPrivate *private;
845
846   g_return_if_fail (window != NULL);
847
848   if ((gint16) width < 1)
849     width = 1;
850   if ((gint16) height < 1)
851     height = 1;
852
853   private = (GdkWindowPrivate*) window;
854
855   if (!private->destroyed &&
856       ((private->resize_count > 0) ||
857        (private->width != (guint16) width) ||
858        (private->height != (guint16) height)))
859     {
860       int x, y;
861
862       GDK_NOTE (MISC, g_print ("gdk_window_resize: %#x %dx%d\n",
863                                private->xwindow, width, height));
864       
865       if (private->window_type != GDK_WINDOW_CHILD)
866         {
867           POINT pt;
868           RECT rect;
869           DWORD dwStyle;
870           DWORD dwExStyle;
871
872           pt.x = 0;
873           pt.y = 0; 
874           ClientToScreen (private->xwindow, &pt);
875           rect.left = pt.x;
876           rect.top = pt.y;
877           rect.right = pt.x + width;
878           rect.bottom = pt.y + height;
879
880           dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
881           dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
882           if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
883             g_warning ("gdk_window_resize: AdjustWindowRectEx failed");
884
885           x = rect.left;
886           y = rect.top;
887           width = rect.right - rect.left;
888           height = rect.bottom - rect.top;
889         }
890       else
891         {
892           x = private->x;
893           y = private->y;
894           private->width = width;
895           private->height = height;
896         }
897
898       private->resize_count += 1;
899
900       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
901                                private->xwindow, width, height, x, y));
902       if (!MoveWindow (private->xwindow,
903                        x, y, width, height,
904                        TRUE))
905         g_warning ("gdk_window_resize: MoveWindow failed");
906     }
907 }
908
909 void
910 gdk_window_move_resize (GdkWindow *window,
911                         gint       x,
912                         gint       y,
913                         gint       width,
914                         gint       height)
915 {
916   GdkWindowPrivate *private;
917
918   g_return_if_fail (window != NULL);
919
920   if ((gint16) width < 1)
921     width = 1;
922   if ((gint16) height < 1)
923     height = 1;
924
925   private = (GdkWindowPrivate*) window;
926   if (!private->destroyed)
927     {
928       RECT rect;
929       DWORD dwStyle;
930       DWORD dwExStyle;
931
932       GDK_NOTE (MISC, g_print ("gdk_window_move_resize: %#x %dx%d@+%d+%d\n",
933                                private->xwindow, width, height, x, y));
934       
935       rect.left = x;
936       rect.top = y;
937       rect.right = x + width;
938       rect.bottom = y + height;
939
940       dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
941       dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
942       if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
943         g_warning ("gdk_window_move_resize: AdjustWindowRectEx failed");
944
945       if (private->window_type == GDK_WINDOW_CHILD)
946         {
947           private->x = x;
948           private->y = y;
949           private->width = width;
950           private->height = height;
951         }
952       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
953                                private->xwindow,
954                                rect.right - rect.left, rect.bottom - rect.top,
955                                rect.left, rect.top));
956       if (!MoveWindow (private->xwindow,
957                        rect.left, rect.top,
958                        rect.right - rect.left, rect.bottom - rect.top,
959                        TRUE))
960         g_warning ("gdk_window_move_resize: MoveWindow failed");
961
962       if (private->guffaw_gravity)
963         {
964           GList *tmp_list = private->children;
965           while (tmp_list)
966             {
967               GdkWindowPrivate *child_private = tmp_list->data;
968               
969               child_private->x -= x - private->x;
970               child_private->y -= y - private->y;
971               
972               tmp_list = tmp_list->next;
973             }
974         }
975       
976     }
977 }
978
979 void
980 gdk_window_reparent (GdkWindow *window,
981                      GdkWindow *new_parent,
982                      gint       x,
983                      gint       y)
984 {
985   GdkWindowPrivate *window_private;
986   GdkWindowPrivate *parent_private;
987   GdkWindowPrivate *old_parent_private;
988
989   g_return_if_fail (window != NULL);
990
991   if (!new_parent)
992     new_parent = (GdkWindow*) &gdk_root_parent;
993
994   window_private = (GdkWindowPrivate*) window;
995   old_parent_private = (GdkWindowPrivate*)window_private->parent;
996   parent_private = (GdkWindowPrivate*) new_parent;
997
998   if (!window_private->destroyed && !parent_private->destroyed)
999     {
1000       GDK_NOTE (MISC, g_print ("gdk_window_reparent: %#x %#x\n",
1001                                window_private->xwindow,
1002                                parent_private->xwindow));
1003       if (!SetParent (window_private->xwindow, parent_private->xwindow))
1004         g_warning ("gdk_window_reparent: SetParent failed");
1005
1006       if (!MoveWindow (window_private->xwindow,
1007                        x, y,
1008                        window_private->width, window_private->height,
1009                        TRUE))
1010         g_warning ("gdk_window_reparent: MoveWindow failed");
1011     }
1012   
1013   window_private->parent = new_parent;
1014
1015   if (old_parent_private)
1016     old_parent_private->children = g_list_remove (old_parent_private->children, window);
1017
1018   if ((old_parent_private &&
1019        (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
1020       (!old_parent_private && parent_private->guffaw_gravity))
1021     gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
1022   
1023   parent_private->children = g_list_prepend (parent_private->children, window);
1024 }
1025
1026 void
1027 gdk_window_clear (GdkWindow *window)
1028 {
1029   GdkWindowPrivate *private;
1030
1031   g_return_if_fail (window != NULL);
1032
1033   private = (GdkWindowPrivate*) window;
1034
1035   if (!private->destroyed)
1036     {
1037       gdk_window_clear_area (window, 0, 0, private->width, private->height);
1038     }
1039 }
1040
1041
1042 void
1043 gdk_window_clear_area (GdkWindow *window,
1044                        gint       x,
1045                        gint       y,
1046                        gint       width,
1047                        gint       height)
1048 {
1049   GdkWindowPrivate *private;
1050   
1051   g_return_if_fail (window != NULL);
1052   
1053   private = (GdkWindowPrivate*) window;
1054   
1055   if (!private->destroyed)
1056     {
1057       HDC hdc;
1058
1059       if (width == -1)
1060         width = G_MAXSHORT/2;           /* Yeah, right */
1061       if (height == -1)
1062         height = G_MAXSHORT/2;
1063       GDK_NOTE (MISC, g_print ("gdk_window_clear_area: %#x %dx%d@+%d+%d\n",
1064                                private->xwindow, width, height, x, y));
1065       hdc = GetDC (private->xwindow);
1066       IntersectClipRect (hdc, x, y, x + width, y + height);
1067       SendMessage (private->xwindow, WM_ERASEBKGND, (WPARAM) hdc, 0);
1068       ReleaseDC (private->xwindow, hdc);
1069     }
1070 }
1071
1072 void
1073 gdk_window_clear_area_e (GdkWindow *window,
1074                          gint       x,
1075                          gint       y,
1076                          gint       width,
1077                          gint       height)
1078 {
1079   GdkWindowPrivate *private;
1080   
1081   g_return_if_fail (window != NULL);
1082   
1083   private = (GdkWindowPrivate*) window;
1084   
1085   if (!private->destroyed)
1086     {
1087       RECT rect;
1088
1089       GDK_NOTE (MISC, g_print ("gdk_window_clear_area_e: %#x %dx%d@+%d+%d\n",
1090                                private->xwindow, width, height, x, y));
1091
1092       rect.left = x;
1093       rect.right = x + width;
1094       rect.top = y;
1095       rect.bottom = y + height;
1096       if (!InvalidateRect (private->xwindow, &rect, TRUE))
1097         g_warning ("gdk_window_clear_area_e: InvalidateRect failed");
1098       UpdateWindow (private->xwindow);
1099     }
1100 }
1101
1102 void
1103 gdk_window_copy_area (GdkWindow    *window,
1104                       GdkGC        *gc,
1105                       gint          x,
1106                       gint          y,
1107                       GdkWindow    *source_window,
1108                       gint          source_x,
1109                       gint          source_y,
1110                       gint          width,
1111                       gint          height)
1112 {
1113   GdkWindowPrivate *src_private;
1114   GdkWindowPrivate *dest_private;
1115   GdkGCPrivate *gc_private;
1116   
1117   g_return_if_fail (window != NULL);
1118   g_return_if_fail (gc != NULL);
1119   
1120   if (source_window == NULL)
1121     source_window = window;
1122   
1123   src_private = (GdkWindowPrivate*) source_window;
1124   dest_private = (GdkWindowPrivate*) window;
1125   gc_private = (GdkGCPrivate*) gc;
1126   
1127   if (!src_private->destroyed && !dest_private->destroyed)
1128     {
1129       HDC hdcDest, hdcSrc;
1130
1131       if ((hdcDest = GetDC (dest_private->xwindow)) == NULL)
1132         g_warning ("gdk_window_copy_area: GetDC failed");
1133
1134       if ((hdcSrc = GetDC (src_private->xwindow)) == NULL)
1135         g_warning ("gdk_window_copy_area: GetDC failed");
1136
1137       if (!BitBlt (hdcDest, x, y, width, height, hdcSrc, source_x, source_y, SRCCOPY))
1138         g_warning ("gdk_window_copy_area: BitBlt failed");
1139
1140       ReleaseDC (dest_private->xwindow, hdcDest);
1141       ReleaseDC (src_private->xwindow, hdcSrc);
1142     }
1143 }
1144
1145 void
1146 gdk_window_raise (GdkWindow *window)
1147 {
1148   GdkWindowPrivate *private;
1149   
1150   g_return_if_fail (window != NULL);
1151   
1152   private = (GdkWindowPrivate*) window;
1153   
1154   if (!private->destroyed)
1155     {
1156       GDK_NOTE (MISC, g_print ("gdk_window_raise: %#x\n", private->xwindow));
1157
1158       if (!BringWindowToTop (private->xwindow))
1159         g_warning ("gdk_window_raise: BringWindowToTop failed");
1160     }
1161 }
1162
1163 void
1164 gdk_window_lower (GdkWindow *window)
1165 {
1166   GdkWindowPrivate *private;
1167   
1168   g_return_if_fail (window != NULL);
1169   
1170   private = (GdkWindowPrivate*) window;
1171   
1172   if (!private->destroyed)
1173     {
1174       GDK_NOTE (MISC, g_print ("gdk_window_lower: %#x\n", private->xwindow));
1175
1176       if (!SetWindowPos (private->xwindow, HWND_BOTTOM, 0, 0, 0, 0,
1177                          SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE))
1178         g_warning ("gdk_window_lower: SetWindowPos failed");
1179     }
1180 }
1181
1182 void
1183 gdk_window_set_user_data (GdkWindow *window,
1184                           gpointer   user_data)
1185 {
1186   g_return_if_fail (window != NULL);
1187   
1188   window->user_data = user_data;
1189 }
1190
1191 void
1192 gdk_window_set_hints (GdkWindow *window,
1193                       gint       x,
1194                       gint       y,
1195                       gint       min_width,
1196                       gint       min_height,
1197                       gint       max_width,
1198                       gint       max_height,
1199                       gint       flags)
1200 {
1201   GdkWindowPrivate *private;
1202   WINDOWPLACEMENT size_hints;
1203   RECT rect;
1204   DWORD dwStyle;
1205   DWORD dwExStyle;
1206   int diff;
1207   
1208   g_return_if_fail (window != NULL);
1209   
1210   private = (GdkWindowPrivate*) window;
1211   if (private->destroyed)
1212     return;
1213   
1214   GDK_NOTE (MISC, g_print ("gdk_window_set_hints: %#x %dx%d..%dx%d @+%d+%d\n",
1215                            private->xwindow,
1216                            min_width, min_height, max_width, max_height,
1217                            x, y));
1218
1219   private->hint_flags = flags;
1220   size_hints.length = sizeof (size_hints);
1221
1222   if (flags)
1223     {
1224       if (flags & GDK_HINT_POS)
1225         if (!GetWindowPlacement (private->xwindow, &size_hints))
1226           g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
1227         else
1228           {
1229             GDK_NOTE (MISC, g_print ("...rcNormalPosition:"
1230                                      " (%d,%d)--(%d,%d)\n",
1231                                      size_hints.rcNormalPosition.left,
1232                                      size_hints.rcNormalPosition.top,
1233                                      size_hints.rcNormalPosition.right,
1234                                      size_hints.rcNormalPosition.bottom));
1235             /* What are the corresponding window coordinates for client
1236              * area coordinates x, y
1237              */
1238             rect.left = x;
1239             rect.top = y;
1240             rect.right = rect.left + 200;       /* dummy */
1241             rect.bottom = rect.top + 200;
1242             dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
1243             dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
1244             AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1245             size_hints.flags = 0;
1246             size_hints.showCmd = SW_SHOWNA;
1247
1248             /* Set the normal position hint to that location, with unchanged
1249              * width and height.
1250              */
1251             diff = size_hints.rcNormalPosition.left - rect.left;
1252             size_hints.rcNormalPosition.left = rect.left;
1253             size_hints.rcNormalPosition.right -= diff;
1254             diff = size_hints.rcNormalPosition.top - rect.top;
1255             size_hints.rcNormalPosition.top = rect.top;
1256             size_hints.rcNormalPosition.bottom -= diff;
1257             GDK_NOTE (MISC, g_print ("...setting: (%d,%d)--(%d,%d)\n",
1258                                      size_hints.rcNormalPosition.left,
1259                                      size_hints.rcNormalPosition.top,
1260                                      size_hints.rcNormalPosition.right,
1261                                      size_hints.rcNormalPosition.bottom));
1262             if (!SetWindowPlacement (private->xwindow, &size_hints))
1263               g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
1264             private->hint_x = rect.left;
1265             private->hint_y = rect.top;
1266           }
1267
1268       if (flags & GDK_HINT_MIN_SIZE)
1269         {
1270           rect.left = 0;
1271           rect.top = 0;
1272           rect.right = min_width;
1273           rect.bottom = min_height;
1274           dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
1275           dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
1276           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1277           private->hint_min_width = rect.right - rect.left;
1278           private->hint_min_height = rect.bottom - rect.top;
1279
1280           /* Also chek if he current size of the window is in bounds. */
1281           GetClientRect (private->xwindow, &rect);
1282           if (rect.right < min_width && rect.bottom < min_height)
1283             gdk_window_resize (window, min_width, min_height);
1284           else if (rect.right < min_width)
1285             gdk_window_resize (window, min_width, rect.bottom);
1286           else if (rect.bottom < min_height)
1287             gdk_window_resize (window, rect.right, min_height);
1288         }
1289       if (flags & GDK_HINT_MAX_SIZE)
1290         {
1291           rect.left = 0;
1292           rect.top = 0;
1293           rect.right = max_width;
1294           rect.bottom = max_height;
1295           dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
1296           dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
1297           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1298           private->hint_max_width = rect.right - rect.left;
1299           private->hint_max_height = rect.bottom - rect.top;
1300           /* Again, check if the window is too large currently. */
1301           GetClientRect (private->xwindow, &rect);
1302           if (rect.right > max_width && rect.bottom > max_height)
1303             gdk_window_resize (window, max_width, max_height);
1304           else if (rect.right > max_width)
1305             gdk_window_resize (window, max_width, rect.bottom);
1306           else if (rect.bottom > max_height)
1307             gdk_window_resize (window, rect.right, max_height);
1308         }
1309     }
1310 }
1311
1312 void 
1313 gdk_window_set_geometry_hints (GdkWindow      *window,
1314                                GdkGeometry    *geometry,
1315                                GdkWindowHints  geom_mask)
1316 {
1317   GdkWindowPrivate *private;
1318   WINDOWPLACEMENT size_hints;
1319   RECT rect;
1320   DWORD dwStyle;
1321   DWORD dwExStyle;
1322   int diff;
1323   
1324   g_return_if_fail (window != NULL);
1325   
1326   private = (GdkWindowPrivate*) window;
1327   if (private->destroyed)
1328     return;
1329   
1330   size_hints.length = sizeof (size_hints);
1331
1332   private->hint_flags = geom_mask;
1333
1334   if (geom_mask & GDK_HINT_POS)
1335     ; /* XXX */
1336
1337   if (geom_mask & GDK_HINT_MIN_SIZE)
1338     {
1339       rect.left = 0;
1340       rect.top = 0;
1341       rect.right = geometry->min_width;
1342       rect.bottom = geometry->min_height;
1343       dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
1344       dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
1345       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1346       private->hint_min_width = rect.right - rect.left;
1347       private->hint_min_height = rect.bottom - rect.top;
1348
1349       /* Also check if he current size of the window is in bounds */
1350       GetClientRect (private->xwindow, &rect);
1351       if (rect.right < geometry->min_width
1352           && rect.bottom < geometry->min_height)
1353         gdk_window_resize (window, geometry->min_width, geometry->min_height);
1354       else if (rect.right < geometry->min_width)
1355         gdk_window_resize (window, geometry->min_width, rect.bottom);
1356       else if (rect.bottom < geometry->min_height)
1357         gdk_window_resize (window, rect.right, geometry->min_height);
1358     }
1359   
1360   if (geom_mask & GDK_HINT_MAX_SIZE)
1361     {
1362       rect.left = 0;
1363       rect.top = 0;
1364       rect.right = geometry->max_width;
1365       rect.bottom = geometry->max_height;
1366       dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
1367       dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
1368       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1369       private->hint_max_width = rect.right - rect.left;
1370       private->hint_max_height = rect.bottom - rect.top;
1371
1372       /* Again, check if the window is too large currently. */
1373       GetClientRect (private->xwindow, &rect);
1374       if (rect.right > geometry->max_width
1375           && rect.bottom > geometry->max_height)
1376         gdk_window_resize (window, geometry->max_width, geometry->max_height);
1377       else if (rect.right > geometry->max_width)
1378         gdk_window_resize (window, geometry->max_width, rect.bottom);
1379       else if (rect.bottom > geometry->max_height)
1380         gdk_window_resize (window, rect.right, geometry->max_height);
1381     }
1382   
1383   /* I don't know what to do when called with zero base_width and height. */
1384   if (geom_mask & GDK_HINT_BASE_SIZE
1385       && geometry->base_width > 0
1386       && geometry->base_height > 0)
1387     if (!GetWindowPlacement (private->xwindow, &size_hints))
1388       g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
1389     else
1390       {
1391         GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints:"
1392                                  " rcNormalPosition: (%d,%d)--(%d,%d)\n",
1393                                  size_hints.rcNormalPosition.left,
1394                                  size_hints.rcNormalPosition.top,
1395                                  size_hints.rcNormalPosition.right,
1396                                  size_hints.rcNormalPosition.bottom));
1397         size_hints.rcNormalPosition.right =
1398           size_hints.rcNormalPosition.left + geometry->base_width;
1399         size_hints.rcNormalPosition.bottom =
1400           size_hints.rcNormalPosition.top + geometry->base_height;
1401         GDK_NOTE (MISC, g_print ("...setting: rcNormal: (%d,%d)--(%d,%d)\n",
1402                                  size_hints.rcNormalPosition.left,
1403                                  size_hints.rcNormalPosition.top,
1404                                  size_hints.rcNormalPosition.right,
1405                                  size_hints.rcNormalPosition.bottom));
1406         if (!SetWindowPlacement (private->xwindow, &size_hints))
1407           g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
1408       }
1409   
1410   if (geom_mask & GDK_HINT_RESIZE_INC)
1411     {
1412       /* XXX */
1413     }
1414   
1415   if (geom_mask & GDK_HINT_ASPECT)
1416     {
1417       /* XXX */
1418     }
1419 }
1420
1421 void
1422 gdk_window_set_title (GdkWindow   *window,
1423                       const gchar *title)
1424 {
1425   GdkWindowPrivate *private;
1426   
1427   g_return_if_fail (window != NULL);
1428   
1429   private = (GdkWindowPrivate*) window;
1430   GDK_NOTE (MISC, g_print ("gdk_window_set_title: %#x %s\n",
1431                            private->xwindow, title));
1432   if (!private->destroyed)
1433     {
1434       if (!SetWindowText (private->xwindow, title))
1435         g_warning ("gdk_window_set_title: SetWindowText failed");
1436     }
1437 }
1438
1439 void          
1440 gdk_window_set_role (GdkWindow   *window,
1441                      const gchar *role)
1442 {
1443   GdkWindowPrivate *private;
1444   
1445   g_return_if_fail (window != NULL);
1446   
1447   private = (GdkWindowPrivate*) window;
1448
1449   GDK_NOTE (MISC, g_print ("gdk_window_set_role: %#x %s\n",
1450                            private->xwindow, (role ? role : "NULL")));
1451   /* XXX */
1452 }
1453
1454 void          
1455 gdk_window_set_transient_for (GdkWindow *window, 
1456                               GdkWindow *parent)
1457 {
1458   GdkWindowPrivate *private;
1459   GdkWindowPrivate *parent_private;
1460   
1461   g_return_if_fail (window != NULL);
1462   
1463   private = (GdkWindowPrivate*) window;
1464   parent_private = (GdkWindowPrivate*) parent;
1465
1466   GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %#x %#x\n",
1467                            private->xwindow, parent_private->xwindow));
1468   /* XXX */
1469 }
1470
1471 void
1472 gdk_window_set_background (GdkWindow *window,
1473                            GdkColor  *color)
1474 {
1475   GdkWindowPrivate *private;
1476   
1477   g_return_if_fail (window != NULL);
1478   
1479   private = (GdkWindowPrivate*) window;
1480   if (!private->destroyed)
1481     {
1482       GdkColormapPrivate *colormap_private =
1483         (GdkColormapPrivate *) private->colormap;
1484
1485       GDK_NOTE (MISC, g_print ("gdk_window_set_background: %#x %s\n",
1486                                private->xwindow, 
1487                                gdk_color_to_string (color)));
1488
1489       if (private->bg_type == GDK_WIN32_BG_PIXMAP)
1490         {
1491           if (private->bg_pixmap != NULL)
1492             {
1493               gdk_pixmap_unref (private->bg_pixmap);
1494               private->bg_pixmap = NULL;
1495             }
1496           private->bg_type = GDK_WIN32_BG_NORMAL;
1497         }
1498 #ifdef MULTIPLE_WINDOW_CLASSES
1499       if (colormap_private != NULL
1500               && colormap_private->xcolormap->rc_palette)
1501         {
1502           /* If we are on a palettized display we can't use the window
1503            * class background brush, but must handle WM_ERASEBKGND.
1504            * At least, I think so.
1505            */
1506 #endif
1507           private->bg_type = GDK_WIN32_BG_PIXEL;
1508           private->bg_pixel = *color;
1509 #ifdef MULTIPLE_WINDOW_CLASSES
1510         }
1511       else
1512         {
1513           /* Non-palettized display; just set the window class background
1514              brush. */
1515           HBRUSH hbr;
1516           HGDIOBJ oldbrush;
1517           COLORREF background;
1518
1519           background = RGB (color->red >> 8,
1520                             color->green >> 8,
1521                             color->blue >> 8);
1522
1523           if ((hbr = CreateSolidBrush (GetNearestColor (gdk_DC,
1524                                                         background))) == NULL)
1525             {
1526               g_warning ("gdk_window_set_background: CreateSolidBrush failed");
1527               return;
1528             }
1529
1530           oldbrush = (HGDIOBJ) GetClassLong (private->xwindow,
1531                                              GCL_HBRBACKGROUND);
1532
1533           if (SetClassLong (private->xwindow, GCL_HBRBACKGROUND,
1534                             (LONG) hbr) == 0)
1535             g_warning ("gdk_window_set_background: SetClassLong failed");
1536
1537           if (!DeleteObject (oldbrush))
1538             g_warning ("gdk_window_set_background: DeleteObject failed");
1539         }
1540 #endif
1541     }
1542 }
1543
1544 void
1545 gdk_window_set_back_pixmap (GdkWindow *window,
1546                             GdkPixmap *pixmap,
1547                             gint       parent_relative)
1548 {
1549   GdkWindowPrivate *window_private;
1550 #ifdef MULTIPLE_WINDOW_CLASSES
1551   GdkPixmapPrivate *pixmap_private;
1552 #endif
1553
1554   g_return_if_fail (window != NULL);
1555   
1556   window_private = (GdkWindowPrivate*) window;
1557 #ifdef MULTIPLE_WINDOW_CLASSES
1558   pixmap_private = (GdkPixmapPrivate*) pixmap;
1559 #endif
1560
1561   if (!window_private->destroyed)
1562     {
1563       GdkColormapPrivate *colormap_private =
1564         (GdkColormapPrivate *) window_private->colormap;
1565       if (window_private->bg_type == GDK_WIN32_BG_PIXMAP)
1566         {
1567           if (window_private->bg_pixmap != NULL)
1568             {
1569               gdk_pixmap_unref (window_private->bg_pixmap);
1570               window_private->bg_pixmap = NULL;
1571             }
1572           window_private->bg_type = GDK_WIN32_BG_NORMAL;
1573         }
1574       if (parent_relative)
1575         {
1576           window_private->bg_type = GDK_WIN32_BG_PARENT_RELATIVE;
1577         }
1578       else if (!pixmap)
1579         {
1580 #ifdef MULTIPLE_WINDOW_CLASSES
1581           SetClassLong (window_private->xwindow, GCL_HBRBACKGROUND,
1582                         (LONG) GetStockObject (BLACK_BRUSH));
1583 #endif
1584         }
1585 #ifdef MULTIPLE_WINDOW_CLASSES
1586       else if (colormap_private->xcolormap->rc_palette)
1587         {
1588           /* Must do the background painting in the
1589            * WM_ERASEBKGND handler.
1590            */
1591           window_private->bg_type = GDK_WIN32_BG_PIXMAP;
1592           window_private->bg_pixmap = pixmap;
1593           gdk_pixmap_ref (pixmap);
1594         }
1595       else if (pixmap_private->width <= 8
1596                && pixmap_private->height <= 8)
1597         {
1598           /* We can use small pixmaps directly as background brush */
1599           SetClassLong (window_private->xwindow, GCL_HBRBACKGROUND,
1600                         (LONG) CreatePatternBrush (pixmap_private->xwindow));
1601         }
1602 #endif
1603       else
1604         {
1605           /* We must cache the pixmap in the WindowPrivate and
1606            * paint it each time we get WM_ERASEBKGND
1607            */
1608           window_private->bg_type = GDK_WIN32_BG_PIXMAP;
1609           window_private->bg_pixmap = pixmap;
1610           gdk_pixmap_ref (pixmap);
1611         }
1612     }
1613 }
1614
1615 void
1616 gdk_window_set_cursor (GdkWindow *window,
1617                        GdkCursor *cursor)
1618 {
1619   GdkWindowPrivate *window_private;
1620   GdkCursorPrivate *cursor_private;
1621   HCURSOR xcursor;
1622   
1623   g_return_if_fail (window != NULL);
1624   
1625   window_private = (GdkWindowPrivate*) window;
1626   cursor_private = (GdkCursorPrivate*) cursor;
1627   
1628   if (!window_private->destroyed)
1629     {
1630       if (!cursor)
1631         xcursor = LoadCursor (NULL, IDC_ARROW);
1632       else
1633         xcursor = cursor_private->xcursor;
1634
1635       GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %#x %#x\n",
1636                                window_private->xwindow, xcursor));
1637 #ifdef MULTIPLE_WINDOW_CLASSES
1638       if (!SetClassLong (window_private->xwindow, GCL_HCURSOR, (LONG) xcursor))
1639         g_warning ("gdk_window_set_cursor: SetClassLong failed");
1640 #else
1641       window_private->xcursor = xcursor;
1642 #endif
1643       SetCursor (xcursor);
1644     }
1645 }
1646
1647 void
1648 gdk_window_set_colormap (GdkWindow   *window,
1649                          GdkColormap *colormap)
1650 {
1651   GdkWindowPrivate *window_private;
1652   GdkColormapPrivate *colormap_private;
1653   
1654   g_return_if_fail (window != NULL);
1655   g_return_if_fail (colormap != NULL);
1656   
1657   window_private = (GdkWindowPrivate*) window;
1658   colormap_private = (GdkColormapPrivate*) colormap;
1659   
1660   if (!window_private->destroyed)
1661     {
1662       /* XXX ??? */
1663       GDK_NOTE (MISC, g_print ("gdk_window_set_colormap: %#x %#x\n",
1664                                window_private->xwindow,
1665                                colormap_private->xcolormap));
1666       if (window_private->colormap)
1667         gdk_colormap_unref (window_private->colormap);
1668       window_private->colormap = colormap;
1669       gdk_colormap_ref (window_private->colormap);
1670       
1671       if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
1672         gdk_window_add_colormap_windows (window);
1673     }
1674 }
1675
1676 void
1677 gdk_window_get_user_data (GdkWindow *window,
1678                           gpointer  *data)
1679 {
1680   g_return_if_fail (window != NULL);
1681   
1682   *data = window->user_data;
1683 }
1684
1685 void
1686 gdk_window_get_geometry (GdkWindow *window,
1687                          gint      *x,
1688                          gint      *y,
1689                          gint      *width,
1690                          gint      *height,
1691                          gint      *depth)
1692 {
1693   GdkWindowPrivate *window_private;
1694   
1695   if (!window)
1696     window = (GdkWindow*) &gdk_root_parent;
1697   
1698   window_private = (GdkWindowPrivate*) window;
1699   
1700   if (!window_private->destroyed)
1701     {
1702       RECT rect;
1703
1704       if (!GetClientRect (window_private->xwindow, &rect))
1705         g_warning ("gdk_window_get_geometry: GetClientRect failed");
1706
1707       if (x)
1708         *x = rect.left;
1709       if (y)
1710         *y = rect.top;
1711       if (width)
1712         *width = rect.right - rect.left;
1713       if (height)
1714         *height = rect.bottom - rect.top;
1715       if (depth)
1716         *depth = gdk_window_get_visual (window)->depth;
1717     }
1718 }
1719
1720 void
1721 gdk_window_get_position (GdkWindow *window,
1722                          gint      *x,
1723                          gint      *y)
1724 {
1725   GdkWindowPrivate *window_private;
1726   
1727   g_return_if_fail (window != NULL);
1728   
1729   window_private = (GdkWindowPrivate*) window;
1730   
1731   if (x)
1732     *x = window_private->x;
1733   if (y)
1734     *y = window_private->y;
1735 }
1736
1737 void
1738 gdk_window_get_size (GdkWindow *window,
1739                      gint       *width,
1740                      gint       *height)
1741 {
1742   GdkWindowPrivate *window_private;
1743   
1744   g_return_if_fail (window != NULL);
1745   
1746   window_private = (GdkWindowPrivate*) window;
1747   
1748   if (width)
1749     *width = window_private->width;
1750   if (height)
1751     *height = window_private->height;
1752 }
1753
1754 GdkVisual*
1755 gdk_window_get_visual (GdkWindow *window)
1756 {
1757   GdkWindowPrivate *window_private;
1758    
1759   g_return_val_if_fail (window != NULL, NULL);
1760
1761   window_private = (GdkWindowPrivate*) window;
1762   /* Huh? ->parent is never set for a pixmap. We should just return
1763    * null immeditately. Well, do it then!
1764    */
1765   if (window_private->window_type == GDK_WINDOW_PIXMAP)
1766     return NULL;
1767   
1768   if (!window_private->destroyed)
1769     {
1770        if (window_private->colormap == NULL)
1771          return gdk_visual_get_system (); /* XXX ??? */
1772        else
1773          return ((GdkColormapPrivate *)window_private->colormap)->visual;
1774     }
1775   
1776   return NULL;
1777 }
1778
1779 GdkColormap*
1780 gdk_window_get_colormap (GdkWindow *window)
1781 {
1782   GdkWindowPrivate *window_private;
1783   
1784   g_return_val_if_fail (window != NULL, NULL);
1785   window_private = (GdkWindowPrivate*) window;
1786
1787   g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL);
1788   if (!window_private->destroyed)
1789     {
1790       if (window_private->colormap == NULL)
1791         return gdk_colormap_get_system (); /* XXX ??? */
1792       else
1793         return window_private->colormap;
1794     }
1795   
1796   return NULL;
1797 }
1798
1799 GdkWindowType
1800 gdk_window_get_type (GdkWindow *window)
1801 {
1802   GdkWindowPrivate *window_private;
1803
1804   g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
1805
1806   window_private = (GdkWindowPrivate*) window;
1807   return window_private->window_type;
1808 }
1809
1810 gint
1811 gdk_window_get_origin (GdkWindow *window,
1812                        gint      *x,
1813                        gint      *y)
1814 {
1815   GdkWindowPrivate *private;
1816   gint return_val;
1817   gint tx = 0;
1818   gint ty = 0;
1819
1820   g_return_val_if_fail (window != NULL, 0);
1821
1822   private = (GdkWindowPrivate*) window;
1823
1824   if (!private->destroyed)
1825     {
1826       POINT pt;
1827
1828       pt.x = 0;
1829       pt.y = 0;
1830       ClientToScreen (private->xwindow, &pt);
1831       tx = pt.x;
1832       ty = pt.y;
1833       return_val = 1;
1834     }
1835   else
1836     return_val = 0;
1837   
1838   if (x)
1839     *x = tx;
1840   if (y)
1841     *y = ty;
1842
1843   GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %#x: +%d+%d\n",
1844                            private->xwindow, tx, ty));
1845   return return_val;
1846 }
1847
1848 gboolean
1849 gdk_window_get_deskrelative_origin (GdkWindow *window,
1850                                     gint      *x,
1851                                     gint      *y)
1852 {
1853   return gdk_window_get_origin (window, x, y);
1854 }
1855
1856 void
1857 gdk_window_get_root_origin (GdkWindow *window,
1858                             gint      *x,
1859                             gint      *y)
1860 {
1861   GdkWindowPrivate *private;
1862   POINT pt;
1863
1864   g_return_if_fail (window != NULL);
1865
1866   private = (GdkWindowPrivate*) window;
1867   if (x)
1868     *x = 0;
1869   if (y)
1870     *y = 0;
1871   if (private->destroyed)
1872     return;
1873       
1874   while (private->parent && ((GdkWindowPrivate*) private->parent)->parent)
1875     private = (GdkWindowPrivate*) private->parent;
1876   if (private->destroyed)
1877     return;
1878
1879   pt.x = 0;
1880   pt.y = 0;
1881   ClientToScreen (private->xwindow, &pt);
1882   if (x)
1883     *x = pt.x;
1884   if (y)
1885     *y = pt.y;
1886
1887   GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %#x: (%#x) +%d+%d\n",
1888                            ((GdkWindowPrivate *) window)->xwindow,
1889                            private->xwindow, pt.x, pt.y));
1890 }
1891
1892 GdkWindow*
1893 gdk_window_get_pointer (GdkWindow       *window,
1894                         gint            *x,
1895                         gint            *y,
1896                         GdkModifierType *mask)
1897 {
1898   GdkWindowPrivate *private;
1899   GdkWindow *return_val;
1900   POINT pointc, point;
1901   HWND hwnd, hwndc;
1902
1903   if (!window)
1904     window = (GdkWindow*) &gdk_root_parent;
1905
1906   private = (GdkWindowPrivate*) window;
1907
1908   return_val = NULL;
1909   GetCursorPos (&pointc);
1910   point = pointc;
1911   ScreenToClient (private->xwindow, &point);
1912
1913   if (x)
1914     *x = point.x;
1915   if (y)
1916     *y = point.y;
1917
1918   hwnd = WindowFromPoint (point);
1919   point = pointc;
1920   ScreenToClient (hwnd, &point);
1921   
1922   do {
1923     hwndc = ChildWindowFromPoint (hwnd, point);
1924     ClientToScreen (hwnd, &point);
1925     ScreenToClient (hwndc, &point);
1926   } while (hwndc != hwnd && (hwnd = hwndc, 1)); /* Ouch! */
1927
1928   return_val = gdk_window_lookup (hwnd);
1929
1930   if (mask)
1931     {
1932       BYTE kbd[256];
1933
1934       GetKeyboardState (kbd);
1935       *mask = 0;
1936       if (kbd[VK_SHIFT] & 0x80)
1937         *mask |= GDK_SHIFT_MASK;
1938       if (kbd[VK_CAPITAL] & 0x80)
1939         *mask |= GDK_LOCK_MASK;
1940       if (kbd[VK_CONTROL] & 0x80)
1941         *mask |= GDK_CONTROL_MASK;
1942       if (kbd[VK_MENU] & 0x80)
1943         *mask |= GDK_MOD1_MASK;
1944       if (kbd[VK_LBUTTON] & 0x80)
1945         *mask |= GDK_BUTTON1_MASK;
1946       if (kbd[VK_MBUTTON] & 0x80)
1947         *mask |= GDK_BUTTON2_MASK;
1948       if (kbd[VK_RBUTTON] & 0x80)
1949         *mask |= GDK_BUTTON3_MASK;
1950     }
1951   
1952   return return_val;
1953 }
1954
1955 GdkWindow*
1956 gdk_window_at_pointer (gint *win_x,
1957                        gint *win_y)
1958 {
1959   GdkWindowPrivate *private;
1960   GdkWindow *window;
1961   POINT point, pointc;
1962   HWND hwnd, hwndc;
1963   RECT rect;
1964
1965   private = &gdk_root_parent;
1966
1967   GetCursorPos (&pointc);
1968   point = pointc;
1969   hwnd = WindowFromPoint (point);
1970
1971   if (hwnd == NULL)
1972     {
1973       window = (GdkWindow *) &gdk_root_parent;
1974       if (win_x)
1975         *win_x = pointc.x;
1976       if (win_y)
1977         *win_y = pointc.y;
1978       return window;
1979     }
1980       
1981   ScreenToClient (hwnd, &point);
1982
1983   do {
1984     hwndc = ChildWindowFromPoint (hwnd, point);
1985     ClientToScreen (hwnd, &point);
1986     ScreenToClient (hwndc, &point);
1987   } while (hwndc != hwnd && (hwnd = hwndc, 1));
1988
1989   window = gdk_window_lookup (hwnd);
1990
1991   if (window && (win_x || win_y))
1992     {
1993       GetClientRect (hwnd, &rect);
1994       if (win_x)
1995         *win_x = point.x - rect.left;
1996       if (win_y)
1997         *win_y = point.y - rect.top;
1998     }
1999
2000   GDK_NOTE (MISC, g_print ("gdk_window_at_pointer: +%d+%d %#x%s\n",
2001                            point.x, point.y, hwnd,
2002                            (window == NULL ? " NULL" : "")));
2003
2004   return window;
2005 }
2006
2007 GdkWindow*
2008 gdk_window_get_parent (GdkWindow *window)
2009 {
2010   g_return_val_if_fail (window != NULL, NULL);
2011
2012   return ((GdkWindowPrivate*) window)->parent;
2013 }
2014
2015 GdkWindow*
2016 gdk_window_get_toplevel (GdkWindow *window)
2017 {
2018   GdkWindowPrivate *private;
2019
2020   g_return_val_if_fail (window != NULL, NULL);
2021
2022   private = (GdkWindowPrivate*) window;
2023
2024   while (private->window_type == GDK_WINDOW_CHILD)
2025     {
2026       window = ((GdkWindowPrivate*) window)->parent;
2027       private = (GdkWindowPrivate*) window;
2028     }
2029
2030   return window;
2031 }
2032
2033 GList*
2034 gdk_window_get_children (GdkWindow *window)
2035 {
2036   GdkWindowPrivate *private;
2037   GList *children;
2038
2039   g_return_val_if_fail (window != NULL, NULL);
2040
2041   private = (GdkWindowPrivate*) window;
2042   if (private->destroyed)
2043     return NULL;
2044
2045   /* XXX ??? */
2046   g_warning ("gdk_window_get_children ???");
2047   children = NULL;
2048
2049   return children;
2050 }
2051
2052 GdkEventMask  
2053 gdk_window_get_events (GdkWindow *window)
2054 {
2055   GdkWindowPrivate *private;
2056
2057   g_return_val_if_fail (window != NULL, 0);
2058
2059   private = (GdkWindowPrivate*) window;
2060   if (private->destroyed)
2061     return 0;
2062
2063   return private->event_mask;
2064 }
2065
2066 void          
2067 gdk_window_set_events (GdkWindow   *window,
2068                        GdkEventMask event_mask)
2069 {
2070   GdkWindowPrivate *private;
2071
2072   g_return_if_fail (window != NULL);
2073
2074   private = (GdkWindowPrivate*) window;
2075   if (private->destroyed)
2076     return;
2077
2078   private->event_mask = event_mask;
2079 }
2080
2081 void
2082 gdk_window_add_colormap_windows (GdkWindow *window)
2083 {
2084   g_warning ("gdk_window_add_colormap_windows not implemented"); /* XXX */
2085 }
2086
2087 /*
2088  * This needs the X11 shape extension.
2089  * If not available, shaped windows will look
2090  * ugly, but programs still work.    Stefan Wille
2091  */
2092 void
2093 gdk_window_shape_combine_mask (GdkWindow *window,
2094                                GdkBitmap *mask,
2095                                gint x, gint y)
2096 {
2097   GdkWindowPrivate *window_private;
2098
2099   g_return_if_fail (window != NULL);
2100
2101   window_private = (GdkWindowPrivate*) window;
2102   
2103   if (!mask)
2104     {
2105       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x none\n",
2106                                window_private->xwindow));
2107       SetWindowRgn (window_private->xwindow, NULL, TRUE);
2108     }
2109   else
2110     {
2111       GdkPixmapPrivate *pixmap_private;
2112       HRGN hrgn;
2113       DWORD dwStyle;
2114       DWORD dwExStyle;
2115       RECT rect;
2116
2117       /* Convert mask bitmap to region */
2118       pixmap_private = (GdkPixmapPrivate*) mask;
2119       hrgn = BitmapToRegion (pixmap_private->xwindow);
2120
2121       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x %#x\n",
2122                                window_private->xwindow,
2123                                pixmap_private->xwindow));
2124
2125       /* SetWindowRgn wants window (not client) coordinates */ 
2126       dwStyle = GetWindowLong (window_private->xwindow, GWL_STYLE);
2127       dwExStyle = GetWindowLong (window_private->xwindow, GWL_EXSTYLE);
2128       GetClientRect (window_private->xwindow, &rect);
2129       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
2130       OffsetRgn (hrgn, -rect.left, -rect.top);
2131
2132       OffsetRgn (hrgn, x, y);
2133
2134       /* If this is a top-level window, add the title bar to the region */
2135       if (window_private->window_type == GDK_WINDOW_TOPLEVEL)
2136         {
2137           CombineRgn (hrgn, hrgn,
2138                       CreateRectRgn (0, 0, rect.right - rect.left, -rect.top),
2139                       RGN_OR);
2140         }
2141       
2142       SetWindowRgn (window_private->xwindow, hrgn, TRUE);
2143     }
2144 }
2145
2146 void          
2147 gdk_window_add_filter (GdkWindow     *window,
2148                        GdkFilterFunc  function,
2149                        gpointer       data)
2150 {
2151   GdkWindowPrivate *private;
2152   GList *tmp_list;
2153   GdkEventFilter *filter;
2154
2155   private = (GdkWindowPrivate*) window;
2156   if (private && private->destroyed)
2157     return;
2158
2159   if (private)
2160     tmp_list = private->filters;
2161   else
2162     tmp_list = gdk_default_filters;
2163
2164   while (tmp_list)
2165     {
2166       filter = (GdkEventFilter *)tmp_list->data;
2167       if ((filter->function == function) && (filter->data == data))
2168         return;
2169       tmp_list = tmp_list->next;
2170     }
2171
2172   filter = g_new (GdkEventFilter, 1);
2173   filter->function = function;
2174   filter->data = data;
2175
2176   if (private)
2177     private->filters = g_list_append (private->filters, filter);
2178   else
2179     gdk_default_filters = g_list_append (gdk_default_filters, filter);
2180 }
2181
2182 void
2183 gdk_window_remove_filter (GdkWindow     *window,
2184                           GdkFilterFunc  function,
2185                           gpointer       data)
2186 {
2187   GdkWindowPrivate *private;
2188   GList *tmp_list, *node;
2189   GdkEventFilter *filter;
2190
2191   private = (GdkWindowPrivate*) window;
2192
2193   if(private)
2194     tmp_list = private->filters;
2195   else
2196     tmp_list = gdk_default_filters;
2197
2198   while (tmp_list)
2199     {
2200       filter = (GdkEventFilter *)tmp_list->data;
2201       node = tmp_list;
2202       tmp_list = tmp_list->next;
2203
2204       if ((filter->function == function) && (filter->data == data))
2205         {
2206           if(private)
2207             private->filters = g_list_remove_link (private->filters, node);
2208           else
2209             gdk_default_filters = g_list_remove_link (gdk_default_filters, tmp_list);
2210           g_list_free_1 (node);
2211           g_free (filter);
2212           
2213           return;
2214         }
2215     }
2216 }
2217
2218 void
2219 gdk_window_set_override_redirect (GdkWindow *window,
2220                                   gboolean   override_redirect)
2221 {
2222   g_warning ("gdk_window_set_override_redirect not implemented"); /* XXX */
2223 }
2224
2225 void          
2226 gdk_window_set_icon (GdkWindow *window, 
2227                      GdkWindow *icon_window,
2228                      GdkPixmap *pixmap,
2229                      GdkBitmap *mask)
2230 {
2231   g_warning ("gdk_window_set_icon not implemented"); /* XXX */
2232 }
2233
2234 void          
2235 gdk_window_set_icon_name (GdkWindow *window, 
2236                           gchar     *name)
2237 {
2238   GdkWindowPrivate *window_private;
2239
2240   g_return_if_fail (window != NULL);
2241   window_private = (GdkWindowPrivate*) window;
2242   if (window_private->destroyed)
2243     return;
2244
2245   if (!SetWindowText (window_private->xwindow, name))
2246     g_warning ("gdk_window_set_icon_name: SetWindowText failed");
2247 }
2248
2249 void          
2250 gdk_window_set_group (GdkWindow *window, 
2251                       GdkWindow *leader)
2252 {
2253   g_warning ("gdk_window_set_group not implemented"); /* XXX */
2254 }
2255
2256 void
2257 gdk_window_set_decorations (GdkWindow      *window,
2258                             GdkWMDecoration decorations)
2259 {
2260   GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
2261   LONG style, exstyle;
2262
2263   style = GetWindowLong (window_private->xwindow, GWL_STYLE);
2264   exstyle = GetWindowLong (window_private->xwindow, GWL_EXSTYLE);
2265
2266   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2267             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE);
2268
2269   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2270
2271   if (decorations & GDK_DECOR_ALL)
2272     style |= (WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2273   if (decorations & GDK_DECOR_BORDER)
2274     style |= (WS_BORDER);
2275   if (decorations & GDK_DECOR_RESIZEH)
2276     style |= (WS_THICKFRAME);
2277   if (decorations & GDK_DECOR_TITLE)
2278     style |= (WS_CAPTION);
2279   if (decorations & GDK_DECOR_MENU)
2280     style |= (WS_SYSMENU);
2281   if (decorations & GDK_DECOR_MINIMIZE)
2282     style |= (WS_MINIMIZEBOX);
2283   if (decorations & GDK_DECOR_MAXIMIZE)
2284     style |= (WS_MAXIMIZEBOX);
2285   
2286   SetWindowLong (window_private->xwindow, GWL_STYLE, style);
2287 }
2288
2289 void
2290 gdk_window_set_functions (GdkWindow    *window,
2291                           GdkWMFunction functions)
2292 {
2293   GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
2294   LONG style, exstyle;
2295
2296   style = GetWindowLong (window_private->xwindow, GWL_STYLE);
2297   exstyle = GetWindowLong (window_private->xwindow, GWL_EXSTYLE);
2298
2299   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2300             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE|WS_CAPTION|WS_BORDER
2301             |WS_SYSMENU);
2302
2303   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2304
2305   if (functions & GDK_FUNC_ALL)
2306     style |= (WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2307   if (functions & GDK_FUNC_RESIZE)
2308     style |= (WS_THICKFRAME);
2309   if (functions & GDK_FUNC_MOVE)
2310     style |= (WS_THICKFRAME);
2311   if (functions & GDK_FUNC_MINIMIZE)
2312     style |= (WS_MINIMIZEBOX);
2313   if (functions & GDK_FUNC_MAXIMIZE)
2314     style |= (WS_MAXIMIZEBOX);
2315   
2316   SetWindowLong (window_private->xwindow, GWL_STYLE, style);
2317 }
2318
2319 GList *
2320 gdk_window_get_toplevels (void)
2321 {
2322   GList *new_list = NULL;
2323   GList *tmp_list;
2324
2325   tmp_list = gdk_root_parent.children;
2326   while (tmp_list)
2327     {
2328       new_list = g_list_prepend (new_list, tmp_list->data);
2329       tmp_list = tmp_list->next;
2330     }
2331
2332   return new_list;
2333 }
2334
2335 /* 
2336  * propagate the shapes from all child windows of a GDK window to the parent 
2337  * window. Shamelessly ripped from Enlightenment's code
2338  * 
2339  * - Raster
2340  */
2341
2342 static void
2343 QueryTree (HWND hwnd,
2344            HWND **children,
2345            gint *nchildren)
2346 {
2347   guint i, n;
2348   HWND child;
2349
2350   n = 0;
2351   do {
2352     if (n == 0)
2353       child = GetWindow (hwnd, GW_CHILD);
2354     else
2355       child = GetWindow (child, GW_HWNDNEXT);
2356     if (child != NULL)
2357       n++;
2358   } while (child != NULL);
2359
2360   if (n > 0)
2361     {
2362       *children = g_new (HWND, n);
2363       for (i = 0; i < n; i++)
2364         {
2365           if (i == 0)
2366             child = GetWindow (hwnd, GW_CHILD);
2367           else
2368             child = GetWindow (child, GW_HWNDNEXT);
2369           *children[i] = child;
2370         }
2371     }
2372 }
2373
2374 static void
2375 gdk_propagate_shapes (HANDLE   win,
2376                       gboolean merge)
2377 {
2378    RECT emptyRect;
2379    HRGN region, childRegion;
2380    RECT rect;
2381    HWND *list = NULL;
2382    gint i, num;
2383
2384    SetRectEmpty (&emptyRect);
2385    region = CreateRectRgnIndirect (&emptyRect);
2386    if (merge)
2387      GetWindowRgn (win, region);
2388    
2389    QueryTree (win, &list, &num);
2390    if (list != NULL)
2391      {
2392        WINDOWPLACEMENT placement;
2393
2394        placement.length = sizeof (WINDOWPLACEMENT);
2395        /* go through all child windows and combine regions */
2396        for (i = 0; i < num; i++)
2397          {
2398            GetWindowPlacement (list[i], &placement);
2399            if (placement.showCmd = SW_SHOWNORMAL)
2400              {
2401                childRegion = CreateRectRgnIndirect (&emptyRect);
2402                GetWindowRgn (list[i], childRegion);
2403                CombineRgn (region, region, childRegion, RGN_OR);
2404                DeleteObject (childRegion);
2405              }
2406           }
2407        SetWindowRgn (win, region, TRUE);
2408      }
2409    else
2410      DeleteObject (region);
2411 }
2412
2413 void
2414 gdk_window_set_child_shapes (GdkWindow *window)
2415 {
2416   GdkWindowPrivate *private;
2417    
2418   g_return_if_fail (window != NULL);
2419    
2420   private = (GdkWindowPrivate*) window;
2421   if (private->destroyed)
2422     return;
2423
2424   gdk_propagate_shapes ( private->xwindow, FALSE);
2425 }
2426
2427 void
2428 gdk_window_merge_child_shapes (GdkWindow *window)
2429 {
2430   GdkWindowPrivate *private;
2431   
2432   g_return_if_fail (window != NULL);
2433   
2434   private = (GdkWindowPrivate*) window;
2435   if (private->destroyed)
2436     return;
2437
2438   gdk_propagate_shapes (private->xwindow, TRUE);
2439 }
2440
2441 /*************************************************************
2442  * gdk_window_is_visible:
2443  *     Check if the given window is mapped.
2444  *   arguments:
2445  *     window: 
2446  *   results:
2447  *     is the window mapped
2448  *************************************************************/
2449
2450 gboolean 
2451 gdk_window_is_visible (GdkWindow *window)
2452 {
2453   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2454
2455   g_return_val_if_fail (window != NULL, FALSE);
2456
2457   return private->mapped;
2458 }
2459
2460 /*************************************************************
2461  * gdk_window_is_viewable:
2462  *     Check if the window and all ancestors of the window
2463  *     are mapped. (This is not necessarily "viewable" in
2464  *     the X sense, since we only check as far as we have
2465  *     GDK window parents, not to the root window)
2466  *   arguments:
2467  *     window:
2468  *   results:
2469  *     is the window viewable
2470  *************************************************************/
2471
2472 gboolean 
2473 gdk_window_is_viewable (GdkWindow *window)
2474 {
2475   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2476
2477   g_return_val_if_fail (window != NULL, FALSE);
2478
2479   while (private && 
2480          (private != &gdk_root_parent) &&
2481          (private->window_type != GDK_WINDOW_FOREIGN))
2482     {
2483       if (!private->mapped)
2484         return FALSE;
2485
2486       private = (GdkWindowPrivate *)private->parent;
2487     }
2488
2489   return TRUE;
2490 }
2491
2492 void          
2493 gdk_drawable_set_data (GdkDrawable   *drawable,
2494                        const gchar   *key,
2495                        gpointer       data,
2496                        GDestroyNotify destroy_func)
2497 {
2498   g_dataset_set_data_full (drawable, key, data, destroy_func);
2499 }
2500
2501
2502 /* Support for windows that can be guffaw-scrolled
2503  * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
2504  */
2505
2506 static gboolean
2507 gdk_window_gravity_works (void)
2508 {
2509   enum { UNKNOWN, NO, YES };
2510   static gint gravity_works = UNKNOWN;
2511
2512   if (gravity_works == UNKNOWN)
2513     {
2514       GdkWindowAttr attr;
2515       GdkWindow *parent;
2516       GdkWindow *child;
2517       gint y;
2518       
2519       attr.window_type = GDK_WINDOW_TEMP;
2520       attr.wclass = GDK_INPUT_OUTPUT;
2521       attr.x = 0;
2522       attr.y = 0;
2523       attr.width = 100;
2524       attr.height = 100;
2525       attr.event_mask = 0;
2526       
2527       parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
2528       
2529       attr.window_type = GDK_WINDOW_CHILD;
2530       child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
2531
2532       gdk_window_set_static_win_gravity (child, TRUE);
2533       
2534       gdk_window_resize (parent, 100, 110);
2535       gdk_window_move (parent, 0, -10);
2536       gdk_window_move_resize (parent, 0, 0, 100, 100);
2537       
2538       gdk_window_resize (parent, 100, 110);
2539       gdk_window_move (parent, 0, -10);
2540       gdk_window_move_resize (parent, 0, 0, 100, 100);
2541       
2542       gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
2543       
2544       gdk_window_destroy (parent);
2545       gdk_window_destroy (child);
2546   
2547       gravity_works = ((y == -20) ? YES : NO);
2548     }
2549
2550   return (gravity_works == YES);
2551 }
2552
2553 static void
2554 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
2555 {
2556   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2557
2558   g_return_if_fail (window != NULL);
2559
2560   GDK_NOTE (MISC,
2561             g_print ("gdk_window_set_static_bit_gravity: Not implemented\n"));
2562 }
2563
2564 static void
2565 gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
2566 {
2567   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2568
2569   g_return_if_fail (window != NULL);
2570
2571   GDK_NOTE (MISC,
2572             g_print ("gdk_window_set_static_win_gravity: Not implemented\n"));
2573 }
2574
2575 /*************************************************************
2576  * gdk_window_set_static_gravities:
2577  *     Set the bit gravity of the given window to static,
2578  *     and flag it so all children get static subwindow
2579  *     gravity.
2580  *   arguments:
2581  *     window: window for which to set static gravity
2582  *     use_static: Whether to turn static gravity on or off.
2583  *   results:
2584  *     Does the XServer support static gravity?
2585  *************************************************************/
2586
2587 gboolean 
2588 gdk_window_set_static_gravities (GdkWindow *window,
2589                                  gboolean   use_static)
2590 {
2591   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2592   GList *tmp_list;
2593
2594   g_return_val_if_fail (window != NULL, FALSE);
2595   
2596   if (!use_static == !private->guffaw_gravity)
2597     return TRUE;
2598   
2599   if (use_static && !gdk_window_gravity_works ())
2600     return FALSE;
2601
2602   private->guffaw_gravity = use_static;
2603
2604   gdk_window_set_static_bit_gravity (window, use_static);
2605
2606   tmp_list = private->children;
2607   while (tmp_list)
2608     {
2609       gdk_window_set_static_win_gravity (window, use_static);
2610       
2611       tmp_list = tmp_list->next;
2612     }
2613
2614   return TRUE;
2615 }