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