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