]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkwindow-win32.c
Mention using GNU gettext. Enable NLS stuff. Use GNU gettext. Minor header
[~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   if (!private->destroyed)
1387     {
1388       if (!SetWindowText (private->xwindow, title))
1389         g_warning ("gdk_window_set_title: SetWindowText failed");
1390     }
1391 }
1392
1393 void          
1394 gdk_window_set_role (GdkWindow   *window,
1395                      const gchar *role)
1396 {
1397   GdkWindowPrivate *private;
1398   
1399   g_return_if_fail (window != NULL);
1400   
1401   private = (GdkWindowPrivate*) window;
1402
1403   GDK_NOTE (MISC, g_print ("gdk_window_set_role: %#x %s\n",
1404                            private->xwindow, (role ? role : "NULL")));
1405   /* XXX */
1406 }
1407
1408 void          
1409 gdk_window_set_transient_for (GdkWindow *window, 
1410                               GdkWindow *parent)
1411 {
1412   GdkWindowPrivate *private;
1413   GdkWindowPrivate *parent_private;
1414   
1415   g_return_if_fail (window != NULL);
1416   
1417   private = (GdkWindowPrivate*) window;
1418   parent_private = (GdkWindowPrivate*) parent;
1419
1420   GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %#x %#x\n",
1421                            private->xwindow, parent_private->xwindow));
1422   /* XXX */
1423 }
1424
1425 void
1426 gdk_window_set_background (GdkWindow *window,
1427                            GdkColor  *color)
1428 {
1429   GdkWindowPrivate *private;
1430   
1431   g_return_if_fail (window != NULL);
1432   
1433   private = (GdkWindowPrivate*) window;
1434   if (!private->destroyed)
1435     {
1436       GdkColormapPrivate *colormap_private =
1437         (GdkColormapPrivate *) private->colormap;
1438
1439       GDK_NOTE (MISC, g_print ("gdk_window_set_background: %#x %s\n",
1440                                private->xwindow, 
1441                                gdk_color_to_string (color)));
1442
1443       if (private->bg_type == GDK_WIN32_BG_PIXMAP)
1444         {
1445           if (private->bg_pixmap != NULL)
1446             {
1447               gdk_pixmap_unref (private->bg_pixmap);
1448               private->bg_pixmap = NULL;
1449             }
1450           private->bg_type = GDK_WIN32_BG_NORMAL;
1451         }
1452 #ifdef MULTIPLE_WINDOW_CLASSES
1453       if (colormap_private != NULL
1454               && colormap_private->xcolormap->rc_palette)
1455         {
1456           /* If we are on a palettized display we can't use the window
1457            * class background brush, but must handle WM_ERASEBKGND.
1458            * At least, I think so.
1459            */
1460 #endif
1461           private->bg_type = GDK_WIN32_BG_PIXEL;
1462           private->bg_pixel = *color;
1463 #ifdef MULTIPLE_WINDOW_CLASSES
1464         }
1465       else
1466         {
1467           /* Non-palettized display; just set the window class background
1468              brush. */
1469           HBRUSH hbr;
1470           HGDIOBJ oldbrush;
1471           COLORREF background;
1472
1473           background = RGB (color->red >> 8,
1474                             color->green >> 8,
1475                             color->blue >> 8);
1476
1477           if ((hbr = CreateSolidBrush (GetNearestColor (gdk_DC,
1478                                                         background))) == NULL)
1479             {
1480               g_warning ("gdk_window_set_background: CreateSolidBrush failed");
1481               return;
1482             }
1483
1484           oldbrush = (HGDIOBJ) GetClassLong (private->xwindow,
1485                                              GCL_HBRBACKGROUND);
1486
1487           if (SetClassLong (private->xwindow, GCL_HBRBACKGROUND,
1488                             (LONG) hbr) == 0)
1489             g_warning ("gdk_window_set_background: SetClassLong failed");
1490
1491           if (!DeleteObject (oldbrush))
1492             g_warning ("gdk_window_set_background: DeleteObject failed");
1493         }
1494 #endif
1495     }
1496 }
1497
1498 void
1499 gdk_window_set_back_pixmap (GdkWindow *window,
1500                             GdkPixmap *pixmap,
1501                             gint       parent_relative)
1502 {
1503   GdkWindowPrivate *window_private;
1504 #ifdef MULTIPLE_WINDOW_CLASSES
1505   GdkPixmapPrivate *pixmap_private;
1506 #endif
1507
1508   g_return_if_fail (window != NULL);
1509   
1510   window_private = (GdkWindowPrivate*) window;
1511 #ifdef MULTIPLE_WINDOW_CLASSES
1512   pixmap_private = (GdkPixmapPrivate*) pixmap;
1513 #endif
1514
1515   if (!window_private->destroyed)
1516     {
1517       GdkColormapPrivate *colormap_private =
1518         (GdkColormapPrivate *) window_private->colormap;
1519       if (window_private->bg_type == GDK_WIN32_BG_PIXMAP)
1520         {
1521           if (window_private->bg_pixmap != NULL)
1522             {
1523               gdk_pixmap_unref (window_private->bg_pixmap);
1524               window_private->bg_pixmap = NULL;
1525             }
1526           window_private->bg_type = GDK_WIN32_BG_NORMAL;
1527         }
1528       if (parent_relative)
1529         {
1530           window_private->bg_type = GDK_WIN32_BG_PARENT_RELATIVE;
1531         }
1532       else if (!pixmap)
1533         {
1534 #ifdef MULTIPLE_WINDOW_CLASSES
1535           SetClassLong (window_private->xwindow, GCL_HBRBACKGROUND,
1536                         (LONG) GetStockObject (BLACK_BRUSH));
1537 #endif
1538         }
1539 #ifdef MULTIPLE_WINDOW_CLASSES
1540       else if (colormap_private->xcolormap->rc_palette)
1541         {
1542           /* Must do the background painting in the
1543            * WM_ERASEBKGND handler.
1544            */
1545           window_private->bg_type = GDK_WIN32_BG_PIXMAP;
1546           window_private->bg_pixmap = pixmap;
1547           gdk_pixmap_ref (pixmap);
1548         }
1549       else if (pixmap_private->width <= 8
1550                && pixmap_private->height <= 8)
1551         {
1552           /* We can use small pixmaps directly as background brush */
1553           SetClassLong (window_private->xwindow, GCL_HBRBACKGROUND,
1554                         (LONG) CreatePatternBrush (pixmap_private->xwindow));
1555         }
1556 #endif
1557       else
1558         {
1559           /* We must cache the pixmap in the WindowPrivate and
1560            * paint it each time we get WM_ERASEBKGND
1561            */
1562           window_private->bg_type = GDK_WIN32_BG_PIXMAP;
1563           window_private->bg_pixmap = pixmap;
1564           gdk_pixmap_ref (pixmap);
1565         }
1566     }
1567 }
1568
1569 void
1570 gdk_window_set_cursor (GdkWindow *window,
1571                        GdkCursor *cursor)
1572 {
1573   GdkWindowPrivate *window_private;
1574   GdkCursorPrivate *cursor_private;
1575   HCURSOR xcursor;
1576   
1577   g_return_if_fail (window != NULL);
1578   
1579   window_private = (GdkWindowPrivate*) window;
1580   cursor_private = (GdkCursorPrivate*) cursor;
1581   
1582   if (!window_private->destroyed)
1583     {
1584       if (!cursor)
1585         xcursor = LoadCursor (NULL, IDC_ARROW);
1586       else
1587         xcursor = cursor_private->xcursor;
1588
1589       GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %#x %#x\n",
1590                                window_private->xwindow, xcursor));
1591 #ifdef MULTIPLE_WINDOW_CLASSES
1592       if (!SetClassLong (window_private->xwindow, GCL_HCURSOR, (LONG) xcursor))
1593         g_warning ("gdk_window_set_cursor: SetClassLong failed");
1594 #else
1595       window_private->xcursor = xcursor;
1596 #endif
1597       SetCursor (xcursor);
1598     }
1599 }
1600
1601 void
1602 gdk_window_set_colormap (GdkWindow   *window,
1603                          GdkColormap *colormap)
1604 {
1605   GdkWindowPrivate *window_private;
1606   GdkColormapPrivate *colormap_private;
1607   
1608   g_return_if_fail (window != NULL);
1609   g_return_if_fail (colormap != NULL);
1610   
1611   window_private = (GdkWindowPrivate*) window;
1612   colormap_private = (GdkColormapPrivate*) colormap;
1613   
1614   if (!window_private->destroyed)
1615     {
1616       /* XXX ??? */
1617       GDK_NOTE (MISC, g_print ("gdk_window_set_colormap: %#x %#x\n",
1618                                window_private->xwindow,
1619                                colormap_private->xcolormap));
1620       if (window_private->colormap)
1621         gdk_colormap_unref (window_private->colormap);
1622       window_private->colormap = colormap;
1623       gdk_colormap_ref (window_private->colormap);
1624       
1625       if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
1626         gdk_window_add_colormap_windows (window);
1627     }
1628 }
1629
1630 void
1631 gdk_window_get_user_data (GdkWindow *window,
1632                           gpointer  *data)
1633 {
1634   g_return_if_fail (window != NULL);
1635   
1636   *data = window->user_data;
1637 }
1638
1639 void
1640 gdk_window_get_geometry (GdkWindow *window,
1641                          gint      *x,
1642                          gint      *y,
1643                          gint      *width,
1644                          gint      *height,
1645                          gint      *depth)
1646 {
1647   GdkWindowPrivate *window_private;
1648   
1649   if (!window)
1650     window = (GdkWindow*) &gdk_root_parent;
1651   
1652   window_private = (GdkWindowPrivate*) window;
1653   
1654   if (!window_private->destroyed)
1655     {
1656       RECT rect;
1657
1658       if (!GetClientRect (window_private->xwindow, &rect))
1659         g_warning ("gdk_window_get_geometry: GetClientRect failed");
1660
1661       if (x)
1662         *x = rect.left;
1663       if (y)
1664         *y = rect.top;
1665       if (width)
1666         *width = rect.right - rect.left;
1667       if (height)
1668         *height = rect.bottom - rect.top;
1669       if (depth)
1670         *depth = gdk_window_get_visual (window)->depth;
1671     }
1672 }
1673
1674 void
1675 gdk_window_get_position (GdkWindow *window,
1676                          gint      *x,
1677                          gint      *y)
1678 {
1679   GdkWindowPrivate *window_private;
1680   
1681   g_return_if_fail (window != NULL);
1682   
1683   window_private = (GdkWindowPrivate*) window;
1684   
1685   if (x)
1686     *x = window_private->x;
1687   if (y)
1688     *y = window_private->y;
1689 }
1690
1691 void
1692 gdk_window_get_size (GdkWindow *window,
1693                      gint       *width,
1694                      gint       *height)
1695 {
1696   GdkWindowPrivate *window_private;
1697   
1698   g_return_if_fail (window != NULL);
1699   
1700   window_private = (GdkWindowPrivate*) window;
1701   
1702   if (width)
1703     *width = window_private->width;
1704   if (height)
1705     *height = window_private->height;
1706 }
1707
1708 GdkVisual*
1709 gdk_window_get_visual (GdkWindow *window)
1710 {
1711   GdkWindowPrivate *window_private;
1712    
1713   g_return_val_if_fail (window != NULL, NULL);
1714
1715   window_private = (GdkWindowPrivate*) window;
1716   /* Huh? ->parent is never set for a pixmap. We should just return
1717    * null immeditately. Well, do it then!
1718    */
1719   if (window_private->window_type == GDK_WINDOW_PIXMAP)
1720     return NULL;
1721   
1722   if (!window_private->destroyed)
1723     {
1724        if (window_private->colormap == NULL)
1725          return gdk_visual_get_system (); /* XXX ??? */
1726        else
1727          return ((GdkColormapPrivate *)window_private->colormap)->visual;
1728     }
1729   
1730   return NULL;
1731 }
1732
1733 GdkColormap*
1734 gdk_window_get_colormap (GdkWindow *window)
1735 {
1736   GdkWindowPrivate *window_private;
1737   
1738   g_return_val_if_fail (window != NULL, NULL);
1739   window_private = (GdkWindowPrivate*) window;
1740
1741   g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL);
1742   if (!window_private->destroyed)
1743     {
1744       if (window_private->colormap == NULL)
1745         return gdk_colormap_get_system (); /* XXX ??? */
1746       else
1747         return window_private->colormap;
1748     }
1749   
1750   return NULL;
1751 }
1752
1753 GdkWindowType
1754 gdk_window_get_type (GdkWindow *window)
1755 {
1756   GdkWindowPrivate *window_private;
1757
1758   g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
1759
1760   window_private = (GdkWindowPrivate*) window;
1761   return window_private->window_type;
1762 }
1763
1764 gint
1765 gdk_window_get_origin (GdkWindow *window,
1766                        gint      *x,
1767                        gint      *y)
1768 {
1769   GdkWindowPrivate *private;
1770   gint return_val;
1771   gint tx = 0;
1772   gint ty = 0;
1773
1774   g_return_val_if_fail (window != NULL, 0);
1775
1776   private = (GdkWindowPrivate*) window;
1777
1778   if (!private->destroyed)
1779     {
1780       POINT pt;
1781
1782       pt.x = 0;
1783       pt.y = 0;
1784       ClientToScreen (private->xwindow, &pt);
1785       tx = pt.x;
1786       ty = pt.y;
1787       return_val = 1;
1788     }
1789   else
1790     return_val = 0;
1791   
1792   if (x)
1793     *x = tx;
1794   if (y)
1795     *y = ty;
1796
1797   GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %#x: +%d+%d\n",
1798                            private->xwindow, tx, ty));
1799   return return_val;
1800 }
1801
1802 gboolean
1803 gdk_window_get_deskrelative_origin (GdkWindow *window,
1804                                     gint      *x,
1805                                     gint      *y)
1806 {
1807   return gdk_window_get_origin (window, x, y);
1808 }
1809
1810 void
1811 gdk_window_get_root_origin (GdkWindow *window,
1812                             gint      *x,
1813                             gint      *y)
1814 {
1815   GdkWindowPrivate *private;
1816   POINT pt;
1817
1818   g_return_if_fail (window != NULL);
1819
1820   private = (GdkWindowPrivate*) window;
1821   if (x)
1822     *x = 0;
1823   if (y)
1824     *y = 0;
1825   if (private->destroyed)
1826     return;
1827       
1828   while (private->parent && ((GdkWindowPrivate*) private->parent)->parent)
1829     private = (GdkWindowPrivate*) private->parent;
1830   if (private->destroyed)
1831     return;
1832
1833   pt.x = 0;
1834   pt.y = 0;
1835   ClientToScreen (private->xwindow, &pt);
1836   if (x)
1837     *x = pt.x;
1838   if (y)
1839     *y = pt.y;
1840
1841   GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %#x: (%#x) +%d+%d\n",
1842                            ((GdkWindowPrivate *) window)->xwindow,
1843                            private->xwindow, pt.x, pt.y));
1844 }
1845
1846 GdkWindow*
1847 gdk_window_get_pointer (GdkWindow       *window,
1848                         gint            *x,
1849                         gint            *y,
1850                         GdkModifierType *mask)
1851 {
1852   GdkWindowPrivate *private;
1853   GdkWindow *return_val;
1854   POINT pointc, point;
1855   HWND hwnd, hwndc;
1856
1857   if (!window)
1858     window = (GdkWindow*) &gdk_root_parent;
1859
1860   private = (GdkWindowPrivate*) window;
1861
1862   return_val = NULL;
1863   GetCursorPos (&pointc);
1864   point = pointc;
1865   ScreenToClient (private->xwindow, &point);
1866
1867   if (x)
1868     *x = point.x;
1869   if (y)
1870     *y = point.y;
1871
1872   hwnd = WindowFromPoint (point);
1873   point = pointc;
1874   ScreenToClient (hwnd, &point);
1875   
1876   do {
1877     hwndc = ChildWindowFromPoint (hwnd, point);
1878     ClientToScreen (hwnd, &point);
1879     ScreenToClient (hwndc, &point);
1880   } while (hwndc != hwnd && (hwnd = hwndc, 1)); /* Ouch! */
1881
1882   return_val = gdk_window_lookup (hwnd);
1883
1884   if (mask)
1885     {
1886       BYTE kbd[256];
1887
1888       GetKeyboardState (kbd);
1889       *mask = 0;
1890       if (kbd[VK_SHIFT] & 0x80)
1891         *mask |= GDK_SHIFT_MASK;
1892       if (kbd[VK_CAPITAL] & 0x80)
1893         *mask |= GDK_LOCK_MASK;
1894       if (kbd[VK_CONTROL] & 0x80)
1895         *mask |= GDK_CONTROL_MASK;
1896       if (kbd[VK_MENU] & 0x80)
1897         *mask |= GDK_MOD1_MASK;
1898       if (kbd[VK_LBUTTON] & 0x80)
1899         *mask |= GDK_BUTTON1_MASK;
1900       if (kbd[VK_MBUTTON] & 0x80)
1901         *mask |= GDK_BUTTON2_MASK;
1902       if (kbd[VK_RBUTTON] & 0x80)
1903         *mask |= GDK_BUTTON3_MASK;
1904     }
1905   
1906   return return_val;
1907 }
1908
1909 GdkWindow*
1910 gdk_window_at_pointer (gint *win_x,
1911                        gint *win_y)
1912 {
1913   GdkWindowPrivate *private;
1914   GdkWindow *window;
1915   POINT point, pointc;
1916   HWND hwnd, hwndc;
1917   RECT rect;
1918
1919   private = &gdk_root_parent;
1920
1921   GetCursorPos (&pointc);
1922   point = pointc;
1923   hwnd = WindowFromPoint (point);
1924
1925   if (hwnd == NULL)
1926     {
1927       window = (GdkWindow *) &gdk_root_parent;
1928       if (win_x)
1929         *win_x = pointc.x;
1930       if (win_y)
1931         *win_y = pointc.y;
1932       return window;
1933     }
1934       
1935   ScreenToClient (hwnd, &point);
1936
1937   do {
1938     hwndc = ChildWindowFromPoint (hwnd, point);
1939     ClientToScreen (hwnd, &point);
1940     ScreenToClient (hwndc, &point);
1941   } while (hwndc != hwnd && (hwnd = hwndc, 1));
1942
1943   window = gdk_window_lookup (hwnd);
1944
1945   if (window && (win_x || win_y))
1946     {
1947       GetClientRect (hwnd, &rect);
1948       if (win_x)
1949         *win_x = point.x - rect.left;
1950       if (win_y)
1951         *win_y = point.y - rect.top;
1952     }
1953
1954   GDK_NOTE (MISC, g_print ("gdk_window_at_pointer: +%d+%d %#x%s\n",
1955                            point.x, point.y, hwnd,
1956                            (window == NULL ? " NULL" : "")));
1957
1958   return window;
1959 }
1960
1961 GdkWindow*
1962 gdk_window_get_parent (GdkWindow *window)
1963 {
1964   g_return_val_if_fail (window != NULL, NULL);
1965
1966   return ((GdkWindowPrivate*) window)->parent;
1967 }
1968
1969 GdkWindow*
1970 gdk_window_get_toplevel (GdkWindow *window)
1971 {
1972   GdkWindowPrivate *private;
1973
1974   g_return_val_if_fail (window != NULL, NULL);
1975
1976   private = (GdkWindowPrivate*) window;
1977
1978   while (private->window_type == GDK_WINDOW_CHILD)
1979     {
1980       window = ((GdkWindowPrivate*) window)->parent;
1981       private = (GdkWindowPrivate*) window;
1982     }
1983
1984   return window;
1985 }
1986
1987 GList*
1988 gdk_window_get_children (GdkWindow *window)
1989 {
1990   GdkWindowPrivate *private;
1991   GList *children;
1992
1993   g_return_val_if_fail (window != NULL, NULL);
1994
1995   private = (GdkWindowPrivate*) window;
1996   if (private->destroyed)
1997     return NULL;
1998
1999   /* XXX ??? */
2000   g_warning ("gdk_window_get_children ???");
2001   children = NULL;
2002
2003   return children;
2004 }
2005
2006 GdkEventMask  
2007 gdk_window_get_events (GdkWindow *window)
2008 {
2009   GdkWindowPrivate *private;
2010
2011   g_return_val_if_fail (window != NULL, 0);
2012
2013   private = (GdkWindowPrivate*) window;
2014   if (private->destroyed)
2015     return 0;
2016
2017   return private->event_mask;
2018 }
2019
2020 void          
2021 gdk_window_set_events (GdkWindow   *window,
2022                        GdkEventMask event_mask)
2023 {
2024   GdkWindowPrivate *private;
2025
2026   g_return_if_fail (window != NULL);
2027
2028   private = (GdkWindowPrivate*) window;
2029   if (private->destroyed)
2030     return;
2031
2032   private->event_mask = event_mask;
2033 }
2034
2035 void
2036 gdk_window_add_colormap_windows (GdkWindow *window)
2037 {
2038   g_warning ("gdk_window_add_colormap_windows not implemented"); /* XXX */
2039 }
2040
2041 /*
2042  * This needs the X11 shape extension.
2043  * If not available, shaped windows will look
2044  * ugly, but programs still work.    Stefan Wille
2045  */
2046 void
2047 gdk_window_shape_combine_mask (GdkWindow *window,
2048                                GdkBitmap *mask,
2049                                gint x, gint y)
2050 {
2051   GdkWindowPrivate *window_private;
2052
2053   g_return_if_fail (window != NULL);
2054
2055   window_private = (GdkWindowPrivate*) window;
2056   
2057   if (!mask)
2058     {
2059       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x none\n",
2060                                window_private->xwindow));
2061       SetWindowRgn (window_private->xwindow, NULL, TRUE);
2062     }
2063   else
2064     {
2065       GdkPixmapPrivate *pixmap_private;
2066       HRGN hrgn;
2067       DWORD dwStyle;
2068       DWORD dwExStyle;
2069       RECT rect;
2070
2071       /* Convert mask bitmap to region */
2072       pixmap_private = (GdkPixmapPrivate*) mask;
2073       hrgn = BitmapToRegion (pixmap_private->xwindow);
2074
2075       GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x %#x\n",
2076                                window_private->xwindow,
2077                                pixmap_private->xwindow));
2078
2079       /* SetWindowRgn wants window (not client) coordinates */ 
2080       dwStyle = GetWindowLong (window_private->xwindow, GWL_STYLE);
2081       dwExStyle = GetWindowLong (window_private->xwindow, GWL_EXSTYLE);
2082       GetClientRect (window_private->xwindow, &rect);
2083       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
2084       OffsetRgn (hrgn, -rect.left, -rect.top);
2085
2086       OffsetRgn (hrgn, x, y);
2087
2088       /* If this is a top-level window, add the title bar to the region */
2089       if (window_private->window_type == GDK_WINDOW_TOPLEVEL)
2090         {
2091           CombineRgn (hrgn, hrgn,
2092                       CreateRectRgn (0, 0, rect.right - rect.left, -rect.top),
2093                       RGN_OR);
2094         }
2095       
2096       SetWindowRgn (window_private->xwindow, hrgn, TRUE);
2097     }
2098 }
2099
2100 void          
2101 gdk_window_add_filter (GdkWindow     *window,
2102                        GdkFilterFunc  function,
2103                        gpointer       data)
2104 {
2105   GdkWindowPrivate *private;
2106   GList *tmp_list;
2107   GdkEventFilter *filter;
2108
2109   private = (GdkWindowPrivate*) window;
2110   if (private && private->destroyed)
2111     return;
2112
2113   if (private)
2114     tmp_list = private->filters;
2115   else
2116     tmp_list = gdk_default_filters;
2117
2118   while (tmp_list)
2119     {
2120       filter = (GdkEventFilter *)tmp_list->data;
2121       if ((filter->function == function) && (filter->data == data))
2122         return;
2123       tmp_list = tmp_list->next;
2124     }
2125
2126   filter = g_new (GdkEventFilter, 1);
2127   filter->function = function;
2128   filter->data = data;
2129
2130   if (private)
2131     private->filters = g_list_append (private->filters, filter);
2132   else
2133     gdk_default_filters = g_list_append (gdk_default_filters, filter);
2134 }
2135
2136 void
2137 gdk_window_remove_filter (GdkWindow     *window,
2138                           GdkFilterFunc  function,
2139                           gpointer       data)
2140 {
2141   GdkWindowPrivate *private;
2142   GList *tmp_list, *node;
2143   GdkEventFilter *filter;
2144
2145   private = (GdkWindowPrivate*) window;
2146
2147   if(private)
2148     tmp_list = private->filters;
2149   else
2150     tmp_list = gdk_default_filters;
2151
2152   while (tmp_list)
2153     {
2154       filter = (GdkEventFilter *)tmp_list->data;
2155       node = tmp_list;
2156       tmp_list = tmp_list->next;
2157
2158       if ((filter->function == function) && (filter->data == data))
2159         {
2160           if(private)
2161             private->filters = g_list_remove_link (private->filters, node);
2162           else
2163             gdk_default_filters = g_list_remove_link (gdk_default_filters, tmp_list);
2164           g_list_free_1 (node);
2165           g_free (filter);
2166           
2167           return;
2168         }
2169     }
2170 }
2171
2172 void
2173 gdk_window_set_override_redirect (GdkWindow *window,
2174                                   gboolean   override_redirect)
2175 {
2176   g_warning ("gdk_window_set_override_redirect not implemented"); /* XXX */
2177 }
2178
2179 void          
2180 gdk_window_set_icon (GdkWindow *window, 
2181                      GdkWindow *icon_window,
2182                      GdkPixmap *pixmap,
2183                      GdkBitmap *mask)
2184 {
2185   g_warning ("gdk_window_set_icon not implemented"); /* XXX */
2186 }
2187
2188 void          
2189 gdk_window_set_icon_name (GdkWindow *window, 
2190                           gchar     *name)
2191 {
2192   GdkWindowPrivate *window_private;
2193
2194   g_return_if_fail (window != NULL);
2195   window_private = (GdkWindowPrivate*) window;
2196   if (window_private->destroyed)
2197     return;
2198
2199   if (!SetWindowText (window_private->xwindow, name))
2200     g_warning ("gdk_window_set_icon_name: SetWindowText failed");
2201 }
2202
2203 void          
2204 gdk_window_set_group (GdkWindow *window, 
2205                       GdkWindow *leader)
2206 {
2207   g_warning ("gdk_window_set_group not implemented"); /* XXX */
2208 }
2209
2210 void
2211 gdk_window_set_decorations (GdkWindow      *window,
2212                             GdkWMDecoration decorations)
2213 {
2214   GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
2215   LONG style, exstyle;
2216
2217   style = GetWindowLong (window_private->xwindow, GWL_STYLE);
2218   exstyle = GetWindowLong (window_private->xwindow, GWL_EXSTYLE);
2219
2220   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2221             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE);
2222
2223   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2224
2225   if (decorations & GDK_DECOR_ALL)
2226     style |= (WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2227   if (decorations & GDK_DECOR_BORDER)
2228     style |= (WS_BORDER);
2229   if (decorations & GDK_DECOR_RESIZEH)
2230     style |= (WS_THICKFRAME);
2231   if (decorations & GDK_DECOR_TITLE)
2232     style |= (WS_CAPTION);
2233   if (decorations & GDK_DECOR_MENU)
2234     style |= (WS_SYSMENU);
2235   if (decorations & GDK_DECOR_MINIMIZE)
2236     style |= (WS_MINIMIZEBOX);
2237   if (decorations & GDK_DECOR_MAXIMIZE)
2238     style |= (WS_MAXIMIZEBOX);
2239   
2240   SetWindowLong (window_private->xwindow, GWL_STYLE, style);
2241 }
2242
2243 void
2244 gdk_window_set_functions (GdkWindow    *window,
2245                           GdkWMFunction functions)
2246 {
2247   GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
2248   LONG style, exstyle;
2249
2250   style = GetWindowLong (window_private->xwindow, GWL_STYLE);
2251   exstyle = GetWindowLong (window_private->xwindow, GWL_EXSTYLE);
2252
2253   style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
2254             |WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE|WS_CAPTION|WS_BORDER
2255             |WS_SYSMENU);
2256
2257   exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
2258
2259   if (functions & GDK_FUNC_ALL)
2260     style |= (WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
2261   if (functions & GDK_FUNC_RESIZE)
2262     style |= (WS_THICKFRAME);
2263   if (functions & GDK_FUNC_MOVE)
2264     style |= (WS_THICKFRAME);
2265   if (functions & GDK_FUNC_MINIMIZE)
2266     style |= (WS_MINIMIZEBOX);
2267   if (functions & GDK_FUNC_MAXIMIZE)
2268     style |= (WS_MAXIMIZEBOX);
2269   
2270   SetWindowLong (window_private->xwindow, GWL_STYLE, style);
2271 }
2272
2273 GList *
2274 gdk_window_get_toplevels (void)
2275 {
2276   GList *new_list = NULL;
2277   GList *tmp_list;
2278
2279   tmp_list = gdk_root_parent.children;
2280   while (tmp_list)
2281     {
2282       new_list = g_list_prepend (new_list, tmp_list->data);
2283       tmp_list = tmp_list->next;
2284     }
2285
2286   return new_list;
2287 }
2288
2289 /* 
2290  * propagate the shapes from all child windows of a GDK window to the parent 
2291  * window. Shamelessly ripped from Enlightenment's code
2292  * 
2293  * - Raster
2294  */
2295
2296 static void
2297 QueryTree (HWND hwnd,
2298            HWND **children,
2299            gint *nchildren)
2300 {
2301   guint i, n;
2302   HWND child;
2303
2304   n = 0;
2305   do {
2306     if (n == 0)
2307       child = GetWindow (hwnd, GW_CHILD);
2308     else
2309       child = GetWindow (child, GW_HWNDNEXT);
2310     if (child != NULL)
2311       n++;
2312   } while (child != NULL);
2313
2314   if (n > 0)
2315     {
2316       *children = g_new (HWND, n);
2317       for (i = 0; i < n; i++)
2318         {
2319           if (i == 0)
2320             child = GetWindow (hwnd, GW_CHILD);
2321           else
2322             child = GetWindow (child, GW_HWNDNEXT);
2323           *children[i] = child;
2324         }
2325     }
2326 }
2327
2328 static void
2329 gdk_propagate_shapes (HANDLE   win,
2330                       gboolean merge)
2331 {
2332    RECT emptyRect;
2333    HRGN region, childRegion;
2334    RECT rect;
2335    HWND *list = NULL;
2336    gint i, num;
2337
2338    SetRectEmpty (&emptyRect);
2339    region = CreateRectRgnIndirect (&emptyRect);
2340    if (merge)
2341      GetWindowRgn (win, region);
2342    
2343    QueryTree (win, &list, &num);
2344    if (list != NULL)
2345      {
2346        WINDOWPLACEMENT placement;
2347
2348        placement.length = sizeof (WINDOWPLACEMENT);
2349        /* go through all child windows and create/insert spans */
2350        for (i = 0; i < num; i++)
2351          {
2352            GetWindowPlacement (list[i], &placement);
2353            if (placement.showCmd = SW_SHOWNORMAL)
2354              {
2355                childRegion = CreateRectRgnIndirect (&emptyRect);
2356                GetWindowRgn (list[i], childRegion);
2357                CombineRgn (region, region, childRegion, RGN_OR);
2358              }
2359           }
2360        SetWindowRgn (win, region, TRUE);
2361      }
2362 }
2363
2364 void
2365 gdk_window_set_child_shapes (GdkWindow *window)
2366 {
2367   GdkWindowPrivate *private;
2368    
2369   g_return_if_fail (window != NULL);
2370    
2371   private = (GdkWindowPrivate*) window;
2372   if (private->destroyed)
2373     return;
2374
2375   gdk_propagate_shapes ( private->xwindow, FALSE);
2376 }
2377
2378 void
2379 gdk_window_merge_child_shapes (GdkWindow *window)
2380 {
2381   GdkWindowPrivate *private;
2382   
2383   g_return_if_fail (window != NULL);
2384   
2385   private = (GdkWindowPrivate*) window;
2386   if (private->destroyed)
2387     return;
2388
2389   gdk_propagate_shapes (private->xwindow, TRUE);
2390 }
2391
2392 /*************************************************************
2393  * gdk_window_is_visible:
2394  *     Check if the given window is mapped.
2395  *   arguments:
2396  *     window: 
2397  *   results:
2398  *     is the window mapped
2399  *************************************************************/
2400
2401 gboolean 
2402 gdk_window_is_visible (GdkWindow *window)
2403 {
2404   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2405
2406   g_return_val_if_fail (window != NULL, FALSE);
2407
2408   return private->mapped;
2409 }
2410
2411 /*************************************************************
2412  * gdk_window_is_viewable:
2413  *     Check if the window and all ancestors of the window
2414  *     are mapped. (This is not necessarily "viewable" in
2415  *     the X sense, since we only check as far as we have
2416  *     GDK window parents, not to the root window)
2417  *   arguments:
2418  *     window:
2419  *   results:
2420  *     is the window viewable
2421  *************************************************************/
2422
2423 gboolean 
2424 gdk_window_is_viewable (GdkWindow *window)
2425 {
2426   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2427
2428   g_return_val_if_fail (window != NULL, FALSE);
2429
2430   while (private && 
2431          (private != &gdk_root_parent) &&
2432          (private->window_type != GDK_WINDOW_FOREIGN))
2433     {
2434       if (!private->mapped)
2435         return FALSE;
2436
2437       private = (GdkWindowPrivate *)private->parent;
2438     }
2439
2440   return TRUE;
2441 }
2442
2443 void          
2444 gdk_drawable_set_data (GdkDrawable   *drawable,
2445                        const gchar   *key,
2446                        gpointer       data,
2447                        GDestroyNotify destroy_func)
2448 {
2449   g_dataset_set_data_full (drawable, key, data, destroy_func);
2450 }
2451
2452
2453 /* Support for windows that can be guffaw-scrolled
2454  * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
2455  */
2456
2457 static gboolean
2458 gdk_window_gravity_works (void)
2459 {
2460   enum { UNKNOWN, NO, YES };
2461   static gint gravity_works = UNKNOWN;
2462
2463   if (gravity_works == UNKNOWN)
2464     {
2465       GdkWindowAttr attr;
2466       GdkWindow *parent;
2467       GdkWindow *child;
2468       gint y;
2469       
2470       attr.window_type = GDK_WINDOW_TEMP;
2471       attr.wclass = GDK_INPUT_OUTPUT;
2472       attr.x = 0;
2473       attr.y = 0;
2474       attr.width = 100;
2475       attr.height = 100;
2476       attr.event_mask = 0;
2477       
2478       parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
2479       
2480       attr.window_type = GDK_WINDOW_CHILD;
2481       child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
2482
2483       gdk_window_set_static_win_gravity (child, TRUE);
2484       
2485       gdk_window_resize (parent, 100, 110);
2486       gdk_window_move (parent, 0, -10);
2487       gdk_window_move_resize (parent, 0, 0, 100, 100);
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_get_geometry (child, NULL, &y, NULL, NULL, NULL);
2494       
2495       gdk_window_destroy (parent);
2496       gdk_window_destroy (child);
2497   
2498       gravity_works = ((y == -20) ? YES : NO);
2499     }
2500
2501   return (gravity_works == YES);
2502 }
2503
2504 static void
2505 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
2506 {
2507   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2508
2509   g_return_if_fail (window != NULL);
2510
2511   GDK_NOTE (MISC,
2512             g_print ("gdk_window_set_static_bit_gravity: Not implemented\n"));
2513 }
2514
2515 static void
2516 gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
2517 {
2518   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2519
2520   g_return_if_fail (window != NULL);
2521
2522   GDK_NOTE (MISC,
2523             g_print ("gdk_window_set_static_win_gravity: Not implemented\n"));
2524 }
2525
2526 /*************************************************************
2527  * gdk_window_set_static_gravities:
2528  *     Set the bit gravity of the given window to static,
2529  *     and flag it so all children get static subwindow
2530  *     gravity.
2531  *   arguments:
2532  *     window: window for which to set static gravity
2533  *     use_static: Whether to turn static gravity on or off.
2534  *   results:
2535  *     Does the XServer support static gravity?
2536  *************************************************************/
2537
2538 gboolean 
2539 gdk_window_set_static_gravities (GdkWindow *window,
2540                                  gboolean   use_static)
2541 {
2542   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
2543   GList *tmp_list;
2544
2545   g_return_val_if_fail (window != NULL, FALSE);
2546   
2547   if (!use_static == !private->guffaw_gravity)
2548     return TRUE;
2549   
2550   if (use_static && !gdk_window_gravity_works ())
2551     return FALSE;
2552
2553   private->guffaw_gravity = use_static;
2554
2555   gdk_window_set_static_bit_gravity (window, use_static);
2556
2557   tmp_list = private->children;
2558   while (tmp_list)
2559     {
2560       gdk_window_set_static_win_gravity (window, use_static);
2561       
2562       tmp_list = tmp_list->next;
2563     }
2564
2565   return TRUE;
2566 }