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