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