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