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