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