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