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