]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow-win32.c
Build Wintab support always on Windows. Don't require the Wintab SDK.
[~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-2004 Tor Lillqvist
4  * Copyright (C) 2001-2004 Hans Breuer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /*
23  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
24  * file for a list of people on the GTK+ Team.  See the ChangeLog
25  * files for a list of changes.  These files are distributed with
26  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
27  */
28
29 #include <config.h>
30 #include <stdlib.h>
31
32 #include "gdk.h"
33 #include "gdkprivate-win32.h"
34 #include "gdkinput-win32.h"
35
36 #if 0
37 #include <gdk-pixbuf/gdk-pixbuf.h>
38 #include <stdio.h>
39 #endif
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 static void     update_style_bits         (GdkWindow *window);
55 static gboolean _gdk_window_get_functions (GdkWindow     *window,
56                                            GdkWMFunction *functions);
57
58 #define WINDOW_IS_TOPLEVEL(window)                 \
59   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
60    GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
61
62 GType
63 _gdk_window_impl_win32_get_type (void)
64 {
65   static GType object_type = 0;
66
67   if (!object_type)
68     {
69       static const GTypeInfo object_info =
70       {
71         sizeof (GdkWindowImplWin32Class),
72         (GBaseInitFunc) NULL,
73         (GBaseFinalizeFunc) NULL,
74         (GClassInitFunc) gdk_window_impl_win32_class_init,
75         NULL,           /* class_finalize */
76         NULL,           /* class_data */
77         sizeof (GdkWindowImplWin32),
78         0,              /* n_preallocs */
79         (GInstanceInitFunc) gdk_window_impl_win32_init,
80       };
81       
82       object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_WIN32,
83                                             "GdkWindowImplWin32",
84                                             &object_info, 0);
85     }
86   
87   return object_type;
88 }
89
90 GType
91 _gdk_window_impl_get_type (void)
92 {
93   return _gdk_window_impl_win32_get_type ();
94 }
95
96 static void
97 gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
98 {
99   impl->width = 1;
100   impl->height = 1;
101   impl->toplevel_window_type = -1;
102   impl->hcursor = NULL;
103   impl->hicon_big = NULL;
104   impl->hicon_small = NULL;
105   impl->hint_flags = 0;
106   impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
107   impl->extension_events_selected = FALSE;
108 }
109
110 static void
111 gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
112 {
113   GObjectClass *object_class = G_OBJECT_CLASS (klass);
114   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
115   
116   parent_class = g_type_class_peek_parent (klass);
117
118   object_class->finalize = gdk_window_impl_win32_finalize;
119
120   drawable_class->set_colormap = gdk_window_impl_win32_set_colormap;
121   drawable_class->get_colormap = gdk_window_impl_win32_get_colormap;
122   drawable_class->get_size = gdk_window_impl_win32_get_size;
123
124   /* Visible and clip regions are the same */
125   drawable_class->get_clip_region = gdk_window_impl_win32_get_visible_region;
126   drawable_class->get_visible_region = gdk_window_impl_win32_get_visible_region;
127 }
128
129 static void
130 gdk_window_impl_win32_finalize (GObject *object)
131 {
132   GdkWindowObject *wrapper;
133   GdkDrawableImplWin32 *draw_impl;
134   GdkWindowImplWin32 *window_impl;
135   
136   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (object));
137
138   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (object);
139   window_impl = GDK_WINDOW_IMPL_WIN32 (object);
140   
141   wrapper = (GdkWindowObject*) draw_impl->wrapper;
142
143   if (!GDK_WINDOW_DESTROYED (wrapper))
144     {
145       gdk_win32_handle_table_remove (draw_impl->handle);
146     }
147
148   if (window_impl->hcursor != NULL)
149     {
150       if (GetCursor () == window_impl->hcursor)
151         SetCursor (NULL);
152       GDI_CALL (DestroyCursor, (window_impl->hcursor));
153       window_impl->hcursor = NULL;
154     }
155   if (window_impl->hicon_big != NULL)
156     {
157       GDI_CALL (DestroyIcon, (window_impl->hicon_big));
158       window_impl->hicon_big = NULL;
159     }
160   if (window_impl->hicon_small != NULL)
161     {
162       GDI_CALL (DestroyIcon, (window_impl->hicon_small));
163       window_impl->hicon_small = NULL;
164     }
165
166   G_OBJECT_CLASS (parent_class)->finalize (object);
167 }
168
169 void
170 _gdk_win32_adjust_client_rect (GdkWindow *window,
171                                RECT      *rect)
172 {
173   LONG style, exstyle;
174
175   style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
176   exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
177   API_CALL (AdjustWindowRectEx, (rect, style, FALSE, exstyle));
178 }
179
180 static GdkColormap*
181 gdk_window_impl_win32_get_colormap (GdkDrawable *drawable)
182 {
183   GdkDrawableImplWin32 *drawable_impl;
184   
185   g_return_val_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable), NULL);
186
187   drawable_impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
188
189   if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only && 
190       drawable_impl->colormap == NULL)
191     {
192       drawable_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
193       g_object_ref (drawable_impl->colormap);
194     }
195   
196   return drawable_impl->colormap;
197 }
198
199 static void
200 gdk_window_impl_win32_set_colormap (GdkDrawable *drawable,
201                                     GdkColormap *cmap)
202 {
203   GdkWindowImplWin32 *impl;
204   GdkDrawableImplWin32 *draw_impl;
205   
206   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable));
207
208   impl = GDK_WINDOW_IMPL_WIN32 (drawable);
209   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
210
211   /* chain up */
212   GDK_DRAWABLE_CLASS (parent_class)->set_colormap (drawable, cmap);
213   
214   if (cmap)
215     {
216       /* XXX */
217       g_print ("gdk_window_impl_win32_set_colormap: XXX\n");
218     }
219 }
220
221 static void
222 gdk_window_impl_win32_get_size (GdkDrawable *drawable,
223                                 gint        *width,
224                                 gint        *height)
225 {
226   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable));
227
228   if (width)
229     *width = GDK_WINDOW_IMPL_WIN32 (drawable)->width;
230   if (height)
231     *height = GDK_WINDOW_IMPL_WIN32 (drawable)->height;
232 }
233
234 static GdkRegion*
235 gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable)
236 {
237   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (drawable);
238   GdkRectangle result_rect;
239
240   result_rect.x = 0;
241   result_rect.y = 0;
242   result_rect.width = impl->width;
243   result_rect.height = impl->height;
244
245   gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
246
247   return gdk_region_rectangle (&result_rect);
248 }
249
250 void
251 _gdk_root_window_size_init (void)
252 {
253   GdkWindowImplWin32 *impl;
254   GdkRectangle rect;
255   int i;
256
257   impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) _gdk_root)->impl);
258   rect = _gdk_monitors[0];
259   for (i = 1; i < _gdk_num_monitors; i++)
260     gdk_rectangle_union (&rect, _gdk_monitors+i, &rect);
261
262   impl->width = rect.width;
263   impl->height = rect.height;
264 }
265
266 void
267 _gdk_windowing_window_init (void)
268 {
269   GdkWindowObject *private;
270   GdkDrawableImplWin32 *draw_impl;
271
272   g_assert (_gdk_root == NULL);
273   
274   _gdk_root = g_object_new (GDK_TYPE_WINDOW, NULL);
275   private = (GdkWindowObject *)_gdk_root;
276   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
277   
278   draw_impl->handle = GetDesktopWindow ();
279   draw_impl->wrapper = GDK_DRAWABLE (private);
280   draw_impl->colormap = gdk_screen_get_default_colormap (_gdk_screen);
281   g_object_ref (draw_impl->colormap);
282   
283   private->window_type = GDK_WINDOW_ROOT;
284   private->depth = gdk_visual_get_system ()->depth;
285
286   _gdk_root_window_size_init ();
287  
288   _gdk_window_init_position (GDK_WINDOW (private));
289
290   gdk_win32_handle_table_insert ((HANDLE *) &draw_impl->handle, _gdk_root);
291
292   GDK_NOTE (MISC, g_print ("_gdk_root=%p\n", GDK_WINDOW_HWND (_gdk_root)));
293 }
294
295 static const gchar *
296 get_default_title (void)
297 {
298   const char *title;
299   title = g_get_application_name ();
300   if (!title)
301     title = g_get_prgname ();
302
303   return title;
304 }
305
306 /* RegisterGdkClass
307  *   is a wrapper function for RegisterWindowClassEx.
308  *   It creates at least one unique class for every 
309  *   GdkWindowType. If support for single window-specific icons
310  *   is ever needed (e.g Dialog specific), every such window should
311  *   get its own class
312  */
313 static ATOM
314 RegisterGdkClass (GdkWindowType wtype)
315 {
316   static ATOM klassTOPLEVEL = 0;
317   static ATOM klassDIALOG   = 0;
318   static ATOM klassCHILD    = 0;
319   static ATOM klassTEMP     = 0;
320   static HICON hAppIcon = NULL;
321   static HICON hAppIconSm = NULL;
322   static WNDCLASSEXW wcl; 
323   ATOM klass = 0;
324
325   wcl.cbSize = sizeof (WNDCLASSEX);
326   wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
327                   * on WM_SIZE and WM_MOVE. Flicker, Performance!
328                   */
329   wcl.lpfnWndProc = _gdk_win32_window_procedure;
330   wcl.cbClsExtra = 0;
331   wcl.cbWndExtra = 0;
332   wcl.hInstance = _gdk_app_hmodule;
333   wcl.hIcon = 0;
334   wcl.hIconSm = 0;
335   /* initialize once! */
336   if (0 == hAppIcon && 0 == hAppIconSm)
337     {
338       gchar sLoc [MAX_PATH+1];
339
340       if (0 != GetModuleFileName (_gdk_app_hmodule, sLoc, MAX_PATH))
341         {
342           ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
343           if (0 == hAppIcon && 0 == hAppIconSm)
344             {
345               if (0 != GetModuleFileName (_gdk_dll_hinstance, sLoc, MAX_PATH))
346                 ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
347             }
348         }
349       if (0 == hAppIcon && 0 == hAppIconSm)
350         {
351           hAppIcon = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
352                                 GetSystemMetrics (SM_CXICON),
353                                 GetSystemMetrics (SM_CYICON), 0);
354           hAppIconSm = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
355                                   GetSystemMetrics (SM_CXSMICON),
356                                   GetSystemMetrics (SM_CYSMICON), 0);
357         }
358     }
359   if (0 == hAppIcon)
360     hAppIcon = hAppIconSm;
361   else if (0 == hAppIconSm)
362     hAppIconSm = hAppIcon;
363
364   wcl.lpszMenuName = NULL;
365
366   /* initialize once per class */
367   /*
368    * HB: Setting the background brush leads to flicker, because we
369    * don't get asked how to clear the background. This is not what
370    * we want, at least not for input_only windows ...
371    */
372 #define ONCE_PER_CLASS() \
373   wcl.hIcon = CopyIcon (hAppIcon); \
374   wcl.hIconSm = CopyIcon (hAppIconSm); \
375   wcl.hbrBackground = NULL; \
376   wcl.hCursor = LoadCursor (NULL, IDC_ARROW); 
377   
378   switch (wtype)
379     {
380     case GDK_WINDOW_TOPLEVEL:
381       if (0 == klassTOPLEVEL)
382         {
383           wcl.lpszClassName = L"gdkWindowToplevel";
384           
385           ONCE_PER_CLASS ();
386           klassTOPLEVEL = RegisterClassExW (&wcl);
387         }
388       klass = klassTOPLEVEL;
389       break;
390       
391     case GDK_WINDOW_CHILD:
392       if (0 == klassCHILD)
393         {
394           wcl.lpszClassName = L"gdkWindowChild";
395           
396           wcl.style |= CS_PARENTDC; /* MSDN: ... enhances system performance. */
397           ONCE_PER_CLASS ();
398           klassCHILD = RegisterClassExW (&wcl);
399         }
400       klass = klassCHILD;
401       break;
402       
403     case GDK_WINDOW_DIALOG:
404       if (0 == klassDIALOG)
405         {
406           wcl.lpszClassName = L"gdkWindowDialog";
407           wcl.style |= CS_SAVEBITS;
408           ONCE_PER_CLASS ();
409           klassDIALOG = RegisterClassExW (&wcl);
410         }
411       klass = klassDIALOG;
412       break;
413       
414     case GDK_WINDOW_TEMP:
415       if (0 == klassTEMP)
416         {
417           wcl.lpszClassName = L"gdkWindowTemp";
418           wcl.style |= CS_SAVEBITS;
419           ONCE_PER_CLASS ();
420           klassTEMP = RegisterClassExW (&wcl);
421         }
422       klass = klassTEMP;
423       break;
424       
425     default:
426       g_assert_not_reached ();
427       break;
428     }
429   
430   if (klass == 0)
431     {
432       WIN32_API_FAILED ("RegisterClassExW");
433       g_error ("That is a fatal error");
434     }
435   return klass;
436 }
437
438 static GdkWindow*
439 gdk_window_new_internal (GdkWindow     *parent,
440                          GdkWindowAttr *attributes,
441                          gint           attributes_mask,
442                          gboolean       from_set_skip_taskbar_hint)
443 {
444   HWND hwndNew;
445   HANDLE hparent;
446   ATOM klass = 0;
447   DWORD dwStyle = 0, dwExStyle;
448   RECT rect;
449   GdkWindow *window;
450   GdkWindow *orig_parent;
451   GdkWindowObject *private;
452   GdkWindowImplWin32 *impl;
453   GdkDrawableImplWin32 *draw_impl;
454   GdkVisual *visual;
455   const gchar *title;
456   wchar_t *wtitle;
457   gint window_width, window_height;
458   gint offset_x = 0, offset_y = 0;
459
460   g_return_val_if_fail (attributes != NULL, NULL);
461
462   if (!parent)
463     parent = _gdk_root;
464
465   g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
466   
467   orig_parent = parent;
468
469   GDK_NOTE (MISC,
470             g_print ("gdk_window_new: %s\n",
471                      (attributes->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
472                       (attributes->window_type == GDK_WINDOW_CHILD ? "CHILD" :
473                        (attributes->window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
474                         (attributes->window_type == GDK_WINDOW_TEMP ? "TEMP" :
475                          "???"))))));
476
477   if (GDK_WINDOW_DESTROYED (parent))
478     return NULL;
479   
480   hparent = GDK_WINDOW_HWND (parent);
481
482   window = g_object_new (GDK_TYPE_WINDOW, NULL);
483   private = (GdkWindowObject *)window;
484   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
485   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
486   draw_impl->wrapper = GDK_DRAWABLE (window);
487
488   /* Windows with a foreign parent are treated as if they are children
489    * of the root window, except for actual creation.
490    */
491   if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
492     parent = _gdk_root;
493   
494   private->parent = (GdkWindowObject *)parent;
495
496   private->accept_focus = TRUE;
497   private->focus_on_map = TRUE;
498
499   if (attributes_mask & GDK_WA_X)
500     private->x = attributes->x;
501   else
502     private->x = 0;
503   
504   if (attributes_mask & GDK_WA_Y)
505     private->y = attributes->y;
506   else if (attributes_mask & GDK_WA_X)
507     private->y = 100;           /* ??? We must put it somewhere... */
508   else
509     private->y = 0;
510   
511   if (attributes_mask & GDK_WA_VISUAL)
512     visual = attributes->visual;
513   else
514     visual = gdk_visual_get_system ();
515
516   impl->width = (attributes->width > 1) ? (attributes->width) : (1);
517   impl->height = (attributes->height > 1) ? (attributes->height) : (1);
518   impl->extension_events_selected = FALSE;
519   if (attributes->wclass == GDK_INPUT_ONLY)
520     {
521       /* Backwards compatiblity - we've always ignored
522        * attributes->window_type for input-only windows
523        * before
524        */
525       if (parent == _gdk_root)
526         private->window_type = GDK_WINDOW_TEMP;
527       else
528         private->window_type = GDK_WINDOW_CHILD;
529     }
530   else
531     private->window_type = attributes->window_type;
532
533   if (attributes->wclass == GDK_INPUT_OUTPUT)
534     {
535       dwExStyle = 0;
536
537       private->input_only = FALSE;
538       private->depth = visual->depth;
539       
540       if (attributes_mask & GDK_WA_COLORMAP)
541         {
542           draw_impl->colormap = attributes->colormap;
543           g_object_ref (attributes->colormap);
544         }
545       else
546         {
547           draw_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
548           g_object_ref (draw_impl->colormap);
549         }
550     }
551   else
552     {
553       /* I very much doubt using WS_EX_TRANSPARENT actually
554        * corresponds to how X11 InputOnly windows work, but it appears
555        * to work well enough for the actual use cases in gtk.
556        */
557       dwExStyle = WS_EX_TRANSPARENT;
558       private->depth = 0;
559       private->input_only = TRUE;
560       draw_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
561       g_object_ref (draw_impl->colormap);
562       GDK_NOTE (MISC, g_print ("... GDK_INPUT_ONLY, system colormap"));
563     }
564
565   switch (private->window_type)
566     {
567     case GDK_WINDOW_TOPLEVEL:
568     case GDK_WINDOW_DIALOG:
569       if (parent != _gdk_root)
570         {
571           g_warning (G_STRLOC ": Toplevel windows must be created as children\n"
572                      "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
573           hparent = GetDesktopWindow ();
574         }
575       /* Children of foreign windows aren't toplevel windows */
576       if (GDK_WINDOW_TYPE (orig_parent) == GDK_WINDOW_FOREIGN)
577         {
578           dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN;
579         }
580       else
581         {
582           if (private->window_type == GDK_WINDOW_TOPLEVEL)
583             dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
584           else
585             dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
586
587           offset_x = _gdk_offset_x;
588           offset_y = _gdk_offset_y;
589         }
590       break;
591
592     case GDK_WINDOW_CHILD:
593       dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
594       break;
595
596     case GDK_WINDOW_TEMP:
597       /* A temp window is not necessarily a top level window */
598       dwStyle = (_gdk_root == parent ? WS_POPUP : WS_CHILDWINDOW);
599       dwStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
600       dwExStyle |= WS_EX_TOOLWINDOW;
601       offset_x = _gdk_offset_x;
602       offset_y = _gdk_offset_y;
603       break;
604
605     case GDK_WINDOW_ROOT:
606       g_error ("cannot make windows of type GDK_WINDOW_ROOT");
607       break;
608
609     default:
610       g_assert_not_reached ();
611     }
612
613   _gdk_window_init_position (GDK_WINDOW (private));
614
615   if (private->window_type != GDK_WINDOW_CHILD)
616     {
617       rect.left = rect.top = 0;
618       rect.right = impl->position_info.width;
619       rect.bottom = impl->position_info.height;
620
621       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
622
623       window_width = rect.right - rect.left;
624       window_height = rect.bottom - rect.top;
625     }
626   else
627     {
628       window_width = impl->position_info.width;
629       window_height = impl->position_info.height;
630     }
631
632   if (attributes_mask & GDK_WA_TITLE)
633     title = attributes->title;
634   else
635     title = get_default_title ();
636   if (!title || !*title)
637     title = "";
638
639   private->event_mask = GDK_STRUCTURE_MASK | attributes->event_mask;
640       
641   if (private->parent)
642     private->parent->children = g_list_prepend (private->parent->children, window);
643
644   klass = RegisterGdkClass (private->window_type);
645
646   wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
647   
648   hwndNew = CreateWindowExW (dwExStyle,
649                              MAKEINTRESOURCEW (klass),
650                              wtitle,
651                              dwStyle,
652                              ((attributes_mask & GDK_WA_X) ?
653                               impl->position_info.x - offset_x : CW_USEDEFAULT),
654                              impl->position_info.y - offset_y, 
655                              window_width, window_height,
656                              hparent,
657                              NULL,
658                              _gdk_app_hmodule,
659                              window);
660   if (GDK_WINDOW_HWND (window) != hwndNew)
661     {
662       g_warning ("gdk_window_new: gdk_event_translate::WM_CREATE (%p, %p) HWND mismatch.",
663                  GDK_WINDOW_HWND (window),
664                  hwndNew);
665
666       /* HB: IHMO due to a race condition the handle was increased by
667        * one, which causes much trouble. Because I can't find the 
668        * real bug, try to workaround it ...
669        * To reproduce: compile with MSVC 5, DEBUG=1
670        */
671 # if 0
672       gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
673       GDK_WINDOW_HWND (window) = hwndNew;
674       gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
675 # else
676       /* the old behaviour, but with warning */
677       draw_impl->handle = hwndNew;
678 # endif
679
680     }
681
682   g_object_ref (window);
683   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
684
685   GDK_NOTE (MISC, g_print ("... \"%s\" %dx%d@%+d%+d %p = %p\n",
686                            title,
687                            window_width, window_height,
688                            ((attributes_mask & GDK_WA_X) ?
689                             impl->position_info.x - offset_x: CW_USEDEFAULT),
690                            impl->position_info.y - offset_y, 
691                            hparent,
692                            GDK_WINDOW_HWND (window)));
693
694   g_free (wtitle);
695
696   if (draw_impl->handle == NULL)
697     {
698       WIN32_API_FAILED ("CreateWindowExW");
699       g_object_unref (window);
700       return NULL;
701     }
702
703   if (!from_set_skip_taskbar_hint && private->window_type == GDK_WINDOW_TEMP)
704     gdk_window_set_skip_taskbar_hint (window, TRUE);
705
706   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
707                                   (attributes->cursor) :
708                                   NULL));
709
710   return window;
711 }
712
713 GdkWindow*
714 gdk_window_new (GdkWindow     *parent,
715                 GdkWindowAttr *attributes,
716                 gint           attributes_mask)
717 {
718   return gdk_window_new_internal (parent, attributes, attributes_mask, FALSE);
719 }
720
721 GdkWindow *
722 gdk_window_foreign_new_for_display (GdkDisplay      *display,
723                                     GdkNativeWindow  anid)
724 {
725   GdkWindow *window;
726   GdkWindowObject *private;
727   GdkWindowImplWin32 *impl;
728   GdkDrawableImplWin32 *draw_impl;
729
730   HANDLE parent;
731   RECT rect;
732   POINT point;
733
734   g_return_val_if_fail (display == _gdk_display, NULL);
735
736   window = g_object_new (GDK_TYPE_WINDOW, NULL);
737   private = (GdkWindowObject *)window;
738   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
739   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
740   draw_impl->wrapper = GDK_DRAWABLE (window);
741   parent = GetParent ((HWND)anid);
742   
743   private->parent = gdk_win32_handle_table_lookup ((GdkNativeWindow) parent);
744   if (!private->parent || GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_FOREIGN)
745     private->parent = (GdkWindowObject *)_gdk_root;
746   
747   private->parent->children = g_list_prepend (private->parent->children, window);
748
749   draw_impl->handle = (HWND) anid;
750   GetClientRect ((HWND) anid, &rect);
751   point.x = rect.left;
752   point.y = rect.right;
753   ClientToScreen ((HWND) anid, &point);
754   if (parent != GetDesktopWindow ())
755     ScreenToClient (parent, &point);
756   private->x = point.x;
757   private->y = point.y;
758   impl->width = rect.right - rect.left;
759   impl->height = rect.bottom - rect.top;
760   private->window_type = GDK_WINDOW_FOREIGN;
761   private->destroyed = FALSE;
762   private->event_mask = GDK_ALL_EVENTS_MASK; /* XXX */
763   if (IsWindowVisible ((HWND) anid))
764     private->state &= (~GDK_WINDOW_STATE_WITHDRAWN);
765   else
766     private->state |= GDK_WINDOW_STATE_WITHDRAWN;
767   if (GetWindowLong ((HWND)anid, GWL_EXSTYLE) & WS_EX_TOPMOST)
768     private->state |= GDK_WINDOW_STATE_ABOVE;
769   else
770     private->state &= (~GDK_WINDOW_STATE_ABOVE);
771   private->state &= (~GDK_WINDOW_STATE_BELOW);
772
773   private->depth = gdk_visual_get_system ()->depth;
774
775   _gdk_window_init_position (GDK_WINDOW (private));
776
777   g_object_ref (window);
778   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
779
780   GDK_NOTE (MISC, g_print ("gdk_window_foreign_new_for_display: %p: %s@%+d%+d\n",
781                            (HWND) anid,
782                            _gdk_win32_drawable_description (window),
783                            private->x, private->y));
784
785   return window;
786 }
787
788 GdkWindow*
789 gdk_window_lookup (GdkNativeWindow hwnd)
790 {
791   return (GdkWindow*) gdk_win32_handle_table_lookup (hwnd); 
792 }
793
794 void
795 _gdk_windowing_window_destroy (GdkWindow *window,
796                                gboolean   recursing,
797                                gboolean   foreign_destroy)
798 {
799   GdkWindowObject *private = (GdkWindowObject *)window;
800
801   g_return_if_fail (GDK_IS_WINDOW (window));
802   
803   GDK_NOTE (MISC, g_print ("_gdk_windowing_window_destroy: %p\n",
804                            GDK_WINDOW_HWND (window)));
805
806   if (private->extension_events != 0)
807     _gdk_input_window_destroy (window);
808
809
810   if (!recursing && !foreign_destroy)
811     {
812       _gdk_win32_drawable_finish (private->impl);
813
814       private->destroyed = TRUE;
815       DestroyWindow (GDK_WINDOW_HWND (window));
816     }
817   gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
818 }
819
820 void
821 _gdk_windowing_window_destroy_foreign (GdkWindow *window)
822 {
823   /* It's somebody else's window, but in our hierarchy, so reparent it
824    * to the desktop, and then try to destroy it.
825    */
826   gdk_window_hide (window);
827   gdk_window_reparent (window, NULL, 0, 0);
828   
829   PostMessage (GDK_WINDOW_HWND (window), WM_CLOSE, 0, 0);
830 }
831
832 /* This function is called when the window really gone.
833  */
834 void
835 gdk_window_destroy_notify (GdkWindow *window)
836 {
837   g_return_if_fail (GDK_IS_WINDOW (window));
838
839   GDK_NOTE (EVENTS,
840             g_print ("gdk_window_destroy_notify: %p%s\n",
841                      GDK_WINDOW_HWND (window),
842                      (GDK_WINDOW_DESTROYED (window) ? " (destroyed)" : "")));
843
844   if (!GDK_WINDOW_DESTROYED (window))
845     {
846       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
847         g_warning ("window %p unexpectedly destroyed",
848                    GDK_WINDOW_HWND (window));
849
850       _gdk_window_destroy (window, TRUE);
851     }
852   
853   gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
854   g_object_unref (window);
855 }
856
857 static void
858 get_outer_rect (GdkWindow *window,
859                 gint       width,
860                 gint       height,
861                 RECT      *rect)
862 {
863   rect->left = rect->top = 0;
864   rect->right = width;
865   rect->bottom = height;
866       
867   _gdk_win32_adjust_client_rect (window, rect);
868 }
869
870 static void
871 adjust_for_gravity_hints (GdkWindowImplWin32 *impl,
872                           RECT               *outer_rect,
873                           gint               *x,
874                           gint               *y)
875 {
876   if (impl->hint_flags & GDK_HINT_WIN_GRAVITY)
877     {
878       gint orig_x = *x, orig_y = *y;
879
880       switch (impl->hints.win_gravity)
881         {
882         case GDK_GRAVITY_NORTH:
883         case GDK_GRAVITY_CENTER:
884         case GDK_GRAVITY_SOUTH:
885           *x -= (outer_rect->right - outer_rect->left) / 2;
886           *x += impl->width / 2;
887           break;
888               
889         case GDK_GRAVITY_SOUTH_EAST:
890         case GDK_GRAVITY_EAST:
891         case GDK_GRAVITY_NORTH_EAST:
892           *x -= outer_rect->right - outer_rect->left;
893           *x += impl->width;
894           break;
895
896         case GDK_GRAVITY_STATIC:
897           *x += outer_rect->left;
898           break;
899
900         default:
901           break;
902         }
903
904       switch (impl->hints.win_gravity)
905         {
906         case GDK_GRAVITY_WEST:
907         case GDK_GRAVITY_CENTER:
908         case GDK_GRAVITY_EAST:
909           *y -= (outer_rect->bottom - outer_rect->top) / 2;
910           *y += impl->height / 2;
911           break;
912
913         case GDK_GRAVITY_SOUTH_WEST:
914         case GDK_GRAVITY_SOUTH:
915         case GDK_GRAVITY_SOUTH_EAST:
916           *y -= outer_rect->bottom - outer_rect->top;
917           *y += impl->height;
918           break;
919
920         case GDK_GRAVITY_STATIC:
921           *y += outer_rect->top;
922           break;
923
924         default:
925           break;
926         }
927       GDK_NOTE (MISC,
928                 (orig_x != *x || orig_y != *y) ?
929                 g_print ("adjust_for_gravity_hints: x: %d->%d, y: %d->%d\n",
930                          orig_x, *x, orig_y, *y)
931                   : (void) 0);
932     }
933 }
934
935 static void
936 show_window_internal (GdkWindow *window,
937                       gboolean   raise,
938                       gboolean   deiconify)
939 {
940   GdkWindowObject *private;
941   HWND old_active_window;
942   gboolean focus_on_map = TRUE;
943
944   private = (GdkWindowObject *) window;
945
946   if (private->destroyed)
947     return;
948
949   GDK_NOTE (MISC, g_print ("show_window_internal: %p: %s%s%s\n",
950                            GDK_WINDOW_HWND (window),
951                            _gdk_win32_window_state_to_string (private->state),
952                            (raise ? " raise" : ""),
953                            (deiconify ? " deiconify" : "")));
954   
955   /* If asked to show (not deiconify) an withdrawn and iconified
956    * window, do that.
957    */
958   if (!deiconify &&
959       !GDK_WINDOW_IS_MAPPED (window) &&
960       (private->state & GDK_WINDOW_STATE_ICONIFIED))
961     {   
962       ShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
963       return;
964     }
965   
966   /* If asked to just show an iconified window, do nothing. */
967   if (!deiconify && (private->state & GDK_WINDOW_STATE_ICONIFIED))
968     return;
969   
970   /* If asked to deiconify an already noniconified window, do
971    * nothing. (Especially, don't cause the window to rise and
972    * activate. There are different calls for that.)
973    */
974   if (deiconify && !(private->state & GDK_WINDOW_STATE_ICONIFIED))
975     return;
976   
977   /* If asked to show (but not raise) a window that is already
978    * visible, do nothing.
979    */
980   if (!deiconify && !raise && IsWindowVisible (GDK_WINDOW_HWND (window)))
981     return;
982
983   /* Other cases */
984   
985   if (!GDK_WINDOW_IS_MAPPED (window))
986     {
987       gdk_synthesize_window_state (window,
988                                    GDK_WINDOW_STATE_WITHDRAWN,
989                                    0);
990       focus_on_map = private->focus_on_map;
991     }
992
993   /* Use SetWindowPos to show transparent windows so automatic redraws
994    * in other windows can be suppressed.
995    */
996   if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
997     {
998       UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE;
999       if (!raise)
1000         flags |= SWP_NOZORDER;
1001       if (!raise || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
1002         flags |= SWP_NOACTIVATE;
1003
1004       SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOP, 0, 0, 0, 0, flags);
1005       return;
1006     }
1007
1008   old_active_window = GetActiveWindow ();
1009
1010   if (private->state & (GDK_WINDOW_STATE_BELOW | GDK_WINDOW_STATE_ABOVE))
1011     {
1012       DWORD exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1013
1014       if (private->state & GDK_WINDOW_STATE_BELOW)
1015         exstyle &= (~WS_EX_TOPMOST);
1016       if (private->state & GDK_WINDOW_STATE_ABOVE)
1017         exstyle |= WS_EX_TOPMOST;
1018
1019       API_CALL (SetWindowLong, (GDK_WINDOW_HWND (window), GWL_EXSTYLE, exstyle));
1020     }
1021
1022   if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
1023     gdk_window_fullscreen (window);
1024   else if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
1025     ShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
1026   else if (private->state & GDK_WINDOW_STATE_ICONIFIED)
1027     ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
1028   else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
1029     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNOACTIVATE);
1030   else
1031     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
1032
1033   if (raise)
1034     {
1035       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
1036         SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOPMOST,
1037                       0, 0, 0, 0,
1038                       SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1039       else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL ||
1040                GDK_WINDOW_TYPE (window) == GDK_WINDOW_DIALOG)
1041         {
1042           if (focus_on_map && private->accept_focus)
1043             SetForegroundWindow (GDK_WINDOW_HWND (window));
1044           else
1045             SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOP,
1046                           0, 0, 0, 0,
1047                           SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1048         }
1049       else
1050         BringWindowToTop (GDK_WINDOW_HWND (window));
1051     }
1052   else if (old_active_window != GDK_WINDOW_HWND (window))
1053     SetActiveWindow (old_active_window);
1054 }
1055
1056 void
1057 gdk_window_show_unraised (GdkWindow *window)
1058 {
1059   g_return_if_fail (GDK_IS_WINDOW (window));
1060   
1061   show_window_internal (window, FALSE, FALSE);
1062 }
1063
1064 void
1065 gdk_window_show (GdkWindow *window)
1066 {
1067   g_return_if_fail (GDK_IS_WINDOW (window));
1068
1069   show_window_internal (window, TRUE, FALSE);
1070 }
1071
1072 void
1073 gdk_window_hide (GdkWindow *window)
1074 {
1075   GdkWindowObject *private;
1076   
1077   g_return_if_fail (GDK_IS_WINDOW (window));
1078
1079   private = (GdkWindowObject*) window;
1080   if (private->destroyed)
1081     return;
1082
1083   GDK_NOTE (MISC, g_print ("gdk_window_hide: %p: %s\n",
1084                            GDK_WINDOW_HWND (window),
1085                            _gdk_win32_window_state_to_string (private->state)));
1086   
1087   if (GDK_WINDOW_IS_MAPPED (window))
1088     gdk_synthesize_window_state (window,
1089                                  0,
1090                                  GDK_WINDOW_STATE_WITHDRAWN);
1091   
1092   _gdk_window_clear_update_area (window);
1093   
1094   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
1095     ShowOwnedPopups (GDK_WINDOW_HWND (window), FALSE);
1096   
1097   if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
1098     {
1099       SetWindowPos (GDK_WINDOW_HWND (window), HWND_BOTTOM,
1100                     0, 0, 0, 0,
1101                     SWP_HIDEWINDOW | SWP_NOREDRAW | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
1102     }
1103   else
1104     {
1105       ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
1106     }
1107 }
1108
1109 void
1110 gdk_window_withdraw (GdkWindow *window)
1111 {
1112   GdkWindowObject *private;
1113   
1114   g_return_if_fail (GDK_IS_WINDOW (window));
1115   
1116   private = (GdkWindowObject*) window;
1117   if (private->destroyed)
1118     return;
1119
1120   GDK_NOTE (MISC, g_print ("gdk_window_withdraw: %p: %s\n",
1121                            GDK_WINDOW_HWND (window),
1122                            _gdk_win32_window_state_to_string (private->state)));
1123   
1124   gdk_window_hide (window);     /* ??? */
1125 }
1126
1127 void
1128 gdk_window_move (GdkWindow *window,
1129                  gint       x,
1130                  gint       y)
1131 {
1132   GdkWindowObject *private = (GdkWindowObject *)window;
1133   GdkWindowImplWin32 *impl;
1134
1135   g_return_if_fail (GDK_IS_WINDOW (window));
1136
1137   if (GDK_WINDOW_DESTROYED (window))
1138     return;
1139
1140   GDK_NOTE (MISC, g_print ("gdk_window_move: %p: %+d%+d\n",
1141                            GDK_WINDOW_HWND (window), x, y));
1142       
1143   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
1144
1145   if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
1146     return;
1147
1148   /* Don't check GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD.
1149    * Foreign windows (another app's windows) might be children of our
1150    * windows! Especially in the case of gtkplug/socket.
1151    */ 
1152   if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1153     _gdk_window_move_resize_child (window, x, y, impl->width, impl->height);
1154   else
1155     {
1156       RECT outer_rect;
1157
1158       get_outer_rect (window, impl->width, impl->height, &outer_rect);
1159       
1160       adjust_for_gravity_hints (impl, &outer_rect, &x, &y);
1161
1162       GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,0,0,"
1163                                "NOACTIVATE|NOSIZE|NOZORDER)\n",
1164                                GDK_WINDOW_HWND (window),
1165                                x - _gdk_offset_x, y - _gdk_offset_y));
1166
1167       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1168                                x - _gdk_offset_x, y - _gdk_offset_y, 0, 0,
1169                                SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
1170     }
1171 }
1172
1173 void
1174 gdk_window_resize (GdkWindow *window,
1175                    gint       width,
1176                    gint       height)
1177 {
1178   GdkWindowObject *private = (GdkWindowObject*) window;
1179   GdkWindowImplWin32 *impl;
1180
1181   g_return_if_fail (GDK_IS_WINDOW (window));
1182
1183   if (GDK_WINDOW_DESTROYED (window))
1184     return;
1185
1186   if (width < 1)
1187     width = 1;
1188   if (height < 1)
1189     height = 1;
1190
1191   GDK_NOTE (MISC, g_print ("gdk_window_resize: %p: %dx%d\n",
1192                            GDK_WINDOW_HWND (window), width, height));
1193
1194   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
1195   
1196   if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
1197     return;
1198
1199   if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1200     _gdk_window_move_resize_child (window, private->x, private->y, width, height);
1201   else
1202     {
1203       RECT outer_rect;
1204
1205       get_outer_rect (window, width, height, &outer_rect);
1206
1207       GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,0,0,%ld,%ld,"
1208                                "NOACTIVATE|NOMOVE|NOZORDER)\n",
1209                                GDK_WINDOW_HWND (window),
1210                                outer_rect.right - outer_rect.left,
1211                                outer_rect.bottom - outer_rect.top));
1212
1213       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1214                                0, 0,
1215                                outer_rect.right - outer_rect.left,
1216                                outer_rect.bottom - outer_rect.top,
1217                                SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER));
1218       private->resize_count += 1;
1219     }
1220 }
1221
1222 void
1223 gdk_window_move_resize (GdkWindow *window,
1224                         gint       x,
1225                         gint       y,
1226                         gint       width,
1227                         gint       height)
1228 {
1229   GdkWindowObject *private = (GdkWindowObject*) window;
1230   GdkWindowImplWin32 *impl;
1231
1232   g_return_if_fail (GDK_IS_WINDOW (window));
1233
1234   if (GDK_WINDOW_DESTROYED (window))
1235     return;
1236
1237   if (width < 1)
1238     width = 1;
1239   if (height < 1)
1240     height = 1;
1241   
1242   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
1243
1244   if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
1245     return;
1246
1247   GDK_NOTE (MISC, g_print ("gdk_window_move_resize: %p: %dx%d@%+d%+d\n",
1248                            GDK_WINDOW_HWND (window),
1249                            width, height, x, y));
1250   
1251   if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1252     _gdk_window_move_resize_child (window, x, y, width, height);
1253   else
1254     {
1255       RECT outer_rect;
1256
1257       get_outer_rect (window, width, height, &outer_rect);
1258
1259       adjust_for_gravity_hints (impl, &outer_rect, &x, &y);
1260
1261       GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%ld,%ld,"
1262                                "NOACTIVATE|NOZORDER)\n",
1263                                GDK_WINDOW_HWND (window),
1264                                x - _gdk_offset_x, y - _gdk_offset_y,
1265                                outer_rect.right - outer_rect.left,
1266                                outer_rect.bottom - outer_rect.top));
1267                                
1268       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1269                                x - _gdk_offset_x, y - _gdk_offset_y,
1270                                outer_rect.right - outer_rect.left,
1271                                outer_rect.bottom - outer_rect.top,
1272                                SWP_NOACTIVATE | SWP_NOZORDER));
1273     }
1274 }
1275
1276 void
1277 gdk_window_reparent (GdkWindow *window,
1278                      GdkWindow *new_parent,
1279                      gint       x,
1280                      gint       y)
1281 {
1282   GdkWindowObject *window_private;
1283   GdkWindowObject *parent_private;
1284   GdkWindowObject *old_parent_private;
1285   GdkWindowImplWin32 *impl;
1286   gboolean was_toplevel;
1287   LONG style;
1288
1289   g_return_if_fail (GDK_IS_WINDOW (window));
1290   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1291   g_return_if_fail (window != _gdk_root);
1292
1293   if (GDK_WINDOW_DESTROYED (window) ||
1294       (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1295     {
1296       return;
1297     }
1298
1299   if (!new_parent)
1300     new_parent = _gdk_root;
1301
1302   window_private = (GdkWindowObject*) window;
1303   old_parent_private = (GdkWindowObject *) window_private->parent;
1304   parent_private = (GdkWindowObject*) new_parent;
1305   impl = GDK_WINDOW_IMPL_WIN32 (window_private->impl);
1306
1307   GDK_NOTE (MISC, g_print ("gdk_window_reparent: %p: %p\n",
1308                            GDK_WINDOW_HWND (window),
1309                            GDK_WINDOW_HWND (new_parent)));
1310
1311   style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1312
1313   was_toplevel = GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) == GetDesktopWindow ();
1314   if (was_toplevel && new_parent != _gdk_root)
1315     {
1316       /* Reparenting from top-level (child of desktop). Clear out
1317        * decorations.
1318        */
1319       style &= ~(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
1320       style |= WS_CHILD;
1321       SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
1322     }
1323   else if (new_parent == _gdk_root)
1324     {
1325       /* Reparenting to top-level. Add decorations. */
1326       style &= ~(WS_CHILD);
1327       style |= WS_OVERLAPPEDWINDOW;
1328       SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
1329     }
1330
1331   API_CALL (SetParent, (GDK_WINDOW_HWND (window),
1332                         GDK_WINDOW_HWND (new_parent)));
1333   
1334   API_CALL (MoveWindow, (GDK_WINDOW_HWND (window),
1335                          x, y, impl->width, impl->height, TRUE));
1336
1337   /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1338    * the root window
1339    */
1340   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1341     new_parent = _gdk_root;
1342   
1343   window_private->parent = (GdkWindowObject *)new_parent;
1344
1345   /* Switch the window type as appropriate */
1346
1347   switch (GDK_WINDOW_TYPE (new_parent))
1348     {
1349     case GDK_WINDOW_ROOT:
1350       if (impl->toplevel_window_type != -1)
1351         GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
1352       else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1353         GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1354       break;
1355
1356     case GDK_WINDOW_TOPLEVEL:
1357     case GDK_WINDOW_CHILD:
1358     case GDK_WINDOW_DIALOG:
1359     case GDK_WINDOW_TEMP:
1360       if (WINDOW_IS_TOPLEVEL (window))
1361         {
1362           /* Save the original window type so we can restore it if the
1363            * window is reparented back to be a toplevel.
1364            */
1365           impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
1366           GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1367         }
1368     }
1369
1370   if (old_parent_private)
1371     old_parent_private->children =
1372       g_list_remove (old_parent_private->children, window);
1373
1374   parent_private->children = g_list_prepend (parent_private->children, window);
1375   _gdk_window_init_position (GDK_WINDOW (window_private));
1376 }
1377
1378 void
1379 _gdk_windowing_window_clear_area (GdkWindow *window,
1380                                   gint       x,
1381                                   gint       y,
1382                                   gint       width,
1383                                   gint       height)
1384 {
1385   GdkWindowImplWin32 *impl;
1386
1387   g_return_if_fail (GDK_IS_WINDOW (window));
1388   
1389   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1390
1391   if (!GDK_WINDOW_DESTROYED (window))
1392     {
1393       HDC hdc;
1394
1395       if (width == 0)
1396         width = impl->width - x;
1397       if (height == 0)
1398         height = impl->height - y;
1399       GDK_NOTE (MISC, g_print ("_gdk_windowing_window_clear_area: %p: "
1400                                "%dx%d@%+d%+d\n",
1401                                GDK_WINDOW_HWND (window),
1402                                width, height, x, y));
1403       hdc = GetDC (GDK_WINDOW_HWND (window));
1404       IntersectClipRect (hdc, x, y, x + width + 1, y + height + 1);
1405       SendMessageW (GDK_WINDOW_HWND (window), WM_ERASEBKGND, (WPARAM) hdc, 0);
1406       GDI_CALL (ReleaseDC, (GDK_WINDOW_HWND (window), hdc));
1407     }
1408 }
1409
1410 void
1411 _gdk_windowing_window_clear_area_e (GdkWindow *window,
1412                                     gint       x,
1413                                     gint       y,
1414                                     gint       width,
1415                                     gint       height)
1416 {
1417   g_return_if_fail (GDK_IS_WINDOW (window));
1418   
1419   if (!GDK_WINDOW_DESTROYED (window))
1420     {
1421       RECT rect;
1422
1423       GDK_NOTE (MISC, g_print ("_gdk_windowing_window_clear_area_e: %p: "
1424                                "%dx%d@%+d%+d\n",
1425                                GDK_WINDOW_HWND (window),
1426                                width, height, x, y));
1427
1428       rect.left = x;
1429       rect.right = x + width + 1;
1430       rect.top = y;
1431       rect.bottom = y + height + 1;
1432       GDI_CALL (InvalidateRect, (GDK_WINDOW_HWND (window), &rect, TRUE));
1433       UpdateWindow (GDK_WINDOW_HWND (window));
1434     }
1435 }
1436
1437 void
1438 gdk_window_raise (GdkWindow *window)
1439 {
1440   g_return_if_fail (GDK_IS_WINDOW (window));
1441   
1442   if (!GDK_WINDOW_DESTROYED (window))
1443     {
1444       GDK_NOTE (MISC, g_print ("gdk_window_raise: %p\n",
1445                                GDK_WINDOW_HWND (window)));
1446
1447       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
1448         API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOPMOST,
1449                                  0, 0, 0, 0,
1450                                  SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1451       else if (((GdkWindowObject *)window)->accept_focus)
1452         API_CALL (BringWindowToTop, (GDK_WINDOW_HWND (window)));
1453       else
1454         API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
1455                                  0, 0, 0, 0,
1456                                  SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1457     }
1458 }
1459
1460 void
1461 gdk_window_lower (GdkWindow *window)
1462 {
1463   g_return_if_fail (GDK_IS_WINDOW (window));
1464   
1465   if (!GDK_WINDOW_DESTROYED (window))
1466     {
1467       GDK_NOTE (MISC, g_print ("gdk_window_lower: %p\n"
1468                                "... SetWindowPos(%p,HWND_BOTTOM,0,0,0,0,"
1469                                "NOACTIVATE|NOMOVE|NOSIZE)\n",
1470                                GDK_WINDOW_HWND (window),
1471                                GDK_WINDOW_HWND (window)));
1472
1473       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_BOTTOM,
1474                                0, 0, 0, 0,
1475                                SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1476     }
1477 }
1478
1479 void
1480 gdk_window_set_hints (GdkWindow *window,
1481                       gint       x,
1482                       gint       y,
1483                       gint       min_width,
1484                       gint       min_height,
1485                       gint       max_width,
1486                       gint       max_height,
1487                       gint       flags)
1488 {
1489   /* Note that this function is obsolete */
1490
1491   GdkWindowImplWin32 *impl;
1492
1493   g_return_if_fail (GDK_IS_WINDOW (window));
1494   
1495   if (GDK_WINDOW_DESTROYED (window))
1496     return;
1497   
1498   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1499
1500   GDK_NOTE (MISC, g_print ("gdk_window_set_hints: %p: %dx%d..%dx%d @%+d%+d\n",
1501                            GDK_WINDOW_HWND (window),
1502                            min_width, min_height, max_width, max_height,
1503                            x, y));
1504
1505   if (flags)
1506     {
1507       GdkGeometry geom;
1508       gint geom_mask = 0;
1509
1510       geom.min_width  = min_width;
1511       geom.min_height = min_height;
1512       geom.max_width  = max_width;
1513       geom.max_height = max_height;
1514
1515       if (flags & GDK_HINT_MIN_SIZE)
1516         geom_mask |= GDK_HINT_MIN_SIZE;
1517
1518       if (flags & GDK_HINT_MAX_SIZE)
1519         geom_mask |= GDK_HINT_MAX_SIZE;
1520
1521       gdk_window_set_geometry_hints (window, &geom, geom_mask);
1522     }
1523 }
1524
1525 void
1526 gdk_window_set_urgency_hint (GdkWindow *window,
1527                              gboolean   urgent)
1528 {
1529   FLASHWINFO flashwinfo;
1530   typedef BOOL (*PFN_FlashWindowEx) (FLASHWINFO*);
1531   PFN_FlashWindowEx flashWindowEx = NULL;
1532
1533   g_return_if_fail (GDK_IS_WINDOW (window));
1534   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1535   
1536   if (GDK_WINDOW_DESTROYED (window))
1537     return;
1538
1539   flashWindowEx = (PFN_FlashWindowEx) GetProcAddress (GetModuleHandle ("user32.dll"), "FlashWindowEx");
1540
1541   if (flashWindowEx)
1542     {
1543       flashwinfo.cbSize = sizeof (flashwinfo);
1544       flashwinfo.hwnd = GDK_WINDOW_HWND (window);
1545       if (urgent)
1546         flashwinfo.dwFlags = FLASHW_ALL | FLASHW_TIMER;
1547       else
1548         flashwinfo.dwFlags = FLASHW_STOP;
1549       flashwinfo.uCount = 0;
1550       flashwinfo.dwTimeout = 0;
1551       
1552       flashWindowEx (&flashwinfo);
1553     }
1554   else
1555     {
1556       FlashWindow (GDK_WINDOW_HWND (window), urgent);
1557     }
1558 }
1559
1560 static gboolean
1561 get_effective_window_decorations (GdkWindow       *window,
1562                                   GdkWMDecoration *decoration)
1563 {
1564   GdkWindowImplWin32 *impl;
1565
1566   impl = (GdkWindowImplWin32 *)((GdkWindowObject *)window)->impl;
1567
1568   if (gdk_window_get_decorations (window, decoration))
1569     return TRUE;
1570     
1571   if (((GdkWindowObject *) window)->window_type != GDK_WINDOW_TOPLEVEL &&
1572       ((GdkWindowObject *) window)->window_type != GDK_WINDOW_DIALOG)
1573     return FALSE;
1574
1575   if ((impl->hint_flags & GDK_HINT_MIN_SIZE) &&
1576       (impl->hint_flags & GDK_HINT_MAX_SIZE) &&
1577       impl->hints.min_width == impl->hints.max_width &&
1578       impl->hints.min_height == impl->hints.max_height)
1579     {
1580       *decoration = GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MAXIMIZE;
1581       if (impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
1582           impl->type_hint == GDK_WINDOW_TYPE_HINT_MENU ||
1583           impl->type_hint == GDK_WINDOW_TYPE_HINT_TOOLBAR)
1584         *decoration |= GDK_DECOR_MINIMIZE;
1585       else if (impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
1586         *decoration |= GDK_DECOR_MENU | GDK_DECOR_MINIMIZE;
1587
1588       return TRUE;
1589     }
1590   else if (impl->hint_flags & GDK_HINT_MAX_SIZE)
1591     {
1592       *decoration = GDK_DECOR_ALL | GDK_DECOR_MAXIMIZE;
1593       if (impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
1594           impl->type_hint == GDK_WINDOW_TYPE_HINT_MENU ||
1595           impl->type_hint == GDK_WINDOW_TYPE_HINT_TOOLBAR)
1596         *decoration |= GDK_DECOR_MINIMIZE;
1597       return TRUE;
1598     }
1599   else
1600     {
1601       switch (impl->type_hint)
1602         {
1603         case GDK_WINDOW_TYPE_HINT_DIALOG:
1604           *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1605           return TRUE;
1606
1607         case GDK_WINDOW_TYPE_HINT_MENU:
1608           *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1609           return TRUE;
1610
1611         case GDK_WINDOW_TYPE_HINT_TOOLBAR:
1612           gdk_window_set_skip_taskbar_hint (window, TRUE);
1613           *decoration = GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE;
1614           return TRUE;
1615
1616         case GDK_WINDOW_TYPE_HINT_UTILITY:
1617           return FALSE;
1618
1619         case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
1620           *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MENU
1621                   | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1622           return TRUE;
1623           
1624         case GDK_WINDOW_TYPE_HINT_DOCK:
1625           return FALSE;
1626           
1627         case GDK_WINDOW_TYPE_HINT_DESKTOP:
1628           return FALSE;
1629
1630         default:
1631           /* Fall thru */
1632         case GDK_WINDOW_TYPE_HINT_NORMAL:
1633           *decoration = GDK_DECOR_ALL;
1634           return TRUE;
1635         }
1636     }
1637     
1638   return FALSE;
1639 }
1640
1641 void 
1642 gdk_window_set_geometry_hints (GdkWindow      *window,
1643                                GdkGeometry    *geometry,
1644                                GdkWindowHints  geom_mask)
1645 {
1646   GdkWindowImplWin32 *impl;
1647
1648   g_return_if_fail (GDK_IS_WINDOW (window));
1649   
1650   if (GDK_WINDOW_DESTROYED (window))
1651     return;
1652
1653   GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints: %p\n",
1654                            GDK_WINDOW_HWND (window)));
1655
1656   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1657
1658   impl->hint_flags = geom_mask;
1659   impl->hints = *geometry;
1660
1661   if (geom_mask & GDK_HINT_POS)
1662     ; /* even the X11 mplementation doesn't care */
1663
1664   if (geom_mask & GDK_HINT_MIN_SIZE)
1665     {
1666       GDK_NOTE (MISC, g_print ("... MIN_SIZE: %dx%d\n",
1667                                geometry->min_width, geometry->min_height));
1668     }
1669   
1670   if (geom_mask & GDK_HINT_MAX_SIZE)
1671     {
1672       GDK_NOTE (MISC, g_print ("... MAX_SIZE: %dx%d\n",
1673                                geometry->max_width, geometry->max_height));
1674     }
1675
1676   if (geom_mask & GDK_HINT_BASE_SIZE)
1677     {
1678       GDK_NOTE (MISC, g_print ("... BASE_SIZE: %dx%d\n",
1679                                geometry->base_width, geometry->base_height));
1680     }
1681   
1682   if (geom_mask & GDK_HINT_RESIZE_INC)
1683     {
1684       GDK_NOTE (MISC, g_print ("... RESIZE_INC: (%d,%d)\n",
1685                                geometry->width_inc, geometry->height_inc));
1686     }
1687   
1688   if (geom_mask & GDK_HINT_ASPECT)
1689     {
1690       GDK_NOTE (MISC, g_print ("... ASPECT: %g--%g\n",
1691                                geometry->min_aspect, geometry->max_aspect));
1692     }
1693
1694   if (geom_mask & GDK_HINT_WIN_GRAVITY)
1695     {
1696       GDK_NOTE (MISC, g_print ("... GRAVITY: %d\n", geometry->win_gravity));
1697     }
1698
1699   update_style_bits (window);
1700 }
1701
1702 void
1703 gdk_window_set_title (GdkWindow   *window,
1704                       const gchar *title)
1705 {
1706   wchar_t *wtitle;
1707
1708   g_return_if_fail (GDK_IS_WINDOW (window));
1709   g_return_if_fail (title != NULL);
1710
1711   if (GDK_WINDOW_DESTROYED (window))
1712     return;
1713
1714   /* Empty window titles not allowed, so set it to just a period. */
1715   if (!title[0])
1716     title = ".";
1717   
1718   GDK_NOTE (MISC, g_print ("gdk_window_set_title: %p: %s\n",
1719                            GDK_WINDOW_HWND (window), title));
1720   
1721   wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
1722   API_CALL (SetWindowTextW, (GDK_WINDOW_HWND (window), wtitle));
1723   g_free (wtitle);
1724 }
1725
1726 void          
1727 gdk_window_set_role (GdkWindow   *window,
1728                      const gchar *role)
1729 {
1730   g_return_if_fail (GDK_IS_WINDOW (window));
1731   
1732   GDK_NOTE (MISC, g_print ("gdk_window_set_role: %p: %s\n",
1733                            GDK_WINDOW_HWND (window),
1734                            (role ? role : "NULL")));
1735   /* XXX */
1736 }
1737
1738 void          
1739 gdk_window_set_transient_for (GdkWindow *window, 
1740                               GdkWindow *parent)
1741 {
1742   HWND window_id, parent_id;
1743
1744   g_return_if_fail (GDK_IS_WINDOW (window));
1745   
1746   GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %p: %p\n",
1747                            GDK_WINDOW_HWND (window),
1748                            GDK_WINDOW_HWND (parent)));
1749
1750   if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (parent))
1751     return;
1752
1753   if (((GdkWindowObject *) window)->window_type == GDK_WINDOW_CHILD)
1754     {
1755       GDK_NOTE (MISC, g_print ("... a child window!\n"));
1756       return;
1757     }
1758   
1759   window_id = GDK_WINDOW_HWND (window);
1760   parent_id = GDK_WINDOW_HWND (parent);
1761
1762   /* This changes the *owner* of the window, despite the misleading
1763    * name. (Owner and parent are unrelated concepts.) At least that's
1764    * what people who seem to know what they talk about say on
1765    * USENET. Search on Google.
1766    */
1767   SetLastError (0);
1768   if (SetWindowLong (window_id, GWL_HWNDPARENT, (long) parent_id) == 0 &&
1769       GetLastError () != 0)
1770     WIN32_API_FAILED ("SetWindowLong");
1771 }
1772
1773 void
1774 gdk_window_set_background (GdkWindow      *window,
1775                            const GdkColor *color)
1776 {
1777   GdkWindowObject *private = (GdkWindowObject *)window;
1778   
1779   g_return_if_fail (GDK_IS_WINDOW (window));
1780   
1781   GDK_NOTE (MISC, g_print ("gdk_window_set_background: %p: %s\n",
1782                            GDK_WINDOW_HWND (window), 
1783                            _gdk_win32_color_to_string (color)));
1784
1785   private->bg_color = *color;
1786
1787   if (private->bg_pixmap &&
1788       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1789       private->bg_pixmap != GDK_NO_BG)
1790     {
1791       g_object_unref (private->bg_pixmap);
1792       private->bg_pixmap = NULL;
1793     }
1794 }
1795
1796 void
1797 gdk_window_set_back_pixmap (GdkWindow *window,
1798                             GdkPixmap *pixmap,
1799                             gint       parent_relative)
1800 {
1801   GdkWindowObject *private = (GdkWindowObject *)window;
1802
1803   g_return_if_fail (GDK_IS_WINDOW (window));
1804   g_return_if_fail (pixmap == NULL || !parent_relative);
1805   g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
1806   
1807   if (pixmap && !gdk_drawable_get_colormap (pixmap))
1808     {
1809       g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
1810       return;
1811     }
1812   
1813   if (private->bg_pixmap &&
1814       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1815       private->bg_pixmap != GDK_NO_BG)
1816     g_object_unref (private->bg_pixmap);
1817
1818   if (parent_relative)
1819     {
1820       private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
1821       GDK_NOTE (MISC, g_print (G_STRLOC ": setting background pixmap to parent_relative\n"));
1822     }
1823   else
1824     {
1825       if (pixmap)
1826         {
1827           g_object_ref (pixmap);
1828           private->bg_pixmap = pixmap;
1829         }
1830       else
1831         {
1832           private->bg_pixmap = GDK_NO_BG;
1833         }
1834     }
1835 }
1836
1837 void
1838 gdk_window_set_cursor (GdkWindow *window,
1839                        GdkCursor *cursor)
1840 {
1841   GdkWindowImplWin32 *impl;
1842   GdkCursorPrivate *cursor_private;
1843   GdkWindowObject *parent_window;
1844   HCURSOR hcursor;
1845   HCURSOR hprevcursor;
1846   
1847   g_return_if_fail (GDK_IS_WINDOW (window));
1848   
1849   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1850   cursor_private = (GdkCursorPrivate*) cursor;
1851   
1852   if (GDK_WINDOW_DESTROYED (window))
1853     return;
1854
1855   if (!cursor)
1856     hcursor = NULL;
1857   else
1858     hcursor = cursor_private->hcursor;
1859   
1860   GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %p: %p\n",
1861                            GDK_WINDOW_HWND (window),
1862                            hcursor));
1863
1864   /* First get the old cursor, if any (we wait to free the old one
1865    * since it may be the current cursor set in the Win32 API right
1866    * now).
1867    */
1868   hprevcursor = impl->hcursor;
1869
1870   if (hcursor == NULL)
1871     impl->hcursor = NULL;
1872   else
1873     {
1874       /* We must copy the cursor as it is OK to destroy the GdkCursor
1875        * while still in use for some window. See for instance
1876        * gimp_change_win_cursor() which calls gdk_window_set_cursor
1877        * (win, cursor), and immediately afterwards gdk_cursor_destroy
1878        * (cursor).
1879        */
1880       if ((impl->hcursor = CopyCursor (hcursor)) == NULL)
1881         WIN32_API_FAILED ("CopyCursor");
1882       GDK_NOTE (MISC, g_print ("... CopyCursor (%p) = %p\n",
1883                                hcursor, impl->hcursor));
1884     }
1885
1886   if (impl->hcursor != NULL)
1887     {
1888       /* If the pointer is over our window, set new cursor */
1889       GdkWindow *curr_window = gdk_window_get_pointer (window, NULL, NULL, NULL);
1890       if (curr_window == window)
1891         SetCursor (impl->hcursor);
1892       else
1893         {
1894           /* Climb up the tree and find whether our window is the
1895            * first ancestor that has cursor defined, and if so, set
1896            * new cursor.
1897            */
1898           GdkWindowObject *curr_window_obj = GDK_WINDOW_OBJECT (curr_window);
1899           while (curr_window_obj &&
1900                  !GDK_WINDOW_IMPL_WIN32 (curr_window_obj->impl)->hcursor)
1901             {
1902               curr_window_obj = curr_window_obj->parent;
1903               if (curr_window_obj == GDK_WINDOW_OBJECT (window))
1904                 {
1905                   SetCursor (impl->hcursor);
1906                   break;
1907                 }
1908             }
1909         }
1910     }
1911
1912   /* Destroy the previous cursor: Need to make sure it's no longer in
1913    * use before we destroy it, in case we're not over our window but
1914    * the cursor is still set to our old one.
1915    */
1916   if (hprevcursor != NULL)
1917     {
1918       if (GetCursor () == hprevcursor)
1919         {
1920           /* Look for a suitable cursor to use instead */
1921           hcursor = NULL;
1922           parent_window = GDK_WINDOW_OBJECT (window)->parent;
1923           while (hcursor == NULL)
1924             {
1925               if (parent_window)
1926                 {
1927                   impl = GDK_WINDOW_IMPL_WIN32 (parent_window->impl);
1928                   hcursor = impl->hcursor;
1929                   parent_window = parent_window->parent;
1930                 }
1931               else
1932                 {
1933                   hcursor = LoadCursor (NULL, IDC_ARROW);
1934                 }
1935             }
1936           SetCursor (hcursor);
1937         }
1938
1939       GDK_NOTE (MISC, g_print ("... DestroyCursor (%p)\n", hprevcursor));
1940       
1941       API_CALL (DestroyCursor, (hprevcursor));
1942     }
1943 }
1944
1945 void
1946 gdk_window_get_geometry (GdkWindow *window,
1947                          gint      *x,
1948                          gint      *y,
1949                          gint      *width,
1950                          gint      *height,
1951                          gint      *depth)
1952 {
1953   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1954   
1955   if (!window)
1956     window = _gdk_root;
1957   
1958   if (!GDK_WINDOW_DESTROYED (window))
1959     {
1960       RECT rect;
1961
1962       API_CALL (GetClientRect, (GDK_WINDOW_HWND (window), &rect));
1963
1964       if (window != _gdk_root)
1965         {
1966           POINT pt;
1967           GdkWindow *parent = gdk_window_get_parent (window);
1968
1969           pt.x = rect.left;
1970           pt.y = rect.top;
1971           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1972           ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
1973           rect.left = pt.x;
1974           rect.top = pt.y;
1975
1976           pt.x = rect.right;
1977           pt.y = rect.bottom;
1978           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1979           ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
1980           rect.right = pt.x;
1981           rect.bottom = pt.y;
1982
1983           if (parent == _gdk_root)
1984             {
1985               rect.left += _gdk_offset_x;
1986               rect.top += _gdk_offset_y;
1987               rect.right += _gdk_offset_x;
1988               rect.bottom += _gdk_offset_y;
1989             }
1990         }
1991
1992       if (x)
1993         *x = rect.left;
1994       if (y)
1995         *y = rect.top;
1996       if (width)
1997         *width = rect.right - rect.left;
1998       if (height)
1999         *height = rect.bottom - rect.top;
2000       if (depth)
2001         *depth = gdk_drawable_get_visual (window)->depth;
2002
2003       GDK_NOTE (MISC, g_print ("gdk_window_get_geometry: %p: %ldx%ldx%d@%+ld%+ld\n",
2004                                GDK_WINDOW_HWND (window),
2005                                rect.right - rect.left, rect.bottom - rect.top,
2006                                gdk_drawable_get_visual (window)->depth,
2007                                rect.left, rect.top));
2008     }
2009 }
2010
2011 gint
2012 gdk_window_get_origin (GdkWindow *window,
2013                        gint      *x,
2014                        gint      *y)
2015 {
2016   gint return_val;
2017   gint tx = 0;
2018   gint ty = 0;
2019
2020   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
2021
2022   if (!GDK_WINDOW_DESTROYED (window))
2023     {
2024       POINT pt;
2025
2026       pt.x = 0;
2027       pt.y = 0;
2028       ClientToScreen (GDK_WINDOW_HWND (window), &pt);
2029       tx = pt.x;
2030       ty = pt.y;
2031       return_val = 1;
2032     }
2033   else
2034     return_val = 0;
2035   
2036   if (x)
2037     *x = tx + _gdk_offset_x;
2038   if (y)
2039     *y = ty + _gdk_offset_y;
2040
2041   GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %p: %+d%+d\n",
2042                            GDK_WINDOW_HWND (window),
2043                            tx, ty));
2044   return return_val;
2045 }
2046
2047 gboolean
2048 gdk_window_get_deskrelative_origin (GdkWindow *window,
2049                                     gint      *x,
2050                                     gint      *y)
2051 {
2052   return gdk_window_get_origin (window, x, y);
2053 }
2054
2055 void
2056 gdk_window_get_root_origin (GdkWindow *window,
2057                             gint      *x,
2058                             gint      *y)
2059 {
2060   GdkRectangle rect;
2061
2062   g_return_if_fail (GDK_IS_WINDOW (window));
2063
2064   gdk_window_get_frame_extents (window, &rect);
2065
2066   if (x)
2067     *x = rect.x;
2068
2069   if (y)
2070     *y = rect.y;
2071
2072   GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %p: %+d%+d\n",
2073                            GDK_WINDOW_HWND (window), rect.x, rect.y));
2074 }
2075
2076 void
2077 gdk_window_get_frame_extents (GdkWindow    *window,
2078                               GdkRectangle *rect)
2079 {
2080   GdkWindowObject *private;
2081   HWND hwnd;
2082   RECT r;
2083
2084   g_return_if_fail (GDK_IS_WINDOW (window));
2085   g_return_if_fail (rect != NULL);
2086
2087   private = GDK_WINDOW_OBJECT (window);
2088
2089   rect->x = 0;
2090   rect->y = 0;
2091   rect->width = 1;
2092   rect->height = 1;
2093   
2094   if (GDK_WINDOW_DESTROYED (window))
2095     return;
2096
2097   /* FIXME: window is documented to be a toplevel GdkWindow, so is it really
2098    * necessary to walk its parent chain?
2099    */
2100   while (private->parent && ((GdkWindowObject*) private->parent)->parent)
2101     private = (GdkWindowObject*) private->parent;
2102
2103   hwnd = GDK_WINDOW_HWND (window);
2104   API_CALL (GetWindowRect, (hwnd, &r));
2105
2106   rect->x = r.left + _gdk_offset_x;
2107   rect->y = r.top + _gdk_offset_y;
2108   rect->width = r.right - r.left;
2109   rect->height = r.bottom - r.top;
2110
2111   GDK_NOTE (MISC, g_print ("gdk_window_get_frame_extents: %p: %ldx%ld@%+ld%+ld\n",
2112                            GDK_WINDOW_HWND (window),
2113                            r.right - r.left, r.bottom - r.top,
2114                            r.left, r.top));
2115 }
2116
2117 GdkWindow*
2118 _gdk_windowing_window_get_pointer (GdkDisplay      *display,
2119                                    GdkWindow       *window,
2120                                    gint            *x,
2121                                    gint            *y,
2122                                    GdkModifierType *mask)
2123 {
2124   GdkWindow *return_val;
2125   POINT screen_point, point;
2126   HWND hwnd, hwndc;
2127   BYTE kbd[256];
2128
2129   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
2130   
2131   return_val = NULL;
2132   GetCursorPos (&screen_point);
2133   point = screen_point;
2134   ScreenToClient (GDK_WINDOW_HWND (window), &point);
2135
2136   *x = point.x;
2137   *y = point.y;
2138
2139   if (window == _gdk_root)
2140     {
2141       *x += _gdk_offset_x;
2142       *y += _gdk_offset_y;
2143     }
2144
2145   hwnd = WindowFromPoint (screen_point);
2146   if (hwnd != NULL)
2147     {
2148       gboolean done = FALSE;
2149       
2150       while (!done)
2151         {
2152           point = screen_point;
2153           ScreenToClient (hwnd, &point);
2154           hwndc = ChildWindowFromPoint (hwnd, point);
2155           if (hwndc == NULL)
2156             done = TRUE;
2157           else if (hwndc == hwnd)
2158             done = TRUE;
2159           else
2160             hwnd = hwndc;
2161         }
2162       
2163       return_val = gdk_window_lookup ((GdkNativeWindow) hwnd);
2164     }
2165   else
2166     return_val = NULL;
2167       
2168   GetKeyboardState (kbd);
2169   *mask = 0;
2170   if (kbd[VK_SHIFT] & 0x80)
2171     *mask |= GDK_SHIFT_MASK;
2172   if (kbd[VK_CAPITAL] & 0x80)
2173     *mask |= GDK_LOCK_MASK;
2174   if (kbd[VK_CONTROL] & 0x80)
2175     *mask |= GDK_CONTROL_MASK;
2176   if (kbd[VK_MENU] & 0x80)
2177     *mask |= GDK_MOD1_MASK;
2178   if (kbd[VK_LBUTTON] & 0x80)
2179     *mask |= GDK_BUTTON1_MASK;
2180   if (kbd[VK_MBUTTON] & 0x80)
2181     *mask |= GDK_BUTTON2_MASK;
2182   if (kbd[VK_RBUTTON] & 0x80)
2183     *mask |= GDK_BUTTON3_MASK;
2184   
2185   return return_val;
2186 }
2187
2188 void
2189 _gdk_windowing_get_pointer (GdkDisplay       *display,
2190                             GdkScreen       **screen,
2191                             gint             *x,
2192                             gint             *y,
2193                             GdkModifierType  *mask)
2194 {
2195   g_return_if_fail (display == _gdk_display);
2196   
2197   *screen = _gdk_screen;
2198   _gdk_windowing_window_get_pointer (_gdk_display, _gdk_root, x, y, mask);
2199 }
2200
2201 void
2202 gdk_display_warp_pointer (GdkDisplay *display,
2203                           GdkScreen  *screen,
2204                           gint        x,
2205                           gint        y)
2206 {
2207   g_return_if_fail (display == _gdk_display);
2208   g_return_if_fail (screen == _gdk_screen);
2209
2210   SetCursorPos (x - _gdk_offset_x, y - _gdk_offset_y);
2211 }
2212
2213 GdkWindow*
2214 _gdk_windowing_window_at_pointer (GdkDisplay *display,
2215                                   gint       *win_x,
2216                                   gint       *win_y)
2217 {
2218   GdkWindow *window;
2219   POINT point, pointc;
2220   HWND hwnd, hwndc;
2221   RECT rect;
2222
2223   GetCursorPos (&pointc);
2224   point = pointc;
2225   hwnd = WindowFromPoint (point);
2226
2227   if (hwnd == NULL)
2228     {
2229       window = _gdk_root;
2230       *win_x = pointc.x + _gdk_offset_x;
2231       *win_y = pointc.y + _gdk_offset_y;
2232       return window;
2233     }
2234       
2235   ScreenToClient (hwnd, &point);
2236
2237   do {
2238     hwndc = ChildWindowFromPoint (hwnd, point);
2239     ClientToScreen (hwnd, &point);
2240     ScreenToClient (hwndc, &point);
2241   } while (hwndc != hwnd && (hwnd = hwndc, 1));
2242
2243   window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
2244
2245   if (window && (win_x || win_y))
2246     {
2247       GetClientRect (hwnd, &rect);
2248       *win_x = point.x - rect.left;
2249       *win_y = point.y - rect.top;
2250     }
2251
2252   GDK_NOTE (MISC, g_print ("_gdk_windowing_window_at_pointer: %+d%+d %p%s\n",
2253                            *win_x, *win_y,
2254                            hwnd,
2255                            (window == NULL ? " NULL" : "")));
2256
2257   return window;
2258 }
2259
2260 GdkEventMask  
2261 gdk_window_get_events (GdkWindow *window)
2262 {
2263   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
2264
2265   if (GDK_WINDOW_DESTROYED (window))
2266     return 0;
2267
2268   return GDK_WINDOW_OBJECT (window)->event_mask;
2269 }
2270
2271 void          
2272 gdk_window_set_events (GdkWindow   *window,
2273                        GdkEventMask event_mask)
2274 {
2275   g_return_if_fail (GDK_IS_WINDOW (window));
2276
2277   if (GDK_WINDOW_DESTROYED (window))
2278     return;
2279
2280   /* gdk_window_new() always sets the GDK_STRUCTURE_MASK, so better
2281    * set it here, too. Not that I know or remember why it is
2282    * necessary, will have to test some day.
2283    */
2284   GDK_WINDOW_OBJECT (window)->event_mask = GDK_STRUCTURE_MASK | event_mask;
2285 }
2286
2287 static void
2288 do_shape_combine_region (GdkWindow *window,
2289                          HRGN       hrgn,
2290                          gint       x, gint y)
2291 {
2292   RECT rect;
2293
2294   GetClientRect (GDK_WINDOW_HWND (window), &rect);
2295   _gdk_win32_adjust_client_rect (window, &rect);
2296
2297   OffsetRgn (hrgn, -rect.left, -rect.top);
2298   OffsetRgn (hrgn, x, y);
2299
2300   /* If this is a top-level window, add the title bar to the region */
2301   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
2302     {
2303       HRGN tmp = CreateRectRgn (0, 0, rect.right - rect.left, -rect.top);
2304       CombineRgn (hrgn, hrgn, tmp, RGN_OR);
2305       DeleteObject (tmp);
2306     }
2307   
2308   SetWindowRgn (GDK_WINDOW_HWND (window), hrgn, TRUE);
2309 }
2310
2311 void
2312 gdk_window_shape_combine_mask (GdkWindow *window,
2313                                GdkBitmap *mask,
2314                                gint x, gint y)
2315 {
2316   GdkWindowObject *private = (GdkWindowObject *)window;
2317
2318   g_return_if_fail (GDK_IS_WINDOW (window));
2319
2320   if (!mask)
2321     {
2322       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %p: none\n",
2323                                GDK_WINDOW_HWND (window)));
2324       SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
2325
2326       private->shaped = FALSE;
2327     }
2328   else
2329     {
2330       HRGN hrgn;
2331
2332       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %p: %p\n",
2333                                GDK_WINDOW_HWND (window),
2334                                GDK_WINDOW_HWND (mask)));
2335
2336       /* Convert mask bitmap to region */
2337       hrgn = _gdk_win32_bitmap_to_hrgn (mask);
2338
2339       do_shape_combine_region (window, hrgn, x, y);
2340
2341       private->shaped = TRUE;
2342     }
2343 }
2344
2345 void 
2346 gdk_window_input_shape_combine_mask (GdkWindow *window,
2347                                      GdkBitmap *mask,
2348                                      gint       x,
2349                                      gint       y)
2350 {
2351   g_return_if_fail (GDK_IS_WINDOW (window));
2352
2353   /* Not yet implemented
2354    *
2355    * I don't think there is anything in the Win32 API to directly
2356    * support this. And anyway, as we don't currently support RGBA
2357    * windows, it doesn't really matter.
2358    *
2359    * When we do support RGBA, input shape functionality could probably
2360    * be implemented by saving the input shape region in the per-window
2361    * private data, and then simply checking before generating an input
2362    * event whether the event's coordinates are inside the region.
2363    */
2364 }
2365
2366 void
2367 gdk_window_set_override_redirect (GdkWindow *window,
2368                                   gboolean   override_redirect)
2369 {
2370   g_return_if_fail (GDK_IS_WINDOW (window));
2371
2372   g_warning ("gdk_window_set_override_redirect not implemented");
2373 }
2374
2375 void
2376 gdk_window_set_accept_focus (GdkWindow *window,
2377                              gboolean accept_focus)
2378 {
2379   GdkWindowObject *private;
2380
2381   g_return_if_fail (GDK_IS_WINDOW (window));
2382
2383   private = (GdkWindowObject *)window;  
2384   
2385   accept_focus = accept_focus != FALSE;
2386
2387   if (private->accept_focus != accept_focus)
2388     private->accept_focus = accept_focus;
2389 }
2390
2391 void
2392 gdk_window_set_focus_on_map (GdkWindow *window,
2393                              gboolean focus_on_map)
2394 {
2395   GdkWindowObject *private;
2396
2397   g_return_if_fail (GDK_IS_WINDOW (window));
2398
2399   private = (GdkWindowObject *)window;  
2400   
2401   focus_on_map = focus_on_map != FALSE;
2402
2403   if (private->focus_on_map != focus_on_map)
2404     private->focus_on_map = focus_on_map;
2405 }
2406
2407 void          
2408 gdk_window_set_icon_list (GdkWindow *window,
2409                           GList     *pixbufs)
2410 {
2411   GdkPixbuf *pixbuf, *big_pixbuf, *small_pixbuf;
2412   gint big_diff, small_diff;
2413   gint big_w, big_h, small_w, small_h;
2414   gint w, h;
2415   gint dw, dh, diff;
2416   HICON small_hicon, big_hicon;
2417   GdkWindowImplWin32 *impl;
2418   gint i, big_i, small_i;
2419
2420   g_return_if_fail (GDK_IS_WINDOW (window));
2421
2422   if (GDK_WINDOW_DESTROYED (window))
2423     return;
2424
2425   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
2426
2427   /* ideal sizes for small and large icons */
2428   big_w = GetSystemMetrics (SM_CXICON);
2429   big_h = GetSystemMetrics (SM_CYICON);
2430   small_w = GetSystemMetrics (SM_CXSMICON);
2431   small_h = GetSystemMetrics (SM_CYSMICON);
2432
2433   /* find closest sized icons in the list */
2434   big_pixbuf = NULL;
2435   small_pixbuf = NULL;
2436   big_diff = 0;
2437   small_diff = 0;
2438   i = 0;
2439   while (pixbufs)
2440     {
2441       pixbuf = (GdkPixbuf*) pixbufs->data;
2442       w = gdk_pixbuf_get_width (pixbuf);
2443       h = gdk_pixbuf_get_height (pixbuf);
2444
2445       dw = ABS (w - big_w);
2446       dh = ABS (h - big_h);
2447       diff = dw*dw + dh*dh;
2448       if (big_pixbuf == NULL || diff < big_diff)
2449         {
2450           big_pixbuf = pixbuf;
2451           big_diff = diff;
2452           big_i = i;
2453         }
2454
2455       dw = ABS (w - small_w);
2456       dh = ABS (h - small_h);
2457       diff = dw*dw + dh*dh;
2458       if (small_pixbuf == NULL || diff < small_diff)
2459         {
2460           small_pixbuf = pixbuf;
2461           small_diff = diff;
2462           small_i = i;
2463         }
2464
2465       pixbufs = g_list_next (pixbufs);
2466       i++;
2467     }
2468
2469   /* Create the icons */
2470   big_hicon = _gdk_win32_pixbuf_to_hicon (big_pixbuf);
2471   small_hicon = _gdk_win32_pixbuf_to_hicon (small_pixbuf);
2472
2473   /* Set the icons */
2474   SendMessageW (GDK_WINDOW_HWND (window), WM_SETICON, ICON_BIG,
2475                 (LPARAM)big_hicon);
2476   SendMessageW (GDK_WINDOW_HWND (window), WM_SETICON, ICON_SMALL,
2477                 (LPARAM)small_hicon);
2478
2479   /* Store the icons, destroying any previous icons */
2480   if (impl->hicon_big)
2481     GDI_CALL (DestroyIcon, (impl->hicon_big));
2482   impl->hicon_big = big_hicon;
2483   if (impl->hicon_small)
2484     GDI_CALL (DestroyIcon, (impl->hicon_small));
2485   impl->hicon_small = small_hicon;
2486 }
2487
2488 void          
2489 gdk_window_set_icon (GdkWindow *window, 
2490                      GdkWindow *icon_window,
2491                      GdkPixmap *pixmap,
2492                      GdkBitmap *mask)
2493 {
2494   g_return_if_fail (GDK_IS_WINDOW (window));
2495
2496   /* do nothing, use gdk_window_set_icon_list instead */
2497 }
2498
2499 void
2500 gdk_window_set_icon_name (GdkWindow   *window, 
2501                           const gchar *name)
2502 {
2503   g_return_if_fail (GDK_IS_WINDOW (window));
2504
2505   if (GDK_WINDOW_DESTROYED (window))
2506     return;
2507   
2508 #if 0
2509   /* This is not the correct thing to do. We should keep both the
2510    * "normal" window title, and the icon name. When the window is
2511    * minimized, call SetWindowText() with the icon name, and when the
2512    * window is restored, with the normal window title. Also, the name
2513    * is in UTF-8, so we should do the normal conversion to either wide
2514    * chars or system codepage, and use either the W or A version of
2515    * SetWindowText(), depending on Windows version.
2516    */
2517   API_CALL (SetWindowText, (GDK_WINDOW_HWND (window), name));
2518 #endif
2519 }
2520
2521 GdkWindow *
2522 gdk_window_get_group (GdkWindow *window)
2523 {
2524   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2525   g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
2526
2527   if (GDK_WINDOW_DESTROYED (window))
2528     return NULL;
2529   
2530   g_warning ("gdk_window_get_group not yet implemented");
2531
2532   return NULL;
2533 }
2534
2535 void          
2536 gdk_window_set_group (GdkWindow *window, 
2537                       GdkWindow *leader)
2538 {
2539   g_return_if_fail (GDK_IS_WINDOW (window));
2540   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2541   g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
2542
2543   if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
2544     return;
2545   
2546   g_warning ("gdk_window_set_group not implemented");
2547 }
2548
2549 static void
2550 update_single_bit (LONG *style,
2551                    BOOL  all,
2552                    int   gdk_bit,
2553                    int   style_bit)
2554 {
2555   /* all controls the interpretation of gdk_bit -- if all is true, gdk_bit
2556      indicates whether style_bit is off; if all is false, gdk bit indicate whether
2557      style_bit is on */
2558   if ((!all && gdk_bit) || (all && !gdk_bit))
2559     *style |= style_bit;
2560   else
2561     *style &= ~style_bit;
2562 }
2563
2564 static void
2565 update_style_bits (GdkWindow *window)
2566 {
2567   GdkWMDecoration decorations;
2568   GdkWMFunction functions;
2569   LONG style, exstyle;
2570   BOOL all;
2571   RECT rect, before, after;
2572
2573   style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2574   exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
2575
2576   GetClientRect (GDK_WINDOW_HWND (window), &before);
2577   after = before;
2578   AdjustWindowRectEx (&before, style, FALSE, exstyle);
2579
2580   if (get_effective_window_decorations (window, &decorations))
2581     {
2582       all = (decorations & GDK_DECOR_ALL);
2583       update_single_bit (&style, all, decorations & GDK_DECOR_BORDER, WS_BORDER);
2584       update_single_bit (&style, all, decorations & GDK_DECOR_RESIZEH, WS_THICKFRAME);
2585       update_single_bit (&style, all, decorations & GDK_DECOR_TITLE, WS_CAPTION);
2586       update_single_bit (&style, all, decorations & GDK_DECOR_MENU, WS_SYSMENU);
2587       update_single_bit (&style, all, decorations & GDK_DECOR_MINIMIZE, WS_MINIMIZEBOX);
2588       update_single_bit (&style, all, decorations & GDK_DECOR_MAXIMIZE, WS_MAXIMIZEBOX);
2589     }
2590
2591   /* XXX this is actually incorrect.  The menu entries should be added or removed
2592      from the system menu without affecting the window style. */
2593   if (_gdk_window_get_functions (window, &functions))
2594     {
2595       all = (functions & GDK_DECOR_ALL);
2596       update_single_bit (&style, all, functions & GDK_FUNC_RESIZE, WS_THICKFRAME);
2597       update_single_bit (&style, all, functions & GDK_FUNC_MOVE, WS_THICKFRAME | WS_SYSMENU);
2598       update_single_bit (&style, all, functions & GDK_FUNC_MINIMIZE, WS_MINIMIZE);
2599       update_single_bit (&style, all, functions & GDK_FUNC_MOVE, WS_MAXIMIZE);
2600       update_single_bit (&style, all, functions & GDK_FUNC_CLOSE, WS_SYSMENU);
2601     }
2602     
2603   SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
2604
2605   AdjustWindowRectEx (&after, style, FALSE, exstyle);
2606
2607   GetWindowRect (GDK_WINDOW_HWND (window), &rect);
2608   rect.left += after.left - before.left;
2609   rect.top += after.top - before.top;
2610   rect.right += after.right - before.right;
2611   rect.bottom += after.bottom - before.bottom;
2612
2613   SetWindowPos (GDK_WINDOW_HWND (window), NULL,
2614                 rect.left, rect.top,
2615                 rect.right - rect.left, rect.bottom - rect.top,
2616                 SWP_FRAMECHANGED | SWP_NOACTIVATE | 
2617                 SWP_NOREPOSITION | SWP_NOZORDER);
2618 }
2619
2620 static GQuark
2621 get_decorations_quark ()
2622 {
2623   static GQuark quark = 0;
2624   
2625   if (!quark)
2626     quark = g_quark_from_static_string ("gdk-window-decorations");
2627   
2628   return quark;
2629 }
2630
2631 void
2632 gdk_window_set_decorations (GdkWindow      *window,
2633                             GdkWMDecoration decorations)
2634 {
2635   GdkWMDecoration* decorations_copy;
2636   
2637   g_return_if_fail (GDK_IS_WINDOW (window));
2638   
2639   GDK_NOTE (MISC, g_print ("gdk_window_set_decorations: %p: %s %s%s%s%s%s%s\n",
2640                            GDK_WINDOW_HWND (window),
2641                            (decorations & GDK_DECOR_ALL ? "clearing" : "setting"),
2642                            (decorations & GDK_DECOR_BORDER ? "BORDER " : ""),
2643                            (decorations & GDK_DECOR_RESIZEH ? "RESIZEH " : ""),
2644                            (decorations & GDK_DECOR_TITLE ? "TITLE " : ""),
2645                            (decorations & GDK_DECOR_MENU ? "MENU " : ""),
2646                            (decorations & GDK_DECOR_MINIMIZE ? "MINIMIZE " : ""),
2647                            (decorations & GDK_DECOR_MAXIMIZE ? "MAXIMIZE " : "")));
2648
2649   decorations_copy = g_malloc (sizeof (GdkWMDecoration));
2650   *decorations_copy = decorations;
2651   g_object_set_qdata_full (G_OBJECT (window), get_decorations_quark (), decorations_copy, g_free);
2652
2653   update_style_bits (window);
2654 }
2655
2656 gboolean
2657 gdk_window_get_decorations (GdkWindow       *window,
2658                             GdkWMDecoration *decorations)
2659 {
2660   GdkWMDecoration* decorations_set;
2661   
2662   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2663
2664   decorations_set = g_object_get_qdata (G_OBJECT (window), get_decorations_quark ());
2665   if (decorations_set)
2666     *decorations = *decorations_set;
2667
2668   return (decorations_set != NULL);
2669 }
2670
2671 static GQuark
2672 get_functions_quark ()
2673 {
2674   static GQuark quark = 0;
2675   
2676   if (!quark)
2677     quark = g_quark_from_static_string ("gdk-window-functions");
2678   
2679   return quark;
2680 }
2681
2682 void
2683 gdk_window_set_functions (GdkWindow    *window,
2684                           GdkWMFunction functions)
2685 {
2686   GdkWMFunction* functions_copy;
2687
2688   g_return_if_fail (GDK_IS_WINDOW (window));
2689   
2690   GDK_NOTE (MISC, g_print ("gdk_window_set_functions: %p: %s %s%s%s%s%s\n",
2691                            GDK_WINDOW_HWND (window),
2692                            (functions & GDK_FUNC_ALL ? "clearing" : "setting"),
2693                            (functions & GDK_FUNC_RESIZE ? "RESIZE " : ""),
2694                            (functions & GDK_FUNC_MOVE ? "MOVE " : ""),
2695                            (functions & GDK_FUNC_MINIMIZE ? "MINIMIZE " : ""),
2696                            (functions & GDK_FUNC_MAXIMIZE ? "MAXIMIZE " : ""),
2697                            (functions & GDK_FUNC_CLOSE ? "CLOSE " : "")));
2698
2699   functions_copy = g_malloc (sizeof (GdkWMFunction));
2700   *functions_copy = functions;
2701   g_object_set_qdata_full (G_OBJECT (window), get_functions_quark (), functions_copy, g_free);
2702
2703   update_style_bits (window);
2704 }
2705
2706 gboolean
2707 _gdk_window_get_functions (GdkWindow     *window,
2708                            GdkWMFunction *functions)
2709 {
2710   GdkWMDecoration* functions_set;
2711   
2712   functions_set = g_object_get_qdata (G_OBJECT (window), get_functions_quark ());
2713   if (functions_set)
2714     *functions = *functions_set;
2715
2716   return (functions_set != NULL);
2717 }
2718
2719 static void
2720 QueryTree (HWND   hwnd,
2721            HWND **children,
2722            gint  *nchildren)
2723 {
2724   guint i, n;
2725   HWND child;
2726
2727   n = 0;
2728   do {
2729     if (n == 0)
2730       child = GetWindow (hwnd, GW_CHILD);
2731     else
2732       child = GetWindow (child, GW_HWNDNEXT);
2733     if (child != NULL)
2734       n++;
2735   } while (child != NULL);
2736
2737   if (n > 0)
2738     {
2739       *children = g_new (HWND, n);
2740       for (i = 0; i < n; i++)
2741         {
2742           if (i == 0)
2743             child = GetWindow (hwnd, GW_CHILD);
2744           else
2745             child = GetWindow (child, GW_HWNDNEXT);
2746           *children[i] = child;
2747         }
2748     }
2749 }
2750
2751 static void
2752 gdk_propagate_shapes (HANDLE   win,
2753                       gboolean merge)
2754 {
2755    RECT emptyRect;
2756    HRGN region, childRegion;
2757    HWND *list = NULL;
2758    gint i, num;
2759
2760    SetRectEmpty (&emptyRect);
2761    region = CreateRectRgnIndirect (&emptyRect);
2762    if (merge)
2763      GetWindowRgn (win, region);
2764    
2765    QueryTree (win, &list, &num);
2766    if (list != NULL)
2767      {
2768        WINDOWPLACEMENT placement;
2769
2770        placement.length = sizeof (WINDOWPLACEMENT);
2771        /* go through all child windows and combine regions */
2772        for (i = 0; i < num; i++)
2773          {
2774            GetWindowPlacement (list[i], &placement);
2775            if (placement.showCmd == SW_SHOWNORMAL)
2776              {
2777                childRegion = CreateRectRgnIndirect (&emptyRect);
2778                GetWindowRgn (list[i], childRegion);
2779                CombineRgn (region, region, childRegion, RGN_OR);
2780                DeleteObject (childRegion);
2781              }
2782           }
2783        SetWindowRgn (win, region, TRUE);
2784        g_free (list);
2785      }
2786    else
2787      DeleteObject (region);
2788 }
2789
2790 void
2791 gdk_window_set_child_shapes (GdkWindow *window)
2792 {
2793   g_return_if_fail (GDK_IS_WINDOW (window));
2794    
2795   if (GDK_WINDOW_DESTROYED (window))
2796     return;
2797
2798   gdk_propagate_shapes (GDK_WINDOW_HWND (window), FALSE);
2799 }
2800
2801 void
2802 gdk_window_merge_child_shapes (GdkWindow *window)
2803 {
2804   g_return_if_fail (GDK_IS_WINDOW (window));
2805   
2806   if (GDK_WINDOW_DESTROYED (window))
2807     return;
2808
2809   gdk_propagate_shapes (GDK_WINDOW_HWND (window), TRUE);
2810 }
2811
2812 void 
2813 gdk_window_set_child_input_shapes (GdkWindow *window)
2814 {
2815   g_return_if_fail (GDK_IS_WINDOW (window));
2816   
2817   /* Not yet implemented. See comment in
2818    * gdk_window_input_shape_combine_mask().
2819    */
2820 }
2821
2822 void 
2823 gdk_window_merge_child_input_shapes (GdkWindow *window)
2824 {
2825   g_return_if_fail (GDK_IS_WINDOW (window));
2826   
2827   /* Not yet implemented. See comment in
2828    * gdk_window_input_shape_combine_mask().
2829    */
2830 }
2831
2832 gboolean 
2833 gdk_window_set_static_gravities (GdkWindow *window,
2834                                  gboolean   use_static)
2835 {
2836   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2837
2838   return !use_static;
2839 }
2840
2841 void
2842 gdk_window_begin_resize_drag (GdkWindow     *window,
2843                               GdkWindowEdge  edge,
2844                               gint           button,
2845                               gint           root_x,
2846                               gint           root_y,
2847                               guint32        timestamp)
2848 {
2849   WPARAM winedge;
2850   
2851   g_return_if_fail (GDK_IS_WINDOW (window));
2852   
2853   if (GDK_WINDOW_DESTROYED (window))
2854     return;
2855
2856   /* Tell Windows to start interactively resizing the window by pretending that
2857    * the left pointer button was clicked in the suitable edge or corner. This
2858    * will only work if the button is down when this function is called, and
2859    * will only work with button 1 (left), since Windows only allows window
2860    * dragging using the left mouse button.
2861    */
2862   if (button != 1)
2863     return;
2864   
2865   /* Must break the automatic grab that occured when the button was
2866    * pressed, otherwise it won't work.
2867    */
2868   gdk_display_pointer_ungrab (_gdk_display, 0);
2869
2870   switch (edge)
2871     {
2872     case GDK_WINDOW_EDGE_NORTH_WEST:
2873       winedge = HTTOPLEFT;
2874       break;
2875
2876     case GDK_WINDOW_EDGE_NORTH:
2877       winedge = HTTOP;
2878       break;
2879
2880     case GDK_WINDOW_EDGE_NORTH_EAST:
2881       winedge = HTTOPRIGHT;
2882       break;
2883
2884     case GDK_WINDOW_EDGE_WEST:
2885       winedge = HTLEFT;
2886       break;
2887
2888     case GDK_WINDOW_EDGE_EAST:
2889       winedge = HTRIGHT;
2890       break;
2891
2892     case GDK_WINDOW_EDGE_SOUTH_WEST:
2893       winedge = HTBOTTOMLEFT;
2894       break;
2895
2896     case GDK_WINDOW_EDGE_SOUTH:
2897       winedge = HTBOTTOM;
2898       break;
2899
2900     case GDK_WINDOW_EDGE_SOUTH_EAST:
2901     default:
2902       winedge = HTBOTTOMRIGHT;
2903       break;
2904     }
2905
2906   DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, winedge,
2907                   MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
2908 }
2909
2910 void
2911 gdk_window_begin_move_drag (GdkWindow *window,
2912                             gint       button,
2913                             gint       root_x,
2914                             gint       root_y,
2915                             guint32    timestamp)
2916 {
2917   g_return_if_fail (GDK_IS_WINDOW (window));
2918   
2919   if (GDK_WINDOW_DESTROYED (window))
2920     return;
2921
2922   /* Tell Windows to start interactively moving the window by pretending that
2923    * the left pointer button was clicked in the titlebar. This will only work
2924    * if the button is down when this function is called, and will only work
2925    * with button 1 (left), since Windows only allows window dragging using the
2926    * left mouse button.
2927    */
2928   if (button != 1)
2929     return;
2930   
2931   /* Must break the automatic grab that occured when the button was pressed,
2932    * otherwise it won't work.
2933    */
2934   gdk_display_pointer_ungrab (_gdk_display, 0);
2935
2936   DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, HTCAPTION,
2937                   MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
2938 }
2939
2940
2941 /*
2942  * Setting window states
2943  */
2944 void
2945 gdk_window_iconify (GdkWindow *window)
2946 {
2947   HWND old_active_window;
2948
2949   g_return_if_fail (GDK_IS_WINDOW (window));
2950
2951   if (GDK_WINDOW_DESTROYED (window))
2952     return;
2953
2954   GDK_NOTE (MISC, g_print ("gdk_window_iconify: %p: %s\n",
2955                            GDK_WINDOW_HWND (window),
2956                            _gdk_win32_window_state_to_string (((GdkWindowObject *) window)->state)));
2957
2958   if (GDK_WINDOW_IS_MAPPED (window))
2959     {
2960       old_active_window = GetActiveWindow ();
2961       ShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
2962       if (old_active_window != GDK_WINDOW_HWND (window))
2963         SetActiveWindow (old_active_window);
2964     }
2965   else
2966     {
2967       gdk_synthesize_window_state (window,
2968                                    0,
2969                                    GDK_WINDOW_STATE_ICONIFIED);
2970     }
2971 }
2972
2973 void
2974 gdk_window_deiconify (GdkWindow *window)
2975 {
2976   g_return_if_fail (GDK_IS_WINDOW (window));
2977
2978   if (GDK_WINDOW_DESTROYED (window))
2979     return;
2980
2981   GDK_NOTE (MISC, g_print ("gdk_window_deiconify: %p: %s\n",
2982                            GDK_WINDOW_HWND (window),
2983                            _gdk_win32_window_state_to_string (((GdkWindowObject *) window)->state)));
2984
2985   if (GDK_WINDOW_IS_MAPPED (window))
2986     {  
2987       show_window_internal (window, FALSE, TRUE);
2988     }
2989   else
2990     {
2991       gdk_synthesize_window_state (window,
2992                                    GDK_WINDOW_STATE_ICONIFIED,
2993                                    0);
2994     }
2995 }
2996
2997 void
2998 gdk_window_stick (GdkWindow *window)
2999 {
3000   g_return_if_fail (GDK_IS_WINDOW (window));
3001
3002   if (GDK_WINDOW_DESTROYED (window))
3003     return;
3004
3005   /* FIXME: Do something? */
3006 }
3007
3008 void
3009 gdk_window_unstick (GdkWindow *window)
3010 {
3011   g_return_if_fail (GDK_IS_WINDOW (window));
3012
3013   if (GDK_WINDOW_DESTROYED (window))
3014     return;
3015
3016   /* FIXME: Do something? */
3017 }
3018
3019 void
3020 gdk_window_maximize (GdkWindow *window)
3021 {
3022   g_return_if_fail (GDK_IS_WINDOW (window));
3023
3024   if (GDK_WINDOW_DESTROYED (window))
3025     return;
3026
3027   GDK_NOTE (MISC, g_print ("gdk_window_maximize: %p: %s\n",
3028                            GDK_WINDOW_HWND (window),
3029                            _gdk_win32_window_state_to_string (((GdkWindowObject *) window)->state)));
3030
3031   if (GDK_WINDOW_IS_MAPPED (window))
3032     ShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
3033   else
3034     gdk_synthesize_window_state (window,
3035                                  0,
3036                                  GDK_WINDOW_STATE_MAXIMIZED);
3037 }
3038
3039 void
3040 gdk_window_unmaximize (GdkWindow *window)
3041 {
3042   g_return_if_fail (GDK_IS_WINDOW (window));
3043
3044   if (GDK_WINDOW_DESTROYED (window))
3045     return;
3046
3047   GDK_NOTE (MISC, g_print ("gdk_window_unmaximize: %p: %s\n",
3048                            GDK_WINDOW_HWND (window),
3049                            _gdk_win32_window_state_to_string (((GdkWindowObject *) window)->state)));
3050
3051   if (GDK_WINDOW_IS_MAPPED (window))
3052     ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
3053   else
3054     gdk_synthesize_window_state (window,
3055                                  GDK_WINDOW_STATE_MAXIMIZED,
3056                                  0);
3057 }
3058
3059 typedef struct _FullscreenInfo FullscreenInfo;
3060
3061 struct _FullscreenInfo
3062 {
3063   RECT  r;
3064   guint hint_flags;
3065   LONG  style;
3066 };
3067
3068 void
3069 gdk_window_fullscreen (GdkWindow *window)
3070 {
3071   gint width, height;
3072   FullscreenInfo *fi;
3073   GdkWindowObject *private = (GdkWindowObject *) window;
3074
3075   g_return_if_fail (GDK_IS_WINDOW (window));
3076
3077   fi = g_new (FullscreenInfo, 1);
3078
3079   if (!GetWindowRect (GDK_WINDOW_HWND (window), &(fi->r)))
3080     g_free (fi);
3081   else
3082     {
3083       GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
3084
3085       width = GetSystemMetrics (SM_CXSCREEN);
3086       height = GetSystemMetrics (SM_CYSCREEN);
3087  
3088       /* remember for restoring */
3089       fi->hint_flags = impl->hint_flags;
3090       impl->hint_flags &= ~GDK_HINT_MAX_SIZE;
3091       g_object_set_data (G_OBJECT (window), "fullscreen-info", fi);
3092       fi->style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
3093
3094       SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, 
3095                      (fi->style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP);
3096
3097       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
3098                                0, 0, width, height,
3099                                SWP_NOCOPYBITS | SWP_SHOWWINDOW));
3100
3101       gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
3102     }
3103 }
3104
3105 void
3106 gdk_window_unfullscreen (GdkWindow *window)
3107 {
3108   FullscreenInfo *fi;
3109   GdkWindowObject *private = (GdkWindowObject *) window;
3110
3111   g_return_if_fail (GDK_IS_WINDOW (window));
3112
3113   fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
3114   if (fi)
3115     {
3116       GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
3117
3118       impl->hint_flags = fi->hint_flags;
3119       SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, fi->style);
3120       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_NOTOPMOST,
3121                                fi->r.left, fi->r.top,
3122                                fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
3123                                SWP_NOCOPYBITS | SWP_SHOWWINDOW));
3124       
3125       g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL);
3126       g_free (fi);
3127
3128       gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
3129     }
3130 }
3131
3132 void
3133 gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
3134 {
3135   g_return_if_fail (GDK_IS_WINDOW (window));
3136
3137   if (GDK_WINDOW_DESTROYED (window))
3138     return;
3139
3140   if (GDK_WINDOW_IS_MAPPED (window))
3141     {
3142       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
3143                                setting ? HWND_TOPMOST : HWND_NOTOPMOST,
3144                                0, 0, 0, 0,
3145                                SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
3146     }
3147   else
3148     gdk_synthesize_window_state (window,
3149                                  setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
3150                                  setting ? GDK_WINDOW_STATE_ABOVE : 0);
3151 }
3152
3153 void
3154 gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
3155 {
3156   g_return_if_fail (GDK_IS_WINDOW (window));
3157
3158   if (GDK_WINDOW_DESTROYED (window))
3159     return;
3160
3161   if (GDK_WINDOW_IS_MAPPED (window))
3162     {
3163       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
3164                                setting ? HWND_BOTTOM : HWND_NOTOPMOST,
3165                                0, 0, 0, 0,
3166                                SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
3167     }
3168   else
3169     gdk_synthesize_window_state (window,
3170                                  setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
3171                                  setting ? GDK_WINDOW_STATE_BELOW : 0);
3172 }
3173
3174 void
3175 gdk_window_focus (GdkWindow *window,
3176                   guint32    timestamp)
3177 {
3178   g_return_if_fail (GDK_IS_WINDOW (window));
3179
3180   if (GDK_WINDOW_DESTROYED (window))
3181     return;
3182   
3183   GDK_NOTE (MISC, g_print ("gdk_window_focus: %p: %s\n",
3184                            GDK_WINDOW_HWND (window),
3185                            _gdk_win32_window_state_to_string (((GdkWindowObject *) window)->state)));
3186
3187   if (((GdkWindowObject *) window)->state & GDK_WINDOW_STATE_MAXIMIZED)
3188     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMAXIMIZED);
3189   else
3190     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
3191   SetFocus (GDK_WINDOW_HWND (window));
3192 }
3193
3194 void
3195 gdk_window_set_modal_hint (GdkWindow *window,
3196                            gboolean   modal)
3197 {
3198   GdkWindowObject *private;
3199
3200   g_return_if_fail (GDK_IS_WINDOW (window));
3201   
3202   if (GDK_WINDOW_DESTROYED (window))
3203     return;
3204
3205   private = (GdkWindowObject*) window;
3206
3207   private->modal_hint = modal;
3208
3209   if (GDK_WINDOW_IS_MAPPED (window))
3210     API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), 
3211                              modal ? HWND_TOPMOST : HWND_NOTOPMOST,
3212                              0, 0, 0, 0,
3213                              SWP_NOMOVE | SWP_NOSIZE));
3214 }
3215
3216 void
3217 gdk_window_set_skip_taskbar_hint (GdkWindow *window,
3218                                   gboolean   skips_taskbar)
3219 {
3220   static GdkWindow *owner = NULL;
3221   GdkWindowAttr wa;
3222
3223   g_return_if_fail (GDK_IS_WINDOW (window));
3224
3225   GDK_NOTE (MISC, g_print ("gdk_window_set_skip_taskbar_hint: %p: %s\n",
3226                            GDK_WINDOW_HWND (window),
3227                            skips_taskbar ? "TRUE" : "FALSE"));
3228
3229   if (skips_taskbar)
3230     {
3231       if (owner == NULL)
3232         {
3233           wa.window_type = GDK_WINDOW_TEMP;
3234           wa.wclass = GDK_INPUT_OUTPUT;
3235           wa.width = wa.height = 1;
3236           wa.event_mask = 0;
3237           owner = gdk_window_new_internal (NULL, &wa, 0, TRUE);
3238         }
3239
3240       SetWindowLong (GDK_WINDOW_HWND (window), GWL_HWNDPARENT,
3241                      (long) GDK_WINDOW_HWND (owner));
3242
3243 #if 0 /* Should we also turn off the minimize and maximize buttons? */
3244       SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE,
3245                      GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE) & ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU));
3246       SetWindowPos (GDK_WINDOW_HWND (window), NULL,
3247                     0, 0, 0, 0,
3248                     SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
3249                     SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
3250 #endif
3251     }
3252   else
3253     {
3254       SetWindowLong (GDK_WINDOW_HWND (window), GWL_HWNDPARENT, 0);
3255     }
3256 }
3257
3258 void
3259 gdk_window_set_skip_pager_hint (GdkWindow *window,
3260                                 gboolean   skips_pager)
3261 {
3262   g_return_if_fail (GDK_IS_WINDOW (window));
3263 }
3264
3265 void
3266 gdk_window_set_type_hint (GdkWindow        *window,
3267                           GdkWindowTypeHint hint)
3268 {
3269   g_return_if_fail (GDK_IS_WINDOW (window));
3270   
3271   if (GDK_WINDOW_DESTROYED (window))
3272     return;
3273
3274   GDK_NOTE (MISC, g_print ("gdk_window_set_type_hint: %p: %d\n",
3275                            GDK_WINDOW_HWND (window), hint));
3276
3277   ((GdkWindowImplWin32 *)((GdkWindowObject *)window)->impl)->type_hint = hint;
3278
3279   update_style_bits (window);
3280 }
3281
3282 GdkWindowTypeHint
3283 gdk_window_get_type_hint (GdkWindow *window)
3284 {
3285   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
3286   
3287   if (GDK_WINDOW_DESTROYED (window))
3288     return GDK_WINDOW_TYPE_HINT_NORMAL;
3289
3290   return GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->type_hint;
3291 }
3292
3293 void
3294 gdk_window_shape_combine_region (GdkWindow *window,
3295                                  GdkRegion *shape_region,
3296                                  gint       offset_x,
3297                                  gint       offset_y)
3298 {
3299   GdkWindowObject *private = (GdkWindowObject *)window;
3300
3301   g_return_if_fail (GDK_IS_WINDOW (window));
3302
3303   if (GDK_WINDOW_DESTROYED (window))
3304     return;
3305
3306   if (!shape_region)
3307     {
3308       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_region: %p: none\n",
3309                                GDK_WINDOW_HWND (window)));
3310       SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
3311
3312       private->shaped = FALSE;
3313     }
3314   else
3315     {
3316       HRGN hrgn;
3317
3318       hrgn = _gdk_win32_gdkregion_to_hrgn (shape_region, 0, 0);
3319       
3320       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_region: %p: %p\n",
3321                                GDK_WINDOW_HWND (window),
3322                                hrgn));
3323
3324       do_shape_combine_region (window, hrgn, offset_x, offset_y);
3325
3326       private->shaped = TRUE;
3327     }
3328 }
3329
3330 void 
3331 gdk_window_input_shape_combine_region (GdkWindow *window,
3332                                        GdkRegion *shape_region,
3333                                        gint       offset_x,
3334                                        gint       offset_y)
3335 {
3336   g_return_if_fail (GDK_IS_WINDOW (window));
3337
3338   /* Not yet implemented. See comment in
3339    * gdk_window_input_shape_combine_mask().
3340    */
3341 }
3342
3343 GdkWindow *
3344 gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
3345 {
3346   g_return_val_if_fail (display == _gdk_display, NULL);
3347
3348   return gdk_window_lookup (anid);
3349 }
3350
3351 void
3352 gdk_window_enable_synchronized_configure (GdkWindow *window)
3353 {
3354   g_return_if_fail (GDK_IS_WINDOW (window));
3355 }
3356
3357 void
3358 gdk_window_configure_finished (GdkWindow *window)
3359 {
3360   g_return_if_fail (GDK_IS_WINDOW (window));
3361 }
3362
3363 void
3364 gdk_window_beep (GdkWindow *window)
3365 {
3366   gdk_display_beep (_gdk_display);
3367 }