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