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