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