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