]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow-win32.c
Must mark also gdk_error_warnings and gdk_error_code as GDKVAR, as they
[~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-win32.h"
37 #include "gdkinputprivate.h"
38 #include "gdkwin32.h"
39
40 static gboolean gdk_window_gravity_works (void);
41 static void     gdk_window_set_static_win_gravity (GdkWindow *window, 
42                                                    gboolean   on);
43
44 /* The Win API function AdjustWindowRect may return negative values
45  * resulting in obscured title bars. This helper function is coreccting it.
46  */
47 BOOL
48 SafeAdjustWindowRectEx (RECT* lpRect, 
49                         DWORD dwStyle, 
50                         BOOL bMenu, 
51                         DWORD dwExStyle)
52 {
53   if (!AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle))
54     return FALSE;
55   if (lpRect->left < 0)
56     {
57       lpRect->right -= lpRect->left;
58       lpRect->left = 0;
59     }
60   if (lpRect->top < 0)
61     {
62       lpRect->bottom -= lpRect->top;
63       lpRect->top = 0;
64     }
65   return TRUE;
66 }
67
68 static void
69 gdk_win32_window_destroy (GdkDrawable *drawable)
70 {
71   if (!GDK_DRAWABLE_DESTROYED (drawable))
72     {
73       if (GDK_DRAWABLE_TYPE (drawable) == GDK_WINDOW_FOREIGN)
74         gdk_xid_table_remove (GDK_DRAWABLE_XID (drawable));
75       else
76         g_warning ("losing last reference to undestroyed window\n");
77     }
78
79   if (GDK_WINDOW_WIN32DATA (drawable)->bg_type == GDK_WIN32_BG_PIXMAP
80       && GDK_WINDOW_WIN32DATA (drawable)->bg_pixmap != NULL)
81     gdk_drawable_unref (GDK_WINDOW_WIN32DATA (drawable)->bg_pixmap);
82
83   g_free (GDK_DRAWABLE_WIN32DATA (drawable));
84 }
85
86 static GdkWindow *
87 gdk_win32_window_alloc (void)
88 {
89   GdkWindow *window;
90   GdkWindowPrivate *private;
91   
92   static GdkDrawableClass klass;
93   static gboolean initialized = FALSE;
94
95   if (!initialized)
96     {
97       initialized = TRUE;
98       
99       klass = _gdk_win32_drawable_class;
100       klass.destroy = gdk_win32_window_destroy;
101     }
102
103   window = _gdk_window_alloc ();
104   private = (GdkWindowPrivate *) window;
105
106   private->drawable.klass = &klass;
107   private->drawable.klass_data = g_new (GdkWindowWin32Data, 1);
108
109   GDK_WINDOW_WIN32DATA (window)->event_mask = 0;
110   GDK_WINDOW_WIN32DATA (window)->bg_type = GDK_WIN32_BG_NORMAL;
111   GDK_WINDOW_WIN32DATA (window)->xcursor = NULL;
112   GDK_WINDOW_WIN32DATA (window)->hint_flags = 0;
113   GDK_WINDOW_WIN32DATA (window)->extension_events = 0;
114   GDK_WINDOW_WIN32DATA (window)->extension_events_selected = FALSE;
115   
116   GDK_WINDOW_WIN32DATA (window)->input_locale = GetKeyboardLayout (0);
117   TranslateCharsetInfo ((DWORD FAR *) GetACP (),
118                         &GDK_WINDOW_WIN32DATA (window)->charset_info,
119                         TCI_SRCCODEPAGE);
120
121   return window;
122 }
123
124 void
125 gdk_window_init (void)
126 {
127   GdkWindowPrivate *private;
128   RECT r;
129   guint width;
130   guint height;
131
132   SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
133   width  = r.right - r.left;
134   height = r.bottom - r.top;
135
136   gdk_parent_root = gdk_win32_window_alloc ();
137   private = (GdkWindowPrivate *) gdk_parent_root;
138   
139   GDK_DRAWABLE_WIN32DATA (gdk_parent_root)->xid = gdk_root_window;
140   private->drawable.window_type = GDK_WINDOW_ROOT;
141   private->drawable.width = width;
142   private->drawable.height = height;
143
144   gdk_xid_table_insert (&gdk_root_window, gdk_parent_root);
145 }
146
147 /* RegisterGdkClass
148  *   is a wrapper function for RegisterWindowClassEx.
149  *   It creates at least one unique class for every 
150  *   GdkWindowType. If support for single window-specific icons
151  *   is ever needed (e.g Dialog specific), every such window should
152  *   get its own class
153  */
154 ATOM
155 RegisterGdkClass (GdkDrawableType wtype)
156 {
157   static ATOM klassTOPLEVEL = 0;
158   static ATOM klassDIALOG   = 0;
159   static ATOM klassCHILD    = 0;
160   static ATOM klassTEMP     = 0;
161   static HICON hAppIcon = NULL;
162   static WNDCLASSEX wcl; 
163   ATOM klass = 0;
164
165   wcl.cbSize = sizeof(WNDCLASSEX);     
166   wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
167                   * on WM_SIZE and WM_MOVE. Flicker, Performance!
168                   */
169   wcl.lpfnWndProc = gdk_WindowProc;
170   wcl.cbClsExtra = 0;
171   wcl.cbWndExtra = 0;
172   wcl.hInstance = gdk_ProgInstance;
173   wcl.hIcon = 0;
174   /* initialize once! */
175   if (0 == hAppIcon)
176     {
177       gchar sLoc [_MAX_PATH+1];
178       HINSTANCE hInst = GetModuleHandle(NULL);
179
180       if (0 != GetModuleFileName(hInst, sLoc, _MAX_PATH))
181         {
182           hAppIcon = ExtractIcon(hInst, sLoc, 0);
183           if (0 == hAppIcon)
184             {
185               char *gdklibname = g_strdup_printf ("gdk-%s.dll", GDK_VERSION);
186
187               hAppIcon = ExtractIcon(hInst, gdklibname, 0);
188               g_free (gdklibname);
189             }
190           
191           if (0 == hAppIcon) 
192             hAppIcon = LoadIcon (NULL, IDI_APPLICATION);
193         }
194     }
195
196   wcl.lpszMenuName = NULL;
197   wcl.hIconSm = 0;
198
199   /* initialize once per class */
200 #define ONCE_PER_CLASS() \
201   wcl.hIcon = CopyIcon (hAppIcon); \
202   wcl.hIconSm = CopyIcon (hAppIcon); \
203   wcl.hbrBackground = CreateSolidBrush( RGB(0,0,0)); \
204   wcl.hCursor = LoadCursor (NULL, IDC_ARROW); 
205   
206   switch (wtype)
207   {
208     case GDK_WINDOW_TOPLEVEL:
209       if (0 == klassTOPLEVEL)
210       {
211         wcl.lpszClassName = "gdkWindowToplevel";
212
213         ONCE_PER_CLASS();
214         klassTOPLEVEL = RegisterClassEx(&wcl);
215       }
216       klass = klassTOPLEVEL;
217       break;
218     case GDK_WINDOW_CHILD:
219       if (0 == klassCHILD)
220       {
221         wcl.lpszClassName = "gdkWindowChild";
222
223         wcl.style |= CS_PARENTDC; /* MSDN: ... enhances system performance. */
224         ONCE_PER_CLASS();
225         klassCHILD = RegisterClassEx(&wcl);
226       }
227       klass = klassCHILD;
228       break;
229     case GDK_WINDOW_DIALOG:
230       if (0 == klassDIALOG)
231       {
232         wcl.lpszClassName = "gdkWindowDialog";
233         wcl.style |= CS_SAVEBITS;
234         ONCE_PER_CLASS();
235         klassDIALOG = RegisterClassEx(&wcl);
236       }
237       klass = klassDIALOG;
238       break;
239     case GDK_WINDOW_TEMP:
240       if (0 == klassTEMP)
241       {
242         wcl.lpszClassName = "gdkWindowTemp";
243         wcl.style |= CS_SAVEBITS;
244         ONCE_PER_CLASS();
245         klassTEMP = RegisterClassEx(&wcl);
246       }
247       klass = klassTEMP;
248       break;
249     case GDK_WINDOW_ROOT:
250       g_error ("cannot make windows of type GDK_WINDOW_ROOT");
251       break;
252     case GDK_DRAWABLE_PIXMAP:
253       g_error ("cannot make windows of type GDK_DRAWABLE_PIXMAP (use gdk_pixmap_new)");
254       break;
255   }
256
257   return klass;
258 }
259
260 GdkWindow*
261 gdk_window_new (GdkWindow     *parent,
262                 GdkWindowAttr *attributes,
263                 gint           attributes_mask)
264 {
265   GdkWindow *window;
266   GdkWindowPrivate *private;
267   GdkWindowPrivate *parent_private;
268   GdkVisual *visual;
269   HANDLE xparent;
270   Visual *xvisual;
271   ATOM klass = 0;
272   DWORD dwStyle, dwExStyle;
273   RECT rect;
274   int width, height;
275   int x, y;
276   char *title;
277   gint titlelen;
278   wchar_t *wctitle;
279   gint wlen;
280   char *mbtitle;
281
282   g_return_val_if_fail (attributes != NULL, NULL);
283
284   if (!parent)
285     parent = gdk_parent_root;
286
287   parent_private = (GdkWindowPrivate*) parent;
288   if (GDK_DRAWABLE_DESTROYED (parent))
289     return NULL;
290
291   xparent = GDK_DRAWABLE_XID (parent);
292
293   window = gdk_win32_window_alloc ();
294   private = (GdkWindowPrivate *)window;
295
296   private->parent = parent;
297
298   private->x = (attributes_mask & GDK_WA_X) ? attributes->x : 0;
299   private->y = (attributes_mask & GDK_WA_Y) ? attributes->y : 0;
300
301   private->drawable.width = (attributes->width > 1) ? (attributes->width) : (1);
302   private->drawable.height = (attributes->height > 1) ? (attributes->height) : (1);
303   private->drawable.window_type = attributes->window_type;
304   GDK_WINDOW_WIN32DATA (window)->extension_events = 0;
305   GDK_WINDOW_WIN32DATA (window)->extension_events_selected = FALSE;
306
307   if (attributes_mask & GDK_WA_VISUAL)
308     visual = attributes->visual;
309   else
310     visual = gdk_visual_get_system ();
311   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
312
313   if (attributes_mask & GDK_WA_TITLE)
314     title = attributes->title;
315   else
316     title = g_get_prgname ();
317   if (!title)
318     title = "GDK client window";
319
320   GDK_WINDOW_WIN32DATA (window)->event_mask = GDK_STRUCTURE_MASK | attributes->event_mask;
321       
322   if (parent_private && parent_private->guffaw_gravity)
323     {
324       /* XXX ??? */
325     }
326
327   if (attributes->wclass == GDK_INPUT_OUTPUT)
328     {
329       dwExStyle = 0;
330       if (attributes_mask & GDK_WA_COLORMAP)
331         private->drawable.colormap = attributes->colormap;
332       else
333         private->drawable.colormap = gdk_colormap_get_system ();
334     }
335   else
336     {
337       dwExStyle = WS_EX_TRANSPARENT;
338       private->drawable.colormap = NULL;
339       GDK_WINDOW_WIN32DATA (window)->bg_type = GDK_WIN32_BG_TRANSPARENT;
340       GDK_WINDOW_WIN32DATA (window)->bg_pixmap = NULL;
341     }
342
343   if (attributes_mask & GDK_WA_X)
344     x = attributes->x;
345   else
346     x = CW_USEDEFAULT;
347
348   if (attributes_mask & GDK_WA_Y)
349     y = attributes->y;
350   else if (attributes_mask & GDK_WA_X)
351     y = 100;                    /* ??? We must put it somewhere... */
352   else
353     y = 500;                    /* x is CW_USEDEFAULT, y doesn't matter then */
354
355   if (parent_private)
356     parent_private->children = g_list_prepend (parent_private->children, window);
357
358   switch (private->drawable.window_type)
359     {
360     case GDK_WINDOW_TOPLEVEL:
361       dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
362       xparent = gdk_root_window;
363       break;
364     case GDK_WINDOW_CHILD:
365       dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
366       break;
367     case GDK_WINDOW_DIALOG:
368       dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
369       dwExStyle |= WS_EX_TOPMOST; /* //HB: want this? */
370       xparent = gdk_root_window;
371       break;
372     case GDK_WINDOW_TEMP:
373       dwStyle = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
374       dwExStyle |= WS_EX_TOOLWINDOW;
375       break;
376     case GDK_WINDOW_ROOT:
377       g_error ("cannot make windows of type GDK_WINDOW_ROOT");
378       break;
379     case GDK_DRAWABLE_PIXMAP:
380       g_error ("cannot make windows of type GDK_DRAWABLE_PIXMAP (use gdk_pixmap_new)");
381       break;
382     }
383
384   klass = RegisterGdkClass (private->drawable.window_type);
385   if (!klass)
386     g_error ("RegisterClassEx failed");
387
388   if (private->drawable.window_type != GDK_WINDOW_CHILD)
389     {
390       if (x == CW_USEDEFAULT)
391         {
392           rect.left = 100;
393           rect.top = 100;
394         }
395       else
396         {
397           rect.left = x;
398           rect.top = y;
399         }
400
401       rect.right = rect.left + private->drawable.width;
402       rect.bottom = rect.top + private->drawable.height;
403
404       if (!SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
405         g_warning ("gdk_window_new: AdjustWindowRectEx failed");
406
407       if (x != CW_USEDEFAULT)
408         {
409           x = rect.left;
410           y = rect.top;
411         }
412       width = rect.right - rect.left;
413       height = rect.bottom - rect.top;
414     }
415   else
416     {
417       width = private->drawable.width;
418       height = private->drawable.height;
419     }
420
421   titlelen = strlen (title);
422   wctitle = g_new (wchar_t, titlelen + 1);
423   mbtitle = g_new (char, 3*titlelen + 1);
424   wlen = gdk_nmbstowchar_ts (wctitle, title, titlelen, titlelen);
425   wctitle[wlen] = 0;
426   WideCharToMultiByte (GetACP (), 0, wctitle, -1,
427                        mbtitle, 3*titlelen, NULL, NULL);
428   
429   GDK_DRAWABLE_WIN32DATA (window)->xid =
430     CreateWindowEx (dwExStyle,
431                     MAKEINTRESOURCE(klass),
432                     mbtitle,
433                     dwStyle,
434                     x, y, 
435                     width, height,
436                     xparent,
437                     NULL,
438                     gdk_ProgInstance,
439                     NULL);
440
441   GDK_NOTE (MISC,
442             g_print ("gdk_window_create: %s %s %dx%d@+%d+%d %#x = %#x\n"
443                      "...locale %#x codepage %d\n",
444                      (private->drawable.window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
445                       (private->drawable.window_type == GDK_WINDOW_CHILD ? "CHILD" :
446                        (private->drawable.window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
447                         (private->drawable.window_type == GDK_WINDOW_TEMP ? "TEMP" :
448                          "???")))),
449                      mbtitle,
450                      width, height, (x == CW_USEDEFAULT ? -9999 : x), y, 
451                      xparent,
452                      GDK_DRAWABLE_XID (window),
453                      GDK_WINDOW_WIN32DATA (window)->input_locale,
454                      GDK_WINDOW_WIN32DATA (window)->charset_info.ciACP));
455
456   g_free (mbtitle);
457   g_free (wctitle);
458
459   if (GDK_DRAWABLE_XID (window) == NULL)
460     {
461       g_warning ("gdk_window_create: CreateWindowEx failed");
462       g_free (GDK_DRAWABLE_WIN32DATA (window));
463       g_free (private);
464       return NULL;
465     }
466
467   gdk_drawable_ref (window);
468   gdk_xid_table_insert (&GDK_DRAWABLE_XID (window), window);
469
470   if (private->drawable.colormap)
471     gdk_colormap_ref (private->drawable.colormap);
472
473   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
474                                   (attributes->cursor) :
475                                   NULL));
476
477   return window;
478 }
479
480 GdkWindow *
481 gdk_window_foreign_new (guint32 anid)
482 {
483   GdkWindow *window;
484   GdkWindowPrivate *private;
485   GdkWindowPrivate *parent_private;
486   HANDLE parent;
487   RECT rect;
488   POINT point;
489
490   window = gdk_win32_window_alloc ();
491   private = (GdkWindowPrivate *)window;
492
493   parent = GetParent ((HWND) anid);
494   private->parent = gdk_xid_table_lookup (parent);
495
496   parent_private = (GdkWindowPrivate *)private->parent;
497   
498   if (parent_private)
499     parent_private->children = g_list_prepend (parent_private->children, window);
500
501   GDK_DRAWABLE_WIN32DATA (window)->xid = (HWND) anid;
502   GetClientRect ((HWND) anid, &rect);
503   point.x = rect.left;
504   point.y = rect.right;
505   ClientToScreen ((HWND) anid, &point);
506   if (parent != GetDesktopWindow ())
507     ScreenToClient (parent, &point);
508   private->x = point.x;
509   private->y = point.y;
510   private->drawable.width = rect.right - rect.left;
511   private->drawable.height = rect.bottom - rect.top;
512   private->drawable.window_type = GDK_WINDOW_FOREIGN;
513   private->drawable.destroyed = FALSE;
514   private->mapped = IsWindowVisible (GDK_DRAWABLE_XID (window));
515
516   private->drawable.colormap = NULL;
517
518   gdk_drawable_ref (window);
519   gdk_xid_table_insert (&GDK_DRAWABLE_XID (window), window);
520
521   return window;
522 }
523
524 /* Call this function when you want a window and all its children to
525  * disappear.  When xdestroy is true, a request to destroy the window
526  * is sent out.  When it is false, it is assumed that the window has
527  * been or will be destroyed by destroying some ancestor of this
528  * window.
529  */
530 static void
531 gdk_window_internal_destroy (GdkWindow *window,
532                              gboolean   xdestroy,
533                              gboolean   our_destroy)
534 {
535   GdkWindowPrivate *private;
536   GdkWindowPrivate *temp_private;
537   GdkWindow *temp_window;
538   GList *children;
539   GList *tmp;
540
541   g_return_if_fail (window != NULL);
542
543   private = (GdkWindowPrivate *) window;
544
545   GDK_NOTE (MISC, g_print ("gdk_window_internal_destroy %#x\n",
546                            GDK_DRAWABLE_XID (window)));
547
548   switch (GDK_DRAWABLE_TYPE (window))
549     {
550     case GDK_WINDOW_TOPLEVEL:
551     case GDK_WINDOW_CHILD:
552     case GDK_WINDOW_DIALOG:
553     case GDK_WINDOW_TEMP:
554     case GDK_WINDOW_FOREIGN:
555       if (!private->drawable.destroyed)
556         {
557           if (private->parent)
558             {
559               GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
560               if (parent_private->children)
561                 parent_private->children = g_list_remove (parent_private->children, window);
562             }
563
564           if (GDK_DRAWABLE_TYPE (window) != GDK_WINDOW_FOREIGN)
565             {
566               children = tmp = private->children;
567               private->children = NULL;
568
569               while (tmp)
570                 {
571                   temp_window = tmp->data;
572                   tmp = tmp->next;
573                   
574                   temp_private = (GdkWindowPrivate*) temp_window;
575                   if (temp_private)
576                     gdk_window_internal_destroy (temp_window, FALSE,
577                                                  our_destroy);
578                 }
579
580               g_list_free (children);
581             }
582
583           if (private->extension_events != 0)
584             gdk_input_window_destroy (window);
585
586           if (private->filters)
587             {
588               tmp = private->filters;
589
590               while (tmp)
591                 {
592                   g_free (tmp->data);
593                   tmp = tmp->next;
594                 }
595
596               g_list_free (private->filters);
597               private->filters = NULL;
598             }
599           
600           if (private->drawable.window_type == GDK_WINDOW_FOREIGN)
601             {
602               if (our_destroy && (private->parent != NULL))
603                 {
604                   /* It's somebody elses window, but in our hierarchy,
605                    * so reparent it to the root window, and then send
606                    * it a delete event, as if we were a WM
607                    */
608                   gdk_window_hide (window);
609                   gdk_window_reparent (window, NULL, 0, 0);
610                   
611                   /* Is this too drastic? Many (most?) applications
612                    * quit if any window receives WM_QUIT I think.
613                    * OTOH, I don't think foreign windows are much
614                    * used, so the question is maybe academic.
615                    */
616                   PostMessage (GDK_DRAWABLE_XID (window), WM_QUIT, 0, 0);
617                 }
618             }
619           else if (xdestroy)
620             DestroyWindow (GDK_DRAWABLE_XID (window));
621
622           if (private->drawable.colormap)
623             gdk_colormap_unref (private->drawable.colormap);
624
625           private->mapped = FALSE;
626           private->drawable.destroyed = TRUE;
627         }
628       break;
629
630     case GDK_WINDOW_ROOT:
631       g_error ("attempted to destroy root window");
632       break;
633
634     case GDK_DRAWABLE_PIXMAP:
635       g_error ("called gdk_window_destroy on a pixmap (use gdk_drawable_unref)");
636       break;
637     }
638 }
639
640 /* Like internal_destroy, but also destroys the reference created by
641    gdk_window_new. */
642
643 void
644 gdk_window_destroy (GdkWindow *window)
645 {
646   gdk_window_internal_destroy (window, TRUE, TRUE);
647   gdk_drawable_unref (window);
648 }
649
650 /* This function is called when the window really gone.  */
651
652 void
653 gdk_window_destroy_notify (GdkWindow *window)
654 {
655   g_return_if_fail (window != NULL);
656
657   GDK_NOTE (EVENTS,
658             g_print ("gdk_window_destroy_notify: %#x  %s\n",
659                      GDK_DRAWABLE_XID (window),
660                      (GDK_DRAWABLE_DESTROYED (window) ? "yes" : "no")));
661
662   if (!GDK_DRAWABLE_DESTROYED (window))
663     {
664       if (GDK_DRAWABLE_TYPE(window) != GDK_WINDOW_FOREIGN)
665         g_warning ("window %#x unexpectedly destroyed",
666                    GDK_DRAWABLE_XID (window));
667
668       gdk_window_internal_destroy (window, FALSE, FALSE);
669     }
670   
671   gdk_xid_table_remove (GDK_DRAWABLE_XID (window));
672   gdk_drawable_unref (window);
673 }
674
675 void
676 gdk_window_show (GdkWindow *window)
677 {
678   g_return_if_fail (window != NULL);
679
680   if (!GDK_DRAWABLE_DESTROYED (window))
681     {
682       GDK_NOTE (MISC, g_print ("gdk_window_show: %#x\n",
683                                GDK_DRAWABLE_XID (window)));
684
685       ((GdkWindowPrivate *) window)->mapped = TRUE;
686       if (GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_TEMP)
687         {
688           ShowWindow (GDK_DRAWABLE_XID (window), SW_SHOWNOACTIVATE);
689           SetWindowPos (GDK_DRAWABLE_XID (window), HWND_TOPMOST, 0, 0, 0, 0,
690                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
691 #if 0
692           /* Don't put on toolbar */
693           ShowWindow (GDK_DRAWABLE_XID (window), SW_HIDE);
694 #endif
695         }
696       else
697         {
698           ShowWindow (GDK_DRAWABLE_XID (window), SW_SHOWNORMAL);
699           ShowWindow (GDK_DRAWABLE_XID (window), SW_RESTORE);
700           SetForegroundWindow (GDK_DRAWABLE_XID (window));
701           BringWindowToTop (GDK_DRAWABLE_XID (window));
702 #if 0
703           ShowOwnedPopups (GDK_DRAWABLE_XID (window), TRUE);
704 #endif
705         }
706     }
707 }
708
709 void
710 gdk_window_hide (GdkWindow *window)
711 {
712   g_return_if_fail (window != NULL);
713
714   if (!GDK_DRAWABLE_DESTROYED (window))
715     {
716       GDK_NOTE (MISC, g_print ("gdk_window_hide: %#x\n",
717                                GDK_DRAWABLE_XID (window)));
718
719       ((GdkWindowPrivate *) window)->mapped = FALSE;
720       if (GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_TOPLEVEL)
721         ShowOwnedPopups (GDK_DRAWABLE_XID (window), FALSE);
722 #if 1
723       ShowWindow (GDK_DRAWABLE_XID (window), SW_HIDE);
724 #elif 0
725       ShowWindow (GDK_DRAWABLE_XID (window), SW_MINIMIZE);
726 #else
727       CloseWindow (GDK_DRAWABLE_XID (window));
728 #endif
729     }
730 }
731
732 void
733 gdk_window_withdraw (GdkWindow *window)
734 {
735   g_return_if_fail (window != NULL);
736
737   if (!GDK_DRAWABLE_DESTROYED (window))
738     {
739       GDK_NOTE (MISC, g_print ("gdk_window_withdraw: %#x\n",
740                                GDK_DRAWABLE_XID (window)));
741
742       gdk_window_hide (window); /* XXX */
743     }
744 }
745
746 void
747 gdk_window_move (GdkWindow *window,
748                  gint       x,
749                  gint       y)
750 {
751   GdkWindowPrivate *private;
752
753   g_return_if_fail (window != NULL);
754
755   if (!GDK_DRAWABLE_DESTROYED (window))
756     {
757       RECT rect;
758
759       GDK_NOTE (MISC, g_print ("gdk_window_move: %#x +%d+%d\n",
760                                GDK_DRAWABLE_XID (window), x, y));
761
762       private = (GdkWindowPrivate *) window;
763       GetClientRect (GDK_DRAWABLE_XID (window), &rect);
764
765       if (GDK_DRAWABLE_TYPE (window) != GDK_WINDOW_CHILD)
766         {
767           POINT ptTL, ptBR;
768           DWORD dwStyle;
769           DWORD dwExStyle;
770
771           ptTL.x = 0;
772           ptTL.y = 0; 
773           ClientToScreen (GDK_DRAWABLE_XID (window), &ptTL);
774           rect.left = x;
775           rect.top = y;
776
777           ptBR.x = rect.right;
778           ptBR.y = rect.bottom;
779           ClientToScreen (GDK_DRAWABLE_XID (window), &ptBR);
780           rect.right = x + ptBR.x - ptTL.x;
781           rect.bottom = y + ptBR.y - ptTL.y;
782
783           dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
784           dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
785           if (!SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
786             g_warning ("gdk_window_move: AdjustWindowRectEx failed");
787
788           x = rect.left;
789           y = rect.top;
790         }
791       else
792         {
793           private->x = x;
794           private->y = y;
795         }
796       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
797                                GDK_DRAWABLE_XID (window),
798                                rect.right - rect.left, rect.bottom - rect.top,
799                                x, y));
800       if (!MoveWindow (GDK_DRAWABLE_XID (window),
801                        x, y, rect.right - rect.left, rect.bottom - rect.top,
802                        TRUE))
803         g_warning ("gdk_window_move: MoveWindow failed");
804     }
805 }
806
807 void
808 gdk_window_resize (GdkWindow *window,
809                    gint       width,
810                    gint       height)
811 {
812   GdkWindowPrivate *private;
813
814   g_return_if_fail (window != NULL);
815
816   if ((gint16) width < 1)
817     width = 1;
818   if ((gint16) height < 1)
819     height = 1;
820
821   private = (GdkWindowPrivate*) window;
822
823   if (!private->drawable.destroyed &&
824       ((private->resize_count > 0) ||
825        (private->drawable.width != (guint16) width) ||
826        (private->drawable.height != (guint16) height)))
827     {
828       int x, y;
829
830       GDK_NOTE (MISC, g_print ("gdk_window_resize: %#x %dx%d\n",
831                                GDK_DRAWABLE_XID (window), width, height));
832       
833       if (private->drawable.window_type != GDK_WINDOW_CHILD)
834         {
835           POINT pt;
836           RECT rect;
837           DWORD dwStyle;
838           DWORD dwExStyle;
839
840           pt.x = 0;
841           pt.y = 0; 
842           ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
843           rect.left = pt.x;
844           rect.top = pt.y;
845           rect.right = pt.x + width;
846           rect.bottom = pt.y + height;
847
848           dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
849           dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
850           if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
851             g_warning ("gdk_window_resize: AdjustWindowRectEx failed");
852
853           x = rect.left;
854           y = rect.top;
855           width = rect.right - rect.left;
856           height = rect.bottom - rect.top;
857         }
858       else
859         {
860           x = private->x;
861           y = private->y;
862           private->drawable.width = width;
863           private->drawable.height = height;
864         }
865
866       private->resize_count += 1;
867
868       GDK_NOTE (MISC,
869                 g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
870                          GDK_DRAWABLE_XID (window), width, height, x, y));
871       if (!MoveWindow (GDK_DRAWABLE_XID (window),
872                        x, y, width, height,
873                        TRUE))
874         g_warning ("gdk_window_resize: MoveWindow failed");
875     }
876 }
877
878 void
879 gdk_window_move_resize (GdkWindow *window,
880                         gint       x,
881                         gint       y,
882                         gint       width,
883                         gint       height)
884 {
885   GdkWindowPrivate *private;
886
887   g_return_if_fail (window != NULL);
888
889   if ((gint16) width < 1)
890     width = 1;
891   if ((gint16) height < 1)
892     height = 1;
893
894   if (!GDK_DRAWABLE_DESTROYED (window))
895     {
896       RECT rect;
897       DWORD dwStyle;
898       DWORD dwExStyle;
899
900       GDK_NOTE (MISC, g_print ("gdk_window_move_resize: %#x %dx%d@+%d+%d\n",
901                                GDK_DRAWABLE_XID (window), width, height, x, y));
902       
903       private = (GdkWindowPrivate*) window;
904       rect.left = x;
905       rect.top = y;
906       rect.right = x + width;
907       rect.bottom = y + height;
908
909       dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
910       dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
911       if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
912         g_warning ("gdk_window_move_resize: AdjustWindowRectEx failed");
913
914       if (private->drawable.window_type == GDK_WINDOW_CHILD)
915         {
916           private->x = x;
917           private->y = y;
918           private->drawable.width = width;
919           private->drawable.height = height;
920         }
921       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
922                                GDK_DRAWABLE_XID (window),
923                                rect.right - rect.left, rect.bottom - rect.top,
924                                rect.left, rect.top));
925       if (!MoveWindow (GDK_DRAWABLE_XID (window),
926                        rect.left, rect.top,
927                        rect.right - rect.left, rect.bottom - rect.top,
928                        TRUE))
929         g_warning ("gdk_window_move_resize: MoveWindow failed");
930
931       if (private->guffaw_gravity)
932         {
933           GList *tmp_list = private->children;
934           while (tmp_list)
935             {
936               GdkWindowPrivate *child_private = tmp_list->data;
937               
938               child_private->x -= x - private->x;
939               child_private->y -= y - private->y;
940               
941               tmp_list = tmp_list->next;
942             }
943         }
944       
945     }
946 }
947
948 void
949 gdk_window_reparent (GdkWindow *window,
950                      GdkWindow *new_parent,
951                      gint       x,
952                      gint       y)
953 {
954   GdkWindowPrivate *window_private;
955   GdkWindowPrivate *parent_private;
956   GdkWindowPrivate *old_parent_private;
957
958   g_return_if_fail (window != NULL);
959
960   if (!new_parent)
961     new_parent = gdk_parent_root;
962
963   window_private = (GdkWindowPrivate*) window;
964   old_parent_private = (GdkWindowPrivate *) window_private->parent;
965   parent_private = (GdkWindowPrivate*) new_parent;
966
967   if (!GDK_DRAWABLE_DESTROYED (window)
968       && !GDK_DRAWABLE_DESTROYED (new_parent))
969     {
970       GDK_NOTE (MISC, g_print ("gdk_window_reparent: %#x %#x\n",
971                                GDK_DRAWABLE_XID (window),
972                                GDK_DRAWABLE_XID (new_parent)));
973       if (!SetParent (GDK_DRAWABLE_XID (window),
974                       GDK_DRAWABLE_XID (new_parent)))
975         g_warning ("gdk_window_reparent: SetParent failed");
976
977       if (!MoveWindow (GDK_DRAWABLE_XID (window),
978                        x, y,
979                        window_private->drawable.width,
980                        window_private->drawable.height,
981                        TRUE))
982         g_warning ("gdk_window_reparent: MoveWindow failed");
983     }
984   
985   window_private->parent = new_parent;
986
987   if (old_parent_private)
988     old_parent_private->children =
989       g_list_remove (old_parent_private->children, window);
990
991   if ((old_parent_private &&
992        (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
993       (!old_parent_private && parent_private->guffaw_gravity))
994     gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
995   
996   parent_private->children = g_list_prepend (parent_private->children, window);
997 }
998
999 void
1000 gdk_window_clear (GdkWindow *window)
1001 {
1002   g_return_if_fail (window != NULL);
1003   g_return_if_fail (GDK_IS_WINDOW (window));
1004
1005   if (!GDK_DRAWABLE_DESTROYED (window))
1006     gdk_window_clear_area (window, 0, 0, -1, -1);
1007 }
1008
1009
1010 void
1011 gdk_window_clear_area (GdkWindow *window,
1012                        gint       x,
1013                        gint       y,
1014                        gint       width,
1015                        gint       height)
1016 {
1017   g_return_if_fail (window != NULL);
1018   g_return_if_fail (GDK_IS_WINDOW (window));
1019   
1020   if (!GDK_DRAWABLE_DESTROYED (window))
1021     {
1022       HDC hdc;
1023
1024       if (width == -1)
1025         width = G_MAXSHORT/2;           /* Yeah, right */
1026       if (height == -1)
1027         height = G_MAXSHORT/2;
1028       GDK_NOTE (MISC, g_print ("gdk_window_clear_area: %#x %dx%d@+%d+%d\n",
1029                                GDK_DRAWABLE_XID (window), width, height, x, y));
1030       hdc = GetDC (GDK_DRAWABLE_XID (window));
1031       IntersectClipRect (hdc, x, y, x + width, y + height);
1032       SendMessage (GDK_DRAWABLE_XID (window), WM_ERASEBKGND, (WPARAM) hdc, 0);
1033       ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
1034     }
1035 }
1036
1037 void
1038 gdk_window_clear_area_e (GdkWindow *window,
1039                          gint       x,
1040                          gint       y,
1041                          gint       width,
1042                          gint       height)
1043 {
1044   g_return_if_fail (window != NULL);
1045   g_return_if_fail (GDK_IS_WINDOW (window));
1046   
1047   if (!GDK_DRAWABLE_DESTROYED (window))
1048     {
1049       RECT rect;
1050
1051       GDK_NOTE (MISC, g_print ("gdk_window_clear_area_e: %#x %dx%d@+%d+%d\n",
1052                                GDK_DRAWABLE_XID (window), width, height, x, y));
1053
1054       rect.left = x;
1055       rect.right = x + width;
1056       rect.top = y;
1057       rect.bottom = y + height;
1058       if (!InvalidateRect (GDK_DRAWABLE_XID (window), &rect, TRUE))
1059         g_warning ("gdk_window_clear_area_e: InvalidateRect failed");
1060       UpdateWindow (GDK_DRAWABLE_XID (window));
1061     }
1062 }
1063
1064 void
1065 gdk_window_raise (GdkWindow *window)
1066 {
1067   g_return_if_fail (window != NULL);
1068   g_return_if_fail (GDK_IS_WINDOW (window));
1069   
1070   if (!GDK_DRAWABLE_DESTROYED (window))
1071     {
1072       GDK_NOTE (MISC, g_print ("gdk_window_raise: %#x\n",
1073                                GDK_DRAWABLE_XID (window)));
1074
1075       if (!BringWindowToTop (GDK_DRAWABLE_XID (window)))
1076         g_warning ("gdk_window_raise: BringWindowToTop failed");
1077     }
1078 }
1079
1080 void
1081 gdk_window_lower (GdkWindow *window)
1082 {
1083   g_return_if_fail (window != NULL);
1084   g_return_if_fail (GDK_IS_WINDOW (window));
1085   
1086   if (!GDK_DRAWABLE_DESTROYED (window))
1087     {
1088       GDK_NOTE (MISC, g_print ("gdk_window_lower: %#x\n",
1089                                GDK_DRAWABLE_XID (window)));
1090
1091       if (!SetWindowPos (GDK_DRAWABLE_XID (window), HWND_BOTTOM, 0, 0, 0, 0,
1092                          SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE))
1093         g_warning ("gdk_window_lower: SetWindowPos failed");
1094     }
1095 }
1096
1097 void
1098 gdk_window_set_hints (GdkWindow *window,
1099                       gint       x,
1100                       gint       y,
1101                       gint       min_width,
1102                       gint       min_height,
1103                       gint       max_width,
1104                       gint       max_height,
1105                       gint       flags)
1106 {
1107   WINDOWPLACEMENT size_hints;
1108   RECT rect;
1109   DWORD dwStyle;
1110   DWORD dwExStyle;
1111   int diff;
1112   
1113   g_return_if_fail (window != NULL);
1114   g_return_if_fail (GDK_IS_WINDOW (window));
1115   
1116   if (GDK_DRAWABLE_DESTROYED (window))
1117     return;
1118   
1119   GDK_NOTE (MISC, g_print ("gdk_window_set_hints: %#x %dx%d..%dx%d @+%d+%d\n",
1120                            GDK_DRAWABLE_XID (window),
1121                            min_width, min_height, max_width, max_height,
1122                            x, y));
1123
1124   GDK_WINDOW_WIN32DATA (window)->hint_flags = flags;
1125   size_hints.length = sizeof (size_hints);
1126
1127   if (flags)
1128     {
1129       if (flags & GDK_HINT_POS)
1130         if (!GetWindowPlacement (GDK_DRAWABLE_XID (window), &size_hints))
1131           g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
1132         else
1133           {
1134             GDK_NOTE (MISC, g_print ("...rcNormalPosition:"
1135                                      " (%d,%d)--(%d,%d)\n",
1136                                      size_hints.rcNormalPosition.left,
1137                                      size_hints.rcNormalPosition.top,
1138                                      size_hints.rcNormalPosition.right,
1139                                      size_hints.rcNormalPosition.bottom));
1140             /* What are the corresponding window coordinates for client
1141              * area coordinates x, y
1142              */
1143             rect.left = x;
1144             rect.top = y;
1145             rect.right = rect.left + 200;       /* dummy */
1146             rect.bottom = rect.top + 200;
1147             dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
1148             dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
1149             AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1150             size_hints.flags = 0;
1151             size_hints.showCmd = SW_SHOWNA;
1152
1153             /* Set the normal position hint to that location, with unchanged
1154              * width and height.
1155              */
1156             diff = size_hints.rcNormalPosition.left - rect.left;
1157             size_hints.rcNormalPosition.left = rect.left;
1158             size_hints.rcNormalPosition.right -= diff;
1159             diff = size_hints.rcNormalPosition.top - rect.top;
1160             size_hints.rcNormalPosition.top = rect.top;
1161             size_hints.rcNormalPosition.bottom -= diff;
1162             GDK_NOTE (MISC, g_print ("...setting: (%d,%d)--(%d,%d)\n",
1163                                      size_hints.rcNormalPosition.left,
1164                                      size_hints.rcNormalPosition.top,
1165                                      size_hints.rcNormalPosition.right,
1166                                      size_hints.rcNormalPosition.bottom));
1167             if (!SetWindowPlacement (GDK_DRAWABLE_XID (window), &size_hints))
1168               g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
1169             GDK_WINDOW_WIN32DATA (window)->hint_x = rect.left;
1170             GDK_WINDOW_WIN32DATA (window)->hint_y = rect.top;
1171           }
1172
1173       if (flags & GDK_HINT_MIN_SIZE)
1174         {
1175           rect.left = 0;
1176           rect.top = 0;
1177           rect.right = min_width;
1178           rect.bottom = min_height;
1179           dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
1180           dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
1181           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1182           GDK_WINDOW_WIN32DATA (window)->hint_min_width =
1183             rect.right - rect.left;
1184           GDK_WINDOW_WIN32DATA (window)->hint_min_height =
1185             rect.bottom - rect.top;
1186
1187           /* Also chek if he current size of the window is in bounds. */
1188           GetClientRect (GDK_DRAWABLE_XID (window), &rect);
1189           if (rect.right < min_width && rect.bottom < min_height)
1190             gdk_window_resize (window, min_width, min_height);
1191           else if (rect.right < min_width)
1192             gdk_window_resize (window, min_width, rect.bottom);
1193           else if (rect.bottom < min_height)
1194             gdk_window_resize (window, rect.right, min_height);
1195         }
1196
1197       if (flags & GDK_HINT_MAX_SIZE)
1198         {
1199           rect.left = 0;
1200           rect.top = 0;
1201           rect.right = max_width;
1202           rect.bottom = max_height;
1203           dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
1204           dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
1205           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1206           GDK_WINDOW_WIN32DATA (window)->hint_max_width =
1207             rect.right - rect.left;
1208           GDK_WINDOW_WIN32DATA (window)->hint_max_height =
1209             rect.bottom - rect.top;
1210           /* Again, check if the window is too large currently. */
1211           GetClientRect (GDK_DRAWABLE_XID (window), &rect);
1212           if (rect.right > max_width && rect.bottom > max_height)
1213             gdk_window_resize (window, max_width, max_height);
1214           else if (rect.right > max_width)
1215             gdk_window_resize (window, max_width, rect.bottom);
1216           else if (rect.bottom > max_height)
1217             gdk_window_resize (window, rect.right, max_height);
1218         }
1219     }
1220 }
1221
1222 void 
1223 gdk_window_set_geometry_hints (GdkWindow      *window,
1224                                GdkGeometry    *geometry,
1225                                GdkWindowHints  geom_mask)
1226 {
1227   WINDOWPLACEMENT size_hints;
1228   RECT rect;
1229   DWORD dwStyle;
1230   DWORD dwExStyle;
1231   int diff;
1232   
1233   g_return_if_fail (window != NULL);
1234   g_return_if_fail (GDK_IS_WINDOW (window));
1235   
1236   if (GDK_DRAWABLE_DESTROYED (window))
1237     return;
1238
1239   size_hints.length = sizeof (size_hints);
1240
1241   GDK_WINDOW_WIN32DATA (window)->hint_flags = geom_mask;
1242
1243   if (geom_mask & GDK_HINT_POS)
1244     ; /* XXX */
1245
1246   if (geom_mask & GDK_HINT_MIN_SIZE)
1247     {
1248       rect.left = 0;
1249       rect.top = 0;
1250       rect.right = geometry->min_width;
1251       rect.bottom = geometry->min_height;
1252       dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
1253       dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
1254       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1255       GDK_WINDOW_WIN32DATA (window)->hint_min_width = rect.right - rect.left;
1256       GDK_WINDOW_WIN32DATA (window)->hint_min_height = rect.bottom - rect.top;
1257
1258       /* Also check if he current size of the window is in bounds */
1259       GetClientRect (GDK_DRAWABLE_XID (window), &rect);
1260       if (rect.right < geometry->min_width
1261           && rect.bottom < geometry->min_height)
1262         gdk_window_resize (window, geometry->min_width, geometry->min_height);
1263       else if (rect.right < geometry->min_width)
1264         gdk_window_resize (window, geometry->min_width, rect.bottom);
1265       else if (rect.bottom < geometry->min_height)
1266         gdk_window_resize (window, rect.right, geometry->min_height);
1267     }
1268   
1269   if (geom_mask & GDK_HINT_MAX_SIZE)
1270     {
1271       rect.left = 0;
1272       rect.top = 0;
1273       rect.right = geometry->max_width;
1274       rect.bottom = geometry->max_height;
1275       dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
1276       dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
1277       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1278       GDK_WINDOW_WIN32DATA (window)->hint_max_width = rect.right - rect.left;
1279       GDK_WINDOW_WIN32DATA (window)->hint_max_height = rect.bottom - rect.top;
1280
1281       /* Again, check if the window is too large currently. */
1282       GetClientRect (GDK_DRAWABLE_XID (window), &rect);
1283       if (rect.right > geometry->max_width
1284           && rect.bottom > geometry->max_height)
1285         gdk_window_resize (window, geometry->max_width, geometry->max_height);
1286       else if (rect.right > geometry->max_width)
1287         gdk_window_resize (window, geometry->max_width, rect.bottom);
1288       else if (rect.bottom > geometry->max_height)
1289         gdk_window_resize (window, rect.right, geometry->max_height);
1290     }
1291   
1292   /* I don't know what to do when called with zero base_width and height. */
1293   if (geom_mask & GDK_HINT_BASE_SIZE
1294       && geometry->base_width > 0
1295       && geometry->base_height > 0)
1296     if (!GetWindowPlacement (GDK_DRAWABLE_XID (window), &size_hints))
1297       g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
1298     else
1299       {
1300         GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints:"
1301                                  " rcNormalPosition: (%d,%d)--(%d,%d)\n",
1302                                  size_hints.rcNormalPosition.left,
1303                                  size_hints.rcNormalPosition.top,
1304                                  size_hints.rcNormalPosition.right,
1305                                  size_hints.rcNormalPosition.bottom));
1306         size_hints.rcNormalPosition.right =
1307           size_hints.rcNormalPosition.left + geometry->base_width;
1308         size_hints.rcNormalPosition.bottom =
1309           size_hints.rcNormalPosition.top + geometry->base_height;
1310         GDK_NOTE (MISC, g_print ("...setting: rcNormal: (%d,%d)--(%d,%d)\n",
1311                                  size_hints.rcNormalPosition.left,
1312                                  size_hints.rcNormalPosition.top,
1313                                  size_hints.rcNormalPosition.right,
1314                                  size_hints.rcNormalPosition.bottom));
1315         if (!SetWindowPlacement (GDK_DRAWABLE_XID (window), &size_hints))
1316           g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
1317       }
1318   
1319   if (geom_mask & GDK_HINT_RESIZE_INC)
1320     {
1321       /* XXX */
1322     }
1323   
1324   if (geom_mask & GDK_HINT_ASPECT)
1325     {
1326       /* XXX */
1327     }
1328 }
1329
1330 void
1331 gdk_window_set_title (GdkWindow   *window,
1332                       const gchar *title)
1333 {
1334   gint titlelen;
1335   wchar_t *wcstr;
1336   gint wlen;
1337   char *mbstr;
1338
1339   g_return_if_fail (window != NULL);
1340   g_return_if_fail (GDK_IS_WINDOW (window));
1341   
1342   GDK_NOTE (MISC, g_print ("gdk_window_set_title: %#x %s\n",
1343                            GDK_DRAWABLE_XID (window), title));
1344   if (!GDK_DRAWABLE_DESTROYED (window))
1345     {
1346       /* As the title most is in UTF-8 we must translate it
1347        * to the system codepage.
1348        */
1349       titlelen = strlen (title);
1350       wcstr = g_new (wchar_t, titlelen + 1);
1351       mbstr = g_new (char, 3*titlelen + 1);
1352       wlen = gdk_nmbstowchar_ts (wcstr, title, titlelen, titlelen);
1353       wcstr[wlen] = 0;
1354       WideCharToMultiByte (GetACP (), 0, wcstr, -1,
1355                            mbstr, 3*titlelen, NULL, NULL);
1356
1357       if (!SetWindowText (GDK_DRAWABLE_XID (window), mbstr))
1358         g_warning ("gdk_window_set_title: SetWindowText failed");
1359
1360       g_free (mbstr);
1361       g_free (wcstr);
1362     }
1363 }
1364
1365 void          
1366 gdk_window_set_role (GdkWindow   *window,
1367                      const gchar *role)
1368 {
1369   g_return_if_fail (window != NULL);
1370   g_return_if_fail (GDK_IS_WINDOW (window));
1371   
1372   GDK_NOTE (MISC, g_print ("gdk_window_set_role: %#x %s\n",
1373                            GDK_DRAWABLE_XID (window), (role ? role : "NULL")));
1374   /* XXX */
1375 }
1376
1377 void          
1378 gdk_window_set_transient_for (GdkWindow *window, 
1379                               GdkWindow *parent)
1380 {
1381   g_return_if_fail (window != NULL);
1382   g_return_if_fail (GDK_IS_WINDOW (window));
1383   
1384   GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %#x %#x\n",
1385                            GDK_DRAWABLE_XID (window),
1386                            GDK_DRAWABLE_XID (parent)));
1387   /* XXX */
1388 }
1389
1390 void
1391 gdk_window_set_background (GdkWindow *window,
1392                            GdkColor  *color)
1393 {
1394   g_return_if_fail (window != NULL);
1395   g_return_if_fail (GDK_IS_WINDOW (window));
1396   
1397   if (!GDK_DRAWABLE_DESTROYED (window))
1398     {
1399       GDK_NOTE (MISC, g_print ("gdk_window_set_background: %#x %s\n",
1400                                GDK_DRAWABLE_XID (window), 
1401                                gdk_color_to_string (color)));
1402
1403       if (GDK_WINDOW_WIN32DATA (window)->bg_type == GDK_WIN32_BG_PIXMAP)
1404         {
1405           if (GDK_WINDOW_WIN32DATA (window)->bg_pixmap != NULL)
1406             {
1407               gdk_drawable_unref (GDK_WINDOW_WIN32DATA (window)->bg_pixmap);
1408               GDK_WINDOW_WIN32DATA (window)->bg_pixmap = NULL;
1409             }
1410           GDK_WINDOW_WIN32DATA (window)->bg_type = GDK_WIN32_BG_NORMAL;
1411         }
1412       GDK_WINDOW_WIN32DATA (window)->bg_type = GDK_WIN32_BG_PIXEL;
1413       GDK_WINDOW_WIN32DATA (window)->bg_pixel = *color;
1414     }
1415 }
1416
1417 void
1418 gdk_window_set_back_pixmap (GdkWindow *window,
1419                             GdkPixmap *pixmap,
1420                             gint       parent_relative)
1421 {
1422   g_return_if_fail (window != NULL);
1423   g_return_if_fail (GDK_IS_WINDOW (window));
1424   
1425   if (!GDK_DRAWABLE_DESTROYED (window))
1426     {
1427       if (GDK_WINDOW_WIN32DATA (window)->bg_type == GDK_WIN32_BG_PIXMAP)
1428         {
1429           if (GDK_WINDOW_WIN32DATA (window)->bg_pixmap != NULL)
1430             {
1431               gdk_drawable_unref (GDK_WINDOW_WIN32DATA (window)->bg_pixmap);
1432               GDK_WINDOW_WIN32DATA (window)->bg_pixmap = NULL;
1433             }
1434           GDK_WINDOW_WIN32DATA (window)->bg_type = GDK_WIN32_BG_NORMAL;
1435         }
1436       if (parent_relative)
1437         {
1438           GDK_WINDOW_WIN32DATA (window)->bg_type =
1439             GDK_WIN32_BG_PARENT_RELATIVE;
1440         }
1441       else if (!pixmap)
1442         {
1443           
1444         }
1445       else
1446         {
1447           /* We must cache the pixmap in the GdkWindowWin32Data and
1448            * paint it each time we get WM_ERASEBKGND
1449            */
1450           GDK_WINDOW_WIN32DATA (window)->bg_type = GDK_WIN32_BG_PIXMAP;
1451           GDK_WINDOW_WIN32DATA (window)->bg_pixmap = pixmap;
1452           gdk_drawable_ref (pixmap);
1453         }
1454     }
1455 }
1456
1457 void
1458 gdk_window_set_cursor (GdkWindow *window,
1459                        GdkCursor *cursor)
1460 {
1461   GdkCursorPrivate *cursor_private;
1462   HCURSOR xcursor;
1463   
1464   g_return_if_fail (window != NULL);
1465   g_return_if_fail (GDK_IS_WINDOW (window));
1466   
1467   cursor_private = (GdkCursorPrivate*) cursor;
1468   
1469   if (!GDK_DRAWABLE_DESTROYED (window))
1470     {
1471       if (!cursor)
1472         xcursor = LoadCursor (NULL, IDC_ARROW);
1473       else
1474         xcursor = cursor_private->xcursor;
1475
1476       GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %#x %#x\n",
1477                                GDK_DRAWABLE_XID (window), xcursor));
1478       GDK_WINDOW_WIN32DATA (window)->xcursor = xcursor;
1479     }
1480 }
1481
1482 void
1483 gdk_window_get_geometry (GdkWindow *window,
1484                          gint      *x,
1485                          gint      *y,
1486                          gint      *width,
1487                          gint      *height,
1488                          gint      *depth)
1489 {
1490   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1491   
1492   if (!window)
1493     window = gdk_parent_root;
1494   
1495   if (!GDK_DRAWABLE_DESTROYED (window))
1496     {
1497       RECT rect;
1498
1499       if (!GetClientRect (GDK_DRAWABLE_XID (window), &rect))
1500         g_warning ("gdk_window_get_geometry: GetClientRect failed");
1501
1502       if (x)
1503         *x = rect.left;
1504       if (y)
1505         *y = rect.top;
1506       if (width)
1507         *width = rect.right - rect.left;
1508       if (height)
1509         *height = rect.bottom - rect.top;
1510       if (depth)
1511         *depth = gdk_drawable_get_visual (window)->depth;
1512     }
1513 }
1514
1515 gint
1516 gdk_window_get_origin (GdkWindow *window,
1517                        gint      *x,
1518                        gint      *y)
1519 {
1520   gint return_val;
1521   gint tx = 0;
1522   gint ty = 0;
1523
1524   g_return_val_if_fail (window != NULL, 0);
1525
1526   if (!GDK_DRAWABLE_DESTROYED (window))
1527     {
1528       POINT pt;
1529
1530       pt.x = 0;
1531       pt.y = 0;
1532       ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
1533       tx = pt.x;
1534       ty = pt.y;
1535       return_val = 1;
1536     }
1537   else
1538     return_val = 0;
1539   
1540   if (x)
1541     *x = tx;
1542   if (y)
1543     *y = ty;
1544
1545   GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %#x: +%d+%d\n",
1546                            GDK_DRAWABLE_XID (window), tx, ty));
1547   return return_val;
1548 }
1549
1550 gboolean
1551 gdk_window_get_deskrelative_origin (GdkWindow *window,
1552                                     gint      *x,
1553                                     gint      *y)
1554 {
1555   return gdk_window_get_origin (window, x, y);
1556 }
1557
1558 void
1559 gdk_window_get_root_origin (GdkWindow *window,
1560                             gint      *x,
1561                             gint      *y)
1562 {
1563   GdkWindowPrivate *rover;
1564   POINT pt;
1565
1566   g_return_if_fail (window != NULL);
1567   g_return_if_fail (GDK_IS_WINDOW (window));
1568
1569   rover = (GdkWindowPrivate*) window;
1570   if (x)
1571     *x = 0;
1572   if (y)
1573     *y = 0;
1574   if (GDK_DRAWABLE_DESTROYED (window))
1575     return;
1576       
1577   while (rover->parent && ((GdkWindowPrivate*) rover->parent)->parent)
1578     rover = (GdkWindowPrivate *) rover->parent;
1579   if (rover->drawable.destroyed)
1580     return;
1581
1582   pt.x = 0;
1583   pt.y = 0;
1584   ClientToScreen (GDK_DRAWABLE_XID (rover), &pt);
1585   if (x)
1586     *x = pt.x;
1587   if (y)
1588     *y = pt.y;
1589
1590   GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %#x: (%#x) +%d+%d\n",
1591                            GDK_DRAWABLE_XID (window),
1592                            GDK_DRAWABLE_XID (rover), pt.x, pt.y));
1593 }
1594
1595 GdkWindow*
1596 gdk_window_get_pointer (GdkWindow       *window,
1597                         gint            *x,
1598                         gint            *y,
1599                         GdkModifierType *mask)
1600 {
1601   GdkWindow *return_val;
1602   POINT pointc, point;
1603   HWND hwnd, hwndc;
1604
1605   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1606   
1607   if (!window)
1608     window = gdk_parent_root;
1609
1610   return_val = NULL;
1611   GetCursorPos (&pointc);
1612   point = pointc;
1613   ScreenToClient (GDK_DRAWABLE_XID (window), &point);
1614
1615   if (x)
1616     *x = point.x;
1617   if (y)
1618     *y = point.y;
1619
1620   hwnd = WindowFromPoint (point);
1621   point = pointc;
1622   ScreenToClient (hwnd, &point);
1623   
1624   do {
1625     hwndc = ChildWindowFromPoint (hwnd, point);
1626     ClientToScreen (hwnd, &point);
1627     ScreenToClient (hwndc, &point);
1628   } while (hwndc != hwnd && (hwnd = hwndc, 1)); /* Ouch! */
1629
1630   return_val = gdk_window_lookup (hwnd);
1631
1632   if (mask)
1633     {
1634       BYTE kbd[256];
1635
1636       GetKeyboardState (kbd);
1637       *mask = 0;
1638       if (kbd[VK_SHIFT] & 0x80)
1639         *mask |= GDK_SHIFT_MASK;
1640       if (kbd[VK_CAPITAL] & 0x80)
1641         *mask |= GDK_LOCK_MASK;
1642       if (kbd[VK_CONTROL] & 0x80)
1643         *mask |= GDK_CONTROL_MASK;
1644       if (kbd[VK_MENU] & 0x80)
1645         *mask |= GDK_MOD1_MASK;
1646       if (kbd[VK_LBUTTON] & 0x80)
1647         *mask |= GDK_BUTTON1_MASK;
1648       if (kbd[VK_MBUTTON] & 0x80)
1649         *mask |= GDK_BUTTON2_MASK;
1650       if (kbd[VK_RBUTTON] & 0x80)
1651         *mask |= GDK_BUTTON3_MASK;
1652     }
1653   
1654   return return_val;
1655 }
1656
1657 GdkWindow*
1658 gdk_window_at_pointer (gint *win_x,
1659                        gint *win_y)
1660 {
1661   GdkWindow *window;
1662   POINT point, pointc;
1663   HWND hwnd, hwndc;
1664   RECT rect;
1665
1666   GetCursorPos (&pointc);
1667   point = pointc;
1668   hwnd = WindowFromPoint (point);
1669
1670   if (hwnd == NULL)
1671     {
1672       window = gdk_parent_root;
1673       if (win_x)
1674         *win_x = pointc.x;
1675       if (win_y)
1676         *win_y = pointc.y;
1677       return window;
1678     }
1679       
1680   ScreenToClient (hwnd, &point);
1681
1682   do {
1683     hwndc = ChildWindowFromPoint (hwnd, point);
1684     ClientToScreen (hwnd, &point);
1685     ScreenToClient (hwndc, &point);
1686   } while (hwndc != hwnd && (hwnd = hwndc, 1));
1687
1688   window = gdk_window_lookup (hwnd);
1689
1690   if (window && (win_x || win_y))
1691     {
1692       GetClientRect (hwnd, &rect);
1693       if (win_x)
1694         *win_x = point.x - rect.left;
1695       if (win_y)
1696         *win_y = point.y - rect.top;
1697     }
1698
1699   GDK_NOTE (MISC, g_print ("gdk_window_at_pointer: +%d+%d %#x%s\n",
1700                            point.x, point.y, hwnd,
1701                            (window == NULL ? " NULL" : "")));
1702
1703   return window;
1704 }
1705
1706 GList*
1707 gdk_window_get_children (GdkWindow *window)
1708 {
1709   GdkWindowPrivate *private;
1710   GList *children;
1711
1712   g_return_val_if_fail (window != NULL, NULL);
1713   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1714
1715   if (GDK_DRAWABLE_DESTROYED (window))
1716     return NULL;
1717
1718   /* XXX ??? */
1719   g_warning ("gdk_window_get_children not implemented");
1720   children = NULL;
1721
1722   return children;
1723 }
1724
1725 GdkEventMask  
1726 gdk_window_get_events (GdkWindow *window)
1727 {
1728   g_return_val_if_fail (window != NULL, 0);
1729   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1730
1731   if (GDK_DRAWABLE_DESTROYED (window))
1732     return 0;
1733
1734   return GDK_WINDOW_WIN32DATA (window)->event_mask;
1735 }
1736
1737 void          
1738 gdk_window_set_events (GdkWindow   *window,
1739                        GdkEventMask event_mask)
1740 {
1741   g_return_if_fail (window != NULL);
1742   g_return_if_fail (GDK_IS_WINDOW (window));
1743
1744   if (GDK_DRAWABLE_DESTROYED (window))
1745     return;
1746
1747   GDK_WINDOW_WIN32DATA (window)->event_mask = event_mask;
1748 }
1749
1750 void
1751 gdk_window_add_colormap_windows (GdkWindow *window)
1752 {
1753   g_warning ("gdk_window_add_colormap_windows not implemented");
1754 }
1755
1756 void
1757 gdk_window_shape_combine_mask (GdkWindow *window,
1758                                GdkBitmap *mask,
1759                                gint x, gint y)
1760 {
1761   g_return_if_fail (window != NULL);
1762   g_return_if_fail (GDK_IS_WINDOW (window));
1763
1764   if (!mask)
1765     {
1766       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x none\n",
1767                                GDK_DRAWABLE_XID (window)));
1768       SetWindowRgn (GDK_DRAWABLE_XID (window), NULL, TRUE);
1769     }
1770   else
1771     {
1772       HRGN hrgn;
1773       DWORD dwStyle;
1774       DWORD dwExStyle;
1775       RECT rect;
1776
1777       /* Convert mask bitmap to region */
1778       hrgn = BitmapToRegion (GDK_DRAWABLE_XID (mask));
1779
1780       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x %#x\n",
1781                                GDK_DRAWABLE_XID (window),
1782                                GDK_DRAWABLE_XID (mask)));
1783
1784       /* SetWindowRgn wants window (not client) coordinates */ 
1785       dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
1786       dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
1787       GetClientRect (GDK_DRAWABLE_XID (window), &rect);
1788       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1789       OffsetRgn (hrgn, -rect.left, -rect.top);
1790
1791       OffsetRgn (hrgn, x, y);
1792
1793       /* If this is a top-level window, add the title bar to the region */
1794       if (GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_TOPLEVEL)
1795         {
1796           CombineRgn (hrgn, hrgn,
1797                       CreateRectRgn (0, 0, rect.right - rect.left, -rect.top),
1798                       RGN_OR);
1799         }
1800       
1801       SetWindowRgn (GDK_DRAWABLE_XID (window), hrgn, TRUE);
1802     }
1803 }
1804
1805 void
1806 gdk_window_set_override_redirect (GdkWindow *window,
1807                                   gboolean   override_redirect)
1808 {
1809   g_return_if_fail (window != NULL);
1810   g_return_if_fail (GDK_IS_WINDOW (window));
1811
1812   g_warning ("gdk_window_set_override_redirect not implemented");
1813 }
1814
1815 void          
1816 gdk_window_set_icon (GdkWindow *window, 
1817                      GdkWindow *icon_window,
1818                      GdkPixmap *pixmap,
1819                      GdkBitmap *mask)
1820 {
1821   g_return_if_fail (window != NULL);
1822   g_return_if_fail (GDK_IS_WINDOW (window));
1823
1824   if (GDK_DRAWABLE_DESTROYED (window))
1825     return;
1826   
1827   g_warning ("gdk_window_set_icon not implemented");
1828 }
1829
1830 void
1831 gdk_window_set_icon_name (GdkWindow *window, 
1832                           gchar     *name)
1833 {
1834   g_return_if_fail (window != NULL);
1835   g_return_if_fail (GDK_IS_WINDOW (window));
1836
1837   if (GDK_DRAWABLE_DESTROYED (window))
1838     return;
1839   
1840   if (!SetWindowText (GDK_DRAWABLE_XID (window), name))
1841     g_warning ("gdk_window_set_icon_name: SetWindowText failed");
1842 }
1843
1844 void          
1845 gdk_window_set_group (GdkWindow *window, 
1846                       GdkWindow *leader)
1847 {
1848   g_return_if_fail (window != NULL);
1849   g_return_if_fail (GDK_IS_WINDOW (window));
1850   g_return_if_fail (leader != NULL);
1851   g_return_if_fail (GDK_IS_WINDOW (leader));
1852
1853   if (GDK_DRAWABLE_DESTROYED (window) || GDK_DRAWABLE_DESTROYED (leader))
1854     return;
1855   
1856   g_warning ("gdk_window_set_group not implemented");
1857 }
1858
1859 void
1860 gdk_window_set_decorations (GdkWindow      *window,
1861                             GdkWMDecoration decorations)
1862 {
1863   LONG style, exstyle;
1864
1865   g_return_if_fail (window != NULL);
1866   g_return_if_fail (GDK_IS_WINDOW (window));
1867   
1868   style = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
1869   exstyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
1870
1871   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
1872             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE);
1873
1874   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
1875
1876   if (decorations & GDK_DECOR_ALL)
1877     style |= (WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
1878   if (decorations & GDK_DECOR_BORDER)
1879     style |= (WS_BORDER);
1880   if (decorations & GDK_DECOR_RESIZEH)
1881     style |= (WS_THICKFRAME);
1882   if (decorations & GDK_DECOR_TITLE)
1883     style |= (WS_CAPTION);
1884   if (decorations & GDK_DECOR_MENU)
1885     style |= (WS_SYSMENU);
1886   if (decorations & GDK_DECOR_MINIMIZE)
1887     style |= (WS_MINIMIZEBOX);
1888   if (decorations & GDK_DECOR_MAXIMIZE)
1889     style |= (WS_MAXIMIZEBOX);
1890   
1891   SetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE, style);
1892 }
1893
1894 void
1895 gdk_window_set_functions (GdkWindow    *window,
1896                           GdkWMFunction functions)
1897 {
1898   LONG style, exstyle;
1899
1900   g_return_if_fail (window != NULL);
1901   g_return_if_fail (GDK_IS_WINDOW (window));
1902   
1903   style = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
1904   exstyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
1905
1906   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
1907             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE|WS_CAPTION|WS_BORDER
1908             |WS_SYSMENU);
1909
1910   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
1911
1912   if (functions & GDK_FUNC_ALL)
1913     style |= (WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
1914   if (functions & GDK_FUNC_RESIZE)
1915     style |= (WS_THICKFRAME);
1916   if (functions & GDK_FUNC_MOVE)
1917     style |= (WS_THICKFRAME);
1918   if (functions & GDK_FUNC_MINIMIZE)
1919     style |= (WS_MINIMIZEBOX);
1920   if (functions & GDK_FUNC_MAXIMIZE)
1921     style |= (WS_MAXIMIZEBOX);
1922   
1923   SetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE, style);
1924 }
1925
1926 /* 
1927  * propagate the shapes from all child windows of a GDK window to the parent 
1928  * window. Shamelessly ripped from Enlightenment's code
1929  * 
1930  * - Raster
1931  */
1932
1933 static void
1934 QueryTree (HWND hwnd,
1935            HWND **children,
1936            gint *nchildren)
1937 {
1938   guint i, n;
1939   HWND child;
1940
1941   n = 0;
1942   do {
1943     if (n == 0)
1944       child = GetWindow (hwnd, GW_CHILD);
1945     else
1946       child = GetWindow (child, GW_HWNDNEXT);
1947     if (child != NULL)
1948       n++;
1949   } while (child != NULL);
1950
1951   if (n > 0)
1952     {
1953       *children = g_new (HWND, n);
1954       for (i = 0; i < n; i++)
1955         {
1956           if (i == 0)
1957             child = GetWindow (hwnd, GW_CHILD);
1958           else
1959             child = GetWindow (child, GW_HWNDNEXT);
1960           *children[i] = child;
1961         }
1962     }
1963 }
1964
1965 static void
1966 gdk_propagate_shapes (HANDLE   win,
1967                       gboolean merge)
1968 {
1969    RECT emptyRect;
1970    HRGN region, childRegion;
1971    RECT rect;
1972    HWND *list = NULL;
1973    gint i, num;
1974
1975    SetRectEmpty (&emptyRect);
1976    region = CreateRectRgnIndirect (&emptyRect);
1977    if (merge)
1978      GetWindowRgn (win, region);
1979    
1980    QueryTree (win, &list, &num);
1981    if (list != NULL)
1982      {
1983        WINDOWPLACEMENT placement;
1984
1985        placement.length = sizeof (WINDOWPLACEMENT);
1986        /* go through all child windows and combine regions */
1987        for (i = 0; i < num; i++)
1988          {
1989            GetWindowPlacement (list[i], &placement);
1990            if (placement.showCmd = SW_SHOWNORMAL)
1991              {
1992                childRegion = CreateRectRgnIndirect (&emptyRect);
1993                GetWindowRgn (list[i], childRegion);
1994                CombineRgn (region, region, childRegion, RGN_OR);
1995                DeleteObject (childRegion);
1996              }
1997           }
1998        SetWindowRgn (win, region, TRUE);
1999      }
2000    else
2001      DeleteObject (region);
2002 }
2003
2004 void
2005 gdk_window_set_child_shapes (GdkWindow *window)
2006 {
2007   g_return_if_fail (window != NULL);
2008   g_return_if_fail (GDK_IS_WINDOW (window));
2009    
2010   if (GDK_DRAWABLE_DESTROYED (window))
2011     return;
2012
2013   gdk_propagate_shapes (GDK_DRAWABLE_XID (window), FALSE);
2014 }
2015
2016 void
2017 gdk_window_merge_child_shapes (GdkWindow *window)
2018 {
2019   g_return_if_fail (window != NULL);
2020   g_return_if_fail (GDK_IS_WINDOW (window));
2021   
2022   if (GDK_DRAWABLE_DESTROYED (window))
2023     return;
2024
2025   gdk_propagate_shapes (GDK_DRAWABLE_XID (window), TRUE);
2026 }
2027
2028 /* Support for windows that can be guffaw-scrolled
2029  * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
2030  */
2031
2032 static gboolean
2033 gdk_window_gravity_works (void)
2034 {
2035   enum { UNKNOWN, NO, YES };
2036   static gint gravity_works = UNKNOWN;
2037   
2038   if (gravity_works == UNKNOWN)
2039     {
2040       GdkWindowAttr attr;
2041       GdkWindow *parent;
2042       GdkWindow *child;
2043       gint y;
2044       
2045       attr.window_type = GDK_WINDOW_TEMP;
2046       attr.wclass = GDK_INPUT_OUTPUT;
2047       attr.x = 0;
2048       attr.y = 0;
2049       attr.width = 100;
2050       attr.height = 100;
2051       attr.event_mask = 0;
2052       
2053       parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
2054       
2055       attr.window_type = GDK_WINDOW_CHILD;
2056       child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
2057       
2058       gdk_window_set_static_win_gravity (child, TRUE);
2059       
2060       gdk_window_resize (parent, 100, 110);
2061       gdk_window_move (parent, 0, -10);
2062       gdk_window_move_resize (parent, 0, 0, 100, 100);
2063       
2064       gdk_window_resize (parent, 100, 110);
2065       gdk_window_move (parent, 0, -10);
2066       gdk_window_move_resize (parent, 0, 0, 100, 100);
2067       
2068       gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
2069       
2070       gdk_window_destroy (parent);
2071       gdk_window_destroy (child);
2072       
2073       gravity_works = ((y == -20) ? YES : NO);
2074     }
2075   
2076   return (gravity_works == YES);
2077 }
2078
2079 static void
2080 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
2081 {
2082   g_return_if_fail (window != NULL);
2083
2084   GDK_NOTE (MISC, g_print ("gdk_window_set_static_bit_gravity: Not implemented\n"));
2085 }
2086
2087 static void
2088 gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
2089 {
2090   g_return_if_fail (window != NULL);
2091
2092   GDK_NOTE (MISC,
2093             g_print ("gdk_window_set_static_win_gravity: Not implemented\n"));
2094 }
2095
2096 /*************************************************************
2097  * gdk_window_set_static_gravities:
2098  *     Set the bit gravity of the given window to static,
2099  *     and flag it so all children get static subwindow
2100  *     gravity.
2101  *   arguments:
2102  *     window: window for which to set static gravity
2103  *     use_static: Whether to turn static gravity on or off.
2104  *   results:
2105  *     Does the XServer support static gravity?
2106  *************************************************************/
2107
2108 gboolean 
2109 gdk_window_set_static_gravities (GdkWindow *window,
2110                                  gboolean   use_static)
2111 {
2112   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2113   GList *tmp_list;
2114   
2115   g_return_val_if_fail (window != NULL, FALSE);
2116   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2117
2118   if (!use_static == !private->guffaw_gravity)
2119     return TRUE;
2120   
2121   if (use_static && !gdk_window_gravity_works ())
2122     return FALSE;
2123   
2124   private->guffaw_gravity = use_static;
2125   
2126   if (!GDK_DRAWABLE_DESTROYED (window))
2127     {
2128       gdk_window_set_static_bit_gravity (window, use_static);
2129       
2130       tmp_list = private->children;
2131       while (tmp_list)
2132         {
2133           gdk_window_set_static_win_gravity (window, use_static);
2134           
2135           tmp_list = tmp_list->next;
2136         }
2137     }
2138   
2139   return TRUE;
2140 }