]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow.c
Add new keysyms from X11R6.4 (including EuroSign).
[~andy/gtk] / gdk / win32 / gdkwindow.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 Library 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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-1999.  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 "config.h"
29
30 #include <stdlib.h>
31 #include <stdio.h>
32
33 #include "gdkevents.h"
34 #include "gdkpixmap.h"
35 #include "gdkwindow.h"
36 #include "gdkprivate.h"
37 #include "gdkinputprivate.h"
38 #include "gdkx.h"
39
40 /* The Win API function AdjustWindowRect may return negative values
41  * resulting in obscured title bars. This helper function is coreccting it.
42  */
43 BOOL
44 SafeAdjustWindowRectEx (RECT* lpRect, 
45                         DWORD dwStyle, 
46                         BOOL bMenu, 
47                         DWORD dwExStyle)
48 {
49   if (!AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle))
50     return FALSE;
51   if (lpRect->left < 0)
52     {
53       lpRect->right -= lpRect->left;
54       lpRect->left = 0;
55     }
56   if (lpRect->top < 0)
57     {
58       lpRect->bottom -= lpRect->top;
59       lpRect->top = 0;
60     }
61   return TRUE;
62 }
63
64 /* Forward declarations */
65 static gboolean gdk_window_gravity_works (void);
66 static void     gdk_window_set_static_win_gravity (GdkWindow *window, 
67                                                    gboolean   on);
68
69 /* 
70  * The following fucntion by The Rasterman <raster@redhat.com>
71  * This function returns the X Window ID in which the x y location is in 
72  * (x and y being relative to the root window), excluding any windows listed
73  * in the GList excludes (this is a list of X Window ID's - gpointer being
74  * the Window ID).
75  * 
76  * This is primarily designed for internal gdk use - for DND for example
77  * when using a shaped icon window as the drag object - you exclude the
78  * X Window ID of the "icon" (perhaps more if excludes may be needed) and
79  * You can get back an X Window ID as to what X Window ID is infact under
80  * those X,Y co-ordinates.
81  */
82 HWND
83 gdk_window_xid_at_coords (gint     x,
84                           gint     y,
85                           GList   *excludes,
86                           gboolean excl_child)
87 {
88   POINT pt;
89   gboolean warned = FALSE;
90
91   pt.x = x;
92   pt.y = y;
93   /* This is probably not correct, just a quick hack */
94
95   if (!warned)
96     {
97       g_warning ("gdk_window_xid_at_coords probably not implemented correctly");
98       warned = TRUE;
99     }
100
101   /* XXX */
102   return WindowFromPoint (pt);
103 }
104
105 void
106 gdk_window_init (void)
107 {
108   RECT r;
109   guint width;
110   guint height;
111
112   SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
113   width  = r.right - r.left;
114   height = r.bottom - r.top;
115
116   gdk_root_parent = g_new (GdkWindowPrivate, 1);
117   gdk_root_parent->drawable.xwindow = gdk_root_window;
118   gdk_root_parent->drawable.window_type = GDK_WINDOW_ROOT;
119   gdk_root_parent->drawable.drawable.user_data = NULL;
120   gdk_root_parent->drawable.width = width;
121   gdk_root_parent->drawable.height = height;
122   gdk_root_parent->drawable.ref_count = 1;
123   gdk_root_parent->drawable.colormap = NULL;
124   gdk_root_parent->children = NULL;
125
126   gdk_xid_table_insert (&gdk_root_window, gdk_root_parent);
127 }
128
129 /* RegisterGdkClass
130  *   is a wrapper function for RegisterWindowClassEx.
131  *   It creates at least one unique class for every 
132  *   GdkWindowType. If support for single window-specific icons
133  *   is ever needed (e.g Dialog specific), every such window should
134  *   get its own class
135  */
136 ATOM
137 RegisterGdkClass(GdkWindowType wtype)
138 {
139   static ATOM klassTOPLEVEL = 0;
140   static ATOM klassDIALOG   = 0;
141   static ATOM klassCHILD    = 0;
142   static ATOM klassTEMP     = 0;
143   static HICON hAppIcon = NULL;
144   static WNDCLASSEX wcl; 
145   ATOM klass = 0;
146
147   wcl.cbSize = sizeof(WNDCLASSEX);     
148   wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
149                   * on WM_SIZE and WM_MOVE. Flicker, Performance!
150                   */
151   wcl.lpfnWndProc = gdk_WindowProc;
152   wcl.cbClsExtra = 0;
153   wcl.cbWndExtra = 0;
154   wcl.hInstance = gdk_ProgInstance;
155   wcl.hIcon = 0;
156   /* initialize once! */
157   if (0 == hAppIcon)
158     {
159       gchar sLoc [_MAX_PATH+1];
160       HINSTANCE hInst = GetModuleHandle(NULL);
161
162       if (0 != GetModuleFileName(hInst, sLoc, _MAX_PATH))
163         {
164           hAppIcon = ExtractIcon(hInst, sLoc, 0);
165           if (0 == hAppIcon)
166             {
167               char *gdklibname = g_strdup_printf ("gdk-%s.dll", GDK_VERSION);
168
169               hAppIcon = ExtractIcon(hInst, gdklibname, 0);
170               g_free (gdklibname);
171             }
172           
173           if (0 == hAppIcon) 
174             hAppIcon = LoadIcon (NULL, IDI_APPLICATION);
175         }
176     }
177
178   wcl.lpszMenuName = NULL;
179   wcl.hIconSm = 0;
180
181   /* initialize once per class */
182 #define ONCE_PER_CLASS() \
183   wcl.hIcon = CopyIcon (hAppIcon); \
184   wcl.hIconSm = CopyIcon (hAppIcon); \
185   wcl.hbrBackground = CreateSolidBrush( RGB(0,0,0)); \
186   wcl.hCursor = LoadCursor (NULL, IDC_ARROW); 
187   
188   switch (wtype)
189   {
190     case GDK_WINDOW_TOPLEVEL:
191       if (0 == klassTOPLEVEL)
192       {
193         wcl.lpszClassName = "gdkWindowToplevel";
194
195         ONCE_PER_CLASS();
196         klassTOPLEVEL = RegisterClassEx(&wcl);
197       }
198       klass = klassTOPLEVEL;
199       break;
200     case GDK_WINDOW_CHILD:
201       if (0 == klassCHILD)
202       {
203         wcl.lpszClassName = "gdkWindowChild";
204
205         wcl.style |= CS_PARENTDC; /* MSDN: ... enhances system performance. */
206         ONCE_PER_CLASS();
207         klassCHILD = RegisterClassEx(&wcl);
208       }
209       klass = klassCHILD;
210       break;
211     case GDK_WINDOW_DIALOG:
212       if (0 == klassDIALOG)
213       {
214         wcl.lpszClassName = "gdkWindowDialog";
215         wcl.style |= CS_SAVEBITS;
216         ONCE_PER_CLASS();
217         klassDIALOG = RegisterClassEx(&wcl);
218       }
219       klass = klassDIALOG;
220       break;
221     case GDK_WINDOW_TEMP:
222       if (0 == klassTEMP)
223       {
224         wcl.lpszClassName = "gdkWindowTemp";
225         wcl.style |= CS_SAVEBITS;
226         ONCE_PER_CLASS();
227         klassTEMP = RegisterClassEx(&wcl);
228       }
229       klass = klassTEMP;
230       break;
231     case GDK_WINDOW_ROOT:
232       g_error ("cannot make windows of type GDK_WINDOW_ROOT");
233       break;
234     case GDK_DRAWABLE_PIXMAP:
235       g_error ("cannot make windows of type GDK_DRAWABLE_PIXMAP (use gdk_pixmap_new)");
236       break;
237   }
238
239   return klass;
240 } /* RegisterGdkClass */
241
242
243 GdkWindow*
244 gdk_window_new (GdkWindow     *parent,
245                 GdkWindowAttr *attributes,
246                 gint           attributes_mask)
247 {
248   GdkWindow *window;
249   GdkWindowPrivate *private;
250   GdkWindowPrivate *parent_private;
251   GdkVisual *visual;
252   HANDLE xparent;
253   Visual *xvisual;
254   ATOM klass = 0;
255   DWORD dwStyle, dwExStyle;
256   RECT rect;
257   UINT acp;
258   int width, height;
259   int x, y;
260   char *title;
261   gint titlelen;
262   wchar_t *wctitle;
263   gint wlen;
264   char *mbtitle;
265
266   g_return_val_if_fail (attributes != NULL, NULL);
267
268   if (!parent)
269     parent = (GdkWindow*) gdk_root_parent;
270
271   parent_private = (GdkWindowPrivate*) parent;
272   if (GDK_DRAWABLE_DESTROYED (parent))
273     return NULL;
274
275   xparent = parent_private->drawable.xwindow;
276
277   private = g_new (GdkWindowPrivate, 1);
278   window = (GdkWindow*) private;
279
280   private->parent = parent;
281
282   private->drawable.destroyed = FALSE;
283   private->mapped = FALSE;
284   private->guffaw_gravity = FALSE;
285   private->resize_count = 0;
286   private->drawable.ref_count = 1;
287
288   private->x = (attributes_mask & GDK_WA_X) ? attributes->x : 0;
289   private->y = (attributes_mask & GDK_WA_Y) ? attributes->y : 0;
290
291   private->drawable.width = (attributes->width > 1) ? (attributes->width) : (1);
292   private->drawable.height = (attributes->height > 1) ? (attributes->height) : (1);
293   private->drawable.window_type = attributes->window_type;
294   private->extension_events = 0;
295   private->extension_events_selected = FALSE;
296
297   private->filters = NULL;
298   private->children = NULL;
299
300   window->user_data = NULL;
301
302   if (attributes_mask & GDK_WA_VISUAL)
303     visual = attributes->visual;
304   else
305     visual = gdk_visual_get_system ();
306   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
307
308   if (attributes_mask & GDK_WA_TITLE)
309     title = attributes->title;
310   else
311     title = g_get_prgname ();
312
313   private->event_mask = GDK_STRUCTURE_MASK | attributes->event_mask;
314   private->bg_type = GDK_WIN32_BG_NORMAL;
315   private->hint_flags = 0;
316   private->xcursor = NULL;
317       
318   if (parent_private && parent_private->guffaw_gravity)
319     {
320       /* XXX ??? */
321     }
322
323   if (attributes->wclass == GDK_INPUT_OUTPUT)
324     {
325       dwExStyle = 0;
326       if (attributes_mask & GDK_WA_COLORMAP)
327         private->drawable.colormap = attributes->colormap;
328       else
329         private->drawable.colormap = gdk_colormap_get_system ();
330     }
331   else
332     {
333       dwExStyle = WS_EX_TRANSPARENT;
334       private->drawable.colormap = NULL;
335       private->bg_type = GDK_WIN32_BG_TRANSPARENT;
336       private->bg_pixmap = NULL;
337     }
338
339   if (attributes_mask & GDK_WA_X)
340     x = attributes->x;
341   else
342     x = CW_USEDEFAULT;
343
344   if (attributes_mask & GDK_WA_Y)
345     y = attributes->y;
346   else if (attributes_mask & GDK_WA_X)
347     y = 100;                    /* ??? We must put it somewhere... */
348   else
349     y = 500;                    /* x is CW_USEDEFAULT, y doesn't matter then */
350
351   if (parent_private)
352     parent_private->children = g_list_prepend (parent_private->children, window);
353
354   switch (private->drawable.window_type)
355     {
356     case GDK_WINDOW_TOPLEVEL:
357       dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
358       xparent = gdk_root_window;
359       break;
360     case GDK_WINDOW_CHILD:
361       dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
362       break;
363     case GDK_WINDOW_DIALOG:
364       dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
365       dwExStyle |= WS_EX_TOPMOST; /* //HB: want this? */
366       xparent = gdk_root_window;
367       break;
368     case GDK_WINDOW_TEMP:
369       dwStyle = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
370       dwExStyle |= WS_EX_TOOLWINDOW;
371       break;
372     case GDK_WINDOW_ROOT:
373       g_error ("cannot make windows of type GDK_WINDOW_ROOT");
374       break;
375     case GDK_DRAWABLE_PIXMAP:
376       g_error ("cannot make windows of type GDK_DRAWABLE_PIXMAP (use gdk_pixmap_new)");
377       break;
378     }
379
380   klass = RegisterGdkClass (private->drawable.window_type);
381   if (!klass)
382     g_error ("RegisterClassEx failed");
383
384   if (private->drawable.window_type != GDK_WINDOW_CHILD)
385     {
386       if (x == CW_USEDEFAULT)
387         {
388           rect.left = 100;
389           rect.top = 100;
390         }
391       else
392         {
393           rect.left = x;
394           rect.top = y;
395         }
396
397       rect.right = rect.left + private->drawable.width;
398       rect.bottom = rect.top + private->drawable.height;
399
400       if (!SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
401         g_warning ("gdk_window_new: AdjustWindowRectEx failed");
402
403       if (x != CW_USEDEFAULT)
404         {
405           x = rect.left;
406           y = rect.top;
407         }
408       width = rect.right - rect.left;
409       height = rect.bottom - rect.top;
410     }
411   else
412     {
413       width = private->drawable.width;
414       height = private->drawable.height;
415     }
416
417   acp = GetACP ();
418   private->input_locale = GetKeyboardLayout (0);
419   TranslateCharsetInfo ((DWORD FAR *) acp,
420                         &private->charset_info,
421                         TCI_SRCCODEPAGE);
422
423   titlelen = strlen (title);
424   wctitle = g_new (wchar_t, titlelen);
425   mbtitle = g_new (char, 3*titlelen + 1);
426   wlen = gdk_nmbstowchar_ts (wctitle, title, titlelen, titlelen);
427   WideCharToMultiByte (GetACP (), 0, wctitle, wlen,
428                        mbtitle, 3*titlelen, NULL, NULL);
429   
430   private->drawable.xwindow =
431     CreateWindowEx (dwExStyle,
432                     MAKEINTRESOURCE(klass),
433                     mbtitle,
434                     dwStyle,
435                     x, y, 
436                     width, height,
437                     xparent,
438                     NULL,
439                     gdk_ProgInstance,
440                     NULL);
441
442   g_free (mbtitle);
443   g_free (wctitle);
444
445   if (private->drawable.xwindow == NULL)
446     {
447       g_warning ("gdk_window_create: CreateWindowEx failed");
448       g_free (private);
449       return NULL;
450     }
451
452   GDK_NOTE (MISC,
453             g_print ("gdk_window_create: %s %s %dx%d@+%d+%d %#x = %#x\n"
454                      "...locale %#x codepage %d\n",
455                      (private->drawable.window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
456                       (private->drawable.window_type == GDK_WINDOW_CHILD ? "CHILD" :
457                        (private->drawable.window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
458                         (private->drawable.window_type == GDK_WINDOW_TEMP ? "TEMP" :
459                          "???")))),
460                      title,
461                      width, height, (x == CW_USEDEFAULT ? -9999 : x), y, 
462                      xparent,
463                      private->drawable.xwindow,
464                      private->input_locale,
465                      private->charset_info.ciACP));
466
467   gdk_window_ref (window);
468   gdk_xid_table_insert (&private->drawable.xwindow, window);
469
470   if (private->drawable.colormap)
471     gdk_colormap_ref (private->drawable.colormap);
472
473   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
474                                   (attributes->cursor) :
475                                   NULL));
476
477   return window;
478 }
479
480 GdkWindow *
481 gdk_window_foreign_new (guint32 anid)
482 {
483   GdkWindow *window;
484   GdkWindowPrivate *private;
485   GdkWindowPrivate *parent_private;
486   HANDLE parent;
487   RECT rect;
488   POINT point;
489
490   private = g_new (GdkWindowPrivate, 1);
491   window = (GdkWindow*) private;
492
493   parent = GetParent ((HWND) anid);
494   private->parent = gdk_xid_table_lookup (parent);
495
496   parent_private = (GdkWindowPrivate *)private->parent;
497   
498   if (parent_private)
499     parent_private->children = g_list_prepend (parent_private->children, window);
500
501   private->drawable.xwindow = (HWND) anid;
502   GetClientRect ((HWND) anid, &rect);
503   point.x = rect.left;
504   point.y = rect.right;
505   ClientToScreen ((HWND) anid, &point);
506   if (parent != GetDesktopWindow ())
507     ScreenToClient (parent, &point);
508   private->x = point.x;
509   private->y = point.y;
510   private->drawable.width = rect.right - rect.left;
511   private->drawable.height = rect.bottom - rect.top;
512   private->resize_count = 0;
513   private->drawable.ref_count = 1;
514   private->drawable.window_type = GDK_WINDOW_FOREIGN;
515   private->drawable.destroyed = FALSE;
516   private->mapped = IsWindowVisible (private->drawable.xwindow);
517   private->guffaw_gravity = FALSE;
518   private->extension_events = 0;
519   private->extension_events_selected = FALSE;
520
521   private->drawable.colormap = NULL;
522
523   private->filters = NULL;
524   private->children = NULL;
525
526   window->user_data = NULL;
527
528   gdk_window_ref (window);
529   gdk_xid_table_insert (&private->drawable.xwindow, window);
530
531   return window;
532 }
533
534 /* Call this function when you want a window and all its children to
535  * disappear.  When xdestroy is true, a request to destroy the XWindow
536  * is sent out.  When it is false, it is assumed that the XWindow has
537  * been or will be destroyed by destroying some ancestor of this
538  * window.
539  */
540 static void
541 gdk_window_internal_destroy (GdkWindow *window,
542                              gboolean   xdestroy,
543                              gboolean   our_destroy)
544 {
545   GdkWindowPrivate *private;
546   GdkWindowPrivate *temp_private;
547   GdkWindow *temp_window;
548   GList *children;
549   GList *tmp;
550
551   g_return_if_fail (window != NULL);
552
553   private = (GdkWindowPrivate*) window;
554
555   GDK_NOTE (MISC, g_print ("gdk_window_internal_destroy %#x\n",
556                            private->drawable.xwindow));
557
558   switch (private->drawable.window_type)
559     {
560     case GDK_WINDOW_TOPLEVEL:
561     case GDK_WINDOW_CHILD:
562     case GDK_WINDOW_DIALOG:
563     case GDK_WINDOW_TEMP:
564     case GDK_WINDOW_FOREIGN:
565       if (!private->drawable.destroyed)
566         {
567           if (private->parent)
568             {
569               GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
570               if (parent_private->children)
571                 parent_private->children = g_list_remove (parent_private->children, window);
572             }
573
574           if (GDK_DRAWABLE_TYPE (window) != GDK_WINDOW_FOREIGN)
575             {
576               children = tmp = private->children;
577               private->children = NULL;
578
579               while (tmp)
580                 {
581                   temp_window = tmp->data;
582                   tmp = tmp->next;
583                   
584                   temp_private = (GdkWindowPrivate*) temp_window;
585                   if (temp_private)
586                     gdk_window_internal_destroy (temp_window, FALSE,
587                                                  our_destroy);
588                 }
589
590               g_list_free (children);
591             }
592
593           if (private->extension_events != 0)
594             gdk_input_window_destroy (window);
595
596           if (private->filters)
597             {
598               tmp = private->filters;
599
600               while (tmp)
601                 {
602                   g_free (tmp->data);
603                   tmp = tmp->next;
604                 }
605
606               g_list_free (private->filters);
607               private->filters = NULL;
608             }
609           
610           if (private->drawable.window_type == GDK_WINDOW_FOREIGN)
611             {
612               if (our_destroy && (private->parent != NULL))
613                 {
614                   /* It's somebody elses window, but in our hierarchy,
615                    * so reparent it to the root window, and then send
616                    * it a delete event, as if we were a WM
617                    */
618                   gdk_window_hide (window);
619                   gdk_window_reparent (window, NULL, 0, 0);
620                   
621                   /* Is this too drastic? Many (most?) applications
622                    * quit if any window receives WM_QUIT I think.
623                    * OTOH, I don't think foreign windows are much
624                    * used, so the question is maybe academic.
625                    */
626                   PostMessage (private->drawable.xwindow, WM_QUIT, 0, 0);
627                 }
628             }
629           else if (xdestroy)
630             DestroyWindow (private->drawable.xwindow);
631
632           if (private->drawable.colormap)
633             gdk_colormap_unref (private->drawable.colormap);
634
635           private->mapped = FALSE;
636           private->drawable.destroyed = TRUE;
637         }
638       break;
639
640     case GDK_WINDOW_ROOT:
641       g_error ("attempted to destroy root window");
642       break;
643
644     case GDK_DRAWABLE_PIXMAP:
645       g_error ("called gdk_window_destroy on a pixmap (use gdk_pixmap_unref)");
646       break;
647     }
648 }
649
650 /* Like internal_destroy, but also destroys the reference created by
651    gdk_window_new. */
652
653 void
654 gdk_window_destroy (GdkWindow *window)
655 {
656   gdk_window_internal_destroy (window, TRUE, TRUE);
657   gdk_window_unref (window);
658 }
659
660 /* This function is called when the XWindow is really gone.  */
661
662 void
663 gdk_window_destroy_notify (GdkWindow *window)
664 {
665   g_return_if_fail (window != NULL);
666
667   GDK_NOTE (EVENTS, g_print ("gdk_window_destroy_notify: %#x  %d\n",
668                              GDK_DRAWABLE_XID (window), GDK_DRAWABLE_DESTROYED (window)));
669
670   if (!GDK_DRAWABLE_DESTROYED (window))
671     {
672       if (GDK_DRAWABLE_TYPE(window) != GDK_WINDOW_FOREIGN)
673         g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_DRAWABLE_XID (window));
674
675       gdk_window_internal_destroy (window, FALSE, FALSE);
676     }
677   
678   gdk_xid_table_remove (GDK_DRAWABLE_XID (window));
679   gdk_window_unref (window);
680 }
681
682 GdkWindow*
683 gdk_window_ref (GdkWindow *window)
684 {
685   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
686   g_return_val_if_fail (window != NULL, NULL);
687   
688   private->drawable.ref_count += 1;
689
690   GDK_NOTE (MISC, g_print ("gdk_window_ref %#x %d\n",
691                            GDK_DRAWABLE_XID (window),
692                            private->drawable.ref_count));
693
694   return window;
695 }
696
697 void
698 gdk_window_unref (GdkWindow *window)
699 {
700   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
701   g_return_if_fail (window != NULL);
702
703   private->drawable.ref_count -= 1;
704
705   GDK_NOTE (MISC, g_print ("gdk_window_unref %#x %d%s\n",
706                            private->drawable.xwindow,
707                            private->drawable.ref_count,
708                            (private->drawable.ref_count == 0 ? " freeing" : "")));
709
710   if (private->drawable.ref_count == 0)
711     {
712       if (private->bg_type == GDK_WIN32_BG_PIXMAP
713           && private->bg_pixmap != NULL)
714         gdk_pixmap_unref (private->bg_pixmap);
715
716       if (!private->drawable.destroyed)
717         {
718           if (private->drawable.window_type == GDK_WINDOW_FOREIGN)
719             gdk_xid_table_remove (private->drawable.xwindow);
720           else
721             g_warning ("losing last reference to undestroyed window");
722         }
723       g_dataset_destroy (window);
724       g_free (window);
725     }
726 }
727
728 void
729 gdk_window_show (GdkWindow *window)
730 {
731   GdkWindowPrivate *private;
732
733   g_return_if_fail (window != NULL);
734
735   private = (GdkWindowPrivate*) window;
736   if (!private->drawable.destroyed)
737     {
738       GDK_NOTE (MISC, g_print ("gdk_window_show: %#x\n",
739                                private->drawable.xwindow));
740
741       private->mapped = TRUE;
742       if (private->drawable.window_type == GDK_WINDOW_TEMP)
743         {
744           ShowWindow (private->drawable.xwindow, SW_SHOWNOACTIVATE);
745           SetWindowPos (private->drawable.xwindow, HWND_TOPMOST, 0, 0, 0, 0,
746                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
747 #if 0
748           ShowWindow (private->drawable.xwindow, SW_HIDE); /* Don't put on toolbar */
749 #endif
750         }
751       else
752         {
753           ShowWindow (private->drawable.xwindow, SW_SHOWNORMAL);
754           ShowWindow (private->drawable.xwindow, SW_RESTORE);
755           SetForegroundWindow (private->drawable.xwindow);
756           BringWindowToTop (private->drawable.xwindow);
757 #if 0
758           ShowOwnedPopups (private->drawable.xwindow, TRUE);
759 #endif
760         }
761     }
762 }
763
764 void
765 gdk_window_hide (GdkWindow *window)
766 {
767   GdkWindowPrivate *private;
768
769   g_return_if_fail (window != NULL);
770
771   private = (GdkWindowPrivate*) window;
772   if (!private->drawable.destroyed)
773     {
774       GDK_NOTE (MISC, g_print ("gdk_window_hide: %#x\n",
775                                private->drawable.xwindow));
776
777       private->mapped = FALSE;
778       if (private->drawable.window_type == GDK_WINDOW_TOPLEVEL)
779         ShowOwnedPopups (private->drawable.xwindow, FALSE);
780 #if 1
781       ShowWindow (private->drawable.xwindow, SW_HIDE);
782 #elif 0
783       ShowWindow (private->drawable.xwindow, SW_MINIMIZE);
784 #else
785       CloseWindow (private->drawable.xwindow);
786 #endif
787     }
788 }
789
790 void
791 gdk_window_withdraw (GdkWindow *window)
792 {
793   GdkWindowPrivate *private;
794
795   g_return_if_fail (window != NULL);
796
797   private = (GdkWindowPrivate*) window;
798   if (!private->drawable.destroyed)
799     {
800       GDK_NOTE (MISC, g_print ("gdk_window_withdraw: %#x\n",
801                                private->drawable.xwindow));
802
803       gdk_window_hide (window); /* XXX */
804     }
805 }
806
807 void
808 gdk_window_move (GdkWindow *window,
809                  gint       x,
810                  gint       y)
811 {
812   GdkWindowPrivate *private;
813
814   g_return_if_fail (window != NULL);
815
816   private = (GdkWindowPrivate*) window;
817   if (!private->drawable.destroyed)
818     {
819       RECT rect;
820
821       GDK_NOTE (MISC, g_print ("gdk_window_move: %#x +%d+%d\n",
822                                private->drawable.xwindow, x, y));
823
824       GetClientRect (private->drawable.xwindow, &rect);
825
826       if (private->drawable.window_type != GDK_WINDOW_CHILD)
827         {
828           POINT ptTL, ptBR;
829           DWORD dwStyle;
830           DWORD dwExStyle;
831
832           ptTL.x = 0;
833           ptTL.y = 0; 
834           ClientToScreen (private->drawable.xwindow, &ptTL);
835           rect.left = x;
836           rect.top = y;
837
838           ptBR.x = rect.right;
839           ptBR.y = rect.bottom;
840           ClientToScreen (private->drawable.xwindow, &ptBR);
841           rect.right = x + ptBR.x - ptTL.x;
842           rect.bottom = y + ptBR.y - ptTL.y;
843
844           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
845           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
846           if (!SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
847             g_warning ("gdk_window_move: AdjustWindowRectEx failed");
848
849           x = rect.left;
850           y = rect.top;
851         }
852       else
853         {
854           private->x = x;
855           private->y = y;
856         }
857       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
858                                private->drawable.xwindow,
859                                rect.right - rect.left, rect.bottom - rect.top,
860                                x, y));
861       if (!MoveWindow (private->drawable.xwindow,
862                        x, y, rect.right - rect.left, rect.bottom - rect.top,
863                        TRUE))
864         g_warning ("gdk_window_move: MoveWindow failed");
865     }
866 }
867
868 void
869 gdk_window_resize (GdkWindow *window,
870                    gint       width,
871                    gint       height)
872 {
873   GdkWindowPrivate *private;
874
875   g_return_if_fail (window != NULL);
876
877   if ((gint16) width < 1)
878     width = 1;
879   if ((gint16) height < 1)
880     height = 1;
881
882   private = (GdkWindowPrivate*) window;
883
884   if (!private->drawable.destroyed &&
885       ((private->resize_count > 0) ||
886        (private->drawable.width != (guint16) width) ||
887        (private->drawable.height != (guint16) height)))
888     {
889       int x, y;
890
891       GDK_NOTE (MISC, g_print ("gdk_window_resize: %#x %dx%d\n",
892                                private->drawable.xwindow, width, height));
893       
894       if (private->drawable.window_type != GDK_WINDOW_CHILD)
895         {
896           POINT pt;
897           RECT rect;
898           DWORD dwStyle;
899           DWORD dwExStyle;
900
901           pt.x = 0;
902           pt.y = 0; 
903           ClientToScreen (private->drawable.xwindow, &pt);
904           rect.left = pt.x;
905           rect.top = pt.y;
906           rect.right = pt.x + width;
907           rect.bottom = pt.y + height;
908
909           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
910           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
911           if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
912             g_warning ("gdk_window_resize: AdjustWindowRectEx failed");
913
914           x = rect.left;
915           y = rect.top;
916           width = rect.right - rect.left;
917           height = rect.bottom - rect.top;
918         }
919       else
920         {
921           x = private->x;
922           y = private->y;
923           private->drawable.width = width;
924           private->drawable.height = height;
925         }
926
927       private->resize_count += 1;
928
929       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
930                                private->drawable.xwindow, width, height, x, y));
931       if (!MoveWindow (private->drawable.xwindow,
932                        x, y, width, height,
933                        TRUE))
934         g_warning ("gdk_window_resize: MoveWindow failed");
935     }
936 }
937
938 void
939 gdk_window_move_resize (GdkWindow *window,
940                         gint       x,
941                         gint       y,
942                         gint       width,
943                         gint       height)
944 {
945   GdkWindowPrivate *private;
946
947   g_return_if_fail (window != NULL);
948
949   if ((gint16) width < 1)
950     width = 1;
951   if ((gint16) height < 1)
952     height = 1;
953
954   private = (GdkWindowPrivate*) window;
955   if (!private->drawable.destroyed)
956     {
957       RECT rect;
958       DWORD dwStyle;
959       DWORD dwExStyle;
960
961       GDK_NOTE (MISC, g_print ("gdk_window_move_resize: %#x %dx%d@+%d+%d\n",
962                                private->drawable.xwindow, width, height, x, y));
963       
964       rect.left = x;
965       rect.top = y;
966       rect.right = x + width;
967       rect.bottom = y + height;
968
969       dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
970       dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
971       if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
972         g_warning ("gdk_window_move_resize: AdjustWindowRectEx failed");
973
974       if (private->drawable.window_type == GDK_WINDOW_CHILD)
975         {
976           private->x = x;
977           private->y = y;
978           private->drawable.width = width;
979           private->drawable.height = height;
980         }
981       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
982                                private->drawable.xwindow,
983                                rect.right - rect.left, rect.bottom - rect.top,
984                                rect.left, rect.top));
985       if (!MoveWindow (private->drawable.xwindow,
986                        rect.left, rect.top,
987                        rect.right - rect.left, rect.bottom - rect.top,
988                        TRUE))
989         g_warning ("gdk_window_move_resize: MoveWindow failed");
990
991       if (private->guffaw_gravity)
992         {
993           GList *tmp_list = private->children;
994           while (tmp_list)
995             {
996               GdkWindowPrivate *child_private = tmp_list->data;
997               
998               child_private->x -= x - private->x;
999               child_private->y -= y - private->y;
1000               
1001               tmp_list = tmp_list->next;
1002             }
1003         }
1004       
1005     }
1006 }
1007
1008 void
1009 gdk_window_reparent (GdkWindow *window,
1010                      GdkWindow *new_parent,
1011                      gint       x,
1012                      gint       y)
1013 {
1014   GdkWindowPrivate *window_private;
1015   GdkWindowPrivate *parent_private;
1016   GdkWindowPrivate *old_parent_private;
1017
1018   g_return_if_fail (window != NULL);
1019
1020   if (!new_parent)
1021     new_parent = (GdkWindow*) gdk_root_parent;
1022
1023   window_private = (GdkWindowPrivate*) window;
1024   old_parent_private = (GdkWindowPrivate*)window_private->parent;
1025   parent_private = (GdkWindowPrivate*) new_parent;
1026
1027   if (!window_private->drawable.destroyed && !parent_private->drawable.destroyed)
1028     {
1029       GDK_NOTE (MISC, g_print ("gdk_window_reparent: %#x %#x\n",
1030                                window_private->drawable.xwindow,
1031                                parent_private->drawable.xwindow));
1032       if (!SetParent (window_private->drawable.xwindow, parent_private->drawable.xwindow))
1033         g_warning ("gdk_window_reparent: SetParent failed");
1034
1035       if (!MoveWindow (window_private->drawable.xwindow,
1036                        x, y,
1037                        window_private->drawable.width, window_private->drawable.height,
1038                        TRUE))
1039         g_warning ("gdk_window_reparent: MoveWindow failed");
1040     }
1041   
1042   window_private->parent = new_parent;
1043
1044   if (old_parent_private)
1045     old_parent_private->children = g_list_remove (old_parent_private->children, window);
1046
1047   if ((old_parent_private &&
1048        (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
1049       (!old_parent_private && parent_private->guffaw_gravity))
1050     gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
1051   
1052   parent_private->children = g_list_prepend (parent_private->children, window);
1053 }
1054
1055 void
1056 gdk_window_clear (GdkWindow *window)
1057 {
1058   g_return_if_fail (window != NULL);
1059   g_return_if_fail (GDK_IS_WINDOW (window));
1060
1061   if (!GDK_DRAWABLE_DESTROYED (window))
1062     gdk_window_clear_area (window, 0, 0, -1, -1);
1063 }
1064
1065
1066 void
1067 gdk_window_clear_area (GdkWindow *window,
1068                        gint       x,
1069                        gint       y,
1070                        gint       width,
1071                        gint       height)
1072 {
1073   g_return_if_fail (window != NULL);
1074   g_return_if_fail (GDK_IS_WINDOW (window));
1075   
1076   if (!GDK_DRAWABLE_DESTROYED (window))
1077     {
1078       HDC hdc;
1079
1080       if (width == -1)
1081         width = G_MAXSHORT/2;           /* Yeah, right */
1082       if (height == -1)
1083         height = G_MAXSHORT/2;
1084       GDK_NOTE (MISC, g_print ("gdk_window_clear_area: %#x %dx%d@+%d+%d\n",
1085                                GDK_DRAWABLE_XID (window), width, height, x, y));
1086       hdc = GetDC (GDK_DRAWABLE_XID (window));
1087       IntersectClipRect (hdc, x, y, x + width, y + height);
1088       SendMessage (GDK_DRAWABLE_XID (window), WM_ERASEBKGND, (WPARAM) hdc, 0);
1089       ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
1090     }
1091 }
1092
1093 void
1094 gdk_window_clear_area_e (GdkWindow *window,
1095                          gint       x,
1096                          gint       y,
1097                          gint       width,
1098                          gint       height)
1099 {
1100   g_return_if_fail (window != NULL);
1101   g_return_if_fail (GDK_IS_WINDOW (window));
1102   
1103   if (!GDK_DRAWABLE_DESTROYED (window))
1104     {
1105       RECT rect;
1106
1107       GDK_NOTE (MISC, g_print ("gdk_window_clear_area_e: %#x %dx%d@+%d+%d\n",
1108                                GDK_DRAWABLE_XID (window), width, height, x, y));
1109
1110       rect.left = x;
1111       rect.right = x + width;
1112       rect.top = y;
1113       rect.bottom = y + height;
1114       if (!InvalidateRect (GDK_DRAWABLE_XID (window), &rect, TRUE))
1115         g_warning ("gdk_window_clear_area_e: InvalidateRect failed");
1116       UpdateWindow (GDK_DRAWABLE_XID (window));
1117     }
1118 }
1119
1120 void
1121 gdk_window_raise (GdkWindow *window)
1122 {
1123   g_return_if_fail (window != NULL);
1124   g_return_if_fail (GDK_IS_WINDOW (window));
1125   
1126   if (!GDK_DRAWABLE_DESTROYED (window))
1127     {
1128       GDK_NOTE (MISC, g_print ("gdk_window_raise: %#x\n",
1129                                GDK_DRAWABLE_XID (window)));
1130
1131       if (!BringWindowToTop (GDK_DRAWABLE_XID (window)))
1132         g_warning ("gdk_window_raise: BringWindowToTop failed");
1133     }
1134 }
1135
1136 void
1137 gdk_window_lower (GdkWindow *window)
1138 {
1139   g_return_if_fail (window != NULL);
1140   g_return_if_fail (GDK_IS_WINDOW (window));
1141   
1142   if (!GDK_DRAWABLE_DESTROYED (window))
1143     {
1144       GDK_NOTE (MISC, g_print ("gdk_window_lower: %#x\n",
1145                                GDK_DRAWABLE_XID (window)));
1146
1147       if (!SetWindowPos (GDK_DRAWABLE_XID (window), HWND_BOTTOM, 0, 0, 0, 0,
1148                          SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE))
1149         g_warning ("gdk_window_lower: SetWindowPos failed");
1150     }
1151 }
1152
1153 void
1154 gdk_window_set_user_data (GdkWindow *window,
1155                           gpointer   user_data)
1156 {
1157   g_return_if_fail (window != NULL);
1158   
1159   window->user_data = user_data;
1160 }
1161
1162 void
1163 gdk_window_set_hints (GdkWindow *window,
1164                       gint       x,
1165                       gint       y,
1166                       gint       min_width,
1167                       gint       min_height,
1168                       gint       max_width,
1169                       gint       max_height,
1170                       gint       flags)
1171 {
1172   GdkWindowPrivate *private;
1173   WINDOWPLACEMENT size_hints;
1174   RECT rect;
1175   DWORD dwStyle;
1176   DWORD dwExStyle;
1177   int diff;
1178   
1179   g_return_if_fail (window != NULL);
1180   g_return_if_fail (GDK_IS_WINDOW (window));
1181   
1182   if (GDK_DRAWABLE_DESTROYED (window))
1183     return;
1184   
1185   private = (GdkWindowPrivate*) window;
1186
1187   GDK_NOTE (MISC, g_print ("gdk_window_set_hints: %#x %dx%d..%dx%d @+%d+%d\n",
1188                            private->drawable.xwindow,
1189                            min_width, min_height, max_width, max_height,
1190                            x, y));
1191
1192   private->hint_flags = flags;
1193   size_hints.length = sizeof (size_hints);
1194
1195   if (flags)
1196     {
1197       if (flags & GDK_HINT_POS)
1198         if (!GetWindowPlacement (private->drawable.xwindow, &size_hints))
1199           g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
1200         else
1201           {
1202             GDK_NOTE (MISC, g_print ("...rcNormalPosition:"
1203                                      " (%d,%d)--(%d,%d)\n",
1204                                      size_hints.rcNormalPosition.left,
1205                                      size_hints.rcNormalPosition.top,
1206                                      size_hints.rcNormalPosition.right,
1207                                      size_hints.rcNormalPosition.bottom));
1208             /* What are the corresponding window coordinates for client
1209              * area coordinates x, y
1210              */
1211             rect.left = x;
1212             rect.top = y;
1213             rect.right = rect.left + 200;       /* dummy */
1214             rect.bottom = rect.top + 200;
1215             dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1216             dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1217             AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1218             size_hints.flags = 0;
1219             size_hints.showCmd = SW_SHOWNA;
1220
1221             /* Set the normal position hint to that location, with unchanged
1222              * width and height.
1223              */
1224             diff = size_hints.rcNormalPosition.left - rect.left;
1225             size_hints.rcNormalPosition.left = rect.left;
1226             size_hints.rcNormalPosition.right -= diff;
1227             diff = size_hints.rcNormalPosition.top - rect.top;
1228             size_hints.rcNormalPosition.top = rect.top;
1229             size_hints.rcNormalPosition.bottom -= diff;
1230             GDK_NOTE (MISC, g_print ("...setting: (%d,%d)--(%d,%d)\n",
1231                                      size_hints.rcNormalPosition.left,
1232                                      size_hints.rcNormalPosition.top,
1233                                      size_hints.rcNormalPosition.right,
1234                                      size_hints.rcNormalPosition.bottom));
1235             if (!SetWindowPlacement (private->drawable.xwindow, &size_hints))
1236               g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
1237             private->hint_x = rect.left;
1238             private->hint_y = rect.top;
1239           }
1240
1241       if (flags & GDK_HINT_MIN_SIZE)
1242         {
1243           rect.left = 0;
1244           rect.top = 0;
1245           rect.right = min_width;
1246           rect.bottom = min_height;
1247           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1248           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1249           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1250           private->hint_min_width = rect.right - rect.left;
1251           private->hint_min_height = rect.bottom - rect.top;
1252
1253           /* Also chek if he current size of the window is in bounds. */
1254           GetClientRect (private->drawable.xwindow, &rect);
1255           if (rect.right < min_width && rect.bottom < min_height)
1256             gdk_window_resize (window, min_width, min_height);
1257           else if (rect.right < min_width)
1258             gdk_window_resize (window, min_width, rect.bottom);
1259           else if (rect.bottom < min_height)
1260             gdk_window_resize (window, rect.right, min_height);
1261         }
1262       if (flags & GDK_HINT_MAX_SIZE)
1263         {
1264           rect.left = 0;
1265           rect.top = 0;
1266           rect.right = max_width;
1267           rect.bottom = max_height;
1268           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1269           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1270           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1271           private->hint_max_width = rect.right - rect.left;
1272           private->hint_max_height = rect.bottom - rect.top;
1273           /* Again, check if the window is too large currently. */
1274           GetClientRect (private->drawable.xwindow, &rect);
1275           if (rect.right > max_width && rect.bottom > max_height)
1276             gdk_window_resize (window, max_width, max_height);
1277           else if (rect.right > max_width)
1278             gdk_window_resize (window, max_width, rect.bottom);
1279           else if (rect.bottom > max_height)
1280             gdk_window_resize (window, rect.right, max_height);
1281         }
1282     }
1283 }
1284
1285 void 
1286 gdk_window_set_geometry_hints (GdkWindow      *window,
1287                                GdkGeometry    *geometry,
1288                                GdkWindowHints  geom_mask)
1289 {
1290   GdkWindowPrivate *private;
1291   WINDOWPLACEMENT size_hints;
1292   RECT rect;
1293   DWORD dwStyle;
1294   DWORD dwExStyle;
1295   int diff;
1296   
1297   g_return_if_fail (window != NULL);
1298   g_return_if_fail (GDK_IS_WINDOW (window));
1299   
1300   if (GDK_DRAWABLE_DESTROYED (window))
1301     return;
1302
1303   private = (GdkWindowPrivate*) window;
1304   
1305   size_hints.length = sizeof (size_hints);
1306
1307   private->hint_flags = geom_mask;
1308
1309   if (geom_mask & GDK_HINT_POS)
1310     ; /* XXX */
1311
1312   if (geom_mask & GDK_HINT_MIN_SIZE)
1313     {
1314       rect.left = 0;
1315       rect.top = 0;
1316       rect.right = geometry->min_width;
1317       rect.bottom = geometry->min_height;
1318       dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1319       dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1320       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1321       private->hint_min_width = rect.right - rect.left;
1322       private->hint_min_height = rect.bottom - rect.top;
1323
1324       /* Also check if he current size of the window is in bounds */
1325       GetClientRect (private->drawable.xwindow, &rect);
1326       if (rect.right < geometry->min_width
1327           && rect.bottom < geometry->min_height)
1328         gdk_window_resize (window, geometry->min_width, geometry->min_height);
1329       else if (rect.right < geometry->min_width)
1330         gdk_window_resize (window, geometry->min_width, rect.bottom);
1331       else if (rect.bottom < geometry->min_height)
1332         gdk_window_resize (window, rect.right, geometry->min_height);
1333     }
1334   
1335   if (geom_mask & GDK_HINT_MAX_SIZE)
1336     {
1337       rect.left = 0;
1338       rect.top = 0;
1339       rect.right = geometry->max_width;
1340       rect.bottom = geometry->max_height;
1341       dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1342       dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1343       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1344       private->hint_max_width = rect.right - rect.left;
1345       private->hint_max_height = rect.bottom - rect.top;
1346
1347       /* Again, check if the window is too large currently. */
1348       GetClientRect (private->drawable.xwindow, &rect);
1349       if (rect.right > geometry->max_width
1350           && rect.bottom > geometry->max_height)
1351         gdk_window_resize (window, geometry->max_width, geometry->max_height);
1352       else if (rect.right > geometry->max_width)
1353         gdk_window_resize (window, geometry->max_width, rect.bottom);
1354       else if (rect.bottom > geometry->max_height)
1355         gdk_window_resize (window, rect.right, geometry->max_height);
1356     }
1357   
1358   /* I don't know what to do when called with zero base_width and height. */
1359   if (geom_mask & GDK_HINT_BASE_SIZE
1360       && geometry->base_width > 0
1361       && geometry->base_height > 0)
1362     if (!GetWindowPlacement (private->drawable.xwindow, &size_hints))
1363       g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
1364     else
1365       {
1366         GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints:"
1367                                  " rcNormalPosition: (%d,%d)--(%d,%d)\n",
1368                                  size_hints.rcNormalPosition.left,
1369                                  size_hints.rcNormalPosition.top,
1370                                  size_hints.rcNormalPosition.right,
1371                                  size_hints.rcNormalPosition.bottom));
1372         size_hints.rcNormalPosition.right =
1373           size_hints.rcNormalPosition.left + geometry->base_width;
1374         size_hints.rcNormalPosition.bottom =
1375           size_hints.rcNormalPosition.top + geometry->base_height;
1376         GDK_NOTE (MISC, g_print ("...setting: rcNormal: (%d,%d)--(%d,%d)\n",
1377                                  size_hints.rcNormalPosition.left,
1378                                  size_hints.rcNormalPosition.top,
1379                                  size_hints.rcNormalPosition.right,
1380                                  size_hints.rcNormalPosition.bottom));
1381         if (!SetWindowPlacement (private->drawable.xwindow, &size_hints))
1382           g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
1383       }
1384   
1385   if (geom_mask & GDK_HINT_RESIZE_INC)
1386     {
1387       /* XXX */
1388     }
1389   
1390   if (geom_mask & GDK_HINT_ASPECT)
1391     {
1392       /* XXX */
1393     }
1394 }
1395
1396 void
1397 gdk_window_set_title (GdkWindow   *window,
1398                       const gchar *title)
1399 {
1400   gint titlelen;
1401   wchar_t *wcstr;
1402   gint wlen;
1403   char *mbstr;
1404
1405   g_return_if_fail (window != NULL);
1406   g_return_if_fail (GDK_IS_WINDOW (window));
1407   
1408   GDK_NOTE (MISC, g_print ("gdk_window_set_title: %#x %s\n",
1409                            GDK_DRAWABLE_XID (window), title));
1410   if (!GDK_DRAWABLE_DESTROYED (window))
1411     {
1412       /* As the title most is in UTF-8 we must translate it
1413        * to the system codepage.
1414        */
1415       titlelen = strlen (title);
1416       wcstr = g_new (wchar_t, titlelen);
1417       mbstr = g_new (char, 3*titlelen + 1);
1418       wlen = gdk_nmbstowchar_ts (wcstr, title, titlelen, titlelen);
1419       WideCharToMultiByte (GetACP (), 0, wcstr, wlen,
1420                            mbstr, 3*titlelen, NULL, NULL);
1421
1422       if (!SetWindowText (GDK_DRAWABLE_XID (window), mbstr))
1423         g_warning ("gdk_window_set_title: SetWindowText failed");
1424
1425       g_free (mbstr);
1426       g_free (wcstr);
1427     }
1428 }
1429
1430 void          
1431 gdk_window_set_role (GdkWindow   *window,
1432                      const gchar *role)
1433 {
1434   g_return_if_fail (window != NULL);
1435   g_return_if_fail (GDK_IS_WINDOW (window));
1436   
1437   GDK_NOTE (MISC, g_print ("gdk_window_set_role: %#x %s\n",
1438                            GDK_DRAWABLE_XID (window), (role ? role : "NULL")));
1439   /* XXX */
1440 }
1441
1442 void          
1443 gdk_window_set_transient_for (GdkWindow *window, 
1444                               GdkWindow *parent)
1445 {
1446   g_return_if_fail (window != NULL);
1447   g_return_if_fail (GDK_IS_WINDOW (window));
1448   
1449   GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %#x %#x\n",
1450                            GDK_DRAWABLE_XID (window),
1451                            GDK_DRAWABLE_XID (parent)));
1452   /* XXX */
1453 }
1454
1455 void
1456 gdk_window_set_background (GdkWindow *window,
1457                            GdkColor  *color)
1458 {
1459   GdkWindowPrivate *private;
1460   
1461   g_return_if_fail (window != NULL);
1462   g_return_if_fail (GDK_IS_WINDOW (window));
1463   
1464   private = (GdkWindowPrivate*) window;
1465   if (!GDK_DRAWABLE_DESTROYED (window))
1466     {
1467       GDK_NOTE (MISC, g_print ("gdk_window_set_background: %#x %s\n",
1468                                private->drawable.xwindow, 
1469                                gdk_color_to_string (color)));
1470
1471       if (private->bg_type == GDK_WIN32_BG_PIXMAP)
1472         {
1473           if (private->bg_pixmap != NULL)
1474             {
1475               gdk_pixmap_unref (private->bg_pixmap);
1476               private->bg_pixmap = NULL;
1477             }
1478           private->bg_type = GDK_WIN32_BG_NORMAL;
1479         }
1480       private->bg_type = GDK_WIN32_BG_PIXEL;
1481       private->bg_pixel = *color;
1482     }
1483 }
1484
1485 void
1486 gdk_window_set_back_pixmap (GdkWindow *window,
1487                             GdkPixmap *pixmap,
1488                             gint       parent_relative)
1489 {
1490   GdkWindowPrivate *private;
1491
1492   g_return_if_fail (window != NULL);
1493   g_return_if_fail (GDK_IS_WINDOW (window));
1494   
1495   private = (GdkWindowPrivate*) window;
1496
1497   if (!GDK_DRAWABLE_DESTROYED (window))
1498     {
1499       if (private->bg_type == GDK_WIN32_BG_PIXMAP)
1500         {
1501           if (private->bg_pixmap != NULL)
1502             {
1503               gdk_pixmap_unref (private->bg_pixmap);
1504               private->bg_pixmap = NULL;
1505             }
1506           private->bg_type = GDK_WIN32_BG_NORMAL;
1507         }
1508       if (parent_relative)
1509         {
1510           private->bg_type = GDK_WIN32_BG_PARENT_RELATIVE;
1511         }
1512       else if (!pixmap)
1513         {
1514           
1515         }
1516       else
1517         {
1518           /* We must cache the pixmap in the WindowPrivate and
1519            * paint it each time we get WM_ERASEBKGND
1520            */
1521           private->bg_type = GDK_WIN32_BG_PIXMAP;
1522           private->bg_pixmap = pixmap;
1523           gdk_pixmap_ref (pixmap);
1524         }
1525     }
1526 }
1527
1528 void
1529 gdk_window_set_cursor (GdkWindow *window,
1530                        GdkCursor *cursor)
1531 {
1532   GdkWindowPrivate *window_private;
1533   GdkCursorPrivate *cursor_private;
1534   HCURSOR xcursor;
1535   
1536   g_return_if_fail (window != NULL);
1537   g_return_if_fail (GDK_IS_WINDOW (window));
1538   
1539   window_private = (GdkWindowPrivate*) window;
1540   cursor_private = (GdkCursorPrivate*) cursor;
1541   
1542   if (!GDK_DRAWABLE_DESTROYED (window))
1543     {
1544       if (!cursor)
1545         xcursor = LoadCursor (NULL, IDC_ARROW);
1546       else
1547         xcursor = cursor_private->xcursor;
1548
1549       GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %#x %#x\n",
1550                                window_private->drawable.xwindow, xcursor));
1551       window_private->xcursor = xcursor;
1552     }
1553 }
1554
1555 void
1556 gdk_window_get_user_data (GdkWindow *window,
1557                           gpointer  *data)
1558 {
1559   g_return_if_fail (window != NULL);
1560   
1561   *data = window->user_data;
1562 }
1563
1564 void
1565 gdk_window_get_geometry (GdkWindow *window,
1566                          gint      *x,
1567                          gint      *y,
1568                          gint      *width,
1569                          gint      *height,
1570                          gint      *depth)
1571 {
1572   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1573   
1574   if (!window)
1575     window = (GdkWindow*) gdk_root_parent;
1576   
1577   if (!GDK_DRAWABLE_DESTROYED (window))
1578     {
1579       RECT rect;
1580
1581       if (!GetClientRect (GDK_DRAWABLE_XID (window), &rect))
1582         g_warning ("gdk_window_get_geometry: GetClientRect failed");
1583
1584       if (x)
1585         *x = rect.left;
1586       if (y)
1587         *y = rect.top;
1588       if (width)
1589         *width = rect.right - rect.left;
1590       if (height)
1591         *height = rect.bottom - rect.top;
1592       if (depth)
1593         *depth = gdk_drawable_get_visual (window)->depth;
1594     }
1595 }
1596
1597 void
1598 gdk_window_get_position (GdkWindow *window,
1599                          gint      *x,
1600                          gint      *y)
1601 {
1602   GdkWindowPrivate *window_private;
1603   
1604   g_return_if_fail (window != NULL);
1605   g_return_if_fail (GDK_IS_WINDOW (window));
1606   
1607   window_private = (GdkWindowPrivate*) window;
1608   
1609   if (x)
1610     *x = window_private->x;
1611   if (y)
1612     *y = window_private->y;
1613 }
1614
1615 gint
1616 gdk_window_get_origin (GdkWindow *window,
1617                        gint      *x,
1618                        gint      *y)
1619 {
1620   gint return_val;
1621   gint tx = 0;
1622   gint ty = 0;
1623
1624   g_return_val_if_fail (window != NULL, 0);
1625
1626   if (!GDK_DRAWABLE_DESTROYED (window))
1627     {
1628       POINT pt;
1629
1630       pt.x = 0;
1631       pt.y = 0;
1632       ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
1633       tx = pt.x;
1634       ty = pt.y;
1635       return_val = 1;
1636     }
1637   else
1638     return_val = 0;
1639   
1640   if (x)
1641     *x = tx;
1642   if (y)
1643     *y = ty;
1644
1645   GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %#x: +%d+%d\n",
1646                            GDK_DRAWABLE_XID (window), tx, ty));
1647   return return_val;
1648 }
1649
1650 gboolean
1651 gdk_window_get_deskrelative_origin (GdkWindow *window,
1652                                     gint      *x,
1653                                     gint      *y)
1654 {
1655   return gdk_window_get_origin (window, x, y);
1656 }
1657
1658 void
1659 gdk_window_get_root_origin (GdkWindow *window,
1660                             gint      *x,
1661                             gint      *y)
1662 {
1663   GdkWindowPrivate *private;
1664   POINT pt;
1665
1666   g_return_if_fail (window != NULL);
1667   g_return_if_fail (GDK_IS_WINDOW (window));
1668
1669   private = (GdkWindowPrivate*) window;
1670   if (x)
1671     *x = 0;
1672   if (y)
1673     *y = 0;
1674   if (GDK_DRAWABLE_DESTROYED (window))
1675     return;
1676       
1677   while (private->parent && ((GdkWindowPrivate*) private->parent)->parent)
1678     private = (GdkWindowPrivate*) private->parent;
1679   if (private->drawable.destroyed)
1680     return;
1681
1682   pt.x = 0;
1683   pt.y = 0;
1684   ClientToScreen (private->drawable.xwindow, &pt);
1685   if (x)
1686     *x = pt.x;
1687   if (y)
1688     *y = pt.y;
1689
1690   GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %#x: (%#x) +%d+%d\n",
1691                            GDK_DRAWABLE_XID (window),
1692                            private->drawable.xwindow, 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 = (GdkWindow*) gdk_root_parent;
1709
1710   return_val = NULL;
1711   GetCursorPos (&pointc);
1712   point = pointc;
1713   ScreenToClient (GDK_DRAWABLE_XID (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_window_lookup (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 = (GdkWindow *) gdk_root_parent;
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_window_lookup (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: +%d+%d %#x%s\n",
1800                            point.x, point.y, hwnd,
1801                            (window == NULL ? " NULL" : "")));
1802
1803   return window;
1804 }
1805
1806 GdkWindow*
1807 gdk_window_get_parent (GdkWindow *window)
1808 {
1809   g_return_val_if_fail (window != NULL, NULL);
1810   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1811
1812   return ((GdkWindowPrivate*) window)->parent;
1813 }
1814
1815 GdkWindow*
1816 gdk_window_get_toplevel (GdkWindow *window)
1817 {
1818   g_return_val_if_fail (window != NULL, NULL);
1819   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1820
1821   while (GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_CHILD)
1822     window = ((GdkWindowPrivate*) window)->parent;
1823
1824   return window;
1825 }
1826
1827 GList*
1828 gdk_window_get_children (GdkWindow *window)
1829 {
1830   GdkWindowPrivate *private;
1831   GList *children;
1832
1833   g_return_val_if_fail (window != NULL, NULL);
1834   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1835
1836   if (GDK_DRAWABLE_DESTROYED (window))
1837     return NULL;
1838
1839   /* XXX ??? */
1840   g_warning ("gdk_window_get_children not implemented");
1841   children = NULL;
1842
1843   return children;
1844 }
1845
1846 GdkEventMask  
1847 gdk_window_get_events (GdkWindow *window)
1848 {
1849   GdkWindowPrivate *private;
1850
1851   g_return_val_if_fail (window != NULL, 0);
1852   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1853
1854   private = (GdkWindowPrivate*) window;
1855   if (GDK_DRAWABLE_DESTROYED (window))
1856     return 0;
1857
1858   return private->event_mask;
1859 }
1860
1861 void          
1862 gdk_window_set_events (GdkWindow   *window,
1863                        GdkEventMask event_mask)
1864 {
1865   GdkWindowPrivate *private;
1866
1867   g_return_if_fail (window != NULL);
1868   g_return_if_fail (GDK_IS_WINDOW (window));
1869
1870   private = (GdkWindowPrivate*) window;
1871   if (GDK_DRAWABLE_DESTROYED (window))
1872     return;
1873
1874   private->event_mask = event_mask;
1875 }
1876
1877 void
1878 gdk_window_add_colormap_windows (GdkWindow *window)
1879 {
1880   g_warning ("gdk_window_add_colormap_windows not implemented");
1881 }
1882
1883 void
1884 gdk_window_shape_combine_mask (GdkWindow *window,
1885                                GdkBitmap *mask,
1886                                gint x, gint y)
1887 {
1888   g_return_if_fail (window != NULL);
1889   g_return_if_fail (GDK_IS_WINDOW (window));
1890
1891   if (!mask)
1892     {
1893       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x none\n",
1894                                GDK_DRAWABLE_XID (window)));
1895       SetWindowRgn (GDK_DRAWABLE_XID (window), NULL, TRUE);
1896     }
1897   else
1898     {
1899       GdkDrawablePrivate *pixmap_private;
1900       HRGN hrgn;
1901       DWORD dwStyle;
1902       DWORD dwExStyle;
1903       RECT rect;
1904
1905       /* Convert mask bitmap to region */
1906       pixmap_private = (GdkDrawablePrivate*) mask;
1907       hrgn = BitmapToRegion (pixmap_private->xwindow);
1908
1909       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x %#x\n",
1910                                GDK_DRAWABLE_XID (window),
1911                                pixmap_private->xwindow));
1912
1913       /* SetWindowRgn wants window (not client) coordinates */ 
1914       dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
1915       dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
1916       GetClientRect (GDK_DRAWABLE_XID (window), &rect);
1917       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1918       OffsetRgn (hrgn, -rect.left, -rect.top);
1919
1920       OffsetRgn (hrgn, x, y);
1921
1922       /* If this is a top-level window, add the title bar to the region */
1923       if (GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_TOPLEVEL)
1924         {
1925           CombineRgn (hrgn, hrgn,
1926                       CreateRectRgn (0, 0, rect.right - rect.left, -rect.top),
1927                       RGN_OR);
1928         }
1929       
1930       SetWindowRgn (GDK_DRAWABLE_XID (window), hrgn, TRUE);
1931     }
1932 }
1933
1934 void          
1935 gdk_window_add_filter (GdkWindow     *window,
1936                        GdkFilterFunc  function,
1937                        gpointer       data)
1938 {
1939   GdkWindowPrivate *private;
1940   GList *tmp_list;
1941   GdkEventFilter *filter;
1942   
1943   g_return_if_fail (window != NULL);
1944   g_return_if_fail (GDK_IS_WINDOW (window));
1945
1946   private = (GdkWindowPrivate*) window;
1947   if (private && GDK_DRAWABLE_DESTROYED (window))
1948     return;
1949   
1950   tmp_list = private->filters;
1951   
1952   while (tmp_list)
1953     {
1954       filter = (GdkEventFilter *)tmp_list->data;
1955       if ((filter->function == function) && (filter->data == data))
1956         return;
1957       tmp_list = tmp_list->next;
1958     }
1959   
1960   filter = g_new (GdkEventFilter, 1);
1961   filter->function = function;
1962   filter->data = data;
1963   
1964   private->filters = g_list_append (private->filters, filter);
1965 }
1966
1967 void
1968 gdk_window_remove_filter (GdkWindow     *window,
1969                           GdkFilterFunc  function,
1970                           gpointer       data)
1971 {
1972   GdkWindowPrivate *private;
1973   GList *tmp_list, *node;
1974   GdkEventFilter *filter;
1975   
1976   g_return_if_fail (window != NULL);
1977   g_return_if_fail (GDK_IS_WINDOW (window));
1978
1979   private = (GdkWindowPrivate*) window;
1980   
1981   tmp_list = private->filters;
1982   
1983   while (tmp_list)
1984     {
1985       filter = (GdkEventFilter *)tmp_list->data;
1986       node = tmp_list;
1987       tmp_list = tmp_list->next;
1988       
1989       if ((filter->function == function) && (filter->data == data))
1990         {
1991           private->filters = g_list_remove_link (private->filters, node);
1992
1993           g_list_free_1 (node);
1994           g_free (filter);
1995           
1996           return;
1997         }
1998     }
1999 }
2000
2001 void
2002 gdk_window_set_override_redirect (GdkWindow *window,
2003                                   gboolean   override_redirect)
2004 {
2005   g_return_if_fail (window != NULL);
2006   g_return_if_fail (GDK_IS_WINDOW (window));
2007
2008   g_warning ("gdk_window_set_override_redirect not implemented");
2009 }
2010
2011 void          
2012 gdk_window_set_icon (GdkWindow *window, 
2013                      GdkWindow *icon_window,
2014                      GdkPixmap *pixmap,
2015                      GdkBitmap *mask)
2016 {
2017   g_return_if_fail (window != NULL);
2018   g_return_if_fail (GDK_IS_WINDOW (window));
2019
2020   if (GDK_DRAWABLE_DESTROYED (window))
2021     return;
2022   
2023   g_warning ("gdk_window_set_icon not implemented");
2024 }
2025
2026 void
2027 gdk_window_set_icon_name (GdkWindow *window, 
2028                           gchar     *name)
2029 {
2030   g_return_if_fail (window != NULL);
2031   g_return_if_fail (GDK_IS_WINDOW (window));
2032
2033   if (GDK_DRAWABLE_DESTROYED (window))
2034     return;
2035   
2036   if (!SetWindowText (GDK_DRAWABLE_XID (window), name))
2037     g_warning ("gdk_window_set_icon_name: SetWindowText failed");
2038 }
2039
2040 void          
2041 gdk_window_set_group (GdkWindow *window, 
2042                       GdkWindow *leader)
2043 {
2044   g_return_if_fail (window != NULL);
2045   g_return_if_fail (GDK_IS_WINDOW (window));
2046   g_return_if_fail (leader != NULL);
2047   g_return_if_fail (GDK_IS_WINDOW (leader));
2048
2049   if (GDK_DRAWABLE_DESTROYED (window) || GDK_DRAWABLE_DESTROYED (leader))
2050     return;
2051   
2052   g_warning ("gdk_window_set_group not implemented");
2053 }
2054
2055 void
2056 gdk_window_set_decorations (GdkWindow      *window,
2057                             GdkWMDecoration decorations)
2058 {
2059   LONG style, exstyle;
2060
2061   g_return_if_fail (window != NULL);
2062   g_return_if_fail (GDK_IS_WINDOW (window));
2063   
2064   style = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
2065   exstyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
2066
2067   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2068             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE);
2069
2070   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2071
2072   if (decorations & GDK_DECOR_ALL)
2073     style |= (WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2074   if (decorations & GDK_DECOR_BORDER)
2075     style |= (WS_BORDER);
2076   if (decorations & GDK_DECOR_RESIZEH)
2077     style |= (WS_THICKFRAME);
2078   if (decorations & GDK_DECOR_TITLE)
2079     style |= (WS_CAPTION);
2080   if (decorations & GDK_DECOR_MENU)
2081     style |= (WS_SYSMENU);
2082   if (decorations & GDK_DECOR_MINIMIZE)
2083     style |= (WS_MINIMIZEBOX);
2084   if (decorations & GDK_DECOR_MAXIMIZE)
2085     style |= (WS_MAXIMIZEBOX);
2086   
2087   SetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE, style);
2088 }
2089
2090 void
2091 gdk_window_set_functions (GdkWindow    *window,
2092                           GdkWMFunction functions)
2093 {
2094   LONG style, exstyle;
2095
2096   g_return_if_fail (window != NULL);
2097   g_return_if_fail (GDK_IS_WINDOW (window));
2098   
2099   style = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
2100   exstyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
2101
2102   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2103             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE|WS_CAPTION|WS_BORDER
2104             |WS_SYSMENU);
2105
2106   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2107
2108   if (functions & GDK_FUNC_ALL)
2109     style |= (WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2110   if (functions & GDK_FUNC_RESIZE)
2111     style |= (WS_THICKFRAME);
2112   if (functions & GDK_FUNC_MOVE)
2113     style |= (WS_THICKFRAME);
2114   if (functions & GDK_FUNC_MINIMIZE)
2115     style |= (WS_MINIMIZEBOX);
2116   if (functions & GDK_FUNC_MAXIMIZE)
2117     style |= (WS_MAXIMIZEBOX);
2118   
2119   SetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE, style);
2120 }
2121
2122 GList *
2123 gdk_window_get_toplevels (void)
2124 {
2125   GList *new_list = NULL;
2126   GList *tmp_list;
2127
2128   tmp_list = gdk_root_parent->children;
2129   while (tmp_list)
2130     {
2131       new_list = g_list_prepend (new_list, tmp_list->data);
2132       tmp_list = tmp_list->next;
2133     }
2134
2135   return new_list;
2136 }
2137
2138 /* 
2139  * propagate the shapes from all child windows of a GDK window to the parent 
2140  * window. Shamelessly ripped from Enlightenment's code
2141  * 
2142  * - Raster
2143  */
2144
2145 static void
2146 QueryTree (HWND hwnd,
2147            HWND **children,
2148            gint *nchildren)
2149 {
2150   guint i, n;
2151   HWND child;
2152
2153   n = 0;
2154   do {
2155     if (n == 0)
2156       child = GetWindow (hwnd, GW_CHILD);
2157     else
2158       child = GetWindow (child, GW_HWNDNEXT);
2159     if (child != NULL)
2160       n++;
2161   } while (child != NULL);
2162
2163   if (n > 0)
2164     {
2165       *children = g_new (HWND, n);
2166       for (i = 0; i < n; i++)
2167         {
2168           if (i == 0)
2169             child = GetWindow (hwnd, GW_CHILD);
2170           else
2171             child = GetWindow (child, GW_HWNDNEXT);
2172           *children[i] = child;
2173         }
2174     }
2175 }
2176
2177 static void
2178 gdk_propagate_shapes (HANDLE   win,
2179                       gboolean merge)
2180 {
2181    RECT emptyRect;
2182    HRGN region, childRegion;
2183    RECT rect;
2184    HWND *list = NULL;
2185    gint i, num;
2186
2187    SetRectEmpty (&emptyRect);
2188    region = CreateRectRgnIndirect (&emptyRect);
2189    if (merge)
2190      GetWindowRgn (win, region);
2191    
2192    QueryTree (win, &list, &num);
2193    if (list != NULL)
2194      {
2195        WINDOWPLACEMENT placement;
2196
2197        placement.length = sizeof (WINDOWPLACEMENT);
2198        /* go through all child windows and combine regions */
2199        for (i = 0; i < num; i++)
2200          {
2201            GetWindowPlacement (list[i], &placement);
2202            if (placement.showCmd = SW_SHOWNORMAL)
2203              {
2204                childRegion = CreateRectRgnIndirect (&emptyRect);
2205                GetWindowRgn (list[i], childRegion);
2206                CombineRgn (region, region, childRegion, RGN_OR);
2207                DeleteObject (childRegion);
2208              }
2209           }
2210        SetWindowRgn (win, region, TRUE);
2211      }
2212    else
2213      DeleteObject (region);
2214 }
2215
2216 void
2217 gdk_window_set_child_shapes (GdkWindow *window)
2218 {
2219   g_return_if_fail (window != NULL);
2220   g_return_if_fail (GDK_IS_WINDOW (window));
2221    
2222   if (GDK_DRAWABLE_DESTROYED (window))
2223     return;
2224
2225   gdk_propagate_shapes (GDK_DRAWABLE_XID (window), FALSE);
2226 }
2227
2228 void
2229 gdk_window_merge_child_shapes (GdkWindow *window)
2230 {
2231   g_return_if_fail (window != NULL);
2232   g_return_if_fail (GDK_IS_WINDOW (window));
2233   
2234   if (GDK_DRAWABLE_DESTROYED (window))
2235     return;
2236
2237   gdk_propagate_shapes (GDK_DRAWABLE_XID (window), TRUE);
2238 }
2239
2240 /*************************************************************
2241  * gdk_window_is_visible:
2242  *     Check if the given window is mapped.
2243  *   arguments:
2244  *     window: 
2245  *   results:
2246  *     is the window mapped
2247  *************************************************************/
2248
2249 gboolean 
2250 gdk_window_is_visible (GdkWindow *window)
2251 {
2252   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2253
2254   g_return_val_if_fail (window != NULL, FALSE);
2255   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2256
2257   return private->mapped;
2258 }
2259
2260 /*************************************************************
2261  * gdk_window_is_viewable:
2262  *     Check if the window and all ancestors of the window
2263  *     are mapped. (This is not necessarily "viewable" in
2264  *     the X sense, since we only check as far as we have
2265  *     GDK window parents, not to the root window)
2266  *   arguments:
2267  *     window:
2268  *   results:
2269  *     is the window viewable
2270  *************************************************************/
2271
2272 gboolean 
2273 gdk_window_is_viewable (GdkWindow *window)
2274 {
2275   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2276
2277   g_return_val_if_fail (window != NULL, FALSE);
2278   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2279
2280   while (private && 
2281          (private != gdk_root_parent) &&
2282          (private->drawable.window_type != GDK_WINDOW_FOREIGN))
2283     {
2284       if (!private->mapped)
2285         return FALSE;
2286
2287       private = (GdkWindowPrivate *)private->parent;
2288     }
2289
2290   return TRUE;
2291 }
2292
2293 /* Support for windows that can be guffaw-scrolled
2294  * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
2295  */
2296
2297 static gboolean
2298 gdk_window_gravity_works (void)
2299 {
2300   enum { UNKNOWN, NO, YES };
2301   static gint gravity_works = UNKNOWN;
2302   
2303   if (gravity_works == UNKNOWN)
2304     {
2305       GdkWindowAttr attr;
2306       GdkWindow *parent;
2307       GdkWindow *child;
2308       gint y;
2309       
2310       attr.window_type = GDK_WINDOW_TEMP;
2311       attr.wclass = GDK_INPUT_OUTPUT;
2312       attr.x = 0;
2313       attr.y = 0;
2314       attr.width = 100;
2315       attr.height = 100;
2316       attr.event_mask = 0;
2317       
2318       parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
2319       
2320       attr.window_type = GDK_WINDOW_CHILD;
2321       child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
2322       
2323       gdk_window_set_static_win_gravity (child, TRUE);
2324       
2325       gdk_window_resize (parent, 100, 110);
2326       gdk_window_move (parent, 0, -10);
2327       gdk_window_move_resize (parent, 0, 0, 100, 100);
2328       
2329       gdk_window_resize (parent, 100, 110);
2330       gdk_window_move (parent, 0, -10);
2331       gdk_window_move_resize (parent, 0, 0, 100, 100);
2332       
2333       gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
2334       
2335       gdk_window_destroy (parent);
2336       gdk_window_destroy (child);
2337       
2338       gravity_works = ((y == -20) ? YES : NO);
2339     }
2340   
2341   return (gravity_works == YES);
2342 }
2343
2344 static void
2345 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
2346 {
2347   g_return_if_fail (window != NULL);
2348
2349   GDK_NOTE (MISC, g_print ("gdk_window_set_static_bit_gravity: Not implemented\n"));
2350 }
2351
2352 static void
2353 gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
2354 {
2355   g_return_if_fail (window != NULL);
2356
2357   GDK_NOTE (MISC,
2358             g_print ("gdk_window_set_static_win_gravity: Not implemented\n"));
2359 }
2360
2361 /*************************************************************
2362  * gdk_window_set_static_gravities:
2363  *     Set the bit gravity of the given window to static,
2364  *     and flag it so all children get static subwindow
2365  *     gravity.
2366  *   arguments:
2367  *     window: window for which to set static gravity
2368  *     use_static: Whether to turn static gravity on or off.
2369  *   results:
2370  *     Does the XServer support static gravity?
2371  *************************************************************/
2372
2373 gboolean 
2374 gdk_window_set_static_gravities (GdkWindow *window,
2375                                  gboolean   use_static)
2376 {
2377   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2378   GList *tmp_list;
2379   
2380   g_return_val_if_fail (window != NULL, FALSE);
2381   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2382
2383   if (!use_static == !private->guffaw_gravity)
2384     return TRUE;
2385   
2386   if (use_static && !gdk_window_gravity_works ())
2387     return FALSE;
2388   
2389   private->guffaw_gravity = use_static;
2390   
2391   if (!GDK_DRAWABLE_DESTROYED (window))
2392     {
2393       gdk_window_set_static_bit_gravity (window, use_static);
2394       
2395       tmp_list = private->children;
2396       while (tmp_list)
2397         {
2398           gdk_window_set_static_win_gravity (window, use_static);
2399           
2400           tmp_list = tmp_list->next;
2401         }
2402     }
2403   
2404   return TRUE;
2405 }