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