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