]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow-win32.c
Some cursor work for csw(win32), more left to do
[~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_new_internal: %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_windowing_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_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_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_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_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_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_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_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_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_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   GdkWindowObject *private = (GdkWindowObject *)window;
1876
1877   /* TODO_CSW? but win32 has no XSetWindowBackgroundPixmap */
1878 }
1879
1880 static void
1881 gdk_win32_window_set_cursor (GdkWindow *window,
1882                              GdkCursor *cursor)
1883 {
1884   GdkWindowImplWin32 *impl;
1885   GdkCursorPrivate *cursor_private;
1886   GdkWindowObject *parent_window;
1887   HCURSOR hcursor;
1888   HCURSOR hprevcursor;
1889   
1890   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1891   cursor_private = (GdkCursorPrivate*) cursor;
1892   
1893   if (GDK_WINDOW_DESTROYED (window))
1894     return;
1895
1896   if (!cursor)
1897     hcursor = NULL;
1898   else
1899     hcursor = cursor_private->hcursor;
1900   
1901   GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %p: %p\n",
1902                            GDK_WINDOW_HWND (window),
1903                            hcursor));
1904
1905   /* First get the old cursor, if any (we wait to free the old one
1906    * since it may be the current cursor set in the Win32 API right
1907    * now).
1908    */
1909   hprevcursor = impl->hcursor;
1910
1911   if (hcursor == NULL)
1912     impl->hcursor = NULL;
1913   else
1914     {
1915       /* We must copy the cursor as it is OK to destroy the GdkCursor
1916        * while still in use for some window. See for instance
1917        * gimp_change_win_cursor() which calls gdk_window_set_cursor
1918        * (win, cursor), and immediately afterwards gdk_cursor_destroy
1919        * (cursor).
1920        */
1921       if ((impl->hcursor = CopyCursor (hcursor)) == NULL)
1922         WIN32_API_FAILED ("CopyCursor");
1923       GDK_NOTE (MISC, g_print ("... CopyCursor (%p) = %p\n",
1924                                hcursor, impl->hcursor));
1925     }
1926
1927   if (impl->hcursor != NULL)
1928     {
1929       /* If the pointer is over our window, set new cursor */
1930       GdkWindow *curr_window = gdk_window_get_pointer (window, NULL, NULL, NULL);
1931       if (curr_window == window ||
1932           (curr_window && window == gdk_window_get_toplevel (curr_window)))
1933         SetCursor (impl->hcursor);
1934       else
1935         {
1936           /* Climb up the tree and find whether our window is the
1937            * first ancestor that has cursor defined, and if so, set
1938            * new cursor.
1939            */
1940           GdkWindowObject *curr_window_obj = GDK_WINDOW_OBJECT (curr_window);
1941           while (curr_window_obj &&
1942                  !GDK_WINDOW_IMPL_WIN32 (curr_window_obj->impl)->hcursor)
1943             {
1944               curr_window_obj = curr_window_obj->parent;
1945               if (curr_window_obj == GDK_WINDOW_OBJECT (window))
1946                 {
1947                   SetCursor (impl->hcursor);
1948                   break;
1949                 }
1950             }
1951         }
1952     }
1953
1954   /* Destroy the previous cursor: Need to make sure it's no longer in
1955    * use before we destroy it, in case we're not over our window but
1956    * the cursor is still set to our old one.
1957    */
1958   if (hprevcursor != NULL)
1959     {
1960       if (GetCursor () == hprevcursor)
1961         {
1962           /* Look for a suitable cursor to use instead */
1963           hcursor = NULL;
1964           parent_window = GDK_WINDOW_OBJECT (window)->parent;
1965           while (hcursor == NULL)
1966             {
1967               if (parent_window)
1968                 {
1969                   impl = GDK_WINDOW_IMPL_WIN32 (parent_window->impl);
1970                   hcursor = impl->hcursor;
1971                   parent_window = parent_window->parent;
1972                 }
1973               else
1974                 {
1975                   hcursor = LoadCursor (NULL, IDC_ARROW);
1976                 }
1977             }
1978           SetCursor (hcursor);
1979         }
1980
1981       GDK_NOTE (MISC, g_print ("... DestroyCursor (%p)\n", hprevcursor));
1982       
1983       API_CALL (DestroyCursor, (hprevcursor));
1984     }
1985 }
1986
1987 static void
1988 gdk_win32_window_get_geometry (GdkWindow *window,
1989                                gint      *x,
1990                                gint      *y,
1991                                gint      *width,
1992                                gint      *height,
1993                                gint      *depth)
1994 {
1995   if (!window)
1996     window = _gdk_root;
1997   
1998   if (!GDK_WINDOW_DESTROYED (window))
1999     {
2000       RECT rect;
2001
2002       API_CALL (GetClientRect, (GDK_WINDOW_HWND (window), &rect));
2003
2004       if (window != _gdk_root)
2005         {
2006           POINT pt;
2007           GdkWindow *parent = gdk_window_get_parent (window);
2008
2009           pt.x = rect.left;
2010           pt.y = rect.top;
2011           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
2012           ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
2013           rect.left = pt.x;
2014           rect.top = pt.y;
2015
2016           pt.x = rect.right;
2017           pt.y = rect.bottom;
2018           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
2019           ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
2020           rect.right = pt.x;
2021           rect.bottom = pt.y;
2022
2023           if (parent == _gdk_root)
2024             {
2025               rect.left += _gdk_offset_x;
2026               rect.top += _gdk_offset_y;
2027               rect.right += _gdk_offset_x;
2028               rect.bottom += _gdk_offset_y;
2029             }
2030         }
2031
2032       if (x)
2033         *x = rect.left;
2034       if (y)
2035         *y = rect.top;
2036       if (width)
2037         *width = rect.right - rect.left;
2038       if (height)
2039         *height = rect.bottom - rect.top;
2040       if (depth)
2041         *depth = gdk_drawable_get_visual (window)->depth;
2042
2043       GDK_NOTE (MISC, g_print ("gdk_window_get_geometry: %p: %ldx%ldx%d@%+ld%+ld\n",
2044                                GDK_WINDOW_HWND (window),
2045                                rect.right - rect.left, rect.bottom - rect.top,
2046                                gdk_drawable_get_visual (window)->depth,
2047                                rect.left, rect.top));
2048     }
2049 }
2050
2051 static gint
2052 gdk_win32_window_get_root_coords (GdkWindow *window,
2053                                   gint       x,
2054                                   gint       y,
2055                                   gint      *root_x,
2056                                   gint      *root_y)
2057 {
2058   gint tx;
2059   gint ty;
2060   POINT pt;
2061
2062   pt.x = x;
2063   pt.y = y;
2064   ClientToScreen (GDK_WINDOW_HWND (window), &pt);
2065   tx = pt.x;
2066   ty = pt.y;
2067   
2068   if (root_x)
2069     *root_x = tx + _gdk_offset_x;
2070   if (root_y)
2071     *root_y = ty + _gdk_offset_y;
2072
2073   GDK_NOTE (MISC, g_print ("gdk_window_get_root_coords: %p: %+d%+d %+d%+d\n",
2074                            GDK_WINDOW_HWND (window),
2075                            x, y,
2076                            tx, ty));
2077   return 1;
2078 }
2079
2080 static gboolean
2081 gdk_win32_window_get_deskrelative_origin (GdkWindow *window,
2082                                           gint      *x,
2083                                           gint      *y)
2084 {
2085   return gdk_win32_window_get_root_coords (window, 0, 0, x, y);
2086 }
2087
2088 static void
2089 gdk_win32_window_restack_under (GdkWindow *window,
2090                                 GList *native_siblings)
2091 {
2092         // ### TODO
2093 }
2094
2095 void
2096 gdk_window_get_root_origin (GdkWindow *window,
2097                             gint      *x,
2098                             gint      *y)
2099 {
2100   GdkRectangle rect;
2101
2102   g_return_if_fail (GDK_IS_WINDOW (window));
2103
2104   gdk_window_get_frame_extents (window, &rect);
2105
2106   if (x)
2107     *x = rect.x;
2108
2109   if (y)
2110     *y = rect.y;
2111
2112   GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %p: %+d%+d\n",
2113                            GDK_WINDOW_HWND (window), rect.x, rect.y));
2114 }
2115
2116 void
2117 gdk_window_get_frame_extents (GdkWindow    *window,
2118                               GdkRectangle *rect)
2119 {
2120   GdkWindowObject *private;
2121   HWND hwnd;
2122   RECT r;
2123
2124   g_return_if_fail (GDK_IS_WINDOW (window));
2125   g_return_if_fail (rect != NULL);
2126
2127   private = GDK_WINDOW_OBJECT (window);
2128
2129   rect->x = 0;
2130   rect->y = 0;
2131   rect->width = 1;
2132   rect->height = 1;
2133   
2134   if (GDK_WINDOW_DESTROYED (window))
2135     return;
2136
2137   /* FIXME: window is documented to be a toplevel GdkWindow, so is it really
2138    * necessary to walk its parent chain?
2139    */
2140   while (private->parent && ((GdkWindowObject*) private->parent)->parent)
2141     private = (GdkWindowObject*) private->parent;
2142
2143   hwnd = GDK_WINDOW_HWND (window);
2144   API_CALL (GetWindowRect, (hwnd, &r));
2145
2146   rect->x = r.left + _gdk_offset_x;
2147   rect->y = r.top + _gdk_offset_y;
2148   rect->width = r.right - r.left;
2149   rect->height = r.bottom - r.top;
2150
2151   GDK_NOTE (MISC, g_print ("gdk_window_get_frame_extents: %p: %ldx%ld@%+ld%+ld\n",
2152                            GDK_WINDOW_HWND (window),
2153                            r.right - r.left, r.bottom - r.top,
2154                            r.left, r.top));
2155 }
2156
2157
2158 static GdkModifierType
2159 get_current_mask (void)
2160 {
2161   GdkModifierType mask;
2162   BYTE kbd[256];
2163
2164   GetKeyboardState (kbd);
2165   mask = 0;
2166   if (kbd[VK_SHIFT] & 0x80)
2167     mask |= GDK_SHIFT_MASK;
2168   if (kbd[VK_CAPITAL] & 0x80)
2169     mask |= GDK_LOCK_MASK;
2170   if (kbd[VK_CONTROL] & 0x80)
2171     mask |= GDK_CONTROL_MASK;
2172   if (kbd[VK_MENU] & 0x80)
2173     mask |= GDK_MOD1_MASK;
2174   if (kbd[VK_LBUTTON] & 0x80)
2175     mask |= GDK_BUTTON1_MASK;
2176   if (kbd[VK_MBUTTON] & 0x80)
2177     mask |= GDK_BUTTON2_MASK;
2178   if (kbd[VK_RBUTTON] & 0x80)
2179     mask |= GDK_BUTTON3_MASK;
2180
2181   return mask;
2182 }
2183     
2184 static gboolean
2185 gdk_window_win32_get_pointer (GdkWindow       *window,
2186                               gint            *x,
2187                               gint            *y,
2188                               GdkModifierType *mask)
2189 {
2190   gboolean return_val;
2191   POINT point;
2192   HWND hwnd, hwndc;
2193
2194   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
2195   
2196   return_val = TRUE;
2197
2198   hwnd = GDK_WINDOW_HWND (window);
2199   GetCursorPos (&point);
2200   ScreenToClient (hwnd, &point);
2201
2202   *x = point.x;
2203   *y = point.y;
2204
2205   if (window == _gdk_root)
2206     {
2207       *x += _gdk_offset_x;
2208       *y += _gdk_offset_y;
2209     }
2210
2211   hwndc = ChildWindowFromPoint (hwnd, point);
2212   if (hwndc != NULL && hwndc != hwnd &&
2213       !gdk_win32_handle_table_lookup ((GdkNativeWindow) hwndc))
2214     return_val = FALSE; /* Direct child unknown to gdk */
2215
2216   *mask = get_current_mask ();
2217   
2218   return return_val;
2219 }
2220
2221 void
2222 _gdk_windowing_get_pointer (GdkDisplay       *display,
2223                             GdkScreen       **screen,
2224                             gint             *x,
2225                             gint             *y,
2226                             GdkModifierType  *mask)
2227 {
2228   POINT point;
2229
2230   g_return_if_fail (display == _gdk_display);
2231   
2232   *screen = _gdk_screen;
2233   GetCursorPos (&point);
2234   *x = point.x + _gdk_offset_x;
2235   *y = point.y + _gdk_offset_y;
2236
2237   *mask = get_current_mask ();
2238 }
2239
2240 void
2241 gdk_display_warp_pointer (GdkDisplay *display,
2242                           GdkScreen  *screen,
2243                           gint        x,
2244                           gint        y)
2245 {
2246   g_return_if_fail (display == _gdk_display);
2247   g_return_if_fail (screen == _gdk_screen);
2248
2249   SetCursorPos (x - _gdk_offset_x, y - _gdk_offset_y);
2250 }
2251
2252 GdkWindow*
2253 _gdk_windowing_window_at_pointer (GdkDisplay *display,
2254                                   gint       *win_x,
2255                                   gint       *win_y,
2256                                   GdkModifierType *mask)
2257 {
2258   GdkWindow *window;
2259   POINT point, pointc;
2260   HWND hwnd, hwndc;
2261   RECT rect;
2262
2263   GetCursorPos (&pointc);
2264   point = pointc;
2265   hwnd = WindowFromPoint (point);
2266
2267   if (hwnd == NULL)
2268     {
2269       window = _gdk_root;
2270       *win_x = pointc.x + _gdk_offset_x;
2271       *win_y = pointc.y + _gdk_offset_y;
2272       return window;
2273     }
2274       
2275   ScreenToClient (hwnd, &point);
2276
2277   do {
2278     hwndc = ChildWindowFromPoint (hwnd, point);
2279     ClientToScreen (hwnd, &point);
2280     ScreenToClient (hwndc, &point);
2281   } while (hwndc != hwnd && (hwnd = hwndc, 1));
2282
2283   window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
2284
2285   if (window && (win_x || win_y))
2286     {
2287       GetClientRect (hwnd, &rect);
2288       *win_x = point.x - rect.left;
2289       *win_y = point.y - rect.top;
2290     }
2291
2292   GDK_NOTE (MISC, g_print ("_gdk_windowing_window_at_pointer: %+d%+d %p%s\n",
2293                            *win_x, *win_y,
2294                            hwnd,
2295                            (window == NULL ? " NULL" : "")));
2296
2297   return window;
2298 }
2299
2300 static GdkEventMask  
2301 gdk_win32_window_get_events (GdkWindow *window)
2302 {
2303   if (GDK_WINDOW_DESTROYED (window))
2304     return 0;
2305
2306   return GDK_WINDOW_OBJECT (window)->event_mask;
2307 }
2308
2309 static void          
2310 gdk_win32_window_set_events (GdkWindow   *window,
2311                        GdkEventMask event_mask)
2312 {
2313   /* gdk_window_new() always sets the GDK_STRUCTURE_MASK, so better
2314    * set it here, too. Not that I know or remember why it is
2315    * necessary, will have to test some day.
2316    */
2317   GDK_WINDOW_OBJECT (window)->event_mask = GDK_STRUCTURE_MASK | event_mask;
2318 }
2319
2320 static void
2321 do_shape_combine_region (GdkWindow *window,
2322                          HRGN       hrgn,
2323                          gint       x, gint y)
2324 {
2325   RECT rect;
2326
2327   GetClientRect (GDK_WINDOW_HWND (window), &rect);
2328   _gdk_win32_adjust_client_rect (window, &rect);
2329
2330   OffsetRgn (hrgn, -rect.left, -rect.top);
2331   OffsetRgn (hrgn, x, y);
2332
2333   /* If this is a top-level window, add the title bar to the region */
2334   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
2335     {
2336       HRGN tmp = CreateRectRgn (0, 0, rect.right - rect.left, -rect.top);
2337       CombineRgn (hrgn, hrgn, tmp, RGN_OR);
2338       DeleteObject (tmp);
2339     }
2340   
2341   SetWindowRgn (GDK_WINDOW_HWND (window), hrgn, TRUE);
2342 }
2343
2344 static void
2345 gdk_win32_window_shape_combine_mask (GdkWindow *window,
2346                                      GdkBitmap *mask,
2347                                      gint x, gint y)
2348 {
2349   GdkWindowObject *private = (GdkWindowObject *)window;
2350
2351   if (!mask)
2352     {
2353       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %p: none\n",
2354                                GDK_WINDOW_HWND (window)));
2355       SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
2356
2357       private->shaped = FALSE;
2358     }
2359   else
2360     {
2361       HRGN hrgn;
2362
2363       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %p: %p\n",
2364                                GDK_WINDOW_HWND (window),
2365                                GDK_WINDOW_HWND (mask)));
2366
2367       /* Convert mask bitmap to region */
2368       hrgn = _gdk_win32_bitmap_to_hrgn (mask);
2369
2370       do_shape_combine_region (window, hrgn, x, y);
2371
2372       private->shaped = TRUE;
2373     }
2374 }
2375
2376 void
2377 gdk_window_set_override_redirect (GdkWindow *window,
2378                                   gboolean   override_redirect)
2379 {
2380   g_return_if_fail (GDK_IS_WINDOW (window));
2381
2382   g_warning ("gdk_window_set_override_redirect not implemented");
2383 }
2384
2385 void
2386 gdk_window_set_accept_focus (GdkWindow *window,
2387                              gboolean accept_focus)
2388 {
2389   GdkWindowObject *private;
2390
2391   g_return_if_fail (GDK_IS_WINDOW (window));
2392
2393   private = (GdkWindowObject *)window;  
2394   
2395   accept_focus = accept_focus != FALSE;
2396
2397   if (private->accept_focus != accept_focus)
2398     private->accept_focus = accept_focus;
2399 }
2400
2401 void
2402 gdk_window_set_focus_on_map (GdkWindow *window,
2403                              gboolean focus_on_map)
2404 {
2405   GdkWindowObject *private;
2406
2407   g_return_if_fail (GDK_IS_WINDOW (window));
2408
2409   private = (GdkWindowObject *)window;  
2410   
2411   focus_on_map = focus_on_map != FALSE;
2412
2413   if (private->focus_on_map != focus_on_map)
2414     private->focus_on_map = focus_on_map;
2415 }
2416
2417 void          
2418 gdk_window_set_icon_list (GdkWindow *window,
2419                           GList     *pixbufs)
2420 {
2421   GdkPixbuf *pixbuf, *big_pixbuf, *small_pixbuf;
2422   gint big_diff, small_diff;
2423   gint big_w, big_h, small_w, small_h;
2424   gint w, h;
2425   gint dw, dh, diff;
2426   HICON small_hicon, big_hicon;
2427   GdkWindowImplWin32 *impl;
2428   gint i, big_i, small_i;
2429
2430   g_return_if_fail (GDK_IS_WINDOW (window));
2431
2432   if (GDK_WINDOW_DESTROYED (window))
2433     return;
2434
2435   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
2436
2437   /* ideal sizes for small and large icons */
2438   big_w = GetSystemMetrics (SM_CXICON);
2439   big_h = GetSystemMetrics (SM_CYICON);
2440   small_w = GetSystemMetrics (SM_CXSMICON);
2441   small_h = GetSystemMetrics (SM_CYSMICON);
2442
2443   /* find closest sized icons in the list */
2444   big_pixbuf = NULL;
2445   small_pixbuf = NULL;
2446   big_diff = 0;
2447   small_diff = 0;
2448   i = 0;
2449   while (pixbufs)
2450     {
2451       pixbuf = (GdkPixbuf*) pixbufs->data;
2452       w = gdk_pixbuf_get_width (pixbuf);
2453       h = gdk_pixbuf_get_height (pixbuf);
2454
2455       dw = ABS (w - big_w);
2456       dh = ABS (h - big_h);
2457       diff = dw*dw + dh*dh;
2458       if (big_pixbuf == NULL || diff < big_diff)
2459         {
2460           big_pixbuf = pixbuf;
2461           big_diff = diff;
2462           big_i = i;
2463         }
2464
2465       dw = ABS (w - small_w);
2466       dh = ABS (h - small_h);
2467       diff = dw*dw + dh*dh;
2468       if (small_pixbuf == NULL || diff < small_diff)
2469         {
2470           small_pixbuf = pixbuf;
2471           small_diff = diff;
2472           small_i = i;
2473         }
2474
2475       pixbufs = g_list_next (pixbufs);
2476       i++;
2477     }
2478
2479   /* Create the icons */
2480   big_hicon = _gdk_win32_pixbuf_to_hicon (big_pixbuf);
2481   small_hicon = _gdk_win32_pixbuf_to_hicon (small_pixbuf);
2482
2483   /* Set the icons */
2484   SendMessageW (GDK_WINDOW_HWND (window), WM_SETICON, ICON_BIG,
2485                 (LPARAM)big_hicon);
2486   SendMessageW (GDK_WINDOW_HWND (window), WM_SETICON, ICON_SMALL,
2487                 (LPARAM)small_hicon);
2488
2489   /* Store the icons, destroying any previous icons */
2490   if (impl->hicon_big)
2491     GDI_CALL (DestroyIcon, (impl->hicon_big));
2492   impl->hicon_big = big_hicon;
2493   if (impl->hicon_small)
2494     GDI_CALL (DestroyIcon, (impl->hicon_small));
2495   impl->hicon_small = small_hicon;
2496 }
2497
2498 void          
2499 gdk_window_set_icon (GdkWindow *window, 
2500                      GdkWindow *icon_window,
2501                      GdkPixmap *pixmap,
2502                      GdkBitmap *mask)
2503 {
2504   g_return_if_fail (GDK_IS_WINDOW (window));
2505
2506   /* do nothing, use gdk_window_set_icon_list instead */
2507 }
2508
2509 void
2510 gdk_window_set_icon_name (GdkWindow   *window, 
2511                           const gchar *name)
2512 {
2513   /* In case I manage to confuse this again (or somebody else does):
2514    * Please note that "icon name" here really *does* mean the name or
2515    * title of an window minimized as an icon on the desktop, or in the
2516    * taskbar. It has nothing to do with the freedesktop.org icon
2517    * naming stuff.
2518    */
2519
2520   g_return_if_fail (GDK_IS_WINDOW (window));
2521
2522   if (GDK_WINDOW_DESTROYED (window))
2523     return;
2524   
2525 #if 0
2526   /* This is not the correct thing to do. We should keep both the
2527    * "normal" window title, and the icon name. When the window is
2528    * minimized, call SetWindowText() with the icon name, and when the
2529    * window is restored, with the normal window title. Also, the name
2530    * is in UTF-8, so we should do the normal conversion to either wide
2531    * chars or system codepage, and use either the W or A version of
2532    * SetWindowText(), depending on Windows version.
2533    */
2534   API_CALL (SetWindowText, (GDK_WINDOW_HWND (window), name));
2535 #endif
2536 }
2537
2538 GdkWindow *
2539 gdk_window_get_group (GdkWindow *window)
2540 {
2541   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2542   g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
2543
2544   if (GDK_WINDOW_DESTROYED (window))
2545     return NULL;
2546   
2547   g_warning ("gdk_window_get_group not yet implemented");
2548
2549   return NULL;
2550 }
2551
2552 void          
2553 gdk_window_set_group (GdkWindow *window, 
2554                       GdkWindow *leader)
2555 {
2556   g_return_if_fail (GDK_IS_WINDOW (window));
2557   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2558   g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
2559
2560   if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
2561     return;
2562   
2563   g_warning ("gdk_window_set_group not implemented");
2564 }
2565
2566 static void
2567 update_single_bit (LONG    *style,
2568                    gboolean all,
2569                    int      gdk_bit,
2570                    int      style_bit)
2571 {
2572   /* all controls the interpretation of gdk_bit -- if all is TRUE,
2573    * gdk_bit indicates whether style_bit is off; if all is FALSE, gdk
2574    * bit indicate whether style_bit is on
2575    */
2576   if ((!all && gdk_bit) || (all && !gdk_bit))
2577     *style |= style_bit;
2578   else
2579     *style &= ~style_bit;
2580 }
2581
2582 static void
2583 update_style_bits (GdkWindow *window)
2584 {
2585   GdkWindowObject *private = (GdkWindowObject *)window;
2586   GdkWindowImplWin32 *impl = (GdkWindowImplWin32 *)private->impl;
2587   GdkWMDecoration decorations;
2588   LONG old_style, new_style, old_exstyle, new_exstyle;
2589   gboolean all;
2590   RECT rect, before, after;
2591
2592   old_style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2593   old_exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
2594
2595   GetClientRect (GDK_WINDOW_HWND (window), &before);
2596   after = before;
2597   AdjustWindowRectEx (&before, old_style, FALSE, old_exstyle);
2598
2599   new_style = old_style;
2600   new_exstyle = old_exstyle;
2601
2602   if (private->window_type == GDK_WINDOW_TEMP ||
2603       impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY)
2604     new_exstyle |= WS_EX_TOOLWINDOW;
2605   else
2606     new_exstyle &= ~WS_EX_TOOLWINDOW;
2607
2608   if (get_effective_window_decorations (window, &decorations))
2609     {
2610       all = (decorations & GDK_DECOR_ALL);
2611       update_single_bit (&new_style, all, decorations & GDK_DECOR_BORDER, WS_BORDER);
2612       update_single_bit (&new_style, all, decorations & GDK_DECOR_RESIZEH, WS_THICKFRAME);
2613       update_single_bit (&new_style, all, decorations & GDK_DECOR_TITLE, WS_CAPTION);
2614       update_single_bit (&new_style, all, decorations & GDK_DECOR_MENU, WS_SYSMENU);
2615       update_single_bit (&new_style, all, decorations & GDK_DECOR_MINIMIZE, WS_MINIMIZEBOX);
2616       update_single_bit (&new_style, all, decorations & GDK_DECOR_MAXIMIZE, WS_MAXIMIZEBOX);
2617     }
2618
2619   if (old_style == new_style && old_exstyle == new_exstyle )
2620     {
2621       GDK_NOTE (MISC, g_print ("update_style_bits: %p: no change\n",
2622                                GDK_WINDOW_HWND (window)));
2623       return;
2624     }
2625
2626   if (old_style != new_style)
2627     {
2628       GDK_NOTE (MISC, g_print ("update_style_bits: %p: STYLE: %s => %s\n",
2629                                GDK_WINDOW_HWND (window),
2630                                _gdk_win32_window_style_to_string (old_style),
2631                                _gdk_win32_window_style_to_string (new_style)));
2632       
2633       SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, new_style);
2634     }
2635
2636   if (old_exstyle != new_exstyle)
2637     {
2638       GDK_NOTE (MISC, g_print ("update_style_bits: %p: EXSTYLE: %s => %s\n",
2639                                GDK_WINDOW_HWND (window),
2640                                _gdk_win32_window_exstyle_to_string (old_exstyle),
2641                                _gdk_win32_window_exstyle_to_string (new_exstyle)));
2642       
2643       SetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE, new_exstyle);
2644     }
2645
2646   AdjustWindowRectEx (&after, new_style, FALSE, new_exstyle);
2647
2648   GetWindowRect (GDK_WINDOW_HWND (window), &rect);
2649   rect.left += after.left - before.left;
2650   rect.top += after.top - before.top;
2651   rect.right += after.right - before.right;
2652   rect.bottom += after.bottom - before.bottom;
2653
2654   SetWindowPos (GDK_WINDOW_HWND (window), NULL,
2655                 rect.left, rect.top,
2656                 rect.right - rect.left, rect.bottom - rect.top,
2657                 SWP_FRAMECHANGED | SWP_NOACTIVATE | 
2658                 SWP_NOREPOSITION | SWP_NOZORDER);
2659
2660 }
2661
2662 static void
2663 update_single_system_menu_entry (HMENU    hmenu,
2664                                  gboolean all,
2665                                  int      gdk_bit,
2666                                  int      menu_entry)
2667 {
2668   /* all controls the interpretation of gdk_bit -- if all is TRUE,
2669    * gdk_bit indicates whether menu entry is disabled; if all is
2670    * FALSE, gdk bit indicate whether menu entry is enabled
2671    */
2672   if ((!all && gdk_bit) || (all && !gdk_bit))
2673     EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_ENABLED);
2674   else
2675     EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_GRAYED);
2676 }
2677
2678 static void
2679 update_system_menu (GdkWindow *window)
2680 {
2681   GdkWMFunction functions;
2682   BOOL all;
2683
2684   if (_gdk_window_get_functions (window, &functions))
2685     {
2686       HMENU hmenu = GetSystemMenu (GDK_WINDOW_HWND (window), FALSE);
2687
2688       all = (functions & GDK_FUNC_ALL);
2689       update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_RESIZE, SC_SIZE);
2690       update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MOVE, SC_MOVE);
2691       update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MINIMIZE, SC_MINIMIZE);
2692       update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MAXIMIZE, SC_MAXIMIZE);
2693       update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_CLOSE, SC_CLOSE);
2694     }
2695 }
2696
2697 static GQuark
2698 get_decorations_quark ()
2699 {
2700   static GQuark quark = 0;
2701   
2702   if (!quark)
2703     quark = g_quark_from_static_string ("gdk-window-decorations");
2704   
2705   return quark;
2706 }
2707
2708 void
2709 gdk_window_set_decorations (GdkWindow      *window,
2710                             GdkWMDecoration decorations)
2711 {
2712   GdkWMDecoration* decorations_copy;
2713   
2714   g_return_if_fail (GDK_IS_WINDOW (window));
2715   
2716   GDK_NOTE (MISC, g_print ("gdk_window_set_decorations: %p: %s %s%s%s%s%s%s\n",
2717                            GDK_WINDOW_HWND (window),
2718                            (decorations & GDK_DECOR_ALL ? "clearing" : "setting"),
2719                            (decorations & GDK_DECOR_BORDER ? "BORDER " : ""),
2720                            (decorations & GDK_DECOR_RESIZEH ? "RESIZEH " : ""),
2721                            (decorations & GDK_DECOR_TITLE ? "TITLE " : ""),
2722                            (decorations & GDK_DECOR_MENU ? "MENU " : ""),
2723                            (decorations & GDK_DECOR_MINIMIZE ? "MINIMIZE " : ""),
2724                            (decorations & GDK_DECOR_MAXIMIZE ? "MAXIMIZE " : "")));
2725
2726   decorations_copy = g_malloc (sizeof (GdkWMDecoration));
2727   *decorations_copy = decorations;
2728   g_object_set_qdata_full (G_OBJECT (window), get_decorations_quark (), decorations_copy, g_free);
2729
2730   update_style_bits (window);
2731 }
2732
2733 gboolean
2734 gdk_window_get_decorations (GdkWindow       *window,
2735                             GdkWMDecoration *decorations)
2736 {
2737   GdkWMDecoration* decorations_set;
2738   
2739   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2740
2741   decorations_set = g_object_get_qdata (G_OBJECT (window), get_decorations_quark ());
2742   if (decorations_set)
2743     *decorations = *decorations_set;
2744
2745   return (decorations_set != NULL);
2746 }
2747
2748 static GQuark
2749 get_functions_quark ()
2750 {
2751   static GQuark quark = 0;
2752   
2753   if (!quark)
2754     quark = g_quark_from_static_string ("gdk-window-functions");
2755   
2756   return quark;
2757 }
2758
2759 void
2760 gdk_window_set_functions (GdkWindow    *window,
2761                           GdkWMFunction functions)
2762 {
2763   GdkWMFunction* functions_copy;
2764
2765   g_return_if_fail (GDK_IS_WINDOW (window));
2766   
2767   GDK_NOTE (MISC, g_print ("gdk_window_set_functions: %p: %s %s%s%s%s%s\n",
2768                            GDK_WINDOW_HWND (window),
2769                            (functions & GDK_FUNC_ALL ? "clearing" : "setting"),
2770                            (functions & GDK_FUNC_RESIZE ? "RESIZE " : ""),
2771                            (functions & GDK_FUNC_MOVE ? "MOVE " : ""),
2772                            (functions & GDK_FUNC_MINIMIZE ? "MINIMIZE " : ""),
2773                            (functions & GDK_FUNC_MAXIMIZE ? "MAXIMIZE " : ""),
2774                            (functions & GDK_FUNC_CLOSE ? "CLOSE " : "")));
2775
2776   functions_copy = g_malloc (sizeof (GdkWMFunction));
2777   *functions_copy = functions;
2778   g_object_set_qdata_full (G_OBJECT (window), get_functions_quark (), functions_copy, g_free);
2779
2780   update_system_menu (window);
2781 }
2782
2783 gboolean
2784 _gdk_window_get_functions (GdkWindow     *window,
2785                            GdkWMFunction *functions)
2786 {
2787   GdkWMDecoration* functions_set;
2788   
2789   functions_set = g_object_get_qdata (G_OBJECT (window), get_functions_quark ());
2790   if (functions_set)
2791     *functions = *functions_set;
2792
2793   return (functions_set != NULL);
2794 }
2795
2796 static void
2797 QueryTree (HWND   hwnd,
2798            HWND **children,
2799            gint  *nchildren)
2800 {
2801   guint i, n;
2802   HWND child = NULL;
2803
2804   n = 0;
2805   do {
2806     if (n == 0)
2807       child = GetWindow (hwnd, GW_CHILD);
2808     else
2809       child = GetWindow (child, GW_HWNDNEXT);
2810     if (child != NULL)
2811       n++;
2812   } while (child != NULL);
2813
2814   if (n > 0)
2815     {
2816       *children = g_new (HWND, n);
2817       for (i = 0; i < n; i++)
2818         {
2819           if (i == 0)
2820             child = GetWindow (hwnd, GW_CHILD);
2821           else
2822             child = GetWindow (child, GW_HWNDNEXT);
2823           *children[i] = child;
2824         }
2825     }
2826 }
2827
2828 static void
2829 gdk_propagate_shapes (HANDLE   win,
2830                       gboolean merge)
2831 {
2832    RECT emptyRect;
2833    HRGN region, childRegion;
2834    HWND *list = NULL;
2835    gint i, num;
2836
2837    SetRectEmpty (&emptyRect);
2838    region = CreateRectRgnIndirect (&emptyRect);
2839    if (merge)
2840      GetWindowRgn (win, region);
2841    
2842    QueryTree (win, &list, &num);
2843    if (list != NULL)
2844      {
2845        WINDOWPLACEMENT placement;
2846
2847        placement.length = sizeof (WINDOWPLACEMENT);
2848        /* go through all child windows and combine regions */
2849        for (i = 0; i < num; i++)
2850          {
2851            GetWindowPlacement (list[i], &placement);
2852            if (placement.showCmd == SW_SHOWNORMAL)
2853              {
2854                childRegion = CreateRectRgnIndirect (&emptyRect);
2855                GetWindowRgn (list[i], childRegion);
2856                CombineRgn (region, region, childRegion, RGN_OR);
2857                DeleteObject (childRegion);
2858              }
2859           }
2860        SetWindowRgn (win, region, TRUE);
2861        g_free (list);
2862      }
2863    else
2864      DeleteObject (region);
2865 }
2866
2867 static void
2868 gdk_win32_window_set_child_shapes (GdkWindow *window)
2869 {
2870   if (GDK_WINDOW_DESTROYED (window))
2871     return;
2872
2873   gdk_propagate_shapes (GDK_WINDOW_HWND (window), FALSE);
2874 }
2875
2876 static void
2877 gdk_win32_window_merge_child_shapes (GdkWindow *window)
2878 {
2879   if (GDK_WINDOW_DESTROYED (window))
2880     return;
2881
2882   gdk_propagate_shapes (GDK_WINDOW_HWND (window), TRUE);
2883 }
2884
2885 static gboolean 
2886 gdk_win32_window_set_static_gravities (GdkWindow *window,
2887                                  gboolean   use_static)
2888 {
2889   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2890
2891   return !use_static;
2892 }
2893
2894 void
2895 gdk_window_begin_resize_drag (GdkWindow     *window,
2896                               GdkWindowEdge  edge,
2897                               gint           button,
2898                               gint           root_x,
2899                               gint           root_y,
2900                               guint32        timestamp)
2901 {
2902   WPARAM winedge;
2903   
2904   g_return_if_fail (GDK_IS_WINDOW (window));
2905   
2906   if (GDK_WINDOW_DESTROYED (window))
2907     return;
2908
2909   /* Tell Windows to start interactively resizing the window by pretending that
2910    * the left pointer button was clicked in the suitable edge or corner. This
2911    * will only work if the button is down when this function is called, and
2912    * will only work with button 1 (left), since Windows only allows window
2913    * dragging using the left mouse button.
2914    */
2915   if (button != 1)
2916     return;
2917   
2918   /* Must break the automatic grab that occured when the button was
2919    * pressed, otherwise it won't work.
2920    */
2921   gdk_display_pointer_ungrab (_gdk_display, 0);
2922
2923   switch (edge)
2924     {
2925     case GDK_WINDOW_EDGE_NORTH_WEST:
2926       winedge = HTTOPLEFT;
2927       break;
2928
2929     case GDK_WINDOW_EDGE_NORTH:
2930       winedge = HTTOP;
2931       break;
2932
2933     case GDK_WINDOW_EDGE_NORTH_EAST:
2934       winedge = HTTOPRIGHT;
2935       break;
2936
2937     case GDK_WINDOW_EDGE_WEST:
2938       winedge = HTLEFT;
2939       break;
2940
2941     case GDK_WINDOW_EDGE_EAST:
2942       winedge = HTRIGHT;
2943       break;
2944
2945     case GDK_WINDOW_EDGE_SOUTH_WEST:
2946       winedge = HTBOTTOMLEFT;
2947       break;
2948
2949     case GDK_WINDOW_EDGE_SOUTH:
2950       winedge = HTBOTTOM;
2951       break;
2952
2953     case GDK_WINDOW_EDGE_SOUTH_EAST:
2954     default:
2955       winedge = HTBOTTOMRIGHT;
2956       break;
2957     }
2958
2959   DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, winedge,
2960                   MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
2961 }
2962
2963 void
2964 gdk_window_begin_move_drag (GdkWindow *window,
2965                             gint       button,
2966                             gint       root_x,
2967                             gint       root_y,
2968                             guint32    timestamp)
2969 {
2970   g_return_if_fail (GDK_IS_WINDOW (window));
2971   
2972   if (GDK_WINDOW_DESTROYED (window))
2973     return;
2974
2975   /* Tell Windows to start interactively moving the window by pretending that
2976    * the left pointer button was clicked in the titlebar. This will only work
2977    * if the button is down when this function is called, and will only work
2978    * with button 1 (left), since Windows only allows window dragging using the
2979    * left mouse button.
2980    */
2981   if (button != 1)
2982     return;
2983   
2984   /* Must break the automatic grab that occured when the button was pressed,
2985    * otherwise it won't work.
2986    */
2987   gdk_display_pointer_ungrab (_gdk_display, 0);
2988
2989   DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, HTCAPTION,
2990                   MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
2991 }
2992
2993
2994 /*
2995  * Setting window states
2996  */
2997 void
2998 gdk_window_iconify (GdkWindow *window)
2999 {
3000   HWND old_active_window;
3001
3002   g_return_if_fail (GDK_IS_WINDOW (window));
3003
3004   if (GDK_WINDOW_DESTROYED (window))
3005     return;
3006
3007   GDK_NOTE (MISC, g_print ("gdk_window_iconify: %p: %s\n",
3008                            GDK_WINDOW_HWND (window),
3009                            _gdk_win32_window_state_to_string (((GdkWindowObject *) window)->state)));
3010
3011   if (GDK_WINDOW_IS_MAPPED (window))
3012     {
3013       old_active_window = GetActiveWindow ();
3014       ShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
3015       if (old_active_window != GDK_WINDOW_HWND (window))
3016         SetActiveWindow (old_active_window);
3017     }
3018   else
3019     {
3020       gdk_synthesize_window_state (window,
3021                                    0,
3022                                    GDK_WINDOW_STATE_ICONIFIED);
3023     }
3024 }
3025
3026 void
3027 gdk_window_deiconify (GdkWindow *window)
3028 {
3029   g_return_if_fail (GDK_IS_WINDOW (window));
3030
3031   if (GDK_WINDOW_DESTROYED (window))
3032     return;
3033
3034   GDK_NOTE (MISC, g_print ("gdk_window_deiconify: %p: %s\n",
3035                            GDK_WINDOW_HWND (window),
3036                            _gdk_win32_window_state_to_string (((GdkWindowObject *) window)->state)));
3037
3038   if (GDK_WINDOW_IS_MAPPED (window))
3039     {  
3040       show_window_internal (window, FALSE, TRUE);
3041     }
3042   else
3043     {
3044       gdk_synthesize_window_state (window,
3045                                    GDK_WINDOW_STATE_ICONIFIED,
3046                                    0);
3047     }
3048 }
3049
3050 void
3051 gdk_window_stick (GdkWindow *window)
3052 {
3053   g_return_if_fail (GDK_IS_WINDOW (window));
3054
3055   if (GDK_WINDOW_DESTROYED (window))
3056     return;
3057
3058   /* FIXME: Do something? */
3059 }
3060
3061 void
3062 gdk_window_unstick (GdkWindow *window)
3063 {
3064   g_return_if_fail (GDK_IS_WINDOW (window));
3065
3066   if (GDK_WINDOW_DESTROYED (window))
3067     return;
3068
3069   /* FIXME: Do something? */
3070 }
3071
3072 void
3073 gdk_window_maximize (GdkWindow *window)
3074 {
3075   g_return_if_fail (GDK_IS_WINDOW (window));
3076
3077   if (GDK_WINDOW_DESTROYED (window))
3078     return;
3079
3080   GDK_NOTE (MISC, g_print ("gdk_window_maximize: %p: %s\n",
3081                            GDK_WINDOW_HWND (window),
3082                            _gdk_win32_window_state_to_string (((GdkWindowObject *) window)->state)));
3083
3084   if (GDK_WINDOW_IS_MAPPED (window))
3085     ShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
3086   else
3087     gdk_synthesize_window_state (window,
3088                                  0,
3089                                  GDK_WINDOW_STATE_MAXIMIZED);
3090 }
3091
3092 void
3093 gdk_window_unmaximize (GdkWindow *window)
3094 {
3095   g_return_if_fail (GDK_IS_WINDOW (window));
3096
3097   if (GDK_WINDOW_DESTROYED (window))
3098     return;
3099
3100   GDK_NOTE (MISC, g_print ("gdk_window_unmaximize: %p: %s\n",
3101                            GDK_WINDOW_HWND (window),
3102                            _gdk_win32_window_state_to_string (((GdkWindowObject *) window)->state)));
3103
3104   if (GDK_WINDOW_IS_MAPPED (window))
3105     ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
3106   else
3107     gdk_synthesize_window_state (window,
3108                                  GDK_WINDOW_STATE_MAXIMIZED,
3109                                  0);
3110 }
3111
3112 typedef struct _FullscreenInfo FullscreenInfo;
3113
3114 struct _FullscreenInfo
3115 {
3116   RECT  r;
3117   guint hint_flags;
3118   LONG  style;
3119 };
3120
3121 void
3122 gdk_window_fullscreen (GdkWindow *window)
3123 {
3124   gint x, y, width, height;
3125   FullscreenInfo *fi;
3126   GdkWindowObject *private = (GdkWindowObject *) window;
3127   HMONITOR monitor;
3128   MONITORINFO mi;
3129
3130   g_return_if_fail (GDK_IS_WINDOW (window));
3131
3132   fi = g_new (FullscreenInfo, 1);
3133
3134   if (!GetWindowRect (GDK_WINDOW_HWND (window), &(fi->r)))
3135     g_free (fi);
3136   else
3137     {
3138       GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
3139
3140       monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST);
3141       mi.cbSize = sizeof (mi);
3142       if (monitor && GetMonitorInfo (monitor, &mi))
3143         {
3144           x = mi.rcMonitor.left;
3145           y = mi.rcMonitor.top;
3146           width = mi.rcMonitor.right - x;
3147           height = mi.rcMonitor.bottom - y;
3148         }
3149       else
3150         {
3151           x = y = 0;
3152           width = GetSystemMetrics (SM_CXSCREEN);
3153           height = GetSystemMetrics (SM_CYSCREEN);
3154         }
3155
3156       /* remember for restoring */
3157       fi->hint_flags = impl->hint_flags;
3158       impl->hint_flags &= ~GDK_HINT_MAX_SIZE;
3159       g_object_set_data (G_OBJECT (window), "fullscreen-info", fi);
3160       fi->style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
3161
3162       SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, 
3163                      (fi->style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP);
3164
3165       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
3166                                x, y, width, height,
3167                                SWP_NOCOPYBITS | SWP_SHOWWINDOW));
3168
3169       gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
3170     }
3171 }
3172
3173 void
3174 gdk_window_unfullscreen (GdkWindow *window)
3175 {
3176   FullscreenInfo *fi;
3177   GdkWindowObject *private = (GdkWindowObject *) window;
3178
3179   g_return_if_fail (GDK_IS_WINDOW (window));
3180
3181   fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
3182   if (fi)
3183     {
3184       GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
3185
3186       impl->hint_flags = fi->hint_flags;
3187       SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, fi->style);
3188       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_NOTOPMOST,
3189                                fi->r.left, fi->r.top,
3190                                fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
3191                                SWP_NOCOPYBITS | SWP_SHOWWINDOW));
3192       
3193       g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL);
3194       g_free (fi);
3195
3196       gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
3197     }
3198 }
3199
3200 void
3201 gdk_window_set_keep_above (GdkWindow *window,
3202                            gboolean   setting)
3203 {
3204   g_return_if_fail (GDK_IS_WINDOW (window));
3205
3206   if (GDK_WINDOW_DESTROYED (window))
3207     return;
3208
3209   GDK_NOTE (MISC, g_print ("gdk_window_set_keep_above: %p: %s\n",
3210                            GDK_WINDOW_HWND (window),
3211                            setting ? "YES" : "NO"));
3212
3213   if (GDK_WINDOW_IS_MAPPED (window))
3214     {
3215       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
3216                                setting ? HWND_TOPMOST : HWND_NOTOPMOST,
3217                                0, 0, 0, 0,
3218                                SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
3219     }
3220   else
3221     gdk_synthesize_window_state (window,
3222                                  setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
3223                                  setting ? GDK_WINDOW_STATE_ABOVE : 0);
3224 }
3225
3226 void
3227 gdk_window_set_keep_below (GdkWindow *window,
3228                            gboolean   setting)
3229 {
3230   g_return_if_fail (GDK_IS_WINDOW (window));
3231
3232   if (GDK_WINDOW_DESTROYED (window))
3233     return;
3234
3235   GDK_NOTE (MISC, g_print ("gdk_window_set_keep_below: %p: %s\n",
3236                            GDK_WINDOW_HWND (window),
3237                            setting ? "YES" : "NO"));
3238
3239   if (GDK_WINDOW_IS_MAPPED (window))
3240     {
3241       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
3242                                setting ? HWND_BOTTOM : HWND_NOTOPMOST,
3243                                0, 0, 0, 0,
3244                                SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
3245     }
3246   else
3247     gdk_synthesize_window_state (window,
3248                                  setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
3249                                  setting ? GDK_WINDOW_STATE_BELOW : 0);
3250 }
3251
3252 void
3253 gdk_window_focus (GdkWindow *window,
3254                   guint32    timestamp)
3255 {
3256   g_return_if_fail (GDK_IS_WINDOW (window));
3257
3258   if (GDK_WINDOW_DESTROYED (window))
3259     return;
3260   
3261   GDK_NOTE (MISC, g_print ("gdk_window_focus: %p: %s\n",
3262                            GDK_WINDOW_HWND (window),
3263                            _gdk_win32_window_state_to_string (((GdkWindowObject *) window)->state)));
3264
3265   if (((GdkWindowObject *) window)->state & GDK_WINDOW_STATE_MAXIMIZED)
3266     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMAXIMIZED);
3267   else
3268     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
3269   SetFocus (GDK_WINDOW_HWND (window));
3270 }
3271
3272 void
3273 gdk_window_set_modal_hint (GdkWindow *window,
3274                            gboolean   modal)
3275 {
3276   GdkWindowObject *private;
3277
3278   g_return_if_fail (GDK_IS_WINDOW (window));
3279   
3280   if (GDK_WINDOW_DESTROYED (window))
3281     return;
3282
3283   GDK_NOTE (MISC, g_print ("gdk_window_set_modal_hint: %p: %s\n",
3284                            GDK_WINDOW_HWND (window),
3285                            modal ? "YES" : "NO"));
3286
3287   private = (GdkWindowObject*) window;
3288
3289   if (modal == private->modal_hint)
3290     return;
3291
3292   private->modal_hint = modal;
3293
3294 #if 0
3295   /* Not sure about this one.. -- Cody */
3296   if (GDK_WINDOW_IS_MAPPED (window))
3297     API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), 
3298                              modal ? HWND_TOPMOST : HWND_NOTOPMOST,
3299                              0, 0, 0, 0,
3300                              SWP_NOMOVE | SWP_NOSIZE));
3301 #else
3302
3303   if (modal)
3304     {
3305       _gdk_push_modal_window (window);
3306       gdk_window_raise (window);
3307     }
3308   else
3309     {
3310       _gdk_remove_modal_window (window);
3311     }
3312
3313 #endif
3314 }
3315
3316 void
3317 gdk_window_set_skip_taskbar_hint (GdkWindow *window,
3318                                   gboolean   skips_taskbar)
3319 {
3320   static GdkWindow *owner = NULL;
3321   //GdkWindowAttr wa;
3322
3323   g_return_if_fail (GDK_IS_WINDOW (window));
3324
3325   GDK_NOTE (MISC, g_print ("gdk_window_set_skip_taskbar_hint: %p: %s, doing nothing\n",
3326                            GDK_WINDOW_HWND (window),
3327                            skips_taskbar ? "YES" : "NO"));
3328
3329   // ### TODO: Need to figure out what to do here.
3330   return;
3331
3332   if (skips_taskbar)
3333     {
3334 #if 0
3335       if (owner == NULL)
3336                 {
3337                   wa.window_type = GDK_WINDOW_TEMP;
3338                   wa.wclass = GDK_INPUT_OUTPUT;
3339                   wa.width = wa.height = 1;
3340                   wa.event_mask = 0;
3341                   owner = gdk_window_new_internal (NULL, &wa, 0, TRUE);
3342                 }
3343 #endif
3344
3345       SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, (LONG_PTR) GDK_WINDOW_HWND (owner));
3346
3347 #if 0 /* Should we also turn off the minimize and maximize buttons? */
3348       SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE,
3349                      GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE) & ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU));
3350      
3351       SetWindowPos (GDK_WINDOW_HWND (window), NULL,
3352                     0, 0, 0, 0,
3353                     SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
3354                     SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
3355 #endif
3356     }
3357   else
3358     {
3359       SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, 0);
3360     }
3361 }
3362
3363 void
3364 gdk_window_set_skip_pager_hint (GdkWindow *window,
3365                                 gboolean   skips_pager)
3366 {
3367   g_return_if_fail (GDK_IS_WINDOW (window));
3368
3369   GDK_NOTE (MISC, g_print ("gdk_window_set_skip_pager_hint: %p: %s, doing nothing\n",
3370                            GDK_WINDOW_HWND (window),
3371                            skips_pager ? "YES" : "NO"));
3372 }
3373
3374 void
3375 gdk_window_set_type_hint (GdkWindow        *window,
3376                           GdkWindowTypeHint hint)
3377 {
3378   g_return_if_fail (GDK_IS_WINDOW (window));
3379   
3380   if (GDK_WINDOW_DESTROYED (window))
3381     return;
3382
3383   GDK_NOTE (MISC,
3384             G_STMT_START{
3385               static GEnumClass *class = NULL;
3386               if (!class)
3387                 class = g_type_class_ref (GDK_TYPE_WINDOW_TYPE_HINT);
3388               g_print ("gdk_window_set_type_hint: %p: %s\n",
3389                        GDK_WINDOW_HWND (window),
3390                        g_enum_get_value (class, hint)->value_name);
3391             }G_STMT_END);
3392
3393   ((GdkWindowImplWin32 *)((GdkWindowObject *)window)->impl)->type_hint = hint;
3394
3395   update_style_bits (window);
3396 }
3397
3398 GdkWindowTypeHint
3399 gdk_window_get_type_hint (GdkWindow *window)
3400 {
3401   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
3402   
3403   if (GDK_WINDOW_DESTROYED (window))
3404     return GDK_WINDOW_TYPE_HINT_NORMAL;
3405
3406   return GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->type_hint;
3407 }
3408
3409 static void
3410 gdk_win32_window_shape_combine_region (GdkWindow       *window,
3411                                        const GdkRegion *shape_region,
3412                                        gint             offset_x,
3413                                        gint             offset_y)
3414 {
3415   GdkWindowObject *private = (GdkWindowObject *)window;
3416
3417   if (GDK_WINDOW_DESTROYED (window))
3418     return;
3419
3420   if (!shape_region)
3421     {
3422       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_region: %p: none\n",
3423                                GDK_WINDOW_HWND (window)));
3424       SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
3425
3426       private->shaped = FALSE;
3427     }
3428   else
3429     {
3430       HRGN hrgn;
3431
3432       hrgn = _gdk_win32_gdkregion_to_hrgn (shape_region, 0, 0);
3433       
3434       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_region: %p: %p\n",
3435                                GDK_WINDOW_HWND (window),
3436                                hrgn));
3437
3438       do_shape_combine_region (window, hrgn, offset_x, offset_y);
3439
3440       private->shaped = TRUE;
3441     }
3442 }
3443
3444 GdkWindow *
3445 gdk_window_lookup_for_display (GdkDisplay      *display,
3446                                GdkNativeWindow  anid)
3447 {
3448   g_return_val_if_fail (display == _gdk_display, NULL);
3449
3450   return gdk_window_lookup (anid);
3451 }
3452
3453 void
3454 gdk_window_enable_synchronized_configure (GdkWindow *window)
3455 {
3456   g_return_if_fail (GDK_IS_WINDOW (window));
3457 }
3458
3459 void
3460 gdk_window_configure_finished (GdkWindow *window)
3461 {
3462   g_return_if_fail (GDK_IS_WINDOW (window));
3463 }
3464
3465 void
3466 _gdk_windowing_window_beep (GdkWindow *window)
3467 {
3468   gdk_display_beep (_gdk_display);
3469 }
3470
3471 void
3472 gdk_window_set_opacity (GdkWindow *window,
3473                         gdouble    opacity)
3474 {
3475   LONG exstyle;
3476   typedef BOOL (*PFN_SetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
3477   PFN_SetLayeredWindowAttributes setLayeredWindowAttributes = NULL;
3478
3479   g_return_if_fail (GDK_IS_WINDOW (window));
3480   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
3481
3482   if (GDK_WINDOW_DESTROYED (window))
3483     return;
3484
3485   if (opacity < 0)
3486     opacity = 0;
3487   else if (opacity > 1)
3488     opacity = 1;
3489
3490   exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
3491
3492   if (!(exstyle & WS_EX_LAYERED))
3493     API_CALL (SetWindowLong, (GDK_WINDOW_HWND (window),
3494                               GWL_EXSTYLE,
3495                               exstyle | WS_EX_LAYERED));
3496
3497   setLayeredWindowAttributes = 
3498     (PFN_SetLayeredWindowAttributes)GetProcAddress (GetModuleHandle ("user32.dll"), "SetLayeredWindowAttributes");
3499
3500   if (setLayeredWindowAttributes)
3501     {
3502       API_CALL (setLayeredWindowAttributes, (GDK_WINDOW_HWND (window),
3503                                              0,
3504                                              opacity * 0xff,
3505                                              LWA_ALPHA));
3506     }
3507 }
3508
3509 GdkRegion *
3510 _gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
3511 {
3512   GdkRegion *region;
3513   HRGN hrgn = _gdk_win32_bitmap_to_hrgn (mask);
3514
3515   region = _gdk_win32_hrgn_to_region (hrgn);
3516   DeleteObject (hrgn);
3517
3518   return region;
3519 }
3520
3521 void
3522 _gdk_windowing_window_set_composited (GdkWindow *window, gboolean composited)
3523 {
3524 }
3525
3526 GdkRegion *
3527 _gdk_windowing_window_get_shape (GdkWindow *window)
3528 {
3529   HRGN hrgn = CreateRectRgn (0, 0, 0, 0);
3530   int  type = GetWindowRgn (GDK_WINDOW_HWND (window), hrgn);
3531
3532   if (type == SIMPLEREGION || type == COMPLEXREGION)
3533     {
3534       GdkRegion *region = _gdk_win32_hrgn_to_region (hrgn);
3535
3536       DeleteObject (hrgn);
3537       return region;
3538     }
3539
3540   return NULL;
3541 }
3542
3543 GdkRegion *
3544 _gdk_windowing_window_get_input_shape (GdkWindow *window)
3545 {
3546   /* CHECK: are these really supposed to be the same? */
3547   return _gdk_windowing_window_get_shape (window);
3548 }
3549
3550 static gboolean
3551 _gdk_win32_window_queue_antiexpose (GdkWindow *window,
3552                                     GdkRegion *area)
3553 {
3554   HRGN hrgn = _gdk_win32_gdkregion_to_hrgn (area, 0, 0);
3555
3556   GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose: ValidateRgn %p %s\n",
3557                              GDK_WINDOW_HWND (window),
3558                              _gdk_win32_gdkregion_to_string (area)));
3559
3560   ValidateRgn (GDK_WINDOW_HWND (window), hrgn);
3561
3562   DeleteObject (hrgn);
3563
3564   return FALSE;
3565 }
3566
3567 /*
3568  * queue_translation is meant to only move any outstanding invalid area
3569  * in the given area by dx,dy. A typical example of when its needed is an
3570  * app with two toplevels where one (A) overlaps the other (B). If the
3571  * app first moves A so that B is invalidated and then scrolls B before
3572  * handling the expose. The scroll operation will copy the invalid area
3573  * to a new position, but when the invalid area is then exposed it only
3574  * redraws the old areas not the place where the invalid data was copied
3575  * by the scroll.
3576  */
3577 static void
3578 _gdk_win32_window_queue_translation (GdkWindow *window,
3579                                      GdkRegion *area,
3580                                      gint       dx,
3581                                      gint       dy)
3582 {
3583   HRGN hrgn = CreateRectRgn (0, 0, 0, 0);
3584   int ret = GetUpdateRgn (GDK_WINDOW_HWND (window), hrgn, FALSE);
3585   if (ret == ERROR)
3586     WIN32_API_FAILED ("GetUpdateRgn");
3587   else if (ret != NULLREGION)
3588     {
3589       /* Get current updateregion, move any part of it that intersects area by dx,dy */
3590       HRGN update = _gdk_win32_gdkregion_to_hrgn (area, 0, 0);
3591       ret = CombineRgn (update, hrgn, update, RGN_AND);
3592       if (ret == ERROR)
3593         WIN32_API_FAILED ("CombineRgn");
3594       else if (ret != NULLREGION)
3595         {
3596           OffsetRgn (update, dx, dy);
3597           API_CALL (InvalidateRgn, (GDK_WINDOW_HWND (window), update, TRUE));
3598         }
3599       DeleteObject (update);
3600     }
3601   DeleteObject (hrgn);
3602 }
3603
3604 static void
3605 gdk_win32_input_shape_combine_region (GdkWindow *window,
3606                                       const GdkRegion *shape_region,
3607                                       gint offset_x,
3608                                       gint offset_y)
3609 {
3610   if (GDK_WINDOW_DESTROYED (window))
3611     return;
3612   /* CHECK: are these really supposed to be the same? */
3613   gdk_win32_window_shape_combine_region (window, shape_region, offset_x, offset_y);
3614 }
3615
3616 void
3617 _gdk_windowing_window_process_updates_recurse (GdkWindow *window,
3618                                                GdkRegion *region)
3619 {
3620   _gdk_window_process_updates_recurse (window, region);
3621 }
3622
3623 void
3624 _gdk_windowing_before_process_all_updates (void)
3625 {
3626 }
3627
3628 void
3629 _gdk_windowing_after_process_all_updates (void)
3630 {
3631 }
3632
3633 static void
3634 gdk_window_impl_iface_init (GdkWindowImplIface *iface)
3635 {
3636   iface->show = gdk_win32_window_show;
3637   iface->hide = gdk_win32_window_hide;
3638   iface->withdraw = gdk_win32_window_withdraw;
3639   iface->set_events = gdk_win32_window_set_events;
3640   iface->get_events = gdk_win32_window_get_events;
3641   iface->raise = gdk_win32_window_raise;
3642   iface->lower = gdk_win32_window_lower;
3643   iface->restack_under = gdk_win32_window_restack_under;
3644   iface->move_resize = gdk_win32_window_move_resize;
3645   iface->set_background = gdk_win32_window_set_background;
3646   iface->set_back_pixmap = gdk_win32_window_set_back_pixmap;
3647   iface->reparent = gdk_win32_window_reparent;
3648   iface->set_cursor = gdk_win32_window_set_cursor;
3649   iface->get_geometry = gdk_win32_window_get_geometry;
3650   iface->get_pointer = gdk_window_win32_get_pointer;
3651   iface->get_root_coords = gdk_win32_window_get_root_coords;
3652   iface->shape_combine_region = gdk_win32_window_shape_combine_region;
3653   iface->input_shape_combine_region = gdk_win32_input_shape_combine_region;
3654   iface->get_deskrelative_origin = gdk_win32_window_get_deskrelative_origin;
3655   iface->set_static_gravities = gdk_win32_window_set_static_gravities;
3656   iface->queue_antiexpose = _gdk_win32_window_queue_antiexpose;
3657   iface->queue_translation = _gdk_win32_window_queue_translation;
3658   iface->destroy = _gdk_win32_window_destroy;
3659 }