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