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