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