]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow-win32.c
6ca5b2c52f182fcd22b17a8b5a2e839703bdbe95
[~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   /* Empty window titles not allowed, so set it to just a period. */
1374   if (!title[0])
1375     title = ".";
1376   
1377   GDK_NOTE (MISC, g_print ("gdk_window_set_title: %#x %s\n",
1378                            GDK_WINDOW_HWND (window), title));
1379   
1380   if (!GDK_WINDOW_DESTROYED (window))
1381     {
1382       /* As the title is in UTF-8 we must translate it
1383        * to the system codepage.
1384        */
1385       titlelen = strlen (title);
1386       wcstr = g_new (wchar_t, titlelen + 1);
1387       mbstr = g_new (char, 3*titlelen + 1);
1388       wlen = gdk_nmbstowchar_ts (wcstr, title, titlelen, titlelen);
1389       wcstr[wlen] = 0;
1390       WideCharToMultiByte (GetACP (), 0, wcstr, -1,
1391                            mbstr, 3*titlelen, NULL, NULL);
1392
1393       if (!SetWindowText (GDK_WINDOW_HWND (window), mbstr))
1394         WIN32_API_FAILED ("SetWindowText");
1395
1396       g_free (mbstr);
1397       g_free (wcstr);
1398     }
1399 }
1400
1401 void          
1402 gdk_window_set_role (GdkWindow   *window,
1403                      const gchar *role)
1404 {
1405   g_return_if_fail (window != NULL);
1406   g_return_if_fail (GDK_IS_WINDOW (window));
1407   
1408   GDK_NOTE (MISC, g_print ("gdk_window_set_role: %#x %s\n",
1409                            GDK_WINDOW_HWND (window), (role ? role : "NULL")));
1410   /* XXX */
1411 }
1412
1413 void          
1414 gdk_window_set_transient_for (GdkWindow *window, 
1415                               GdkWindow *parent)
1416 {
1417   g_return_if_fail (window != NULL);
1418   g_return_if_fail (GDK_IS_WINDOW (window));
1419   
1420   GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %#x %#x\n",
1421                            GDK_WINDOW_HWND (window),
1422                            GDK_WINDOW_HWND (parent)));
1423   /* XXX */
1424 }
1425
1426 void
1427 gdk_window_set_background (GdkWindow *window,
1428                            GdkColor  *color)
1429 {
1430   GdkWindowObject *private = (GdkWindowObject *)window;
1431   
1432   g_return_if_fail (window != NULL);
1433   g_return_if_fail (GDK_IS_WINDOW (window));
1434   
1435   GDK_NOTE (MISC, g_print ("gdk_window_set_background: %#x %s\n",
1436                            GDK_WINDOW_HWND (window), 
1437                            gdk_win32_color_to_string (color)));
1438
1439   private->bg_color = *color;
1440
1441   if (private->bg_pixmap &&
1442       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1443       private->bg_pixmap != GDK_NO_BG)
1444     {
1445       gdk_drawable_unref (private->bg_pixmap);
1446       private->bg_pixmap = NULL;
1447     }
1448 }
1449
1450 void
1451 gdk_window_set_back_pixmap (GdkWindow *window,
1452                             GdkPixmap *pixmap,
1453                             gint       parent_relative)
1454 {
1455   GdkWindowObject *private = (GdkWindowObject *)window;
1456
1457   g_return_if_fail (window != NULL);
1458   g_return_if_fail (GDK_IS_WINDOW (window));
1459   g_return_if_fail (pixmap == NULL || !parent_relative);
1460   
1461   if (private->bg_pixmap &&
1462       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1463       private->bg_pixmap != GDK_NO_BG)
1464     gdk_drawable_unref (private->bg_pixmap);
1465
1466   if (parent_relative)
1467     {
1468       private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
1469     }
1470   else
1471     {
1472       if (pixmap)
1473         {
1474           gdk_drawable_ref (pixmap);
1475           private->bg_pixmap = pixmap;
1476         }
1477       else
1478         {
1479           private->bg_pixmap = GDK_NO_BG;
1480         }
1481     }
1482 }
1483
1484 void
1485 gdk_window_set_cursor (GdkWindow *window,
1486                        GdkCursor *cursor)
1487 {
1488   GdkWindowImplWin32 *impl;
1489   GdkCursorPrivate *cursor_private;
1490   HCURSOR hcursor;
1491   POINT pt;
1492   
1493   g_return_if_fail (window != NULL);
1494   g_return_if_fail (GDK_IS_WINDOW (window));
1495   
1496   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1497   cursor_private = (GdkCursorPrivate*) cursor;
1498   
1499   if (!GDK_WINDOW_DESTROYED (window))
1500     {
1501       if (!cursor)
1502         hcursor = NULL;
1503       else
1504         hcursor = cursor_private->hcursor;
1505
1506       GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %#x %#x\n",
1507                                GDK_WINDOW_HWND (window), hcursor));
1508       if (impl->hcursor != NULL)
1509         {
1510           GDK_NOTE (MISC, g_print ("...DestroyCursor (%#x)\n", impl->hcursor));
1511           
1512           DestroyCursor (impl->hcursor);
1513           impl->hcursor = NULL;
1514         }
1515       if (hcursor != NULL)
1516         {
1517           /* We must copy the cursor as it is OK to destroy the GdkCursor
1518            * while still in use for some window. See for instance
1519            * gimp_change_win_cursor() which calls
1520            * gdk_window_set_cursor (win, cursor), and immediately
1521            * afterwards gdk_cursor_destroy (cursor).
1522            */
1523           impl->hcursor = CopyCursor (hcursor);
1524           GDK_NOTE (MISC, g_print ("...CopyCursor (%#x) = %#x\n",
1525                                    hcursor, impl->hcursor));
1526
1527           GetCursorPos (&pt);
1528           if (ChildWindowFromPoint (GDK_WINDOW_HWND (window), pt) == GDK_WINDOW_HWND (window))
1529             SetCursor (impl->hcursor);
1530         }
1531     }
1532 }
1533
1534 void
1535 gdk_window_get_geometry (GdkWindow *window,
1536                          gint      *x,
1537                          gint      *y,
1538                          gint      *width,
1539                          gint      *height,
1540                          gint      *depth)
1541 {
1542   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1543   
1544   if (!window)
1545     window = gdk_parent_root;
1546   
1547   if (!GDK_WINDOW_DESTROYED (window))
1548     {
1549       RECT rect;
1550
1551       if (!GetClientRect (GDK_WINDOW_HWND (window), &rect))
1552         WIN32_API_FAILED ("GetClientRect");
1553
1554       if (x)
1555         *x = rect.left;
1556       if (y)
1557         *y = rect.top;
1558       if (width)
1559         *width = rect.right - rect.left;
1560       if (height)
1561         *height = rect.bottom - rect.top;
1562       if (depth)
1563         *depth = gdk_drawable_get_visual (window)->depth;
1564     }
1565 }
1566
1567 gint
1568 gdk_window_get_origin (GdkWindow *window,
1569                        gint      *x,
1570                        gint      *y)
1571 {
1572   gint return_val;
1573   gint tx = 0;
1574   gint ty = 0;
1575
1576   g_return_val_if_fail (window != NULL, 0);
1577
1578   if (!GDK_WINDOW_DESTROYED (window))
1579     {
1580       POINT pt;
1581
1582       pt.x = 0;
1583       pt.y = 0;
1584       ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1585       tx = pt.x;
1586       ty = pt.y;
1587       return_val = 1;
1588     }
1589   else
1590     return_val = 0;
1591   
1592   if (x)
1593     *x = tx;
1594   if (y)
1595     *y = ty;
1596
1597   GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %#x: +%d+%d\n",
1598                            GDK_WINDOW_HWND (window), tx, ty));
1599   return return_val;
1600 }
1601
1602 gboolean
1603 gdk_window_get_deskrelative_origin (GdkWindow *window,
1604                                     gint      *x,
1605                                     gint      *y)
1606 {
1607   return gdk_window_get_origin (window, x, y);
1608 }
1609
1610 void
1611 gdk_window_get_root_origin (GdkWindow *window,
1612                             gint      *x,
1613                             gint      *y)
1614 {
1615   GdkWindowObject *rover;
1616   POINT pt;
1617
1618   g_return_if_fail (window != NULL);
1619   g_return_if_fail (GDK_IS_WINDOW (window));
1620
1621   rover = (GdkWindowObject*) window;
1622   if (x)
1623     *x = 0;
1624   if (y)
1625     *y = 0;
1626
1627   if (GDK_WINDOW_DESTROYED (window))
1628     return;
1629       
1630   while (rover->parent && ((GdkWindowObject*) rover->parent)->parent)
1631     rover = (GdkWindowObject *) rover->parent;
1632   if (rover->destroyed)
1633     return;
1634
1635   pt.x = 0;
1636   pt.y = 0;
1637   ClientToScreen (GDK_WINDOW_HWND (rover), &pt);
1638   if (x)
1639     *x = pt.x;
1640   if (y)
1641     *y = pt.y;
1642
1643   GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %#x: (%#x) +%d+%d\n",
1644                            GDK_WINDOW_HWND (window),
1645                            GDK_WINDOW_HWND (rover), pt.x, pt.y));
1646 }
1647
1648 GdkWindow*
1649 gdk_window_get_pointer (GdkWindow       *window,
1650                         gint            *x,
1651                         gint            *y,
1652                         GdkModifierType *mask)
1653 {
1654   GdkWindow *return_val;
1655   POINT pointc, point;
1656   HWND hwnd, hwndc;
1657
1658   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1659   
1660   if (!window)
1661     window = gdk_parent_root;
1662
1663   return_val = NULL;
1664   GetCursorPos (&pointc);
1665   point = pointc;
1666   ScreenToClient (GDK_WINDOW_HWND (window), &point);
1667
1668   if (x)
1669     *x = point.x;
1670   if (y)
1671     *y = point.y;
1672
1673   hwnd = WindowFromPoint (point);
1674   point = pointc;
1675   ScreenToClient (hwnd, &point);
1676   
1677   do {
1678     hwndc = ChildWindowFromPoint (hwnd, point);
1679     ClientToScreen (hwnd, &point);
1680     ScreenToClient (hwndc, &point);
1681   } while (hwndc != hwnd && (hwnd = hwndc, 1)); /* Ouch! */
1682
1683   return_val = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
1684
1685   if (mask)
1686     {
1687       BYTE kbd[256];
1688
1689       GetKeyboardState (kbd);
1690       *mask = 0;
1691       if (kbd[VK_SHIFT] & 0x80)
1692         *mask |= GDK_SHIFT_MASK;
1693       if (kbd[VK_CAPITAL] & 0x80)
1694         *mask |= GDK_LOCK_MASK;
1695       if (kbd[VK_CONTROL] & 0x80)
1696         *mask |= GDK_CONTROL_MASK;
1697       if (kbd[VK_MENU] & 0x80)
1698         *mask |= GDK_MOD1_MASK;
1699       if (kbd[VK_LBUTTON] & 0x80)
1700         *mask |= GDK_BUTTON1_MASK;
1701       if (kbd[VK_MBUTTON] & 0x80)
1702         *mask |= GDK_BUTTON2_MASK;
1703       if (kbd[VK_RBUTTON] & 0x80)
1704         *mask |= GDK_BUTTON3_MASK;
1705     }
1706   
1707   return return_val;
1708 }
1709
1710 GdkWindow*
1711 gdk_window_at_pointer (gint *win_x,
1712                        gint *win_y)
1713 {
1714   GdkWindow *window;
1715   POINT point, pointc;
1716   HWND hwnd, hwndc;
1717   RECT rect;
1718
1719   GetCursorPos (&pointc);
1720   point = pointc;
1721   hwnd = WindowFromPoint (point);
1722
1723   if (hwnd == NULL)
1724     {
1725       window = gdk_parent_root;
1726       if (win_x)
1727         *win_x = pointc.x;
1728       if (win_y)
1729         *win_y = pointc.y;
1730       return window;
1731     }
1732       
1733   ScreenToClient (hwnd, &point);
1734
1735   do {
1736     hwndc = ChildWindowFromPoint (hwnd, point);
1737     ClientToScreen (hwnd, &point);
1738     ScreenToClient (hwndc, &point);
1739   } while (hwndc != hwnd && (hwnd = hwndc, 1));
1740
1741   window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
1742
1743   if (window && (win_x || win_y))
1744     {
1745       GetClientRect (hwnd, &rect);
1746       if (win_x)
1747         *win_x = point.x - rect.left;
1748       if (win_y)
1749         *win_y = point.y - rect.top;
1750     }
1751
1752   GDK_NOTE (MISC, g_print ("gdk_window_at_pointer: +%d+%d %#x%s\n",
1753                            point.x, point.y, hwnd,
1754                            (window == NULL ? " NULL" : "")));
1755
1756   return window;
1757 }
1758
1759 GdkEventMask  
1760 gdk_window_get_events (GdkWindow *window)
1761 {
1762   g_return_val_if_fail (window != NULL, 0);
1763   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1764
1765   if (GDK_WINDOW_DESTROYED (window))
1766     return 0;
1767
1768   return GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl)->event_mask;
1769 }
1770
1771 void          
1772 gdk_window_set_events (GdkWindow   *window,
1773                        GdkEventMask event_mask)
1774 {
1775   g_return_if_fail (window != NULL);
1776   g_return_if_fail (GDK_IS_WINDOW (window));
1777
1778   if (GDK_WINDOW_DESTROYED (window))
1779     return;
1780
1781   GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl)->event_mask = event_mask;
1782 }
1783
1784 void
1785 gdk_window_shape_combine_mask (GdkWindow *window,
1786                                GdkBitmap *mask,
1787                                gint x, gint y)
1788 {
1789   g_return_if_fail (window != NULL);
1790   g_return_if_fail (GDK_IS_WINDOW (window));
1791
1792   if (!mask)
1793     {
1794       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x none\n",
1795                                GDK_WINDOW_HWND (window)));
1796       SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
1797     }
1798   else
1799     {
1800       HRGN hrgn;
1801       DWORD dwStyle;
1802       DWORD dwExStyle;
1803       RECT rect;
1804
1805       /* Convert mask bitmap to region */
1806       hrgn = BitmapToRegion (GDK_WINDOW_HWND (mask));
1807
1808       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x %#x\n",
1809                                GDK_WINDOW_HWND (window),
1810                                GDK_WINDOW_HWND (mask)));
1811
1812       /* SetWindowRgn wants window (not client) coordinates */ 
1813       dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1814       dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1815       GetClientRect (GDK_WINDOW_HWND (window), &rect);
1816       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1817       OffsetRgn (hrgn, -rect.left, -rect.top);
1818
1819       OffsetRgn (hrgn, x, y);
1820
1821       /* If this is a top-level window, add the title bar to the region */
1822       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
1823         {
1824           CombineRgn (hrgn, hrgn,
1825                       CreateRectRgn (0, 0, rect.right - rect.left, -rect.top),
1826                       RGN_OR);
1827         }
1828       
1829       SetWindowRgn (GDK_WINDOW_HWND (window), hrgn, TRUE);
1830     }
1831 }
1832
1833 void
1834 gdk_window_set_override_redirect (GdkWindow *window,
1835                                   gboolean   override_redirect)
1836 {
1837   g_return_if_fail (window != NULL);
1838   g_return_if_fail (GDK_IS_WINDOW (window));
1839
1840   g_warning ("gdk_window_set_override_redirect not implemented");
1841 }
1842
1843 void          
1844 gdk_window_set_icon (GdkWindow *window, 
1845                      GdkWindow *icon_window,
1846                      GdkPixmap *pixmap,
1847                      GdkBitmap *mask)
1848 {
1849   g_return_if_fail (window != NULL);
1850   g_return_if_fail (GDK_IS_WINDOW (window));
1851
1852   if (GDK_WINDOW_DESTROYED (window))
1853     return;
1854   
1855   /* Nothing to do, really. As we share window classes between windows
1856    * we can't have window-specific icons, sorry. Don't print any warning
1857    * either.
1858    */
1859 }
1860
1861 void
1862 gdk_window_set_icon_name (GdkWindow   *window, 
1863                           const gchar *name)
1864 {
1865   g_return_if_fail (window != NULL);
1866   g_return_if_fail (GDK_IS_WINDOW (window));
1867
1868   if (GDK_WINDOW_DESTROYED (window))
1869     return;
1870   
1871   if (!SetWindowText (GDK_WINDOW_HWND (window), name))
1872     WIN32_API_FAILED ("SetWindowText");
1873 }
1874
1875 void          
1876 gdk_window_set_group (GdkWindow *window, 
1877                       GdkWindow *leader)
1878 {
1879   g_return_if_fail (window != NULL);
1880   g_return_if_fail (GDK_IS_WINDOW (window));
1881   g_return_if_fail (leader != NULL);
1882   g_return_if_fail (GDK_IS_WINDOW (leader));
1883
1884   if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
1885     return;
1886   
1887   g_warning ("gdk_window_set_group not implemented");
1888 }
1889
1890 void
1891 gdk_window_set_decorations (GdkWindow      *window,
1892                             GdkWMDecoration decorations)
1893 {
1894   LONG style, exstyle;
1895
1896   g_return_if_fail (window != NULL);
1897   g_return_if_fail (GDK_IS_WINDOW (window));
1898   
1899   style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1900   exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1901
1902   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
1903             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE);
1904
1905   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
1906
1907   if (decorations & GDK_DECOR_ALL)
1908     style |= (WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
1909   if (decorations & GDK_DECOR_BORDER)
1910     style |= (WS_BORDER);
1911   if (decorations & GDK_DECOR_RESIZEH)
1912     style |= (WS_THICKFRAME);
1913   if (decorations & GDK_DECOR_TITLE)
1914     style |= (WS_CAPTION);
1915   if (decorations & GDK_DECOR_MENU)
1916     style |= (WS_SYSMENU);
1917   if (decorations & GDK_DECOR_MINIMIZE)
1918     style |= (WS_MINIMIZEBOX);
1919   if (decorations & GDK_DECOR_MAXIMIZE)
1920     style |= (WS_MAXIMIZEBOX);
1921   
1922   SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
1923 }
1924
1925 void
1926 gdk_window_set_functions (GdkWindow    *window,
1927                           GdkWMFunction functions)
1928 {
1929   LONG style, exstyle;
1930
1931   g_return_if_fail (window != NULL);
1932   g_return_if_fail (GDK_IS_WINDOW (window));
1933   
1934   style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1935   exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1936
1937   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
1938             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE|WS_CAPTION|WS_BORDER
1939             |WS_SYSMENU);
1940
1941   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
1942
1943   if (functions & GDK_FUNC_ALL)
1944     style |= (WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
1945   if (functions & GDK_FUNC_RESIZE)
1946     style |= (WS_THICKFRAME);
1947   if (functions & GDK_FUNC_MOVE)
1948     style |= (WS_THICKFRAME);
1949   if (functions & GDK_FUNC_MINIMIZE)
1950     style |= (WS_MINIMIZEBOX);
1951   if (functions & GDK_FUNC_MAXIMIZE)
1952     style |= (WS_MAXIMIZEBOX);
1953   
1954   SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
1955 }
1956
1957 /* 
1958  * propagate the shapes from all child windows of a GDK window to the parent 
1959  * window. Shamelessly ripped from Enlightenment's code
1960  * 
1961  * - Raster
1962  */
1963
1964 static void
1965 QueryTree (HWND hwnd,
1966            HWND **children,
1967            gint *nchildren)
1968 {
1969   guint i, n;
1970   HWND child;
1971
1972   n = 0;
1973   do {
1974     if (n == 0)
1975       child = GetWindow (hwnd, GW_CHILD);
1976     else
1977       child = GetWindow (child, GW_HWNDNEXT);
1978     if (child != NULL)
1979       n++;
1980   } while (child != NULL);
1981
1982   if (n > 0)
1983     {
1984       *children = g_new (HWND, n);
1985       for (i = 0; i < n; i++)
1986         {
1987           if (i == 0)
1988             child = GetWindow (hwnd, GW_CHILD);
1989           else
1990             child = GetWindow (child, GW_HWNDNEXT);
1991           *children[i] = child;
1992         }
1993     }
1994 }
1995
1996 static void
1997 gdk_propagate_shapes (HANDLE   win,
1998                       gboolean merge)
1999 {
2000    RECT emptyRect;
2001    HRGN region, childRegion;
2002    RECT rect;
2003    HWND *list = NULL;
2004    gint i, num;
2005
2006    SetRectEmpty (&emptyRect);
2007    region = CreateRectRgnIndirect (&emptyRect);
2008    if (merge)
2009      GetWindowRgn (win, region);
2010    
2011    QueryTree (win, &list, &num);
2012    if (list != NULL)
2013      {
2014        WINDOWPLACEMENT placement;
2015
2016        placement.length = sizeof (WINDOWPLACEMENT);
2017        /* go through all child windows and combine regions */
2018        for (i = 0; i < num; i++)
2019          {
2020            GetWindowPlacement (list[i], &placement);
2021            if (placement.showCmd == SW_SHOWNORMAL)
2022              {
2023                childRegion = CreateRectRgnIndirect (&emptyRect);
2024                GetWindowRgn (list[i], childRegion);
2025                CombineRgn (region, region, childRegion, RGN_OR);
2026                DeleteObject (childRegion);
2027              }
2028           }
2029        SetWindowRgn (win, region, TRUE);
2030      }
2031    else
2032      DeleteObject (region);
2033 }
2034
2035 void
2036 gdk_window_set_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_WINDOW_DESTROYED (window))
2042     return;
2043
2044   gdk_propagate_shapes (GDK_WINDOW_HWND (window), FALSE);
2045 }
2046
2047 void
2048 gdk_window_merge_child_shapes (GdkWindow *window)
2049 {
2050   g_return_if_fail (window != NULL);
2051   g_return_if_fail (GDK_IS_WINDOW (window));
2052   
2053   if (GDK_WINDOW_DESTROYED (window))
2054     return;
2055
2056   gdk_propagate_shapes (GDK_WINDOW_HWND (window), TRUE);
2057 }
2058
2059 /* Support for windows that can be guffaw-scrolled
2060  * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
2061  */
2062
2063 static gboolean
2064 gdk_window_gravity_works (void)
2065 {
2066   enum { UNKNOWN, NO, YES };
2067   static gint gravity_works = UNKNOWN;
2068   
2069   if (gravity_works == UNKNOWN)
2070     {
2071       GdkWindowAttr attr;
2072       GdkWindow *parent;
2073       GdkWindow *child;
2074       gint y;
2075       
2076       attr.window_type = GDK_WINDOW_TEMP;
2077       attr.wclass = GDK_INPUT_OUTPUT;
2078       attr.x = 0;
2079       attr.y = 0;
2080       attr.width = 100;
2081       attr.height = 100;
2082       attr.event_mask = 0;
2083       
2084       parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
2085       
2086       attr.window_type = GDK_WINDOW_CHILD;
2087       child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
2088       
2089       gdk_window_set_static_win_gravity (child, TRUE);
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_resize (parent, 100, 110);
2096       gdk_window_move (parent, 0, -10);
2097       gdk_window_move_resize (parent, 0, 0, 100, 100);
2098       
2099       gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
2100       
2101       gdk_window_destroy (parent);
2102       gdk_window_destroy (child);
2103       
2104       gravity_works = ((y == -20) ? YES : NO);
2105     }
2106   
2107   return (gravity_works == YES);
2108 }
2109
2110 static void
2111 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
2112 {
2113   g_return_if_fail (window != NULL);
2114
2115   GDK_NOTE (MISC, g_print ("gdk_window_set_static_bit_gravity: Not implemented\n"));
2116 }
2117
2118 static void
2119 gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
2120 {
2121   g_return_if_fail (window != NULL);
2122
2123   GDK_NOTE (MISC,
2124             g_print ("gdk_window_set_static_win_gravity: Not implemented\n"));
2125 }
2126
2127 /*************************************************************
2128  * gdk_window_set_static_gravities:
2129  *     Set the bit gravity of the given window to static,
2130  *     and flag it so all children get static subwindow
2131  *     gravity.
2132  *   arguments:
2133  *     window: window for which to set static gravity
2134  *     use_static: Whether to turn static gravity on or off.
2135  *   results:
2136  *     Does the XServer support static gravity?
2137  *************************************************************/
2138
2139 gboolean 
2140 gdk_window_set_static_gravities (GdkWindow *window,
2141                                  gboolean   use_static)
2142 {
2143   GdkWindowObject *private = (GdkWindowObject *)window;
2144   GList *tmp_list;
2145   
2146   g_return_val_if_fail (window != NULL, FALSE);
2147   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2148
2149   if (!use_static == !private->guffaw_gravity)
2150     return TRUE;
2151   
2152   if (use_static && !gdk_window_gravity_works ())
2153     return FALSE;
2154   
2155   private->guffaw_gravity = use_static;
2156   
2157   if (!GDK_WINDOW_DESTROYED (window))
2158     {
2159       gdk_window_set_static_bit_gravity (window, use_static);
2160       
2161       tmp_list = private->children;
2162       while (tmp_list)
2163         {
2164           gdk_window_set_static_win_gravity (window, use_static);
2165           
2166           tmp_list = tmp_list->next;
2167         }
2168     }
2169   
2170   return TRUE;
2171 }