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