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