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