]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow-win32.c
Implement the functions that until now just were non-functional stubs. For
[~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->event_mask = 0;
95   impl->hcursor = NULL;
96   impl->hint_flags = 0;
97   impl->extension_events_selected = FALSE;
98 }
99
100 static void
101 gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
102 {
103   GObjectClass *object_class = G_OBJECT_CLASS (klass);
104   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
105   
106   parent_class = g_type_class_peek_parent (klass);
107
108   object_class->finalize = gdk_window_impl_win32_finalize;
109
110   drawable_class->set_colormap = gdk_window_impl_win32_set_colormap;
111   drawable_class->get_colormap = gdk_window_impl_win32_get_colormap;
112   drawable_class->get_size = gdk_window_impl_win32_get_size;
113
114   /* Visible and clip regions are the same */
115   drawable_class->get_clip_region = gdk_window_impl_win32_get_visible_region;
116   drawable_class->get_visible_region = gdk_window_impl_win32_get_visible_region;
117 }
118
119 static void
120 gdk_window_impl_win32_finalize (GObject *object)
121 {
122   GdkWindowObject *wrapper;
123   GdkDrawableImplWin32 *draw_impl;
124   GdkWindowImplWin32 *window_impl;
125   
126   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (object));
127
128   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (object);
129   window_impl = GDK_WINDOW_IMPL_WIN32 (object);
130   
131   wrapper = (GdkWindowObject*) draw_impl->wrapper;
132
133   if (!GDK_WINDOW_DESTROYED (wrapper))
134     {
135       gdk_win32_handle_table_remove (draw_impl->handle);
136     }
137
138   if (window_impl->hcursor != NULL)
139     {
140       if (GetCursor () == window_impl->hcursor)
141         SetCursor (NULL);
142       if (!DestroyCursor (window_impl->hcursor))
143         WIN32_GDI_FAILED("DestroyCursor");
144       window_impl->hcursor = NULL;
145     }
146
147   G_OBJECT_CLASS (parent_class)->finalize (object);
148 }
149
150 static GdkColormap*
151 gdk_window_impl_win32_get_colormap (GdkDrawable *drawable)
152 {
153   GdkDrawableImplWin32 *drawable_impl;
154   
155   g_return_val_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable), NULL);
156
157   drawable_impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
158
159   if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only && 
160       drawable_impl->colormap == NULL)
161     {
162       drawable_impl->colormap = gdk_colormap_get_system ();
163       gdk_colormap_ref (drawable_impl->colormap);
164     }
165   
166   return drawable_impl->colormap;
167 }
168
169 static void
170 gdk_window_impl_win32_set_colormap (GdkDrawable *drawable,
171                                     GdkColormap *cmap)
172 {
173   GdkWindowImplWin32 *impl;
174   GdkDrawableImplWin32 *draw_impl;
175   
176   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable));
177
178   impl = GDK_WINDOW_IMPL_WIN32 (drawable);
179   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
180
181   /* chain up */
182   GDK_DRAWABLE_CLASS (parent_class)->set_colormap (drawable, cmap);
183   
184   if (cmap)
185     {
186       /* XXX */
187       g_print("gdk_window_impl_win32_set_colormap: XXX\n");
188     }
189 }
190
191 static void
192 gdk_window_impl_win32_get_size (GdkDrawable *drawable,
193                                 gint        *width,
194                                 gint        *height)
195 {
196   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable));
197
198   if (width)
199     *width = GDK_WINDOW_IMPL_WIN32 (drawable)->width;
200   if (height)
201     *height = GDK_WINDOW_IMPL_WIN32 (drawable)->height;
202 }
203
204 static GdkRegion*
205 gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable)
206 {
207   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (drawable);
208   GdkRectangle result_rect;
209
210   result_rect.x = 0;
211   result_rect.y = 0;
212   result_rect.width = impl->width;
213   result_rect.height = impl->height;
214
215   gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
216
217   return gdk_region_rectangle (&result_rect);
218 }
219
220 void
221 _gdk_windowing_window_init (void)
222 {
223   GdkWindowObject *private;
224   GdkWindowImplWin32 *impl;
225   GdkDrawableImplWin32 *draw_impl;
226   RECT rect;
227   guint width;
228   guint height;
229
230   g_assert (_gdk_parent_root == NULL);
231   
232   SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
233   width  = rect.right - rect.left;
234   height = rect.bottom - rect.top;
235
236   _gdk_parent_root = g_object_new (GDK_TYPE_WINDOW, NULL);
237   private = (GdkWindowObject *)_gdk_parent_root;
238   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
239   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
240   
241   draw_impl->handle = gdk_root_window;
242   draw_impl->wrapper = GDK_DRAWABLE (private);
243   draw_impl->colormap = gdk_colormap_get_system ();
244   gdk_colormap_ref (draw_impl->colormap);
245   
246   private->window_type = GDK_WINDOW_ROOT;
247   private->depth = gdk_visual_get_system ()->depth;
248   impl->width = width;
249   impl->height = height;
250
251   gdk_win32_handle_table_insert (&gdk_root_window, _gdk_parent_root);
252 }
253
254 /* The Win API function AdjustWindowRect may return negative values
255  * resulting in obscured title bars. This helper function is coreccting it.
256  */
257 static BOOL
258 SafeAdjustWindowRectEx (RECT* lpRect,
259                         DWORD dwStyle, 
260                         BOOL  bMenu, 
261                         DWORD dwExStyle)
262 {
263   if (!AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle))
264     {
265       WIN32_API_FAILED ("AdjustWindowRectEx");
266       return FALSE;
267     }
268   if (lpRect->left < 0)
269     {
270       lpRect->right -= lpRect->left;
271       lpRect->left = 0;
272     }
273   if (lpRect->top < 0)
274     {
275       lpRect->bottom -= lpRect->top;
276       lpRect->top = 0;
277     }
278   return TRUE;
279 }
280
281 /* RegisterGdkClass
282  *   is a wrapper function for RegisterWindowClassEx.
283  *   It creates at least one unique class for every 
284  *   GdkWindowType. If support for single window-specific icons
285  *   is ever needed (e.g Dialog specific), every such window should
286  *   get its own class
287  */
288 static ATOM
289 RegisterGdkClass (GdkWindowType wtype)
290 {
291   static ATOM klassTOPLEVEL = 0;
292   static ATOM klassDIALOG   = 0;
293   static ATOM klassCHILD    = 0;
294   static ATOM klassTEMP     = 0;
295   static HICON hAppIcon = NULL;
296   static WNDCLASSEX wcl; 
297   ATOM klass = 0;
298
299   wcl.cbSize = sizeof (WNDCLASSEX);
300   wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
301                   * on WM_SIZE and WM_MOVE. Flicker, Performance!
302                   */
303   wcl.lpfnWndProc = _gdk_win32_window_procedure;
304   wcl.cbClsExtra = 0;
305   wcl.cbWndExtra = 0;
306   wcl.hInstance = gdk_app_hmodule;
307   wcl.hIcon = 0;
308   /* initialize once! */
309   if (0 == hAppIcon)
310     {
311       gchar sLoc [_MAX_PATH+1];
312
313       if (0 != GetModuleFileName (gdk_app_hmodule, sLoc, _MAX_PATH))
314         {
315           hAppIcon = ExtractIcon (gdk_app_hmodule, sLoc, 0);
316           if (0 == hAppIcon)
317             {
318               if (0 != GetModuleFileName (gdk_dll_hinstance, sLoc, _MAX_PATH))
319                 hAppIcon = ExtractIcon (gdk_dll_hinstance, sLoc, 0);
320             }
321         }
322       if (0 == hAppIcon) 
323         hAppIcon = LoadIcon (NULL, IDI_APPLICATION);
324     }
325
326   wcl.lpszMenuName = NULL;
327   wcl.hIconSm = 0;
328
329   /* initialize once per class */
330   /*
331    * HB: Setting the background brush leads to flicker, because we
332    * don't get asked how to clear the background. This is not what
333    * we want, at least not for input_only windows ...
334    */
335 #define ONCE_PER_CLASS() \
336   wcl.hIcon = CopyIcon (hAppIcon); \
337   wcl.hIconSm = CopyIcon (hAppIcon); \
338   wcl.hbrBackground = NULL; \
339   wcl.hCursor = LoadCursor (NULL, IDC_ARROW); 
340   
341   switch (wtype)
342     {
343     case GDK_WINDOW_TOPLEVEL:
344       if (0 == klassTOPLEVEL)
345         {
346           wcl.lpszClassName = "gdkWindowToplevel";
347           
348           ONCE_PER_CLASS();
349           klassTOPLEVEL = RegisterClassEx (&wcl);
350         }
351       klass = klassTOPLEVEL;
352       break;
353       
354     case GDK_WINDOW_CHILD:
355       if (0 == klassCHILD)
356         {
357           wcl.lpszClassName = "gdkWindowChild";
358           
359           wcl.style |= CS_PARENTDC; /* MSDN: ... enhances system performance. */
360           ONCE_PER_CLASS();
361           klassCHILD = RegisterClassEx (&wcl);
362         }
363       klass = klassCHILD;
364       break;
365       
366     case GDK_WINDOW_DIALOG:
367       if (0 == klassDIALOG)
368         {
369           wcl.lpszClassName = "gdkWindowDialog";
370           wcl.style |= CS_SAVEBITS;
371           ONCE_PER_CLASS();
372           klassDIALOG = RegisterClassEx (&wcl);
373         }
374       klass = klassDIALOG;
375       break;
376       
377     case GDK_WINDOW_TEMP:
378       if (0 == klassTEMP)
379         {
380           wcl.lpszClassName = "gdkWindowTemp";
381           wcl.style |= CS_SAVEBITS;
382           ONCE_PER_CLASS();
383           klassTEMP = RegisterClassEx (&wcl);
384         }
385       klass = klassTEMP;
386       break;
387       
388     default:
389       g_assert_not_reached ();
390       break;
391     }
392   
393   if (klass == 0)
394     {
395       WIN32_API_FAILED ("RegisterClassEx");
396       g_error ("That is a fatal error");
397     }
398   return klass;
399 }
400
401 GdkWindow*
402 gdk_window_new (GdkWindow     *parent,
403                 GdkWindowAttr *attributes,
404                 gint           attributes_mask)
405 {
406   HANDLE hparent;
407   ATOM klass = 0;
408   DWORD dwStyle, dwExStyle;
409   RECT rect;
410   GdkWindow *window;
411   GdkWindowObject *private;
412   GdkWindowImplWin32 *impl;
413   GdkDrawableImplWin32 *draw_impl;
414   GdkVisual *visual;
415   int width, height;
416   int x, y;
417   char *title;
418   char *mbtitle;
419
420   g_return_val_if_fail (attributes != NULL, NULL);
421
422   if (!parent)
423     parent = _gdk_parent_root;
424
425   g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
426   
427   GDK_NOTE (MISC,
428             g_print ("gdk_window_new: %s\n",
429                      (attributes->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
430                       (attributes->window_type == GDK_WINDOW_CHILD ? "CHILD" :
431                        (attributes->window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
432                         (attributes->window_type == GDK_WINDOW_TEMP ? "TEMP" :
433                          "???"))))));
434
435   if (GDK_WINDOW_DESTROYED (parent))
436     return NULL;
437   
438   hparent = GDK_WINDOW_HWND (parent);
439
440   window = g_object_new (GDK_TYPE_WINDOW, NULL);
441   private = (GdkWindowObject *)window;
442   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
443   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
444   draw_impl->wrapper = GDK_DRAWABLE (window);
445
446   /* Windows with a foreign parent are treated as if they are children
447    * of the root window, except for actual creation.
448    */
449   if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
450     parent = _gdk_parent_root;
451   
452   private->parent = (GdkWindowObject *)parent;
453
454   if (attributes_mask & GDK_WA_X)
455     x = attributes->x;
456   else
457     x = CW_USEDEFAULT;
458   
459   if (attributes_mask & GDK_WA_Y)
460     y = attributes->y;
461   else if (attributes_mask & GDK_WA_X)
462     y = 100;                    /* ??? We must put it somewhere... */
463   else
464     y = 0;                      /* x is CW_USEDEFAULT, y doesn't matter then */
465   
466   private->x = x;
467   private->y = y;
468   impl->width = (attributes->width > 1) ? (attributes->width) : (1);
469   impl->height = (attributes->height > 1) ? (attributes->height) : (1);
470   impl->extension_events_selected = FALSE;
471   private->window_type = attributes->window_type;
472
473   _gdk_window_init_position (GDK_WINDOW (private));
474   if (impl->position_info.big)
475     private->guffaw_gravity = TRUE;
476
477   if (attributes_mask & GDK_WA_VISUAL)
478     visual = attributes->visual;
479   else
480     visual = gdk_visual_get_system ();
481
482   if (attributes_mask & GDK_WA_TITLE)
483     title = attributes->title;
484   else
485     title = g_get_prgname ();
486   if (!title || !*title)
487     title = "GDK client window";
488
489   impl->event_mask = GDK_STRUCTURE_MASK | attributes->event_mask;
490       
491   if (private->parent && private->parent->guffaw_gravity)
492     {
493       /* XXX ??? */
494     }
495
496   if (attributes->wclass == GDK_INPUT_OUTPUT)
497     {
498       dwExStyle = 0;
499
500       private->input_only = FALSE;
501       private->depth = visual->depth;
502       
503       if (attributes_mask & GDK_WA_COLORMAP)
504         {
505           draw_impl->colormap = attributes->colormap;
506           gdk_colormap_ref (attributes->colormap);
507         }
508       else
509         {
510           draw_impl->colormap = gdk_colormap_get_system ();
511         }
512     }
513   else
514     {
515       dwExStyle = WS_EX_TRANSPARENT;
516       private->depth = 0;
517       private->input_only = TRUE;
518       draw_impl->colormap = gdk_colormap_get_system ();
519       gdk_colormap_ref (draw_impl->colormap);
520       GDK_NOTE (MISC, g_print ("...GDK_INPUT_ONLY, system colormap\n"));
521     }
522
523   if (private->parent)
524     private->parent->children = g_list_prepend (private->parent->children, window);
525
526   switch (private->window_type)
527     {
528     case GDK_WINDOW_TOPLEVEL:
529       dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
530       hparent = gdk_root_window;
531       break;
532
533     case GDK_WINDOW_CHILD:
534       dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
535       break;
536
537     case GDK_WINDOW_DIALOG:
538       dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
539 #if 0
540       dwExStyle |= WS_EX_TOPMOST; /* //HB: want this? */
541 #endif
542       hparent = gdk_root_window;
543       break;
544
545     case GDK_WINDOW_TEMP:
546       dwStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
547       /* a temp window is not necessarily a top level window */
548       dwStyle |= (_gdk_parent_root == parent ? WS_POPUP : WS_CHILDWINDOW);
549       dwExStyle |= WS_EX_TOOLWINDOW;
550       break;
551
552     case GDK_WINDOW_ROOT:
553       g_error ("cannot make windows of type GDK_WINDOW_ROOT");
554       break;
555     }
556
557   klass = RegisterGdkClass (private->window_type);
558
559   if (private->window_type != GDK_WINDOW_CHILD)
560     {
561       if (x == CW_USEDEFAULT)
562         {
563           rect.left = 100;
564           rect.top = 100;
565         }
566       else
567         {
568           rect.left = x;
569           rect.top = y;
570         }
571
572       rect.right = rect.left + impl->width;
573       rect.bottom = rect.top + impl->height;
574
575       SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
576
577       if (x != CW_USEDEFAULT)
578         {
579           x = rect.left;
580           y = rect.top;
581         }
582       width = rect.right - rect.left;
583       height = rect.bottom - rect.top;
584     }
585   else
586     {
587       width = impl->width;
588       height = impl->height;
589     }
590
591   mbtitle = g_locale_from_utf8 (title, -1, NULL, NULL, NULL);
592   
593 #ifdef WITHOUT_WM_CREATE
594   draw_impl->handle = CreateWindowEx (dwExStyle,
595                                       MAKEINTRESOURCE(klass),
596                                       mbtitle,
597                                       dwStyle,
598                                       impl->position_info.x, impl->position_info.y, 
599                                       impl->position_info.width, impl->position_info.height,
600                                       hparent,
601                                       NULL,
602                                       gdk_app_hmodule,
603                                       NULL);
604 #else
605   {
606   HWND hwndNew =
607     CreateWindowEx (dwExStyle,
608                     MAKEINTRESOURCE(klass),
609                     mbtitle,
610                     dwStyle,
611                     impl->position_info.x, impl->position_info.y, 
612                     impl->position_info.width, impl->position_info.height,
613                     hparent,
614                     NULL,
615                     gdk_app_hmodule,
616                     window);
617   if (GDK_WINDOW_HWND (window) != hwndNew)
618     {
619       g_warning("gdk_window_new: gdk_event_translate::WM_CREATE (%p, %p) HWND mismatch.",
620                 GDK_WINDOW_HWND (window),
621                 hwndNew);
622
623       /* HB: IHMO due to a race condition the handle was increased by
624        * one, which causes much trouble. Because I can't find the 
625        * real bug, try to workaround it ...
626        * To reproduce: compile with MSVC 5, DEBUG=1
627        */
628 # if 0
629       gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
630       GDK_WINDOW_HWND (window) = hwndNew;
631       gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
632 # else
633       /* the old behaviour, but with warning */
634       GDK_WINDOW_HWND (window) = hwndNew;
635 # endif
636
637     }
638   }
639   gdk_drawable_ref (window);
640   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
641 #endif
642
643   GDK_NOTE (MISC,
644             g_print ("... \"%s\" %dx%d@+%d+%d %p = %p\n",
645                      mbtitle,
646                      width, height, (x == CW_USEDEFAULT ? -9999 : x), y, 
647                      hparent,
648                      GDK_WINDOW_HWND (window)));
649
650   g_free (mbtitle);
651
652   if (draw_impl->handle == NULL)
653     {
654       WIN32_API_FAILED ("CreateWindowEx");
655       g_object_unref ((GObject *) window);
656       return NULL;
657     }
658
659 #ifdef WITHOUT_WM_CREATE
660   gdk_drawable_ref (window);
661   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
662 #endif
663
664   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
665                                   (attributes->cursor) :
666                                   NULL));
667
668   return window;
669 }
670
671 GdkWindow *
672 gdk_window_foreign_new (GdkNativeWindow anid)
673 {
674   GdkWindow *window;
675   GdkWindowObject *private;
676   GdkWindowImplWin32 *impl;
677   GdkDrawableImplWin32 *draw_impl;
678
679   HANDLE parent;
680   RECT rect;
681   POINT point;
682
683   window = g_object_new (GDK_TYPE_WINDOW, NULL);
684   private = (GdkWindowObject *)window;
685   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
686   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
687   draw_impl->wrapper = GDK_DRAWABLE (window);
688   parent = GetParent ((HWND)anid);
689   
690   private->parent = gdk_win32_handle_table_lookup ((GdkNativeWindow) parent);
691   if (!private->parent || GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_FOREIGN)
692     private->parent = (GdkWindowObject *)_gdk_parent_root;
693   
694   private->parent->children = g_list_prepend (private->parent->children, window);
695
696   draw_impl->handle = (HWND) anid;
697   GetClientRect ((HWND) anid, &rect);
698   point.x = rect.left;
699   point.y = rect.right;
700   ClientToScreen ((HWND) anid, &point);
701   if (parent != gdk_root_window)
702     ScreenToClient (parent, &point);
703   private->x = point.x;
704   private->y = point.y;
705   impl->width = rect.right - rect.left;
706   impl->height = rect.bottom - rect.top;
707   private->window_type = GDK_WINDOW_FOREIGN;
708   private->destroyed = FALSE;
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   
1567   if (private->bg_pixmap &&
1568       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1569       private->bg_pixmap != GDK_NO_BG)
1570     gdk_drawable_unref (private->bg_pixmap);
1571
1572   if (parent_relative)
1573     {
1574       private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
1575       GDK_NOTE (MISC, g_print (G_STRLOC ": setting background pixmap to parent_relative\n"));
1576     }
1577   else
1578     {
1579       if (pixmap)
1580         {
1581           gdk_drawable_ref (pixmap);
1582           private->bg_pixmap = pixmap;
1583         }
1584       else
1585         {
1586           private->bg_pixmap = GDK_NO_BG;
1587         }
1588     }
1589 }
1590
1591 void
1592 gdk_window_set_cursor (GdkWindow *window,
1593                        GdkCursor *cursor)
1594 {
1595   GdkWindowImplWin32 *impl;
1596   GdkCursorPrivate *cursor_private;
1597   HCURSOR hcursor;
1598   HCURSOR hprevcursor;
1599   
1600   g_return_if_fail (window != NULL);
1601   g_return_if_fail (GDK_IS_WINDOW (window));
1602   
1603   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1604   cursor_private = (GdkCursorPrivate*) cursor;
1605   
1606   if (GDK_WINDOW_DESTROYED (window))
1607     return;
1608
1609   if (!cursor)
1610     hcursor = NULL;
1611   else
1612     hcursor = cursor_private->hcursor;
1613   
1614   GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %p %p\n",
1615                            GDK_WINDOW_HWND (window),
1616                            hcursor));
1617
1618   /* First get the old cursor, if any (we wait to free the old one
1619    * since it may be the current cursor set in the Win32 API right
1620    * now).
1621    */
1622   hprevcursor = impl->hcursor;
1623
1624   if (hcursor == NULL)
1625     impl->hcursor = NULL;
1626   else
1627     {
1628       /* We must copy the cursor as it is OK to destroy the GdkCursor
1629        * while still in use for some window. See for instance
1630        * gimp_change_win_cursor() which calls gdk_window_set_cursor
1631        * (win, cursor), and immediately afterwards gdk_cursor_destroy
1632        * (cursor).
1633        */
1634       if ((impl->hcursor = CopyCursor (hcursor)) == NULL)
1635         WIN32_API_FAILED ("CopyCursor");
1636       GDK_NOTE (MISC, g_print ("...CopyCursor (%p) = %p\n",
1637                                hcursor, impl->hcursor));
1638     }
1639
1640    /* Set new cursor in all cases if we're over our window */
1641   if (gdk_window_get_pointer(window, NULL, NULL, NULL) == window)
1642     SetCursor (impl->hcursor);
1643
1644   /* Destroy the previous cursor: Need to make sure it's no longer in
1645    * use before we destroy it, in case we're not over our window but
1646    * the cursor is still set to our old one.
1647    */
1648   if (hprevcursor != NULL)
1649     {
1650       if (GetCursor() == hprevcursor)
1651         SetCursor (NULL);
1652
1653       GDK_NOTE (MISC, g_print ("...DestroyCursor (%p)\n",
1654                                hprevcursor));
1655       
1656       if (!DestroyCursor (hprevcursor))
1657         WIN32_API_FAILED ("DestroyCursor");
1658     }
1659 }
1660
1661 void
1662 gdk_window_get_geometry (GdkWindow *window,
1663                          gint      *x,
1664                          gint      *y,
1665                          gint      *width,
1666                          gint      *height,
1667                          gint      *depth)
1668 {
1669   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1670   
1671   if (!window)
1672     window = _gdk_parent_root;
1673   
1674   if (!GDK_WINDOW_DESTROYED (window))
1675     {
1676       RECT rect;
1677
1678       if (!GetClientRect (GDK_WINDOW_HWND (window), &rect))
1679         WIN32_API_FAILED ("GetClientRect");
1680
1681       if (x)
1682         *x = rect.left;
1683       if (y)
1684         *y = rect.top;
1685       if (width)
1686         *width = rect.right - rect.left;
1687       if (height)
1688         *height = rect.bottom - rect.top;
1689       if (depth)
1690         *depth = gdk_drawable_get_visual (window)->depth;
1691     }
1692 }
1693
1694 gint
1695 gdk_window_get_origin (GdkWindow *window,
1696                        gint      *x,
1697                        gint      *y)
1698 {
1699   gint return_val;
1700   gint tx = 0;
1701   gint ty = 0;
1702
1703   g_return_val_if_fail (window != NULL, 0);
1704
1705   if (!GDK_WINDOW_DESTROYED (window))
1706     {
1707       POINT pt;
1708
1709       pt.x = 0;
1710       pt.y = 0;
1711       ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1712       tx = pt.x;
1713       ty = pt.y;
1714       return_val = 1;
1715     }
1716   else
1717     return_val = 0;
1718   
1719   if (x)
1720     *x = tx;
1721   if (y)
1722     *y = ty;
1723
1724   GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %p: +%d+%d\n",
1725                            GDK_WINDOW_HWND (window),
1726                            tx, ty));
1727   return return_val;
1728 }
1729
1730 gboolean
1731 gdk_window_get_deskrelative_origin (GdkWindow *window,
1732                                     gint      *x,
1733                                     gint      *y)
1734 {
1735   return gdk_window_get_origin (window, x, y);
1736 }
1737
1738 void
1739 gdk_window_get_root_origin (GdkWindow *window,
1740                             gint      *x,
1741                             gint      *y)
1742 {
1743   GdkRectangle rect;
1744
1745   g_return_if_fail (GDK_IS_WINDOW (window));
1746
1747   gdk_window_get_frame_extents (window, &rect);
1748
1749   if (x)
1750     *x = rect.x;
1751
1752   if (y)
1753     *y = rect.y;
1754 }
1755
1756 void
1757 gdk_window_get_frame_extents (GdkWindow    *window,
1758                               GdkRectangle *rect)
1759 {
1760   GdkWindowObject *private;
1761   HWND hwnd;
1762   RECT r;
1763
1764   g_return_if_fail (GDK_IS_WINDOW (window));
1765   g_return_if_fail (rect != NULL);
1766
1767   private = GDK_WINDOW_OBJECT (window);
1768
1769   rect->x = 0;
1770   rect->y = 0;
1771   rect->width = 1;
1772   rect->height = 1;
1773   
1774   if (GDK_WINDOW_DESTROYED (window))
1775     return;
1776
1777   while (private->parent && ((GdkWindowObject*) private->parent)->parent)
1778     private = (GdkWindowObject*) private->parent;
1779
1780   hwnd = GDK_WINDOW_HWND (window);
1781
1782   /* find the frame window */
1783   while (HWND_DESKTOP != GetParent (hwnd))
1784     {
1785       hwnd = GetParent (hwnd);
1786       g_return_if_fail (NULL != hwnd);
1787     }
1788
1789   if (!GetWindowRect (hwnd, &r))
1790     WIN32_API_FAILED ("GetWindowRect");
1791
1792   rect->x = r.left;
1793   rect->y = r.right;
1794   rect->width = r.right - r.left;
1795   rect->height = r.bottom - r.top;
1796 }
1797
1798 GdkWindow*
1799 _gdk_windowing_window_get_pointer (GdkWindow       *window,
1800                                    gint            *x,
1801                                    gint            *y,
1802                                    GdkModifierType *mask)
1803 {
1804   GdkWindow *return_val;
1805   POINT screen_point, point;
1806   HWND hwnd, hwndc;
1807
1808   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1809   
1810   if (!window)
1811     window = _gdk_parent_root;
1812
1813   return_val = NULL;
1814   GetCursorPos (&screen_point);
1815   point = screen_point;
1816   ScreenToClient (GDK_WINDOW_HWND (window), &point);
1817
1818   if (x)
1819     *x = point.x;
1820   if (y)
1821     *y = point.y;
1822
1823   hwnd = WindowFromPoint (point);
1824   if (hwnd != NULL)
1825     {
1826       gboolean done = FALSE;
1827       
1828       while (!done)
1829         {
1830           point = screen_point;
1831           ScreenToClient (hwnd, &point);
1832           hwndc = ChildWindowFromPoint (hwnd, point);
1833           if (hwndc == NULL)
1834             done = TRUE;
1835           else if (hwndc == hwnd)
1836             done = TRUE;
1837           else
1838             hwnd = hwndc;
1839         }
1840       
1841       return_val = gdk_window_lookup ((GdkNativeWindow) hwnd);
1842     }
1843   else
1844     return_val = NULL;
1845       
1846   if (mask)
1847     {
1848       BYTE kbd[256];
1849
1850       GetKeyboardState (kbd);
1851       *mask = 0;
1852       if (kbd[VK_SHIFT] & 0x80)
1853         *mask |= GDK_SHIFT_MASK;
1854       if (kbd[VK_CAPITAL] & 0x80)
1855         *mask |= GDK_LOCK_MASK;
1856       if (kbd[VK_CONTROL] & 0x80)
1857         *mask |= GDK_CONTROL_MASK;
1858       if (kbd[VK_MENU] & 0x80)
1859         *mask |= GDK_MOD1_MASK;
1860       if (kbd[VK_LBUTTON] & 0x80)
1861         *mask |= GDK_BUTTON1_MASK;
1862       if (kbd[VK_MBUTTON] & 0x80)
1863         *mask |= GDK_BUTTON2_MASK;
1864       if (kbd[VK_RBUTTON] & 0x80)
1865         *mask |= GDK_BUTTON3_MASK;
1866     }
1867   
1868   return return_val;
1869 }
1870
1871 GdkWindow*
1872 _gdk_windowing_window_at_pointer (GdkScreen *screen,
1873                                   gint      *win_x,
1874                                   gint      *win_y)
1875 {
1876   GdkWindow *window;
1877   POINT point, pointc;
1878   HWND hwnd, hwndc;
1879   RECT rect;
1880
1881   GetCursorPos (&pointc);
1882   point = pointc;
1883   hwnd = WindowFromPoint (point);
1884
1885   if (hwnd == NULL)
1886     {
1887       window = _gdk_parent_root;
1888       if (win_x)
1889         *win_x = pointc.x;
1890       if (win_y)
1891         *win_y = pointc.y;
1892       return window;
1893     }
1894       
1895   ScreenToClient (hwnd, &point);
1896
1897   do {
1898     hwndc = ChildWindowFromPoint (hwnd, point);
1899     ClientToScreen (hwnd, &point);
1900     ScreenToClient (hwndc, &point);
1901   } while (hwndc != hwnd && (hwnd = hwndc, 1));
1902
1903   window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
1904
1905   if (window && (win_x || win_y))
1906     {
1907       GetClientRect (hwnd, &rect);
1908       if (win_x)
1909         *win_x = point.x - rect.left;
1910       if (win_y)
1911         *win_y = point.y - rect.top;
1912     }
1913
1914   GDK_NOTE (MISC, g_print ("gdk_window_at_pointer: +%ld+%ld %p%s\n",
1915                            point.x, point.y,
1916                            hwnd,
1917                            (window == NULL ? " NULL" : "")));
1918
1919   return window;
1920 }
1921
1922 GdkEventMask  
1923 gdk_window_get_events (GdkWindow *window)
1924 {
1925   g_return_val_if_fail (window != NULL, 0);
1926   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1927
1928   if (GDK_WINDOW_DESTROYED (window))
1929     return 0;
1930
1931   return GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl)->event_mask;
1932 }
1933
1934 void          
1935 gdk_window_set_events (GdkWindow   *window,
1936                        GdkEventMask event_mask)
1937 {
1938   g_return_if_fail (window != NULL);
1939   g_return_if_fail (GDK_IS_WINDOW (window));
1940
1941   if (GDK_WINDOW_DESTROYED (window))
1942     return;
1943
1944   GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl)->event_mask = event_mask;
1945 }
1946
1947 void
1948 gdk_window_shape_combine_mask (GdkWindow *window,
1949                                GdkBitmap *mask,
1950                                gint x, gint y)
1951 {
1952   g_return_if_fail (window != NULL);
1953   g_return_if_fail (GDK_IS_WINDOW (window));
1954
1955   if (!mask)
1956     {
1957       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %p none\n",
1958                                GDK_WINDOW_HWND (window)));
1959       SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
1960     }
1961   else
1962     {
1963       HRGN hrgn;
1964       DWORD dwStyle;
1965       DWORD dwExStyle;
1966       RECT rect;
1967
1968       /* Convert mask bitmap to region */
1969       hrgn = _gdk_win32_bitmap_to_region (mask);
1970
1971       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %p %p\n",
1972                                GDK_WINDOW_HWND (window),
1973                                GDK_WINDOW_HWND (mask)));
1974
1975       /* SetWindowRgn wants window (not client) coordinates */ 
1976       dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1977       dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1978       GetClientRect (GDK_WINDOW_HWND (window), &rect);
1979       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1980       OffsetRgn (hrgn, -rect.left, -rect.top);
1981
1982       OffsetRgn (hrgn, x, y);
1983
1984       /* If this is a top-level window, add the title bar to the region */
1985       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
1986         {
1987           HRGN tmp = CreateRectRgn (0, 0, rect.right - rect.left, -rect.top);
1988           CombineRgn (hrgn, hrgn, tmp, RGN_OR);
1989           DeleteObject (tmp);
1990         }
1991       
1992       SetWindowRgn (GDK_WINDOW_HWND (window), hrgn, TRUE);
1993     }
1994 }
1995
1996 void
1997 gdk_window_set_override_redirect (GdkWindow *window,
1998                                   gboolean   override_redirect)
1999 {
2000   g_return_if_fail (window != NULL);
2001   g_return_if_fail (GDK_IS_WINDOW (window));
2002
2003   g_warning ("gdk_window_set_override_redirect not implemented");
2004 }
2005
2006 void          
2007 gdk_window_set_icon_list (GdkWindow *window,
2008                           GList     *pixbufs)
2009 {
2010   g_return_if_fail (GDK_IS_WINDOW (window));
2011
2012   if (GDK_WINDOW_DESTROYED (window))
2013     return;
2014
2015   /* We could convert it to a hIcon and DrawIcon () it when getting
2016    * a WM_PAINT with IsIconic, but is it worth it ? Same probably
2017    * goes for gdk_window_set_icon (). Patches accepted :-)  --hb
2018    * Or do we only need to deliver the Icon on WM_GETICON ?
2019    */
2020 }
2021
2022 void          
2023 gdk_window_set_icon (GdkWindow *window, 
2024                      GdkWindow *icon_window,
2025                      GdkPixmap *pixmap,
2026                      GdkBitmap *mask)
2027 {
2028   g_return_if_fail (window != NULL);
2029   g_return_if_fail (GDK_IS_WINDOW (window));
2030
2031   if (GDK_WINDOW_DESTROYED (window))
2032     return;
2033   
2034   /* Nothing to do, really. As we share window classes between windows
2035    * we can't have window-specific icons, sorry. Don't print any warning
2036    * either.
2037    */
2038 }
2039
2040 void
2041 gdk_window_set_icon_name (GdkWindow   *window, 
2042                           const gchar *name)
2043 {
2044   g_return_if_fail (window != NULL);
2045   g_return_if_fail (GDK_IS_WINDOW (window));
2046
2047   if (GDK_WINDOW_DESTROYED (window))
2048     return;
2049   
2050   if (!SetWindowText (GDK_WINDOW_HWND (window), name))
2051     WIN32_API_FAILED ("SetWindowText");
2052 }
2053
2054 void          
2055 gdk_window_set_group (GdkWindow *window, 
2056                       GdkWindow *leader)
2057 {
2058   g_return_if_fail (window != NULL);
2059   g_return_if_fail (GDK_IS_WINDOW (window));
2060   g_return_if_fail (leader != NULL);
2061   g_return_if_fail (GDK_IS_WINDOW (leader));
2062
2063   if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
2064     return;
2065   
2066   g_warning ("gdk_window_set_group not implemented");
2067 }
2068
2069 void
2070 gdk_window_set_decorations (GdkWindow      *window,
2071                             GdkWMDecoration decorations)
2072 {
2073   LONG style, exstyle;
2074
2075   g_return_if_fail (window != NULL);
2076   g_return_if_fail (GDK_IS_WINDOW (window));
2077   
2078   style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2079   exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
2080
2081   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2082             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE);
2083
2084   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2085
2086   if (decorations & GDK_DECOR_ALL)
2087     style |= (WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2088   if (decorations & GDK_DECOR_BORDER)
2089     style |= (WS_BORDER);
2090   if (decorations & GDK_DECOR_RESIZEH)
2091     style |= (WS_THICKFRAME);
2092   if (decorations & GDK_DECOR_TITLE)
2093     style |= (WS_CAPTION);
2094   if (decorations & GDK_DECOR_MENU)
2095     style |= (WS_SYSMENU);
2096   if (decorations & GDK_DECOR_MINIMIZE)
2097     style |= (WS_MINIMIZEBOX);
2098   if (decorations & GDK_DECOR_MAXIMIZE)
2099     style |= (WS_MAXIMIZEBOX);
2100   
2101   SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
2102 }
2103
2104 void
2105 gdk_window_set_functions (GdkWindow    *window,
2106                           GdkWMFunction functions)
2107 {
2108   LONG style, exstyle;
2109
2110   g_return_if_fail (window != NULL);
2111   g_return_if_fail (GDK_IS_WINDOW (window));
2112   
2113   style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2114   exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
2115
2116   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2117             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE|WS_CAPTION|WS_BORDER
2118             |WS_SYSMENU);
2119
2120   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2121
2122   if (functions & GDK_FUNC_ALL)
2123     style |= (WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2124   if (functions & GDK_FUNC_RESIZE)
2125     style |= (WS_THICKFRAME);
2126   if (functions & GDK_FUNC_MOVE)
2127     style |= (WS_THICKFRAME);
2128   if (functions & GDK_FUNC_MINIMIZE)
2129     style |= (WS_MINIMIZEBOX);
2130   if (functions & GDK_FUNC_MAXIMIZE)
2131     style |= (WS_MAXIMIZEBOX);
2132   
2133   SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
2134 }
2135
2136 /* 
2137  * propagate the shapes from all child windows of a GDK window to the parent 
2138  * window. Shamelessly ripped from Enlightenment's code
2139  * 
2140  * - Raster
2141  */
2142
2143 static void
2144 QueryTree (HWND hwnd,
2145            HWND **children,
2146            gint *nchildren)
2147 {
2148   guint i, n;
2149   HWND child;
2150
2151   n = 0;
2152   do {
2153     if (n == 0)
2154       child = GetWindow (hwnd, GW_CHILD);
2155     else
2156       child = GetWindow (child, GW_HWNDNEXT);
2157     if (child != NULL)
2158       n++;
2159   } while (child != NULL);
2160
2161   if (n > 0)
2162     {
2163       *children = g_new (HWND, n);
2164       for (i = 0; i < n; i++)
2165         {
2166           if (i == 0)
2167             child = GetWindow (hwnd, GW_CHILD);
2168           else
2169             child = GetWindow (child, GW_HWNDNEXT);
2170           *children[i] = child;
2171         }
2172     }
2173 }
2174
2175 static void
2176 gdk_propagate_shapes (HANDLE   win,
2177                       gboolean merge)
2178 {
2179    RECT emptyRect;
2180    HRGN region, childRegion;
2181    HWND *list = NULL;
2182    gint i, num;
2183
2184    SetRectEmpty (&emptyRect);
2185    region = CreateRectRgnIndirect (&emptyRect);
2186    if (merge)
2187      GetWindowRgn (win, region);
2188    
2189    QueryTree (win, &list, &num);
2190    if (list != NULL)
2191      {
2192        WINDOWPLACEMENT placement;
2193
2194        placement.length = sizeof (WINDOWPLACEMENT);
2195        /* go through all child windows and combine regions */
2196        for (i = 0; i < num; i++)
2197          {
2198            GetWindowPlacement (list[i], &placement);
2199            if (placement.showCmd == SW_SHOWNORMAL)
2200              {
2201                childRegion = CreateRectRgnIndirect (&emptyRect);
2202                GetWindowRgn (list[i], childRegion);
2203                CombineRgn (region, region, childRegion, RGN_OR);
2204                DeleteObject (childRegion);
2205              }
2206           }
2207        SetWindowRgn (win, region, TRUE);
2208      }
2209    else
2210      DeleteObject (region);
2211 }
2212
2213 void
2214 gdk_window_set_child_shapes (GdkWindow *window)
2215 {
2216   g_return_if_fail (window != NULL);
2217   g_return_if_fail (GDK_IS_WINDOW (window));
2218    
2219   if (GDK_WINDOW_DESTROYED (window))
2220     return;
2221
2222   gdk_propagate_shapes (GDK_WINDOW_HWND (window), FALSE);
2223 }
2224
2225 void
2226 gdk_window_merge_child_shapes (GdkWindow *window)
2227 {
2228   g_return_if_fail (window != NULL);
2229   g_return_if_fail (GDK_IS_WINDOW (window));
2230   
2231   if (GDK_WINDOW_DESTROYED (window))
2232     return;
2233
2234   gdk_propagate_shapes (GDK_WINDOW_HWND (window), TRUE);
2235 }
2236
2237 /* Support for windows that can be guffaw-scrolled
2238  * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
2239  */
2240
2241 static gboolean
2242 gdk_window_gravity_works (void)
2243 {
2244   enum { UNKNOWN, NO, YES };
2245   static gint gravity_works = UNKNOWN;
2246   
2247   if (gravity_works == UNKNOWN)
2248     {
2249       GdkWindowAttr attr;
2250       GdkWindow *parent;
2251       GdkWindow *child;
2252       gint y;
2253       
2254       attr.window_type = GDK_WINDOW_TEMP;
2255       attr.wclass = GDK_INPUT_OUTPUT;
2256       attr.x = 0;
2257       attr.y = 0;
2258       attr.width = 100;
2259       attr.height = 100;
2260       attr.event_mask = 0;
2261       
2262       parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
2263       
2264       attr.window_type = GDK_WINDOW_CHILD;
2265       child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
2266       
2267       gdk_window_set_static_win_gravity (child, TRUE);
2268       
2269       gdk_window_resize (parent, 100, 110);
2270       gdk_window_move (parent, 0, -10);
2271       gdk_window_move_resize (parent, 0, 0, 100, 100);
2272       
2273       gdk_window_resize (parent, 100, 110);
2274       gdk_window_move (parent, 0, -10);
2275       gdk_window_move_resize (parent, 0, 0, 100, 100);
2276       
2277       gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
2278       
2279       gdk_window_destroy (parent);
2280       gdk_window_destroy (child);
2281       
2282       gravity_works = ((y == -20) ? YES : NO);
2283     }
2284   
2285   return (gravity_works == YES);
2286 }
2287
2288 static void
2289 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
2290 {
2291   g_return_if_fail (window != NULL);
2292
2293   GDK_NOTE (MISC, g_print ("gdk_window_set_static_bit_gravity: Not implemented\n"));
2294 }
2295
2296 static void
2297 gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
2298 {
2299   g_return_if_fail (window != NULL);
2300
2301   GDK_NOTE (MISC,
2302             g_print ("gdk_window_set_static_win_gravity: Not implemented\n"));
2303 }
2304
2305 /*************************************************************
2306  * gdk_window_set_static_gravities:
2307  *     Set the bit gravity of the given window to static,
2308  *     and flag it so all children get static subwindow
2309  *     gravity.
2310  *   arguments:
2311  *     window: window for which to set static gravity
2312  *     use_static: Whether to turn static gravity on or off.
2313  *   results:
2314  *     Does the XServer support static gravity?
2315  *************************************************************/
2316
2317 gboolean 
2318 gdk_window_set_static_gravities (GdkWindow *window,
2319                                  gboolean   use_static)
2320 {
2321   GdkWindowObject *private = (GdkWindowObject *)window;
2322   GList *tmp_list;
2323   
2324   g_return_val_if_fail (window != NULL, FALSE);
2325   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2326
2327   if (!use_static == !private->guffaw_gravity)
2328     return TRUE;
2329   
2330   if (use_static && !gdk_window_gravity_works ())
2331     return FALSE;
2332   
2333   private->guffaw_gravity = use_static;
2334   
2335   if (!GDK_WINDOW_DESTROYED (window))
2336     {
2337       gdk_window_set_static_bit_gravity (window, use_static);
2338       
2339       tmp_list = private->children;
2340       while (tmp_list)
2341         {
2342           gdk_window_set_static_win_gravity (window, use_static);
2343           
2344           tmp_list = tmp_list->next;
2345         }
2346     }
2347   
2348   return TRUE;
2349 }
2350
2351 /*
2352  * Setting window states
2353  */
2354 void
2355 gdk_window_iconify (GdkWindow *window)
2356 {
2357   g_return_if_fail (window != NULL);
2358   g_return_if_fail (GDK_IS_WINDOW (window));
2359
2360   if (GDK_WINDOW_DESTROYED (window))
2361     return;
2362
2363   if (GDK_WINDOW_IS_MAPPED (window))
2364     {
2365       ShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
2366     }
2367   else
2368     {
2369       /* Flip our client side flag, the real work happens on map. */
2370       gdk_synthesize_window_state (window,
2371                                    0,
2372                                    GDK_WINDOW_STATE_ICONIFIED);
2373     }
2374 }
2375
2376 void
2377 gdk_window_deiconify (GdkWindow *window)
2378 {
2379   g_return_if_fail (window != NULL);
2380   g_return_if_fail (GDK_IS_WINDOW (window));
2381
2382   if (GDK_WINDOW_DESTROYED (window))
2383     return;
2384
2385   if (GDK_WINDOW_IS_MAPPED (window))
2386     {  
2387       gdk_window_show (window);
2388     }
2389   else
2390     {
2391       /* Flip our client side flag, the real work happens on map. */
2392       gdk_synthesize_window_state (window,
2393                                    GDK_WINDOW_STATE_ICONIFIED,
2394                                    0);
2395     }
2396 }
2397
2398 void
2399 gdk_window_stick (GdkWindow *window)
2400 {
2401   g_return_if_fail (GDK_IS_WINDOW (window));
2402
2403   if (GDK_WINDOW_DESTROYED (window))
2404     return;
2405
2406   if (GDK_WINDOW_IS_MAPPED (window))
2407     {
2408       /* "stick" means stick to all desktops _and_ do not scroll with the
2409        * viewport. i.e. glue to the monitor glass in all cases.
2410        */
2411       g_warning ("gdk_window_stick (%p) ???", GDK_WINDOW_HWND (window));
2412     }
2413   else
2414     {
2415       /* Flip our client side flag, the real work happens on map. */
2416       gdk_synthesize_window_state (window,
2417                                    0,
2418                                    GDK_WINDOW_STATE_STICKY);
2419     }
2420 }
2421
2422 void
2423 gdk_window_unstick (GdkWindow *window)
2424 {
2425   g_return_if_fail (GDK_IS_WINDOW (window));
2426
2427   if (GDK_WINDOW_DESTROYED (window))
2428     return;
2429
2430   if (GDK_WINDOW_IS_MAPPED (window))
2431     {
2432       g_warning ("gdk_window_unstick (%p) ???", GDK_WINDOW_HWND (window));
2433     }
2434   else
2435     {
2436       /* Flip our client side flag, the real work happens on map. */
2437       gdk_synthesize_window_state (window,
2438                                    GDK_WINDOW_STATE_STICKY,
2439                                    0);
2440     }
2441 }
2442
2443 void
2444 gdk_window_maximize (GdkWindow *window)
2445 {
2446   g_return_if_fail (GDK_IS_WINDOW (window));
2447
2448   if (GDK_WINDOW_DESTROYED (window))
2449     return;
2450
2451   if (GDK_WINDOW_IS_MAPPED (window))
2452     ShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
2453   else
2454     gdk_synthesize_window_state (window,
2455                                  0,
2456                                  GDK_WINDOW_STATE_MAXIMIZED);
2457 }
2458
2459 void
2460 gdk_window_unmaximize (GdkWindow *window)
2461 {
2462   g_return_if_fail (GDK_IS_WINDOW (window));
2463
2464   if (GDK_WINDOW_DESTROYED (window))
2465     return;
2466
2467   if (GDK_WINDOW_IS_MAPPED (window))
2468     ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
2469   else
2470     gdk_synthesize_window_state (window,
2471                                  GDK_WINDOW_STATE_MAXIMIZED,
2472                                  0);
2473 }
2474
2475 void
2476 gdk_window_focus (GdkWindow *window,
2477                   guint32    timestamp)
2478 {
2479   g_return_if_fail (GDK_IS_WINDOW (window));
2480
2481   if (GDK_WINDOW_DESTROYED (window))
2482     return;
2483   
2484   ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
2485 }
2486
2487 void
2488 gdk_window_set_modal_hint (GdkWindow *window,
2489                            gboolean   modal)
2490 {
2491   GdkWindowObject *private;
2492
2493   g_return_if_fail (window != NULL);
2494   g_return_if_fail (GDK_IS_WINDOW (window));
2495   
2496   if (GDK_WINDOW_DESTROYED (window))
2497     return;
2498
2499   private = (GdkWindowObject*) window;
2500
2501   private->modal_hint = modal;
2502
2503   if (GDK_WINDOW_IS_MAPPED (window))
2504     if (!SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOPMOST,
2505                            0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE))
2506       WIN32_API_FAILED ("SetWindowPos");
2507 }
2508
2509 void
2510 gdk_window_set_type_hint (GdkWindow        *window,
2511                           GdkWindowTypeHint hint)
2512 {
2513   GdkAtom atom;
2514   
2515   g_return_if_fail (window != NULL);
2516   g_return_if_fail (GDK_IS_WINDOW (window));
2517   
2518   if (GDK_WINDOW_DESTROYED (window))
2519     return;
2520
2521   switch (hint)
2522     {
2523     case GDK_WINDOW_TYPE_HINT_DIALOG:
2524       atom = gdk_atom_intern ("_NET_WM_WINDOW_TYPE_DIALOG", FALSE);
2525       break;
2526     case GDK_WINDOW_TYPE_HINT_MENU:
2527       atom = gdk_atom_intern ("_NET_WM_WINDOW_TYPE_MENU", FALSE);
2528       break;
2529     case GDK_WINDOW_TYPE_HINT_TOOLBAR:
2530       atom = gdk_atom_intern ("_NET_WM_WINDOW_TYPE_TOOLBAR", FALSE);
2531       break;
2532     default:
2533       g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2534       /* Fall thru */
2535     case GDK_WINDOW_TYPE_HINT_NORMAL:
2536       atom = gdk_atom_intern ("_NET_WM_WINDOW_TYPE_NORMAL", FALSE);
2537       break;
2538     }
2539   /*
2540    * XXX ???
2541    */
2542   GDK_NOTE (MISC,
2543             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 }