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