]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow-win32.c
updated for win32 msvc build (forgot this before)
[~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-1999 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 "gdkinternals.h"
35 #include "gdkprivate-win32.h"
36 #include "gdkinput-win32.h"
37
38 static gboolean gdk_window_gravity_works (void);
39 static void     gdk_window_set_static_win_gravity (GdkWindow *window, 
40                                                    gboolean   on);
41
42 static GdkColormap* gdk_window_impl_win32_get_colormap (GdkDrawable *drawable);
43 static void         gdk_window_impl_win32_set_colormap (GdkDrawable *drawable,
44                                                         GdkColormap *cmap);
45 static void         gdk_window_impl_win32_get_size     (GdkDrawable *drawable,
46                                                         gint *width,
47                                                         gint *height);
48 static GdkRegion*  gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable);
49 static void gdk_window_impl_win32_init       (GdkWindowImplWin32      *window);
50 static void gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass);
51 static void gdk_window_impl_win32_finalize   (GObject                 *object);
52
53 static gpointer parent_class = NULL;
54
55 GType
56 gdk_window_impl_win32_get_type (void)
57 {
58   static GType object_type = 0;
59
60   if (!object_type)
61     {
62       static const GTypeInfo object_info =
63       {
64         sizeof (GdkWindowImplWin32Class),
65         (GBaseInitFunc) NULL,
66         (GBaseFinalizeFunc) NULL,
67         (GClassInitFunc) gdk_window_impl_win32_class_init,
68         NULL,           /* class_finalize */
69         NULL,           /* class_data */
70         sizeof (GdkWindowImplWin32),
71         0,              /* n_preallocs */
72         (GInstanceInitFunc) gdk_window_impl_win32_init,
73       };
74       
75       object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_WIN32,
76                                             "GdkWindowImplWin32",
77                                             &object_info, 0);
78     }
79   
80   return object_type;
81 }
82
83 GType
84 _gdk_window_impl_get_type (void)
85 {
86   return gdk_window_impl_win32_get_type ();
87 }
88
89 static void
90 gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
91 {
92   impl->width = 1;
93   impl->height = 1;
94
95   impl->event_mask = 0;
96   impl->hcursor = NULL;
97   impl->hint_flags = 0;
98   impl->extension_events_selected = FALSE;
99   impl->input_locale = GetKeyboardLayout (0);
100   TranslateCharsetInfo ((DWORD FAR *) GetACP (), &impl->charset_info,
101                         TCI_SRCCODEPAGE);
102 }
103
104 static void
105 gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
106 {
107   GObjectClass *object_class = G_OBJECT_CLASS (klass);
108   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
109   
110   parent_class = g_type_class_peek_parent (klass);
111
112   object_class->finalize = gdk_window_impl_win32_finalize;
113
114   drawable_class->set_colormap = gdk_window_impl_win32_set_colormap;
115   drawable_class->get_colormap = gdk_window_impl_win32_get_colormap;
116   drawable_class->get_size = gdk_window_impl_win32_get_size;
117
118   /* Visible and clip regions are the same */
119   drawable_class->get_clip_region = gdk_window_impl_win32_get_visible_region;
120   drawable_class->get_visible_region = gdk_window_impl_win32_get_visible_region;
121 }
122
123 static void
124 gdk_window_impl_win32_finalize (GObject *object)
125 {
126   GdkWindowObject *wrapper;
127   GdkDrawableImplWin32 *draw_impl;
128   GdkWindowImplWin32 *window_impl;
129   
130   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (object));
131
132   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (object);
133   window_impl = GDK_WINDOW_IMPL_WIN32 (object);
134   
135   wrapper = (GdkWindowObject*) draw_impl->wrapper;
136
137   if (!GDK_WINDOW_DESTROYED (wrapper))
138     {
139       gdk_win32_handle_table_remove (draw_impl->handle);
140     }
141
142   if (window_impl->hcursor != NULL)
143     {
144       if (!DestroyCursor (window_impl->hcursor))
145         WIN32_GDI_FAILED("DestroyCursor");
146       window_impl->hcursor = NULL;
147     }
148
149   G_OBJECT_CLASS (parent_class)->finalize (object);
150 }
151
152 static GdkColormap*
153 gdk_window_impl_win32_get_colormap (GdkDrawable *drawable)
154 {
155   GdkDrawableImplWin32 *drawable_impl;
156   GdkWindowImplWin32 *window_impl;
157   
158   g_return_val_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable), NULL);
159
160   drawable_impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
161   window_impl = GDK_WINDOW_IMPL_WIN32 (drawable);
162
163   if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only && 
164       drawable_impl->colormap == NULL)
165     {
166       drawable_impl->colormap = gdk_colormap_get_system ();
167       gdk_colormap_ref (drawable_impl->colormap);
168     }
169   
170   return drawable_impl->colormap;
171 }
172
173 static void
174 gdk_window_impl_win32_set_colormap (GdkDrawable *drawable,
175                                     GdkColormap *cmap)
176 {
177   GdkWindowImplWin32 *impl;
178   GdkDrawableImplWin32 *draw_impl;
179   
180   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable));
181   g_return_if_fail (gdk_colormap_get_visual (cmap) != gdk_drawable_get_visual (drawable));
182
183   impl = GDK_WINDOW_IMPL_WIN32 (drawable);
184   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
185
186   GDK_DRAWABLE_GET_CLASS (draw_impl)->set_colormap (drawable, cmap);
187   
188   /* XXX */
189   g_print("gdk_window_impl_win32_set_colormap: XXX\n");
190 }
191
192 static void
193 gdk_window_impl_win32_get_size (GdkDrawable *drawable,
194                                 gint        *width,
195                                 gint        *height)
196 {
197   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable));
198
199   if (width)
200     *width = GDK_WINDOW_IMPL_WIN32 (drawable)->width;
201   if (height)
202     *height = GDK_WINDOW_IMPL_WIN32 (drawable)->height;
203 }
204
205 static GdkRegion*
206 gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable)
207 {
208   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (drawable);
209   GdkRectangle result_rect;
210
211   result_rect.x = 0;
212   result_rect.y = 0;
213   result_rect.width = impl->width;
214   result_rect.height = impl->height;
215
216   gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
217
218   return gdk_region_rectangle (&result_rect);
219 }
220
221 void
222 _gdk_windowing_window_init (void)
223 {
224   GdkWindowObject *private;
225   GdkWindowImplWin32 *impl;
226   GdkDrawableImplWin32 *draw_impl;
227   RECT rect;
228   guint width;
229   guint height;
230
231   g_assert (gdk_parent_root == NULL);
232   
233   SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
234   width  = rect.right - rect.left;
235   height = rect.bottom - rect.top;
236
237   gdk_parent_root = g_object_new (GDK_TYPE_WINDOW, NULL);
238   private = (GdkWindowObject *)gdk_parent_root;
239   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
240   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
241   
242   draw_impl->handle = gdk_root_window;
243   draw_impl->wrapper = GDK_DRAWABLE (private);
244   
245   private->window_type = GDK_WINDOW_ROOT;
246   private->depth = gdk_visual_get_system ()->depth;
247   impl->width = width;
248   impl->height = height;
249
250   gdk_win32_handle_table_insert (&gdk_root_window, gdk_parent_root);
251 }
252
253 /* The Win API function AdjustWindowRect may return negative values
254  * resulting in obscured title bars. This helper function is coreccting it.
255  */
256 BOOL
257 SafeAdjustWindowRectEx (RECT* lpRect,
258                         DWORD dwStyle, 
259                         BOOL  bMenu, 
260                         DWORD dwExStyle)
261 {
262   if (!AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle))
263     {
264       WIN32_API_FAILED ("AdjustWindowRectEx");
265       return FALSE;
266     }
267   if (lpRect->left < 0)
268     {
269       lpRect->right -= lpRect->left;
270       lpRect->left = 0;
271     }
272   if (lpRect->top < 0)
273     {
274       lpRect->bottom -= lpRect->top;
275       lpRect->top = 0;
276     }
277   return TRUE;
278 }
279
280 /* RegisterGdkClass
281  *   is a wrapper function for RegisterWindowClassEx.
282  *   It creates at least one unique class for every 
283  *   GdkWindowType. If support for single window-specific icons
284  *   is ever needed (e.g Dialog specific), every such window should
285  *   get its own class
286  */
287 ATOM
288 RegisterGdkClass (GdkWindowType wtype)
289 {
290   static ATOM klassTOPLEVEL = 0;
291   static ATOM klassDIALOG   = 0;
292   static ATOM klassCHILD    = 0;
293   static ATOM klassTEMP     = 0;
294   static HICON hAppIcon = NULL;
295   static WNDCLASSEX wcl; 
296   ATOM klass = 0;
297
298   wcl.cbSize = sizeof(WNDCLASSEX);     
299   wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
300                   * on WM_SIZE and WM_MOVE. Flicker, Performance!
301                   */
302   wcl.lpfnWndProc = gdk_window_procedure;
303   wcl.cbClsExtra = 0;
304   wcl.cbWndExtra = 0;
305   wcl.hInstance = gdk_app_hmodule;
306   wcl.hIcon = 0;
307   /* initialize once! */
308   if (0 == hAppIcon)
309     {
310       gchar sLoc [_MAX_PATH+1];
311
312       if (0 != GetModuleFileName (gdk_app_hmodule, sLoc, _MAX_PATH))
313         {
314           hAppIcon = ExtractIcon (gdk_app_hmodule, sLoc, 0);
315           if (0 == hAppIcon)
316             {
317               char *gdklibname = g_strdup_printf ("gdk-%s.dll", GDK_VERSION);
318
319               hAppIcon = ExtractIcon (gdk_app_hmodule, gdklibname, 0);
320               g_free (gdklibname);
321             }
322           
323           if (0 == hAppIcon) 
324             hAppIcon = LoadIcon (NULL, IDI_APPLICATION);
325         }
326     }
327
328   wcl.lpszMenuName = NULL;
329   wcl.hIconSm = 0;
330
331   /* initialize once per class */
332 #define ONCE_PER_CLASS() \
333   wcl.hIcon = CopyIcon (hAppIcon); \
334   wcl.hIconSm = CopyIcon (hAppIcon); \
335   wcl.hbrBackground = CreateSolidBrush (RGB (0,0,0)); \
336   wcl.hCursor = LoadCursor (NULL, IDC_ARROW); 
337   
338   switch (wtype)
339   {
340   case GDK_WINDOW_TOPLEVEL:
341     if (0 == klassTOPLEVEL)
342       {
343         wcl.lpszClassName = "gdkWindowToplevel";
344         
345         ONCE_PER_CLASS();
346         klassTOPLEVEL = RegisterClassEx (&wcl);
347       }
348     klass = klassTOPLEVEL;
349     break;
350
351     case GDK_WINDOW_CHILD:
352       if (0 == klassCHILD)
353         {
354           wcl.lpszClassName = "gdkWindowChild";
355           
356           wcl.style |= CS_PARENTDC; /* MSDN: ... enhances system performance. */
357           ONCE_PER_CLASS();
358           klassCHILD = RegisterClassEx (&wcl);
359         }
360       klass = klassCHILD;
361       break;
362
363   case GDK_WINDOW_DIALOG:
364     if (0 == klassDIALOG)
365       {
366         wcl.lpszClassName = "gdkWindowDialog";
367         wcl.style |= CS_SAVEBITS;
368         ONCE_PER_CLASS();
369         klassDIALOG = RegisterClassEx (&wcl);
370       }
371     klass = klassDIALOG;
372     break;
373
374   case GDK_WINDOW_TEMP:
375     if (0 == klassTEMP)
376       {
377         wcl.lpszClassName = "gdkWindowTemp";
378         wcl.style |= CS_SAVEBITS;
379         ONCE_PER_CLASS();
380         klassTEMP = RegisterClassEx (&wcl);
381       }
382     klass = klassTEMP;
383     break;
384
385   default:
386     g_assert_not_reached ();
387     break;
388   }
389
390   if (klass == 0)
391     {
392       WIN32_API_FAILED ("RegisterClassEx");
393       g_error ("That is a fatal error");
394     }
395   return klass;
396 }
397
398 GdkWindow*
399 gdk_window_new (GdkWindow     *parent,
400                 GdkWindowAttr *attributes,
401                 gint           attributes_mask)
402 {
403   GdkWindow *window;
404   GdkWindowObject *private;
405   GdkWindowObject *parent_private;
406   GdkWindowImplWin32 *impl;
407   GdkDrawableImplWin32 *draw_impl;
408
409   GdkVisual *visual;
410
411   HANDLE hparent;
412   ATOM klass = 0;
413   DWORD dwStyle, dwExStyle;
414   RECT rect;
415   Visual *xvisual;
416
417   int width, height;
418   int x, y;
419   char *title;
420   char *mbtitle;
421
422   g_return_val_if_fail (attributes != NULL, NULL);
423
424   if (!parent)
425     parent = gdk_parent_root;
426
427   g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
428   
429   GDK_NOTE (MISC,
430             g_print ("gdk_window_new: %s\n",
431                      (attributes->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
432                       (attributes->window_type == GDK_WINDOW_CHILD ? "CHILD" :
433                        (attributes->window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
434                         (attributes->window_type == GDK_WINDOW_TEMP ? "TEMP" :
435                          "???"))))));
436
437   parent_private = (GdkWindowObject*) parent;
438   if (GDK_WINDOW_DESTROYED (parent))
439     return NULL;
440   
441   hparent = GDK_WINDOW_HWND (parent);
442
443   window = g_object_new (GDK_TYPE_WINDOW, NULL);
444   private = (GdkWindowObject *)window;
445   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
446   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
447   draw_impl->wrapper = GDK_DRAWABLE (window);
448
449   private->parent = (GdkWindowObject *)parent;
450
451   if (attributes_mask & GDK_WA_X)
452     x = attributes->x;
453   else
454     x = CW_USEDEFAULT;
455   
456   if (attributes_mask & GDK_WA_Y)
457     y = attributes->y;
458   else if (attributes_mask & GDK_WA_X)
459     y = 100;                    /* ??? We must put it somewhere... */
460   else
461     y = 0;                      /* x is CW_USEDEFAULT, y doesn't matter then */
462   
463   private->x = x;
464   private->y = y;
465   impl->width = (attributes->width > 1) ? (attributes->width) : (1);
466   impl->height = (attributes->height > 1) ? (attributes->height) : (1);
467   impl->extension_events_selected = FALSE;
468   private->window_type = attributes->window_type;
469
470   _gdk_window_init_position (GDK_WINDOW (private));
471   if (impl->position_info.big)
472     private->guffaw_gravity = TRUE;
473
474   if (attributes_mask & GDK_WA_VISUAL)
475     visual = attributes->visual;
476   else
477     visual = gdk_visual_get_system ();
478   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
479
480   if (attributes_mask & GDK_WA_TITLE)
481     title = attributes->title;
482   else
483     title = g_get_prgname ();
484   if (!title || !*title)
485     title = "GDK client window";
486
487   impl->event_mask = GDK_STRUCTURE_MASK | attributes->event_mask;
488       
489   if (parent_private && parent_private->guffaw_gravity)
490     {
491       /* XXX ??? */
492     }
493
494   if (attributes->wclass == GDK_INPUT_OUTPUT)
495     {
496       dwExStyle = 0;
497
498       private->input_only = FALSE;
499       private->depth = visual->depth;
500       
501       if (attributes_mask & GDK_WA_COLORMAP)
502         {
503           draw_impl->colormap = attributes->colormap;
504           gdk_colormap_ref (attributes->colormap);
505         }
506       else
507         {
508           if ((((GdkVisualPrivate*)gdk_visual_get_system ())->xvisual) == xvisual)
509             {
510               draw_impl->colormap = gdk_colormap_get_system ();
511               gdk_colormap_ref (draw_impl->colormap);
512               GDK_NOTE (MISC, g_print ("...using system colormap %p\n",
513                                        draw_impl->colormap));
514             }
515           else
516             {
517               draw_impl->colormap = gdk_colormap_new (visual, FALSE);
518               GDK_NOTE (MISC, g_print ("...using new colormap %p\n",
519                                        draw_impl->colormap));
520             }
521         }
522     }
523   else
524     {
525       dwExStyle = WS_EX_TRANSPARENT;
526       private->depth = 0;
527       private->input_only = TRUE;
528       draw_impl->colormap = NULL;
529       GDK_NOTE (MISC, g_print ("...GDK_INPUT_ONLY, NULL colormap\n"));
530     }
531
532   if (parent_private)
533     parent_private->children = g_list_prepend (parent_private->children, window);
534
535   switch (private->window_type)
536     {
537     case GDK_WINDOW_TOPLEVEL:
538       dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
539       hparent = gdk_root_window;
540       break;
541
542     case GDK_WINDOW_CHILD:
543       dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
544       break;
545
546     case GDK_WINDOW_DIALOG:
547       dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
548 #if 0
549       dwExStyle |= WS_EX_TOPMOST; /* //HB: want this? */
550 #endif
551       hparent = gdk_root_window;
552       break;
553
554     case GDK_WINDOW_TEMP:
555       dwStyle = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
556       dwExStyle |= WS_EX_TOOLWINDOW;
557       break;
558
559     case GDK_WINDOW_ROOT:
560       g_error ("cannot make windows of type GDK_WINDOW_ROOT");
561       break;
562     }
563
564   klass = RegisterGdkClass (private->window_type);
565
566   if (private->window_type != GDK_WINDOW_CHILD)
567     {
568       if (x == CW_USEDEFAULT)
569         {
570           rect.left = 100;
571           rect.top = 100;
572         }
573       else
574         {
575           rect.left = x;
576           rect.top = y;
577         }
578
579       rect.right = rect.left + impl->width;
580       rect.bottom = rect.top + impl->height;
581
582       SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
583
584       if (x != CW_USEDEFAULT)
585         {
586           x = rect.left;
587           y = rect.top;
588         }
589       width = rect.right - rect.left;
590       height = rect.bottom - rect.top;
591     }
592   else
593     {
594       width = impl->width;
595       height = impl->height;
596     }
597
598   mbtitle = g_locale_from_utf8 (title, -1, NULL, NULL, NULL);
599   
600 #ifdef WITHOUT_WM_CREATE
601   draw_impl->handle = CreateWindowEx (dwExStyle,
602                                       MAKEINTRESOURCE(klass),
603                                       mbtitle,
604                                       dwStyle,
605                                       x, y, 
606                                       width, height,
607                                       hparent,
608                                       NULL,
609                                       gdk_app_hmodule,
610                                       NULL);
611 #else
612   {
613   HWND hwndNew =
614     CreateWindowEx (dwExStyle,
615                     MAKEINTRESOURCE(klass),
616                     mbtitle,
617                     dwStyle,
618                     x, y, 
619                     width, height,
620                     hparent,
621                     NULL,
622                     gdk_app_hmodule,
623                     window);
624   if (GDK_WINDOW_HWND (window) != hwndNew)
625     {
626       g_warning("gdk_window_new: gdk_event_translate::WM_CREATE (%#x, %#x) HWND mismatch.",
627                 (guint) GDK_WINDOW_HWND (window),
628                 (guint) hwndNew);
629
630       /* HB: IHMO due to a race condition the handle was increased by
631        * one, which causes much trouble. Because I can't find the 
632        * real bug, try to workaround it ...
633        * To reproduce: compile with MSVC 5, DEBUG=1
634        */
635 # if 0
636       gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
637       GDK_WINDOW_HWND (window) = hwndNew;
638       gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
639 # else
640       /* the old behaviour, but with warning */
641       GDK_WINDOW_HWND (window) = hwndNew;
642 # endif
643
644     }
645   }
646   gdk_drawable_ref (window);
647   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
648 #endif
649
650   GDK_NOTE (MISC,
651             g_print ("... \"%s\" %dx%d@+%d+%d %#x = %#x\n"
652                      "... locale %#x codepage %d\n",
653                      mbtitle,
654                      width, height, (x == CW_USEDEFAULT ? -9999 : x), y, 
655                      (guint) hparent,
656                      (guint) GDK_WINDOW_HWND (window),
657                      (guint) impl->input_locale,
658                      (guint) impl->charset_info.ciACP));
659
660   g_free (mbtitle);
661
662   if (draw_impl->handle == NULL)
663     {
664       WIN32_API_FAILED ("CreateWindowEx");
665       g_object_unref ((GObject *) window);
666       return NULL;
667     }
668
669 #ifdef WITHOUT_WM_CREATE
670   gdk_drawable_ref (window);
671   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
672 #endif
673
674   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
675                                   (attributes->cursor) :
676                                   NULL));
677
678   return window;
679 }
680
681 GdkWindow *
682 gdk_window_foreign_new (GdkNativeWindow anid)
683 {
684   GdkWindow *window;
685   GdkWindowObject *private;
686   GdkWindowObject *parent_private;
687   GdkWindowImplWin32 *impl;
688   GdkDrawableImplWin32 *draw_impl;
689
690   HANDLE parent;
691   RECT rect;
692   POINT point;
693
694   window = g_object_new (GDK_TYPE_WINDOW, NULL);
695   private = (GdkWindowObject *)window;
696   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
697   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
698   draw_impl->wrapper = GDK_DRAWABLE (window);
699   parent = GetParent ((HWND)anid);
700   
701   private->parent = gdk_win32_handle_table_lookup ((GdkNativeWindow) parent);
702   
703   parent_private = (GdkWindowObject *)private->parent;
704   
705   if (parent_private)
706     parent_private->children = g_list_prepend (parent_private->children, window);
707
708   draw_impl->handle = (HWND) anid;
709   GetClientRect ((HWND) anid, &rect);
710   point.x = rect.left;
711   point.y = rect.right;
712   ClientToScreen ((HWND) anid, &point);
713   if (parent != gdk_root_window)
714     ScreenToClient (parent, &point);
715   private->x = point.x;
716   private->y = point.y;
717   impl->width = rect.right - rect.left;
718   impl->height = rect.bottom - rect.top;
719   private->window_type = GDK_WINDOW_FOREIGN;
720   private->destroyed = FALSE;
721   private->mapped = IsWindowVisible ((HWND) anid);
722   private->depth = gdk_visual_get_system ()->depth;
723
724   gdk_drawable_ref (window);
725   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
726
727   return window;
728 }
729
730 void
731 _gdk_windowing_window_destroy (GdkWindow *window,
732                                gboolean   recursing,
733                                gboolean   foreign_destroy)
734 {
735   GdkWindowObject *private = (GdkWindowObject *)window;
736
737   g_return_if_fail (GDK_IS_WINDOW (window));
738   
739   GDK_NOTE (MISC, g_print ("_gdk_windowing_window_destroy %#x\n",
740                            (guint) GDK_WINDOW_HWND (window)));
741
742   if (private->extension_events != 0)
743     gdk_input_window_destroy (window);
744
745   if (private->window_type == GDK_WINDOW_FOREIGN)
746     {
747       if (!foreign_destroy && (private->parent != NULL))
748         {
749           /* It's somebody else's window, but in our hierarchy,
750            * so reparent it to the root window, and then call
751            * DestroyWindow() on it.
752            */
753           gdk_window_hide (window);
754           gdk_window_reparent (window, NULL, 0, 0);
755           
756           /* Is this too drastic? Many (most?) applications
757            * quit if any window receives WM_QUIT I think.
758            * OTOH, I don't think foreign windows are much
759            * used, so the question is maybe academic.
760            */
761           PostMessage (GDK_WINDOW_HWND (window), WM_QUIT, 0, 0);
762         }
763     }
764   else if (!recursing && !foreign_destroy)
765     DestroyWindow (GDK_WINDOW_HWND (window));
766 }
767
768 /* This function is called when the window really gone.
769  */
770 void
771 gdk_window_destroy_notify (GdkWindow *window)
772 {
773   g_return_if_fail (window != NULL);
774   g_return_if_fail (GDK_IS_WINDOW (window));
775
776   GDK_NOTE (EVENTS,
777             g_print ("gdk_window_destroy_notify: %#x  %s\n",
778                      (guint) GDK_WINDOW_HWND (window),
779                      (GDK_WINDOW_DESTROYED (window) ? "(destroyed)" : "")));
780
781   if (!GDK_WINDOW_DESTROYED (window))
782     {
783       if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
784         g_warning ("window %#x unexpectedly destroyed",
785                    (guint) GDK_WINDOW_HWND (window));
786
787       _gdk_window_destroy (window, TRUE);
788     }
789   
790   gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
791   gdk_drawable_unref (window);
792 }
793
794 void
795 gdk_window_show (GdkWindow *window)
796 {
797   GdkWindowObject *private;
798   
799   g_return_if_fail (GDK_IS_WINDOW (window));
800   
801   private = (GdkWindowObject*) window;
802   if (!private->destroyed)
803     {
804       GDK_NOTE (MISC, g_print ("gdk_window_show: %#x\n",
805                                (guint) GDK_WINDOW_HWND (window)));
806
807       private->mapped = TRUE;
808       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
809         {
810           ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNOACTIVATE);
811           SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOPMOST, 0, 0, 0, 0,
812                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
813 #if 0
814           /* Don't put on toolbar */
815           ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
816 #endif
817         }
818       else
819         {
820           if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
821             {
822               SetWindowPos(GDK_WINDOW_HWND (window), HWND_TOP, 0, 0, 0, 0,
823                            SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE);
824             }
825           else
826             {
827               GdkWindow *parent = private->parent;
828
829               ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
830               ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
831               if (parent == gdk_parent_root)
832                 SetForegroundWindow (GDK_WINDOW_HWND (window));
833               BringWindowToTop (GDK_WINDOW_HWND (window));
834 #if 0
835               ShowOwnedPopups (GDK_WINDOW_HWND (window), TRUE);
836 #endif
837             }
838         }
839     }
840 }
841
842 void
843 gdk_window_hide (GdkWindow *window)
844 {
845   GdkWindowObject *private;
846   
847   g_return_if_fail (window != NULL);
848
849   private = (GdkWindowObject*) window;
850   if (!private->destroyed)
851     {
852       GDK_NOTE (MISC, g_print ("gdk_window_hide: %#x\n",
853                                (guint) GDK_WINDOW_HWND (window)));
854
855       private->mapped = FALSE;
856       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
857         ShowOwnedPopups (GDK_WINDOW_HWND (window), FALSE);
858
859       if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
860         {
861           SetWindowPos(GDK_WINDOW_HWND (window), HWND_BOTTOM, 0, 0, 0, 0,
862                        SWP_HIDEWINDOW | SWP_NOREDRAW | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
863         }
864       else
865         {
866           ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
867         }
868     }
869 }
870
871 void
872 gdk_window_withdraw (GdkWindow *window)
873 {
874   GdkWindowObject *private;
875   
876   g_return_if_fail (window != NULL);
877   
878   private = (GdkWindowObject*) window;
879   if (!private->destroyed)
880     {
881       GDK_NOTE (MISC, g_print ("gdk_window_withdraw: %#x\n",
882                                (guint) GDK_WINDOW_HWND (window)));
883
884       gdk_window_hide (window); /* ??? */
885     }
886 }
887
888 void
889 gdk_window_move (GdkWindow *window,
890                  gint       x,
891                  gint       y)
892 {
893   GdkWindowObject *private = (GdkWindowObject *)window;
894   GdkWindowImplWin32 *impl;
895
896   g_return_if_fail (window != NULL);
897   g_return_if_fail (GDK_IS_WINDOW (window));
898
899   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
900   
901   gdk_window_move_resize (window, x, y, impl->width, impl->height);
902 }
903
904 void
905 gdk_window_resize (GdkWindow *window,
906                    gint       width,
907                    gint       height)
908 {
909   GdkWindowObject *private = (GdkWindowObject*) window;
910   GdkWindowImplWin32 *impl;
911   int x, y;
912
913   g_return_if_fail (window != NULL);
914   g_return_if_fail (GDK_IS_WINDOW (window));
915
916   if (width < 1)
917     width = 1;
918   if (height < 1)
919     height = 1;
920
921   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
922   
923   if (!private->destroyed)
924     {
925       GDK_NOTE (MISC, g_print ("gdk_window_resize: %#x %dx%d\n",
926                                (guint) GDK_WINDOW_HWND (window),
927                                width, height));
928       
929       if (GDK_WINDOW_TYPE (private) != GDK_WINDOW_CHILD)
930         {
931           POINT pt;
932           RECT rect;
933           DWORD dwStyle;
934           DWORD dwExStyle;
935
936           pt.x = 0;
937           pt.y = 0; 
938           ClientToScreen (GDK_WINDOW_HWND (window), &pt);
939           rect.left = pt.x;
940           rect.top = pt.y;
941           rect.right = pt.x + width;
942           rect.bottom = pt.y + height;
943
944           dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
945           dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
946           if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
947             WIN32_API_FAILED ("AdjustWindowRectEx");
948
949           x = rect.left;
950           y = rect.top;
951           width = rect.right - rect.left;
952           height = rect.bottom - rect.top;
953         }
954       else
955         {
956           x = private->x;
957           y = private->y;
958           impl->width = width;
959           impl->height = height;
960         }
961
962       private->resize_count += 1;
963
964       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
965                                (guint) GDK_WINDOW_HWND (window),
966                                width, height, x, y));
967       if (!MoveWindow (GDK_WINDOW_HWND (window), x, y, width, height, TRUE))
968         WIN32_API_FAILED ("MoveWindow");
969     }
970 }
971
972 void
973 gdk_window_move_resize (GdkWindow *window,
974                         gint       x,
975                         gint       y,
976                         gint       width,
977                         gint       height)
978 {
979   GdkWindowObject *private = (GdkWindowObject*) window;
980   GdkWindowImplWin32 *impl;
981
982   g_return_if_fail (window != NULL);
983   g_return_if_fail (GDK_IS_WINDOW (window));
984
985   if (width < 1)
986     width = 1;
987   if (height < 1)
988     height = 1;
989   
990   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
991
992   if (!private->destroyed)
993     {
994       RECT rect;
995       DWORD dwStyle;
996       DWORD dwExStyle;
997
998       GDK_NOTE (MISC, g_print ("gdk_window_move_resize: %#x %dx%d@+%d+%d\n",
999                                (guint) GDK_WINDOW_HWND (window),
1000                                width, height, x, y));
1001       
1002       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
1003         _gdk_window_move_resize_child (window, x, y, width, height);
1004       else
1005         {
1006           rect.left = x;
1007           rect.top = y;
1008           rect.right = x + width;
1009           rect.bottom = y + height;
1010
1011           dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1012           dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1013           if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
1014             WIN32_API_FAILED ("AdjustWindowRectEx");
1015
1016           GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%ldx%ld@+%ld+%ld)\n",
1017                                    (guint) GDK_WINDOW_HWND (window),
1018                                    rect.right - rect.left, rect.bottom - rect.top,
1019                                    rect.left, rect.top));
1020           if (!MoveWindow (GDK_WINDOW_HWND (window),
1021                            rect.left, rect.top,
1022                            rect.right - rect.left, rect.bottom - rect.top,
1023                            TRUE))
1024             WIN32_API_FAILED ("MoveWindow");
1025         }
1026     }
1027 }
1028
1029 void
1030 gdk_window_reparent (GdkWindow *window,
1031                      GdkWindow *new_parent,
1032                      gint       x,
1033                      gint       y)
1034 {
1035   GdkWindowObject *window_private;
1036   GdkWindowObject *parent_private;
1037   GdkWindowObject *old_parent_private;
1038   GdkWindowImplWin32 *impl;
1039
1040   g_return_if_fail (window != NULL);
1041
1042   if (!new_parent)
1043     new_parent = gdk_parent_root;
1044
1045   window_private = (GdkWindowObject*) window;
1046   old_parent_private = (GdkWindowObject *) window_private->parent;
1047   parent_private = (GdkWindowObject*) new_parent;
1048   impl = GDK_WINDOW_IMPL_WIN32 (window_private->impl);
1049
1050   if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (new_parent))
1051     {
1052       GDK_NOTE (MISC, g_print ("gdk_window_reparent: %#x %#x\n",
1053                                (guint) GDK_WINDOW_HWND (window),
1054                                (guint) GDK_WINDOW_HWND (new_parent)));
1055       if (!SetParent (GDK_WINDOW_HWND (window),
1056                       GDK_WINDOW_HWND (new_parent)))
1057         WIN32_API_FAILED ("SetParent");
1058
1059       if (!MoveWindow (GDK_WINDOW_HWND (window),
1060                        x, y, impl->width, impl->height, TRUE))
1061         WIN32_API_FAILED ("MoveWindow");
1062     }
1063   
1064   window_private->parent = (GdkWindowObject *)new_parent;
1065
1066   if (old_parent_private)
1067     old_parent_private->children =
1068       g_list_remove (old_parent_private->children, window);
1069
1070   if ((old_parent_private &&
1071        (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
1072       (!old_parent_private && parent_private->guffaw_gravity))
1073     gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
1074   
1075   parent_private->children = g_list_prepend (parent_private->children, window);
1076 }
1077
1078 void
1079 _gdk_windowing_window_clear_area (GdkWindow *window,
1080                                   gint       x,
1081                                   gint       y,
1082                                   gint       width,
1083                                   gint       height)
1084 {
1085   GdkWindowImplWin32 *impl;
1086
1087   g_return_if_fail (window != NULL);
1088   g_return_if_fail (GDK_IS_WINDOW (window));
1089   
1090   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1091
1092   if (!GDK_WINDOW_DESTROYED (window))
1093     {
1094       HDC hdc;
1095
1096       if (width == 0)
1097         width = impl->width - x;
1098       if (height == 0)
1099         height = impl->height - y;
1100       GDK_NOTE (MISC, g_print ("_gdk_windowing_window_clear_area: "
1101                                "%#x %dx%d@+%d+%d\n",
1102                                (guint) GDK_WINDOW_HWND (window),
1103                                width, height, x, y));
1104       hdc = GetDC (GDK_WINDOW_HWND (window));
1105       IntersectClipRect (hdc, x, y, x + width + 1, y + height + 1);
1106       SendMessage (GDK_WINDOW_HWND (window), WM_ERASEBKGND, (WPARAM) hdc, 0);
1107       ReleaseDC (GDK_WINDOW_HWND (window), hdc);
1108     }
1109 }
1110
1111 void
1112 _gdk_windowing_window_clear_area_e (GdkWindow *window,
1113                                     gint       x,
1114                                     gint       y,
1115                                     gint       width,
1116                                     gint       height)
1117 {
1118   g_return_if_fail (window != NULL);
1119   g_return_if_fail (GDK_IS_WINDOW (window));
1120   
1121   if (!GDK_WINDOW_DESTROYED (window))
1122     {
1123       RECT rect;
1124
1125       GDK_NOTE (MISC, g_print ("_gdk_windowing_window_clear_area_e: "
1126                                "%#x %dx%d@+%d+%d\n",
1127                                (guint) GDK_WINDOW_HWND (window),
1128                                width, height, x, y));
1129
1130       rect.left = x;
1131       rect.right = x + width + 1;
1132       rect.top = y;
1133       rect.bottom = y + height + 1;
1134       if (!InvalidateRect (GDK_WINDOW_HWND (window), &rect, TRUE))
1135         WIN32_GDI_FAILED ("InvalidateRect");
1136       UpdateWindow (GDK_WINDOW_HWND (window));
1137     }
1138 }
1139
1140 void
1141 gdk_window_raise (GdkWindow *window)
1142 {
1143   g_return_if_fail (window != NULL);
1144   g_return_if_fail (GDK_IS_WINDOW (window));
1145   
1146   if (!GDK_WINDOW_DESTROYED (window))
1147     {
1148       GDK_NOTE (MISC, g_print ("gdk_window_raise: %#x\n",
1149                                (guint) GDK_WINDOW_HWND (window)));
1150
1151       if (!BringWindowToTop (GDK_WINDOW_HWND (window)))
1152         WIN32_API_FAILED ("BringWindowToTop");
1153     }
1154 }
1155
1156 void
1157 gdk_window_lower (GdkWindow *window)
1158 {
1159   g_return_if_fail (window != NULL);
1160   g_return_if_fail (GDK_IS_WINDOW (window));
1161   
1162   if (!GDK_WINDOW_DESTROYED (window))
1163     {
1164       GDK_NOTE (MISC, g_print ("gdk_window_lower: %#x\n",
1165                                (guint) GDK_WINDOW_HWND (window)));
1166
1167       if (!SetWindowPos (GDK_WINDOW_HWND (window), HWND_BOTTOM, 0, 0, 0, 0,
1168                          SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE))
1169         WIN32_API_FAILED ("SetWindowPos");
1170     }
1171 }
1172
1173 void
1174 gdk_window_set_hints (GdkWindow *window,
1175                       gint       x,
1176                       gint       y,
1177                       gint       min_width,
1178                       gint       min_height,
1179                       gint       max_width,
1180                       gint       max_height,
1181                       gint       flags)
1182 {
1183   GdkWindowImplWin32 *impl;
1184   WINDOWPLACEMENT size_hints;
1185   RECT rect;
1186   DWORD dwStyle;
1187   DWORD dwExStyle;
1188   int diff;
1189   
1190   g_return_if_fail (window != NULL);
1191   g_return_if_fail (GDK_IS_WINDOW (window));
1192   
1193   if (GDK_WINDOW_DESTROYED (window))
1194     return;
1195   
1196   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1197
1198   GDK_NOTE (MISC, g_print ("gdk_window_set_hints: %#x %dx%d..%dx%d @+%d+%d\n",
1199                            (guint) GDK_WINDOW_HWND (window),
1200                            min_width, min_height, max_width, max_height,
1201                            x, y));
1202
1203   impl->hint_flags = flags;
1204   size_hints.length = sizeof (size_hints);
1205
1206   if (flags)
1207     {
1208       if (flags & GDK_HINT_POS)
1209         {
1210           if (!GetWindowPlacement (GDK_WINDOW_HWND (window), &size_hints))
1211             WIN32_API_FAILED ("GetWindowPlacement");
1212           else
1213             {
1214               GDK_NOTE (MISC, g_print ("...rcNormalPosition:"
1215                                        " (%ld,%ld)--(%ld,%ld)\n",
1216                                        size_hints.rcNormalPosition.left,
1217                                        size_hints.rcNormalPosition.top,
1218                                        size_hints.rcNormalPosition.right,
1219                                        size_hints.rcNormalPosition.bottom));
1220               /* What are the corresponding window coordinates for client
1221                * area coordinates x, y
1222                */
1223               rect.left = x;
1224               rect.top = y;
1225               rect.right = rect.left + 200;     /* dummy */
1226               rect.bottom = rect.top + 200;
1227               dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1228               dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1229               AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1230               size_hints.flags = 0;
1231               size_hints.showCmd = SW_SHOWNA;
1232               
1233               /* Set the normal position hint to that location, with unchanged
1234                * width and height.
1235                */
1236               diff = size_hints.rcNormalPosition.left - rect.left;
1237               size_hints.rcNormalPosition.left = rect.left;
1238               size_hints.rcNormalPosition.right -= diff;
1239               diff = size_hints.rcNormalPosition.top - rect.top;
1240               size_hints.rcNormalPosition.top = rect.top;
1241               size_hints.rcNormalPosition.bottom -= diff;
1242               GDK_NOTE (MISC, g_print ("...setting: (%ld,%ld)--(%ld,%ld)\n",
1243                                        size_hints.rcNormalPosition.left,
1244                                        size_hints.rcNormalPosition.top,
1245                                        size_hints.rcNormalPosition.right,
1246                                        size_hints.rcNormalPosition.bottom));
1247               if (!SetWindowPlacement (GDK_WINDOW_HWND (window), &size_hints))
1248                 WIN32_API_FAILED ("SetWindowPlacement");
1249               impl->hint_x = rect.left;
1250               impl->hint_y = rect.top;
1251             }
1252         }
1253
1254       if (flags & GDK_HINT_MIN_SIZE)
1255         {
1256           rect.left = 0;
1257           rect.top = 0;
1258           rect.right = min_width;
1259           rect.bottom = min_height;
1260           dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1261           dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1262           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1263           impl->hint_min_width = rect.right - rect.left;
1264           impl->hint_min_height = rect.bottom - rect.top;
1265
1266           /* Also chek if he current size of the window is in bounds. */
1267           GetClientRect (GDK_WINDOW_HWND (window), &rect);
1268           if (rect.right < min_width && rect.bottom < min_height)
1269             gdk_window_resize (window, min_width, min_height);
1270           else if (rect.right < min_width)
1271             gdk_window_resize (window, min_width, rect.bottom);
1272           else if (rect.bottom < min_height)
1273             gdk_window_resize (window, rect.right, min_height);
1274         }
1275
1276       if (flags & GDK_HINT_MAX_SIZE)
1277         {
1278           rect.left = 0;
1279           rect.top = 0;
1280           rect.right = max_width;
1281           rect.bottom = max_height;
1282           dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1283           dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1284           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1285           impl->hint_max_width = rect.right - rect.left;
1286           impl->hint_max_height = rect.bottom - rect.top;
1287           /* Again, check if the window is too large currently. */
1288           GetClientRect (GDK_WINDOW_HWND (window), &rect);
1289           if (rect.right > max_width && rect.bottom > max_height)
1290             gdk_window_resize (window, max_width, max_height);
1291           else if (rect.right > max_width)
1292             gdk_window_resize (window, max_width, rect.bottom);
1293           else if (rect.bottom > max_height)
1294             gdk_window_resize (window, rect.right, max_height);
1295         }
1296     }
1297 }
1298
1299 void 
1300 gdk_window_set_geometry_hints (GdkWindow      *window,
1301                                GdkGeometry    *geometry,
1302                                GdkWindowHints  geom_mask)
1303 {
1304   GdkWindowImplWin32 *impl;
1305   WINDOWPLACEMENT size_hints;
1306   RECT rect;
1307   DWORD dwStyle;
1308   DWORD dwExStyle;
1309   
1310   g_return_if_fail (window != NULL);
1311   g_return_if_fail (GDK_IS_WINDOW (window));
1312   
1313   if (GDK_WINDOW_DESTROYED (window))
1314     return;
1315
1316   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1317   size_hints.length = sizeof (size_hints);
1318
1319   impl->hint_flags = geom_mask;
1320
1321   if (geom_mask & GDK_HINT_POS)
1322     ; /* XXX */
1323
1324   if (geom_mask & GDK_HINT_MIN_SIZE)
1325     {
1326       rect.left = 0;
1327       rect.top = 0;
1328       rect.right = geometry->min_width;
1329       rect.bottom = geometry->min_height;
1330       dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1331       dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1332       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1333       impl->hint_min_width = rect.right - rect.left;
1334       impl->hint_min_height = rect.bottom - rect.top;
1335
1336       /* Also check if he current size of the window is in bounds */
1337       GetClientRect (GDK_WINDOW_HWND (window), &rect);
1338       if (rect.right < geometry->min_width
1339           && rect.bottom < geometry->min_height)
1340         gdk_window_resize (window, geometry->min_width, geometry->min_height);
1341       else if (rect.right < geometry->min_width)
1342         gdk_window_resize (window, geometry->min_width, rect.bottom);
1343       else if (rect.bottom < geometry->min_height)
1344         gdk_window_resize (window, rect.right, geometry->min_height);
1345     }
1346   
1347   if (geom_mask & GDK_HINT_MAX_SIZE)
1348     {
1349       rect.left = 0;
1350       rect.top = 0;
1351       rect.right = geometry->max_width;
1352       rect.bottom = geometry->max_height;
1353       dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1354       dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1355       /* HB: dont' know why AdjustWindowRectEx is called here, ... */
1356       SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1357       impl->hint_max_width = rect.right - rect.left;
1358       impl->hint_max_height = rect.bottom - rect.top;
1359       /* ... but negative sizes are always wrong */
1360       if (impl->hint_max_width < 0) impl->hint_max_width = G_MAXSHORT;
1361       if (impl->hint_max_height < 0) impl->hint_max_height = G_MAXSHORT;
1362
1363       /* Again, check if the window is too large currently. */
1364       GetClientRect (GDK_WINDOW_HWND (window), &rect);
1365       if (rect.right > geometry->max_width
1366           && rect.bottom > geometry->max_height)
1367         gdk_window_resize (window, geometry->max_width, geometry->max_height);
1368       else if (rect.right > geometry->max_width)
1369         gdk_window_resize (window, geometry->max_width, rect.bottom);
1370       else if (rect.bottom > geometry->max_height)
1371         gdk_window_resize (window, rect.right, geometry->max_height);
1372     }
1373   
1374   /* I don't know what to do when called with zero base_width and height. */
1375   if (geom_mask & GDK_HINT_BASE_SIZE
1376       && geometry->base_width > 0
1377       && geometry->base_height > 0)
1378     {
1379       if (!GetWindowPlacement (GDK_WINDOW_HWND (window), &size_hints))
1380         WIN32_API_FAILED ("GetWindowPlacement");
1381       else
1382         {
1383           GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints:"
1384                                    " rcNormalPosition: (%ld,%ld)--(%ld,%ld)\n",
1385                                    size_hints.rcNormalPosition.left,
1386                                    size_hints.rcNormalPosition.top,
1387                                    size_hints.rcNormalPosition.right,
1388                                    size_hints.rcNormalPosition.bottom));
1389           size_hints.rcNormalPosition.right =
1390             size_hints.rcNormalPosition.left + geometry->base_width;
1391           size_hints.rcNormalPosition.bottom =
1392             size_hints.rcNormalPosition.top + geometry->base_height;
1393           GDK_NOTE (MISC, g_print ("...setting: rcNormal: (%ld,%ld)--(%ld,%ld)\n",
1394                                    size_hints.rcNormalPosition.left,
1395                                    size_hints.rcNormalPosition.top,
1396                                    size_hints.rcNormalPosition.right,
1397                                    size_hints.rcNormalPosition.bottom));
1398           if (!SetWindowPlacement (GDK_WINDOW_HWND (window), &size_hints))
1399             WIN32_API_FAILED ("SetWindowPlacement");
1400         }
1401     }
1402   
1403   if (geom_mask & GDK_HINT_RESIZE_INC)
1404     {
1405       /* XXX */
1406     }
1407   
1408   if (geom_mask & GDK_HINT_ASPECT)
1409     {
1410       /* XXX */
1411     }
1412 }
1413
1414 void
1415 gdk_window_set_title (GdkWindow   *window,
1416                       const gchar *title)
1417 {
1418   char *mbtitle;
1419
1420   g_return_if_fail (window != NULL);
1421   g_return_if_fail (GDK_IS_WINDOW (window));
1422   g_return_if_fail (title != NULL);
1423
1424   /* Empty window titles not allowed, so set it to just a period. */
1425   if (!title[0])
1426     title = ".";
1427   
1428   GDK_NOTE (MISC, g_print ("gdk_window_set_title: %#x %s\n",
1429                            (guint) GDK_WINDOW_HWND (window), title));
1430   
1431   if (!GDK_WINDOW_DESTROYED (window))
1432     {
1433       /* As the title is in UTF-8 we must translate it
1434        * to the system codepage.
1435        */
1436       mbtitle = g_locale_from_utf8 (title, -1, NULL, NULL, NULL);
1437       if (!SetWindowText (GDK_WINDOW_HWND (window), mbtitle))
1438         WIN32_API_FAILED ("SetWindowText");
1439
1440       g_free (mbtitle);
1441     }
1442 }
1443
1444 void          
1445 gdk_window_set_role (GdkWindow   *window,
1446                      const gchar *role)
1447 {
1448   g_return_if_fail (window != NULL);
1449   g_return_if_fail (GDK_IS_WINDOW (window));
1450   
1451   GDK_NOTE (MISC, g_print ("gdk_window_set_role: %#x %s\n",
1452                            (guint) GDK_WINDOW_HWND (window),
1453                            (role ? role : "NULL")));
1454   /* XXX */
1455 }
1456
1457 void          
1458 gdk_window_set_transient_for (GdkWindow *window, 
1459                               GdkWindow *parent)
1460 {
1461   g_return_if_fail (window != NULL);
1462   g_return_if_fail (GDK_IS_WINDOW (window));
1463   
1464   GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %#x %#x\n",
1465                            (guint) GDK_WINDOW_HWND (window),
1466                            (guint) GDK_WINDOW_HWND (parent)));
1467   /* XXX */
1468 }
1469
1470 void
1471 gdk_window_set_background (GdkWindow *window,
1472                            GdkColor  *color)
1473 {
1474   GdkWindowObject *private = (GdkWindowObject *)window;
1475   
1476   g_return_if_fail (window != NULL);
1477   g_return_if_fail (GDK_IS_WINDOW (window));
1478   
1479   GDK_NOTE (MISC, g_print ("gdk_window_set_background: %#x %s\n",
1480                            (guint) GDK_WINDOW_HWND (window), 
1481                            gdk_win32_color_to_string (color)));
1482
1483   private->bg_color = *color;
1484
1485   if (private->bg_pixmap &&
1486       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1487       private->bg_pixmap != GDK_NO_BG)
1488     {
1489       gdk_drawable_unref (private->bg_pixmap);
1490       private->bg_pixmap = NULL;
1491     }
1492 }
1493
1494 void
1495 gdk_window_set_back_pixmap (GdkWindow *window,
1496                             GdkPixmap *pixmap,
1497                             gint       parent_relative)
1498 {
1499   GdkWindowObject *private = (GdkWindowObject *)window;
1500
1501   g_return_if_fail (window != NULL);
1502   g_return_if_fail (GDK_IS_WINDOW (window));
1503   g_return_if_fail (pixmap == NULL || !parent_relative);
1504   
1505   if (private->bg_pixmap &&
1506       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1507       private->bg_pixmap != GDK_NO_BG)
1508     gdk_drawable_unref (private->bg_pixmap);
1509
1510   if (parent_relative)
1511     {
1512       private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
1513     }
1514   else
1515     {
1516       if (pixmap)
1517         {
1518           gdk_drawable_ref (pixmap);
1519           private->bg_pixmap = pixmap;
1520         }
1521       else
1522         {
1523           private->bg_pixmap = GDK_NO_BG;
1524         }
1525     }
1526 }
1527
1528 void
1529 gdk_window_set_cursor (GdkWindow *window,
1530                        GdkCursor *cursor)
1531 {
1532   GdkWindowImplWin32 *impl;
1533   GdkCursorPrivate *cursor_private;
1534   HCURSOR hcursor;
1535   HCURSOR hprevcursor;
1536   POINT pt;
1537   
1538   g_return_if_fail (window != NULL);
1539   g_return_if_fail (GDK_IS_WINDOW (window));
1540   
1541   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
1542   cursor_private = (GdkCursorPrivate*) cursor;
1543   
1544   if (!GDK_WINDOW_DESTROYED (window))
1545     {
1546       if (!cursor)
1547         hcursor = NULL;
1548       else
1549         hcursor = cursor_private->hcursor;
1550
1551       GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %#x %#x\n",
1552                                (guint) GDK_WINDOW_HWND (window),
1553                                (guint) hcursor));
1554       hprevcursor = impl->hcursor;
1555       if (hcursor == NULL)
1556         impl->hcursor = NULL;
1557       else
1558         {
1559           /* We must copy the cursor as it is OK to destroy the GdkCursor
1560            * while still in use for some window. See for instance
1561            * gimp_change_win_cursor() which calls
1562            * gdk_window_set_cursor (win, cursor), and immediately
1563            * afterwards gdk_cursor_destroy (cursor).
1564            */
1565           impl->hcursor = CopyCursor (hcursor);
1566           GDK_NOTE (MISC, g_print ("...CopyCursor (%#x) = %#x\n",
1567                                    (guint) hcursor, (guint) impl->hcursor));
1568
1569           GetCursorPos (&pt);
1570           if (ChildWindowFromPoint (GDK_WINDOW_HWND (window), pt) == GDK_WINDOW_HWND (window))
1571             SetCursor (impl->hcursor);
1572
1573           if (hprevcursor != NULL)
1574             {
1575               GDK_NOTE (MISC, g_print ("...DestroyCursor (%#x)\n",
1576                                        (guint) hprevcursor));
1577           
1578               if (!DestroyCursor (hprevcursor))
1579                 WIN32_API_FAILED ("DestroyCursor");
1580               impl->hcursor = NULL;
1581             }
1582         }
1583     }
1584 }
1585
1586 void
1587 gdk_window_get_geometry (GdkWindow *window,
1588                          gint      *x,
1589                          gint      *y,
1590                          gint      *width,
1591                          gint      *height,
1592                          gint      *depth)
1593 {
1594   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1595   
1596   if (!window)
1597     window = gdk_parent_root;
1598   
1599   if (!GDK_WINDOW_DESTROYED (window))
1600     {
1601       RECT rect;
1602
1603       if (!GetClientRect (GDK_WINDOW_HWND (window), &rect))
1604         WIN32_API_FAILED ("GetClientRect");
1605
1606       if (x)
1607         *x = rect.left;
1608       if (y)
1609         *y = rect.top;
1610       if (width)
1611         *width = rect.right - rect.left;
1612       if (height)
1613         *height = rect.bottom - rect.top;
1614       if (depth)
1615         *depth = gdk_drawable_get_visual (window)->depth;
1616     }
1617 }
1618
1619 gint
1620 gdk_window_get_origin (GdkWindow *window,
1621                        gint      *x,
1622                        gint      *y)
1623 {
1624   gint return_val;
1625   gint tx = 0;
1626   gint ty = 0;
1627
1628   g_return_val_if_fail (window != NULL, 0);
1629
1630   if (!GDK_WINDOW_DESTROYED (window))
1631     {
1632       POINT pt;
1633
1634       pt.x = 0;
1635       pt.y = 0;
1636       ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1637       tx = pt.x;
1638       ty = pt.y;
1639       return_val = 1;
1640     }
1641   else
1642     return_val = 0;
1643   
1644   if (x)
1645     *x = tx;
1646   if (y)
1647     *y = ty;
1648
1649   GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %#x: +%d+%d\n",
1650                            (guint) GDK_WINDOW_HWND (window),
1651                            tx, ty));
1652   return return_val;
1653 }
1654
1655 gboolean
1656 gdk_window_get_deskrelative_origin (GdkWindow *window,
1657                                     gint      *x,
1658                                     gint      *y)
1659 {
1660   return gdk_window_get_origin (window, x, y);
1661 }
1662
1663 void
1664 gdk_window_get_root_origin (GdkWindow *window,
1665                             gint      *x,
1666                             gint      *y)
1667 {
1668   GdkWindowObject *rover;
1669   POINT pt;
1670
1671   g_return_if_fail (window != NULL);
1672   g_return_if_fail (GDK_IS_WINDOW (window));
1673
1674   rover = (GdkWindowObject*) window;
1675   if (x)
1676     *x = 0;
1677   if (y)
1678     *y = 0;
1679
1680   if (GDK_WINDOW_DESTROYED (window))
1681     return;
1682       
1683   while (rover->parent && ((GdkWindowObject*) rover->parent)->parent)
1684     rover = (GdkWindowObject *) rover->parent;
1685   if (rover->destroyed)
1686     return;
1687
1688   pt.x = 0;
1689   pt.y = 0;
1690   ClientToScreen (GDK_WINDOW_HWND (rover), &pt);
1691   if (x)
1692     *x = pt.x;
1693   if (y)
1694     *y = pt.y;
1695
1696   GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %#x: (%#x) +%ld+%ld\n",
1697                            (guint) GDK_WINDOW_HWND (window),
1698                            (guint) GDK_WINDOW_HWND (rover),
1699                            pt.x, pt.y));
1700 }
1701
1702 GdkWindow*
1703 gdk_window_get_pointer (GdkWindow       *window,
1704                         gint            *x,
1705                         gint            *y,
1706                         GdkModifierType *mask)
1707 {
1708   GdkWindow *return_val;
1709   POINT pointc, point;
1710   HWND hwnd, hwndc;
1711
1712   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1713   
1714   if (!window)
1715     window = gdk_parent_root;
1716
1717   return_val = NULL;
1718   GetCursorPos (&pointc);
1719   point = pointc;
1720   ScreenToClient (GDK_WINDOW_HWND (window), &point);
1721
1722   if (x)
1723     *x = point.x;
1724   if (y)
1725     *y = point.y;
1726
1727   hwnd = WindowFromPoint (point);
1728   point = pointc;
1729   ScreenToClient (hwnd, &point);
1730   
1731   do {
1732     hwndc = ChildWindowFromPoint (hwnd, point);
1733     ClientToScreen (hwnd, &point);
1734     ScreenToClient (hwndc, &point);
1735   } while (hwndc != hwnd && (hwnd = hwndc, 1)); /* Ouch! */
1736
1737   return_val = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
1738
1739   if (mask)
1740     {
1741       BYTE kbd[256];
1742
1743       GetKeyboardState (kbd);
1744       *mask = 0;
1745       if (kbd[VK_SHIFT] & 0x80)
1746         *mask |= GDK_SHIFT_MASK;
1747       if (kbd[VK_CAPITAL] & 0x80)
1748         *mask |= GDK_LOCK_MASK;
1749       if (kbd[VK_CONTROL] & 0x80)
1750         *mask |= GDK_CONTROL_MASK;
1751       if (kbd[VK_MENU] & 0x80)
1752         *mask |= GDK_MOD1_MASK;
1753       if (kbd[VK_LBUTTON] & 0x80)
1754         *mask |= GDK_BUTTON1_MASK;
1755       if (kbd[VK_MBUTTON] & 0x80)
1756         *mask |= GDK_BUTTON2_MASK;
1757       if (kbd[VK_RBUTTON] & 0x80)
1758         *mask |= GDK_BUTTON3_MASK;
1759     }
1760   
1761   return return_val;
1762 }
1763
1764 GdkWindow*
1765 gdk_window_at_pointer (gint *win_x,
1766                        gint *win_y)
1767 {
1768   GdkWindow *window;
1769   POINT point, pointc;
1770   HWND hwnd, hwndc;
1771   RECT rect;
1772
1773   GetCursorPos (&pointc);
1774   point = pointc;
1775   hwnd = WindowFromPoint (point);
1776
1777   if (hwnd == NULL)
1778     {
1779       window = gdk_parent_root;
1780       if (win_x)
1781         *win_x = pointc.x;
1782       if (win_y)
1783         *win_y = pointc.y;
1784       return window;
1785     }
1786       
1787   ScreenToClient (hwnd, &point);
1788
1789   do {
1790     hwndc = ChildWindowFromPoint (hwnd, point);
1791     ClientToScreen (hwnd, &point);
1792     ScreenToClient (hwndc, &point);
1793   } while (hwndc != hwnd && (hwnd = hwndc, 1));
1794
1795   window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
1796
1797   if (window && (win_x || win_y))
1798     {
1799       GetClientRect (hwnd, &rect);
1800       if (win_x)
1801         *win_x = point.x - rect.left;
1802       if (win_y)
1803         *win_y = point.y - rect.top;
1804     }
1805
1806   GDK_NOTE (MISC, g_print ("gdk_window_at_pointer: +%ld+%ld %#x%s\n",
1807                            point.x, point.y,
1808                            (guint) hwnd,
1809                            (window == NULL ? " NULL" : "")));
1810
1811   return window;
1812 }
1813
1814 GdkEventMask  
1815 gdk_window_get_events (GdkWindow *window)
1816 {
1817   g_return_val_if_fail (window != NULL, 0);
1818   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1819
1820   if (GDK_WINDOW_DESTROYED (window))
1821     return 0;
1822
1823   return GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl)->event_mask;
1824 }
1825
1826 void          
1827 gdk_window_set_events (GdkWindow   *window,
1828                        GdkEventMask event_mask)
1829 {
1830   g_return_if_fail (window != NULL);
1831   g_return_if_fail (GDK_IS_WINDOW (window));
1832
1833   if (GDK_WINDOW_DESTROYED (window))
1834     return;
1835
1836   GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl)->event_mask = event_mask;
1837 }
1838
1839 void
1840 gdk_window_shape_combine_mask (GdkWindow *window,
1841                                GdkBitmap *mask,
1842                                gint x, gint y)
1843 {
1844   g_return_if_fail (window != NULL);
1845   g_return_if_fail (GDK_IS_WINDOW (window));
1846
1847   if (!mask)
1848     {
1849       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x none\n",
1850                                (guint) GDK_WINDOW_HWND (window)));
1851       SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
1852     }
1853   else
1854     {
1855       HRGN hrgn;
1856       DWORD dwStyle;
1857       DWORD dwExStyle;
1858       RECT rect;
1859
1860       /* Convert mask bitmap to region */
1861       hrgn = BitmapToRegion (GDK_WINDOW_HWND (mask));
1862
1863       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x %#x\n",
1864                                (guint) GDK_WINDOW_HWND (window),
1865                                (guint) GDK_WINDOW_HWND (mask)));
1866
1867       /* SetWindowRgn wants window (not client) coordinates */ 
1868       dwStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1869       dwExStyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1870       GetClientRect (GDK_WINDOW_HWND (window), &rect);
1871       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1872       OffsetRgn (hrgn, -rect.left, -rect.top);
1873
1874       OffsetRgn (hrgn, x, y);
1875
1876       /* If this is a top-level window, add the title bar to the region */
1877       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
1878         {
1879           CombineRgn (hrgn, hrgn,
1880                       CreateRectRgn (0, 0, rect.right - rect.left, -rect.top),
1881                       RGN_OR);
1882         }
1883       
1884       SetWindowRgn (GDK_WINDOW_HWND (window), hrgn, TRUE);
1885     }
1886 }
1887
1888 void
1889 gdk_window_set_override_redirect (GdkWindow *window,
1890                                   gboolean   override_redirect)
1891 {
1892   g_return_if_fail (window != NULL);
1893   g_return_if_fail (GDK_IS_WINDOW (window));
1894
1895   g_warning ("gdk_window_set_override_redirect not implemented");
1896 }
1897
1898 void          
1899 gdk_window_set_icon (GdkWindow *window, 
1900                      GdkWindow *icon_window,
1901                      GdkPixmap *pixmap,
1902                      GdkBitmap *mask)
1903 {
1904   g_return_if_fail (window != NULL);
1905   g_return_if_fail (GDK_IS_WINDOW (window));
1906
1907   if (GDK_WINDOW_DESTROYED (window))
1908     return;
1909   
1910   /* Nothing to do, really. As we share window classes between windows
1911    * we can't have window-specific icons, sorry. Don't print any warning
1912    * either.
1913    */
1914 }
1915
1916 void
1917 gdk_window_set_icon_name (GdkWindow   *window, 
1918                           const gchar *name)
1919 {
1920   g_return_if_fail (window != NULL);
1921   g_return_if_fail (GDK_IS_WINDOW (window));
1922
1923   if (GDK_WINDOW_DESTROYED (window))
1924     return;
1925   
1926   if (!SetWindowText (GDK_WINDOW_HWND (window), name))
1927     WIN32_API_FAILED ("SetWindowText");
1928 }
1929
1930 void          
1931 gdk_window_set_group (GdkWindow *window, 
1932                       GdkWindow *leader)
1933 {
1934   g_return_if_fail (window != NULL);
1935   g_return_if_fail (GDK_IS_WINDOW (window));
1936   g_return_if_fail (leader != NULL);
1937   g_return_if_fail (GDK_IS_WINDOW (leader));
1938
1939   if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
1940     return;
1941   
1942   g_warning ("gdk_window_set_group not implemented");
1943 }
1944
1945 void
1946 gdk_window_set_decorations (GdkWindow      *window,
1947                             GdkWMDecoration decorations)
1948 {
1949   LONG style, exstyle;
1950
1951   g_return_if_fail (window != NULL);
1952   g_return_if_fail (GDK_IS_WINDOW (window));
1953   
1954   style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1955   exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1956
1957   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
1958             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE);
1959
1960   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
1961
1962   if (decorations & GDK_DECOR_ALL)
1963     style |= (WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
1964   if (decorations & GDK_DECOR_BORDER)
1965     style |= (WS_BORDER);
1966   if (decorations & GDK_DECOR_RESIZEH)
1967     style |= (WS_THICKFRAME);
1968   if (decorations & GDK_DECOR_TITLE)
1969     style |= (WS_CAPTION);
1970   if (decorations & GDK_DECOR_MENU)
1971     style |= (WS_SYSMENU);
1972   if (decorations & GDK_DECOR_MINIMIZE)
1973     style |= (WS_MINIMIZEBOX);
1974   if (decorations & GDK_DECOR_MAXIMIZE)
1975     style |= (WS_MAXIMIZEBOX);
1976   
1977   SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
1978 }
1979
1980 void
1981 gdk_window_set_functions (GdkWindow    *window,
1982                           GdkWMFunction functions)
1983 {
1984   LONG style, exstyle;
1985
1986   g_return_if_fail (window != NULL);
1987   g_return_if_fail (GDK_IS_WINDOW (window));
1988   
1989   style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1990   exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
1991
1992   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
1993             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE|WS_CAPTION|WS_BORDER
1994             |WS_SYSMENU);
1995
1996   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
1997
1998   if (functions & GDK_FUNC_ALL)
1999     style |= (WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2000   if (functions & GDK_FUNC_RESIZE)
2001     style |= (WS_THICKFRAME);
2002   if (functions & GDK_FUNC_MOVE)
2003     style |= (WS_THICKFRAME);
2004   if (functions & GDK_FUNC_MINIMIZE)
2005     style |= (WS_MINIMIZEBOX);
2006   if (functions & GDK_FUNC_MAXIMIZE)
2007     style |= (WS_MAXIMIZEBOX);
2008   
2009   SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
2010 }
2011
2012 /* 
2013  * propagate the shapes from all child windows of a GDK window to the parent 
2014  * window. Shamelessly ripped from Enlightenment's code
2015  * 
2016  * - Raster
2017  */
2018
2019 static void
2020 QueryTree (HWND hwnd,
2021            HWND **children,
2022            gint *nchildren)
2023 {
2024   guint i, n;
2025   HWND child;
2026
2027   n = 0;
2028   do {
2029     if (n == 0)
2030       child = GetWindow (hwnd, GW_CHILD);
2031     else
2032       child = GetWindow (child, GW_HWNDNEXT);
2033     if (child != NULL)
2034       n++;
2035   } while (child != NULL);
2036
2037   if (n > 0)
2038     {
2039       *children = g_new (HWND, n);
2040       for (i = 0; i < n; i++)
2041         {
2042           if (i == 0)
2043             child = GetWindow (hwnd, GW_CHILD);
2044           else
2045             child = GetWindow (child, GW_HWNDNEXT);
2046           *children[i] = child;
2047         }
2048     }
2049 }
2050
2051 static void
2052 gdk_propagate_shapes (HANDLE   win,
2053                       gboolean merge)
2054 {
2055    RECT emptyRect;
2056    HRGN region, childRegion;
2057    HWND *list = NULL;
2058    gint i, num;
2059
2060    SetRectEmpty (&emptyRect);
2061    region = CreateRectRgnIndirect (&emptyRect);
2062    if (merge)
2063      GetWindowRgn (win, region);
2064    
2065    QueryTree (win, &list, &num);
2066    if (list != NULL)
2067      {
2068        WINDOWPLACEMENT placement;
2069
2070        placement.length = sizeof (WINDOWPLACEMENT);
2071        /* go through all child windows and combine regions */
2072        for (i = 0; i < num; i++)
2073          {
2074            GetWindowPlacement (list[i], &placement);
2075            if (placement.showCmd == SW_SHOWNORMAL)
2076              {
2077                childRegion = CreateRectRgnIndirect (&emptyRect);
2078                GetWindowRgn (list[i], childRegion);
2079                CombineRgn (region, region, childRegion, RGN_OR);
2080                DeleteObject (childRegion);
2081              }
2082           }
2083        SetWindowRgn (win, region, TRUE);
2084      }
2085    else
2086      DeleteObject (region);
2087 }
2088
2089 void
2090 gdk_window_set_child_shapes (GdkWindow *window)
2091 {
2092   g_return_if_fail (window != NULL);
2093   g_return_if_fail (GDK_IS_WINDOW (window));
2094    
2095   if (GDK_WINDOW_DESTROYED (window))
2096     return;
2097
2098   gdk_propagate_shapes (GDK_WINDOW_HWND (window), FALSE);
2099 }
2100
2101 void
2102 gdk_window_merge_child_shapes (GdkWindow *window)
2103 {
2104   g_return_if_fail (window != NULL);
2105   g_return_if_fail (GDK_IS_WINDOW (window));
2106   
2107   if (GDK_WINDOW_DESTROYED (window))
2108     return;
2109
2110   gdk_propagate_shapes (GDK_WINDOW_HWND (window), TRUE);
2111 }
2112
2113 /* Support for windows that can be guffaw-scrolled
2114  * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
2115  */
2116
2117 static gboolean
2118 gdk_window_gravity_works (void)
2119 {
2120   enum { UNKNOWN, NO, YES };
2121   static gint gravity_works = UNKNOWN;
2122   
2123   if (gravity_works == UNKNOWN)
2124     {
2125       GdkWindowAttr attr;
2126       GdkWindow *parent;
2127       GdkWindow *child;
2128       gint y;
2129       
2130       attr.window_type = GDK_WINDOW_TEMP;
2131       attr.wclass = GDK_INPUT_OUTPUT;
2132       attr.x = 0;
2133       attr.y = 0;
2134       attr.width = 100;
2135       attr.height = 100;
2136       attr.event_mask = 0;
2137       
2138       parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
2139       
2140       attr.window_type = GDK_WINDOW_CHILD;
2141       child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
2142       
2143       gdk_window_set_static_win_gravity (child, TRUE);
2144       
2145       gdk_window_resize (parent, 100, 110);
2146       gdk_window_move (parent, 0, -10);
2147       gdk_window_move_resize (parent, 0, 0, 100, 100);
2148       
2149       gdk_window_resize (parent, 100, 110);
2150       gdk_window_move (parent, 0, -10);
2151       gdk_window_move_resize (parent, 0, 0, 100, 100);
2152       
2153       gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
2154       
2155       gdk_window_destroy (parent);
2156       gdk_window_destroy (child);
2157       
2158       gravity_works = ((y == -20) ? YES : NO);
2159     }
2160   
2161   return (gravity_works == YES);
2162 }
2163
2164 static void
2165 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
2166 {
2167   g_return_if_fail (window != NULL);
2168
2169   GDK_NOTE (MISC, g_print ("gdk_window_set_static_bit_gravity: Not implemented\n"));
2170 }
2171
2172 static void
2173 gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
2174 {
2175   g_return_if_fail (window != NULL);
2176
2177   GDK_NOTE (MISC,
2178             g_print ("gdk_window_set_static_win_gravity: Not implemented\n"));
2179 }
2180
2181 /*************************************************************
2182  * gdk_window_set_static_gravities:
2183  *     Set the bit gravity of the given window to static,
2184  *     and flag it so all children get static subwindow
2185  *     gravity.
2186  *   arguments:
2187  *     window: window for which to set static gravity
2188  *     use_static: Whether to turn static gravity on or off.
2189  *   results:
2190  *     Does the XServer support static gravity?
2191  *************************************************************/
2192
2193 gboolean 
2194 gdk_window_set_static_gravities (GdkWindow *window,
2195                                  gboolean   use_static)
2196 {
2197   GdkWindowObject *private = (GdkWindowObject *)window;
2198   GList *tmp_list;
2199   
2200   g_return_val_if_fail (window != NULL, FALSE);
2201   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2202
2203   if (!use_static == !private->guffaw_gravity)
2204     return TRUE;
2205   
2206   if (use_static && !gdk_window_gravity_works ())
2207     return FALSE;
2208   
2209   private->guffaw_gravity = use_static;
2210   
2211   if (!GDK_WINDOW_DESTROYED (window))
2212     {
2213       gdk_window_set_static_bit_gravity (window, use_static);
2214       
2215       tmp_list = private->children;
2216       while (tmp_list)
2217         {
2218           gdk_window_set_static_win_gravity (window, use_static);
2219           
2220           tmp_list = tmp_list->next;
2221         }
2222     }
2223   
2224   return TRUE;
2225 }