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