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