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