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