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