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