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