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