]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow-win32.c
Corresponding changes as in X11 backend.
[~andy/gtk] / gdk / win32 / gdkwindow-win32.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
33 #include "gdkevents.h"
34 #include "gdkpixmap.h"
35 #include "gdkwindow.h"
36 #include "gdkprivate.h"
37 #include "gdkinputprivate.h"
38 #include "gdkx.h"
39
40 /* The Win API function AdjustWindowRect may return negative values
41  * resulting in obscured title bars. This helper function is coreccting it.
42  */
43 BOOL
44 SafeAdjustWindowRectEx (RECT* lpRect, 
45                         DWORD dwStyle, 
46                         BOOL bMenu, 
47                         DWORD dwExStyle)
48 {
49   if (!AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle))
50     return FALSE;
51   if (lpRect->left < 0)
52     {
53       lpRect->right -= lpRect->left;
54       lpRect->left = 0;
55     }
56   if (lpRect->top < 0)
57     {
58       lpRect->bottom -= lpRect->top;
59       lpRect->top = 0;
60     }
61   return TRUE;
62 }
63
64 /* Forward declarations */
65 static gboolean gdk_window_gravity_works (void);
66 static void     gdk_window_set_static_win_gravity (GdkWindow *window, 
67                                                    gboolean   on);
68
69 /* 
70  * The following fucntion by The Rasterman <raster@redhat.com>
71  * This function returns the X Window ID in which the x y location is in 
72  * (x and y being relative to the root window), excluding any windows listed
73  * in the GList excludes (this is a list of X Window ID's - gpointer being
74  * the Window ID).
75  * 
76  * This is primarily designed for internal gdk use - for DND for example
77  * when using a shaped icon window as the drag object - you exclude the
78  * X Window ID of the "icon" (perhaps more if excludes may be needed) and
79  * You can get back an X Window ID as to what X Window ID is infact under
80  * those X,Y co-ordinates.
81  */
82 HWND
83 gdk_window_xid_at_coords (gint     x,
84                           gint     y,
85                           GList   *excludes,
86                           gboolean excl_child)
87 {
88   POINT pt;
89   gboolean warned = FALSE;
90
91   pt.x = x;
92   pt.y = y;
93   /* This is probably not correct, just a quick hack */
94
95   if (!warned)
96     {
97       g_warning ("gdk_window_xid_at_coords probably not implemented correctly");
98       warned = TRUE;
99     }
100
101   /* XXX */
102   return WindowFromPoint (pt);
103 }
104
105 void
106 gdk_window_init (void)
107 {
108   unsigned int width;
109   unsigned int height;
110 #if 0
111   width = GetSystemMetrics (SM_CXSCREEN);
112   height = GetSystemMetrics (SM_CYSCREEN);
113 #else
114   { RECT r; /* //HB: don't obscure tray window (task bar) */
115     SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
116     width  = r.right - r.left;
117     height = r.bottom - r.top;
118   }
119 #endif
120
121   gdk_root_parent.drawable.xwindow = gdk_root_window;
122   gdk_root_parent.drawable.window_type = GDK_WINDOW_ROOT;
123   gdk_root_parent.drawable.drawable.user_data = NULL;
124   gdk_root_parent.drawable.width = width;
125   gdk_root_parent.drawable.height = height;
126   gdk_root_parent.drawable.ref_count = 1;
127   gdk_root_parent.drawable.colormap = NULL;
128   gdk_root_parent.children = NULL;
129
130   gdk_xid_table_insert (&gdk_root_window, &gdk_root_parent);
131 }
132
133 /* RegisterGdkClass
134  *   is a wrapper function for RegisterWindowClassEx.
135  *   It creates at least one unique class for every 
136  *   GdkWindowType. If support for single window-specific icons
137  *   is ever needed (e.g Dialog specific), every such window should
138  *   get its own class
139  */
140 ATOM
141 RegisterGdkClass(GdkWindowType wtype)
142 {
143   static ATOM klassTOPLEVEL = 0;
144   static ATOM klassDIALOG   = 0;
145   static ATOM klassCHILD    = 0;
146   static ATOM klassTEMP     = 0;
147   static HICON hAppIcon = NULL;
148   static WNDCLASSEX wcl; 
149   ATOM klass = 0;
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_DRAWABLE_PIXMAP:
239       g_error ("cannot make windows of type GDK_DRAWABLE_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 (GDK_DRAWABLE_DESTROYED (parent))
272     return NULL;
273
274   xparent = parent_private->drawable.xwindow;
275
276   private = g_new (GdkWindowPrivate, 1);
277   window = (GdkWindow*) private;
278
279   private->parent = parent;
280
281   private->drawable.destroyed = FALSE;
282   private->mapped = FALSE;
283   private->guffaw_gravity = FALSE;
284   private->resize_count = 0;
285   private->drawable.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->drawable.width = (attributes->width > 1) ? (attributes->width) : (1);
291   private->drawable.height = (attributes->height > 1) ? (attributes->height) : (1);
292   private->drawable.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->drawable.colormap = attributes->colormap;
327       else
328         private->drawable.colormap = gdk_colormap_get_system ();
329     }
330   else
331     {
332       dwExStyle = WS_EX_TRANSPARENT;
333       private->drawable.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->drawable.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_DRAWABLE_PIXMAP:
375       g_error ("cannot make windows of type GDK_DRAWABLE_PIXMAP (use gdk_pixmap_new)");
376       break;
377     }
378
379   klass = RegisterGdkClass (private->drawable.window_type);
380   if (!klass)
381     g_error ("RegisterClassEx failed");
382
383   if (private->drawable.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->drawable.width;
397       rect.bottom = rect.top + private->drawable.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->drawable.width;
413       height = private->drawable.height;
414     }
415
416   private->drawable.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->drawable.window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
430                       (private->drawable.window_type == GDK_WINDOW_CHILD ? "CHILD" :
431                        (private->drawable.window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
432                         (private->drawable.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->drawable.xwindow));
440
441   gdk_window_ref (window);
442   gdk_xid_table_insert (&private->drawable.xwindow, window);
443
444   if (private->drawable.colormap)
445     gdk_colormap_ref (private->drawable.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->drawable.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->drawable.width = rect.right - rect.left;
485   private->drawable.height = rect.bottom - rect.top;
486   private->resize_count = 0;
487   private->drawable.ref_count = 1;
488   private->drawable.window_type = GDK_WINDOW_FOREIGN;
489   private->drawable.destroyed = FALSE;
490   private->mapped = IsWindowVisible (private->drawable.xwindow);
491   private->guffaw_gravity = FALSE;
492   private->extension_events = 0;
493   private->extension_events_selected = FALSE;
494
495   private->drawable.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->drawable.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->drawable.xwindow));
531
532   switch (private->drawable.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->drawable.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 (GDK_DRAWABLE_TYPE (window) != 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->drawable.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->drawable.xwindow, WM_QUIT, 0, 0);
601                 }
602             }
603           else if (xdestroy)
604             DestroyWindow (private->drawable.xwindow);
605
606           if (private->drawable.colormap)
607             gdk_colormap_unref (private->drawable.colormap);
608
609           private->mapped = FALSE;
610           private->drawable.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_DRAWABLE_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   g_return_if_fail (window != NULL);
640
641   GDK_NOTE (EVENTS, g_print ("gdk_window_destroy_notify: %#x  %d\n",
642                              GDK_DRAWABLE_XID (window), GDK_DRAWABLE_DESTROYED (window)));
643
644   if (!GDK_DRAWABLE_DESTROYED (window))
645     {
646       if (GDK_DRAWABLE_TYPE(window) != GDK_WINDOW_FOREIGN)
647         g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_DRAWABLE_XID (window));
648
649       gdk_window_internal_destroy (window, FALSE, FALSE);
650     }
651   
652   gdk_xid_table_remove (GDK_DRAWABLE_XID (window));
653   gdk_window_unref (window);
654 }
655
656 GdkWindow*
657 gdk_window_ref (GdkWindow *window)
658 {
659   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
660   g_return_val_if_fail (window != NULL, NULL);
661   
662   private->drawable.ref_count += 1;
663
664   GDK_NOTE (MISC, g_print ("gdk_window_ref %#x %d\n",
665                            GDK_DRAWABLE_XID (window),
666                            private->drawable.ref_count));
667
668   return window;
669 }
670
671 void
672 gdk_window_unref (GdkWindow *window)
673 {
674   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
675   g_return_if_fail (window != NULL);
676
677   private->drawable.ref_count -= 1;
678
679   GDK_NOTE (MISC, g_print ("gdk_window_unref %#x %d%s\n",
680                            private->drawable.xwindow,
681                            private->drawable.ref_count,
682                            (private->drawable.ref_count == 0 ? " freeing" : "")));
683
684   if (private->drawable.ref_count == 0)
685     {
686       if (private->bg_type == GDK_WIN32_BG_PIXMAP
687           && private->bg_pixmap != NULL)
688         gdk_pixmap_unref (private->bg_pixmap);
689
690       if (!private->drawable.destroyed)
691         {
692           if (private->drawable.window_type == GDK_WINDOW_FOREIGN)
693             gdk_xid_table_remove (private->drawable.xwindow);
694           else
695             g_warning ("losing last reference to undestroyed window");
696         }
697       g_dataset_destroy (window);
698       g_free (window);
699     }
700 }
701
702 void
703 gdk_window_show (GdkWindow *window)
704 {
705   GdkWindowPrivate *private;
706
707   g_return_if_fail (window != NULL);
708
709   private = (GdkWindowPrivate*) window;
710   if (!private->drawable.destroyed)
711     {
712       GDK_NOTE (MISC, g_print ("gdk_window_show: %#x\n",
713                                private->drawable.xwindow));
714
715       private->mapped = TRUE;
716       if (private->drawable.window_type == GDK_WINDOW_TEMP)
717         {
718           ShowWindow (private->drawable.xwindow, SW_SHOWNOACTIVATE);
719           SetWindowPos (private->drawable.xwindow, HWND_TOPMOST, 0, 0, 0, 0,
720                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
721 #if 0
722           ShowWindow (private->drawable.xwindow, SW_HIDE); /* Don't put on toolbar */
723 #endif
724         }
725       else
726         {
727           ShowWindow (private->drawable.xwindow, SW_SHOWNORMAL);
728           ShowWindow (private->drawable.xwindow, SW_RESTORE);
729           SetForegroundWindow (private->drawable.xwindow);
730 #if 0
731           ShowOwnedPopups (private->drawable.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->drawable.destroyed)
746     {
747       GDK_NOTE (MISC, g_print ("gdk_window_hide: %#x\n",
748                                private->drawable.xwindow));
749
750       private->mapped = FALSE;
751       if (private->drawable.window_type == GDK_WINDOW_TOPLEVEL)
752         ShowOwnedPopups (private->drawable.xwindow, FALSE);
753 #if 1
754       ShowWindow (private->drawable.xwindow, SW_HIDE);
755 #elif 0
756       ShowWindow (private->drawable.xwindow, SW_MINIMIZE);
757 #else
758       CloseWindow (private->drawable.xwindow);
759 #endif
760     }
761 }
762
763 void
764 gdk_window_withdraw (GdkWindow *window)
765 {
766   GdkWindowPrivate *private;
767
768   g_return_if_fail (window != NULL);
769
770   private = (GdkWindowPrivate*) window;
771   if (!private->drawable.destroyed)
772     {
773       GDK_NOTE (MISC, g_print ("gdk_window_withdraw: %#x\n",
774                                private->drawable.xwindow));
775
776       gdk_window_hide (window); /* XXX */
777     }
778 }
779
780 void
781 gdk_window_move (GdkWindow *window,
782                  gint       x,
783                  gint       y)
784 {
785   GdkWindowPrivate *private;
786
787   g_return_if_fail (window != NULL);
788
789   private = (GdkWindowPrivate*) window;
790   if (!private->drawable.destroyed)
791     {
792       RECT rect;
793
794       GDK_NOTE (MISC, g_print ("gdk_window_move: %#x +%d+%d\n",
795                                private->drawable.xwindow, x, y));
796
797       GetClientRect (private->drawable.xwindow, &rect);
798
799       if (private->drawable.window_type != GDK_WINDOW_CHILD)
800         {
801           POINT ptTL, ptBR;
802           DWORD dwStyle;
803           DWORD dwExStyle;
804
805           ptTL.x = 0;
806           ptTL.y = 0; 
807           ClientToScreen (private->drawable.xwindow, &ptTL);
808           rect.left = x;
809           rect.top = y;
810
811           ptBR.x = rect.right;
812           ptBR.y = rect.bottom;
813           ClientToScreen (private->drawable.xwindow, &ptBR);
814           rect.right = x + ptBR.x - ptTL.x;
815           rect.bottom = y + ptBR.y - ptTL.y;
816
817           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
818           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
819           if (!SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
820             g_warning ("gdk_window_move: AdjustWindowRectEx failed");
821
822           x = rect.left;
823           y = rect.top;
824         }
825       else
826         {
827           private->x = x;
828           private->y = y;
829         }
830       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
831                                private->drawable.xwindow,
832                                rect.right - rect.left, rect.bottom - rect.top,
833                                x, y));
834       if (!MoveWindow (private->drawable.xwindow,
835                        x, y, rect.right - rect.left, rect.bottom - rect.top,
836                        TRUE))
837         g_warning ("gdk_window_move: MoveWindow failed");
838     }
839 }
840
841 void
842 gdk_window_resize (GdkWindow *window,
843                    gint       width,
844                    gint       height)
845 {
846   GdkWindowPrivate *private;
847
848   g_return_if_fail (window != NULL);
849
850   if ((gint16) width < 1)
851     width = 1;
852   if ((gint16) height < 1)
853     height = 1;
854
855   private = (GdkWindowPrivate*) window;
856
857   if (!private->drawable.destroyed &&
858       ((private->resize_count > 0) ||
859        (private->drawable.width != (guint16) width) ||
860        (private->drawable.height != (guint16) height)))
861     {
862       int x, y;
863
864       GDK_NOTE (MISC, g_print ("gdk_window_resize: %#x %dx%d\n",
865                                private->drawable.xwindow, width, height));
866       
867       if (private->drawable.window_type != GDK_WINDOW_CHILD)
868         {
869           POINT pt;
870           RECT rect;
871           DWORD dwStyle;
872           DWORD dwExStyle;
873
874           pt.x = 0;
875           pt.y = 0; 
876           ClientToScreen (private->drawable.xwindow, &pt);
877           rect.left = pt.x;
878           rect.top = pt.y;
879           rect.right = pt.x + width;
880           rect.bottom = pt.y + height;
881
882           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
883           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
884           if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
885             g_warning ("gdk_window_resize: AdjustWindowRectEx failed");
886
887           x = rect.left;
888           y = rect.top;
889           width = rect.right - rect.left;
890           height = rect.bottom - rect.top;
891         }
892       else
893         {
894           x = private->x;
895           y = private->y;
896           private->drawable.width = width;
897           private->drawable.height = height;
898         }
899
900       private->resize_count += 1;
901
902       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
903                                private->drawable.xwindow, width, height, x, y));
904       if (!MoveWindow (private->drawable.xwindow,
905                        x, y, width, height,
906                        TRUE))
907         g_warning ("gdk_window_resize: MoveWindow failed");
908     }
909 }
910
911 void
912 gdk_window_move_resize (GdkWindow *window,
913                         gint       x,
914                         gint       y,
915                         gint       width,
916                         gint       height)
917 {
918   GdkWindowPrivate *private;
919
920   g_return_if_fail (window != NULL);
921
922   if ((gint16) width < 1)
923     width = 1;
924   if ((gint16) height < 1)
925     height = 1;
926
927   private = (GdkWindowPrivate*) window;
928   if (!private->drawable.destroyed)
929     {
930       RECT rect;
931       DWORD dwStyle;
932       DWORD dwExStyle;
933
934       GDK_NOTE (MISC, g_print ("gdk_window_move_resize: %#x %dx%d@+%d+%d\n",
935                                private->drawable.xwindow, width, height, x, y));
936       
937       rect.left = x;
938       rect.top = y;
939       rect.right = x + width;
940       rect.bottom = y + height;
941
942       dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
943       dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
944       if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
945         g_warning ("gdk_window_move_resize: AdjustWindowRectEx failed");
946
947       if (private->drawable.window_type == GDK_WINDOW_CHILD)
948         {
949           private->x = x;
950           private->y = y;
951           private->drawable.width = width;
952           private->drawable.height = height;
953         }
954       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
955                                private->drawable.xwindow,
956                                rect.right - rect.left, rect.bottom - rect.top,
957                                rect.left, rect.top));
958       if (!MoveWindow (private->drawable.xwindow,
959                        rect.left, rect.top,
960                        rect.right - rect.left, rect.bottom - rect.top,
961                        TRUE))
962         g_warning ("gdk_window_move_resize: MoveWindow failed");
963
964       if (private->guffaw_gravity)
965         {
966           GList *tmp_list = private->children;
967           while (tmp_list)
968             {
969               GdkWindowPrivate *child_private = tmp_list->data;
970               
971               child_private->x -= x - private->x;
972               child_private->y -= y - private->y;
973               
974               tmp_list = tmp_list->next;
975             }
976         }
977       
978     }
979 }
980
981 void
982 gdk_window_reparent (GdkWindow *window,
983                      GdkWindow *new_parent,
984                      gint       x,
985                      gint       y)
986 {
987   GdkWindowPrivate *window_private;
988   GdkWindowPrivate *parent_private;
989   GdkWindowPrivate *old_parent_private;
990
991   g_return_if_fail (window != NULL);
992
993   if (!new_parent)
994     new_parent = (GdkWindow*) &gdk_root_parent;
995
996   window_private = (GdkWindowPrivate*) window;
997   old_parent_private = (GdkWindowPrivate*)window_private->parent;
998   parent_private = (GdkWindowPrivate*) new_parent;
999
1000   if (!window_private->drawable.destroyed && !parent_private->drawable.destroyed)
1001     {
1002       GDK_NOTE (MISC, g_print ("gdk_window_reparent: %#x %#x\n",
1003                                window_private->drawable.xwindow,
1004                                parent_private->drawable.xwindow));
1005       if (!SetParent (window_private->drawable.xwindow, parent_private->drawable.xwindow))
1006         g_warning ("gdk_window_reparent: SetParent failed");
1007
1008       if (!MoveWindow (window_private->drawable.xwindow,
1009                        x, y,
1010                        window_private->drawable.width, window_private->drawable.height,
1011                        TRUE))
1012         g_warning ("gdk_window_reparent: MoveWindow failed");
1013     }
1014   
1015   window_private->parent = new_parent;
1016
1017   if (old_parent_private)
1018     old_parent_private->children = g_list_remove (old_parent_private->children, window);
1019
1020   if ((old_parent_private &&
1021        (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
1022       (!old_parent_private && parent_private->guffaw_gravity))
1023     gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
1024   
1025   parent_private->children = g_list_prepend (parent_private->children, window);
1026 }
1027
1028 void
1029 gdk_window_clear (GdkWindow *window)
1030 {
1031   g_return_if_fail (window != NULL);
1032   g_return_if_fail (GDK_IS_WINDOW (window));
1033
1034   if (!GDK_DRAWABLE_DESTROYED (window))
1035     gdk_window_clear_area (window, 0, 0, -1, -1);
1036 }
1037
1038
1039 void
1040 gdk_window_clear_area (GdkWindow *window,
1041                        gint       x,
1042                        gint       y,
1043                        gint       width,
1044                        gint       height)
1045 {
1046   g_return_if_fail (window != NULL);
1047   g_return_if_fail (GDK_IS_WINDOW (window));
1048   
1049   if (!GDK_DRAWABLE_DESTROYED (window))
1050     {
1051       HDC hdc;
1052
1053       if (width == -1)
1054         width = G_MAXSHORT/2;           /* Yeah, right */
1055       if (height == -1)
1056         height = G_MAXSHORT/2;
1057       GDK_NOTE (MISC, g_print ("gdk_window_clear_area: %#x %dx%d@+%d+%d\n",
1058                                GDK_DRAWABLE_XID (window), width, height, x, y));
1059       hdc = GetDC (GDK_DRAWABLE_XID (window));
1060       IntersectClipRect (hdc, x, y, x + width, y + height);
1061       SendMessage (GDK_DRAWABLE_XID (window), WM_ERASEBKGND, (WPARAM) hdc, 0);
1062       ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
1063     }
1064 }
1065
1066 void
1067 gdk_window_clear_area_e (GdkWindow *window,
1068                          gint       x,
1069                          gint       y,
1070                          gint       width,
1071                          gint       height)
1072 {
1073   g_return_if_fail (window != NULL);
1074   g_return_if_fail (GDK_IS_WINDOW (window));
1075   
1076   if (!GDK_DRAWABLE_DESTROYED (window))
1077     {
1078       RECT rect;
1079
1080       GDK_NOTE (MISC, g_print ("gdk_window_clear_area_e: %#x %dx%d@+%d+%d\n",
1081                                GDK_DRAWABLE_XID (window), width, height, x, y));
1082
1083       rect.left = x;
1084       rect.right = x + width;
1085       rect.top = y;
1086       rect.bottom = y + height;
1087       if (!InvalidateRect (GDK_DRAWABLE_XID (window), &rect, TRUE))
1088         g_warning ("gdk_window_clear_area_e: InvalidateRect failed");
1089       UpdateWindow (GDK_DRAWABLE_XID (window));
1090     }
1091 }
1092
1093 void
1094 gdk_window_raise (GdkWindow *window)
1095 {
1096   g_return_if_fail (window != NULL);
1097   g_return_if_fail (GDK_IS_WINDOW (window));
1098   
1099   if (!GDK_DRAWABLE_DESTROYED (window))
1100     {
1101       GDK_NOTE (MISC, g_print ("gdk_window_raise: %#x\n",
1102                                GDK_DRAWABLE_XID (window)));
1103
1104       if (!BringWindowToTop (GDK_DRAWABLE_XID (window)))
1105         g_warning ("gdk_window_raise: BringWindowToTop failed");
1106     }
1107 }
1108
1109 void
1110 gdk_window_lower (GdkWindow *window)
1111 {
1112   g_return_if_fail (window != NULL);
1113   g_return_if_fail (GDK_IS_WINDOW (window));
1114   
1115   if (!GDK_DRAWABLE_DESTROYED (window))
1116     {
1117       GDK_NOTE (MISC, g_print ("gdk_window_lower: %#x\n",
1118                                GDK_DRAWABLE_XID (window)));
1119
1120       if (!SetWindowPos (GDK_DRAWABLE_XID (window), HWND_BOTTOM, 0, 0, 0, 0,
1121                          SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE))
1122         g_warning ("gdk_window_lower: SetWindowPos failed");
1123     }
1124 }
1125
1126 void
1127 gdk_window_set_user_data (GdkWindow *window,
1128                           gpointer   user_data)
1129 {
1130   g_return_if_fail (window != NULL);
1131   
1132   window->user_data = user_data;
1133 }
1134
1135 void
1136 gdk_window_set_hints (GdkWindow *window,
1137                       gint       x,
1138                       gint       y,
1139                       gint       min_width,
1140                       gint       min_height,
1141                       gint       max_width,
1142                       gint       max_height,
1143                       gint       flags)
1144 {
1145   GdkWindowPrivate *private;
1146   WINDOWPLACEMENT size_hints;
1147   RECT rect;
1148   DWORD dwStyle;
1149   DWORD dwExStyle;
1150   int diff;
1151   
1152   g_return_if_fail (window != NULL);
1153   g_return_if_fail (GDK_IS_WINDOW (window));
1154   
1155   if (GDK_DRAWABLE_DESTROYED (window))
1156     return;
1157   
1158   private = (GdkWindowPrivate*) window;
1159
1160   GDK_NOTE (MISC, g_print ("gdk_window_set_hints: %#x %dx%d..%dx%d @+%d+%d\n",
1161                            private->drawable.xwindow,
1162                            min_width, min_height, max_width, max_height,
1163                            x, y));
1164
1165   private->hint_flags = flags;
1166   size_hints.length = sizeof (size_hints);
1167
1168   if (flags)
1169     {
1170       if (flags & GDK_HINT_POS)
1171         if (!GetWindowPlacement (private->drawable.xwindow, &size_hints))
1172           g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
1173         else
1174           {
1175             GDK_NOTE (MISC, g_print ("...rcNormalPosition:"
1176                                      " (%d,%d)--(%d,%d)\n",
1177                                      size_hints.rcNormalPosition.left,
1178                                      size_hints.rcNormalPosition.top,
1179                                      size_hints.rcNormalPosition.right,
1180                                      size_hints.rcNormalPosition.bottom));
1181             /* What are the corresponding window coordinates for client
1182              * area coordinates x, y
1183              */
1184             rect.left = x;
1185             rect.top = y;
1186             rect.right = rect.left + 200;       /* dummy */
1187             rect.bottom = rect.top + 200;
1188             dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1189             dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1190             AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1191             size_hints.flags = 0;
1192             size_hints.showCmd = SW_SHOWNA;
1193
1194             /* Set the normal position hint to that location, with unchanged
1195              * width and height.
1196              */
1197             diff = size_hints.rcNormalPosition.left - rect.left;
1198             size_hints.rcNormalPosition.left = rect.left;
1199             size_hints.rcNormalPosition.right -= diff;
1200             diff = size_hints.rcNormalPosition.top - rect.top;
1201             size_hints.rcNormalPosition.top = rect.top;
1202             size_hints.rcNormalPosition.bottom -= diff;
1203             GDK_NOTE (MISC, g_print ("...setting: (%d,%d)--(%d,%d)\n",
1204                                      size_hints.rcNormalPosition.left,
1205                                      size_hints.rcNormalPosition.top,
1206                                      size_hints.rcNormalPosition.right,
1207                                      size_hints.rcNormalPosition.bottom));
1208             if (!SetWindowPlacement (private->drawable.xwindow, &size_hints))
1209               g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
1210             private->hint_x = rect.left;
1211             private->hint_y = rect.top;
1212           }
1213
1214       if (flags & GDK_HINT_MIN_SIZE)
1215         {
1216           rect.left = 0;
1217           rect.top = 0;
1218           rect.right = min_width;
1219           rect.bottom = min_height;
1220           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1221           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1222           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1223           private->hint_min_width = rect.right - rect.left;
1224           private->hint_min_height = rect.bottom - rect.top;
1225
1226           /* Also chek if he current size of the window is in bounds. */
1227           GetClientRect (private->drawable.xwindow, &rect);
1228           if (rect.right < min_width && rect.bottom < min_height)
1229             gdk_window_resize (window, min_width, min_height);
1230           else if (rect.right < min_width)
1231             gdk_window_resize (window, min_width, rect.bottom);
1232           else if (rect.bottom < min_height)
1233             gdk_window_resize (window, rect.right, min_height);
1234         }
1235       if (flags & GDK_HINT_MAX_SIZE)
1236         {
1237           rect.left = 0;
1238           rect.top = 0;
1239           rect.right = max_width;
1240           rect.bottom = max_height;
1241           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1242           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1243           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1244           private->hint_max_width = rect.right - rect.left;
1245           private->hint_max_height = rect.bottom - rect.top;
1246           /* Again, check if the window is too large currently. */
1247           GetClientRect (private->drawable.xwindow, &rect);
1248           if (rect.right > max_width && rect.bottom > max_height)
1249             gdk_window_resize (window, max_width, max_height);
1250           else if (rect.right > max_width)
1251             gdk_window_resize (window, max_width, rect.bottom);
1252           else if (rect.bottom > max_height)
1253             gdk_window_resize (window, rect.right, max_height);
1254         }
1255     }
1256 }
1257
1258 void 
1259 gdk_window_set_geometry_hints (GdkWindow      *window,
1260                                GdkGeometry    *geometry,
1261                                GdkWindowHints  geom_mask)
1262 {
1263   GdkWindowPrivate *private;
1264   WINDOWPLACEMENT size_hints;
1265   RECT rect;
1266   DWORD dwStyle;
1267   DWORD dwExStyle;
1268   int diff;
1269   
1270   g_return_if_fail (window != NULL);
1271   g_return_if_fail (GDK_IS_WINDOW (window));
1272   
1273   if (GDK_DRAWABLE_DESTROYED (window))
1274     return;
1275
1276   private = (GdkWindowPrivate*) window;
1277   
1278   size_hints.length = sizeof (size_hints);
1279
1280   private->hint_flags = geom_mask;
1281
1282   if (geom_mask & GDK_HINT_POS)
1283     ; /* XXX */
1284
1285   if (geom_mask & GDK_HINT_MIN_SIZE)
1286     {
1287       rect.left = 0;
1288       rect.top = 0;
1289       rect.right = geometry->min_width;
1290       rect.bottom = geometry->min_height;
1291       dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1292       dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1293       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1294       private->hint_min_width = rect.right - rect.left;
1295       private->hint_min_height = rect.bottom - rect.top;
1296
1297       /* Also check if he current size of the window is in bounds */
1298       GetClientRect (private->drawable.xwindow, &rect);
1299       if (rect.right < geometry->min_width
1300           && rect.bottom < geometry->min_height)
1301         gdk_window_resize (window, geometry->min_width, geometry->min_height);
1302       else if (rect.right < geometry->min_width)
1303         gdk_window_resize (window, geometry->min_width, rect.bottom);
1304       else if (rect.bottom < geometry->min_height)
1305         gdk_window_resize (window, rect.right, geometry->min_height);
1306     }
1307   
1308   if (geom_mask & GDK_HINT_MAX_SIZE)
1309     {
1310       rect.left = 0;
1311       rect.top = 0;
1312       rect.right = geometry->max_width;
1313       rect.bottom = geometry->max_height;
1314       dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1315       dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1316       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1317       private->hint_max_width = rect.right - rect.left;
1318       private->hint_max_height = rect.bottom - rect.top;
1319
1320       /* Again, check if the window is too large currently. */
1321       GetClientRect (private->drawable.xwindow, &rect);
1322       if (rect.right > geometry->max_width
1323           && rect.bottom > geometry->max_height)
1324         gdk_window_resize (window, geometry->max_width, geometry->max_height);
1325       else if (rect.right > geometry->max_width)
1326         gdk_window_resize (window, geometry->max_width, rect.bottom);
1327       else if (rect.bottom > geometry->max_height)
1328         gdk_window_resize (window, rect.right, geometry->max_height);
1329     }
1330   
1331   /* I don't know what to do when called with zero base_width and height. */
1332   if (geom_mask & GDK_HINT_BASE_SIZE
1333       && geometry->base_width > 0
1334       && geometry->base_height > 0)
1335     if (!GetWindowPlacement (private->drawable.xwindow, &size_hints))
1336       g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
1337     else
1338       {
1339         GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints:"
1340                                  " rcNormalPosition: (%d,%d)--(%d,%d)\n",
1341                                  size_hints.rcNormalPosition.left,
1342                                  size_hints.rcNormalPosition.top,
1343                                  size_hints.rcNormalPosition.right,
1344                                  size_hints.rcNormalPosition.bottom));
1345         size_hints.rcNormalPosition.right =
1346           size_hints.rcNormalPosition.left + geometry->base_width;
1347         size_hints.rcNormalPosition.bottom =
1348           size_hints.rcNormalPosition.top + geometry->base_height;
1349         GDK_NOTE (MISC, g_print ("...setting: rcNormal: (%d,%d)--(%d,%d)\n",
1350                                  size_hints.rcNormalPosition.left,
1351                                  size_hints.rcNormalPosition.top,
1352                                  size_hints.rcNormalPosition.right,
1353                                  size_hints.rcNormalPosition.bottom));
1354         if (!SetWindowPlacement (private->drawable.xwindow, &size_hints))
1355           g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
1356       }
1357   
1358   if (geom_mask & GDK_HINT_RESIZE_INC)
1359     {
1360       /* XXX */
1361     }
1362   
1363   if (geom_mask & GDK_HINT_ASPECT)
1364     {
1365       /* XXX */
1366     }
1367 }
1368
1369 void
1370 gdk_window_set_title (GdkWindow   *window,
1371                       const gchar *title)
1372 {
1373   g_return_if_fail (window != NULL);
1374   g_return_if_fail (GDK_IS_WINDOW (window));
1375   
1376   GDK_NOTE (MISC, g_print ("gdk_window_set_title: %#x %s\n",
1377                            GDK_DRAWABLE_XID (window), title));
1378   if (!GDK_DRAWABLE_DESTROYED (window))
1379     {
1380       if (!SetWindowText (GDK_DRAWABLE_XID (window), title))
1381         g_warning ("gdk_window_set_title: SetWindowText failed");
1382     }
1383 }
1384
1385 void          
1386 gdk_window_set_role (GdkWindow   *window,
1387                      const gchar *role)
1388 {
1389   g_return_if_fail (window != NULL);
1390   g_return_if_fail (GDK_IS_WINDOW (window));
1391   
1392   GDK_NOTE (MISC, g_print ("gdk_window_set_role: %#x %s\n",
1393                            GDK_DRAWABLE_XID (window), (role ? role : "NULL")));
1394   /* XXX */
1395 }
1396
1397 void          
1398 gdk_window_set_transient_for (GdkWindow *window, 
1399                               GdkWindow *parent)
1400 {
1401   g_return_if_fail (window != NULL);
1402   g_return_if_fail (GDK_IS_WINDOW (window));
1403   
1404   GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %#x %#x\n",
1405                            GDK_DRAWABLE_XID (window),
1406                            GDK_DRAWABLE_XID (parent)));
1407   /* XXX */
1408 }
1409
1410 void
1411 gdk_window_set_background (GdkWindow *window,
1412                            GdkColor  *color)
1413 {
1414   GdkWindowPrivate *private;
1415   
1416   g_return_if_fail (window != NULL);
1417   g_return_if_fail (GDK_IS_WINDOW (window));
1418   
1419   private = (GdkWindowPrivate*) window;
1420   if (!GDK_DRAWABLE_DESTROYED (window))
1421     {
1422       GDK_NOTE (MISC, g_print ("gdk_window_set_background: %#x %s\n",
1423                                private->drawable.xwindow, 
1424                                gdk_color_to_string (color)));
1425
1426       if (private->bg_type == GDK_WIN32_BG_PIXMAP)
1427         {
1428           if (private->bg_pixmap != NULL)
1429             {
1430               gdk_pixmap_unref (private->bg_pixmap);
1431               private->bg_pixmap = NULL;
1432             }
1433           private->bg_type = GDK_WIN32_BG_NORMAL;
1434         }
1435       private->bg_type = GDK_WIN32_BG_PIXEL;
1436       private->bg_pixel = *color;
1437     }
1438 }
1439
1440 void
1441 gdk_window_set_back_pixmap (GdkWindow *window,
1442                             GdkPixmap *pixmap,
1443                             gint       parent_relative)
1444 {
1445   GdkWindowPrivate *private;
1446
1447   g_return_if_fail (window != NULL);
1448   g_return_if_fail (GDK_IS_WINDOW (window));
1449   
1450   private = (GdkWindowPrivate*) window;
1451
1452   if (!GDK_DRAWABLE_DESTROYED (window))
1453     {
1454       if (private->bg_type == GDK_WIN32_BG_PIXMAP)
1455         {
1456           if (private->bg_pixmap != NULL)
1457             {
1458               gdk_pixmap_unref (private->bg_pixmap);
1459               private->bg_pixmap = NULL;
1460             }
1461           private->bg_type = GDK_WIN32_BG_NORMAL;
1462         }
1463       if (parent_relative)
1464         {
1465           private->bg_type = GDK_WIN32_BG_PARENT_RELATIVE;
1466         }
1467       else if (!pixmap)
1468         {
1469           
1470         }
1471       else
1472         {
1473           /* We must cache the pixmap in the WindowPrivate and
1474            * paint it each time we get WM_ERASEBKGND
1475            */
1476           private->bg_type = GDK_WIN32_BG_PIXMAP;
1477           private->bg_pixmap = pixmap;
1478           gdk_pixmap_ref (pixmap);
1479         }
1480     }
1481 }
1482
1483 void
1484 gdk_window_set_cursor (GdkWindow *window,
1485                        GdkCursor *cursor)
1486 {
1487   GdkWindowPrivate *window_private;
1488   GdkCursorPrivate *cursor_private;
1489   HCURSOR xcursor;
1490   
1491   g_return_if_fail (window != NULL);
1492   g_return_if_fail (GDK_IS_WINDOW (window));
1493   
1494   window_private = (GdkWindowPrivate*) window;
1495   cursor_private = (GdkCursorPrivate*) cursor;
1496   
1497   if (!GDK_DRAWABLE_DESTROYED (window))
1498     {
1499       if (!cursor)
1500         xcursor = LoadCursor (NULL, IDC_ARROW);
1501       else
1502         xcursor = cursor_private->xcursor;
1503
1504       GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %#x %#x\n",
1505                                window_private->drawable.xwindow, xcursor));
1506       window_private->xcursor = xcursor;
1507     }
1508 }
1509
1510 void
1511 gdk_window_get_user_data (GdkWindow *window,
1512                           gpointer  *data)
1513 {
1514   g_return_if_fail (window != NULL);
1515   
1516   *data = window->user_data;
1517 }
1518
1519 void
1520 gdk_window_get_geometry (GdkWindow *window,
1521                          gint      *x,
1522                          gint      *y,
1523                          gint      *width,
1524                          gint      *height,
1525                          gint      *depth)
1526 {
1527   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1528   
1529   if (!window)
1530     window = (GdkWindow*) &gdk_root_parent;
1531   
1532   if (!GDK_DRAWABLE_DESTROYED (window))
1533     {
1534       RECT rect;
1535
1536       if (!GetClientRect (GDK_DRAWABLE_XID (window), &rect))
1537         g_warning ("gdk_window_get_geometry: GetClientRect failed");
1538
1539       if (x)
1540         *x = rect.left;
1541       if (y)
1542         *y = rect.top;
1543       if (width)
1544         *width = rect.right - rect.left;
1545       if (height)
1546         *height = rect.bottom - rect.top;
1547       if (depth)
1548         *depth = gdk_drawable_get_visual (window)->depth;
1549     }
1550 }
1551
1552 void
1553 gdk_window_get_position (GdkWindow *window,
1554                          gint      *x,
1555                          gint      *y)
1556 {
1557   GdkWindowPrivate *window_private;
1558   
1559   g_return_if_fail (window != NULL);
1560   g_return_if_fail (GDK_IS_WINDOW (window));
1561   
1562   window_private = (GdkWindowPrivate*) window;
1563   
1564   if (x)
1565     *x = window_private->x;
1566   if (y)
1567     *y = window_private->y;
1568 }
1569
1570 gint
1571 gdk_window_get_origin (GdkWindow *window,
1572                        gint      *x,
1573                        gint      *y)
1574 {
1575   gint return_val;
1576   gint tx = 0;
1577   gint ty = 0;
1578
1579   g_return_val_if_fail (window != NULL, 0);
1580
1581   if (!GDK_DRAWABLE_DESTROYED (window))
1582     {
1583       POINT pt;
1584
1585       pt.x = 0;
1586       pt.y = 0;
1587       ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
1588       tx = pt.x;
1589       ty = pt.y;
1590       return_val = 1;
1591     }
1592   else
1593     return_val = 0;
1594   
1595   if (x)
1596     *x = tx;
1597   if (y)
1598     *y = ty;
1599
1600   GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %#x: +%d+%d\n",
1601                            GDK_DRAWABLE_XID (window), tx, ty));
1602   return return_val;
1603 }
1604
1605 gboolean
1606 gdk_window_get_deskrelative_origin (GdkWindow *window,
1607                                     gint      *x,
1608                                     gint      *y)
1609 {
1610   return gdk_window_get_origin (window, x, y);
1611 }
1612
1613 void
1614 gdk_window_get_root_origin (GdkWindow *window,
1615                             gint      *x,
1616                             gint      *y)
1617 {
1618   GdkWindowPrivate *private;
1619   POINT pt;
1620
1621   g_return_if_fail (window != NULL);
1622   g_return_if_fail (GDK_IS_WINDOW (window));
1623
1624   private = (GdkWindowPrivate*) window;
1625   if (x)
1626     *x = 0;
1627   if (y)
1628     *y = 0;
1629   if (GDK_DRAWABLE_DESTROYED (window))
1630     return;
1631       
1632   while (private->parent && ((GdkWindowPrivate*) private->parent)->parent)
1633     private = (GdkWindowPrivate*) private->parent;
1634   if (private->drawable.destroyed)
1635     return;
1636
1637   pt.x = 0;
1638   pt.y = 0;
1639   ClientToScreen (private->drawable.xwindow, &pt);
1640   if (x)
1641     *x = pt.x;
1642   if (y)
1643     *y = pt.y;
1644
1645   GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %#x: (%#x) +%d+%d\n",
1646                            GDK_DRAWABLE_XID (window),
1647                            private->drawable.xwindow, pt.x, pt.y));
1648 }
1649
1650 GdkWindow*
1651 gdk_window_get_pointer (GdkWindow       *window,
1652                         gint            *x,
1653                         gint            *y,
1654                         GdkModifierType *mask)
1655 {
1656   GdkWindow *return_val;
1657   POINT pointc, point;
1658   HWND hwnd, hwndc;
1659
1660   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1661   
1662   if (!window)
1663     window = (GdkWindow*) &gdk_root_parent;
1664
1665   return_val = NULL;
1666   GetCursorPos (&pointc);
1667   point = pointc;
1668   ScreenToClient (GDK_DRAWABLE_XID (window), &point);
1669
1670   if (x)
1671     *x = point.x;
1672   if (y)
1673     *y = point.y;
1674
1675   hwnd = WindowFromPoint (point);
1676   point = pointc;
1677   ScreenToClient (hwnd, &point);
1678   
1679   do {
1680     hwndc = ChildWindowFromPoint (hwnd, point);
1681     ClientToScreen (hwnd, &point);
1682     ScreenToClient (hwndc, &point);
1683   } while (hwndc != hwnd && (hwnd = hwndc, 1)); /* Ouch! */
1684
1685   return_val = gdk_window_lookup (hwnd);
1686
1687   if (mask)
1688     {
1689       BYTE kbd[256];
1690
1691       GetKeyboardState (kbd);
1692       *mask = 0;
1693       if (kbd[VK_SHIFT] & 0x80)
1694         *mask |= GDK_SHIFT_MASK;
1695       if (kbd[VK_CAPITAL] & 0x80)
1696         *mask |= GDK_LOCK_MASK;
1697       if (kbd[VK_CONTROL] & 0x80)
1698         *mask |= GDK_CONTROL_MASK;
1699       if (kbd[VK_MENU] & 0x80)
1700         *mask |= GDK_MOD1_MASK;
1701       if (kbd[VK_LBUTTON] & 0x80)
1702         *mask |= GDK_BUTTON1_MASK;
1703       if (kbd[VK_MBUTTON] & 0x80)
1704         *mask |= GDK_BUTTON2_MASK;
1705       if (kbd[VK_RBUTTON] & 0x80)
1706         *mask |= GDK_BUTTON3_MASK;
1707     }
1708   
1709   return return_val;
1710 }
1711
1712 GdkWindow*
1713 gdk_window_at_pointer (gint *win_x,
1714                        gint *win_y)
1715 {
1716   GdkWindow *window;
1717   POINT point, pointc;
1718   HWND hwnd, hwndc;
1719   RECT rect;
1720
1721   GetCursorPos (&pointc);
1722   point = pointc;
1723   hwnd = WindowFromPoint (point);
1724
1725   if (hwnd == NULL)
1726     {
1727       window = (GdkWindow *) &gdk_root_parent;
1728       if (win_x)
1729         *win_x = pointc.x;
1730       if (win_y)
1731         *win_y = pointc.y;
1732       return window;
1733     }
1734       
1735   ScreenToClient (hwnd, &point);
1736
1737   do {
1738     hwndc = ChildWindowFromPoint (hwnd, point);
1739     ClientToScreen (hwnd, &point);
1740     ScreenToClient (hwndc, &point);
1741   } while (hwndc != hwnd && (hwnd = hwndc, 1));
1742
1743   window = gdk_window_lookup (hwnd);
1744
1745   if (window && (win_x || win_y))
1746     {
1747       GetClientRect (hwnd, &rect);
1748       if (win_x)
1749         *win_x = point.x - rect.left;
1750       if (win_y)
1751         *win_y = point.y - rect.top;
1752     }
1753
1754   GDK_NOTE (MISC, g_print ("gdk_window_at_pointer: +%d+%d %#x%s\n",
1755                            point.x, point.y, hwnd,
1756                            (window == NULL ? " NULL" : "")));
1757
1758   return window;
1759 }
1760
1761 GdkWindow*
1762 gdk_window_get_parent (GdkWindow *window)
1763 {
1764   g_return_val_if_fail (window != NULL, NULL);
1765   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1766
1767   return ((GdkWindowPrivate*) window)->parent;
1768 }
1769
1770 GdkWindow*
1771 gdk_window_get_toplevel (GdkWindow *window)
1772 {
1773   g_return_val_if_fail (window != NULL, NULL);
1774   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1775
1776   while (GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_CHILD)
1777     window = ((GdkWindowPrivate*) window)->parent;
1778
1779   return window;
1780 }
1781
1782 GList*
1783 gdk_window_get_children (GdkWindow *window)
1784 {
1785   GdkWindowPrivate *private;
1786   GList *children;
1787
1788   g_return_val_if_fail (window != NULL, NULL);
1789   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1790
1791   if (GDK_DRAWABLE_DESTROYED (window))
1792     return NULL;
1793
1794   /* XXX ??? */
1795   g_warning ("gdk_window_get_children not implemented");
1796   children = NULL;
1797
1798   return children;
1799 }
1800
1801 GdkEventMask  
1802 gdk_window_get_events (GdkWindow *window)
1803 {
1804   GdkWindowPrivate *private;
1805
1806   g_return_val_if_fail (window != NULL, 0);
1807   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1808
1809   private = (GdkWindowPrivate*) window;
1810   if (GDK_DRAWABLE_DESTROYED (window))
1811     return 0;
1812
1813   return private->event_mask;
1814 }
1815
1816 void          
1817 gdk_window_set_events (GdkWindow   *window,
1818                        GdkEventMask event_mask)
1819 {
1820   GdkWindowPrivate *private;
1821
1822   g_return_if_fail (window != NULL);
1823   g_return_if_fail (GDK_IS_WINDOW (window));
1824
1825   private = (GdkWindowPrivate*) window;
1826   if (GDK_DRAWABLE_DESTROYED (window))
1827     return;
1828
1829   private->event_mask = event_mask;
1830 }
1831
1832 void
1833 gdk_window_add_colormap_windows (GdkWindow *window)
1834 {
1835   g_warning ("gdk_window_add_colormap_windows not implemented");
1836 }
1837
1838 void
1839 gdk_window_shape_combine_mask (GdkWindow *window,
1840                                GdkBitmap *mask,
1841                                gint x, gint y)
1842 {
1843   g_return_if_fail (window != NULL);
1844   g_return_if_fail (GDK_IS_WINDOW (window));
1845
1846   if (!mask)
1847     {
1848       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x none\n",
1849                                GDK_DRAWABLE_XID (window)));
1850       SetWindowRgn (GDK_DRAWABLE_XID (window), NULL, TRUE);
1851     }
1852   else
1853     {
1854       GdkDrawablePrivate *pixmap_private;
1855       HRGN hrgn;
1856       DWORD dwStyle;
1857       DWORD dwExStyle;
1858       RECT rect;
1859
1860       /* Convert mask bitmap to region */
1861       pixmap_private = (GdkDrawablePrivate*) mask;
1862       hrgn = BitmapToRegion (pixmap_private->xwindow);
1863
1864       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x %#x\n",
1865                                GDK_DRAWABLE_XID (window),
1866                                pixmap_private->xwindow));
1867
1868       /* SetWindowRgn wants window (not client) coordinates */ 
1869       dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
1870       dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
1871       GetClientRect (GDK_DRAWABLE_XID (window), &rect);
1872       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1873       OffsetRgn (hrgn, -rect.left, -rect.top);
1874
1875       OffsetRgn (hrgn, x, y);
1876
1877       /* If this is a top-level window, add the title bar to the region */
1878       if (GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_TOPLEVEL)
1879         {
1880           CombineRgn (hrgn, hrgn,
1881                       CreateRectRgn (0, 0, rect.right - rect.left, -rect.top),
1882                       RGN_OR);
1883         }
1884       
1885       SetWindowRgn (GDK_DRAWABLE_XID (window), hrgn, TRUE);
1886     }
1887 }
1888
1889 void          
1890 gdk_window_add_filter (GdkWindow     *window,
1891                        GdkFilterFunc  function,
1892                        gpointer       data)
1893 {
1894   GdkWindowPrivate *private;
1895   GList *tmp_list;
1896   GdkEventFilter *filter;
1897   
1898   g_return_if_fail (window != NULL);
1899   g_return_if_fail (GDK_IS_WINDOW (window));
1900
1901   private = (GdkWindowPrivate*) window;
1902   if (private && GDK_DRAWABLE_DESTROYED (window))
1903     return;
1904   
1905   if (private)
1906     tmp_list = private->filters;
1907   else
1908     tmp_list = gdk_default_filters;
1909   
1910   while (tmp_list)
1911     {
1912       filter = (GdkEventFilter *)tmp_list->data;
1913       if ((filter->function == function) && (filter->data == data))
1914         return;
1915       tmp_list = tmp_list->next;
1916     }
1917   
1918   filter = g_new (GdkEventFilter, 1);
1919   filter->function = function;
1920   filter->data = data;
1921   
1922   if (private)
1923     private->filters = g_list_append (private->filters, filter);
1924   else
1925     gdk_default_filters = g_list_append (gdk_default_filters, filter);
1926 }
1927
1928 void
1929 gdk_window_remove_filter (GdkWindow     *window,
1930                           GdkFilterFunc  function,
1931                           gpointer       data)
1932 {
1933   GdkWindowPrivate *private;
1934   GList *tmp_list, *node;
1935   GdkEventFilter *filter;
1936   
1937   g_return_if_fail (window != NULL);
1938   g_return_if_fail (GDK_IS_WINDOW (window));
1939
1940   private = (GdkWindowPrivate*) window;
1941   
1942   if (private)
1943     tmp_list = private->filters;
1944   else
1945     tmp_list = gdk_default_filters;
1946   
1947   while (tmp_list)
1948     {
1949       filter = (GdkEventFilter *)tmp_list->data;
1950       node = tmp_list;
1951       tmp_list = tmp_list->next;
1952       
1953       if ((filter->function == function) && (filter->data == data))
1954         {
1955           if (private)
1956             private->filters = g_list_remove_link (private->filters, node);
1957           else
1958             gdk_default_filters = g_list_remove_link (gdk_default_filters, node);
1959           g_list_free_1 (node);
1960           g_free (filter);
1961           
1962           return;
1963         }
1964     }
1965 }
1966
1967 void
1968 gdk_window_set_override_redirect (GdkWindow *window,
1969                                   gboolean   override_redirect)
1970 {
1971   g_return_if_fail (window != NULL);
1972   g_return_if_fail (GDK_IS_WINDOW (window));
1973
1974   g_warning ("gdk_window_set_override_redirect not implemented");
1975 }
1976
1977 void          
1978 gdk_window_set_icon (GdkWindow *window, 
1979                      GdkWindow *icon_window,
1980                      GdkPixmap *pixmap,
1981                      GdkBitmap *mask)
1982 {
1983   g_return_if_fail (window != NULL);
1984   g_return_if_fail (GDK_IS_WINDOW (window));
1985
1986   if (GDK_DRAWABLE_DESTROYED (window))
1987     return;
1988   
1989   g_warning ("gdk_window_set_icon not implemented");
1990 }
1991
1992 void
1993 gdk_window_set_icon_name (GdkWindow *window, 
1994                           gchar     *name)
1995 {
1996   g_return_if_fail (window != NULL);
1997   g_return_if_fail (GDK_IS_WINDOW (window));
1998
1999   if (GDK_DRAWABLE_DESTROYED (window))
2000     return;
2001   
2002   if (!SetWindowText (GDK_DRAWABLE_XID (window), name))
2003     g_warning ("gdk_window_set_icon_name: SetWindowText failed");
2004 }
2005
2006 void          
2007 gdk_window_set_group (GdkWindow *window, 
2008                       GdkWindow *leader)
2009 {
2010   g_return_if_fail (window != NULL);
2011   g_return_if_fail (GDK_IS_WINDOW (window));
2012   g_return_if_fail (leader != NULL);
2013   g_return_if_fail (GDK_IS_WINDOW (leader));
2014
2015   if (GDK_DRAWABLE_DESTROYED (window) || GDK_DRAWABLE_DESTROYED (leader))
2016     return;
2017   
2018   g_warning ("gdk_window_set_group not implemented");
2019 }
2020
2021 void
2022 gdk_window_set_decorations (GdkWindow      *window,
2023                             GdkWMDecoration decorations)
2024 {
2025   LONG style, exstyle;
2026
2027   g_return_if_fail (window != NULL);
2028   g_return_if_fail (GDK_IS_WINDOW (window));
2029   
2030   style = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
2031   exstyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
2032
2033   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2034             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE);
2035
2036   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2037
2038   if (decorations & GDK_DECOR_ALL)
2039     style |= (WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2040   if (decorations & GDK_DECOR_BORDER)
2041     style |= (WS_BORDER);
2042   if (decorations & GDK_DECOR_RESIZEH)
2043     style |= (WS_THICKFRAME);
2044   if (decorations & GDK_DECOR_TITLE)
2045     style |= (WS_CAPTION);
2046   if (decorations & GDK_DECOR_MENU)
2047     style |= (WS_SYSMENU);
2048   if (decorations & GDK_DECOR_MINIMIZE)
2049     style |= (WS_MINIMIZEBOX);
2050   if (decorations & GDK_DECOR_MAXIMIZE)
2051     style |= (WS_MAXIMIZEBOX);
2052   
2053   SetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE, style);
2054 }
2055
2056 void
2057 gdk_window_set_functions (GdkWindow    *window,
2058                           GdkWMFunction functions)
2059 {
2060   LONG style, exstyle;
2061
2062   g_return_if_fail (window != NULL);
2063   g_return_if_fail (GDK_IS_WINDOW (window));
2064   
2065   style = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
2066   exstyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
2067
2068   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2069             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE|WS_CAPTION|WS_BORDER
2070             |WS_SYSMENU);
2071
2072   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2073
2074   if (functions & GDK_FUNC_ALL)
2075     style |= (WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2076   if (functions & GDK_FUNC_RESIZE)
2077     style |= (WS_THICKFRAME);
2078   if (functions & GDK_FUNC_MOVE)
2079     style |= (WS_THICKFRAME);
2080   if (functions & GDK_FUNC_MINIMIZE)
2081     style |= (WS_MINIMIZEBOX);
2082   if (functions & GDK_FUNC_MAXIMIZE)
2083     style |= (WS_MAXIMIZEBOX);
2084   
2085   SetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE, style);
2086 }
2087
2088 GList *
2089 gdk_window_get_toplevels (void)
2090 {
2091   GList *new_list = NULL;
2092   GList *tmp_list;
2093
2094   tmp_list = gdk_root_parent.children;
2095   while (tmp_list)
2096     {
2097       new_list = g_list_prepend (new_list, tmp_list->data);
2098       tmp_list = tmp_list->next;
2099     }
2100
2101   return new_list;
2102 }
2103
2104 /* 
2105  * propagate the shapes from all child windows of a GDK window to the parent 
2106  * window. Shamelessly ripped from Enlightenment's code
2107  * 
2108  * - Raster
2109  */
2110
2111 static void
2112 QueryTree (HWND hwnd,
2113            HWND **children,
2114            gint *nchildren)
2115 {
2116   guint i, n;
2117   HWND child;
2118
2119   n = 0;
2120   do {
2121     if (n == 0)
2122       child = GetWindow (hwnd, GW_CHILD);
2123     else
2124       child = GetWindow (child, GW_HWNDNEXT);
2125     if (child != NULL)
2126       n++;
2127   } while (child != NULL);
2128
2129   if (n > 0)
2130     {
2131       *children = g_new (HWND, n);
2132       for (i = 0; i < n; i++)
2133         {
2134           if (i == 0)
2135             child = GetWindow (hwnd, GW_CHILD);
2136           else
2137             child = GetWindow (child, GW_HWNDNEXT);
2138           *children[i] = child;
2139         }
2140     }
2141 }
2142
2143 static void
2144 gdk_propagate_shapes (HANDLE   win,
2145                       gboolean merge)
2146 {
2147    RECT emptyRect;
2148    HRGN region, childRegion;
2149    RECT rect;
2150    HWND *list = NULL;
2151    gint i, num;
2152
2153    SetRectEmpty (&emptyRect);
2154    region = CreateRectRgnIndirect (&emptyRect);
2155    if (merge)
2156      GetWindowRgn (win, region);
2157    
2158    QueryTree (win, &list, &num);
2159    if (list != NULL)
2160      {
2161        WINDOWPLACEMENT placement;
2162
2163        placement.length = sizeof (WINDOWPLACEMENT);
2164        /* go through all child windows and combine regions */
2165        for (i = 0; i < num; i++)
2166          {
2167            GetWindowPlacement (list[i], &placement);
2168            if (placement.showCmd = SW_SHOWNORMAL)
2169              {
2170                childRegion = CreateRectRgnIndirect (&emptyRect);
2171                GetWindowRgn (list[i], childRegion);
2172                CombineRgn (region, region, childRegion, RGN_OR);
2173                DeleteObject (childRegion);
2174              }
2175           }
2176        SetWindowRgn (win, region, TRUE);
2177      }
2178    else
2179      DeleteObject (region);
2180 }
2181
2182 void
2183 gdk_window_set_child_shapes (GdkWindow *window)
2184 {
2185   g_return_if_fail (window != NULL);
2186   g_return_if_fail (GDK_IS_WINDOW (window));
2187    
2188   if (GDK_DRAWABLE_DESTROYED (window))
2189     return;
2190
2191   gdk_propagate_shapes (GDK_DRAWABLE_XID (window), FALSE);
2192 }
2193
2194 void
2195 gdk_window_merge_child_shapes (GdkWindow *window)
2196 {
2197   g_return_if_fail (window != NULL);
2198   g_return_if_fail (GDK_IS_WINDOW (window));
2199   
2200   if (GDK_DRAWABLE_DESTROYED (window))
2201     return;
2202
2203   gdk_propagate_shapes (GDK_DRAWABLE_XID (window), TRUE);
2204 }
2205
2206 /*************************************************************
2207  * gdk_window_is_visible:
2208  *     Check if the given window is mapped.
2209  *   arguments:
2210  *     window: 
2211  *   results:
2212  *     is the window mapped
2213  *************************************************************/
2214
2215 gboolean 
2216 gdk_window_is_visible (GdkWindow *window)
2217 {
2218   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2219
2220   g_return_val_if_fail (window != NULL, FALSE);
2221   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2222
2223   return private->mapped;
2224 }
2225
2226 /*************************************************************
2227  * gdk_window_is_viewable:
2228  *     Check if the window and all ancestors of the window
2229  *     are mapped. (This is not necessarily "viewable" in
2230  *     the X sense, since we only check as far as we have
2231  *     GDK window parents, not to the root window)
2232  *   arguments:
2233  *     window:
2234  *   results:
2235  *     is the window viewable
2236  *************************************************************/
2237
2238 gboolean 
2239 gdk_window_is_viewable (GdkWindow *window)
2240 {
2241   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2242
2243   g_return_val_if_fail (window != NULL, FALSE);
2244   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2245
2246   while (private && 
2247          (private != &gdk_root_parent) &&
2248          (private->drawable.window_type != GDK_WINDOW_FOREIGN))
2249     {
2250       if (!private->mapped)
2251         return FALSE;
2252
2253       private = (GdkWindowPrivate *)private->parent;
2254     }
2255
2256   return TRUE;
2257 }
2258
2259 /* Support for windows that can be guffaw-scrolled
2260  * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
2261  */
2262
2263 static gboolean
2264 gdk_window_gravity_works (void)
2265 {
2266   enum { UNKNOWN, NO, YES };
2267   static gint gravity_works = UNKNOWN;
2268   
2269   if (gravity_works == UNKNOWN)
2270     {
2271       GdkWindowAttr attr;
2272       GdkWindow *parent;
2273       GdkWindow *child;
2274       gint y;
2275       
2276       attr.window_type = GDK_WINDOW_TEMP;
2277       attr.wclass = GDK_INPUT_OUTPUT;
2278       attr.x = 0;
2279       attr.y = 0;
2280       attr.width = 100;
2281       attr.height = 100;
2282       attr.event_mask = 0;
2283       
2284       parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
2285       
2286       attr.window_type = GDK_WINDOW_CHILD;
2287       child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
2288       
2289       gdk_window_set_static_win_gravity (child, TRUE);
2290       
2291       gdk_window_resize (parent, 100, 110);
2292       gdk_window_move (parent, 0, -10);
2293       gdk_window_move_resize (parent, 0, 0, 100, 100);
2294       
2295       gdk_window_resize (parent, 100, 110);
2296       gdk_window_move (parent, 0, -10);
2297       gdk_window_move_resize (parent, 0, 0, 100, 100);
2298       
2299       gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
2300       
2301       gdk_window_destroy (parent);
2302       gdk_window_destroy (child);
2303       
2304       gravity_works = ((y == -20) ? YES : NO);
2305     }
2306   
2307   return (gravity_works == YES);
2308 }
2309
2310 static void
2311 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
2312 {
2313   g_return_if_fail (window != NULL);
2314
2315   GDK_NOTE (MISC, g_print ("gdk_window_set_static_bit_gravity: Not implemented\n"));
2316 }
2317
2318 static void
2319 gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
2320 {
2321   g_return_if_fail (window != NULL);
2322
2323   GDK_NOTE (MISC,
2324             g_print ("gdk_window_set_static_win_gravity: Not implemented\n"));
2325 }
2326
2327 /*************************************************************
2328  * gdk_window_set_static_gravities:
2329  *     Set the bit gravity of the given window to static,
2330  *     and flag it so all children get static subwindow
2331  *     gravity.
2332  *   arguments:
2333  *     window: window for which to set static gravity
2334  *     use_static: Whether to turn static gravity on or off.
2335  *   results:
2336  *     Does the XServer support static gravity?
2337  *************************************************************/
2338
2339 gboolean 
2340 gdk_window_set_static_gravities (GdkWindow *window,
2341                                  gboolean   use_static)
2342 {
2343   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2344   GList *tmp_list;
2345   
2346   g_return_val_if_fail (window != NULL, FALSE);
2347   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2348
2349   if (!use_static == !private->guffaw_gravity)
2350     return TRUE;
2351   
2352   if (use_static && !gdk_window_gravity_works ())
2353     return FALSE;
2354   
2355   private->guffaw_gravity = use_static;
2356   
2357   if (!GDK_DRAWABLE_DESTROYED (window))
2358     {
2359       gdk_window_set_static_bit_gravity (window, use_static);
2360       
2361       tmp_list = private->children;
2362       while (tmp_list)
2363         {
2364           gdk_window_set_static_win_gravity (window, use_static);
2365           
2366           tmp_list = tmp_list->next;
2367         }
2368     }
2369   
2370   return TRUE;
2371 }