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