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