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