]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow-win32.c
Merge from stable:
[~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 static GdkColormap* gdk_window_impl_win32_get_colormap (GdkDrawable *drawable);
39 static void         gdk_window_impl_win32_set_colormap (GdkDrawable *drawable,
40                                                         GdkColormap *cmap);
41 static void         gdk_window_impl_win32_get_size     (GdkDrawable *drawable,
42                                                         gint *width,
43                                                         gint *height);
44 static GdkRegion*   gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable);
45 static void gdk_window_impl_win32_init       (GdkWindowImplWin32      *window);
46 static void gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass);
47 static void gdk_window_impl_win32_finalize   (GObject                 *object);
48
49 static gpointer parent_class = NULL;
50
51 GType
52 _gdk_window_impl_win32_get_type (void)
53 {
54   static GType object_type = 0;
55
56   if (!object_type)
57     {
58       static const GTypeInfo object_info =
59       {
60         sizeof (GdkWindowImplWin32Class),
61         (GBaseInitFunc) NULL,
62         (GBaseFinalizeFunc) NULL,
63         (GClassInitFunc) gdk_window_impl_win32_class_init,
64         NULL,           /* class_finalize */
65         NULL,           /* class_data */
66         sizeof (GdkWindowImplWin32),
67         0,              /* n_preallocs */
68         (GInstanceInitFunc) gdk_window_impl_win32_init,
69       };
70       
71       object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_WIN32,
72                                             "GdkWindowImplWin32",
73                                             &object_info, 0);
74     }
75   
76   return object_type;
77 }
78
79 GType
80 _gdk_window_impl_get_type (void)
81 {
82   return _gdk_window_impl_win32_get_type ();
83 }
84
85 static void
86 gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
87 {
88   impl->width = 1;
89   impl->height = 1;
90
91   impl->hcursor = NULL;
92   impl->hint_flags = 0;
93   impl->extension_events_selected = FALSE;
94 }
95
96 static void
97 gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
98 {
99   GObjectClass *object_class = G_OBJECT_CLASS (klass);
100   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
101   
102   parent_class = g_type_class_peek_parent (klass);
103
104   object_class->finalize = gdk_window_impl_win32_finalize;
105
106   drawable_class->set_colormap = gdk_window_impl_win32_set_colormap;
107   drawable_class->get_colormap = gdk_window_impl_win32_get_colormap;
108   drawable_class->get_size = gdk_window_impl_win32_get_size;
109
110   /* Visible and clip regions are the same */
111   drawable_class->get_clip_region = gdk_window_impl_win32_get_visible_region;
112   drawable_class->get_visible_region = gdk_window_impl_win32_get_visible_region;
113 }
114
115 static void
116 gdk_window_impl_win32_finalize (GObject *object)
117 {
118   GdkWindowObject *wrapper;
119   GdkDrawableImplWin32 *draw_impl;
120   GdkWindowImplWin32 *window_impl;
121   
122   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (object));
123
124   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (object);
125   window_impl = GDK_WINDOW_IMPL_WIN32 (object);
126   
127   wrapper = (GdkWindowObject*) draw_impl->wrapper;
128
129   if (!GDK_WINDOW_DESTROYED (wrapper))
130     {
131       gdk_win32_handle_table_remove (draw_impl->handle);
132     }
133
134   if (window_impl->hcursor != NULL)
135     {
136       if (GetCursor () == window_impl->hcursor)
137         SetCursor (NULL);
138       if (!DestroyCursor (window_impl->hcursor))
139         WIN32_GDI_FAILED("DestroyCursor");
140       window_impl->hcursor = NULL;
141     }
142
143   G_OBJECT_CLASS (parent_class)->finalize (object);
144 }
145
146 static GdkColormap*
147 gdk_window_impl_win32_get_colormap (GdkDrawable *drawable)
148 {
149   GdkDrawableImplWin32 *drawable_impl;
150   
151   g_return_val_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable), NULL);
152
153   drawable_impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
154
155   if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only && 
156       drawable_impl->colormap == NULL)
157     {
158       drawable_impl->colormap = gdk_colormap_get_system ();
159       gdk_colormap_ref (drawable_impl->colormap);
160     }
161   
162   return drawable_impl->colormap;
163 }
164
165 static void
166 gdk_window_impl_win32_set_colormap (GdkDrawable *drawable,
167                                     GdkColormap *cmap)
168 {
169   GdkWindowImplWin32 *impl;
170   GdkDrawableImplWin32 *draw_impl;
171   
172   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable));
173
174   impl = GDK_WINDOW_IMPL_WIN32 (drawable);
175   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
176
177   /* chain up */
178   GDK_DRAWABLE_CLASS (parent_class)->set_colormap (drawable, cmap);
179   
180   if (cmap)
181     {
182       /* XXX */
183       g_print("gdk_window_impl_win32_set_colormap: XXX\n");
184     }
185 }
186
187 static void
188 gdk_window_impl_win32_get_size (GdkDrawable *drawable,
189                                 gint        *width,
190                                 gint        *height)
191 {
192   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable));
193
194   if (width)
195     *width = GDK_WINDOW_IMPL_WIN32 (drawable)->width;
196   if (height)
197     *height = GDK_WINDOW_IMPL_WIN32 (drawable)->height;
198 }
199
200 static GdkRegion*
201 gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable)
202 {
203   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (drawable);
204   GdkRectangle result_rect;
205
206   result_rect.x = 0;
207   result_rect.y = 0;
208   result_rect.width = impl->width;
209   result_rect.height = impl->height;
210
211   gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
212
213   return gdk_region_rectangle (&result_rect);
214 }
215
216 void
217 _gdk_windowing_window_init (void)
218 {
219   GdkWindowObject *private;
220   GdkWindowImplWin32 *impl;
221   GdkDrawableImplWin32 *draw_impl;
222   RECT rect;
223   guint width;
224   guint height;
225
226   g_assert (_gdk_parent_root == NULL);
227   
228   SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
229   width  = rect.right - rect.left;
230   height = rect.bottom - rect.top;
231
232   _gdk_parent_root = g_object_new (GDK_TYPE_WINDOW, NULL);
233   private = (GdkWindowObject *)_gdk_parent_root;
234   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
235   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
236   
237   draw_impl->handle = _gdk_root_window;
238   draw_impl->wrapper = GDK_DRAWABLE (private);
239   draw_impl->colormap = gdk_colormap_get_system ();
240   gdk_colormap_ref (draw_impl->colormap);
241   
242   private->window_type = GDK_WINDOW_ROOT;
243   private->depth = gdk_visual_get_system ()->depth;
244   impl->width = width;
245   impl->height = height;
246
247   _gdk_window_init_position (GDK_WINDOW (private));
248
249   gdk_win32_handle_table_insert (&_gdk_root_window, _gdk_parent_root);
250 }
251
252 static const gchar *
253 get_default_title (void)
254 {
255   const char *title;
256 #if 0 /* So that we can build with GLib 2.0... */
257   title = g_get_application_name ();
258   if (!title)
259 #endif
260     title = g_get_prgname ();
261
262   return title;
263 }
264
265 /* The Win API function AdjustWindowRect may return negative values
266  * resulting in obscured title bars. This helper function is coreccting it.
267  */
268 static BOOL
269 SafeAdjustWindowRectEx (RECT* lpRect,
270                         DWORD dwStyle, 
271                         BOOL  bMenu, 
272                         DWORD dwExStyle)
273 {
274   if (!AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle))
275     {
276       WIN32_API_FAILED ("AdjustWindowRectEx");
277       return FALSE;
278     }
279   if (lpRect->left < 0)
280     {
281       lpRect->right -= lpRect->left;
282       lpRect->left = 0;
283     }
284   if (lpRect->top < 0)
285     {
286       lpRect->bottom -= lpRect->top;
287       lpRect->top = 0;
288     }
289   return TRUE;
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, dwExStyle;
420   RECT rect;
421   GdkWindow *window;
422   GdkWindowObject *private;
423   GdkWindowImplWin32 *impl;
424   GdkDrawableImplWin32 *draw_impl;
425   GdkVisual *visual;
426   int width, height;
427   int x, y;
428   char *title;
429   char *mbtitle;
430
431   g_return_val_if_fail (attributes != NULL, NULL);
432
433   if (!parent)
434     parent = _gdk_parent_root;
435
436   g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
437   
438   GDK_NOTE (MISC,
439             g_print ("gdk_window_new: %s\n",
440                      (attributes->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
441                       (attributes->window_type == GDK_WINDOW_CHILD ? "CHILD" :
442                        (attributes->window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
443                         (attributes->window_type == GDK_WINDOW_TEMP ? "TEMP" :
444                          "???"))))));
445
446   if (GDK_WINDOW_DESTROYED (parent))
447     return NULL;
448   
449   hparent = GDK_WINDOW_HWND (parent);
450
451   window = g_object_new (GDK_TYPE_WINDOW, NULL);
452   private = (GdkWindowObject *)window;
453   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
454   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
455   draw_impl->wrapper = GDK_DRAWABLE (window);
456
457   /* Windows with a foreign parent are treated as if they are children
458    * of the root window, except for actual creation.
459    */
460   if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
461     parent = _gdk_parent_root;
462   
463   private->parent = (GdkWindowObject *)parent;
464
465   if (attributes_mask & GDK_WA_X)
466     x = attributes->x;
467   else
468     x = CW_USEDEFAULT;
469   
470   if (attributes_mask & GDK_WA_Y)
471     y = attributes->y;
472   else if (attributes_mask & GDK_WA_X)
473     y = 100;                    /* ??? We must put it somewhere... */
474   else
475     y = 0;                      /* x is CW_USEDEFAULT, y doesn't matter then */
476   
477   private->x = x;
478   private->y = y;
479   impl->width = (attributes->width > 1) ? (attributes->width) : (1);
480   impl->height = (attributes->height > 1) ? (attributes->height) : (1);
481   impl->extension_events_selected = FALSE;
482   private->window_type = attributes->window_type;
483
484   _gdk_window_init_position (GDK_WINDOW (private));
485   if (impl->position_info.big)
486     private->guffaw_gravity = TRUE;
487
488   if (attributes_mask & GDK_WA_VISUAL)
489     visual = attributes->visual;
490   else
491     visual = gdk_visual_get_system ();
492
493   if (attributes_mask & GDK_WA_TITLE)
494     title = attributes->title;
495   else
496     title = get_default_title ();
497   if (!title || !*title)
498     title = "GDK client window";
499
500   private->event_mask = GDK_STRUCTURE_MASK | attributes->event_mask;
501       
502   if (private->parent && private->parent->guffaw_gravity)
503     {
504       /* XXX ??? */
505     }
506
507   if (attributes->wclass == GDK_INPUT_OUTPUT)
508     {
509       dwExStyle = 0;
510
511       private->input_only = FALSE;
512       private->depth = visual->depth;
513       
514       if (attributes_mask & GDK_WA_COLORMAP)
515         {
516           draw_impl->colormap = attributes->colormap;
517           gdk_colormap_ref (attributes->colormap);
518         }
519       else
520         {
521           draw_impl->colormap = gdk_colormap_get_system ();
522         }
523     }
524   else
525     {
526       dwExStyle = WS_EX_TRANSPARENT;
527       private->depth = 0;
528       private->input_only = TRUE;
529       draw_impl->colormap = gdk_colormap_get_system ();
530       gdk_colormap_ref (draw_impl->colormap);
531       GDK_NOTE (MISC, g_print ("...GDK_INPUT_ONLY, system colormap\n"));
532     }
533
534   if (private->parent)
535     private->parent->children = g_list_prepend (private->parent->children, window);
536
537   switch (private->window_type)
538     {
539     case GDK_WINDOW_TOPLEVEL:
540       dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
541       hparent = _gdk_root_window;
542       break;
543
544     case GDK_WINDOW_CHILD:
545       dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
546       break;
547
548     case GDK_WINDOW_DIALOG:
549       dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
550 #if 0
551       dwExStyle |= WS_EX_TOPMOST; /* //HB: want this? */
552 #endif
553       hparent = _gdk_root_window;
554       break;
555
556     case GDK_WINDOW_TEMP:
557       dwStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
558       /* a temp window is not necessarily a top level window */
559       dwStyle |= (_gdk_parent_root == parent ? WS_POPUP : WS_CHILDWINDOW);
560       dwExStyle |= WS_EX_TOOLWINDOW;
561       break;
562
563     case GDK_WINDOW_ROOT:
564       g_error ("cannot make windows of type GDK_WINDOW_ROOT");
565       break;
566     }
567
568   klass = RegisterGdkClass (private->window_type);
569
570   if (private->window_type != GDK_WINDOW_CHILD)
571     {
572       if (x == CW_USEDEFAULT)
573         {
574           rect.left = 100;
575           rect.top = 100;
576         }
577       else
578         {
579           rect.left = x;
580           rect.top = y;
581         }
582
583       rect.right = rect.left + impl->width;
584       rect.bottom = rect.top + impl->height;
585
586       SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
587
588       if (x != CW_USEDEFAULT)
589         {
590           x = rect.left;
591           y = rect.top;
592         }
593       width = rect.right - rect.left;
594       height = rect.bottom - rect.top;
595     }
596   else
597     {
598       width = impl->width;
599       height = impl->height;
600     }
601
602   mbtitle = g_locale_from_utf8 (title, -1, NULL, NULL, NULL);
603   
604 #ifdef WITHOUT_WM_CREATE
605   draw_impl->handle = CreateWindowEx (dwExStyle,
606                                       MAKEINTRESOURCE(klass),
607                                       mbtitle,
608                                       dwStyle,
609                                       impl->position_info.x, impl->position_info.y, 
610                                       impl->position_info.width, impl->position_info.height,
611                                       hparent,
612                                       NULL,
613                                       _gdk_app_hmodule,
614                                       NULL);
615 #else
616   {
617   HWND hwndNew =
618     CreateWindowEx (dwExStyle,
619                     MAKEINTRESOURCE(klass),
620                     mbtitle,
621                     dwStyle,
622                     impl->position_info.x, impl->position_info.y, 
623                     impl->position_info.width, impl->position_info.height,
624                     hparent,
625                     NULL,
626                     _gdk_app_hmodule,
627                     window);
628   if (GDK_WINDOW_HWND (window) != hwndNew)
629     {
630       g_warning("gdk_window_new: gdk_event_translate::WM_CREATE (%p, %p) HWND mismatch.",
631                 GDK_WINDOW_HWND (window),
632                 hwndNew);
633
634       /* HB: IHMO due to a race condition the handle was increased by
635        * one, which causes much trouble. Because I can't find the 
636        * real bug, try to workaround it ...
637        * To reproduce: compile with MSVC 5, DEBUG=1
638        */
639 # if 0
640       gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
641       GDK_WINDOW_HWND (window) = hwndNew;
642       gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
643 # else
644       /* the old behaviour, but with warning */
645       GDK_WINDOW_HWND (window) = hwndNew;
646 # endif
647
648     }
649   }
650   gdk_drawable_ref (window);
651   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
652 #endif
653
654   GDK_NOTE (MISC,
655             g_print ("... \"%s\" %dx%d@+%d+%d %p = %p\n",
656                      mbtitle,
657                      width, height, (x == CW_USEDEFAULT ? -9999 : x), y, 
658                      hparent,
659                      GDK_WINDOW_HWND (window)));
660
661   g_free (mbtitle);
662
663   if (draw_impl->handle == NULL)
664     {
665       WIN32_API_FAILED ("CreateWindowEx");
666       g_object_unref ((GObject *) window);
667       return NULL;
668     }
669
670 #ifdef WITHOUT_WM_CREATE
671   gdk_drawable_ref (window);
672   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
673 #endif
674
675   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
676                                   (attributes->cursor) :
677                                   NULL));
678
679   return window;
680 }
681
682 GdkWindow *
683 gdk_window_foreign_new_for_display (GdkDisplay      *display,
684                                     GdkNativeWindow  anid)
685 {
686   GdkWindow *window;
687   GdkWindowObject *private;
688   GdkWindowImplWin32 *impl;
689   GdkDrawableImplWin32 *draw_impl;
690
691   HANDLE parent;
692   RECT rect;
693   POINT point;
694
695   g_return_val_if_fail (display == gdk_display_get_default (), NULL);
696
697   window = g_object_new (GDK_TYPE_WINDOW, NULL);
698   private = (GdkWindowObject *)window;
699   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
700   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
701   draw_impl->wrapper = GDK_DRAWABLE (window);
702   parent = GetParent ((HWND)anid);
703   
704   private->parent = gdk_win32_handle_table_lookup ((GdkNativeWindow) parent);
705   if (!private->parent || GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_FOREIGN)
706     private->parent = (GdkWindowObject *)_gdk_parent_root;
707   
708   private->parent->children = g_list_prepend (private->parent->children, window);
709
710   draw_impl->handle = (HWND) anid;
711   GetClientRect ((HWND) anid, &rect);
712   point.x = rect.left;
713   point.y = rect.right;
714   ClientToScreen ((HWND) anid, &point);
715   if (parent != _gdk_root_window)
716     ScreenToClient (parent, &point);
717   private->x = point.x;
718   private->y = point.y;
719   impl->width = rect.right - rect.left;
720   impl->height = rect.bottom - rect.top;
721   private->window_type = GDK_WINDOW_FOREIGN;
722   private->destroyed = FALSE;
723   private->event_mask = GDK_ALL_EVENTS_MASK; /* XXX */
724   if (IsWindowVisible ((HWND) anid))
725     private->state &= (~GDK_WINDOW_STATE_WITHDRAWN);
726   else
727     private->state |= GDK_WINDOW_STATE_WITHDRAWN;
728   private->depth = gdk_visual_get_system ()->depth;
729
730   _gdk_window_init_position (GDK_WINDOW (private));
731
732   gdk_drawable_ref (window);
733   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
734
735   return window;
736 }
737
738 GdkWindow*
739 gdk_window_lookup (GdkNativeWindow hwnd)
740 {
741   return (GdkWindow*) gdk_win32_handle_table_lookup (hwnd); 
742 }
743
744 void
745 _gdk_windowing_window_destroy (GdkWindow *window,
746                                gboolean   recursing,
747                                gboolean   foreign_destroy)
748 {
749   GdkWindowObject *private = (GdkWindowObject *)window;
750
751   g_return_if_fail (GDK_IS_WINDOW (window));
752   
753   GDK_NOTE (MISC, g_print ("_gdk_windowing_window_destroy %p\n",
754                            GDK_WINDOW_HWND (window)));
755
756   if (private->extension_events != 0)
757     _gdk_input_window_destroy (window);
758
759   if (private->window_type == GDK_WINDOW_FOREIGN)
760     {
761       if (!foreign_destroy && (private->parent != NULL))
762         {
763           /* It's somebody else's window, but in our hierarchy,
764            * so reparent it to the root window, and then call
765            * DestroyWindow() on it.
766            */
767           gdk_window_hide (window);
768           gdk_window_reparent (window, NULL, 0, 0);
769           
770           /* Is this too drastic? Many (most?) applications
771            * quit if any window receives WM_QUIT I think.
772            * OTOH, I don't think foreign windows are much
773            * used, so the question is maybe academic.
774            */
775           PostMessage (GDK_WINDOW_HWND (window), WM_QUIT, 0, 0);
776         }
777     }
778   else if (!recursing && !foreign_destroy)
779     {
780       private->destroyed = TRUE;
781       DestroyWindow (GDK_WINDOW_HWND (window));
782     }
783 }
784
785 /* This function is called when the window really gone.
786  */
787 void
788 gdk_window_destroy_notify (GdkWindow *window)
789 {
790   g_return_if_fail (window != NULL);
791   g_return_if_fail (GDK_IS_WINDOW (window));
792
793   GDK_NOTE (EVENTS,
794             g_print ("gdk_window_destroy_notify: %p  %s\n",
795                      GDK_WINDOW_HWND (window),
796                      (GDK_WINDOW_DESTROYED (window) ? "(destroyed)" : "")));
797
798   if (!GDK_WINDOW_DESTROYED (window))
799     {
800       if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
801         g_warning ("window %p unexpectedly destroyed",
802                    GDK_WINDOW_HWND (window));
803
804       _gdk_window_destroy (window, TRUE);
805     }
806   
807   gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
808   gdk_drawable_unref (window);
809 }
810
811 static void
812 show_window_internal (GdkWindow *window,
813                       gboolean   raise)
814 {
815   GdkWindowObject *private;
816   
817   private = GDK_WINDOW_OBJECT (window);
818
819   if (!private->destroyed)
820     {
821       GDK_NOTE (MISC, g_print ("gdk_window_show: %p\n",
822                                GDK_WINDOW_HWND (window)));
823
824       private->state &= (~GDK_WINDOW_STATE_WITHDRAWN);
825       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
826         {
827           ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNOACTIVATE);
828           SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOPMOST, 0, 0, 0, 0,
829                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
830 #if 0
831           /* Don't put on toolbar */
832           ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
833 #endif
834         }
835       else
836         {
837           if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
838             {
839               SetWindowPos(GDK_WINDOW_HWND (window), HWND_TOP, 0, 0, 0, 0,
840                            SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE);
841             }
842           else
843             {
844               GdkWindow *parent = GDK_WINDOW (private->parent);
845
846               /* Todo: GDK_WINDOW_STATE_STICKY */
847               if (private->state & GDK_WINDOW_STATE_ICONIFIED)
848                 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMINIMIZED);
849               else if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
850                 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMAXIMIZED);
851               else
852                 {
853                   ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
854                   ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
855                 }
856               if (parent == _gdk_parent_root)
857                 SetForegroundWindow (GDK_WINDOW_HWND (window));
858               if (raise)
859                 BringWindowToTop (GDK_WINDOW_HWND (window));
860 #if 0
861               ShowOwnedPopups (GDK_WINDOW_HWND (window), TRUE);
862 #endif
863             }
864         }
865     }
866 }
867
868 void
869 gdk_window_show_unraised (GdkWindow *window)
870 {
871   g_return_if_fail (GDK_IS_WINDOW (window));
872   
873   show_window_internal (window, FALSE);
874 }
875
876 void
877 gdk_window_show (GdkWindow *window)
878 {
879   g_return_if_fail (GDK_IS_WINDOW (window));
880
881   show_window_internal (window, TRUE);
882 }
883
884 void
885 gdk_window_hide (GdkWindow *window)
886 {
887   GdkWindowObject *private;
888   
889   g_return_if_fail (window != NULL);
890
891   private = (GdkWindowObject*) window;
892   if (!private->destroyed)
893     {
894       GDK_NOTE (MISC, g_print ("gdk_window_hide: %p\n",
895                                GDK_WINDOW_HWND (window)));
896
897       private->state |= GDK_WINDOW_STATE_WITHDRAWN;
898
899       _gdk_window_clear_update_area (window);
900
901       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
902         ShowOwnedPopups (GDK_WINDOW_HWND (window), FALSE);
903
904       if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
905         {
906           SetWindowPos(GDK_WINDOW_HWND (window), HWND_BOTTOM, 0, 0, 0, 0,
907                        SWP_HIDEWINDOW | SWP_NOREDRAW | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
908         }
909       else
910         {
911           ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
912         }
913     }
914 }
915
916 void
917 gdk_window_withdraw (GdkWindow *window)
918 {
919   GdkWindowObject *private;
920   
921   g_return_if_fail (window != NULL);
922   
923   private = (GdkWindowObject*) window;
924   if (!private->destroyed)
925     {
926       GDK_NOTE (MISC, g_print ("gdk_window_withdraw: %p\n",
927                                GDK_WINDOW_HWND (window)));
928
929       gdk_window_hide (window); /* ??? */
930     }
931 }
932
933 void
934 gdk_window_move (GdkWindow *window,
935                  gint       x,
936                  gint       y)
937 {
938   GdkWindowObject *private = (GdkWindowObject *)window;
939   GdkWindowImplWin32 *impl;
940
941   g_return_if_fail (window != NULL);
942   g_return_if_fail (GDK_IS_WINDOW (window));
943
944   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
945   
946   if (!GDK_WINDOW_DESTROYED (window))
947     {
948       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
949         _gdk_window_move_resize_child (window, x, y,
950                                        impl->width, impl->height);
951       else
952         {
953           if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
954                              x, y, impl->width, impl->height,
955                              SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER))
956             WIN32_API_FAILED ("SetWindowPos");
957         }
958     }
959 }
960
961 void
962 gdk_window_resize (GdkWindow *window,
963                    gint       width,
964                    gint       height)
965 {
966   GdkWindowObject *private = (GdkWindowObject*) window;
967   GdkWindowImplWin32 *impl;
968   int x, y;
969
970   g_return_if_fail (window != NULL);
971   g_return_if_fail (GDK_IS_WINDOW (window));
972
973   if (width < 1)
974     width = 1;
975   if (height < 1)
976     height = 1;
977
978   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
979   
980   if (!GDK_WINDOW_DESTROYED (window))
981     {
982       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
983         _gdk_window_move_resize_child (window, private->x, private->y,
984                                        width, height);
985       else
986         {
987           POINT pt;
988           RECT rect;
989           DWORD dwStyle;
990           DWORD dwExStyle;
991
992           pt.x = 0;
993           pt.y = 0; 
994           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
995           rect.left = pt.x;
996           rect.top = pt.y;
997           rect.right = pt.x + width;
998           rect.bottom = pt.y + height;
999
1000           dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1001           dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1002           if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
1003             WIN32_API_FAILED ("AdjustWindowRectEx");
1004
1005           x = rect.left;
1006           y = rect.top;
1007           width = rect.right - rect.left;
1008           height = rect.bottom - rect.top;
1009           if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
1010                              x, y, width, height,
1011                              SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER))
1012             WIN32_API_FAILED ("SetWindowPos");
1013         }
1014       private->resize_count += 1;
1015     }
1016 }
1017
1018 void
1019 gdk_window_move_resize (GdkWindow *window,
1020                         gint       x,
1021                         gint       y,
1022                         gint       width,
1023                         gint       height)
1024 {
1025   GdkWindowObject *private = (GdkWindowObject*) window;
1026   GdkWindowImplWin32 *impl;
1027
1028   g_return_if_fail (window != NULL);
1029   g_return_if_fail (GDK_IS_WINDOW (window));
1030
1031   if (width < 1)
1032     width = 1;
1033   if (height < 1)
1034     height = 1;
1035   
1036   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
1037
1038   if (!private->destroyed)
1039     {
1040       RECT rect;
1041       DWORD dwStyle;
1042       DWORD dwExStyle;
1043
1044       GDK_NOTE (MISC, g_print ("gdk_window_move_resize: %p %dx%d@+%d+%d\n",
1045                                GDK_WINDOW_HWND (window),
1046                                width, height, x, y));
1047       
1048       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
1049         _gdk_window_move_resize_child (window, x, y, width, height);
1050       else
1051         {
1052           rect.left = x;
1053           rect.top = y;
1054           rect.right = x + width;
1055           rect.bottom = y + height;
1056
1057           dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1058           dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1059           if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
1060             WIN32_API_FAILED ("AdjustWindowRectEx");
1061
1062           GDK_NOTE (MISC, g_print ("...SetWindowPos(%p,%ldx%ld@+%ld+%ld)\n",
1063                                    GDK_WINDOW_HWND (window),
1064                                    rect.right - rect.left, rect.bottom - rect.top,
1065                                    rect.left, rect.top));
1066           if (!SetWindowPos (GDK_WINDOW_HWND (window), NULL,
1067                              rect.left, rect.top,
1068                              rect.right - rect.left, rect.bottom - rect.top,
1069                              SWP_NOACTIVATE | SWP_NOZORDER))
1070             WIN32_API_FAILED ("SetWindowPos");
1071         }
1072     }
1073 }
1074
1075 void
1076 gdk_window_reparent (GdkWindow *window,
1077                      GdkWindow *new_parent,
1078                      gint       x,
1079                      gint       y)
1080 {
1081   GdkWindowObject *window_private;
1082   GdkWindowObject *parent_private;
1083   GdkWindowObject *old_parent_private;
1084   GdkWindowImplWin32 *impl;
1085
1086   g_return_if_fail (window != NULL);
1087   g_return_if_fail (GDK_IS_WINDOW (window));
1088   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1089   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1090
1091   if (!new_parent)
1092     new_parent = _gdk_parent_root;
1093
1094   window_private = (GdkWindowObject*) window;
1095   old_parent_private = (GdkWindowObject *) window_private->parent;
1096   parent_private = (GdkWindowObject*) new_parent;
1097   impl = GDK_WINDOW_IMPL_WIN32 (window_private->impl);
1098
1099   if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (new_parent))
1100     {
1101       GDK_NOTE (MISC, g_print ("gdk_window_reparent: %p %p\n",
1102                                GDK_WINDOW_HWND (window),
1103                                GDK_WINDOW_HWND (new_parent)));
1104       if (!SetParent (GDK_WINDOW_HWND (window),
1105                       GDK_WINDOW_HWND (new_parent)))
1106         WIN32_API_FAILED ("SetParent");
1107
1108       if (!MoveWindow (GDK_WINDOW_HWND (window),
1109                        x, y, impl->width, impl->height, TRUE))
1110         WIN32_API_FAILED ("MoveWindow");
1111     }
1112
1113   /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1114    * the root window
1115    */
1116   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1117     new_parent = _gdk_parent_root;
1118   
1119   window_private->parent = (GdkWindowObject *)new_parent;
1120
1121   if (old_parent_private)
1122     old_parent_private->children =
1123       g_list_remove (old_parent_private->children, window);
1124
1125 #if 0
1126   if ((old_parent_private &&
1127        (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
1128       (!old_parent_private && parent_private->guffaw_gravity))
1129     gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
1130 #endif
1131
1132   parent_private->children = g_list_prepend (parent_private->children, window);
1133   _gdk_window_init_position (GDK_WINDOW (window_private));
1134 }
1135
1136 void
1137 _gdk_windowing_window_clear_area (GdkWindow *window,
1138                                   gint       x,
1139                                   gint       y,
1140                                   gint       width,
1141                                   gint       height)
1142 {
1143   GdkWindowImplWin32 *impl;
1144
1145   g_return_if_fail (window != NULL);
1146   g_return_if_fail (GDK_IS_WINDOW (window));
1147   
1148   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1149
1150   if (!GDK_WINDOW_DESTROYED (window))
1151     {
1152       HDC hdc;
1153
1154       if (width == 0)
1155         width = impl->width - x;
1156       if (height == 0)
1157         height = impl->height - y;
1158       GDK_NOTE (MISC, g_print ("_gdk_windowing_window_clear_area: "
1159                                "%p %dx%d@+%d+%d\n",
1160                                GDK_WINDOW_HWND (window),
1161                                width, height, x, y));
1162       hdc = GetDC (GDK_WINDOW_HWND (window));
1163       IntersectClipRect (hdc, x, y, x + width + 1, y + height + 1);
1164       SendMessage (GDK_WINDOW_HWND (window), WM_ERASEBKGND, (WPARAM) hdc, 0);
1165       if (!ReleaseDC (GDK_WINDOW_HWND (window), hdc))
1166         WIN32_GDI_FAILED ("ReleaseDC");
1167     }
1168 }
1169
1170 void
1171 _gdk_windowing_window_clear_area_e (GdkWindow *window,
1172                                     gint       x,
1173                                     gint       y,
1174                                     gint       width,
1175                                     gint       height)
1176 {
1177   g_return_if_fail (window != NULL);
1178   g_return_if_fail (GDK_IS_WINDOW (window));
1179   
1180   if (!GDK_WINDOW_DESTROYED (window))
1181     {
1182       RECT rect;
1183
1184       GDK_NOTE (MISC, g_print ("_gdk_windowing_window_clear_area_e: "
1185                                "%p %dx%d@+%d+%d\n",
1186                                GDK_WINDOW_HWND (window),
1187                                width, height, x, y));
1188
1189       rect.left = x;
1190       rect.right = x + width + 1;
1191       rect.top = y;
1192       rect.bottom = y + height + 1;
1193       if (!InvalidateRect (GDK_WINDOW_HWND (window), &rect, TRUE))
1194         WIN32_GDI_FAILED ("InvalidateRect");
1195       UpdateWindow (GDK_WINDOW_HWND (window));
1196     }
1197 }
1198
1199 void
1200 gdk_window_raise (GdkWindow *window)
1201 {
1202   g_return_if_fail (window != NULL);
1203   g_return_if_fail (GDK_IS_WINDOW (window));
1204   
1205   if (!GDK_WINDOW_DESTROYED (window))
1206     {
1207       GDK_NOTE (MISC, g_print ("gdk_window_raise: %p\n",
1208                                GDK_WINDOW_HWND (window)));
1209
1210       if (!BringWindowToTop (GDK_WINDOW_HWND (window)))
1211         WIN32_API_FAILED ("BringWindowToTop");
1212     }
1213 }
1214
1215 void
1216 gdk_window_lower (GdkWindow *window)
1217 {
1218   g_return_if_fail (window != NULL);
1219   g_return_if_fail (GDK_IS_WINDOW (window));
1220   
1221   if (!GDK_WINDOW_DESTROYED (window))
1222     {
1223       GDK_NOTE (MISC, g_print ("gdk_window_lower: %p\n",
1224                                GDK_WINDOW_HWND (window)));
1225
1226       if (!SetWindowPos (GDK_WINDOW_HWND (window), HWND_BOTTOM, 0, 0, 0, 0,
1227                          SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE))
1228         WIN32_API_FAILED ("SetWindowPos");
1229     }
1230 }
1231
1232 void
1233 gdk_window_set_hints (GdkWindow *window,
1234                       gint       x,
1235                       gint       y,
1236                       gint       min_width,
1237                       gint       min_height,
1238                       gint       max_width,
1239                       gint       max_height,
1240                       gint       flags)
1241 {
1242   GdkWindowImplWin32 *impl;
1243   WINDOWPLACEMENT size_hints;
1244   RECT rect;
1245   DWORD dwStyle;
1246   DWORD dwExStyle;
1247   int diff;
1248   
1249   g_return_if_fail (window != NULL);
1250   g_return_if_fail (GDK_IS_WINDOW (window));
1251   
1252   if (GDK_WINDOW_DESTROYED (window))
1253     return;
1254   
1255   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1256
1257   GDK_NOTE (MISC, g_print ("gdk_window_set_hints: %p %dx%d..%dx%d @+%d+%d\n",
1258                            GDK_WINDOW_HWND (window),
1259                            min_width, min_height, max_width, max_height,
1260                            x, y));
1261
1262   impl->hint_flags = flags;
1263   size_hints.length = sizeof (size_hints);
1264
1265   if (flags)
1266     {
1267       GdkGeometry geom;
1268       gint        geom_mask = 0;
1269
1270       geom.min_width  = min_width;
1271       geom.min_height = min_height;
1272       geom.max_width  = max_width;
1273       geom.max_height = max_height;
1274
1275       if (flags & GDK_HINT_POS)
1276         {
1277           if (!GetWindowPlacement (GDK_WINDOW_HWND (window), &size_hints))
1278             WIN32_API_FAILED ("GetWindowPlacement");
1279           else
1280             {
1281               GDK_NOTE (MISC, g_print ("...rcNormalPosition:"
1282                                        " (%ld,%ld)--(%ld,%ld)\n",
1283                                        size_hints.rcNormalPosition.left,
1284                                        size_hints.rcNormalPosition.top,
1285                                        size_hints.rcNormalPosition.right,
1286                                        size_hints.rcNormalPosition.bottom));
1287               /* What are the corresponding window coordinates for client
1288                * area coordinates x, y
1289                */
1290               rect.left = x;
1291               rect.top = y;
1292               rect.right = rect.left + 200;     /* dummy */
1293               rect.bottom = rect.top + 200;
1294               dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1295               dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1296               AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1297               size_hints.flags = 0;
1298               size_hints.showCmd = SW_SHOWNA;
1299               
1300               /* Set the normal position hint to that location, with unchanged
1301                * width and height.
1302                */
1303               diff = size_hints.rcNormalPosition.left - rect.left;
1304               size_hints.rcNormalPosition.left = rect.left;
1305               size_hints.rcNormalPosition.right -= diff;
1306               diff = size_hints.rcNormalPosition.top - rect.top;
1307               size_hints.rcNormalPosition.top = rect.top;
1308               size_hints.rcNormalPosition.bottom -= diff;
1309               GDK_NOTE (MISC, g_print ("...setting: (%ld,%ld)--(%ld,%ld)\n",
1310                                        size_hints.rcNormalPosition.left,
1311                                        size_hints.rcNormalPosition.top,
1312                                        size_hints.rcNormalPosition.right,
1313                                        size_hints.rcNormalPosition.bottom));
1314               if (!SetWindowPlacement (GDK_WINDOW_HWND (window), &size_hints))
1315                 WIN32_API_FAILED ("SetWindowPlacement");
1316               impl->hint_x = rect.left;
1317               impl->hint_y = rect.top;
1318             }
1319         }
1320
1321       if (flags & GDK_HINT_MIN_SIZE)
1322         geom_mask |= GDK_HINT_MIN_SIZE;
1323
1324       if (flags & GDK_HINT_MAX_SIZE)
1325         geom_mask |= GDK_HINT_MAX_SIZE;
1326
1327       gdk_window_set_geometry_hints (window, &geom, geom_mask);
1328     }
1329 }
1330
1331 void 
1332 gdk_window_set_geometry_hints (GdkWindow      *window,
1333                                GdkGeometry    *geometry,
1334                                GdkWindowHints  geom_mask)
1335 {
1336   GdkWindowImplWin32 *impl;
1337   WINDOWPLACEMENT size_hints;
1338   RECT rect;
1339   DWORD dwStyle;
1340   DWORD dwExStyle;
1341   gint new_width = 0, new_height = 0;
1342   
1343   g_return_if_fail (window != NULL);
1344   g_return_if_fail (GDK_IS_WINDOW (window));
1345   
1346   if (GDK_WINDOW_DESTROYED (window))
1347     return;
1348
1349   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1350   size_hints.length = sizeof (size_hints);
1351
1352   impl->hint_flags = geom_mask;
1353
1354   if (geom_mask & GDK_HINT_POS)
1355     ; /* even the X11 mplementation doesn't care */
1356
1357   if (geom_mask & GDK_HINT_MIN_SIZE)
1358     {
1359       rect.left = 0;
1360       rect.top = 0;
1361       rect.right = geometry->min_width;
1362       rect.bottom = geometry->min_height;
1363       dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1364       dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1365       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1366       impl->hint_min_width = rect.right - rect.left;
1367       impl->hint_min_height = rect.bottom - rect.top;
1368
1369       /* Also check if he current size of the window is in bounds */
1370       GetClientRect (GDK_WINDOW_HWND (window), &rect);
1371
1372       if (rect.right < geometry->min_width
1373           && rect.bottom < geometry->min_height)
1374         {
1375           new_width = geometry->min_width; new_height = geometry->min_height;
1376         }
1377       else if (rect.right < geometry->min_width)
1378         {
1379           new_width = geometry->min_width; new_height = rect.bottom;
1380         }
1381       else if (rect.bottom < geometry->min_height)
1382         {
1383           new_width = rect.right; new_height = geometry->min_height;
1384         }
1385     }
1386   
1387   if (geom_mask & GDK_HINT_MAX_SIZE)
1388     {
1389       rect.left = 0;
1390       rect.top = 0;
1391       rect.right = geometry->max_width;
1392       rect.bottom = geometry->max_height;
1393       dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1394       dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1395       /* HB: dont' know why AdjustWindowRectEx is called here, ... */
1396       SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1397       impl->hint_max_width = rect.right - rect.left;
1398       impl->hint_max_height = rect.bottom - rect.top;
1399       /* ... but negative sizes are always wrong */
1400       if (impl->hint_max_width < 0) impl->hint_max_width = G_MAXSHORT;
1401       if (impl->hint_max_height < 0) impl->hint_max_height = G_MAXSHORT;
1402
1403       /* Again, check if the window is too large currently. */
1404       GetClientRect (GDK_WINDOW_HWND (window), &rect);
1405       if (rect.right > geometry->max_width
1406           && rect.bottom > geometry->max_height)
1407         {
1408           new_width = geometry->max_width; new_height = geometry->max_height;
1409         }
1410       else if (rect.right > geometry->max_width)
1411         {
1412           new_width = geometry->max_width; new_height = rect.bottom;
1413         }
1414       else if (rect.bottom > geometry->max_height)
1415         {
1416           new_width = rect.right; new_height = geometry->max_height;
1417         }
1418     }
1419
1420   /* finally apply new size constraints */
1421   if (new_width != 0 && new_height != 0)
1422     gdk_window_resize (window, new_width, new_height);
1423   
1424   /* I don't know what to do when called with zero base_width and height. */
1425   if (geom_mask & GDK_HINT_BASE_SIZE
1426       && geometry->base_width > 0
1427       && geometry->base_height > 0)
1428     {
1429       if (!GetWindowPlacement (GDK_WINDOW_HWND (window), &size_hints))
1430         WIN32_API_FAILED ("GetWindowPlacement");
1431       else
1432         {
1433           GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints:"
1434                                    " rcNormalPosition: (%ld,%ld)--(%ld,%ld)\n",
1435                                    size_hints.rcNormalPosition.left,
1436                                    size_hints.rcNormalPosition.top,
1437                                    size_hints.rcNormalPosition.right,
1438                                    size_hints.rcNormalPosition.bottom));
1439           size_hints.rcNormalPosition.right =
1440             size_hints.rcNormalPosition.left + geometry->base_width;
1441           size_hints.rcNormalPosition.bottom =
1442             size_hints.rcNormalPosition.top + geometry->base_height;
1443           GDK_NOTE (MISC, g_print ("...setting: rcNormal: (%ld,%ld)--(%ld,%ld)\n",
1444                                    size_hints.rcNormalPosition.left,
1445                                    size_hints.rcNormalPosition.top,
1446                                    size_hints.rcNormalPosition.right,
1447                                    size_hints.rcNormalPosition.bottom));
1448           if (!SetWindowPlacement (GDK_WINDOW_HWND (window), &size_hints))
1449             WIN32_API_FAILED ("SetWindowPlacement");
1450         }
1451     }
1452   
1453   if (geom_mask & GDK_HINT_RESIZE_INC)
1454     {
1455       /* XXX */
1456     }
1457   
1458   if (geom_mask & GDK_HINT_ASPECT)
1459     {
1460       /* XXX */
1461     }
1462 }
1463
1464 void
1465 gdk_window_set_title (GdkWindow   *window,
1466                       const gchar *title)
1467 {
1468   char *mbtitle;
1469
1470   g_return_if_fail (window != NULL);
1471   g_return_if_fail (GDK_IS_WINDOW (window));
1472   g_return_if_fail (title != NULL);
1473
1474   /* Empty window titles not allowed, so set it to just a period. */
1475   if (!title[0])
1476     title = ".";
1477   
1478   GDK_NOTE (MISC, g_print ("gdk_window_set_title: %p %s\n",
1479                            GDK_WINDOW_HWND (window), title));
1480   
1481   if (!GDK_WINDOW_DESTROYED (window))
1482     {
1483       /* As the title is in UTF-8 we must translate it
1484        * to the system codepage.
1485        */
1486       mbtitle = g_locale_from_utf8 (title, -1, NULL, NULL, NULL);
1487       if (!SetWindowText (GDK_WINDOW_HWND (window), mbtitle))
1488         WIN32_API_FAILED ("SetWindowText");
1489
1490       g_free (mbtitle);
1491     }
1492 }
1493
1494 void          
1495 gdk_window_set_role (GdkWindow   *window,
1496                      const gchar *role)
1497 {
1498   g_return_if_fail (window != NULL);
1499   g_return_if_fail (GDK_IS_WINDOW (window));
1500   
1501   GDK_NOTE (MISC, g_print ("gdk_window_set_role: %p %s\n",
1502                            GDK_WINDOW_HWND (window),
1503                            (role ? role : "NULL")));
1504   /* XXX */
1505 }
1506
1507 void          
1508 gdk_window_set_transient_for (GdkWindow *window, 
1509                               GdkWindow *parent)
1510 {
1511   HWND window_id, parent_id;
1512   LONG style;
1513
1514   g_return_if_fail (window != NULL);
1515   g_return_if_fail (GDK_IS_WINDOW (window));
1516   
1517   GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %p %p\n",
1518                            GDK_WINDOW_HWND (window),
1519                            GDK_WINDOW_HWND (parent)));
1520
1521   if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (parent))
1522     return;
1523
1524   window_id = GDK_WINDOW_HWND (window);
1525   parent_id = GDK_WINDOW_HWND (parent);
1526
1527   if ((style = GetWindowLong (window_id, GWL_STYLE)) == 0)
1528     WIN32_API_FAILED ("GetWindowLong");
1529
1530   style |= WS_POPUP;
1531 #if 0 /* not sure if we want to do this */
1532   style &= ~(WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX);
1533 #endif
1534
1535   if (!SetWindowLong (window_id, GWL_STYLE, style))
1536     WIN32_API_FAILED ("SetWindowLong");
1537 #if 0 /* not sure if we want to do this, clipping to parent size! */
1538   if (!SetParent (window_id, parent_id))
1539         WIN32_API_FAILED ("SetParent");
1540 #else /* make the modal window topmost instead */
1541   if (!SetWindowPos (window_id, HWND_NOTOPMOST, 0, 0, 0, 0,
1542                      SWP_NOMOVE | SWP_NOSIZE))
1543     WIN32_API_FAILED ("SetWindowPos");
1544 #endif
1545
1546   if (!RedrawWindow (window_id, NULL, NULL, 
1547                      RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW))
1548     WIN32_API_FAILED ("RedrawWindow");
1549 }
1550
1551 void
1552 gdk_window_set_background (GdkWindow *window,
1553                            GdkColor  *color)
1554 {
1555   GdkWindowObject *private = (GdkWindowObject *)window;
1556   
1557   g_return_if_fail (window != NULL);
1558   g_return_if_fail (GDK_IS_WINDOW (window));
1559   
1560   GDK_NOTE (MISC, g_print ("gdk_window_set_background: %p %s\n",
1561                            GDK_WINDOW_HWND (window), 
1562                            _gdk_win32_color_to_string (color)));
1563
1564   private->bg_color = *color;
1565
1566   if (private->bg_pixmap &&
1567       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1568       private->bg_pixmap != GDK_NO_BG)
1569     {
1570       gdk_drawable_unref (private->bg_pixmap);
1571       private->bg_pixmap = NULL;
1572     }
1573 }
1574
1575 void
1576 gdk_window_set_back_pixmap (GdkWindow *window,
1577                             GdkPixmap *pixmap,
1578                             gint       parent_relative)
1579 {
1580   GdkWindowObject *private = (GdkWindowObject *)window;
1581
1582   g_return_if_fail (window != NULL);
1583   g_return_if_fail (GDK_IS_WINDOW (window));
1584   g_return_if_fail (pixmap == NULL || !parent_relative);
1585   g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
1586   
1587   if (private->bg_pixmap &&
1588       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1589       private->bg_pixmap != GDK_NO_BG)
1590     gdk_drawable_unref (private->bg_pixmap);
1591
1592   if (parent_relative)
1593     {
1594       private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
1595       GDK_NOTE (MISC, g_print (G_STRLOC ": setting background pixmap to parent_relative\n"));
1596     }
1597   else
1598     {
1599       if (pixmap)
1600         {
1601           gdk_drawable_ref (pixmap);
1602           private->bg_pixmap = pixmap;
1603         }
1604       else
1605         {
1606           private->bg_pixmap = GDK_NO_BG;
1607         }
1608     }
1609 }
1610
1611 void
1612 gdk_window_set_cursor (GdkWindow *window,
1613                        GdkCursor *cursor)
1614 {
1615   GdkWindowImplWin32 *impl;
1616   GdkCursorPrivate *cursor_private;
1617   GdkWindowObject *parent_window;
1618   HCURSOR hcursor;
1619   HCURSOR hprevcursor;
1620   
1621   g_return_if_fail (window != NULL);
1622   g_return_if_fail (GDK_IS_WINDOW (window));
1623   
1624   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1625   cursor_private = (GdkCursorPrivate*) cursor;
1626   
1627   if (GDK_WINDOW_DESTROYED (window))
1628     return;
1629
1630   if (!cursor)
1631     hcursor = NULL;
1632   else
1633     hcursor = cursor_private->hcursor;
1634   
1635   GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %p %p\n",
1636                            GDK_WINDOW_HWND (window),
1637                            hcursor));
1638
1639   /* First get the old cursor, if any (we wait to free the old one
1640    * since it may be the current cursor set in the Win32 API right
1641    * now).
1642    */
1643   hprevcursor = impl->hcursor;
1644
1645   if (hcursor == NULL)
1646     impl->hcursor = NULL;
1647   else
1648     {
1649       /* We must copy the cursor as it is OK to destroy the GdkCursor
1650        * while still in use for some window. See for instance
1651        * gimp_change_win_cursor() which calls gdk_window_set_cursor
1652        * (win, cursor), and immediately afterwards gdk_cursor_destroy
1653        * (cursor).
1654        */
1655       if ((impl->hcursor = CopyCursor (hcursor)) == NULL)
1656         WIN32_API_FAILED ("CopyCursor");
1657       GDK_NOTE (MISC, g_print ("...CopyCursor (%p) = %p\n",
1658                                hcursor, impl->hcursor));
1659     }
1660
1661   /* If the pointer is over our window, set new cursor if given */
1662   if (gdk_window_get_pointer(window, NULL, NULL, NULL) == window)
1663     if (impl->hcursor != NULL)
1664       SetCursor (impl->hcursor);
1665
1666   /* Destroy the previous cursor: Need to make sure it's no longer in
1667    * use before we destroy it, in case we're not over our window but
1668    * the cursor is still set to our old one.
1669    */
1670   if (hprevcursor != NULL)
1671     {
1672       if (GetCursor() == hprevcursor)
1673         {
1674           /* Look for a suitable cursor to use instead */
1675           hcursor = NULL;
1676           parent_window = GDK_WINDOW_OBJECT (window)->parent;
1677           while (hcursor == NULL)
1678             {
1679               if (parent_window)
1680                 {
1681                   impl = GDK_WINDOW_IMPL_WIN32 (parent_window->impl);
1682                   hcursor = impl->hcursor;
1683                   parent_window = parent_window->parent;
1684                 }
1685               else
1686                 {
1687                   hcursor = LoadCursor (NULL, IDC_ARROW);
1688                 }
1689             }
1690           SetCursor (hcursor);
1691         }
1692
1693       GDK_NOTE (MISC, g_print ("...DestroyCursor (%p)\n",
1694                                hprevcursor));
1695       
1696       if (!DestroyCursor (hprevcursor))
1697         WIN32_API_FAILED ("DestroyCursor");
1698     }
1699 }
1700
1701 void
1702 gdk_window_get_geometry (GdkWindow *window,
1703                          gint      *x,
1704                          gint      *y,
1705                          gint      *width,
1706                          gint      *height,
1707                          gint      *depth)
1708 {
1709   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1710   
1711   if (!window)
1712     window = _gdk_parent_root;
1713   
1714   if (!GDK_WINDOW_DESTROYED (window))
1715     {
1716       RECT rect;
1717
1718       if (!GetClientRect (GDK_WINDOW_HWND (window), &rect))
1719         WIN32_API_FAILED ("GetClientRect");
1720
1721       if (window != _gdk_parent_root)
1722         {
1723           POINT pt;
1724           GdkWindow *parent = gdk_window_get_parent (window);
1725
1726           pt.x = rect.left;
1727           pt.y = rect.top;
1728           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1729           ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
1730           rect.left = pt.x;
1731           rect.top = pt.y;
1732
1733           pt.x = rect.right;
1734           pt.y = rect.bottom;
1735           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1736           ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
1737           rect.right = pt.x;
1738           rect.bottom = pt.y;
1739         }
1740
1741       if (x)
1742         *x = rect.left;
1743       if (y)
1744         *y = rect.top;
1745       if (width)
1746         *width = rect.right - rect.left;
1747       if (height)
1748         *height = rect.bottom - rect.top;
1749       if (depth)
1750         *depth = gdk_drawable_get_visual (window)->depth;
1751     }
1752 }
1753
1754 gint
1755 gdk_window_get_origin (GdkWindow *window,
1756                        gint      *x,
1757                        gint      *y)
1758 {
1759   gint return_val;
1760   gint tx = 0;
1761   gint ty = 0;
1762
1763   g_return_val_if_fail (window != NULL, 0);
1764
1765   if (!GDK_WINDOW_DESTROYED (window))
1766     {
1767       POINT pt;
1768
1769       pt.x = 0;
1770       pt.y = 0;
1771       ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1772       tx = pt.x;
1773       ty = pt.y;
1774       return_val = 1;
1775     }
1776   else
1777     return_val = 0;
1778   
1779   if (x)
1780     *x = tx;
1781   if (y)
1782     *y = ty;
1783
1784   GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %p: +%d+%d\n",
1785                            GDK_WINDOW_HWND (window),
1786                            tx, ty));
1787   return return_val;
1788 }
1789
1790 gboolean
1791 gdk_window_get_deskrelative_origin (GdkWindow *window,
1792                                     gint      *x,
1793                                     gint      *y)
1794 {
1795   return gdk_window_get_origin (window, x, y);
1796 }
1797
1798 void
1799 gdk_window_get_root_origin (GdkWindow *window,
1800                             gint      *x,
1801                             gint      *y)
1802 {
1803   GdkRectangle rect;
1804
1805   g_return_if_fail (GDK_IS_WINDOW (window));
1806
1807   gdk_window_get_frame_extents (window, &rect);
1808
1809   if (x)
1810     *x = rect.x;
1811
1812   if (y)
1813     *y = rect.y;
1814 }
1815
1816 void
1817 gdk_window_get_frame_extents (GdkWindow    *window,
1818                               GdkRectangle *rect)
1819 {
1820   GdkWindowObject *private;
1821   HWND hwnd;
1822   RECT r;
1823
1824   g_return_if_fail (GDK_IS_WINDOW (window));
1825   g_return_if_fail (rect != NULL);
1826
1827   private = GDK_WINDOW_OBJECT (window);
1828
1829   rect->x = 0;
1830   rect->y = 0;
1831   rect->width = 1;
1832   rect->height = 1;
1833   
1834   if (GDK_WINDOW_DESTROYED (window))
1835     return;
1836
1837   while (private->parent && ((GdkWindowObject*) private->parent)->parent)
1838     private = (GdkWindowObject*) private->parent;
1839
1840   hwnd = GDK_WINDOW_HWND (window);
1841
1842   /* find the frame window */
1843   while (HWND_DESKTOP != GetParent (hwnd))
1844     {
1845       hwnd = GetParent (hwnd);
1846       g_return_if_fail (NULL != hwnd);
1847     }
1848
1849   if (!GetWindowRect (hwnd, &r))
1850     WIN32_API_FAILED ("GetWindowRect");
1851
1852   rect->x = r.left;
1853   rect->y = r.top;
1854   rect->width = r.right - r.left;
1855   rect->height = r.bottom - r.top;
1856 }
1857
1858 GdkWindow*
1859 _gdk_windowing_window_get_pointer (GdkDisplay      *display,
1860                                    GdkWindow       *window,
1861                                    gint            *x,
1862                                    gint            *y,
1863                                    GdkModifierType *mask)
1864 {
1865   GdkWindow *return_val;
1866   POINT screen_point, point;
1867   HWND hwnd, hwndc;
1868   BYTE kbd[256];
1869
1870   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1871   
1872   return_val = NULL;
1873   GetCursorPos (&screen_point);
1874   point = screen_point;
1875   ScreenToClient (GDK_WINDOW_HWND (window), &point);
1876
1877   *x = point.x;
1878   *y = point.y;
1879
1880   hwnd = WindowFromPoint (point);
1881   if (hwnd != NULL)
1882     {
1883       gboolean done = FALSE;
1884       
1885       while (!done)
1886         {
1887           point = screen_point;
1888           ScreenToClient (hwnd, &point);
1889           hwndc = ChildWindowFromPoint (hwnd, point);
1890           if (hwndc == NULL)
1891             done = TRUE;
1892           else if (hwndc == hwnd)
1893             done = TRUE;
1894           else
1895             hwnd = hwndc;
1896         }
1897       
1898       return_val = gdk_window_lookup ((GdkNativeWindow) hwnd);
1899     }
1900   else
1901     return_val = NULL;
1902       
1903   GetKeyboardState (kbd);
1904   *mask = 0;
1905   if (kbd[VK_SHIFT] & 0x80)
1906     *mask |= GDK_SHIFT_MASK;
1907   if (kbd[VK_CAPITAL] & 0x80)
1908     *mask |= GDK_LOCK_MASK;
1909   if (kbd[VK_CONTROL] & 0x80)
1910     *mask |= GDK_CONTROL_MASK;
1911   if (kbd[VK_MENU] & 0x80)
1912     *mask |= GDK_MOD1_MASK;
1913   if (kbd[VK_LBUTTON] & 0x80)
1914     *mask |= GDK_BUTTON1_MASK;
1915   if (kbd[VK_MBUTTON] & 0x80)
1916     *mask |= GDK_BUTTON2_MASK;
1917   if (kbd[VK_RBUTTON] & 0x80)
1918     *mask |= GDK_BUTTON3_MASK;
1919   
1920   return return_val;
1921 }
1922
1923 void
1924 _gdk_windowing_get_pointer (GdkDisplay       *display,
1925                             GdkScreen       **screen,
1926                             gint             *x,
1927                             gint             *y,
1928                             GdkModifierType  *mask)
1929 {
1930   GdkScreen *default_screen = gdk_display_get_default_screen (display);
1931   GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
1932   
1933   *screen = default_screen;
1934   _gdk_windowing_window_get_pointer (display, root_window, x, y, mask);
1935 }
1936
1937 GdkWindow*
1938 _gdk_windowing_window_at_pointer (GdkDisplay *display,
1939                                   gint       *win_x,
1940                                   gint       *win_y)
1941 {
1942   GdkWindow *window;
1943   POINT point, pointc;
1944   HWND hwnd, hwndc;
1945   RECT rect;
1946
1947   GetCursorPos (&pointc);
1948   point = pointc;
1949   hwnd = WindowFromPoint (point);
1950
1951   if (hwnd == NULL)
1952     {
1953       window = _gdk_parent_root;
1954       *win_x = pointc.x;
1955       *win_y = pointc.y;
1956       return window;
1957     }
1958       
1959   ScreenToClient (hwnd, &point);
1960
1961   do {
1962     hwndc = ChildWindowFromPoint (hwnd, point);
1963     ClientToScreen (hwnd, &point);
1964     ScreenToClient (hwndc, &point);
1965   } while (hwndc != hwnd && (hwnd = hwndc, 1));
1966
1967   window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
1968
1969   if (window && (win_x || win_y))
1970     {
1971       GetClientRect (hwnd, &rect);
1972       *win_x = point.x - rect.left;
1973       *win_y = point.y - rect.top;
1974     }
1975
1976   GDK_NOTE (MISC, g_print ("gdk_window_at_pointer: +%ld+%ld %p%s\n",
1977                            point.x, point.y,
1978                            hwnd,
1979                            (window == NULL ? " NULL" : "")));
1980
1981   return window;
1982 }
1983
1984 GdkEventMask  
1985 gdk_window_get_events (GdkWindow *window)
1986 {
1987   g_return_val_if_fail (window != NULL, 0);
1988   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1989
1990   if (GDK_WINDOW_DESTROYED (window))
1991     return 0;
1992
1993   return GDK_WINDOW_OBJECT (window)->event_mask;
1994 }
1995
1996 void          
1997 gdk_window_set_events (GdkWindow   *window,
1998                        GdkEventMask event_mask)
1999 {
2000   g_return_if_fail (window != NULL);
2001   g_return_if_fail (GDK_IS_WINDOW (window));
2002
2003   if (GDK_WINDOW_DESTROYED (window))
2004     return;
2005
2006   /* gdk_window_new() always sets the GDK_STRUCTURE_MASK, so better
2007    * set it here, too. Not that I know or remember why it is
2008    * necessary, will have to test some day.
2009    */
2010   GDK_WINDOW_OBJECT (window)->event_mask = GDK_STRUCTURE_MASK | event_mask;
2011 }
2012
2013 void
2014 gdk_window_shape_combine_mask (GdkWindow *window,
2015                                GdkBitmap *mask,
2016                                gint x, gint y)
2017 {
2018   g_return_if_fail (window != NULL);
2019   g_return_if_fail (GDK_IS_WINDOW (window));
2020
2021   if (!mask)
2022     {
2023       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %p none\n",
2024                                GDK_WINDOW_HWND (window)));
2025       SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
2026     }
2027   else
2028     {
2029       HRGN hrgn;
2030       DWORD dwStyle;
2031       DWORD dwExStyle;
2032       RECT rect;
2033
2034       /* Convert mask bitmap to region */
2035       hrgn = _gdk_win32_bitmap_to_hrgn (mask);
2036
2037       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %p %p\n",
2038                                GDK_WINDOW_HWND (window),
2039                                GDK_WINDOW_HWND (mask)));
2040
2041       /* SetWindowRgn wants window (not client) coordinates */ 
2042       dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2043       dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
2044       GetClientRect (GDK_WINDOW_HWND (window), &rect);
2045       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
2046       OffsetRgn (hrgn, -rect.left, -rect.top);
2047
2048       OffsetRgn (hrgn, x, y);
2049
2050       /* If this is a top-level window, add the title bar to the region */
2051       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
2052         {
2053           HRGN tmp = CreateRectRgn (0, 0, rect.right - rect.left, -rect.top);
2054           CombineRgn (hrgn, hrgn, tmp, RGN_OR);
2055           DeleteObject (tmp);
2056         }
2057       
2058       SetWindowRgn (GDK_WINDOW_HWND (window), hrgn, TRUE);
2059     }
2060 }
2061
2062 void
2063 gdk_window_set_override_redirect (GdkWindow *window,
2064                                   gboolean   override_redirect)
2065 {
2066   g_return_if_fail (window != NULL);
2067   g_return_if_fail (GDK_IS_WINDOW (window));
2068
2069   g_warning ("gdk_window_set_override_redirect not implemented");
2070 }
2071
2072 void          
2073 gdk_window_set_icon_list (GdkWindow *window,
2074                           GList     *pixbufs)
2075 {
2076   g_return_if_fail (GDK_IS_WINDOW (window));
2077
2078   if (GDK_WINDOW_DESTROYED (window))
2079     return;
2080
2081   /* We could convert it to a hIcon and DrawIcon () it when getting
2082    * a WM_PAINT with IsIconic, but is it worth it ? Same probably
2083    * goes for gdk_window_set_icon (). Patches accepted :-)  --hb
2084    * Or do we only need to deliver the Icon on WM_GETICON ?
2085    */
2086 }
2087
2088 void          
2089 gdk_window_set_icon (GdkWindow *window, 
2090                      GdkWindow *icon_window,
2091                      GdkPixmap *pixmap,
2092                      GdkBitmap *mask)
2093 {
2094   g_return_if_fail (window != NULL);
2095   g_return_if_fail (GDK_IS_WINDOW (window));
2096
2097   if (GDK_WINDOW_DESTROYED (window))
2098     return;
2099   
2100   /* Nothing to do, really. As we share window classes between windows
2101    * we can't have window-specific icons, sorry. Don't print any warning
2102    * either.
2103    */
2104 }
2105
2106 void
2107 gdk_window_set_icon_name (GdkWindow   *window, 
2108                           const gchar *name)
2109 {
2110   g_return_if_fail (window != NULL);
2111   g_return_if_fail (GDK_IS_WINDOW (window));
2112
2113   if (GDK_WINDOW_DESTROYED (window))
2114     return;
2115   
2116   if (!SetWindowText (GDK_WINDOW_HWND (window), name))
2117     WIN32_API_FAILED ("SetWindowText");
2118 }
2119
2120 void          
2121 gdk_window_set_group (GdkWindow *window, 
2122                       GdkWindow *leader)
2123 {
2124   g_return_if_fail (window != NULL);
2125   g_return_if_fail (GDK_IS_WINDOW (window));
2126   g_return_if_fail (leader != NULL);
2127   g_return_if_fail (GDK_IS_WINDOW (leader));
2128
2129   if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
2130     return;
2131   
2132   g_warning ("gdk_window_set_group not implemented");
2133 }
2134
2135 void
2136 gdk_window_set_decorations (GdkWindow      *window,
2137                             GdkWMDecoration decorations)
2138 {
2139   LONG style;
2140
2141   g_return_if_fail (window != NULL);
2142   g_return_if_fail (GDK_IS_WINDOW (window));
2143   
2144   GDK_NOTE (MISC, g_print ("gdk_window_set_decorations: %p %s%s%s%s%s%s%s\n",
2145                            GDK_WINDOW_HWND (window),
2146                            (decorations & GDK_DECOR_ALL ? "ALL " : ""),
2147                            (decorations & GDK_DECOR_BORDER ? "BORDER " : ""),
2148                            (decorations & GDK_DECOR_RESIZEH ? "RESIZEH " : ""),
2149                            (decorations & GDK_DECOR_TITLE ? "TITLE " : ""),
2150                            (decorations & GDK_DECOR_MENU ? "MENU " : ""),
2151                            (decorations & GDK_DECOR_MINIMIZE ? "MINIMIZE " : ""),
2152                            (decorations & GDK_DECOR_MAXIMIZE ? "MAXIMIZE " : "")));
2153
2154   style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2155
2156   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2157             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE);
2158
2159   if (decorations & GDK_DECOR_ALL)
2160     style |= (WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2161   if (decorations & GDK_DECOR_BORDER)
2162     style |= (WS_BORDER);
2163   if (decorations & GDK_DECOR_RESIZEH)
2164     style |= (WS_THICKFRAME);
2165   if (decorations & GDK_DECOR_TITLE)
2166     style |= (WS_CAPTION);
2167   if (decorations & GDK_DECOR_MENU)
2168     style |= (WS_SYSMENU);
2169   if (decorations & GDK_DECOR_MINIMIZE)
2170     style |= (WS_MINIMIZEBOX);
2171   if (decorations & GDK_DECOR_MAXIMIZE)
2172     style |= (WS_MAXIMIZEBOX);
2173   
2174   SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
2175   SetWindowPos (GDK_WINDOW_HWND (window), NULL, 0, 0, 0, 0,
2176                 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
2177                 SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
2178 }
2179
2180 void
2181 gdk_window_set_functions (GdkWindow    *window,
2182                           GdkWMFunction functions)
2183 {
2184   LONG style;
2185
2186   g_return_if_fail (window != NULL);
2187   g_return_if_fail (GDK_IS_WINDOW (window));
2188   
2189   GDK_NOTE (MISC, g_print ("gdk_window_set_functions: %p %s%s%s%s%s%s\n",
2190                            GDK_WINDOW_HWND (window),
2191                            (functions & GDK_FUNC_ALL ? "ALL " : ""),
2192                            (functions & GDK_FUNC_RESIZE ? "RESIZE " : ""),
2193                            (functions & GDK_FUNC_MOVE ? "MOVE " : ""),
2194                            (functions & GDK_FUNC_MINIMIZE ? "MINIMIZE " : ""),
2195                            (functions & GDK_FUNC_MAXIMIZE ? "MAXIMIZE " : ""),
2196                            (functions & GDK_FUNC_CLOSE ? "CLOSE " : "")));
2197
2198   style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2199
2200   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2201             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE|WS_CAPTION|WS_BORDER
2202             |WS_SYSMENU);
2203
2204   if (functions & GDK_FUNC_ALL)
2205     style |= (WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2206   if (functions & GDK_FUNC_RESIZE)
2207     style |= (WS_THICKFRAME);
2208   if (functions & GDK_FUNC_MOVE)
2209     style |= (WS_THICKFRAME);
2210   if (functions & GDK_FUNC_MINIMIZE)
2211     style |= (WS_MINIMIZEBOX);
2212   if (functions & GDK_FUNC_MAXIMIZE)
2213     style |= (WS_MAXIMIZEBOX);
2214   
2215   SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
2216   SetWindowPos (GDK_WINDOW_HWND (window), NULL, 0, 0, 0, 0,
2217                 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
2218                 SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
2219 }
2220
2221 static void
2222 QueryTree (HWND   hwnd,
2223            HWND **children,
2224            gint  *nchildren)
2225 {
2226   guint i, n;
2227   HWND child;
2228
2229   n = 0;
2230   do {
2231     if (n == 0)
2232       child = GetWindow (hwnd, GW_CHILD);
2233     else
2234       child = GetWindow (child, GW_HWNDNEXT);
2235     if (child != NULL)
2236       n++;
2237   } while (child != NULL);
2238
2239   if (n > 0)
2240     {
2241       *children = g_new (HWND, n);
2242       for (i = 0; i < n; i++)
2243         {
2244           if (i == 0)
2245             child = GetWindow (hwnd, GW_CHILD);
2246           else
2247             child = GetWindow (child, GW_HWNDNEXT);
2248           *children[i] = child;
2249         }
2250     }
2251 }
2252
2253 static void
2254 gdk_propagate_shapes (HANDLE   win,
2255                       gboolean merge)
2256 {
2257    RECT emptyRect;
2258    HRGN region, childRegion;
2259    HWND *list = NULL;
2260    gint i, num;
2261
2262    SetRectEmpty (&emptyRect);
2263    region = CreateRectRgnIndirect (&emptyRect);
2264    if (merge)
2265      GetWindowRgn (win, region);
2266    
2267    QueryTree (win, &list, &num);
2268    if (list != NULL)
2269      {
2270        WINDOWPLACEMENT placement;
2271
2272        placement.length = sizeof (WINDOWPLACEMENT);
2273        /* go through all child windows and combine regions */
2274        for (i = 0; i < num; i++)
2275          {
2276            GetWindowPlacement (list[i], &placement);
2277            if (placement.showCmd == SW_SHOWNORMAL)
2278              {
2279                childRegion = CreateRectRgnIndirect (&emptyRect);
2280                GetWindowRgn (list[i], childRegion);
2281                CombineRgn (region, region, childRegion, RGN_OR);
2282                DeleteObject (childRegion);
2283              }
2284           }
2285        SetWindowRgn (win, region, TRUE);
2286        g_free (list);
2287      }
2288    else
2289      DeleteObject (region);
2290 }
2291
2292 void
2293 gdk_window_set_child_shapes (GdkWindow *window)
2294 {
2295   g_return_if_fail (window != NULL);
2296   g_return_if_fail (GDK_IS_WINDOW (window));
2297    
2298   if (GDK_WINDOW_DESTROYED (window))
2299     return;
2300
2301   gdk_propagate_shapes (GDK_WINDOW_HWND (window), FALSE);
2302 }
2303
2304 void
2305 gdk_window_merge_child_shapes (GdkWindow *window)
2306 {
2307   g_return_if_fail (window != NULL);
2308   g_return_if_fail (GDK_IS_WINDOW (window));
2309   
2310   if (GDK_WINDOW_DESTROYED (window))
2311     return;
2312
2313   gdk_propagate_shapes (GDK_WINDOW_HWND (window), TRUE);
2314 }
2315
2316 gboolean 
2317 gdk_window_set_static_gravities (GdkWindow *window,
2318                                  gboolean   use_static)
2319 {
2320   GdkWindowObject *private = (GdkWindowObject *)window;
2321   
2322   g_return_val_if_fail (window != NULL, FALSE);
2323   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2324
2325   if (!use_static == !private->guffaw_gravity)
2326     return TRUE;
2327   
2328   if (use_static)
2329     return FALSE;
2330   
2331   private->guffaw_gravity = use_static;
2332   
2333   return TRUE;
2334 }
2335
2336 /*
2337  * Setting window states
2338  */
2339 void
2340 gdk_window_iconify (GdkWindow *window)
2341 {
2342   g_return_if_fail (window != NULL);
2343   g_return_if_fail (GDK_IS_WINDOW (window));
2344
2345   if (GDK_WINDOW_DESTROYED (window))
2346     return;
2347
2348   if (GDK_WINDOW_IS_MAPPED (window))
2349     {
2350       ShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
2351     }
2352   else
2353     {
2354       /* Flip our client side flag, the real work happens on map. */
2355       gdk_synthesize_window_state (window,
2356                                    0,
2357                                    GDK_WINDOW_STATE_ICONIFIED);
2358     }
2359 }
2360
2361 void
2362 gdk_window_deiconify (GdkWindow *window)
2363 {
2364   g_return_if_fail (window != NULL);
2365   g_return_if_fail (GDK_IS_WINDOW (window));
2366
2367   if (GDK_WINDOW_DESTROYED (window))
2368     return;
2369
2370   if (GDK_WINDOW_IS_MAPPED (window))
2371     {  
2372       gdk_window_show (window);
2373     }
2374   else
2375     {
2376       /* Flip our client side flag, the real work happens on map. */
2377       gdk_synthesize_window_state (window,
2378                                    GDK_WINDOW_STATE_ICONIFIED,
2379                                    0);
2380     }
2381 }
2382
2383 void
2384 gdk_window_stick (GdkWindow *window)
2385 {
2386   g_return_if_fail (GDK_IS_WINDOW (window));
2387
2388   if (GDK_WINDOW_DESTROYED (window))
2389     return;
2390
2391   if (GDK_WINDOW_IS_MAPPED (window))
2392     {
2393       /* "stick" means stick to all desktops _and_ do not scroll with the
2394        * viewport. i.e. glue to the monitor glass in all cases.
2395        */
2396       g_warning ("gdk_window_stick (%p) ???", GDK_WINDOW_HWND (window));
2397     }
2398   else
2399     {
2400       /* Flip our client side flag, the real work happens on map. */
2401       gdk_synthesize_window_state (window,
2402                                    0,
2403                                    GDK_WINDOW_STATE_STICKY);
2404     }
2405 }
2406
2407 void
2408 gdk_window_unstick (GdkWindow *window)
2409 {
2410   g_return_if_fail (GDK_IS_WINDOW (window));
2411
2412   if (GDK_WINDOW_DESTROYED (window))
2413     return;
2414
2415   if (GDK_WINDOW_IS_MAPPED (window))
2416     {
2417       g_warning ("gdk_window_unstick (%p) ???", GDK_WINDOW_HWND (window));
2418     }
2419   else
2420     {
2421       /* Flip our client side flag, the real work happens on map. */
2422       gdk_synthesize_window_state (window,
2423                                    GDK_WINDOW_STATE_STICKY,
2424                                    0);
2425     }
2426 }
2427
2428 void
2429 gdk_window_maximize (GdkWindow *window)
2430 {
2431   g_return_if_fail (GDK_IS_WINDOW (window));
2432
2433   if (GDK_WINDOW_DESTROYED (window))
2434     return;
2435
2436   if (GDK_WINDOW_IS_MAPPED (window))
2437     ShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
2438   else
2439     gdk_synthesize_window_state (window,
2440                                  0,
2441                                  GDK_WINDOW_STATE_MAXIMIZED);
2442 }
2443
2444 void
2445 gdk_window_unmaximize (GdkWindow *window)
2446 {
2447   g_return_if_fail (GDK_IS_WINDOW (window));
2448
2449   if (GDK_WINDOW_DESTROYED (window))
2450     return;
2451
2452   if (GDK_WINDOW_IS_MAPPED (window))
2453     ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
2454   else
2455     gdk_synthesize_window_state (window,
2456                                  GDK_WINDOW_STATE_MAXIMIZED,
2457                                  0);
2458 }
2459
2460 void
2461 gdk_window_fullscreen (GdkWindow *window)
2462 {
2463   g_return_if_fail (GDK_IS_WINDOW (window));
2464
2465   g_warning ("gdk_window_fullscreen() not implemented.\n");
2466 }
2467
2468 void
2469 gdk_window_unfullscreen (GdkWindow *window)
2470 {
2471   g_return_if_fail (GDK_IS_WINDOW (window));
2472 }
2473
2474 void
2475 gdk_window_focus (GdkWindow *window,
2476                   guint32    timestamp)
2477 {
2478   g_return_if_fail (GDK_IS_WINDOW (window));
2479
2480   if (GDK_WINDOW_DESTROYED (window))
2481     return;
2482   
2483   GDK_NOTE (MISC, g_print ("gdk_window_focus: %p\n", GDK_WINDOW_HWND (window)));
2484
2485   ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
2486   SetFocus (GDK_WINDOW_HWND (window));
2487 }
2488
2489 void
2490 gdk_window_set_modal_hint (GdkWindow *window,
2491                            gboolean   modal)
2492 {
2493   GdkWindowObject *private;
2494
2495   g_return_if_fail (window != NULL);
2496   g_return_if_fail (GDK_IS_WINDOW (window));
2497   
2498   if (GDK_WINDOW_DESTROYED (window))
2499     return;
2500
2501   private = (GdkWindowObject*) window;
2502
2503   private->modal_hint = modal;
2504
2505   if (GDK_WINDOW_IS_MAPPED (window))
2506     if (!SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOPMOST,
2507                        0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE))
2508       WIN32_API_FAILED ("SetWindowPos");
2509 }
2510
2511 void
2512 gdk_window_set_skip_taskbar_hint (GdkWindow *window,
2513                                   gboolean   skips_taskbar)
2514 {
2515   g_return_if_fail (GDK_IS_WINDOW (window));
2516 }
2517
2518 void
2519 gdk_window_set_skip_pager_hint (GdkWindow *window,
2520                                 gboolean   skips_pager)
2521 {
2522   g_return_if_fail (GDK_IS_WINDOW (window));
2523 }
2524
2525 void
2526 gdk_window_set_type_hint (GdkWindow        *window,
2527                           GdkWindowTypeHint hint)
2528 {
2529   g_return_if_fail (window != NULL);
2530   g_return_if_fail (GDK_IS_WINDOW (window));
2531   
2532   if (GDK_WINDOW_DESTROYED (window))
2533     return;
2534
2535   switch (hint)
2536     {
2537     case GDK_WINDOW_TYPE_HINT_DIALOG:
2538       break;
2539     case GDK_WINDOW_TYPE_HINT_MENU:
2540       break;
2541     case GDK_WINDOW_TYPE_HINT_TOOLBAR:
2542       break;
2543     default:
2544       g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2545       /* Fall thru */
2546     case GDK_WINDOW_TYPE_HINT_NORMAL:
2547       break;
2548     }
2549   /*
2550    * XXX ???
2551    */
2552   GDK_NOTE (MISC, g_print ("gdk_window_set_type_hint: %p\n",
2553                            GDK_WINDOW_HWND (window)));
2554 }
2555
2556 void
2557 gdk_window_shape_combine_region (GdkWindow *window,
2558                                  GdkRegion *shape_region,
2559                                  gint       offset_x,
2560                                  gint       offset_y)
2561 {
2562   g_return_if_fail (GDK_IS_WINDOW (window));
2563
2564   if (GDK_WINDOW_DESTROYED (window))
2565     return;
2566
2567   /* XXX: even on X implemented conditional ... */  
2568 }
2569
2570 void
2571 gdk_window_begin_resize_drag (GdkWindow     *window,
2572                               GdkWindowEdge  edge,
2573                               gint           button,
2574                               gint           root_x,
2575                               gint           root_y,
2576                               guint32        timestamp)
2577 {
2578   g_return_if_fail (GDK_IS_WINDOW (window));
2579   
2580   if (GDK_WINDOW_DESTROYED (window))
2581     return;
2582
2583   /* XXX: isn't all this default on win32 ... */  
2584 }
2585
2586 void
2587 gdk_window_begin_move_drag (GdkWindow *window,
2588                             gint       button,
2589                             gint       root_x,
2590                             gint       root_y,
2591                             guint32    timestamp)
2592 {
2593   g_return_if_fail (GDK_IS_WINDOW (window));
2594   
2595   if (GDK_WINDOW_DESTROYED (window))
2596     return;
2597
2598   /* XXX: isn't all this default on win32 ... */  
2599 }
2600
2601 GdkWindow *
2602 gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
2603 {
2604   g_return_val_if_fail (display == gdk_display_get_default(), NULL);
2605
2606   return gdk_window_lookup (anid);
2607 }