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