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