]> Pileus Git - ~andy/gtk/blob - gdk/quartz/gdkwindow-quartz.c
gdk/gdkdisplay.h gdk/gdkdrawable.h gdk/gdkevents.h gdk/gdkpango.h
[~andy/gtk] / gdk / quartz / gdkwindow-quartz.c
1 /* gdkwindow-quartz.c
2  *
3  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4  * Copyright (C) 2005-2007 Imendio AB
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include <config.h>
23 #include <Carbon/Carbon.h>
24
25 #include "gdk.h"
26 #include "gdkprivate-quartz.h"
27
28 static gpointer parent_class;
29
30 static GSList *update_windows;
31 static guint   update_idle;
32
33 static GSList *main_window_stack;
34
35 static void update_toplevel_order (void);
36 static void clear_toplevel_order (void);
37
38 #define WINDOW_IS_TOPLEVEL(window)                 \
39   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
40    GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
41
42 NSView *
43 gdk_quartz_window_get_nsview (GdkWindow *window)
44 {
45   GdkWindowObject *private = (GdkWindowObject *)window;
46
47   if (GDK_WINDOW_DESTROYED (window))
48     return NULL;
49
50   return ((GdkWindowImplQuartz *)private->impl)->view;
51 }
52
53 NSWindow *
54 gdk_quartz_window_get_nswindow (GdkWindow *window)
55 {
56   GdkWindowObject *private = (GdkWindowObject *)window;
57
58   if (GDK_WINDOW_DESTROYED (window))
59     return NULL;
60
61   return ((GdkWindowImplQuartz *)private->impl)->toplevel;
62 }
63
64 static void
65 gdk_window_impl_quartz_get_size (GdkDrawable *drawable,
66                                  gint        *width,
67                                  gint        *height)
68 {
69   g_return_if_fail (GDK_IS_WINDOW_IMPL_QUARTZ (drawable));
70
71   if (width)
72     *width = GDK_WINDOW_IMPL_QUARTZ (drawable)->width;
73   if (height)
74     *height = GDK_WINDOW_IMPL_QUARTZ (drawable)->height;
75 }
76
77 static GdkRegion*
78 gdk_window_impl_quartz_get_visible_region (GdkDrawable *drawable)
79 {
80   GdkWindowObject *private = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_QUARTZ (drawable)->wrapper);
81   GdkRectangle rect;
82   GdkWindowImplQuartz *impl;
83   GList *windows = NULL, *l;
84
85   /* FIXME: The clip rectangle should really be cached
86    * and recalculated when the window rectangle changes.
87    */
88   while (private)
89     {
90       windows = g_list_prepend (windows, private);
91
92       if (private->parent == GDK_WINDOW_OBJECT (_gdk_root))
93         break;
94
95       private = private->parent;
96     }
97
98   /* Get rectangle for toplevel window */
99   private = GDK_WINDOW_OBJECT (windows->data);
100   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
101   
102   rect.x = 0;
103   rect.y = 0;
104   rect.width = impl->width;
105   rect.height = impl->height;
106
107   /* Skip toplevel window since we have its rect */
108   for (l = windows->next; l; l = l->next)
109     {
110       private = GDK_WINDOW_OBJECT (l->data);
111       impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
112       GdkRectangle tmp_rect;
113
114       tmp_rect.x = -MIN (0, private->x - rect.x);
115       tmp_rect.y = -MIN (0, private->y - rect.y);
116       tmp_rect.width = MIN (rect.width, impl->width + private->x - rect.x) - MAX (0, private->x - rect.x);
117       tmp_rect.height = MIN (rect.height, impl->height + private->y - rect.y) - MAX (0, private->y - rect.y);
118
119       rect = tmp_rect;
120     }
121   
122   g_list_free (windows);
123   
124   return gdk_region_rectangle (&rect);
125 }
126
127 static void
128 gdk_window_impl_quartz_finalize (GObject *object)
129 {
130   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (object);
131
132   if (impl->nscursor)
133     [impl->nscursor release];
134
135   if (impl->paint_clip_region)
136     gdk_region_destroy (impl->paint_clip_region);
137
138   if (impl->transient_for)
139     g_object_unref (impl->transient_for);
140
141   G_OBJECT_CLASS (parent_class)->finalize (object);
142 }
143
144 static void
145 gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
146 {
147   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
148   GObjectClass *object_class = G_OBJECT_CLASS (klass);
149
150   parent_class = g_type_class_peek_parent (klass);
151
152   object_class->finalize = gdk_window_impl_quartz_finalize;
153
154   drawable_class->get_size = gdk_window_impl_quartz_get_size;
155
156   /* Visible and clip regions are the same */
157   drawable_class->get_clip_region = gdk_window_impl_quartz_get_visible_region;
158   drawable_class->get_visible_region = gdk_window_impl_quartz_get_visible_region;
159 }
160
161 static void
162 gdk_window_impl_quartz_init (GdkWindowImplQuartz *impl)
163 {
164   impl->width = 1;
165   impl->height = 1;
166   impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
167 }
168
169 static void
170 gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable,
171                                            GdkRegion    *region)
172 {
173   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
174   GdkDrawableImplQuartz *drawable_impl;
175   int n_rects;
176   GdkRectangle *rects;
177   GdkPixmap *bg_pixmap;
178   GdkWindow *window;
179
180   drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (impl);
181   bg_pixmap = GDK_WINDOW_OBJECT (drawable_impl->wrapper)->bg_pixmap;
182
183   if (impl->begin_paint_count == 0)
184     impl->paint_clip_region = gdk_region_copy (region);
185   else
186     gdk_region_union (impl->paint_clip_region, region);
187
188   impl->begin_paint_count++;
189
190   if (bg_pixmap == GDK_NO_BG)
191     return;
192
193   gdk_region_get_rectangles (region, &rects, &n_rects);
194
195   if (bg_pixmap == NULL)
196     {
197       CGContextRef cg_context;
198       gfloat r, g, b, a;
199       gint i;
200
201       cg_context = gdk_quartz_drawable_get_context (GDK_DRAWABLE (impl), FALSE);
202       _gdk_quartz_colormap_get_rgba_from_pixel (gdk_drawable_get_colormap (drawable_impl->wrapper),
203                                       GDK_WINDOW_OBJECT (drawable_impl->wrapper)->bg_color.pixel,
204                                       &r, &g, &b, &a);
205  
206       for (i = 0; i < n_rects; i++) 
207         {
208           CGContextSetRGBFillColor (cg_context, r, g, b, a);
209           CGContextFillRect (cg_context,
210                              CGRectMake (rects[i].x, rects[i].y,
211                                          rects[i].width, rects[i].height));
212         }
213
214       gdk_quartz_drawable_release_context (GDK_DRAWABLE (impl), cg_context);
215     }
216   else
217     {
218       int x, y;
219       int x_offset, y_offset;
220       int width, height;
221       GdkGC *gc;
222
223       x_offset = y_offset = 0;
224
225       window = GDK_WINDOW (drawable_impl->wrapper);
226       while (window && bg_pixmap == GDK_PARENT_RELATIVE_BG)
227         {
228           /* If this window should have the same background as the parent,
229            * fetch the parent. (And if the same goes for the parent, fetch
230            * the grandparent, etc.)
231            */
232           x_offset += ((GdkWindowObject *) window)->x;
233           y_offset += ((GdkWindowObject *) window)->y;
234           window = GDK_WINDOW (((GdkWindowObject *) window)->parent);
235           bg_pixmap = ((GdkWindowObject *) window)->bg_pixmap;
236         }
237
238       if (bg_pixmap == NULL || bg_pixmap == GDK_NO_BG || bg_pixmap == GDK_PARENT_RELATIVE_BG)
239         {
240           /* Parent relative background but the parent doesn't have a
241            * pixmap.
242            */ 
243           g_free (rects);
244           return;
245         }
246
247       /* Note: There should be a CG API to draw tiled images, we might
248        * want to look into that for this. 
249        */
250       gc = gdk_gc_new (GDK_DRAWABLE (impl));
251
252       gdk_drawable_get_size (GDK_DRAWABLE (bg_pixmap), &width, &height);
253
254       x = -x_offset;
255       while (x < (rects[0].x + rects[0].width))
256         {
257           if (x + width >= rects[0].x)
258             {
259               y = -y_offset;
260               while (y < (rects[0].y + rects[0].height))
261                 {
262                   if (y + height >= rects[0].y)
263                     gdk_draw_drawable (GDK_DRAWABLE (impl), gc, bg_pixmap, 0, 0, x, y, width, height);
264                   
265                   y += height;
266                 }
267             }
268           x += width;
269         }
270
271       g_object_unref (gc);
272     }
273
274   g_free (rects);
275 }
276
277 static void
278 gdk_window_impl_quartz_end_paint (GdkPaintable *paintable)
279 {
280   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
281
282   impl->begin_paint_count--;
283
284   if (impl->begin_paint_count == 0)
285     {
286       gdk_region_destroy (impl->paint_clip_region);
287       impl->paint_clip_region = NULL;
288     }
289 }
290
291 static void
292 gdk_window_quartz_process_updates_internal (GdkWindow *window)
293 {
294   GdkWindowObject *private = (GdkWindowObject *) window;
295   GdkWindowImplQuartz *impl = (GdkWindowImplQuartz *) private->impl;
296       
297   if (private->update_area)
298     {
299       int i, n_rects;
300       GdkRectangle *rects;
301
302       gdk_region_get_rectangles (private->update_area, &rects, &n_rects);
303
304       gdk_region_destroy (private->update_area);
305       private->update_area = NULL;
306
307       for (i = 0; i < n_rects; i++) 
308         {
309           [impl->view setNeedsDisplayInRect:NSMakeRect (rects[i].x, rects[i].y,
310                                                         rects[i].width, rects[i].height)];
311         }
312
313       [impl->view displayIfNeeded];
314
315       g_free (rects);
316     }
317 }
318
319 static void
320 gdk_window_quartz_process_all_updates (void)
321 {
322   GSList *old_update_windows = update_windows;
323   GSList *tmp_list = update_windows;
324
325   update_idle = 0;
326   update_windows = NULL;
327
328   g_slist_foreach (old_update_windows, (GFunc) g_object_ref, NULL);
329   
330   GDK_QUARTZ_ALLOC_POOL;
331
332   while (tmp_list)
333     {
334       gdk_window_quartz_process_updates_internal (tmp_list->data);
335
336       g_object_unref (tmp_list->data);
337       tmp_list = tmp_list->next;
338     }
339
340   GDK_QUARTZ_RELEASE_POOL;
341
342   g_slist_free (old_update_windows);
343 }
344
345 static gboolean
346 gdk_window_quartz_update_idle (gpointer data)
347 {
348   GDK_THREADS_ENTER ();
349   gdk_window_quartz_process_all_updates ();
350   GDK_THREADS_LEAVE ();
351
352   return FALSE;
353 }
354
355 static void
356 gdk_window_impl_quartz_invalidate_maybe_recurse (GdkPaintable *paintable,
357                                                  GdkRegion    *region,
358                                                  gboolean    (*child_func) (GdkWindow *, gpointer),
359                                                  gpointer      user_data)
360 {
361   GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
362   GdkDrawableImplQuartz *drawable_impl = (GdkDrawableImplQuartz *) window_impl;
363   GdkWindow *window = (GdkWindow *) drawable_impl->wrapper;
364   GdkWindowObject *private = (GdkWindowObject *) window;
365   GdkRegion *visible_region;
366
367   visible_region = gdk_drawable_get_visible_region (window);
368   gdk_region_intersect (visible_region, region);
369
370   if (private->update_area)
371     {
372       gdk_region_union (private->update_area, visible_region);
373       gdk_region_destroy (visible_region);
374     }
375   else
376     {
377       update_windows = g_slist_prepend (update_windows, window);
378       private->update_area = visible_region;
379
380       if (update_idle == 0)
381         update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
382                                        gdk_window_quartz_update_idle, NULL, NULL);
383     }
384 }
385
386 static void
387 gdk_window_impl_quartz_process_updates (GdkPaintable *paintable,
388                                         gboolean      update_children)
389 {
390   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
391   GdkDrawableImplQuartz *drawable_impl = (GdkDrawableImplQuartz *) impl;
392   GdkWindowObject *private = (GdkWindowObject *) drawable_impl->wrapper;
393
394   if (private->update_area)
395     {
396       GDK_QUARTZ_ALLOC_POOL;
397       gdk_window_quartz_process_updates_internal ((GdkWindow *) private);
398       update_windows = g_slist_remove (update_windows, private);
399       GDK_QUARTZ_RELEASE_POOL;
400     }
401 }
402
403 static void
404 gdk_window_impl_quartz_paintable_init (GdkPaintableIface *iface)
405 {
406   iface->begin_paint_region = gdk_window_impl_quartz_begin_paint_region;
407   iface->end_paint = gdk_window_impl_quartz_end_paint;
408
409   iface->invalidate_maybe_recurse = gdk_window_impl_quartz_invalidate_maybe_recurse;
410   iface->process_updates = gdk_window_impl_quartz_process_updates;
411 }
412
413 GType
414 _gdk_window_impl_quartz_get_type (void)
415 {
416   static GType object_type = 0;
417
418   if (!object_type)
419     {
420       const GTypeInfo object_info =
421         {
422           sizeof (GdkWindowImplQuartzClass),
423           (GBaseInitFunc) NULL,
424           (GBaseFinalizeFunc) NULL,
425           (GClassInitFunc) gdk_window_impl_quartz_class_init,
426           NULL,           /* class_finalize */
427           NULL,           /* class_data */
428           sizeof (GdkWindowImplQuartz),
429           0,              /* n_preallocs */
430           (GInstanceInitFunc) gdk_window_impl_quartz_init,
431         };
432
433       const GInterfaceInfo paintable_info = 
434         {
435           (GInterfaceInitFunc) gdk_window_impl_quartz_paintable_init,
436           NULL,
437           NULL
438         };
439
440       object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_QUARTZ,
441                                             "GdkWindowImplQuartz",
442                                             &object_info, 0);
443       g_type_add_interface_static (object_type,
444                                    GDK_TYPE_PAINTABLE,
445                                    &paintable_info);
446     }
447
448   return object_type;
449 }
450
451 GType
452 _gdk_window_impl_get_type (void)
453 {
454   return _gdk_window_impl_quartz_get_type ();
455 }
456
457 static const gchar *
458 get_default_title (void)
459 {
460   const char *title;
461
462   title = g_get_application_name ();
463   if (!title)
464     title = g_get_prgname ();
465
466   return title;
467 }
468
469 gboolean
470 _gdk_quartz_window_is_ancestor (GdkWindow *ancestor,
471                                 GdkWindow *window)
472 {
473   if (ancestor == NULL || window == NULL)
474     return FALSE;
475
476   return (gdk_window_get_parent (window) == ancestor ||
477           _gdk_quartz_window_is_ancestor (ancestor, 
478                                           gdk_window_get_parent (window)));
479 }
480
481 /* FIXME: It would be nice to have one function that takes an NSPoint
482  * and flips the coords for any window.
483  */
484 gint 
485 _gdk_quartz_window_get_inverted_screen_y (gint y)
486 {
487   NSRect rect = [[NSScreen mainScreen] frame];
488
489   return rect.size.height - y;
490 }
491
492 static GdkWindow *
493 find_child_window_helper (GdkWindow *window,
494                           gint       x,
495                           gint       y,
496                           gint       x_offset,
497                           gint       y_offset)
498 {
499   GdkWindowImplQuartz *impl;
500   GList *l;
501
502   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
503
504   if (window == _gdk_root)
505     update_toplevel_order ();
506
507   for (l = impl->sorted_children; l; l = l->next)
508     {
509       GdkWindowObject *child_private = l->data;
510       GdkWindowImplQuartz *child_impl = GDK_WINDOW_IMPL_QUARTZ (child_private->impl);
511       int temp_x, temp_y;
512
513       if (!GDK_WINDOW_IS_MAPPED (child_private))
514         continue;
515
516       temp_x = x_offset + child_private->x;
517       temp_y = y_offset + child_private->y;
518
519       /* Special-case the root window. We have to include the title
520        * bar in the checks, otherwise the window below the title bar
521        * will be found i.e. events punch through. (If we can find a
522        * better way to deal with the events in gdkevents-quartz, this
523        * might not be needed.)
524        */
525       if (window == _gdk_root)
526         {
527           NSRect frame = NSMakeRect (0, 0, 100, 100);
528           NSRect content;
529           int mask;
530           int titlebar_height;
531
532           mask = [child_impl->toplevel styleMask];
533
534           /* Get the title bar height. */
535           content = [NSWindow contentRectForFrameRect:frame
536                                             styleMask:mask];
537           titlebar_height = frame.size.height - content.size.height;
538
539           if (titlebar_height > 0 &&
540               x >= temp_x && y >= temp_y - titlebar_height &&
541               x < temp_x + child_impl->width && y < temp_y)
542             {
543               /* The root means "unknown" i.e. a window not managed by
544                * GDK.
545                */
546               return (GdkWindow *)_gdk_root;
547             }
548         }
549
550       if (x >= temp_x && y >= temp_y &&
551           x < temp_x + child_impl->width && y < temp_y + child_impl->height)
552         {
553           /* Look for child windows. */
554           return find_child_window_helper (l->data,
555                                            x, y,
556                                            temp_x, temp_y);
557         }
558     }
559   
560   return window;
561 }
562
563 /* Given a GdkWindow and coordinates relative to it, returns the
564  * innermost subwindow that contains the point. If the coordinates are
565  * outside the passed in window, NULL is returned.
566  */
567 GdkWindow *
568 _gdk_quartz_window_find_child (GdkWindow *window,
569                                gint       x,
570                                gint       y)
571 {
572   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
573   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
574
575   if (x >= 0 && y >= 0 && x < impl->width && y < impl->height)
576     return find_child_window_helper (window, x, y, 0, 0);
577
578   return NULL;
579 }
580
581 void
582 _gdk_quartz_window_did_become_main (GdkWindow *window)
583 {
584   main_window_stack = g_slist_remove (main_window_stack, window);
585
586   if (GDK_WINDOW_OBJECT (window)->window_type != GDK_WINDOW_TEMP)
587     main_window_stack = g_slist_prepend (main_window_stack, window);
588
589   clear_toplevel_order ();
590 }
591
592 void
593 _gdk_quartz_window_did_resign_main (GdkWindow *window)
594 {
595   GdkWindow *new_window = NULL;
596
597   if (main_window_stack)
598     new_window = main_window_stack->data;
599   else
600     {
601       GList *toplevels;
602
603       toplevels = gdk_window_get_toplevels ();
604       if (toplevels)
605         new_window = toplevels->data;
606       g_list_free (toplevels);
607     }
608
609   if (new_window &&
610       new_window != window &&
611       GDK_WINDOW_IS_MAPPED (new_window) &&
612       GDK_WINDOW_OBJECT (new_window)->window_type != GDK_WINDOW_TEMP)
613     {
614       GdkWindowObject *private = (GdkWindowObject *) new_window;
615       GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
616
617       [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
618     }
619
620   clear_toplevel_order ();
621 }
622
623 GdkWindow *
624 gdk_window_new (GdkWindow     *parent,
625                 GdkWindowAttr *attributes,
626                 gint           attributes_mask)
627 {
628   GdkWindow *window;
629   GdkWindowObject *private;
630   GdkWindowImplQuartz *impl;
631   GdkDrawableImplQuartz *draw_impl;
632   GdkVisual *visual;
633   GdkWindowImplQuartz *parent_impl;
634
635   if (parent && GDK_WINDOW_DESTROYED (parent))
636     return NULL;
637
638   GDK_QUARTZ_ALLOC_POOL;
639
640   if (!parent)
641     parent = _gdk_root;
642
643   window = g_object_new (GDK_TYPE_WINDOW, NULL);
644   private = (GdkWindowObject *)window;
645   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
646   draw_impl = GDK_DRAWABLE_IMPL_QUARTZ (private->impl);
647   draw_impl->wrapper = GDK_DRAWABLE (window);
648
649   private->parent = (GdkWindowObject *)parent;
650   parent_impl = GDK_WINDOW_IMPL_QUARTZ (private->parent->impl);
651
652   private->accept_focus = TRUE;
653   private->focus_on_map = TRUE;
654
655   if (attributes_mask & GDK_WA_X)
656     private->x = attributes->x;
657   else
658     private->x = 0;
659   
660   if (attributes_mask & GDK_WA_Y)
661     private->y = attributes->y;
662   else if (attributes_mask & GDK_WA_X)
663     private->y = 100;
664   else
665     private->y = 0;
666
667   private->event_mask = attributes->event_mask;
668
669   impl->width = attributes->width > 1 ? attributes->width : 1;
670   impl->height = attributes->height > 1 ? attributes->height : 1;
671
672   if (attributes_mask & GDK_WA_VISUAL)
673     visual = attributes->visual;
674   else
675     visual = gdk_screen_get_system_visual (_gdk_screen);
676
677   if (attributes->wclass == GDK_INPUT_ONLY)
678     {
679       /* Backwards compatiblity - we've always ignored
680        * attributes->window_type for input-only windows
681        * before
682        */
683       if (parent == _gdk_root)
684         private->window_type = GDK_WINDOW_TEMP;
685       else
686         private->window_type = GDK_WINDOW_CHILD;
687     }
688   else
689     private->window_type = attributes->window_type;
690
691   /* Sanity checks */
692   switch (private->window_type)
693     {
694     case GDK_WINDOW_TOPLEVEL:
695     case GDK_WINDOW_DIALOG:
696     case GDK_WINDOW_TEMP:
697       if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
698         {
699           g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
700                      "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
701         }
702     case GDK_WINDOW_CHILD:
703       break;
704     default:
705       g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
706       GDK_QUARTZ_RELEASE_POOL;
707       return NULL;
708     }
709
710   if (attributes->wclass == GDK_INPUT_OUTPUT)
711     {
712       private->input_only = FALSE;
713       private->depth = visual->depth;
714
715       if (attributes_mask & GDK_WA_COLORMAP)
716         {
717           draw_impl->colormap = attributes->colormap;
718           g_object_ref (attributes->colormap);
719         }
720       else
721         {
722           if (visual == gdk_screen_get_system_visual (_gdk_screen))
723             {
724               draw_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
725               g_object_ref (draw_impl->colormap);
726             }
727           else if (visual == gdk_screen_get_rgba_visual (_gdk_screen))
728             {
729               draw_impl->colormap = gdk_screen_get_rgba_colormap (_gdk_screen);
730               g_object_ref (draw_impl->colormap);
731             }
732           else
733             {
734               draw_impl->colormap = gdk_colormap_new (visual, FALSE);
735             }
736         }
737
738       private->bg_color.pixel = 0;
739       private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
740     }
741   else
742     {
743       private->depth = 0;
744       private->input_only = TRUE;
745       draw_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
746       g_object_ref (draw_impl->colormap);
747     }
748
749   private->parent->children = g_list_prepend (private->parent->children, window);
750
751   /* Maintain the z-ordered list of children. */
752   if (parent != _gdk_root)
753     parent_impl->sorted_children = g_list_prepend (parent_impl->sorted_children, window);
754   else
755     clear_toplevel_order ();
756
757   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
758                                   (attributes->cursor) :
759                                   NULL));
760
761   switch (attributes->window_type) 
762     {
763     case GDK_WINDOW_TOPLEVEL:
764     case GDK_WINDOW_DIALOG:
765     case GDK_WINDOW_TEMP:
766       {
767         NSRect content_rect;
768         int style_mask;
769         const char *title;
770
771         /* Big hack: We start out outside the screen and move the
772          * window in before showing it. This makes the initial
773          * MouseEntered event work if the window ends up right under
774          * the mouse pointer, bad quartz.
775          */
776         content_rect = NSMakeRect (-500 - impl->width, -500 - impl->height,
777                                    impl->width, impl->height);
778
779         switch (attributes->window_type) 
780           {
781           case GDK_WINDOW_TEMP:
782             style_mask = NSBorderlessWindowMask;
783             break;
784           default:
785             style_mask = (NSTitledWindowMask |
786                           NSClosableWindowMask |
787                           NSMiniaturizableWindowMask |
788                           NSResizableWindowMask);
789           }
790
791         impl->toplevel = [[GdkQuartzWindow alloc] initWithContentRect:content_rect 
792                                                             styleMask:style_mask
793                                                               backing:NSBackingStoreBuffered
794                                                                 defer:NO];
795
796         if (attributes_mask & GDK_WA_TITLE)
797           title = attributes->title;
798         else
799           title = get_default_title ();
800
801         gdk_window_set_title (window, title);
802   
803         if (draw_impl->colormap == gdk_screen_get_rgba_colormap (_gdk_screen))
804           {
805             [impl->toplevel setOpaque:NO];
806             [impl->toplevel setBackgroundColor:[NSColor clearColor]];
807           }
808
809         impl->view = [[GdkQuartzView alloc] initWithFrame:content_rect];
810         [impl->view setGdkWindow:window];
811         [impl->toplevel setContentView:impl->view];
812       }
813       break;
814
815     case GDK_WINDOW_CHILD:
816       {
817         GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (parent)->impl);
818
819         if (attributes->wclass == GDK_INPUT_OUTPUT)
820           {
821             NSRect frame_rect = NSMakeRect (private->x, private->y, impl->width, impl->height);
822         
823             impl->view = [[GdkQuartzView alloc] initWithFrame:frame_rect];
824             
825             [impl->view setGdkWindow:window];
826
827             /* GdkWindows should be hidden by default */
828             [impl->view setHidden:YES];
829             [parent_impl->view addSubview:impl->view];
830           }
831       }
832       break;
833
834     default:
835       g_assert_not_reached ();
836     }
837
838   GDK_QUARTZ_RELEASE_POOL;
839
840   if (attributes_mask & GDK_WA_TYPE_HINT)
841     gdk_window_set_type_hint (window, attributes->type_hint);
842
843   return window;
844 }
845
846 void
847 _gdk_windowing_window_init (void)
848 {
849   GdkWindowObject *private;
850   GdkWindowImplQuartz *impl;
851   GdkDrawableImplQuartz *drawable_impl;
852   NSRect rect;
853
854   g_assert (_gdk_root == NULL);
855
856   _gdk_root = g_object_new (GDK_TYPE_WINDOW, NULL);
857
858   /* Note: This needs to be reworked for multi-screen support. */
859   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (_gdk_root)->impl);
860   rect = [[NSScreen mainScreen] frame];
861   impl->width = rect.size.width;
862   impl->height = rect.size.height;
863
864   private = (GdkWindowObject *)_gdk_root;
865
866   private->state = 0; /* We don't want GDK_WINDOW_STATE_WITHDRAWN here */
867   private->window_type = GDK_WINDOW_ROOT;
868   private->depth = 24;
869
870   drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (private->impl);
871   
872   drawable_impl->wrapper = GDK_DRAWABLE (private);
873   drawable_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
874   g_object_ref (drawable_impl->colormap);
875 }
876
877 void
878 _gdk_windowing_window_destroy (GdkWindow *window,
879                                gboolean   recursing,
880                                gboolean   foreign_destroy)
881 {
882   GdkWindowObject *private;
883   GdkWindowImplQuartz *impl;
884   GdkWindowObject *parent;
885   GdkWindow *mouse_window;
886
887   private = GDK_WINDOW_OBJECT (window);
888   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
889
890   update_windows = g_slist_remove (update_windows, window);
891   main_window_stack = g_slist_remove (main_window_stack, window);
892
893   g_list_free (impl->sorted_children);
894   impl->sorted_children = NULL;
895
896   parent = private->parent;
897   if (parent)
898     {
899       GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (parent->impl);
900
901       parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window);
902     }
903
904   /* If the destroyed window was targeted for a pointer or keyboard
905    * grab, release the grab.
906    */
907   if (window == _gdk_quartz_pointer_grab_window)
908     gdk_pointer_ungrab (0);
909
910   if (window == _gdk_quartz_keyboard_grab_window)
911     gdk_keyboard_ungrab (0);
912
913   _gdk_quartz_drawable_finish (GDK_DRAWABLE (impl));
914
915   mouse_window = _gdk_quartz_events_get_mouse_window (FALSE);
916   if (window == mouse_window ||
917       _gdk_quartz_window_is_ancestor (window, mouse_window))
918     _gdk_quartz_events_update_mouse_window (_gdk_root);
919
920   if (!recursing && !foreign_destroy)
921     {
922       GDK_QUARTZ_ALLOC_POOL;
923
924       if (impl->toplevel)
925         [impl->toplevel close];
926       else if (impl->view)
927         [impl->view removeFromSuperview];
928
929       GDK_QUARTZ_RELEASE_POOL;
930     }
931 }
932
933 void
934 _gdk_windowing_window_destroy_foreign (GdkWindow *window)
935 {
936   /* Foreign windows aren't supported in OSX. */
937 }
938
939 static gboolean
940 all_parents_shown (GdkWindowObject *private)
941 {
942   while (GDK_WINDOW_IS_MAPPED (private))
943     {
944       if (private->parent)
945         private = (GdkWindowObject *)private->parent;
946       else
947         return TRUE;
948     }
949
950   return FALSE;
951 }
952
953 /* Note: the raise argument is not really used, it doesn't seem
954  * possible to show a window without raising it?
955  */
956 static void
957 show_window_internal (GdkWindow *window,
958                       gboolean   raise)
959 {
960   GdkWindowObject *private;
961   GdkWindowImplQuartz *impl;
962   gboolean focus_on_map;
963
964   if (GDK_WINDOW_DESTROYED (window))
965     return;
966
967   GDK_QUARTZ_ALLOC_POOL;
968
969   private = (GdkWindowObject *)window;
970   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
971
972   if (!GDK_WINDOW_IS_MAPPED (window))
973     focus_on_map = private->focus_on_map;
974   else
975     focus_on_map = TRUE;
976
977   if (impl->toplevel)
978     {
979       gboolean make_key;
980
981       /* Move the window into place, to guarantee that we get the
982        * initial MouseEntered event.
983        */
984       make_key = (private->accept_focus && focus_on_map && raise && 
985                   private->window_type != GDK_WINDOW_TEMP);
986
987       [(GdkQuartzWindow*)impl->toplevel showAndMakeKey:make_key];
988     }
989   else
990     {
991       [impl->view setHidden:NO];
992     }
993
994   [impl->view setNeedsDisplay:YES];
995
996   if (all_parents_shown (private->parent))
997     _gdk_quartz_events_send_map_events (window);
998
999   gdk_synthesize_window_state (window, GDK_WINDOW_STATE_WITHDRAWN, 0);
1000
1001   if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
1002     gdk_window_maximize (window);
1003
1004   if (private->state & GDK_WINDOW_STATE_ICONIFIED)
1005     gdk_window_iconify (window);
1006
1007   if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1008     _gdk_quartz_window_attach_to_parent (window);
1009
1010   GDK_QUARTZ_RELEASE_POOL;
1011 }
1012
1013 /* Temporarily unsets the parent window, if the window is a
1014  * transient. 
1015  */
1016 void
1017 _gdk_quartz_window_detach_from_parent (GdkWindow *window)
1018 {
1019   GdkWindowImplQuartz *impl;
1020
1021   g_return_if_fail (GDK_IS_WINDOW (window));
1022
1023   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
1024   
1025   g_return_if_fail (impl->toplevel != NULL);
1026
1027   if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1028     {
1029       GdkWindowImplQuartz *parent_impl;
1030
1031       parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (impl->transient_for)->impl);
1032       [parent_impl->toplevel removeChildWindow:impl->toplevel];
1033     }
1034 }
1035
1036 /* Re-sets the parent window, if the window is a transient. */
1037 void
1038 _gdk_quartz_window_attach_to_parent (GdkWindow *window)
1039 {
1040   GdkWindowImplQuartz *impl;
1041
1042   g_return_if_fail (GDK_IS_WINDOW (window));
1043
1044   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
1045   
1046   g_return_if_fail (impl->toplevel != NULL);
1047
1048   if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1049     {
1050       GdkWindowImplQuartz *parent_impl;
1051
1052       parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (impl->transient_for)->impl);
1053       [parent_impl->toplevel addChildWindow:impl->toplevel ordered:NSWindowAbove];
1054     }
1055 }
1056
1057 void
1058 gdk_window_show_unraised (GdkWindow *window)
1059 {
1060   g_return_if_fail (GDK_IS_WINDOW (window));
1061
1062   show_window_internal (window, FALSE);
1063 }
1064
1065 void
1066 gdk_window_show (GdkWindow *window)
1067 {
1068   g_return_if_fail (GDK_IS_WINDOW (window));
1069
1070   show_window_internal (window, TRUE);
1071 }
1072
1073 void
1074 gdk_window_hide (GdkWindow *window)
1075 {
1076   GdkWindowObject *private = (GdkWindowObject *)window;
1077   GdkWindowImplQuartz *impl;
1078   GdkWindow *mouse_window;
1079
1080   g_return_if_fail (GDK_IS_WINDOW (window));
1081
1082   if (GDK_WINDOW_DESTROYED (window))
1083     return;
1084
1085   mouse_window = _gdk_quartz_events_get_mouse_window (FALSE);
1086   if (window == mouse_window || 
1087       _gdk_quartz_window_is_ancestor (window, mouse_window))
1088     _gdk_quartz_events_update_mouse_window (_gdk_root);
1089
1090   if (GDK_WINDOW_IS_MAPPED (window))
1091     gdk_synthesize_window_state (window,
1092                                  0,
1093                                  GDK_WINDOW_STATE_WITHDRAWN);
1094
1095   _gdk_window_clear_update_area (window);
1096
1097   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
1098
1099   if (impl->toplevel) 
1100     {
1101       NSRect content_rect;
1102       NSRect frame_rect;
1103
1104      /* Update main window. */
1105       main_window_stack = g_slist_remove (main_window_stack, window);
1106       if ([NSApp mainWindow] == impl->toplevel)
1107         _gdk_quartz_window_did_resign_main (window);
1108
1109       if (impl->transient_for)
1110         _gdk_quartz_window_detach_from_parent (window);
1111
1112       [(GdkQuartzWindow*)impl->toplevel hide];
1113     }
1114   else if (impl->view)
1115     {
1116       [impl->view setHidden:YES];
1117     }
1118
1119   if (window == _gdk_quartz_pointer_grab_window)
1120     gdk_pointer_ungrab (0);
1121
1122   if (window == _gdk_quartz_keyboard_grab_window)
1123     gdk_keyboard_ungrab (0);
1124 }
1125
1126 void
1127 gdk_window_withdraw (GdkWindow *window)
1128 {
1129   gdk_window_hide (window);
1130 }
1131
1132 static void
1133 move_resize_window_internal (GdkWindow *window,
1134                              gint       x,
1135                              gint       y,
1136                              gint       width,
1137                              gint       height)
1138 {
1139   GdkWindowObject *private = (GdkWindowObject *)window;
1140   GdkWindowImplQuartz *impl;
1141   GdkRectangle old_visible;
1142   GdkRectangle new_visible;
1143   GdkRectangle scroll_rect;
1144   GdkRegion *old_region;
1145   GdkRegion *expose_region;
1146   NSSize delta;
1147
1148   if (GDK_WINDOW_DESTROYED (window))
1149     return;
1150
1151   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
1152
1153   if ((x == -1 || (x == private->x)) &&
1154       (y == -1 || (y == private->y)) &&
1155       (width == -1 || (width == impl->width)) &&
1156       (height == -1 || (height == impl->height)))
1157     {
1158       return;
1159     }
1160
1161   if (!impl->toplevel)
1162     {
1163       /* The previously visible area of this window in a coordinate
1164        * system rooted at the origin of this window.
1165        */
1166       old_visible.x = -private->x;
1167       old_visible.y = -private->y;
1168
1169       gdk_window_get_size (GDK_DRAWABLE (private->parent), 
1170                            &old_visible.width, 
1171                            &old_visible.height);
1172     }
1173
1174   if (x != -1)
1175     {
1176       delta.width = x - private->x;
1177       private->x = x;
1178     }
1179   else
1180     {
1181       delta.width = 0;
1182     }
1183
1184   if (y != -1)
1185     {
1186       delta.height = y - private->y;
1187       private->y = y;
1188     }
1189   else
1190     {
1191       delta.height = 0;
1192     }
1193
1194   if (width != -1)
1195     impl->width = width;
1196
1197   if (height != -1)
1198     impl->height = height;
1199
1200   GDK_QUARTZ_ALLOC_POOL;
1201
1202   if (impl->toplevel)
1203     {
1204       NSRect content_rect;
1205       NSRect frame_rect;
1206
1207       /* We don't update the NSWindow while unmapped, since we move windows
1208        * off-screen when hiding in order for MouseEntered to be triggered
1209        * reliably when showing windows and they appear under the mouse.
1210        */
1211       if (GDK_WINDOW_IS_MAPPED (window))
1212         {
1213           content_rect =  NSMakeRect (private->x,
1214                                       _gdk_quartz_window_get_inverted_screen_y (private->y + impl->height),
1215                                       impl->width, impl->height);
1216
1217           frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
1218           [impl->toplevel setFrame:frame_rect display:YES];
1219         }
1220     }
1221   else 
1222     {
1223       if (!private->input_only)
1224         {
1225           NSRect nsrect;
1226
1227           nsrect = NSMakeRect (private->x, private->y, impl->width, impl->height);
1228
1229           /* The newly visible area of this window in a coordinate
1230            * system rooted at the origin of this window.
1231            */
1232           new_visible.x = -private->x;
1233           new_visible.y = -private->y;
1234           new_visible.width = old_visible.width;   /* parent has not changed size */
1235           new_visible.height = old_visible.height; /* parent has not changed size */
1236
1237           expose_region = gdk_region_rectangle (&new_visible);
1238           old_region = gdk_region_rectangle (&old_visible);
1239           gdk_region_subtract (expose_region, old_region);
1240
1241           /* Determine what (if any) part of the previously visible
1242            * part of the window can be copied without a redraw
1243            */
1244           scroll_rect = old_visible;
1245           scroll_rect.x -= delta.width;
1246           scroll_rect.y -= delta.height;
1247           gdk_rectangle_intersect (&scroll_rect, &old_visible, &scroll_rect);
1248
1249           if (!gdk_region_empty (expose_region))
1250             {
1251               GdkRectangle* rects;
1252               gint n_rects;
1253               gint n;
1254
1255               if (scroll_rect.width != 0 && scroll_rect.height != 0)
1256                 {
1257                   [impl->view scrollRect:NSMakeRect (scroll_rect.x,
1258                                                      scroll_rect.y,
1259                                                      scroll_rect.width,
1260                                                      scroll_rect.height)
1261                                       by:delta];
1262                 }
1263
1264               [impl->view setFrame:nsrect];
1265
1266               gdk_region_get_rectangles (expose_region, &rects, &n_rects);
1267
1268               for (n = 0; n < n_rects; ++n)
1269                 {
1270                   [impl->view setNeedsDisplayInRect:NSMakeRect (rects[n].x,
1271                                                                 rects[n].y,
1272                                                                 rects[n].width,
1273                                                                 rects[n].height)];
1274                 }
1275
1276               g_free (rects);
1277             }
1278           else
1279             {
1280               [impl->view setFrame:nsrect];
1281               [impl->view setNeedsDisplay:YES];
1282             }
1283
1284           gdk_region_destroy (expose_region);
1285           gdk_region_destroy (old_region);
1286         }
1287     }
1288
1289   GDK_QUARTZ_RELEASE_POOL;
1290 }
1291
1292 void
1293 gdk_window_move (GdkWindow *window,
1294                  gint       x,
1295                  gint       y)
1296 {
1297   g_return_if_fail (GDK_IS_WINDOW (window));
1298
1299   if (((GdkWindowObject *)window)->state & GDK_WINDOW_STATE_FULLSCREEN)
1300     return;
1301
1302   move_resize_window_internal (window, x, y, -1, -1);
1303 }
1304
1305 void
1306 gdk_window_resize (GdkWindow *window,
1307                    gint       width,
1308                    gint       height)
1309 {
1310   g_return_if_fail (GDK_IS_WINDOW (window));
1311
1312   if (((GdkWindowObject *)window)->state & GDK_WINDOW_STATE_FULLSCREEN)
1313     return;
1314
1315   if (width < 1)
1316     width = 1;
1317   if (height < 1)
1318     height = 1;
1319
1320   move_resize_window_internal (window, -1, -1, width, height);
1321 }
1322
1323 void
1324 gdk_window_move_resize (GdkWindow *window,
1325                         gint       x,
1326                         gint       y,
1327                         gint       width,
1328                         gint       height)
1329 {
1330   if (width < 1)
1331     width = 1;
1332   if (height < 1)
1333     height = 1;
1334
1335   move_resize_window_internal (window, x, y, width, height);
1336 }
1337
1338 void
1339 gdk_window_reparent (GdkWindow *window,
1340                      GdkWindow *new_parent,
1341                      gint       x,
1342                      gint       y)
1343 {
1344   g_warning ("gdk_window_reparent: %p %p (%d, %d)", 
1345              window, new_parent, x, y);
1346
1347   /* FIXME: Implement */
1348 }
1349
1350 void
1351 _gdk_windowing_window_clear_area (GdkWindow *window,
1352                                   gint       x,
1353                                   gint       y,
1354                                   gint       width,
1355                                   gint       height)
1356 {
1357   /* FIXME: Implement */
1358 }
1359
1360 void
1361 _gdk_windowing_window_clear_area_e (GdkWindow *window,
1362                                     gint       x,
1363                                     gint       y,
1364                                     gint       width,
1365                                     gint       height)
1366 {
1367   /* FIXME: Implement */
1368 }
1369
1370 /* Get the toplevel ordering from NSApp and update our own list. We do
1371  * this on demand since the NSApp's list is not up to date directly
1372  * after we get windowDidBecomeMain.
1373  */
1374 static void
1375 update_toplevel_order (void)
1376 {
1377   GdkWindowObject *root;
1378   GdkWindowImplQuartz *root_impl;
1379   NSEnumerator *enumerator;
1380   id nswindow;
1381   GList *toplevels = NULL;
1382
1383   root = GDK_WINDOW_OBJECT (_gdk_root);
1384   root_impl = GDK_WINDOW_IMPL_QUARTZ (root->impl);
1385
1386   if (root_impl->sorted_children)
1387     return;
1388
1389   GDK_QUARTZ_ALLOC_POOL;
1390
1391   enumerator = [[NSApp orderedWindows] objectEnumerator];
1392   while ((nswindow = [enumerator nextObject]))
1393     {
1394       GdkWindow *window;
1395
1396       if (![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
1397         continue;
1398
1399       window = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
1400       toplevels = g_list_prepend (toplevels, window);
1401     }
1402
1403   GDK_QUARTZ_RELEASE_POOL;
1404
1405   root_impl->sorted_children = g_list_reverse (toplevels);
1406 }
1407
1408 static void
1409 clear_toplevel_order (void)
1410 {
1411   GdkWindowObject *root;
1412   GdkWindowImplQuartz *root_impl;
1413
1414   root = GDK_WINDOW_OBJECT (_gdk_root);
1415   root_impl = GDK_WINDOW_IMPL_QUARTZ (root->impl);
1416
1417   g_list_free (root_impl->sorted_children);
1418   root_impl->sorted_children = NULL;
1419 }
1420
1421 void
1422 gdk_window_raise (GdkWindow *window)
1423 {
1424   g_return_if_fail (GDK_IS_WINDOW (window));
1425
1426   if (GDK_WINDOW_DESTROYED (window))
1427     return;
1428
1429   if (WINDOW_IS_TOPLEVEL (window))
1430     {
1431       GdkWindowImplQuartz *impl;
1432
1433       impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
1434       [impl->toplevel orderFront:impl->toplevel];
1435
1436       clear_toplevel_order ();
1437     }
1438   else
1439     {
1440       GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
1441
1442       if (parent)
1443         {
1444           GdkWindowImplQuartz *impl;
1445
1446           impl = (GdkWindowImplQuartz *)parent->impl;
1447
1448           impl->sorted_children = g_list_remove (impl->sorted_children, window);
1449           impl->sorted_children = g_list_prepend (impl->sorted_children, window);
1450         }
1451     }
1452 }
1453
1454 void
1455 gdk_window_lower (GdkWindow *window)
1456 {
1457   g_return_if_fail (GDK_IS_WINDOW (window));
1458
1459   if (GDK_WINDOW_DESTROYED (window))
1460     return;
1461
1462   if (WINDOW_IS_TOPLEVEL (window))
1463     {
1464       GdkWindowImplQuartz *impl;
1465
1466       impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
1467       [impl->toplevel orderBack:impl->toplevel];
1468
1469       clear_toplevel_order ();
1470     }
1471   else
1472     {
1473       GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
1474
1475       if (parent)
1476         {
1477           GdkWindowImplQuartz *impl;
1478
1479           impl = (GdkWindowImplQuartz *)parent->impl;
1480
1481           impl->sorted_children = g_list_remove (impl->sorted_children, window);
1482           impl->sorted_children = g_list_append (impl->sorted_children, window);
1483         }
1484     }
1485 }
1486
1487 void
1488 gdk_window_set_background (GdkWindow      *window,
1489                            const GdkColor *color)
1490 {
1491   GdkWindowObject *private = (GdkWindowObject *)window;
1492   GdkWindowImplQuartz *impl;
1493
1494   g_return_if_fail (GDK_IS_WINDOW (window));
1495
1496   if (GDK_WINDOW_DESTROYED (window))
1497     return;
1498
1499   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
1500
1501   private->bg_color = *color;
1502
1503   if (private->bg_pixmap &&
1504       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1505       private->bg_pixmap != GDK_NO_BG)
1506     g_object_unref (private->bg_pixmap);
1507   
1508   private->bg_pixmap = NULL;
1509 }
1510
1511 void
1512 gdk_window_set_back_pixmap (GdkWindow *window,
1513                             GdkPixmap *pixmap,
1514                             gboolean   parent_relative)
1515 {
1516   GdkWindowObject *private = (GdkWindowObject *)window;
1517
1518   g_return_if_fail (GDK_IS_WINDOW (window));
1519   g_return_if_fail (pixmap == NULL || !parent_relative);
1520   g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
1521
1522   if (GDK_WINDOW_DESTROYED (window))
1523     return;
1524
1525   if (private->bg_pixmap &&
1526       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1527       private->bg_pixmap != GDK_NO_BG)
1528     g_object_unref (private->bg_pixmap);
1529
1530   if (parent_relative)
1531     {
1532       private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
1533       GDK_NOTE (MISC, g_print (G_STRLOC ": setting background pixmap to parent_relative\n"));
1534     }
1535   else
1536     {
1537       if (pixmap)
1538         {
1539           g_object_ref (pixmap);
1540           private->bg_pixmap = pixmap;
1541         }
1542       else
1543         {
1544           private->bg_pixmap = GDK_NO_BG;
1545         }
1546     }
1547 }
1548
1549 void
1550 gdk_window_set_cursor (GdkWindow *window,
1551                        GdkCursor *cursor)
1552 {
1553   GdkWindowImplQuartz *impl;
1554   GdkCursorPrivate *cursor_private;
1555   NSCursor *nscursor;
1556
1557   g_return_if_fail (GDK_IS_WINDOW (window));
1558
1559   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
1560   cursor_private = (GdkCursorPrivate *)cursor;
1561
1562   if (GDK_WINDOW_DESTROYED (window))
1563     return;
1564
1565   GDK_QUARTZ_ALLOC_POOL;
1566
1567   if (!cursor)
1568     nscursor = NULL;
1569   else 
1570     nscursor = [cursor_private->nscursor retain];
1571
1572   if (impl->nscursor)
1573     [impl->nscursor release];
1574
1575   impl->nscursor = nscursor;
1576
1577   GDK_QUARTZ_RELEASE_POOL;
1578
1579   _gdk_quartz_events_update_cursor (_gdk_quartz_events_get_mouse_window (TRUE));
1580 }
1581
1582 void
1583 gdk_window_get_geometry (GdkWindow *window,
1584                          gint      *x,
1585                          gint      *y,
1586                          gint      *width,
1587                          gint      *height,
1588                          gint      *depth)
1589 {
1590   GdkWindowImplQuartz *impl;
1591   NSRect ns_rect;
1592
1593   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1594
1595   if (!window)
1596     window = _gdk_root;
1597   
1598   if (GDK_WINDOW_DESTROYED (window))
1599     return;
1600
1601   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
1602   if (window == _gdk_root)
1603     {
1604       if (x) 
1605         *x = 0;
1606       if (y) 
1607         *y = 0;
1608
1609       if (width) 
1610         *width = impl->width;
1611       if (height)
1612         *height = impl->height;
1613     }
1614   else if (WINDOW_IS_TOPLEVEL (window))
1615     {
1616       ns_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
1617
1618       /* This doesn't work exactly as in X. There doesn't seem to be a
1619        * way to get the coords relative to the parent window (usually
1620        * the window frame), but that seems useless except for
1621        * borderless windows where it's relative to the root window. So
1622        * we return (0, 0) (should be something like (0, 22)) for
1623        * windows with borders and the root relative coordinates
1624        * otherwise.
1625        */
1626       if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
1627         {
1628           if (x)
1629             *x = ns_rect.origin.x;
1630           if (y)
1631             *y = _gdk_quartz_window_get_inverted_screen_y (ns_rect.origin.y + ns_rect.size.height);
1632         }
1633       else 
1634         {
1635           if (x)
1636             *x = 0;
1637           if (y)
1638             *y = 0;
1639         }
1640
1641       if (width)
1642         *width = ns_rect.size.width;
1643       if (height)
1644         *height = ns_rect.size.height;
1645     }
1646   else
1647     {
1648       ns_rect = [impl->view frame];
1649       
1650       if (x)
1651         *x = ns_rect.origin.x;
1652       if (y)
1653         *y = ns_rect.origin.y;
1654       if (width)
1655         *width  = ns_rect.size.width;
1656       if (height)
1657         *height = ns_rect.size.height;
1658     }
1659     
1660   if (depth)
1661       *depth = gdk_drawable_get_depth (window);
1662 }
1663
1664 gboolean
1665 gdk_window_get_origin (GdkWindow *window,
1666                        gint      *x,
1667                        gint      *y)
1668 {
1669   GdkWindowObject *private;
1670   int tmp_x = 0, tmp_y = 0;
1671   GdkWindow *toplevel;
1672   NSRect content_rect;
1673   GdkWindowImplQuartz *impl;
1674
1675   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1676
1677   if (GDK_WINDOW_DESTROYED (window)) 
1678     {
1679       if (x) 
1680         *x = 0;
1681       if (y) 
1682         *y = 0;
1683       
1684       return FALSE;
1685     }
1686
1687   if (window == _gdk_root)
1688     {
1689       *x = 0;
1690       *y = 0;
1691       return TRUE;
1692     }
1693   
1694   private = GDK_WINDOW_OBJECT (window);
1695
1696   toplevel = gdk_window_get_toplevel (window);
1697   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
1698
1699   content_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
1700
1701   tmp_x = content_rect.origin.x;
1702   tmp_y = _gdk_quartz_window_get_inverted_screen_y (content_rect.origin.y + content_rect.size.height);
1703
1704   while (private != GDK_WINDOW_OBJECT (toplevel))
1705     {
1706       tmp_x += private->x;
1707       tmp_y += private->y;
1708
1709       private = private->parent;
1710     }
1711
1712   if (x)
1713     *x = tmp_x;
1714   if (y)
1715     *y = tmp_y;
1716
1717   return TRUE;
1718 }
1719
1720 gboolean
1721 gdk_window_get_deskrelative_origin (GdkWindow *window,
1722                                     gint      *x,
1723                                     gint      *y)
1724 {
1725   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1726
1727   return gdk_window_get_origin (window, x, y);
1728 }
1729
1730 void
1731 gdk_window_get_root_origin (GdkWindow *window,
1732                             gint      *x,
1733                             gint      *y)
1734 {
1735   GdkRectangle rect;
1736
1737   g_return_if_fail (GDK_IS_WINDOW (window));
1738
1739   rect.x = 0;
1740   rect.y = 0;
1741   
1742   gdk_window_get_frame_extents (window, &rect);
1743
1744   if (x)
1745     *x = rect.x;
1746
1747   if (y)
1748     *y = rect.y;
1749 }
1750
1751 /* Returns coordinates relative to the root. */
1752 void
1753 _gdk_windowing_get_pointer (GdkDisplay       *display,
1754                             GdkScreen       **screen,
1755                             gint             *x,
1756                             gint             *y,
1757                             GdkModifierType  *mask)
1758 {
1759   g_return_if_fail (display == _gdk_display);
1760   
1761   *screen = _gdk_screen;
1762   _gdk_windowing_window_get_pointer (_gdk_display, _gdk_root, x, y, mask);
1763 }
1764
1765 /* Returns coordinates relative to the passed in window. */
1766 GdkWindow *
1767 _gdk_windowing_window_get_pointer (GdkDisplay      *display,
1768                                    GdkWindow       *window,
1769                                    gint            *x,
1770                                    gint            *y,
1771                                    GdkModifierType *mask)
1772 {
1773   GdkWindowObject *toplevel;
1774   GdkWindowObject *private;
1775   NSPoint point;
1776   gint x_tmp, y_tmp;
1777   GdkWindow *found_window;
1778
1779   if (GDK_WINDOW_DESTROYED (window))
1780     {
1781       *x = 0;
1782       *y = 0;
1783       *mask = 0;
1784       return NULL;
1785     }
1786   
1787   toplevel = GDK_WINDOW_OBJECT (gdk_window_get_toplevel (window));
1788
1789   *mask = _gdk_quartz_events_get_current_event_mask ();
1790
1791   /* Get the y coordinate, needs to be flipped. */
1792   if (window == _gdk_root)
1793     {
1794       point = [NSEvent mouseLocation];
1795       x_tmp = point.x;
1796       y_tmp = _gdk_quartz_window_get_inverted_screen_y (point.y);
1797     }
1798   else
1799     {
1800       GdkWindowImplQuartz *impl;
1801       NSWindow *nswindow;
1802
1803       impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
1804       nswindow = impl->toplevel;
1805
1806       point = [nswindow mouseLocationOutsideOfEventStream];
1807       x_tmp = point.x;
1808       y_tmp = impl->height - point.y;
1809     }
1810
1811   /* The coords are relative to the toplevel of the passed in window
1812    * at this point, make them relative to the passed in window:
1813    */
1814   private = GDK_WINDOW_OBJECT (window);
1815   while (private != toplevel)
1816     {
1817       x_tmp -= private->x;
1818       y_tmp -= private->y;
1819
1820       private = private->parent;
1821     }
1822
1823   found_window = _gdk_quartz_window_find_child (window, x_tmp, y_tmp);
1824
1825   /* We never return the root window. */
1826   if (found_window == _gdk_root)
1827     found_window = NULL;
1828
1829   *x = x_tmp;
1830   *y = y_tmp;
1831
1832   return found_window;
1833 }
1834
1835 void
1836 gdk_display_warp_pointer (GdkDisplay *display,
1837                           GdkScreen  *screen,
1838                           gint        x,
1839                           gint        y)
1840 {
1841   CGDisplayMoveCursorToPoint (CGMainDisplayID (), CGPointMake (x, y));
1842 }
1843
1844 /* Returns coordinates relative to the found window. */
1845 GdkWindow *
1846 _gdk_windowing_window_at_pointer (GdkDisplay *display,
1847                                   gint       *win_x,
1848                                   gint       *win_y)
1849 {
1850   GdkModifierType mask;
1851   GdkWindow *found_window;
1852   gint x, y;
1853
1854   found_window = _gdk_windowing_window_get_pointer (display,
1855                                                     _gdk_root,
1856                                                     &x, &y,
1857                                                     &mask);
1858   if (found_window)
1859     {
1860       GdkWindowObject *private;
1861
1862       /* The coordinates returned above are relative the root, we want
1863        * coordinates relative the window here. 
1864        */
1865       private = GDK_WINDOW_OBJECT (found_window);
1866       while (private != GDK_WINDOW_OBJECT (_gdk_root))
1867         {
1868           x -= private->x;
1869           y -= private->y;
1870           
1871           private = private->parent;
1872         }
1873
1874       *win_x = x;
1875       *win_y = y;
1876     }
1877   else
1878     {
1879       /* Mimic the X backend here, -1,-1 for unknown windows. */
1880       *win_x = -1;
1881       *win_y = -1;
1882     }
1883
1884   return found_window;
1885 }
1886
1887 GdkEventMask  
1888 gdk_window_get_events (GdkWindow *window)
1889 {
1890   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1891
1892   if (GDK_WINDOW_DESTROYED (window))
1893     return 0;
1894   else
1895     return GDK_WINDOW_OBJECT (window)->event_mask;
1896 }
1897
1898 void          
1899 gdk_window_set_events (GdkWindow       *window,
1900                        GdkEventMask     event_mask)
1901 {
1902   g_return_if_fail (GDK_IS_WINDOW (window));
1903
1904   if (!GDK_WINDOW_DESTROYED (window))
1905     {
1906       GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
1907     }
1908 }
1909
1910 void
1911 gdk_window_set_urgency_hint (GdkWindow *window,
1912                              gboolean   urgent)
1913 {
1914   /* FIXME: Implement */
1915 }
1916
1917 void 
1918 gdk_window_set_geometry_hints (GdkWindow         *window,
1919                                const GdkGeometry *geometry,
1920                                GdkWindowHints     geom_mask)
1921 {
1922   GdkWindowImplQuartz *impl;
1923
1924   g_return_if_fail (GDK_IS_WINDOW (window));
1925   g_return_if_fail (geometry != NULL);
1926
1927   if (GDK_WINDOW_DESTROYED (window))
1928     return;
1929   
1930   impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl);
1931   if (!impl->toplevel)
1932     return;
1933
1934   if (geom_mask & GDK_HINT_POS)
1935     {
1936       /* FIXME: Implement */
1937     }
1938
1939   if (geom_mask & GDK_HINT_USER_POS)
1940     {
1941       /* FIXME: Implement */
1942     }
1943
1944   if (geom_mask & GDK_HINT_USER_SIZE)
1945     {
1946       /* FIXME: Implement */
1947     }
1948   
1949   if (geom_mask & GDK_HINT_MIN_SIZE)
1950     {
1951       NSSize size;
1952
1953       size.width = geometry->min_width;
1954       size.height = geometry->min_height;
1955
1956       [impl->toplevel setContentMinSize:size];
1957     }
1958   
1959   if (geom_mask & GDK_HINT_MAX_SIZE)
1960     {
1961       NSSize size;
1962
1963       size.width = geometry->max_width;
1964       size.height = geometry->max_height;
1965
1966       [impl->toplevel setContentMaxSize:size];
1967     }
1968   
1969   if (geom_mask & GDK_HINT_BASE_SIZE)
1970     {
1971       /* FIXME: Implement */
1972     }
1973   
1974   if (geom_mask & GDK_HINT_RESIZE_INC)
1975     {
1976       NSSize size;
1977
1978       size.width = geometry->width_inc;
1979       size.height = geometry->height_inc;
1980
1981       [impl->toplevel setContentResizeIncrements:size];
1982     }
1983   
1984   if (geom_mask & GDK_HINT_ASPECT)
1985     {
1986       /* FIXME: Implement */
1987     }
1988
1989   if (geom_mask & GDK_HINT_WIN_GRAVITY)
1990     {
1991       /* FIXME: Implement */
1992     }
1993 }
1994
1995 void
1996 gdk_window_set_title (GdkWindow   *window,
1997                       const gchar *title)
1998 {
1999   GdkWindowImplQuartz *impl;
2000
2001   g_return_if_fail (GDK_IS_WINDOW (window));
2002   g_return_if_fail (title != NULL);
2003
2004   if (GDK_WINDOW_DESTROYED (window))
2005     return;
2006
2007   impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *)window)->impl);
2008
2009   if (impl->toplevel)
2010     {
2011       GDK_QUARTZ_ALLOC_POOL;
2012       [impl->toplevel setTitle:[NSString stringWithUTF8String:title]];
2013       GDK_QUARTZ_RELEASE_POOL;
2014     }
2015 }
2016
2017 void          
2018 gdk_window_set_role (GdkWindow   *window,
2019                      const gchar *role)
2020 {
2021   /* FIXME: Implement */
2022 }
2023
2024 void
2025 gdk_window_set_transient_for (GdkWindow *window, 
2026                               GdkWindow *parent)
2027 {
2028   GdkWindowImplQuartz *window_impl;
2029   GdkWindowImplQuartz *parent_impl;
2030
2031   if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (parent))
2032     return;
2033
2034   window_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2035   if (!window_impl->toplevel)
2036     return;
2037
2038   GDK_QUARTZ_ALLOC_POOL;
2039
2040   if (window_impl->transient_for)
2041     {
2042       _gdk_quartz_window_detach_from_parent (window);
2043
2044       g_object_unref (window_impl->transient_for);
2045       window_impl->transient_for = NULL;
2046     }
2047
2048   parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (parent)->impl);
2049   if (parent_impl->toplevel)
2050     {
2051       /* We save the parent because it needs to be unset/reset when
2052        * hiding and showing the window. 
2053        */
2054
2055       /* We don't set transients for tooltips, they are already
2056        * handled by the window level being the top one. If we do, then
2057        * the parent window will be brought to the top just because the
2058        * tooltip is, which is not what we want.
2059        */
2060       if (gdk_window_get_type_hint (window) != GDK_WINDOW_TYPE_HINT_TOOLTIP)
2061         {
2062           window_impl->transient_for = g_object_ref (parent);
2063
2064           /* We only add the window if it is shown, otherwise it will
2065            * be shown unconditionally here. If it is not shown, the
2066            * window will be added in show() instead.
2067            */
2068           if (!(GDK_WINDOW_OBJECT (window)->state & GDK_WINDOW_STATE_WITHDRAWN))
2069             _gdk_quartz_window_attach_to_parent (window);
2070         }
2071     }
2072   
2073   GDK_QUARTZ_RELEASE_POOL;
2074 }
2075
2076 void
2077 gdk_window_shape_combine_region (GdkWindow       *window,
2078                                  const GdkRegion *shape,
2079                                  gint             x,
2080                                  gint             y)
2081 {
2082   g_return_if_fail (GDK_IS_WINDOW (window));
2083
2084   /* FIXME: Implement */
2085 }
2086
2087 void
2088 gdk_window_shape_combine_mask (GdkWindow *window,
2089                                GdkBitmap *mask,
2090                                gint x, gint y)
2091 {
2092   /* FIXME: Implement */
2093 }
2094
2095 void
2096 gdk_window_input_shape_combine_mask (GdkWindow *window,
2097                                      GdkBitmap *mask,
2098                                      gint       x,
2099                                      gint       y)
2100 {
2101   /* FIXME: Implement */
2102 }
2103
2104 void
2105 gdk_window_input_shape_combine_region (GdkWindow       *window,
2106                                        const GdkRegion *shape_region,
2107                                        gint             offset_x,
2108                                        gint             offset_y)
2109 {
2110   /* FIXME: Implement */
2111 }
2112
2113 void 
2114 gdk_window_set_child_input_shapes (GdkWindow *window)
2115 {
2116   /* FIXME: IMplement */
2117 }
2118
2119 void
2120 gdk_window_set_override_redirect (GdkWindow *window,
2121                                   gboolean override_redirect)
2122 {
2123   /* FIXME: Implement */
2124 }
2125
2126 void
2127 gdk_window_set_accept_focus (GdkWindow *window,
2128                              gboolean accept_focus)
2129 {
2130   GdkWindowObject *private;
2131
2132   g_return_if_fail (GDK_IS_WINDOW (window));
2133
2134   private = (GdkWindowObject *)window;  
2135
2136   private->accept_focus = accept_focus != FALSE;
2137 }
2138
2139 void
2140 gdk_window_set_child_shapes (GdkWindow *window)
2141 {
2142   g_return_if_fail (GDK_IS_WINDOW (window));
2143
2144   /* FIXME: Implement */
2145 }
2146
2147 void
2148 gdk_window_merge_child_shapes (GdkWindow *window)
2149 {
2150   g_return_if_fail (GDK_IS_WINDOW (window));
2151
2152   /* FIXME: Implement */
2153 }
2154
2155 void 
2156 gdk_window_merge_child_input_shapes (GdkWindow *window)
2157 {
2158   /* FIXME: Implement */
2159 }
2160
2161 gboolean 
2162 gdk_window_set_static_gravities (GdkWindow *window,
2163                                  gboolean   use_static)
2164 {
2165   /* FIXME: Implement */
2166   return FALSE;
2167 }
2168
2169 void
2170 gdk_window_set_focus_on_map (GdkWindow *window,
2171                              gboolean focus_on_map)
2172 {
2173   GdkWindowObject *private;
2174
2175   g_return_if_fail (GDK_IS_WINDOW (window));
2176
2177   private = (GdkWindowObject *)window;  
2178   
2179   private->focus_on_map = focus_on_map != FALSE;
2180 }
2181
2182 void          
2183 gdk_window_set_icon (GdkWindow *window, 
2184                      GdkWindow *icon_window,
2185                      GdkPixmap *pixmap,
2186                      GdkBitmap *mask)
2187 {
2188   g_return_if_fail (GDK_IS_WINDOW (window));
2189
2190   /* FIXME: Implement */
2191 }
2192
2193 void          
2194 gdk_window_set_icon_name (GdkWindow   *window, 
2195                           const gchar *name)
2196 {
2197   g_return_if_fail (GDK_IS_WINDOW (window));
2198
2199   /* FIXME: Implement */
2200 }
2201
2202 void
2203 gdk_window_focus (GdkWindow *window,
2204                   guint32    timestamp)
2205 {
2206   GdkWindowObject *private;
2207   GdkWindowImplQuartz *impl;
2208         
2209   g_return_if_fail (GDK_IS_WINDOW (window));
2210
2211   private = (GdkWindowObject*) window;
2212   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2213
2214   if (impl->toplevel)
2215     {
2216       if (private->accept_focus && private->window_type != GDK_WINDOW_TEMP) 
2217         {
2218           GDK_QUARTZ_ALLOC_POOL;
2219           [impl->toplevel makeKeyWindow];
2220           GDK_QUARTZ_RELEASE_POOL;
2221         }
2222     }
2223 }
2224
2225 void
2226 gdk_window_set_hints (GdkWindow *window,
2227                       gint       x,
2228                       gint       y,
2229                       gint       min_width,
2230                       gint       min_height,
2231                       gint       max_width,
2232                       gint       max_height,
2233                       gint       flags)
2234 {
2235   /* FIXME: Implement */
2236 }
2237
2238 static
2239 gint window_type_hint_to_level (GdkWindowTypeHint hint)
2240 {
2241   switch (hint)
2242     {
2243     case GDK_WINDOW_TYPE_HINT_DOCK:
2244     case GDK_WINDOW_TYPE_HINT_UTILITY:
2245       return NSFloatingWindowLevel;
2246
2247     case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
2248     case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
2249       return NSTornOffMenuWindowLevel;
2250
2251     case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2252     case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2253       return NSStatusWindowLevel;
2254
2255     case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2256     case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2257     case GDK_WINDOW_TYPE_HINT_COMBO:
2258     case GDK_WINDOW_TYPE_HINT_DND:
2259       return NSPopUpMenuWindowLevel;
2260
2261     case GDK_WINDOW_TYPE_HINT_NORMAL:  /* Normal toplevel window */
2262     case GDK_WINDOW_TYPE_HINT_DIALOG:  /* Dialog window */
2263     case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
2264     case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
2265       break;
2266
2267     default:
2268       break;
2269     }
2270
2271   return NSNormalWindowLevel;
2272 }
2273
2274 static gboolean 
2275 window_type_hint_to_shadow (GdkWindowTypeHint hint)
2276 {
2277   switch (hint)
2278     {
2279     case GDK_WINDOW_TYPE_HINT_NORMAL:  /* Normal toplevel window */
2280     case GDK_WINDOW_TYPE_HINT_DIALOG:  /* Dialog window */
2281     case GDK_WINDOW_TYPE_HINT_DOCK:
2282     case GDK_WINDOW_TYPE_HINT_UTILITY:
2283     case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
2284     case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
2285     case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2286     case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2287     case GDK_WINDOW_TYPE_HINT_COMBO:
2288     case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2289     case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2290       return TRUE;
2291
2292     case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
2293     case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
2294     case GDK_WINDOW_TYPE_HINT_DND:
2295       break;
2296
2297     default:
2298       break;
2299     }
2300
2301   return FALSE;
2302 }
2303
2304
2305 void
2306 gdk_window_set_type_hint (GdkWindow        *window,
2307                           GdkWindowTypeHint hint)
2308 {
2309   GdkWindowImplQuartz *impl;
2310   
2311   g_return_if_fail (GDK_IS_WINDOW (window));
2312
2313   if (GDK_WINDOW_DESTROYED (window))
2314     return;
2315
2316   impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl);
2317
2318   impl->type_hint = hint;
2319
2320   /* Match the documentation, only do something if we're not mapped yet. */
2321   if (GDK_WINDOW_IS_MAPPED (window))
2322     return;
2323
2324   [impl->toplevel setHasShadow: window_type_hint_to_shadow (hint)];
2325   [impl->toplevel setLevel: window_type_hint_to_level (hint)];
2326 }
2327
2328 GdkWindowTypeHint
2329 gdk_window_get_type_hint (GdkWindow *window)
2330 {
2331   if (GDK_WINDOW_DESTROYED (window))
2332     return GDK_WINDOW_TYPE_HINT_NORMAL;
2333   
2334   return GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl)->type_hint;
2335 }
2336
2337 void
2338 gdk_window_set_modal_hint (GdkWindow *window,
2339                            gboolean   modal)
2340 {
2341   g_return_if_fail (GDK_IS_WINDOW (window));
2342
2343   /* FIXME: Implement */
2344 }
2345
2346 void
2347 gdk_window_set_skip_taskbar_hint (GdkWindow *window,
2348                                   gboolean   skips_taskbar)
2349 {
2350   g_return_if_fail (GDK_IS_WINDOW (window));
2351
2352   /* FIXME: Implement */
2353 }
2354
2355 void
2356 gdk_window_set_skip_pager_hint (GdkWindow *window,
2357                                 gboolean   skips_pager)
2358 {
2359   g_return_if_fail (GDK_IS_WINDOW (window));
2360
2361   /* FIXME: Implement */
2362 }
2363
2364 void
2365 gdk_window_begin_resize_drag (GdkWindow     *window,
2366                               GdkWindowEdge  edge,
2367                               gint           button,
2368                               gint           root_x,
2369                               gint           root_y,
2370                               guint32        timestamp)
2371 {
2372   GdkWindowObject *private;
2373   GdkWindowImplQuartz *impl;
2374
2375   g_return_if_fail (GDK_IS_WINDOW (window));
2376
2377   if (edge != GDK_WINDOW_EDGE_SOUTH_EAST)
2378     {
2379       g_warning ("Resizing is only implemented for GDK_WINDOW_EDGE_SOUTH_EAST on Mac OS");
2380       return;
2381     }
2382
2383   if (GDK_WINDOW_DESTROYED (window))
2384     return;
2385
2386   private = GDK_WINDOW_OBJECT (window);
2387   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2388
2389   if (!impl->toplevel)
2390     {
2391       g_warning ("Can't call gdk_window_begin_resize_drag on non-toplevel window");
2392       return;
2393     }
2394
2395   [(GdkQuartzWindow *)impl->toplevel beginManualResize];
2396 }
2397
2398 void
2399 gdk_window_begin_move_drag (GdkWindow *window,
2400                             gint       button,
2401                             gint       root_x,
2402                             gint       root_y,
2403                             guint32    timestamp)
2404 {
2405   GdkWindowObject *private;
2406   GdkWindowImplQuartz *impl;
2407
2408   g_return_if_fail (GDK_IS_WINDOW (window));
2409
2410   if (GDK_WINDOW_DESTROYED (window))
2411     return;
2412
2413   private = GDK_WINDOW_OBJECT (window);
2414   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2415
2416   if (!impl->toplevel)
2417     {
2418       g_warning ("Can't call gdk_window_begin_move_drag on non-toplevel window");
2419       return;
2420     }
2421
2422   [(GdkQuartzWindow *)impl->toplevel beginManualMove];
2423 }
2424
2425 void
2426 gdk_window_set_icon_list (GdkWindow *window,
2427                           GList     *pixbufs)
2428 {
2429   /* FIXME: Implement */
2430 }
2431
2432 void
2433 gdk_window_get_frame_extents (GdkWindow    *window,
2434                               GdkRectangle *rect)
2435 {
2436   GdkWindowObject *private;
2437   GdkWindow *toplevel;
2438   GdkWindowImplQuartz *impl;
2439   NSRect ns_rect;
2440
2441   g_return_if_fail (GDK_IS_WINDOW (window));
2442   g_return_if_fail (rect != NULL);
2443
2444   private = GDK_WINDOW_OBJECT (window);
2445
2446   rect->x = 0;
2447   rect->y = 0;
2448   rect->width = 1;
2449   rect->height = 1;
2450   
2451   if (GDK_WINDOW_DESTROYED (window))
2452     return;
2453
2454   toplevel = gdk_window_get_toplevel (window);
2455   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
2456
2457   ns_rect = [impl->toplevel frame];
2458
2459   rect->x = ns_rect.origin.x;
2460   rect->y = _gdk_quartz_window_get_inverted_screen_y (ns_rect.origin.y + ns_rect.size.height);
2461   rect->width = ns_rect.size.width;
2462   rect->height = ns_rect.size.height;
2463 }
2464
2465 void
2466 gdk_window_set_decorations (GdkWindow       *window,
2467                             GdkWMDecoration  decorations)
2468 {
2469   GdkWindowImplQuartz *impl;
2470   int old_mask, new_mask;
2471   NSView *old_view;
2472
2473   g_return_if_fail (GDK_IS_WINDOW (window));
2474   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
2475
2476   if (GDK_WINDOW_DESTROYED (window))
2477     return;
2478
2479   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2480
2481   if (decorations == 0 || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
2482     {
2483       new_mask = NSBorderlessWindowMask;
2484     }
2485   else
2486     {
2487       /* FIXME: Honor other GDK_DECOR_* flags. */
2488       new_mask = (NSTitledWindowMask | NSClosableWindowMask |
2489                     NSMiniaturizableWindowMask | NSResizableWindowMask);
2490     }
2491
2492   GDK_QUARTZ_ALLOC_POOL;
2493
2494   old_mask = [impl->toplevel styleMask];
2495
2496   /* Note, there doesn't seem to be a way to change this without
2497    * recreating the toplevel. There might be bad side-effects of doing
2498    * that, but it seems alright.
2499    */
2500   if (old_mask != new_mask)
2501     {
2502       NSRect rect;
2503
2504       old_view = [impl->toplevel contentView];
2505
2506       rect = [impl->toplevel frame];
2507
2508       /* Properly update the size of the window when the titlebar is
2509        * added or removed.
2510        */
2511       if (old_mask == NSBorderlessWindowMask &&
2512           new_mask != NSBorderlessWindowMask)
2513         {
2514           rect = [NSWindow frameRectForContentRect:rect styleMask:new_mask];
2515         }
2516       else if (old_mask != NSBorderlessWindowMask &&
2517                new_mask == NSBorderlessWindowMask)
2518         {
2519           rect = [NSWindow contentRectForFrameRect:rect styleMask:old_mask];
2520         }
2521
2522       impl->toplevel = [impl->toplevel initWithContentRect:rect
2523                                                  styleMask:new_mask
2524                                                    backing:NSBackingStoreBuffered
2525                                                      defer:NO];
2526
2527       [impl->toplevel setContentView:old_view];
2528       [impl->toplevel setFrame:rect display:YES];
2529     }
2530
2531   GDK_QUARTZ_RELEASE_POOL;
2532 }
2533
2534 gboolean
2535 gdk_window_get_decorations (GdkWindow       *window,
2536                             GdkWMDecoration *decorations)
2537 {
2538   GdkWindowImplQuartz *impl;
2539
2540   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2541   g_return_val_if_fail (WINDOW_IS_TOPLEVEL (window), FALSE);
2542
2543   if (GDK_WINDOW_DESTROYED (window))
2544     return FALSE;
2545
2546   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2547
2548   if (decorations)
2549     {
2550       /* Borderless is 0, so we can't check it as a bit being set. */
2551       if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
2552         {
2553           *decorations = 0;
2554         }
2555       else
2556         {
2557           /* FIXME: Honor the other GDK_DECOR_* flags. */
2558           *decorations = GDK_DECOR_ALL;
2559         }
2560     }
2561
2562   return TRUE;
2563 }
2564
2565 void
2566 gdk_window_set_functions (GdkWindow    *window,
2567                           GdkWMFunction functions)
2568 {
2569   g_return_if_fail (GDK_IS_WINDOW (window));
2570
2571   /* FIXME: Implement */
2572 }
2573
2574 void
2575 _gdk_windowing_window_get_offsets (GdkWindow  *window,
2576                                    gint       *x_offset,
2577                                    gint       *y_offset)
2578 {
2579   *x_offset = *y_offset = 0;
2580 }
2581
2582 gboolean
2583 _gdk_windowing_window_queue_antiexpose (GdkWindow  *window,
2584                                         GdkRegion  *area)
2585 {
2586   return FALSE;
2587 }
2588
2589 void
2590 gdk_window_stick (GdkWindow *window)
2591 {
2592   g_return_if_fail (GDK_IS_WINDOW (window));
2593 }
2594
2595 void
2596 gdk_window_unstick (GdkWindow *window)
2597 {
2598   g_return_if_fail (GDK_IS_WINDOW (window));
2599 }
2600
2601 void
2602 gdk_window_maximize (GdkWindow *window)
2603 {
2604   GdkWindowImplQuartz *impl;
2605
2606   g_return_if_fail (GDK_IS_WINDOW (window));
2607
2608   if (GDK_WINDOW_DESTROYED (window))
2609     return;
2610
2611   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2612
2613   if (GDK_WINDOW_IS_MAPPED (window))
2614     {
2615       GDK_QUARTZ_ALLOC_POOL;
2616
2617       if (impl->toplevel && ![impl->toplevel isZoomed])
2618         [impl->toplevel zoom:nil];
2619
2620       GDK_QUARTZ_RELEASE_POOL;
2621     }
2622   else
2623     {
2624       gdk_synthesize_window_state (window,
2625                                    0,
2626                                    GDK_WINDOW_STATE_MAXIMIZED);
2627     }
2628 }
2629
2630 void
2631 gdk_window_unmaximize (GdkWindow *window)
2632 {
2633   GdkWindowImplQuartz *impl;
2634
2635   g_return_if_fail (GDK_IS_WINDOW (window));
2636
2637   if (GDK_WINDOW_DESTROYED (window))
2638     return;
2639
2640   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2641
2642   if (GDK_WINDOW_IS_MAPPED (window))
2643     {
2644       GDK_QUARTZ_ALLOC_POOL;
2645
2646       if (impl->toplevel && [impl->toplevel isZoomed])
2647         [impl->toplevel zoom:nil];
2648
2649       GDK_QUARTZ_RELEASE_POOL;
2650     }
2651   else
2652     {
2653       gdk_synthesize_window_state (window,
2654                                    GDK_WINDOW_STATE_MAXIMIZED,
2655                                    0);
2656     }
2657 }
2658
2659 void
2660 gdk_window_iconify (GdkWindow *window)
2661 {
2662   GdkWindowImplQuartz *impl;
2663
2664   g_return_if_fail (GDK_IS_WINDOW (window));
2665   
2666   if (GDK_WINDOW_DESTROYED (window))
2667     return;
2668   
2669   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2670
2671   if (GDK_WINDOW_IS_MAPPED (window))
2672     {
2673       GDK_QUARTZ_ALLOC_POOL;
2674
2675       if (impl->toplevel)
2676         [impl->toplevel miniaturize:nil];
2677
2678       GDK_QUARTZ_RELEASE_POOL;
2679     }
2680   else
2681     {
2682       gdk_synthesize_window_state (window,
2683                                    0,
2684                                    GDK_WINDOW_STATE_ICONIFIED);
2685     }
2686 }
2687
2688 void
2689 gdk_window_deiconify (GdkWindow *window)
2690 {
2691   GdkWindowImplQuartz *impl;
2692
2693   g_return_if_fail (GDK_IS_WINDOW (window));
2694   
2695   if (GDK_WINDOW_DESTROYED (window))
2696     return;
2697
2698   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2699
2700   if (GDK_WINDOW_IS_MAPPED (window))
2701     {
2702       GDK_QUARTZ_ALLOC_POOL;
2703
2704       if (impl->toplevel)
2705         [impl->toplevel deminiaturize:nil];
2706
2707       GDK_QUARTZ_RELEASE_POOL;
2708     }
2709   else
2710     {
2711       gdk_synthesize_window_state (window,
2712                                    GDK_WINDOW_STATE_ICONIFIED,
2713                                    0);
2714     }
2715 }
2716
2717 #define FULLSCREEN_DATA "fullscreen-data"
2718
2719 typedef struct
2720 {
2721   gint            x, y;
2722   gint            width, height;
2723   GdkWMDecoration decor;
2724 } FullscreenSavedGeometry;
2725
2726 void
2727 gdk_window_fullscreen (GdkWindow *window)
2728 {
2729   FullscreenSavedGeometry *geometry;
2730   GdkWindowObject *private = (GdkWindowObject *) window;
2731   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2732   NSRect frame;
2733
2734   g_return_if_fail (GDK_IS_WINDOW (window));
2735   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
2736
2737   geometry = g_new (FullscreenSavedGeometry, 1);
2738
2739   geometry->x = private->x;
2740   geometry->y = private->y;
2741   geometry->width = impl->width;
2742   geometry->height = impl->height;
2743   
2744   if (!gdk_window_get_decorations (window, &geometry->decor))
2745     geometry->decor = GDK_DECOR_ALL;
2746
2747   g_object_set_data_full (G_OBJECT (window),
2748                           FULLSCREEN_DATA, geometry, 
2749                           g_free);
2750
2751   HideMenuBar ();
2752
2753   gdk_window_set_decorations (window, 0);
2754
2755   frame = [[NSScreen mainScreen] frame];
2756   move_resize_window_internal (window,
2757                                0, 0, 
2758                                frame.size.width, frame.size.height);
2759
2760   gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
2761 }
2762
2763 void
2764 gdk_window_unfullscreen (GdkWindow *window)
2765 {
2766   FullscreenSavedGeometry *geometry;
2767
2768   g_return_if_fail (GDK_IS_WINDOW (window));
2769   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
2770
2771   geometry = g_object_get_data (G_OBJECT (window), FULLSCREEN_DATA);
2772
2773   if (geometry)
2774     {
2775       ShowMenuBar ();
2776
2777       move_resize_window_internal (window,
2778                                    geometry->x,
2779                                    geometry->y,
2780                                    geometry->width,
2781                                    geometry->height);
2782       
2783       gdk_window_set_decorations (window, geometry->decor);
2784
2785       g_object_set_data (G_OBJECT (window), FULLSCREEN_DATA, NULL);
2786
2787       gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
2788     }
2789 }
2790
2791 void
2792 gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
2793 {
2794   GdkWindowObject *private = (GdkWindowObject *) window;
2795   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2796   gint level;
2797
2798   g_return_if_fail (GDK_IS_WINDOW (window));
2799   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
2800
2801   if (GDK_WINDOW_DESTROYED (window))
2802     return;
2803
2804   level = window_type_hint_to_level (gdk_window_get_type_hint (window));
2805   
2806   /* Adjust normal window level by one if necessary. */
2807   [impl->toplevel setLevel: level + (setting ? 1 : 0)];
2808 }
2809
2810 void
2811 gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
2812 {
2813   GdkWindowObject *private = (GdkWindowObject *) window;
2814   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2815   gint level;
2816
2817   g_return_if_fail (GDK_IS_WINDOW (window));
2818   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
2819
2820   if (GDK_WINDOW_DESTROYED (window))
2821     return;
2822   
2823   level = window_type_hint_to_level (gdk_window_get_type_hint (window));
2824   
2825   /* Adjust normal window level by one if necessary. */
2826   [impl->toplevel setLevel: level - (setting ? 1 : 0)];
2827 }
2828
2829 GdkWindow *
2830 gdk_window_get_group (GdkWindow *window)
2831 {
2832   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2833   g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
2834
2835   /* FIXME: Implement */
2836
2837   return NULL;
2838 }
2839
2840 void          
2841 gdk_window_set_group (GdkWindow *window, 
2842                       GdkWindow *leader)
2843 {
2844   /* FIXME: Implement */        
2845 }
2846
2847 GdkWindow*
2848 gdk_window_foreign_new_for_display (GdkDisplay      *display,
2849                                     GdkNativeWindow  anid)
2850 {
2851   /* Foreign windows aren't supported in Mac OS X */
2852   return NULL;
2853 }
2854
2855 GdkWindow*
2856 gdk_window_lookup (GdkNativeWindow anid)
2857 {
2858   /* Foreign windows aren't supported in Mac OS X */
2859   return NULL;
2860 }
2861
2862 GdkWindow *
2863 gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
2864 {
2865   /* Foreign windows aren't supported in Mac OS X */
2866   return NULL;
2867 }
2868
2869 void
2870 gdk_window_enable_synchronized_configure (GdkWindow *window)
2871 {
2872 }
2873
2874 void
2875 gdk_window_configure_finished (GdkWindow *window)
2876 {
2877 }
2878
2879 void
2880 gdk_window_destroy_notify (GdkWindow *window)
2881 {
2882 }
2883
2884 void 
2885 gdk_window_beep (GdkWindow *window)
2886 {
2887   gdk_display_beep (_gdk_display);
2888 }
2889
2890 void
2891 gdk_window_set_opacity (GdkWindow *window,
2892                         gdouble    opacity)
2893 {
2894   GdkWindowObject *private = (GdkWindowObject *) window;
2895   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2896
2897   g_return_if_fail (GDK_IS_WINDOW (window));
2898   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
2899
2900   if (GDK_WINDOW_DESTROYED (window))
2901     return;
2902
2903   if (opacity < 0)
2904     opacity = 0;
2905   else if (opacity > 1)
2906     opacity = 1;
2907
2908   [impl->toplevel setAlphaValue: opacity];
2909 }
2910
2911 void
2912 _gdk_windowing_window_set_composited (GdkWindow *window, gboolean composited)
2913 {
2914 }