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