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