]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow-win32.c
re-adding for manual rename of repository files.
[~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 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 + 1);
425   mbtitle = g_new (char, 3*titlelen + 1);
426   wlen = gdk_nmbstowchar_ts (wctitle, title, titlelen, titlelen);
427   wctitle[wlen] = 0;
428   WideCharToMultiByte (GetACP (), 0, wctitle, -1,
429                        mbtitle, 3*titlelen, NULL, NULL);
430   
431   private->drawable.xwindow =
432     CreateWindowEx (dwExStyle,
433                     MAKEINTRESOURCE(klass),
434                     mbtitle,
435                     dwStyle,
436                     x, y, 
437                     width, height,
438                     xparent,
439                     NULL,
440                     gdk_ProgInstance,
441                     NULL);
442
443   GDK_NOTE (MISC,
444             g_print ("gdk_window_create: %s %s %dx%d@+%d+%d %#x = %#x\n"
445                      "...locale %#x codepage %d\n",
446                      (private->drawable.window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
447                       (private->drawable.window_type == GDK_WINDOW_CHILD ? "CHILD" :
448                        (private->drawable.window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
449                         (private->drawable.window_type == GDK_WINDOW_TEMP ? "TEMP" :
450                          "???")))),
451                      mbtitle,
452                      width, height, (x == CW_USEDEFAULT ? -9999 : x), y, 
453                      xparent,
454                      private->drawable.xwindow,
455                      private->input_locale,
456                      private->charset_info.ciACP));
457
458   g_free (mbtitle);
459   g_free (wctitle);
460
461   if (private->drawable.xwindow == NULL)
462     {
463       g_warning ("gdk_window_create: CreateWindowEx failed");
464       g_free (private);
465       return NULL;
466     }
467
468   gdk_window_ref (window);
469   gdk_xid_table_insert (&private->drawable.xwindow, window);
470
471   if (private->drawable.colormap)
472     gdk_colormap_ref (private->drawable.colormap);
473
474   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
475                                   (attributes->cursor) :
476                                   NULL));
477
478   return window;
479 }
480
481 GdkWindow *
482 gdk_window_foreign_new (guint32 anid)
483 {
484   GdkWindow *window;
485   GdkWindowPrivate *private;
486   GdkWindowPrivate *parent_private;
487   HANDLE parent;
488   RECT rect;
489   POINT point;
490
491   private = g_new (GdkWindowPrivate, 1);
492   window = (GdkWindow*) private;
493
494   parent = GetParent ((HWND) anid);
495   private->parent = gdk_xid_table_lookup (parent);
496
497   parent_private = (GdkWindowPrivate *)private->parent;
498   
499   if (parent_private)
500     parent_private->children = g_list_prepend (parent_private->children, window);
501
502   private->drawable.xwindow = (HWND) anid;
503   GetClientRect ((HWND) anid, &rect);
504   point.x = rect.left;
505   point.y = rect.right;
506   ClientToScreen ((HWND) anid, &point);
507   if (parent != GetDesktopWindow ())
508     ScreenToClient (parent, &point);
509   private->x = point.x;
510   private->y = point.y;
511   private->drawable.width = rect.right - rect.left;
512   private->drawable.height = rect.bottom - rect.top;
513   private->resize_count = 0;
514   private->drawable.ref_count = 1;
515   private->drawable.window_type = GDK_WINDOW_FOREIGN;
516   private->drawable.destroyed = FALSE;
517   private->mapped = IsWindowVisible (private->drawable.xwindow);
518   private->guffaw_gravity = FALSE;
519   private->extension_events = 0;
520   private->extension_events_selected = FALSE;
521
522   private->drawable.colormap = NULL;
523
524   private->filters = NULL;
525   private->children = NULL;
526
527   window->user_data = NULL;
528
529   gdk_window_ref (window);
530   gdk_xid_table_insert (&private->drawable.xwindow, window);
531
532   return window;
533 }
534
535 /* Call this function when you want a window and all its children to
536  * disappear.  When xdestroy is true, a request to destroy the XWindow
537  * is sent out.  When it is false, it is assumed that the XWindow has
538  * been or will be destroyed by destroying some ancestor of this
539  * window.
540  */
541 static void
542 gdk_window_internal_destroy (GdkWindow *window,
543                              gboolean   xdestroy,
544                              gboolean   our_destroy)
545 {
546   GdkWindowPrivate *private;
547   GdkWindowPrivate *temp_private;
548   GdkWindow *temp_window;
549   GList *children;
550   GList *tmp;
551
552   g_return_if_fail (window != NULL);
553
554   private = (GdkWindowPrivate*) window;
555
556   GDK_NOTE (MISC, g_print ("gdk_window_internal_destroy %#x\n",
557                            private->drawable.xwindow));
558
559   switch (private->drawable.window_type)
560     {
561     case GDK_WINDOW_TOPLEVEL:
562     case GDK_WINDOW_CHILD:
563     case GDK_WINDOW_DIALOG:
564     case GDK_WINDOW_TEMP:
565     case GDK_WINDOW_FOREIGN:
566       if (!private->drawable.destroyed)
567         {
568           if (private->parent)
569             {
570               GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
571               if (parent_private->children)
572                 parent_private->children = g_list_remove (parent_private->children, window);
573             }
574
575           if (GDK_DRAWABLE_TYPE (window) != GDK_WINDOW_FOREIGN)
576             {
577               children = tmp = private->children;
578               private->children = NULL;
579
580               while (tmp)
581                 {
582                   temp_window = tmp->data;
583                   tmp = tmp->next;
584                   
585                   temp_private = (GdkWindowPrivate*) temp_window;
586                   if (temp_private)
587                     gdk_window_internal_destroy (temp_window, FALSE,
588                                                  our_destroy);
589                 }
590
591               g_list_free (children);
592             }
593
594           if (private->extension_events != 0)
595             gdk_input_window_destroy (window);
596
597           if (private->filters)
598             {
599               tmp = private->filters;
600
601               while (tmp)
602                 {
603                   g_free (tmp->data);
604                   tmp = tmp->next;
605                 }
606
607               g_list_free (private->filters);
608               private->filters = NULL;
609             }
610           
611           if (private->drawable.window_type == GDK_WINDOW_FOREIGN)
612             {
613               if (our_destroy && (private->parent != NULL))
614                 {
615                   /* It's somebody elses window, but in our hierarchy,
616                    * so reparent it to the root window, and then send
617                    * it a delete event, as if we were a WM
618                    */
619                   gdk_window_hide (window);
620                   gdk_window_reparent (window, NULL, 0, 0);
621                   
622                   /* Is this too drastic? Many (most?) applications
623                    * quit if any window receives WM_QUIT I think.
624                    * OTOH, I don't think foreign windows are much
625                    * used, so the question is maybe academic.
626                    */
627                   PostMessage (private->drawable.xwindow, WM_QUIT, 0, 0);
628                 }
629             }
630           else if (xdestroy)
631             DestroyWindow (private->drawable.xwindow);
632
633           if (private->drawable.colormap)
634             gdk_colormap_unref (private->drawable.colormap);
635
636           private->mapped = FALSE;
637           private->drawable.destroyed = TRUE;
638         }
639       break;
640
641     case GDK_WINDOW_ROOT:
642       g_error ("attempted to destroy root window");
643       break;
644
645     case GDK_DRAWABLE_PIXMAP:
646       g_error ("called gdk_window_destroy on a pixmap (use gdk_pixmap_unref)");
647       break;
648     }
649 }
650
651 /* Like internal_destroy, but also destroys the reference created by
652    gdk_window_new. */
653
654 void
655 gdk_window_destroy (GdkWindow *window)
656 {
657   gdk_window_internal_destroy (window, TRUE, TRUE);
658   gdk_window_unref (window);
659 }
660
661 /* This function is called when the XWindow is really gone.  */
662
663 void
664 gdk_window_destroy_notify (GdkWindow *window)
665 {
666   g_return_if_fail (window != NULL);
667
668   GDK_NOTE (EVENTS, g_print ("gdk_window_destroy_notify: %#x  %d\n",
669                              GDK_DRAWABLE_XID (window), GDK_DRAWABLE_DESTROYED (window)));
670
671   if (!GDK_DRAWABLE_DESTROYED (window))
672     {
673       if (GDK_DRAWABLE_TYPE(window) != GDK_WINDOW_FOREIGN)
674         g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_DRAWABLE_XID (window));
675
676       gdk_window_internal_destroy (window, FALSE, FALSE);
677     }
678   
679   gdk_xid_table_remove (GDK_DRAWABLE_XID (window));
680   gdk_window_unref (window);
681 }
682
683 GdkWindow*
684 gdk_window_ref (GdkWindow *window)
685 {
686   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
687   g_return_val_if_fail (window != NULL, NULL);
688   
689   private->drawable.ref_count += 1;
690
691   GDK_NOTE (MISC, g_print ("gdk_window_ref %#x %d\n",
692                            GDK_DRAWABLE_XID (window),
693                            private->drawable.ref_count));
694
695   return window;
696 }
697
698 void
699 gdk_window_unref (GdkWindow *window)
700 {
701   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
702   g_return_if_fail (window != NULL);
703
704   private->drawable.ref_count -= 1;
705
706   GDK_NOTE (MISC, g_print ("gdk_window_unref %#x %d%s\n",
707                            private->drawable.xwindow,
708                            private->drawable.ref_count,
709                            (private->drawable.ref_count == 0 ? " freeing" : "")));
710
711   if (private->drawable.ref_count == 0)
712     {
713       if (private->bg_type == GDK_WIN32_BG_PIXMAP
714           && private->bg_pixmap != NULL)
715         gdk_pixmap_unref (private->bg_pixmap);
716
717       if (!private->drawable.destroyed)
718         {
719           if (private->drawable.window_type == GDK_WINDOW_FOREIGN)
720             gdk_xid_table_remove (private->drawable.xwindow);
721           else
722             g_warning ("losing last reference to undestroyed window");
723         }
724       g_dataset_destroy (window);
725       g_free (window);
726     }
727 }
728
729 void
730 gdk_window_show (GdkWindow *window)
731 {
732   GdkWindowPrivate *private;
733
734   g_return_if_fail (window != NULL);
735
736   private = (GdkWindowPrivate*) window;
737   if (!private->drawable.destroyed)
738     {
739       GDK_NOTE (MISC, g_print ("gdk_window_show: %#x\n",
740                                private->drawable.xwindow));
741
742       private->mapped = TRUE;
743       if (private->drawable.window_type == GDK_WINDOW_TEMP)
744         {
745           ShowWindow (private->drawable.xwindow, SW_SHOWNOACTIVATE);
746           SetWindowPos (private->drawable.xwindow, HWND_TOPMOST, 0, 0, 0, 0,
747                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
748 #if 0
749           ShowWindow (private->drawable.xwindow, SW_HIDE); /* Don't put on toolbar */
750 #endif
751         }
752       else
753         {
754           ShowWindow (private->drawable.xwindow, SW_SHOWNORMAL);
755           ShowWindow (private->drawable.xwindow, SW_RESTORE);
756           SetForegroundWindow (private->drawable.xwindow);
757           BringWindowToTop (private->drawable.xwindow);
758 #if 0
759           ShowOwnedPopups (private->drawable.xwindow, TRUE);
760 #endif
761         }
762     }
763 }
764
765 void
766 gdk_window_hide (GdkWindow *window)
767 {
768   GdkWindowPrivate *private;
769
770   g_return_if_fail (window != NULL);
771
772   private = (GdkWindowPrivate*) window;
773   if (!private->drawable.destroyed)
774     {
775       GDK_NOTE (MISC, g_print ("gdk_window_hide: %#x\n",
776                                private->drawable.xwindow));
777
778       private->mapped = FALSE;
779       if (private->drawable.window_type == GDK_WINDOW_TOPLEVEL)
780         ShowOwnedPopups (private->drawable.xwindow, FALSE);
781 #if 1
782       ShowWindow (private->drawable.xwindow, SW_HIDE);
783 #elif 0
784       ShowWindow (private->drawable.xwindow, SW_MINIMIZE);
785 #else
786       CloseWindow (private->drawable.xwindow);
787 #endif
788     }
789 }
790
791 void
792 gdk_window_withdraw (GdkWindow *window)
793 {
794   GdkWindowPrivate *private;
795
796   g_return_if_fail (window != NULL);
797
798   private = (GdkWindowPrivate*) window;
799   if (!private->drawable.destroyed)
800     {
801       GDK_NOTE (MISC, g_print ("gdk_window_withdraw: %#x\n",
802                                private->drawable.xwindow));
803
804       gdk_window_hide (window); /* XXX */
805     }
806 }
807
808 void
809 gdk_window_move (GdkWindow *window,
810                  gint       x,
811                  gint       y)
812 {
813   GdkWindowPrivate *private;
814
815   g_return_if_fail (window != NULL);
816
817   private = (GdkWindowPrivate*) window;
818   if (!private->drawable.destroyed)
819     {
820       RECT rect;
821
822       GDK_NOTE (MISC, g_print ("gdk_window_move: %#x +%d+%d\n",
823                                private->drawable.xwindow, x, y));
824
825       GetClientRect (private->drawable.xwindow, &rect);
826
827       if (private->drawable.window_type != GDK_WINDOW_CHILD)
828         {
829           POINT ptTL, ptBR;
830           DWORD dwStyle;
831           DWORD dwExStyle;
832
833           ptTL.x = 0;
834           ptTL.y = 0; 
835           ClientToScreen (private->drawable.xwindow, &ptTL);
836           rect.left = x;
837           rect.top = y;
838
839           ptBR.x = rect.right;
840           ptBR.y = rect.bottom;
841           ClientToScreen (private->drawable.xwindow, &ptBR);
842           rect.right = x + ptBR.x - ptTL.x;
843           rect.bottom = y + ptBR.y - ptTL.y;
844
845           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
846           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
847           if (!SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
848             g_warning ("gdk_window_move: AdjustWindowRectEx failed");
849
850           x = rect.left;
851           y = rect.top;
852         }
853       else
854         {
855           private->x = x;
856           private->y = y;
857         }
858       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
859                                private->drawable.xwindow,
860                                rect.right - rect.left, rect.bottom - rect.top,
861                                x, y));
862       if (!MoveWindow (private->drawable.xwindow,
863                        x, y, rect.right - rect.left, rect.bottom - rect.top,
864                        TRUE))
865         g_warning ("gdk_window_move: MoveWindow failed");
866     }
867 }
868
869 void
870 gdk_window_resize (GdkWindow *window,
871                    gint       width,
872                    gint       height)
873 {
874   GdkWindowPrivate *private;
875
876   g_return_if_fail (window != NULL);
877
878   if ((gint16) width < 1)
879     width = 1;
880   if ((gint16) height < 1)
881     height = 1;
882
883   private = (GdkWindowPrivate*) window;
884
885   if (!private->drawable.destroyed &&
886       ((private->resize_count > 0) ||
887        (private->drawable.width != (guint16) width) ||
888        (private->drawable.height != (guint16) height)))
889     {
890       int x, y;
891
892       GDK_NOTE (MISC, g_print ("gdk_window_resize: %#x %dx%d\n",
893                                private->drawable.xwindow, width, height));
894       
895       if (private->drawable.window_type != GDK_WINDOW_CHILD)
896         {
897           POINT pt;
898           RECT rect;
899           DWORD dwStyle;
900           DWORD dwExStyle;
901
902           pt.x = 0;
903           pt.y = 0; 
904           ClientToScreen (private->drawable.xwindow, &pt);
905           rect.left = pt.x;
906           rect.top = pt.y;
907           rect.right = pt.x + width;
908           rect.bottom = pt.y + height;
909
910           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
911           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
912           if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
913             g_warning ("gdk_window_resize: AdjustWindowRectEx failed");
914
915           x = rect.left;
916           y = rect.top;
917           width = rect.right - rect.left;
918           height = rect.bottom - rect.top;
919         }
920       else
921         {
922           x = private->x;
923           y = private->y;
924           private->drawable.width = width;
925           private->drawable.height = height;
926         }
927
928       private->resize_count += 1;
929
930       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
931                                private->drawable.xwindow, width, height, x, y));
932       if (!MoveWindow (private->drawable.xwindow,
933                        x, y, width, height,
934                        TRUE))
935         g_warning ("gdk_window_resize: MoveWindow failed");
936     }
937 }
938
939 void
940 gdk_window_move_resize (GdkWindow *window,
941                         gint       x,
942                         gint       y,
943                         gint       width,
944                         gint       height)
945 {
946   GdkWindowPrivate *private;
947
948   g_return_if_fail (window != NULL);
949
950   if ((gint16) width < 1)
951     width = 1;
952   if ((gint16) height < 1)
953     height = 1;
954
955   private = (GdkWindowPrivate*) window;
956   if (!private->drawable.destroyed)
957     {
958       RECT rect;
959       DWORD dwStyle;
960       DWORD dwExStyle;
961
962       GDK_NOTE (MISC, g_print ("gdk_window_move_resize: %#x %dx%d@+%d+%d\n",
963                                private->drawable.xwindow, width, height, x, y));
964       
965       rect.left = x;
966       rect.top = y;
967       rect.right = x + width;
968       rect.bottom = y + height;
969
970       dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
971       dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
972       if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
973         g_warning ("gdk_window_move_resize: AdjustWindowRectEx failed");
974
975       if (private->drawable.window_type == GDK_WINDOW_CHILD)
976         {
977           private->x = x;
978           private->y = y;
979           private->drawable.width = width;
980           private->drawable.height = height;
981         }
982       GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
983                                private->drawable.xwindow,
984                                rect.right - rect.left, rect.bottom - rect.top,
985                                rect.left, rect.top));
986       if (!MoveWindow (private->drawable.xwindow,
987                        rect.left, rect.top,
988                        rect.right - rect.left, rect.bottom - rect.top,
989                        TRUE))
990         g_warning ("gdk_window_move_resize: MoveWindow failed");
991
992       if (private->guffaw_gravity)
993         {
994           GList *tmp_list = private->children;
995           while (tmp_list)
996             {
997               GdkWindowPrivate *child_private = tmp_list->data;
998               
999               child_private->x -= x - private->x;
1000               child_private->y -= y - private->y;
1001               
1002               tmp_list = tmp_list->next;
1003             }
1004         }
1005       
1006     }
1007 }
1008
1009 void
1010 gdk_window_reparent (GdkWindow *window,
1011                      GdkWindow *new_parent,
1012                      gint       x,
1013                      gint       y)
1014 {
1015   GdkWindowPrivate *window_private;
1016   GdkWindowPrivate *parent_private;
1017   GdkWindowPrivate *old_parent_private;
1018
1019   g_return_if_fail (window != NULL);
1020
1021   if (!new_parent)
1022     new_parent = (GdkWindow*) gdk_root_parent;
1023
1024   window_private = (GdkWindowPrivate*) window;
1025   old_parent_private = (GdkWindowPrivate*)window_private->parent;
1026   parent_private = (GdkWindowPrivate*) new_parent;
1027
1028   if (!window_private->drawable.destroyed && !parent_private->drawable.destroyed)
1029     {
1030       GDK_NOTE (MISC, g_print ("gdk_window_reparent: %#x %#x\n",
1031                                window_private->drawable.xwindow,
1032                                parent_private->drawable.xwindow));
1033       if (!SetParent (window_private->drawable.xwindow, parent_private->drawable.xwindow))
1034         g_warning ("gdk_window_reparent: SetParent failed");
1035
1036       if (!MoveWindow (window_private->drawable.xwindow,
1037                        x, y,
1038                        window_private->drawable.width, window_private->drawable.height,
1039                        TRUE))
1040         g_warning ("gdk_window_reparent: MoveWindow failed");
1041     }
1042   
1043   window_private->parent = new_parent;
1044
1045   if (old_parent_private)
1046     old_parent_private->children = g_list_remove (old_parent_private->children, window);
1047
1048   if ((old_parent_private &&
1049        (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
1050       (!old_parent_private && parent_private->guffaw_gravity))
1051     gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
1052   
1053   parent_private->children = g_list_prepend (parent_private->children, window);
1054 }
1055
1056 void
1057 gdk_window_clear (GdkWindow *window)
1058 {
1059   g_return_if_fail (window != NULL);
1060   g_return_if_fail (GDK_IS_WINDOW (window));
1061
1062   if (!GDK_DRAWABLE_DESTROYED (window))
1063     gdk_window_clear_area (window, 0, 0, -1, -1);
1064 }
1065
1066
1067 void
1068 gdk_window_clear_area (GdkWindow *window,
1069                        gint       x,
1070                        gint       y,
1071                        gint       width,
1072                        gint       height)
1073 {
1074   g_return_if_fail (window != NULL);
1075   g_return_if_fail (GDK_IS_WINDOW (window));
1076   
1077   if (!GDK_DRAWABLE_DESTROYED (window))
1078     {
1079       HDC hdc;
1080
1081       if (width == -1)
1082         width = G_MAXSHORT/2;           /* Yeah, right */
1083       if (height == -1)
1084         height = G_MAXSHORT/2;
1085       GDK_NOTE (MISC, g_print ("gdk_window_clear_area: %#x %dx%d@+%d+%d\n",
1086                                GDK_DRAWABLE_XID (window), width, height, x, y));
1087       hdc = GetDC (GDK_DRAWABLE_XID (window));
1088       IntersectClipRect (hdc, x, y, x + width, y + height);
1089       SendMessage (GDK_DRAWABLE_XID (window), WM_ERASEBKGND, (WPARAM) hdc, 0);
1090       ReleaseDC (GDK_DRAWABLE_XID (window), hdc);
1091     }
1092 }
1093
1094 void
1095 gdk_window_clear_area_e (GdkWindow *window,
1096                          gint       x,
1097                          gint       y,
1098                          gint       width,
1099                          gint       height)
1100 {
1101   g_return_if_fail (window != NULL);
1102   g_return_if_fail (GDK_IS_WINDOW (window));
1103   
1104   if (!GDK_DRAWABLE_DESTROYED (window))
1105     {
1106       RECT rect;
1107
1108       GDK_NOTE (MISC, g_print ("gdk_window_clear_area_e: %#x %dx%d@+%d+%d\n",
1109                                GDK_DRAWABLE_XID (window), width, height, x, y));
1110
1111       rect.left = x;
1112       rect.right = x + width;
1113       rect.top = y;
1114       rect.bottom = y + height;
1115       if (!InvalidateRect (GDK_DRAWABLE_XID (window), &rect, TRUE))
1116         g_warning ("gdk_window_clear_area_e: InvalidateRect failed");
1117       UpdateWindow (GDK_DRAWABLE_XID (window));
1118     }
1119 }
1120
1121 void
1122 gdk_window_raise (GdkWindow *window)
1123 {
1124   g_return_if_fail (window != NULL);
1125   g_return_if_fail (GDK_IS_WINDOW (window));
1126   
1127   if (!GDK_DRAWABLE_DESTROYED (window))
1128     {
1129       GDK_NOTE (MISC, g_print ("gdk_window_raise: %#x\n",
1130                                GDK_DRAWABLE_XID (window)));
1131
1132       if (!BringWindowToTop (GDK_DRAWABLE_XID (window)))
1133         g_warning ("gdk_window_raise: BringWindowToTop failed");
1134     }
1135 }
1136
1137 void
1138 gdk_window_lower (GdkWindow *window)
1139 {
1140   g_return_if_fail (window != NULL);
1141   g_return_if_fail (GDK_IS_WINDOW (window));
1142   
1143   if (!GDK_DRAWABLE_DESTROYED (window))
1144     {
1145       GDK_NOTE (MISC, g_print ("gdk_window_lower: %#x\n",
1146                                GDK_DRAWABLE_XID (window)));
1147
1148       if (!SetWindowPos (GDK_DRAWABLE_XID (window), HWND_BOTTOM, 0, 0, 0, 0,
1149                          SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE))
1150         g_warning ("gdk_window_lower: SetWindowPos failed");
1151     }
1152 }
1153
1154 void
1155 gdk_window_set_user_data (GdkWindow *window,
1156                           gpointer   user_data)
1157 {
1158   g_return_if_fail (window != NULL);
1159   
1160   window->user_data = user_data;
1161 }
1162
1163 void
1164 gdk_window_set_hints (GdkWindow *window,
1165                       gint       x,
1166                       gint       y,
1167                       gint       min_width,
1168                       gint       min_height,
1169                       gint       max_width,
1170                       gint       max_height,
1171                       gint       flags)
1172 {
1173   GdkWindowPrivate *private;
1174   WINDOWPLACEMENT size_hints;
1175   RECT rect;
1176   DWORD dwStyle;
1177   DWORD dwExStyle;
1178   int diff;
1179   
1180   g_return_if_fail (window != NULL);
1181   g_return_if_fail (GDK_IS_WINDOW (window));
1182   
1183   if (GDK_DRAWABLE_DESTROYED (window))
1184     return;
1185   
1186   private = (GdkWindowPrivate*) window;
1187
1188   GDK_NOTE (MISC, g_print ("gdk_window_set_hints: %#x %dx%d..%dx%d @+%d+%d\n",
1189                            private->drawable.xwindow,
1190                            min_width, min_height, max_width, max_height,
1191                            x, y));
1192
1193   private->hint_flags = flags;
1194   size_hints.length = sizeof (size_hints);
1195
1196   if (flags)
1197     {
1198       if (flags & GDK_HINT_POS)
1199         if (!GetWindowPlacement (private->drawable.xwindow, &size_hints))
1200           g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
1201         else
1202           {
1203             GDK_NOTE (MISC, g_print ("...rcNormalPosition:"
1204                                      " (%d,%d)--(%d,%d)\n",
1205                                      size_hints.rcNormalPosition.left,
1206                                      size_hints.rcNormalPosition.top,
1207                                      size_hints.rcNormalPosition.right,
1208                                      size_hints.rcNormalPosition.bottom));
1209             /* What are the corresponding window coordinates for client
1210              * area coordinates x, y
1211              */
1212             rect.left = x;
1213             rect.top = y;
1214             rect.right = rect.left + 200;       /* dummy */
1215             rect.bottom = rect.top + 200;
1216             dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1217             dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1218             AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1219             size_hints.flags = 0;
1220             size_hints.showCmd = SW_SHOWNA;
1221
1222             /* Set the normal position hint to that location, with unchanged
1223              * width and height.
1224              */
1225             diff = size_hints.rcNormalPosition.left - rect.left;
1226             size_hints.rcNormalPosition.left = rect.left;
1227             size_hints.rcNormalPosition.right -= diff;
1228             diff = size_hints.rcNormalPosition.top - rect.top;
1229             size_hints.rcNormalPosition.top = rect.top;
1230             size_hints.rcNormalPosition.bottom -= diff;
1231             GDK_NOTE (MISC, g_print ("...setting: (%d,%d)--(%d,%d)\n",
1232                                      size_hints.rcNormalPosition.left,
1233                                      size_hints.rcNormalPosition.top,
1234                                      size_hints.rcNormalPosition.right,
1235                                      size_hints.rcNormalPosition.bottom));
1236             if (!SetWindowPlacement (private->drawable.xwindow, &size_hints))
1237               g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
1238             private->hint_x = rect.left;
1239             private->hint_y = rect.top;
1240           }
1241
1242       if (flags & GDK_HINT_MIN_SIZE)
1243         {
1244           rect.left = 0;
1245           rect.top = 0;
1246           rect.right = min_width;
1247           rect.bottom = min_height;
1248           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1249           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1250           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1251           private->hint_min_width = rect.right - rect.left;
1252           private->hint_min_height = rect.bottom - rect.top;
1253
1254           /* Also chek if he current size of the window is in bounds. */
1255           GetClientRect (private->drawable.xwindow, &rect);
1256           if (rect.right < min_width && rect.bottom < min_height)
1257             gdk_window_resize (window, min_width, min_height);
1258           else if (rect.right < min_width)
1259             gdk_window_resize (window, min_width, rect.bottom);
1260           else if (rect.bottom < min_height)
1261             gdk_window_resize (window, rect.right, min_height);
1262         }
1263       if (flags & GDK_HINT_MAX_SIZE)
1264         {
1265           rect.left = 0;
1266           rect.top = 0;
1267           rect.right = max_width;
1268           rect.bottom = max_height;
1269           dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1270           dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1271           AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1272           private->hint_max_width = rect.right - rect.left;
1273           private->hint_max_height = rect.bottom - rect.top;
1274           /* Again, check if the window is too large currently. */
1275           GetClientRect (private->drawable.xwindow, &rect);
1276           if (rect.right > max_width && rect.bottom > max_height)
1277             gdk_window_resize (window, max_width, max_height);
1278           else if (rect.right > max_width)
1279             gdk_window_resize (window, max_width, rect.bottom);
1280           else if (rect.bottom > max_height)
1281             gdk_window_resize (window, rect.right, max_height);
1282         }
1283     }
1284 }
1285
1286 void 
1287 gdk_window_set_geometry_hints (GdkWindow      *window,
1288                                GdkGeometry    *geometry,
1289                                GdkWindowHints  geom_mask)
1290 {
1291   GdkWindowPrivate *private;
1292   WINDOWPLACEMENT size_hints;
1293   RECT rect;
1294   DWORD dwStyle;
1295   DWORD dwExStyle;
1296   int diff;
1297   
1298   g_return_if_fail (window != NULL);
1299   g_return_if_fail (GDK_IS_WINDOW (window));
1300   
1301   if (GDK_DRAWABLE_DESTROYED (window))
1302     return;
1303
1304   private = (GdkWindowPrivate*) window;
1305   
1306   size_hints.length = sizeof (size_hints);
1307
1308   private->hint_flags = geom_mask;
1309
1310   if (geom_mask & GDK_HINT_POS)
1311     ; /* XXX */
1312
1313   if (geom_mask & GDK_HINT_MIN_SIZE)
1314     {
1315       rect.left = 0;
1316       rect.top = 0;
1317       rect.right = geometry->min_width;
1318       rect.bottom = geometry->min_height;
1319       dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1320       dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1321       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1322       private->hint_min_width = rect.right - rect.left;
1323       private->hint_min_height = rect.bottom - rect.top;
1324
1325       /* Also check if he current size of the window is in bounds */
1326       GetClientRect (private->drawable.xwindow, &rect);
1327       if (rect.right < geometry->min_width
1328           && rect.bottom < geometry->min_height)
1329         gdk_window_resize (window, geometry->min_width, geometry->min_height);
1330       else if (rect.right < geometry->min_width)
1331         gdk_window_resize (window, geometry->min_width, rect.bottom);
1332       else if (rect.bottom < geometry->min_height)
1333         gdk_window_resize (window, rect.right, geometry->min_height);
1334     }
1335   
1336   if (geom_mask & GDK_HINT_MAX_SIZE)
1337     {
1338       rect.left = 0;
1339       rect.top = 0;
1340       rect.right = geometry->max_width;
1341       rect.bottom = geometry->max_height;
1342       dwStyle = GetWindowLong (private->drawable.xwindow, GWL_STYLE);
1343       dwExStyle = GetWindowLong (private->drawable.xwindow, GWL_EXSTYLE);
1344       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1345       private->hint_max_width = rect.right - rect.left;
1346       private->hint_max_height = rect.bottom - rect.top;
1347
1348       /* Again, check if the window is too large currently. */
1349       GetClientRect (private->drawable.xwindow, &rect);
1350       if (rect.right > geometry->max_width
1351           && rect.bottom > geometry->max_height)
1352         gdk_window_resize (window, geometry->max_width, geometry->max_height);
1353       else if (rect.right > geometry->max_width)
1354         gdk_window_resize (window, geometry->max_width, rect.bottom);
1355       else if (rect.bottom > geometry->max_height)
1356         gdk_window_resize (window, rect.right, geometry->max_height);
1357     }
1358   
1359   /* I don't know what to do when called with zero base_width and height. */
1360   if (geom_mask & GDK_HINT_BASE_SIZE
1361       && geometry->base_width > 0
1362       && geometry->base_height > 0)
1363     if (!GetWindowPlacement (private->drawable.xwindow, &size_hints))
1364       g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
1365     else
1366       {
1367         GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints:"
1368                                  " rcNormalPosition: (%d,%d)--(%d,%d)\n",
1369                                  size_hints.rcNormalPosition.left,
1370                                  size_hints.rcNormalPosition.top,
1371                                  size_hints.rcNormalPosition.right,
1372                                  size_hints.rcNormalPosition.bottom));
1373         size_hints.rcNormalPosition.right =
1374           size_hints.rcNormalPosition.left + geometry->base_width;
1375         size_hints.rcNormalPosition.bottom =
1376           size_hints.rcNormalPosition.top + geometry->base_height;
1377         GDK_NOTE (MISC, g_print ("...setting: rcNormal: (%d,%d)--(%d,%d)\n",
1378                                  size_hints.rcNormalPosition.left,
1379                                  size_hints.rcNormalPosition.top,
1380                                  size_hints.rcNormalPosition.right,
1381                                  size_hints.rcNormalPosition.bottom));
1382         if (!SetWindowPlacement (private->drawable.xwindow, &size_hints))
1383           g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
1384       }
1385   
1386   if (geom_mask & GDK_HINT_RESIZE_INC)
1387     {
1388       /* XXX */
1389     }
1390   
1391   if (geom_mask & GDK_HINT_ASPECT)
1392     {
1393       /* XXX */
1394     }
1395 }
1396
1397 void
1398 gdk_window_set_title (GdkWindow   *window,
1399                       const gchar *title)
1400 {
1401   gint titlelen;
1402   wchar_t *wcstr;
1403   gint wlen;
1404   char *mbstr;
1405
1406   g_return_if_fail (window != NULL);
1407   g_return_if_fail (GDK_IS_WINDOW (window));
1408   
1409   GDK_NOTE (MISC, g_print ("gdk_window_set_title: %#x %s\n",
1410                            GDK_DRAWABLE_XID (window), title));
1411   if (!GDK_DRAWABLE_DESTROYED (window))
1412     {
1413       /* As the title most is in UTF-8 we must translate it
1414        * to the system codepage.
1415        */
1416       titlelen = strlen (title);
1417       wcstr = g_new (wchar_t, titlelen + 1);
1418       mbstr = g_new (char, 3*titlelen + 1);
1419       wlen = gdk_nmbstowchar_ts (wcstr, title, titlelen, titlelen);
1420       wcstr[wlen] = 0;
1421       WideCharToMultiByte (GetACP (), 0, wcstr, -1,
1422                            mbstr, 3*titlelen, NULL, NULL);
1423
1424       if (!SetWindowText (GDK_DRAWABLE_XID (window), mbstr))
1425         g_warning ("gdk_window_set_title: SetWindowText failed");
1426
1427       g_free (mbstr);
1428       g_free (wcstr);
1429     }
1430 }
1431
1432 void          
1433 gdk_window_set_role (GdkWindow   *window,
1434                      const gchar *role)
1435 {
1436   g_return_if_fail (window != NULL);
1437   g_return_if_fail (GDK_IS_WINDOW (window));
1438   
1439   GDK_NOTE (MISC, g_print ("gdk_window_set_role: %#x %s\n",
1440                            GDK_DRAWABLE_XID (window), (role ? role : "NULL")));
1441   /* XXX */
1442 }
1443
1444 void          
1445 gdk_window_set_transient_for (GdkWindow *window, 
1446                               GdkWindow *parent)
1447 {
1448   g_return_if_fail (window != NULL);
1449   g_return_if_fail (GDK_IS_WINDOW (window));
1450   
1451   GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %#x %#x\n",
1452                            GDK_DRAWABLE_XID (window),
1453                            GDK_DRAWABLE_XID (parent)));
1454   /* XXX */
1455 }
1456
1457 void
1458 gdk_window_set_background (GdkWindow *window,
1459                            GdkColor  *color)
1460 {
1461   GdkWindowPrivate *private;
1462   
1463   g_return_if_fail (window != NULL);
1464   g_return_if_fail (GDK_IS_WINDOW (window));
1465   
1466   private = (GdkWindowPrivate*) window;
1467   if (!GDK_DRAWABLE_DESTROYED (window))
1468     {
1469       GDK_NOTE (MISC, g_print ("gdk_window_set_background: %#x %s\n",
1470                                private->drawable.xwindow, 
1471                                gdk_color_to_string (color)));
1472
1473       if (private->bg_type == GDK_WIN32_BG_PIXMAP)
1474         {
1475           if (private->bg_pixmap != NULL)
1476             {
1477               gdk_pixmap_unref (private->bg_pixmap);
1478               private->bg_pixmap = NULL;
1479             }
1480           private->bg_type = GDK_WIN32_BG_NORMAL;
1481         }
1482       private->bg_type = GDK_WIN32_BG_PIXEL;
1483       private->bg_pixel = *color;
1484     }
1485 }
1486
1487 void
1488 gdk_window_set_back_pixmap (GdkWindow *window,
1489                             GdkPixmap *pixmap,
1490                             gint       parent_relative)
1491 {
1492   GdkWindowPrivate *private;
1493
1494   g_return_if_fail (window != NULL);
1495   g_return_if_fail (GDK_IS_WINDOW (window));
1496   
1497   private = (GdkWindowPrivate*) window;
1498
1499   if (!GDK_DRAWABLE_DESTROYED (window))
1500     {
1501       if (private->bg_type == GDK_WIN32_BG_PIXMAP)
1502         {
1503           if (private->bg_pixmap != NULL)
1504             {
1505               gdk_pixmap_unref (private->bg_pixmap);
1506               private->bg_pixmap = NULL;
1507             }
1508           private->bg_type = GDK_WIN32_BG_NORMAL;
1509         }
1510       if (parent_relative)
1511         {
1512           private->bg_type = GDK_WIN32_BG_PARENT_RELATIVE;
1513         }
1514       else if (!pixmap)
1515         {
1516           
1517         }
1518       else
1519         {
1520           /* We must cache the pixmap in the WindowPrivate and
1521            * paint it each time we get WM_ERASEBKGND
1522            */
1523           private->bg_type = GDK_WIN32_BG_PIXMAP;
1524           private->bg_pixmap = pixmap;
1525           gdk_pixmap_ref (pixmap);
1526         }
1527     }
1528 }
1529
1530 void
1531 gdk_window_set_cursor (GdkWindow *window,
1532                        GdkCursor *cursor)
1533 {
1534   GdkWindowPrivate *window_private;
1535   GdkCursorPrivate *cursor_private;
1536   HCURSOR xcursor;
1537   
1538   g_return_if_fail (window != NULL);
1539   g_return_if_fail (GDK_IS_WINDOW (window));
1540   
1541   window_private = (GdkWindowPrivate*) window;
1542   cursor_private = (GdkCursorPrivate*) cursor;
1543   
1544   if (!GDK_DRAWABLE_DESTROYED (window))
1545     {
1546       if (!cursor)
1547         xcursor = LoadCursor (NULL, IDC_ARROW);
1548       else
1549         xcursor = cursor_private->xcursor;
1550
1551       GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %#x %#x\n",
1552                                window_private->drawable.xwindow, xcursor));
1553       window_private->xcursor = xcursor;
1554     }
1555 }
1556
1557 void
1558 gdk_window_get_user_data (GdkWindow *window,
1559                           gpointer  *data)
1560 {
1561   g_return_if_fail (window != NULL);
1562   
1563   *data = window->user_data;
1564 }
1565
1566 void
1567 gdk_window_get_geometry (GdkWindow *window,
1568                          gint      *x,
1569                          gint      *y,
1570                          gint      *width,
1571                          gint      *height,
1572                          gint      *depth)
1573 {
1574   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1575   
1576   if (!window)
1577     window = (GdkWindow*) gdk_root_parent;
1578   
1579   if (!GDK_DRAWABLE_DESTROYED (window))
1580     {
1581       RECT rect;
1582
1583       if (!GetClientRect (GDK_DRAWABLE_XID (window), &rect))
1584         g_warning ("gdk_window_get_geometry: GetClientRect failed");
1585
1586       if (x)
1587         *x = rect.left;
1588       if (y)
1589         *y = rect.top;
1590       if (width)
1591         *width = rect.right - rect.left;
1592       if (height)
1593         *height = rect.bottom - rect.top;
1594       if (depth)
1595         *depth = gdk_drawable_get_visual (window)->depth;
1596     }
1597 }
1598
1599 void
1600 gdk_window_get_position (GdkWindow *window,
1601                          gint      *x,
1602                          gint      *y)
1603 {
1604   GdkWindowPrivate *window_private;
1605   
1606   g_return_if_fail (window != NULL);
1607   g_return_if_fail (GDK_IS_WINDOW (window));
1608   
1609   window_private = (GdkWindowPrivate*) window;
1610   
1611   if (x)
1612     *x = window_private->x;
1613   if (y)
1614     *y = window_private->y;
1615 }
1616
1617 gint
1618 gdk_window_get_origin (GdkWindow *window,
1619                        gint      *x,
1620                        gint      *y)
1621 {
1622   gint return_val;
1623   gint tx = 0;
1624   gint ty = 0;
1625
1626   g_return_val_if_fail (window != NULL, 0);
1627
1628   if (!GDK_DRAWABLE_DESTROYED (window))
1629     {
1630       POINT pt;
1631
1632       pt.x = 0;
1633       pt.y = 0;
1634       ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
1635       tx = pt.x;
1636       ty = pt.y;
1637       return_val = 1;
1638     }
1639   else
1640     return_val = 0;
1641   
1642   if (x)
1643     *x = tx;
1644   if (y)
1645     *y = ty;
1646
1647   GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %#x: +%d+%d\n",
1648                            GDK_DRAWABLE_XID (window), tx, ty));
1649   return return_val;
1650 }
1651
1652 gboolean
1653 gdk_window_get_deskrelative_origin (GdkWindow *window,
1654                                     gint      *x,
1655                                     gint      *y)
1656 {
1657   return gdk_window_get_origin (window, x, y);
1658 }
1659
1660 void
1661 gdk_window_get_root_origin (GdkWindow *window,
1662                             gint      *x,
1663                             gint      *y)
1664 {
1665   GdkWindowPrivate *private;
1666   POINT pt;
1667
1668   g_return_if_fail (window != NULL);
1669   g_return_if_fail (GDK_IS_WINDOW (window));
1670
1671   private = (GdkWindowPrivate*) window;
1672   if (x)
1673     *x = 0;
1674   if (y)
1675     *y = 0;
1676   if (GDK_DRAWABLE_DESTROYED (window))
1677     return;
1678       
1679   while (private->parent && ((GdkWindowPrivate*) private->parent)->parent)
1680     private = (GdkWindowPrivate*) private->parent;
1681   if (private->drawable.destroyed)
1682     return;
1683
1684   pt.x = 0;
1685   pt.y = 0;
1686   ClientToScreen (private->drawable.xwindow, &pt);
1687   if (x)
1688     *x = pt.x;
1689   if (y)
1690     *y = pt.y;
1691
1692   GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %#x: (%#x) +%d+%d\n",
1693                            GDK_DRAWABLE_XID (window),
1694                            private->drawable.xwindow, pt.x, pt.y));
1695 }
1696
1697 GdkWindow*
1698 gdk_window_get_pointer (GdkWindow       *window,
1699                         gint            *x,
1700                         gint            *y,
1701                         GdkModifierType *mask)
1702 {
1703   GdkWindow *return_val;
1704   POINT pointc, point;
1705   HWND hwnd, hwndc;
1706
1707   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1708   
1709   if (!window)
1710     window = (GdkWindow*) gdk_root_parent;
1711
1712   return_val = NULL;
1713   GetCursorPos (&pointc);
1714   point = pointc;
1715   ScreenToClient (GDK_DRAWABLE_XID (window), &point);
1716
1717   if (x)
1718     *x = point.x;
1719   if (y)
1720     *y = point.y;
1721
1722   hwnd = WindowFromPoint (point);
1723   point = pointc;
1724   ScreenToClient (hwnd, &point);
1725   
1726   do {
1727     hwndc = ChildWindowFromPoint (hwnd, point);
1728     ClientToScreen (hwnd, &point);
1729     ScreenToClient (hwndc, &point);
1730   } while (hwndc != hwnd && (hwnd = hwndc, 1)); /* Ouch! */
1731
1732   return_val = gdk_window_lookup (hwnd);
1733
1734   if (mask)
1735     {
1736       BYTE kbd[256];
1737
1738       GetKeyboardState (kbd);
1739       *mask = 0;
1740       if (kbd[VK_SHIFT] & 0x80)
1741         *mask |= GDK_SHIFT_MASK;
1742       if (kbd[VK_CAPITAL] & 0x80)
1743         *mask |= GDK_LOCK_MASK;
1744       if (kbd[VK_CONTROL] & 0x80)
1745         *mask |= GDK_CONTROL_MASK;
1746       if (kbd[VK_MENU] & 0x80)
1747         *mask |= GDK_MOD1_MASK;
1748       if (kbd[VK_LBUTTON] & 0x80)
1749         *mask |= GDK_BUTTON1_MASK;
1750       if (kbd[VK_MBUTTON] & 0x80)
1751         *mask |= GDK_BUTTON2_MASK;
1752       if (kbd[VK_RBUTTON] & 0x80)
1753         *mask |= GDK_BUTTON3_MASK;
1754     }
1755   
1756   return return_val;
1757 }
1758
1759 GdkWindow*
1760 gdk_window_at_pointer (gint *win_x,
1761                        gint *win_y)
1762 {
1763   GdkWindow *window;
1764   POINT point, pointc;
1765   HWND hwnd, hwndc;
1766   RECT rect;
1767
1768   GetCursorPos (&pointc);
1769   point = pointc;
1770   hwnd = WindowFromPoint (point);
1771
1772   if (hwnd == NULL)
1773     {
1774       window = (GdkWindow *) gdk_root_parent;
1775       if (win_x)
1776         *win_x = pointc.x;
1777       if (win_y)
1778         *win_y = pointc.y;
1779       return window;
1780     }
1781       
1782   ScreenToClient (hwnd, &point);
1783
1784   do {
1785     hwndc = ChildWindowFromPoint (hwnd, point);
1786     ClientToScreen (hwnd, &point);
1787     ScreenToClient (hwndc, &point);
1788   } while (hwndc != hwnd && (hwnd = hwndc, 1));
1789
1790   window = gdk_window_lookup (hwnd);
1791
1792   if (window && (win_x || win_y))
1793     {
1794       GetClientRect (hwnd, &rect);
1795       if (win_x)
1796         *win_x = point.x - rect.left;
1797       if (win_y)
1798         *win_y = point.y - rect.top;
1799     }
1800
1801   GDK_NOTE (MISC, g_print ("gdk_window_at_pointer: +%d+%d %#x%s\n",
1802                            point.x, point.y, hwnd,
1803                            (window == NULL ? " NULL" : "")));
1804
1805   return window;
1806 }
1807
1808 GdkWindow*
1809 gdk_window_get_parent (GdkWindow *window)
1810 {
1811   g_return_val_if_fail (window != NULL, NULL);
1812   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1813
1814   return ((GdkWindowPrivate*) window)->parent;
1815 }
1816
1817 GdkWindow*
1818 gdk_window_get_toplevel (GdkWindow *window)
1819 {
1820   g_return_val_if_fail (window != NULL, NULL);
1821   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1822
1823   while (GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_CHILD)
1824     window = ((GdkWindowPrivate*) window)->parent;
1825
1826   return window;
1827 }
1828
1829 GList*
1830 gdk_window_get_children (GdkWindow *window)
1831 {
1832   GdkWindowPrivate *private;
1833   GList *children;
1834
1835   g_return_val_if_fail (window != NULL, NULL);
1836   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1837
1838   if (GDK_DRAWABLE_DESTROYED (window))
1839     return NULL;
1840
1841   /* XXX ??? */
1842   g_warning ("gdk_window_get_children not implemented");
1843   children = NULL;
1844
1845   return children;
1846 }
1847
1848 GdkEventMask  
1849 gdk_window_get_events (GdkWindow *window)
1850 {
1851   GdkWindowPrivate *private;
1852
1853   g_return_val_if_fail (window != NULL, 0);
1854   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1855
1856   private = (GdkWindowPrivate*) window;
1857   if (GDK_DRAWABLE_DESTROYED (window))
1858     return 0;
1859
1860   return private->event_mask;
1861 }
1862
1863 void          
1864 gdk_window_set_events (GdkWindow   *window,
1865                        GdkEventMask event_mask)
1866 {
1867   GdkWindowPrivate *private;
1868
1869   g_return_if_fail (window != NULL);
1870   g_return_if_fail (GDK_IS_WINDOW (window));
1871
1872   private = (GdkWindowPrivate*) window;
1873   if (GDK_DRAWABLE_DESTROYED (window))
1874     return;
1875
1876   private->event_mask = event_mask;
1877 }
1878
1879 void
1880 gdk_window_add_colormap_windows (GdkWindow *window)
1881 {
1882   g_warning ("gdk_window_add_colormap_windows not implemented");
1883 }
1884
1885 void
1886 gdk_window_shape_combine_mask (GdkWindow *window,
1887                                GdkBitmap *mask,
1888                                gint x, gint y)
1889 {
1890   g_return_if_fail (window != NULL);
1891   g_return_if_fail (GDK_IS_WINDOW (window));
1892
1893   if (!mask)
1894     {
1895       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x none\n",
1896                                GDK_DRAWABLE_XID (window)));
1897       SetWindowRgn (GDK_DRAWABLE_XID (window), NULL, TRUE);
1898     }
1899   else
1900     {
1901       GdkDrawablePrivate *pixmap_private;
1902       HRGN hrgn;
1903       DWORD dwStyle;
1904       DWORD dwExStyle;
1905       RECT rect;
1906
1907       /* Convert mask bitmap to region */
1908       pixmap_private = (GdkDrawablePrivate*) mask;
1909       hrgn = BitmapToRegion (pixmap_private->xwindow);
1910
1911       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x %#x\n",
1912                                GDK_DRAWABLE_XID (window),
1913                                pixmap_private->xwindow));
1914
1915       /* SetWindowRgn wants window (not client) coordinates */ 
1916       dwStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
1917       dwExStyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
1918       GetClientRect (GDK_DRAWABLE_XID (window), &rect);
1919       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
1920       OffsetRgn (hrgn, -rect.left, -rect.top);
1921
1922       OffsetRgn (hrgn, x, y);
1923
1924       /* If this is a top-level window, add the title bar to the region */
1925       if (GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_TOPLEVEL)
1926         {
1927           CombineRgn (hrgn, hrgn,
1928                       CreateRectRgn (0, 0, rect.right - rect.left, -rect.top),
1929                       RGN_OR);
1930         }
1931       
1932       SetWindowRgn (GDK_DRAWABLE_XID (window), hrgn, TRUE);
1933     }
1934 }
1935
1936 void          
1937 gdk_window_add_filter (GdkWindow     *window,
1938                        GdkFilterFunc  function,
1939                        gpointer       data)
1940 {
1941   GdkWindowPrivate *private;
1942   GList *tmp_list;
1943   GdkEventFilter *filter;
1944   
1945   g_return_if_fail (window != NULL);
1946   g_return_if_fail (GDK_IS_WINDOW (window));
1947
1948   private = (GdkWindowPrivate*) window;
1949   if (private && GDK_DRAWABLE_DESTROYED (window))
1950     return;
1951   
1952   tmp_list = private->filters;
1953   
1954   while (tmp_list)
1955     {
1956       filter = (GdkEventFilter *)tmp_list->data;
1957       if ((filter->function == function) && (filter->data == data))
1958         return;
1959       tmp_list = tmp_list->next;
1960     }
1961   
1962   filter = g_new (GdkEventFilter, 1);
1963   filter->function = function;
1964   filter->data = data;
1965   
1966   private->filters = g_list_append (private->filters, filter);
1967 }
1968
1969 void
1970 gdk_window_remove_filter (GdkWindow     *window,
1971                           GdkFilterFunc  function,
1972                           gpointer       data)
1973 {
1974   GdkWindowPrivate *private;
1975   GList *tmp_list, *node;
1976   GdkEventFilter *filter;
1977   
1978   g_return_if_fail (window != NULL);
1979   g_return_if_fail (GDK_IS_WINDOW (window));
1980
1981   private = (GdkWindowPrivate*) window;
1982   
1983   tmp_list = private->filters;
1984   
1985   while (tmp_list)
1986     {
1987       filter = (GdkEventFilter *)tmp_list->data;
1988       node = tmp_list;
1989       tmp_list = tmp_list->next;
1990       
1991       if ((filter->function == function) && (filter->data == data))
1992         {
1993           private->filters = g_list_remove_link (private->filters, node);
1994
1995           g_list_free_1 (node);
1996           g_free (filter);
1997           
1998           return;
1999         }
2000     }
2001 }
2002
2003 void
2004 gdk_window_set_override_redirect (GdkWindow *window,
2005                                   gboolean   override_redirect)
2006 {
2007   g_return_if_fail (window != NULL);
2008   g_return_if_fail (GDK_IS_WINDOW (window));
2009
2010   g_warning ("gdk_window_set_override_redirect not implemented");
2011 }
2012
2013 void          
2014 gdk_window_set_icon (GdkWindow *window, 
2015                      GdkWindow *icon_window,
2016                      GdkPixmap *pixmap,
2017                      GdkBitmap *mask)
2018 {
2019   g_return_if_fail (window != NULL);
2020   g_return_if_fail (GDK_IS_WINDOW (window));
2021
2022   if (GDK_DRAWABLE_DESTROYED (window))
2023     return;
2024   
2025   g_warning ("gdk_window_set_icon not implemented");
2026 }
2027
2028 void
2029 gdk_window_set_icon_name (GdkWindow *window, 
2030                           gchar     *name)
2031 {
2032   g_return_if_fail (window != NULL);
2033   g_return_if_fail (GDK_IS_WINDOW (window));
2034
2035   if (GDK_DRAWABLE_DESTROYED (window))
2036     return;
2037   
2038   if (!SetWindowText (GDK_DRAWABLE_XID (window), name))
2039     g_warning ("gdk_window_set_icon_name: SetWindowText failed");
2040 }
2041
2042 void          
2043 gdk_window_set_group (GdkWindow *window, 
2044                       GdkWindow *leader)
2045 {
2046   g_return_if_fail (window != NULL);
2047   g_return_if_fail (GDK_IS_WINDOW (window));
2048   g_return_if_fail (leader != NULL);
2049   g_return_if_fail (GDK_IS_WINDOW (leader));
2050
2051   if (GDK_DRAWABLE_DESTROYED (window) || GDK_DRAWABLE_DESTROYED (leader))
2052     return;
2053   
2054   g_warning ("gdk_window_set_group not implemented");
2055 }
2056
2057 void
2058 gdk_window_set_decorations (GdkWindow      *window,
2059                             GdkWMDecoration decorations)
2060 {
2061   LONG style, exstyle;
2062
2063   g_return_if_fail (window != NULL);
2064   g_return_if_fail (GDK_IS_WINDOW (window));
2065   
2066   style = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
2067   exstyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
2068
2069   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2070             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE);
2071
2072   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2073
2074   if (decorations & GDK_DECOR_ALL)
2075     style |= (WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2076   if (decorations & GDK_DECOR_BORDER)
2077     style |= (WS_BORDER);
2078   if (decorations & GDK_DECOR_RESIZEH)
2079     style |= (WS_THICKFRAME);
2080   if (decorations & GDK_DECOR_TITLE)
2081     style |= (WS_CAPTION);
2082   if (decorations & GDK_DECOR_MENU)
2083     style |= (WS_SYSMENU);
2084   if (decorations & GDK_DECOR_MINIMIZE)
2085     style |= (WS_MINIMIZEBOX);
2086   if (decorations & GDK_DECOR_MAXIMIZE)
2087     style |= (WS_MAXIMIZEBOX);
2088   
2089   SetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE, style);
2090 }
2091
2092 void
2093 gdk_window_set_functions (GdkWindow    *window,
2094                           GdkWMFunction functions)
2095 {
2096   LONG style, exstyle;
2097
2098   g_return_if_fail (window != NULL);
2099   g_return_if_fail (GDK_IS_WINDOW (window));
2100   
2101   style = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE);
2102   exstyle = GetWindowLong (GDK_DRAWABLE_XID (window), GWL_EXSTYLE);
2103
2104   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2105             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE|WS_CAPTION|WS_BORDER
2106             |WS_SYSMENU);
2107
2108   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2109
2110   if (functions & GDK_FUNC_ALL)
2111     style |= (WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2112   if (functions & GDK_FUNC_RESIZE)
2113     style |= (WS_THICKFRAME);
2114   if (functions & GDK_FUNC_MOVE)
2115     style |= (WS_THICKFRAME);
2116   if (functions & GDK_FUNC_MINIMIZE)
2117     style |= (WS_MINIMIZEBOX);
2118   if (functions & GDK_FUNC_MAXIMIZE)
2119     style |= (WS_MAXIMIZEBOX);
2120   
2121   SetWindowLong (GDK_DRAWABLE_XID (window), GWL_STYLE, style);
2122 }
2123
2124 GList *
2125 gdk_window_get_toplevels (void)
2126 {
2127   GList *new_list = NULL;
2128   GList *tmp_list;
2129
2130   tmp_list = gdk_root_parent->children;
2131   while (tmp_list)
2132     {
2133       new_list = g_list_prepend (new_list, tmp_list->data);
2134       tmp_list = tmp_list->next;
2135     }
2136
2137   return new_list;
2138 }
2139
2140 /* 
2141  * propagate the shapes from all child windows of a GDK window to the parent 
2142  * window. Shamelessly ripped from Enlightenment's code
2143  * 
2144  * - Raster
2145  */
2146
2147 static void
2148 QueryTree (HWND hwnd,
2149            HWND **children,
2150            gint *nchildren)
2151 {
2152   guint i, n;
2153   HWND child;
2154
2155   n = 0;
2156   do {
2157     if (n == 0)
2158       child = GetWindow (hwnd, GW_CHILD);
2159     else
2160       child = GetWindow (child, GW_HWNDNEXT);
2161     if (child != NULL)
2162       n++;
2163   } while (child != NULL);
2164
2165   if (n > 0)
2166     {
2167       *children = g_new (HWND, n);
2168       for (i = 0; i < n; i++)
2169         {
2170           if (i == 0)
2171             child = GetWindow (hwnd, GW_CHILD);
2172           else
2173             child = GetWindow (child, GW_HWNDNEXT);
2174           *children[i] = child;
2175         }
2176     }
2177 }
2178
2179 static void
2180 gdk_propagate_shapes (HANDLE   win,
2181                       gboolean merge)
2182 {
2183    RECT emptyRect;
2184    HRGN region, childRegion;
2185    RECT rect;
2186    HWND *list = NULL;
2187    gint i, num;
2188
2189    SetRectEmpty (&emptyRect);
2190    region = CreateRectRgnIndirect (&emptyRect);
2191    if (merge)
2192      GetWindowRgn (win, region);
2193    
2194    QueryTree (win, &list, &num);
2195    if (list != NULL)
2196      {
2197        WINDOWPLACEMENT placement;
2198
2199        placement.length = sizeof (WINDOWPLACEMENT);
2200        /* go through all child windows and combine regions */
2201        for (i = 0; i < num; i++)
2202          {
2203            GetWindowPlacement (list[i], &placement);
2204            if (placement.showCmd = SW_SHOWNORMAL)
2205              {
2206                childRegion = CreateRectRgnIndirect (&emptyRect);
2207                GetWindowRgn (list[i], childRegion);
2208                CombineRgn (region, region, childRegion, RGN_OR);
2209                DeleteObject (childRegion);
2210              }
2211           }
2212        SetWindowRgn (win, region, TRUE);
2213      }
2214    else
2215      DeleteObject (region);
2216 }
2217
2218 void
2219 gdk_window_set_child_shapes (GdkWindow *window)
2220 {
2221   g_return_if_fail (window != NULL);
2222   g_return_if_fail (GDK_IS_WINDOW (window));
2223    
2224   if (GDK_DRAWABLE_DESTROYED (window))
2225     return;
2226
2227   gdk_propagate_shapes (GDK_DRAWABLE_XID (window), FALSE);
2228 }
2229
2230 void
2231 gdk_window_merge_child_shapes (GdkWindow *window)
2232 {
2233   g_return_if_fail (window != NULL);
2234   g_return_if_fail (GDK_IS_WINDOW (window));
2235   
2236   if (GDK_DRAWABLE_DESTROYED (window))
2237     return;
2238
2239   gdk_propagate_shapes (GDK_DRAWABLE_XID (window), TRUE);
2240 }
2241
2242 /*************************************************************
2243  * gdk_window_is_visible:
2244  *     Check if the given window is mapped.
2245  *   arguments:
2246  *     window: 
2247  *   results:
2248  *     is the window mapped
2249  *************************************************************/
2250
2251 gboolean 
2252 gdk_window_is_visible (GdkWindow *window)
2253 {
2254   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2255
2256   g_return_val_if_fail (window != NULL, FALSE);
2257   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2258
2259   return private->mapped;
2260 }
2261
2262 /*************************************************************
2263  * gdk_window_is_viewable:
2264  *     Check if the window and all ancestors of the window
2265  *     are mapped. (This is not necessarily "viewable" in
2266  *     the X sense, since we only check as far as we have
2267  *     GDK window parents, not to the root window)
2268  *   arguments:
2269  *     window:
2270  *   results:
2271  *     is the window viewable
2272  *************************************************************/
2273
2274 gboolean 
2275 gdk_window_is_viewable (GdkWindow *window)
2276 {
2277   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2278
2279   g_return_val_if_fail (window != NULL, FALSE);
2280   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2281
2282   while (private && 
2283          (private != gdk_root_parent) &&
2284          (private->drawable.window_type != GDK_WINDOW_FOREIGN))
2285     {
2286       if (!private->mapped)
2287         return FALSE;
2288
2289       private = (GdkWindowPrivate *)private->parent;
2290     }
2291
2292   return TRUE;
2293 }
2294
2295 /* Support for windows that can be guffaw-scrolled
2296  * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
2297  */
2298
2299 static gboolean
2300 gdk_window_gravity_works (void)
2301 {
2302   enum { UNKNOWN, NO, YES };
2303   static gint gravity_works = UNKNOWN;
2304   
2305   if (gravity_works == UNKNOWN)
2306     {
2307       GdkWindowAttr attr;
2308       GdkWindow *parent;
2309       GdkWindow *child;
2310       gint y;
2311       
2312       attr.window_type = GDK_WINDOW_TEMP;
2313       attr.wclass = GDK_INPUT_OUTPUT;
2314       attr.x = 0;
2315       attr.y = 0;
2316       attr.width = 100;
2317       attr.height = 100;
2318       attr.event_mask = 0;
2319       
2320       parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
2321       
2322       attr.window_type = GDK_WINDOW_CHILD;
2323       child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
2324       
2325       gdk_window_set_static_win_gravity (child, TRUE);
2326       
2327       gdk_window_resize (parent, 100, 110);
2328       gdk_window_move (parent, 0, -10);
2329       gdk_window_move_resize (parent, 0, 0, 100, 100);
2330       
2331       gdk_window_resize (parent, 100, 110);
2332       gdk_window_move (parent, 0, -10);
2333       gdk_window_move_resize (parent, 0, 0, 100, 100);
2334       
2335       gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
2336       
2337       gdk_window_destroy (parent);
2338       gdk_window_destroy (child);
2339       
2340       gravity_works = ((y == -20) ? YES : NO);
2341     }
2342   
2343   return (gravity_works == YES);
2344 }
2345
2346 static void
2347 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
2348 {
2349   g_return_if_fail (window != NULL);
2350
2351   GDK_NOTE (MISC, g_print ("gdk_window_set_static_bit_gravity: Not implemented\n"));
2352 }
2353
2354 static void
2355 gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
2356 {
2357   g_return_if_fail (window != NULL);
2358
2359   GDK_NOTE (MISC,
2360             g_print ("gdk_window_set_static_win_gravity: Not implemented\n"));
2361 }
2362
2363 /*************************************************************
2364  * gdk_window_set_static_gravities:
2365  *     Set the bit gravity of the given window to static,
2366  *     and flag it so all children get static subwindow
2367  *     gravity.
2368  *   arguments:
2369  *     window: window for which to set static gravity
2370  *     use_static: Whether to turn static gravity on or off.
2371  *   results:
2372  *     Does the XServer support static gravity?
2373  *************************************************************/
2374
2375 gboolean 
2376 gdk_window_set_static_gravities (GdkWindow *window,
2377                                  gboolean   use_static)
2378 {
2379   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2380   GList *tmp_list;
2381   
2382   g_return_val_if_fail (window != NULL, FALSE);
2383   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2384
2385   if (!use_static == !private->guffaw_gravity)
2386     return TRUE;
2387   
2388   if (use_static && !gdk_window_gravity_works ())
2389     return FALSE;
2390   
2391   private->guffaw_gravity = use_static;
2392   
2393   if (!GDK_DRAWABLE_DESTROYED (window))
2394     {
2395       gdk_window_set_static_bit_gravity (window, use_static);
2396       
2397       tmp_list = private->children;
2398       while (tmp_list)
2399         {
2400           gdk_window_set_static_win_gravity (window, use_static);
2401           
2402           tmp_list = tmp_list->next;
2403         }
2404     }
2405   
2406   return TRUE;
2407 }