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