]> Pileus Git - ~andy/gtk/blob - gdk/quartz/gdkwindow-quartz.c
Fix memleak in get_nsscreen_for_point()
[~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       }
1062       break;
1063
1064     case GDK_WINDOW_CHILD:
1065       {
1066         GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (private->parent)->impl);
1067
1068         if (!private->input_only)
1069           {
1070             NSRect frame_rect = NSMakeRect (private->x + private->parent->abs_x,
1071                                             private->y + private->parent->abs_y,
1072                                             private->width,
1073                                             private->height);
1074         
1075             impl->view = [[GdkQuartzView alloc] initWithFrame:frame_rect];
1076             
1077             [impl->view setGdkWindow:window];
1078
1079             /* GdkWindows should be hidden by default */
1080             [impl->view setHidden:YES];
1081             [parent_impl->view addSubview:impl->view];
1082           }
1083       }
1084       break;
1085
1086     default:
1087       g_assert_not_reached ();
1088     }
1089
1090   GDK_QUARTZ_RELEASE_POOL;
1091
1092   if (attributes_mask & GDK_WA_TYPE_HINT)
1093     gdk_window_set_type_hint (window, attributes->type_hint);
1094 }
1095
1096 void
1097 _gdk_quartz_window_update_position (GdkWindow *window)
1098 {
1099   NSRect frame_rect;
1100   NSRect content_rect;
1101   GdkWindowObject *private = (GdkWindowObject *)window;
1102   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
1103
1104   GDK_QUARTZ_ALLOC_POOL;
1105
1106   frame_rect = [impl->toplevel frame];
1107   content_rect = [impl->toplevel contentRectForFrameRect:frame_rect];
1108
1109   _gdk_quartz_window_xy_to_gdk_xy (content_rect.origin.x,
1110                                    content_rect.origin.y + content_rect.size.height,
1111                                    &private->x, &private->y);
1112
1113
1114   GDK_QUARTZ_RELEASE_POOL;
1115 }
1116
1117 void
1118 _gdk_windowing_update_window_sizes (GdkScreen *screen)
1119 {
1120   GList *windows, *list;
1121   GdkWindowObject *private = (GdkWindowObject *)_gdk_root;
1122
1123   /* The size of the root window is so that it can contain all
1124    * monitors attached to this machine.  The monitors are laid out
1125    * within this root window.  We calculate the size of the root window
1126    * and the positions of the different monitors in gdkscreen-quartz.c.
1127    *
1128    * This data is updated when the monitor configuration is changed.
1129    */
1130   private->x = 0;
1131   private->y = 0;
1132   private->abs_x = 0;
1133   private->abs_y = 0;
1134   private->width = gdk_screen_get_width (screen);
1135   private->height = gdk_screen_get_height (screen);
1136
1137   windows = gdk_screen_get_toplevel_windows (screen);
1138
1139   for (list = windows; list; list = list->next)
1140     _gdk_quartz_window_update_position (list->data);
1141
1142   g_list_free (windows);
1143 }
1144
1145 void
1146 _gdk_windowing_window_init (void)
1147 {
1148   GdkWindowObject *private;
1149   GdkWindowImplQuartz *impl;
1150   GdkDrawableImplQuartz *drawable_impl;
1151
1152   g_assert (_gdk_root == NULL);
1153
1154   _gdk_root = g_object_new (GDK_TYPE_WINDOW, NULL);
1155
1156   private = (GdkWindowObject *)_gdk_root;
1157   private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
1158   private->impl_window = private;
1159
1160   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (_gdk_root)->impl);
1161
1162   _gdk_windowing_update_window_sizes (_gdk_screen);
1163
1164   private->state = 0; /* We don't want GDK_WINDOW_STATE_WITHDRAWN here */
1165   private->window_type = GDK_WINDOW_ROOT;
1166   private->depth = 24;
1167   private->viewable = TRUE;
1168
1169   drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (private->impl);
1170   
1171   drawable_impl->wrapper = GDK_DRAWABLE (private);
1172   drawable_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
1173   g_object_ref (drawable_impl->colormap);
1174 }
1175
1176 static void
1177 _gdk_quartz_window_destroy (GdkWindow *window,
1178                             gboolean   recursing,
1179                             gboolean   foreign_destroy)
1180 {
1181   GdkWindowObject *private;
1182   GdkWindowImplQuartz *impl;
1183   GdkWindowObject *parent;
1184
1185   private = GDK_WINDOW_OBJECT (window);
1186   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
1187
1188   main_window_stack = g_slist_remove (main_window_stack, window);
1189
1190   g_list_free (impl->sorted_children);
1191   impl->sorted_children = NULL;
1192
1193   parent = private->parent;
1194   if (parent)
1195     {
1196       GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (parent->impl);
1197
1198       parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window);
1199     }
1200
1201   _gdk_quartz_drawable_finish (GDK_DRAWABLE (impl));
1202
1203   if (!recursing && !foreign_destroy)
1204     {
1205       GDK_QUARTZ_ALLOC_POOL;
1206
1207       if (impl->toplevel)
1208         [impl->toplevel close];
1209       else if (impl->view)
1210         [impl->view removeFromSuperview];
1211
1212       GDK_QUARTZ_RELEASE_POOL;
1213     }
1214 }
1215
1216 void
1217 _gdk_windowing_window_destroy_foreign (GdkWindow *window)
1218 {
1219   /* Foreign windows aren't supported in OSX. */
1220 }
1221
1222 /* FIXME: This might be possible to simplify with client-side windows. Also
1223  * note that already_mapped is not used yet, see the x11 backend.
1224 */
1225 static void
1226 gdk_window_quartz_show (GdkWindow *window, gboolean already_mapped)
1227 {
1228   GdkWindowObject *private = (GdkWindowObject *)window;
1229   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
1230   gboolean focus_on_map;
1231
1232   GDK_QUARTZ_ALLOC_POOL;
1233
1234   if (!GDK_WINDOW_IS_MAPPED (window))
1235     focus_on_map = private->focus_on_map;
1236   else
1237     focus_on_map = TRUE;
1238
1239   if (impl->toplevel)
1240     {
1241       gboolean make_key;
1242
1243       make_key = (private->accept_focus && focus_on_map &&
1244                   private->window_type != GDK_WINDOW_TEMP);
1245
1246       [(GdkQuartzWindow*)impl->toplevel showAndMakeKey:make_key];
1247       clear_toplevel_order ();
1248
1249       _gdk_quartz_events_send_map_event (window);
1250     }
1251   else
1252     {
1253       [impl->view setHidden:NO];
1254     }
1255
1256   [impl->view setNeedsDisplay:YES];
1257
1258   gdk_synthesize_window_state (window, GDK_WINDOW_STATE_WITHDRAWN, 0);
1259
1260   if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
1261     gdk_window_maximize (window);
1262
1263   if (private->state & GDK_WINDOW_STATE_ICONIFIED)
1264     gdk_window_iconify (window);
1265
1266   if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1267     _gdk_quartz_window_attach_to_parent (window);
1268
1269   GDK_QUARTZ_RELEASE_POOL;
1270 }
1271
1272 /* Temporarily unsets the parent window, if the window is a
1273  * transient. 
1274  */
1275 void
1276 _gdk_quartz_window_detach_from_parent (GdkWindow *window)
1277 {
1278   GdkWindowImplQuartz *impl;
1279
1280   g_return_if_fail (GDK_IS_WINDOW (window));
1281
1282   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
1283   
1284   g_return_if_fail (impl->toplevel != NULL);
1285
1286   if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1287     {
1288       GdkWindowImplQuartz *parent_impl;
1289
1290       parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (impl->transient_for)->impl);
1291       [parent_impl->toplevel removeChildWindow:impl->toplevel];
1292       clear_toplevel_order ();
1293     }
1294 }
1295
1296 /* Re-sets the parent window, if the window is a transient. */
1297 void
1298 _gdk_quartz_window_attach_to_parent (GdkWindow *window)
1299 {
1300   GdkWindowImplQuartz *impl;
1301
1302   g_return_if_fail (GDK_IS_WINDOW (window));
1303
1304   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
1305   
1306   g_return_if_fail (impl->toplevel != NULL);
1307
1308   if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1309     {
1310       GdkWindowImplQuartz *parent_impl;
1311
1312       parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (impl->transient_for)->impl);
1313       [parent_impl->toplevel addChildWindow:impl->toplevel ordered:NSWindowAbove];
1314       clear_toplevel_order ();
1315     }
1316 }
1317
1318 void
1319 gdk_window_quartz_hide (GdkWindow *window)
1320 {
1321   GdkWindowObject *private = (GdkWindowObject *)window;
1322   GdkWindowImplQuartz *impl;
1323
1324   /* Make sure we're not stuck in fullscreen mode. */
1325   if (get_fullscreen_geometry (window))
1326     SetSystemUIMode (kUIModeNormal, 0);
1327
1328   check_grab_unmap (window);
1329
1330   _gdk_window_clear_update_area (window);
1331
1332   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
1333
1334   if (impl->toplevel) 
1335     {
1336      /* Update main window. */
1337       main_window_stack = g_slist_remove (main_window_stack, window);
1338       if ([NSApp mainWindow] == impl->toplevel)
1339         _gdk_quartz_window_did_resign_main (window);
1340
1341       if (impl->transient_for)
1342         _gdk_quartz_window_detach_from_parent (window);
1343
1344       [(GdkQuartzWindow*)impl->toplevel hide];
1345     }
1346   else if (impl->view)
1347     {
1348       [impl->view setHidden:YES];
1349     }
1350 }
1351
1352 void
1353 gdk_window_quartz_withdraw (GdkWindow *window)
1354 {
1355   gdk_window_hide (window);
1356 }
1357
1358 static void
1359 move_resize_window_internal (GdkWindow *window,
1360                              gint       x,
1361                              gint       y,
1362                              gint       width,
1363                              gint       height)
1364 {
1365   GdkWindowObject *private = (GdkWindowObject *)window;
1366   GdkWindowImplQuartz *impl;
1367   GdkRectangle old_visible;
1368   GdkRectangle new_visible;
1369   GdkRectangle scroll_rect;
1370   GdkRegion *old_region;
1371   GdkRegion *expose_region;
1372   NSSize delta;
1373
1374   if (GDK_WINDOW_DESTROYED (window))
1375     return;
1376
1377   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
1378
1379   if ((x == -1 || (x == private->x)) &&
1380       (y == -1 || (y == private->y)) &&
1381       (width == -1 || (width == private->width)) &&
1382       (height == -1 || (height == private->height)))
1383     {
1384       return;
1385     }
1386
1387   if (!impl->toplevel)
1388     {
1389       /* The previously visible area of this window in a coordinate
1390        * system rooted at the origin of this window.
1391        */
1392       old_visible.x = -private->x;
1393       old_visible.y = -private->y;
1394
1395       gdk_window_get_size (GDK_DRAWABLE (private->parent), 
1396                            &old_visible.width, 
1397                            &old_visible.height);
1398     }
1399
1400   if (x != -1)
1401     {
1402       delta.width = x - private->x;
1403       private->x = x;
1404     }
1405   else
1406     {
1407       delta.width = 0;
1408     }
1409
1410   if (y != -1)
1411     {
1412       delta.height = y - private->y;
1413       private->y = y;
1414     }
1415   else
1416     {
1417       delta.height = 0;
1418     }
1419
1420   if (width != -1)
1421     private->width = width;
1422
1423   if (height != -1)
1424     private->height = height;
1425
1426   GDK_QUARTZ_ALLOC_POOL;
1427
1428   if (impl->toplevel)
1429     {
1430       NSRect content_rect;
1431       NSRect frame_rect;
1432       gint gx, gy;
1433
1434       _gdk_quartz_window_gdk_xy_to_xy (private->x, private->y + private->height,
1435                                        &gx, &gy);
1436
1437       content_rect = NSMakeRect (gx, gy, private->width, private->height);
1438
1439       frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
1440       [impl->toplevel setFrame:frame_rect display:YES];
1441     }
1442   else 
1443     {
1444       if (!private->input_only)
1445         {
1446           NSRect nsrect;
1447
1448           nsrect = NSMakeRect (private->x, private->y, private->width, private->height);
1449
1450           /* The newly visible area of this window in a coordinate
1451            * system rooted at the origin of this window.
1452            */
1453           new_visible.x = -private->x;
1454           new_visible.y = -private->y;
1455           new_visible.width = old_visible.width;   /* parent has not changed size */
1456           new_visible.height = old_visible.height; /* parent has not changed size */
1457
1458           expose_region = gdk_region_rectangle (&new_visible);
1459           old_region = gdk_region_rectangle (&old_visible);
1460           gdk_region_subtract (expose_region, old_region);
1461
1462           /* Determine what (if any) part of the previously visible
1463            * part of the window can be copied without a redraw
1464            */
1465           scroll_rect = old_visible;
1466           scroll_rect.x -= delta.width;
1467           scroll_rect.y -= delta.height;
1468           gdk_rectangle_intersect (&scroll_rect, &old_visible, &scroll_rect);
1469
1470           if (!gdk_region_empty (expose_region))
1471             {
1472               GdkRectangle* rects;
1473               gint n_rects;
1474               gint n;
1475
1476               if (scroll_rect.width != 0 && scroll_rect.height != 0)
1477                 {
1478                   [impl->view scrollRect:NSMakeRect (scroll_rect.x,
1479                                                      scroll_rect.y,
1480                                                      scroll_rect.width,
1481                                                      scroll_rect.height)
1482                                       by:delta];
1483                 }
1484
1485               [impl->view setFrame:nsrect];
1486
1487               gdk_region_get_rectangles (expose_region, &rects, &n_rects);
1488
1489               for (n = 0; n < n_rects; ++n)
1490                 _gdk_quartz_window_set_needs_display_in_rect (window, &rects[n]);
1491
1492               g_free (rects);
1493             }
1494           else
1495             {
1496               [impl->view setFrame:nsrect];
1497               [impl->view setNeedsDisplay:YES];
1498             }
1499
1500           gdk_region_destroy (expose_region);
1501           gdk_region_destroy (old_region);
1502         }
1503     }
1504
1505   GDK_QUARTZ_RELEASE_POOL;
1506 }
1507
1508 static inline void
1509 window_quartz_move (GdkWindow *window,
1510                     gint       x,
1511                     gint       y)
1512 {
1513   g_return_if_fail (GDK_IS_WINDOW (window));
1514
1515   if (((GdkWindowObject *)window)->state & GDK_WINDOW_STATE_FULLSCREEN)
1516     return;
1517
1518   move_resize_window_internal (window, x, y, -1, -1);
1519 }
1520
1521 static inline void
1522 window_quartz_resize (GdkWindow *window,
1523                       gint       width,
1524                       gint       height)
1525 {
1526   g_return_if_fail (GDK_IS_WINDOW (window));
1527
1528   if (((GdkWindowObject *)window)->state & GDK_WINDOW_STATE_FULLSCREEN)
1529     return;
1530
1531   if (width < 1)
1532     width = 1;
1533   if (height < 1)
1534     height = 1;
1535
1536   move_resize_window_internal (window, -1, -1, width, height);
1537 }
1538
1539 static inline void
1540 window_quartz_move_resize (GdkWindow *window,
1541                            gint       x,
1542                            gint       y,
1543                            gint       width,
1544                            gint       height)
1545 {
1546   if (width < 1)
1547     width = 1;
1548   if (height < 1)
1549     height = 1;
1550
1551   move_resize_window_internal (window, x, y, width, height);
1552 }
1553
1554 static void
1555 gdk_window_quartz_move_resize (GdkWindow *window,
1556                                gboolean   with_move,
1557                                gint       x,
1558                                gint       y,
1559                                gint       width,
1560                                gint       height)
1561 {
1562   if (with_move && (width < 0 && height < 0))
1563     window_quartz_move (window, x, y);
1564   else
1565     {
1566       if (with_move)
1567         window_quartz_move_resize (window, x, y, width, height);
1568       else
1569         window_quartz_resize (window, width, height);
1570     }
1571 }
1572
1573 /* FIXME: This might need fixing (reparenting didn't work before client-side
1574  * windows either).
1575  */
1576 static gboolean
1577 gdk_window_quartz_reparent (GdkWindow *window,
1578                             GdkWindow *new_parent,
1579                             gint       x,
1580                             gint       y)
1581 {
1582   GdkWindowObject *private, *old_parent_private, *new_parent_private;
1583   GdkWindowImplQuartz *impl, *old_parent_impl, *new_parent_impl;
1584   NSView *view, *new_parent_view;
1585
1586   if (new_parent == _gdk_root)
1587     {
1588       /* Could be added, just needs implementing. */
1589       g_warning ("Reparenting to root window is not supported yet in the Mac OS X backend");
1590       return FALSE;
1591     }
1592
1593   private = GDK_WINDOW_OBJECT (window);
1594   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
1595   view = impl->view;
1596
1597   new_parent_private = GDK_WINDOW_OBJECT (new_parent);
1598   new_parent_impl = GDK_WINDOW_IMPL_QUARTZ (new_parent_private->impl);
1599   new_parent_view = new_parent_impl->view;
1600
1601   old_parent_private = GDK_WINDOW_OBJECT (private->parent);
1602   old_parent_impl = GDK_WINDOW_IMPL_QUARTZ (old_parent_private->impl);
1603
1604   [view retain];
1605
1606   [view removeFromSuperview];
1607   [new_parent_view addSubview:view];
1608
1609   [view release];
1610
1611   private->parent = new_parent_private;
1612
1613   if (old_parent_private)
1614     {
1615       old_parent_impl->sorted_children = g_list_remove (old_parent_impl->sorted_children, window);
1616     }
1617
1618   new_parent_impl->sorted_children = g_list_prepend (new_parent_impl->sorted_children, window);
1619
1620   return FALSE;
1621 }
1622
1623 /* Get the toplevel ordering from NSApp and update our own list. We do
1624  * this on demand since the NSApp's list is not up to date directly
1625  * after we get windowDidBecomeMain.
1626  */
1627 static void
1628 update_toplevel_order (void)
1629 {
1630   GdkWindowObject *root;
1631   GdkWindowImplQuartz *root_impl;
1632   NSEnumerator *enumerator;
1633   id nswindow;
1634   GList *toplevels = NULL;
1635
1636   root = GDK_WINDOW_OBJECT (_gdk_root);
1637   root_impl = GDK_WINDOW_IMPL_QUARTZ (root->impl);
1638
1639   if (root_impl->sorted_children)
1640     return;
1641
1642   GDK_QUARTZ_ALLOC_POOL;
1643
1644   enumerator = [[NSApp orderedWindows] objectEnumerator];
1645   while ((nswindow = [enumerator nextObject]))
1646     {
1647       GdkWindow *window;
1648
1649       if (![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
1650         continue;
1651
1652       window = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
1653       toplevels = g_list_prepend (toplevels, window);
1654     }
1655
1656   GDK_QUARTZ_RELEASE_POOL;
1657
1658   root_impl->sorted_children = g_list_reverse (toplevels);
1659 }
1660
1661 static void
1662 clear_toplevel_order (void)
1663 {
1664   GdkWindowObject *root;
1665   GdkWindowImplQuartz *root_impl;
1666
1667   root = GDK_WINDOW_OBJECT (_gdk_root);
1668   root_impl = GDK_WINDOW_IMPL_QUARTZ (root->impl);
1669
1670   g_list_free (root_impl->sorted_children);
1671   root_impl->sorted_children = NULL;
1672 }
1673
1674 static void
1675 gdk_window_quartz_raise (GdkWindow *window)
1676 {
1677   if (GDK_WINDOW_DESTROYED (window))
1678     return;
1679
1680   if (WINDOW_IS_TOPLEVEL (window))
1681     {
1682       GdkWindowImplQuartz *impl;
1683
1684       impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
1685       [impl->toplevel orderFront:impl->toplevel];
1686
1687       clear_toplevel_order ();
1688     }
1689   else
1690     {
1691       GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
1692
1693       if (parent)
1694         {
1695           GdkWindowImplQuartz *impl;
1696
1697           impl = (GdkWindowImplQuartz *)parent->impl;
1698
1699           impl->sorted_children = g_list_remove (impl->sorted_children, window);
1700           impl->sorted_children = g_list_prepend (impl->sorted_children, window);
1701         }
1702     }
1703 }
1704
1705 static void
1706 gdk_window_quartz_lower (GdkWindow *window)
1707 {
1708   if (GDK_WINDOW_DESTROYED (window))
1709     return;
1710
1711   if (WINDOW_IS_TOPLEVEL (window))
1712     {
1713       GdkWindowImplQuartz *impl;
1714
1715       impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
1716       [impl->toplevel orderBack:impl->toplevel];
1717
1718       clear_toplevel_order ();
1719     }
1720   else
1721     {
1722       GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
1723
1724       if (parent)
1725         {
1726           GdkWindowImplQuartz *impl;
1727
1728           impl = (GdkWindowImplQuartz *)parent->impl;
1729
1730           impl->sorted_children = g_list_remove (impl->sorted_children, window);
1731           impl->sorted_children = g_list_append (impl->sorted_children, window);
1732         }
1733     }
1734 }
1735
1736 static void
1737 gdk_window_quartz_restack_toplevel (GdkWindow *window,
1738                                     GdkWindow *sibling,
1739                                     gboolean   above)
1740 {
1741   /* FIXME: Implement this */
1742 }
1743
1744 static void
1745 gdk_window_quartz_set_background (GdkWindow      *window,
1746                                   const GdkColor *color)
1747 {
1748   /* FIXME: We could theoretically set the background color for toplevels
1749    * here. (Currently we draw the background before emitting expose events)
1750    */
1751 }
1752
1753 static void
1754 gdk_window_quartz_set_back_pixmap (GdkWindow *window,
1755                                    GdkPixmap *pixmap)
1756 {
1757   /* FIXME: Could theoretically set some background image here. (Currently
1758    * the back pixmap is drawn before emitting expose events.
1759    */
1760 }
1761
1762 static void
1763 gdk_window_quartz_set_cursor (GdkWindow *window,
1764                               GdkCursor *cursor)
1765 {
1766   GdkCursorPrivate *cursor_private;
1767   NSCursor *nscursor;
1768
1769   cursor_private = (GdkCursorPrivate *)cursor;
1770
1771   if (GDK_WINDOW_DESTROYED (window))
1772     return;
1773
1774   if (!cursor)
1775     nscursor = [NSCursor arrowCursor];
1776   else 
1777     nscursor = cursor_private->nscursor;
1778
1779   [nscursor set];
1780 }
1781
1782 static void
1783 gdk_window_quartz_get_geometry (GdkWindow *window,
1784                                 gint      *x,
1785                                 gint      *y,
1786                                 gint      *width,
1787                                 gint      *height,
1788                                 gint      *depth)
1789 {
1790   GdkWindowImplQuartz *impl;
1791   GdkWindowObject *private;
1792   NSRect ns_rect;
1793
1794   if (GDK_WINDOW_DESTROYED (window))
1795     return;
1796
1797   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
1798   private = GDK_WINDOW_OBJECT (window);
1799   if (window == _gdk_root)
1800     {
1801       if (x) 
1802         *x = 0;
1803       if (y) 
1804         *y = 0;
1805
1806       if (width) 
1807         *width = private->width;
1808       if (height)
1809         *height = private->height;
1810     }
1811   else if (WINDOW_IS_TOPLEVEL (window))
1812     {
1813       ns_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
1814
1815       /* This doesn't work exactly as in X. There doesn't seem to be a
1816        * way to get the coords relative to the parent window (usually
1817        * the window frame), but that seems useless except for
1818        * borderless windows where it's relative to the root window. So
1819        * we return (0, 0) (should be something like (0, 22)) for
1820        * windows with borders and the root relative coordinates
1821        * otherwise.
1822        */
1823       if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
1824         {
1825           _gdk_quartz_window_xy_to_gdk_xy (ns_rect.origin.x,
1826                                            ns_rect.origin.y + ns_rect.size.height,
1827                                            x, y);
1828         }
1829       else 
1830         {
1831           if (x)
1832             *x = 0;
1833           if (y)
1834             *y = 0;
1835         }
1836
1837       if (width)
1838         *width = ns_rect.size.width;
1839       if (height)
1840         *height = ns_rect.size.height;
1841     }
1842   else
1843     {
1844       ns_rect = [impl->view frame];
1845       
1846       if (x)
1847         *x = ns_rect.origin.x;
1848       if (y)
1849         *y = ns_rect.origin.y;
1850       if (width)
1851         *width  = ns_rect.size.width;
1852       if (height)
1853         *height = ns_rect.size.height;
1854     }
1855     
1856   if (depth)
1857       *depth = gdk_drawable_get_depth (window);
1858 }
1859
1860 static gint
1861 gdk_window_quartz_get_root_coords (GdkWindow *window,
1862                                    gint       x,
1863                                    gint       y,
1864                                    gint      *root_x,
1865                                    gint      *root_y)
1866 {
1867   GdkWindowObject *private;
1868   int tmp_x = 0, tmp_y = 0;
1869   GdkWindow *toplevel;
1870   NSRect content_rect;
1871   GdkWindowImplQuartz *impl;
1872
1873   if (GDK_WINDOW_DESTROYED (window)) 
1874     {
1875       if (root_x)
1876         *root_x = 0;
1877       if (root_y)
1878         *root_y = 0;
1879       
1880       return 0;
1881     }
1882
1883   if (window == _gdk_root)
1884     {
1885       if (root_x)
1886         *root_x = x;
1887       if (root_y)
1888         *root_y = y;
1889
1890       return 1;
1891     }
1892   
1893   private = GDK_WINDOW_OBJECT (window);
1894
1895   toplevel = gdk_window_get_toplevel (window);
1896   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
1897
1898   content_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
1899
1900   _gdk_quartz_window_xy_to_gdk_xy (content_rect.origin.x,
1901                                    content_rect.origin.y + content_rect.size.height,
1902                                    &tmp_x, &tmp_y);
1903
1904   tmp_x += x;
1905   tmp_y += y;
1906
1907   while (private != GDK_WINDOW_OBJECT (toplevel))
1908     {
1909       if (_gdk_window_has_impl ((GdkWindow *)private))
1910         {
1911           tmp_x += private->x;
1912           tmp_y += private->y;
1913         }
1914
1915       private = private->parent;
1916     }
1917
1918   if (root_x)
1919     *root_x = tmp_x;
1920   if (root_y)
1921     *root_y = tmp_y;
1922
1923   return TRUE;
1924 }
1925
1926 static gboolean
1927 gdk_window_quartz_get_deskrelative_origin (GdkWindow *window,
1928                                            gint      *x,
1929                                            gint      *y)
1930 {
1931   return gdk_window_get_origin (window, x, y);
1932 }
1933
1934 void
1935 gdk_window_get_root_origin (GdkWindow *window,
1936                             gint      *x,
1937                             gint      *y)
1938 {
1939   GdkRectangle rect;
1940
1941   rect.x = 0;
1942   rect.y = 0;
1943   
1944   gdk_window_get_frame_extents (window, &rect);
1945
1946   if (x)
1947     *x = rect.x;
1948
1949   if (y)
1950     *y = rect.y;
1951 }
1952
1953 /* Returns coordinates relative to the passed in window. */
1954 static GdkWindow *
1955 gdk_window_quartz_get_pointer_helper (GdkWindow       *window,
1956                                       gint            *x,
1957                                       gint            *y,
1958                                       GdkModifierType *mask)
1959 {
1960   GdkWindowObject *toplevel;
1961   GdkWindowObject *private;
1962   NSPoint point;
1963   gint x_tmp, y_tmp;
1964   GdkWindow *found_window;
1965
1966   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1967
1968   if (GDK_WINDOW_DESTROYED (window))
1969     {
1970       *x = 0;
1971       *y = 0;
1972       *mask = 0;
1973       return NULL;
1974     }
1975   
1976   toplevel = GDK_WINDOW_OBJECT (gdk_window_get_toplevel (window));
1977
1978   *mask = _gdk_quartz_events_get_current_event_mask ();
1979
1980   /* Get the y coordinate, needs to be flipped. */
1981   if (window == _gdk_root)
1982     {
1983       point = [NSEvent mouseLocation];
1984       _gdk_quartz_window_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
1985     }
1986   else
1987     {
1988       GdkWindowImplQuartz *impl;
1989       NSWindow *nswindow;
1990
1991       impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
1992       private = GDK_WINDOW_OBJECT (toplevel);
1993       nswindow = impl->toplevel;
1994
1995       point = [nswindow mouseLocationOutsideOfEventStream];
1996
1997       x_tmp = point.x;
1998       y_tmp = private->height - point.y;
1999
2000       window = (GdkWindow *)toplevel;
2001     }
2002
2003   found_window = _gdk_quartz_window_find_child (window, x_tmp, y_tmp);
2004
2005   /* We never return the root window. */
2006   if (found_window == _gdk_root)
2007     found_window = NULL;
2008
2009   *x = x_tmp;
2010   *y = y_tmp;
2011
2012   return found_window;
2013 }
2014
2015 static gboolean
2016 gdk_window_quartz_get_pointer (GdkWindow       *window,
2017                                gint            *x,
2018                                gint            *y,
2019                                GdkModifierType *mask)
2020 {
2021   return gdk_window_quartz_get_pointer_helper (window, x, y, mask) != NULL;
2022 }
2023
2024 /* Returns coordinates relative to the root. */
2025 void
2026 _gdk_windowing_get_pointer (GdkDisplay       *display,
2027                             GdkScreen       **screen,
2028                             gint             *x,
2029                             gint             *y,
2030                             GdkModifierType  *mask)
2031 {
2032   g_return_if_fail (display == _gdk_display);
2033   
2034   *screen = _gdk_screen;
2035   gdk_window_quartz_get_pointer_helper (_gdk_root, x, y, mask);
2036 }
2037
2038 void
2039 gdk_display_warp_pointer (GdkDisplay *display,
2040                           GdkScreen  *screen,
2041                           gint        x,
2042                           gint        y)
2043 {
2044   CGDisplayMoveCursorToPoint (CGMainDisplayID (), CGPointMake (x, y));
2045 }
2046
2047 /* Returns coordinates relative to the found window. */
2048 GdkWindow *
2049 _gdk_windowing_window_at_pointer (GdkDisplay      *display,
2050                                   gint            *win_x,
2051                                   gint            *win_y,
2052                                   GdkModifierType *mask,
2053                                   gboolean         get_toplevel)
2054 {
2055   GdkWindow *found_window;
2056   gint x, y;
2057   GdkModifierType tmp_mask = 0;
2058
2059   found_window = gdk_window_quartz_get_pointer_helper (_gdk_root,
2060                                                        &x, &y,
2061                                                        &tmp_mask);
2062   if (found_window)
2063     {
2064       GdkWindowObject *private;
2065
2066       /* The coordinates returned above are relative the root, we want
2067        * coordinates relative the window here. 
2068        */
2069       private = GDK_WINDOW_OBJECT (found_window);
2070       while (private != GDK_WINDOW_OBJECT (_gdk_root))
2071         {
2072           x -= private->x;
2073           y -= private->y;
2074           
2075           private = private->parent;
2076         }
2077
2078       *win_x = x;
2079       *win_y = y;
2080     }
2081   else
2082     {
2083       /* Mimic the X backend here, -1,-1 for unknown windows. */
2084       *win_x = -1;
2085       *win_y = -1;
2086     }
2087
2088   if (mask)
2089     *mask = tmp_mask;
2090
2091   if (get_toplevel)
2092     {
2093       GdkWindowObject *w = (GdkWindowObject *)found_window;
2094       /* Requested toplevel, find it. */
2095       /* TODO: This can be implemented more efficient by never
2096          recursing into children in the first place */
2097       if (w)
2098         {
2099           /* Convert to toplevel */
2100           while (w->parent != NULL &&
2101                  w->parent->window_type != GDK_WINDOW_ROOT)
2102             {
2103               *win_x += w->x;
2104               *win_y += w->y;
2105               w = w->parent;
2106             }
2107           found_window = (GdkWindow *)w;
2108         }
2109     }
2110
2111   return found_window;
2112 }
2113
2114 static GdkEventMask  
2115 gdk_window_quartz_get_events (GdkWindow *window)
2116 {
2117   if (GDK_WINDOW_DESTROYED (window))
2118     return 0;
2119   else
2120     return GDK_WINDOW_OBJECT (window)->event_mask;
2121 }
2122
2123 static void
2124 gdk_window_quartz_set_events (GdkWindow       *window,
2125                               GdkEventMask     event_mask)
2126 {
2127   /* The mask is set in the common code. */
2128 }
2129
2130 void
2131 gdk_window_set_urgency_hint (GdkWindow *window,
2132                              gboolean   urgent)
2133 {
2134   if (GDK_WINDOW_DESTROYED (window) ||
2135       !WINDOW_IS_TOPLEVEL (window))
2136     return;
2137
2138   /* FIXME: Implement */
2139 }
2140
2141 void 
2142 gdk_window_set_geometry_hints (GdkWindow         *window,
2143                                const GdkGeometry *geometry,
2144                                GdkWindowHints     geom_mask)
2145 {
2146   GdkWindowImplQuartz *impl;
2147
2148   g_return_if_fail (geometry != NULL);
2149
2150   if (GDK_WINDOW_DESTROYED (window) ||
2151       !WINDOW_IS_TOPLEVEL (window))
2152     return;
2153   
2154   impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl);
2155   if (!impl->toplevel)
2156     return;
2157
2158   if (geom_mask & GDK_HINT_POS)
2159     {
2160       /* FIXME: Implement */
2161     }
2162
2163   if (geom_mask & GDK_HINT_USER_POS)
2164     {
2165       /* FIXME: Implement */
2166     }
2167
2168   if (geom_mask & GDK_HINT_USER_SIZE)
2169     {
2170       /* FIXME: Implement */
2171     }
2172   
2173   if (geom_mask & GDK_HINT_MIN_SIZE)
2174     {
2175       NSSize size;
2176
2177       size.width = geometry->min_width;
2178       size.height = geometry->min_height;
2179
2180       [impl->toplevel setContentMinSize:size];
2181     }
2182   
2183   if (geom_mask & GDK_HINT_MAX_SIZE)
2184     {
2185       NSSize size;
2186
2187       size.width = geometry->max_width;
2188       size.height = geometry->max_height;
2189
2190       [impl->toplevel setContentMaxSize:size];
2191     }
2192   
2193   if (geom_mask & GDK_HINT_BASE_SIZE)
2194     {
2195       /* FIXME: Implement */
2196     }
2197   
2198   if (geom_mask & GDK_HINT_RESIZE_INC)
2199     {
2200       NSSize size;
2201
2202       size.width = geometry->width_inc;
2203       size.height = geometry->height_inc;
2204
2205       [impl->toplevel setContentResizeIncrements:size];
2206     }
2207   
2208   if (geom_mask & GDK_HINT_ASPECT)
2209     {
2210       /* FIXME: Implement */
2211     }
2212
2213   if (geom_mask & GDK_HINT_WIN_GRAVITY)
2214     {
2215       /* FIXME: Implement */
2216     }
2217 }
2218
2219 void
2220 gdk_window_set_title (GdkWindow   *window,
2221                       const gchar *title)
2222 {
2223   GdkWindowImplQuartz *impl;
2224
2225   g_return_if_fail (title != NULL);
2226
2227   if (GDK_WINDOW_DESTROYED (window) ||
2228       !WINDOW_IS_TOPLEVEL (window))
2229     return;
2230
2231   impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *)window)->impl);
2232
2233   if (impl->toplevel)
2234     {
2235       GDK_QUARTZ_ALLOC_POOL;
2236       [impl->toplevel setTitle:[NSString stringWithUTF8String:title]];
2237       GDK_QUARTZ_RELEASE_POOL;
2238     }
2239 }
2240
2241 void          
2242 gdk_window_set_role (GdkWindow   *window,
2243                      const gchar *role)
2244 {
2245   if (GDK_WINDOW_DESTROYED (window) ||
2246       WINDOW_IS_TOPLEVEL (window))
2247     return;
2248
2249   /* FIXME: Implement */
2250 }
2251
2252 void
2253 gdk_window_set_transient_for (GdkWindow *window, 
2254                               GdkWindow *parent)
2255 {
2256   GdkWindowImplQuartz *window_impl;
2257   GdkWindowImplQuartz *parent_impl;
2258
2259   if (GDK_WINDOW_DESTROYED (window)  || GDK_WINDOW_DESTROYED (parent) ||
2260       !WINDOW_IS_TOPLEVEL (window))
2261     return;
2262
2263   window_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2264   if (!window_impl->toplevel)
2265     return;
2266
2267   GDK_QUARTZ_ALLOC_POOL;
2268
2269   if (window_impl->transient_for)
2270     {
2271       _gdk_quartz_window_detach_from_parent (window);
2272
2273       g_object_unref (window_impl->transient_for);
2274       window_impl->transient_for = NULL;
2275     }
2276
2277   parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (parent)->impl);
2278   if (parent_impl->toplevel)
2279     {
2280       /* We save the parent because it needs to be unset/reset when
2281        * hiding and showing the window. 
2282        */
2283
2284       /* We don't set transients for tooltips, they are already
2285        * handled by the window level being the top one. If we do, then
2286        * the parent window will be brought to the top just because the
2287        * tooltip is, which is not what we want.
2288        */
2289       if (gdk_window_get_type_hint (window) != GDK_WINDOW_TYPE_HINT_TOOLTIP)
2290         {
2291           window_impl->transient_for = g_object_ref (parent);
2292
2293           /* We only add the window if it is shown, otherwise it will
2294            * be shown unconditionally here. If it is not shown, the
2295            * window will be added in show() instead.
2296            */
2297           if (!(GDK_WINDOW_OBJECT (window)->state & GDK_WINDOW_STATE_WITHDRAWN))
2298             _gdk_quartz_window_attach_to_parent (window);
2299         }
2300     }
2301   
2302   GDK_QUARTZ_RELEASE_POOL;
2303 }
2304
2305 static void
2306 gdk_window_quartz_shape_combine_region (GdkWindow       *window,
2307                                         const GdkRegion *shape,
2308                                         gint             x,
2309                                         gint             y)
2310 {
2311   /* FIXME: Implement */
2312 }
2313
2314 static void
2315 gdk_window_quartz_input_shape_combine_region (GdkWindow       *window,
2316                                               const GdkRegion *shape_region,
2317                                               gint             offset_x,
2318                                               gint             offset_y)
2319 {
2320   /* FIXME: Implement */
2321 }
2322
2323 void
2324 gdk_window_set_override_redirect (GdkWindow *window,
2325                                   gboolean override_redirect)
2326 {
2327   /* FIXME: Implement */
2328 }
2329
2330 void
2331 gdk_window_set_accept_focus (GdkWindow *window,
2332                              gboolean accept_focus)
2333 {
2334   GdkWindowObject *private;
2335
2336   private = (GdkWindowObject *)window;  
2337
2338   private->accept_focus = accept_focus != FALSE;
2339 }
2340
2341 static gboolean 
2342 gdk_window_quartz_set_static_gravities (GdkWindow *window,
2343                                         gboolean   use_static)
2344 {
2345   if (GDK_WINDOW_DESTROYED (window) ||
2346       !WINDOW_IS_TOPLEVEL (window))
2347     return FALSE;
2348
2349   /* FIXME: Implement */
2350   return FALSE;
2351 }
2352
2353 void
2354 gdk_window_set_focus_on_map (GdkWindow *window,
2355                              gboolean focus_on_map)
2356 {
2357   GdkWindowObject *private;
2358
2359   private = (GdkWindowObject *)window;  
2360   
2361   private->focus_on_map = focus_on_map != FALSE;
2362 }
2363
2364 void          
2365 gdk_window_set_icon (GdkWindow *window, 
2366                      GdkWindow *icon_window,
2367                      GdkPixmap *pixmap,
2368                      GdkBitmap *mask)
2369 {
2370   /* FIXME: Implement */
2371 }
2372
2373 void          
2374 gdk_window_set_icon_name (GdkWindow   *window, 
2375                           const gchar *name)
2376 {
2377   /* FIXME: Implement */
2378 }
2379
2380 void
2381 gdk_window_focus (GdkWindow *window,
2382                   guint32    timestamp)
2383 {
2384   GdkWindowObject *private;
2385   GdkWindowImplQuartz *impl;
2386         
2387   private = (GdkWindowObject*) window;
2388   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2389
2390   if (GDK_WINDOW_DESTROYED (window) ||
2391       !WINDOW_IS_TOPLEVEL (window))
2392     return;
2393
2394   if (private->accept_focus && private->window_type != GDK_WINDOW_TEMP)
2395     {
2396       GDK_QUARTZ_ALLOC_POOL;
2397       [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
2398       clear_toplevel_order ();
2399       GDK_QUARTZ_RELEASE_POOL;
2400     }
2401 }
2402
2403 void
2404 gdk_window_set_hints (GdkWindow *window,
2405                       gint       x,
2406                       gint       y,
2407                       gint       min_width,
2408                       gint       min_height,
2409                       gint       max_width,
2410                       gint       max_height,
2411                       gint       flags)
2412 {
2413   /* FIXME: Implement */
2414 }
2415
2416 static
2417 gint window_type_hint_to_level (GdkWindowTypeHint hint)
2418 {
2419   switch (hint)
2420     {
2421     case GDK_WINDOW_TYPE_HINT_DOCK:
2422     case GDK_WINDOW_TYPE_HINT_UTILITY:
2423       return NSFloatingWindowLevel;
2424
2425     case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
2426     case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
2427       return NSTornOffMenuWindowLevel;
2428
2429     case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2430     case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2431       return NSStatusWindowLevel;
2432
2433     case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2434     case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2435     case GDK_WINDOW_TYPE_HINT_COMBO:
2436     case GDK_WINDOW_TYPE_HINT_DND:
2437       return NSPopUpMenuWindowLevel;
2438
2439     case GDK_WINDOW_TYPE_HINT_NORMAL:  /* Normal toplevel window */
2440     case GDK_WINDOW_TYPE_HINT_DIALOG:  /* Dialog window */
2441     case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
2442     case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
2443       break;
2444
2445     default:
2446       break;
2447     }
2448
2449   return NSNormalWindowLevel;
2450 }
2451
2452 static gboolean 
2453 window_type_hint_to_shadow (GdkWindowTypeHint hint)
2454 {
2455   switch (hint)
2456     {
2457     case GDK_WINDOW_TYPE_HINT_NORMAL:  /* Normal toplevel window */
2458     case GDK_WINDOW_TYPE_HINT_DIALOG:  /* Dialog window */
2459     case GDK_WINDOW_TYPE_HINT_DOCK:
2460     case GDK_WINDOW_TYPE_HINT_UTILITY:
2461     case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
2462     case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
2463     case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2464     case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2465     case GDK_WINDOW_TYPE_HINT_COMBO:
2466     case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2467     case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2468       return TRUE;
2469
2470     case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
2471     case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
2472     case GDK_WINDOW_TYPE_HINT_DND:
2473       break;
2474
2475     default:
2476       break;
2477     }
2478
2479   return FALSE;
2480 }
2481
2482
2483 void
2484 gdk_window_set_type_hint (GdkWindow        *window,
2485                           GdkWindowTypeHint hint)
2486 {
2487   GdkWindowImplQuartz *impl;
2488   
2489   if (GDK_WINDOW_DESTROYED (window) ||
2490       !WINDOW_IS_TOPLEVEL (window))
2491     return;
2492
2493   impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl);
2494
2495   impl->type_hint = hint;
2496
2497   /* Match the documentation, only do something if we're not mapped yet. */
2498   if (GDK_WINDOW_IS_MAPPED (window))
2499     return;
2500
2501   [impl->toplevel setHasShadow: window_type_hint_to_shadow (hint)];
2502   [impl->toplevel setLevel: window_type_hint_to_level (hint)];
2503 }
2504
2505 GdkWindowTypeHint
2506 gdk_window_get_type_hint (GdkWindow *window)
2507 {
2508   if (GDK_WINDOW_DESTROYED (window) ||
2509       !WINDOW_IS_TOPLEVEL (window))
2510     return GDK_WINDOW_TYPE_HINT_NORMAL;
2511   
2512   return GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl)->type_hint;
2513 }
2514
2515 void
2516 gdk_window_set_modal_hint (GdkWindow *window,
2517                            gboolean   modal)
2518 {
2519   if (GDK_WINDOW_DESTROYED (window) ||
2520       !WINDOW_IS_TOPLEVEL (window))
2521     return;
2522
2523   /* FIXME: Implement */
2524 }
2525
2526 void
2527 gdk_window_set_skip_taskbar_hint (GdkWindow *window,
2528                                   gboolean   skips_taskbar)
2529 {
2530   if (GDK_WINDOW_DESTROYED (window) ||
2531       !WINDOW_IS_TOPLEVEL (window))
2532     return;
2533
2534   /* FIXME: Implement */
2535 }
2536
2537 void
2538 gdk_window_set_skip_pager_hint (GdkWindow *window,
2539                                 gboolean   skips_pager)
2540 {
2541   if (GDK_WINDOW_DESTROYED (window) ||
2542       !WINDOW_IS_TOPLEVEL (window))
2543     return;
2544
2545   /* FIXME: Implement */
2546 }
2547
2548 void
2549 gdk_window_begin_resize_drag (GdkWindow     *window,
2550                               GdkWindowEdge  edge,
2551                               gint           button,
2552                               gint           root_x,
2553                               gint           root_y,
2554                               guint32        timestamp)
2555 {
2556   GdkWindowObject *private;
2557   GdkWindowImplQuartz *impl;
2558
2559   g_return_if_fail (GDK_IS_WINDOW (window));
2560
2561   if (edge != GDK_WINDOW_EDGE_SOUTH_EAST)
2562     {
2563       g_warning ("Resizing is only implemented for GDK_WINDOW_EDGE_SOUTH_EAST on Mac OS");
2564       return;
2565     }
2566
2567   if (GDK_WINDOW_DESTROYED (window))
2568     return;
2569
2570   private = GDK_WINDOW_OBJECT (window);
2571   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2572
2573   if (!impl->toplevel)
2574     {
2575       g_warning ("Can't call gdk_window_begin_resize_drag on non-toplevel window");
2576       return;
2577     }
2578
2579   [(GdkQuartzWindow *)impl->toplevel beginManualResize];
2580 }
2581
2582 void
2583 gdk_window_begin_move_drag (GdkWindow *window,
2584                             gint       button,
2585                             gint       root_x,
2586                             gint       root_y,
2587                             guint32    timestamp)
2588 {
2589   GdkWindowObject *private;
2590   GdkWindowImplQuartz *impl;
2591
2592   if (GDK_WINDOW_DESTROYED (window) ||
2593       !WINDOW_IS_TOPLEVEL (window))
2594     return;
2595
2596   private = GDK_WINDOW_OBJECT (window);
2597   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2598
2599   if (!impl->toplevel)
2600     {
2601       g_warning ("Can't call gdk_window_begin_move_drag on non-toplevel window");
2602       return;
2603     }
2604
2605   [(GdkQuartzWindow *)impl->toplevel beginManualMove];
2606 }
2607
2608 void
2609 gdk_window_set_icon_list (GdkWindow *window,
2610                           GList     *pixbufs)
2611 {
2612   /* FIXME: Implement */
2613 }
2614
2615 void
2616 gdk_window_get_frame_extents (GdkWindow    *window,
2617                               GdkRectangle *rect)
2618 {
2619   GdkWindowObject *private;
2620   GdkWindow *toplevel;
2621   GdkWindowImplQuartz *impl;
2622   NSRect ns_rect;
2623
2624   g_return_if_fail (rect != NULL);
2625
2626   private = GDK_WINDOW_OBJECT (window);
2627
2628   rect->x = 0;
2629   rect->y = 0;
2630   rect->width = 1;
2631   rect->height = 1;
2632   
2633   toplevel = gdk_window_get_toplevel (window);
2634   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
2635
2636   ns_rect = [impl->toplevel frame];
2637
2638   _gdk_quartz_window_xy_to_gdk_xy (ns_rect.origin.x,
2639                                    ns_rect.origin.y + ns_rect.size.height,
2640                                    &rect->x, &rect->y);
2641
2642   rect->width = ns_rect.size.width;
2643   rect->height = ns_rect.size.height;
2644 }
2645
2646 void
2647 gdk_window_set_decorations (GdkWindow       *window,
2648                             GdkWMDecoration  decorations)
2649 {
2650   GdkWindowImplQuartz *impl;
2651   NSUInteger old_mask, new_mask;
2652   NSView *old_view;
2653
2654   if (GDK_WINDOW_DESTROYED (window) ||
2655       !WINDOW_IS_TOPLEVEL (window))
2656     return;
2657
2658   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2659
2660   if (decorations == 0 || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP ||
2661       impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN )
2662     {
2663       new_mask = NSBorderlessWindowMask;
2664     }
2665   else
2666     {
2667       /* FIXME: Honor other GDK_DECOR_* flags. */
2668       new_mask = (NSTitledWindowMask | NSClosableWindowMask |
2669                     NSMiniaturizableWindowMask | NSResizableWindowMask);
2670     }
2671
2672   GDK_QUARTZ_ALLOC_POOL;
2673
2674   old_mask = [impl->toplevel styleMask];
2675
2676   /* Note, there doesn't seem to be a way to change this without
2677    * recreating the toplevel. There might be bad side-effects of doing
2678    * that, but it seems alright.
2679    */
2680   if (old_mask != new_mask)
2681     {
2682       NSRect rect;
2683
2684       old_view = [impl->toplevel contentView];
2685
2686       rect = [impl->toplevel frame];
2687
2688       /* Properly update the size of the window when the titlebar is
2689        * added or removed.
2690        */
2691       if (old_mask == NSBorderlessWindowMask &&
2692           new_mask != NSBorderlessWindowMask)
2693         {
2694           rect = [NSWindow frameRectForContentRect:rect styleMask:new_mask];
2695
2696         }
2697       else if (old_mask != NSBorderlessWindowMask &&
2698                new_mask == NSBorderlessWindowMask)
2699         {
2700           rect = [NSWindow contentRectForFrameRect:rect styleMask:old_mask];
2701         }
2702
2703       impl->toplevel = [impl->toplevel initWithContentRect:rect
2704                                                  styleMask:new_mask
2705                                                    backing:NSBackingStoreBuffered
2706                                                      defer:NO];
2707
2708       [impl->toplevel setHasShadow: window_type_hint_to_shadow (impl->type_hint)];
2709       [impl->toplevel setLevel: window_type_hint_to_level (impl->type_hint)];
2710
2711       [impl->toplevel setContentView:old_view];
2712       [impl->toplevel setFrame:rect display:YES];
2713
2714       /* Invalidate the window shadow for non-opaque views that have shadow
2715        * enabled, to get the shadow shape updated.
2716        */
2717       if (![old_view isOpaque] && [impl->toplevel hasShadow])
2718         [(GdkQuartzView*)old_view setNeedsInvalidateShadow:YES];
2719     }
2720
2721   GDK_QUARTZ_RELEASE_POOL;
2722 }
2723
2724 gboolean
2725 gdk_window_get_decorations (GdkWindow       *window,
2726                             GdkWMDecoration *decorations)
2727 {
2728   GdkWindowImplQuartz *impl;
2729
2730   if (GDK_WINDOW_DESTROYED (window) ||
2731       !WINDOW_IS_TOPLEVEL (window))
2732     return FALSE;
2733
2734   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2735
2736   if (decorations)
2737     {
2738       /* Borderless is 0, so we can't check it as a bit being set. */
2739       if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
2740         {
2741           *decorations = 0;
2742         }
2743       else
2744         {
2745           /* FIXME: Honor the other GDK_DECOR_* flags. */
2746           *decorations = GDK_DECOR_ALL;
2747         }
2748     }
2749
2750   return TRUE;
2751 }
2752
2753 void
2754 gdk_window_set_functions (GdkWindow    *window,
2755                           GdkWMFunction functions)
2756 {
2757   g_return_if_fail (GDK_IS_WINDOW (window));
2758
2759   /* FIXME: Implement */
2760 }
2761
2762 gboolean
2763 _gdk_windowing_window_queue_antiexpose (GdkWindow  *window,
2764                                         GdkRegion  *area)
2765 {
2766   return FALSE;
2767 }
2768
2769 void
2770 gdk_window_stick (GdkWindow *window)
2771 {
2772   if (GDK_WINDOW_DESTROYED (window) ||
2773       !WINDOW_IS_TOPLEVEL (window))
2774     return;
2775 }
2776
2777 void
2778 gdk_window_unstick (GdkWindow *window)
2779 {
2780   if (GDK_WINDOW_DESTROYED (window) ||
2781       !WINDOW_IS_TOPLEVEL (window))
2782     return;
2783 }
2784
2785 void
2786 gdk_window_maximize (GdkWindow *window)
2787 {
2788   GdkWindowImplQuartz *impl;
2789
2790   if (GDK_WINDOW_DESTROYED (window) ||
2791       !WINDOW_IS_TOPLEVEL (window))
2792     return;
2793
2794   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2795
2796   if (GDK_WINDOW_IS_MAPPED (window))
2797     {
2798       GDK_QUARTZ_ALLOC_POOL;
2799
2800       if (impl->toplevel && ![impl->toplevel isZoomed])
2801         [impl->toplevel zoom:nil];
2802
2803       GDK_QUARTZ_RELEASE_POOL;
2804     }
2805   else
2806     {
2807       gdk_synthesize_window_state (window,
2808                                    0,
2809                                    GDK_WINDOW_STATE_MAXIMIZED);
2810     }
2811 }
2812
2813 void
2814 gdk_window_unmaximize (GdkWindow *window)
2815 {
2816   GdkWindowImplQuartz *impl;
2817
2818   if (GDK_WINDOW_DESTROYED (window) ||
2819       !WINDOW_IS_TOPLEVEL (window))
2820     return;
2821
2822   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2823
2824   if (GDK_WINDOW_IS_MAPPED (window))
2825     {
2826       GDK_QUARTZ_ALLOC_POOL;
2827
2828       if (impl->toplevel && [impl->toplevel isZoomed])
2829         [impl->toplevel zoom:nil];
2830
2831       GDK_QUARTZ_RELEASE_POOL;
2832     }
2833   else
2834     {
2835       gdk_synthesize_window_state (window,
2836                                    GDK_WINDOW_STATE_MAXIMIZED,
2837                                    0);
2838     }
2839 }
2840
2841 void
2842 gdk_window_iconify (GdkWindow *window)
2843 {
2844   GdkWindowImplQuartz *impl;
2845
2846   if (GDK_WINDOW_DESTROYED (window) ||
2847       !WINDOW_IS_TOPLEVEL (window))
2848     return;
2849
2850   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2851
2852   if (GDK_WINDOW_IS_MAPPED (window))
2853     {
2854       GDK_QUARTZ_ALLOC_POOL;
2855
2856       if (impl->toplevel)
2857         [impl->toplevel miniaturize:nil];
2858
2859       GDK_QUARTZ_RELEASE_POOL;
2860     }
2861   else
2862     {
2863       gdk_synthesize_window_state (window,
2864                                    0,
2865                                    GDK_WINDOW_STATE_ICONIFIED);
2866     }
2867 }
2868
2869 void
2870 gdk_window_deiconify (GdkWindow *window)
2871 {
2872   GdkWindowImplQuartz *impl;
2873
2874   if (GDK_WINDOW_DESTROYED (window) ||
2875       !WINDOW_IS_TOPLEVEL (window))
2876     return;
2877
2878   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
2879
2880   if (GDK_WINDOW_IS_MAPPED (window))
2881     {
2882       GDK_QUARTZ_ALLOC_POOL;
2883
2884       if (impl->toplevel)
2885         [impl->toplevel deminiaturize:nil];
2886
2887       GDK_QUARTZ_RELEASE_POOL;
2888     }
2889   else
2890     {
2891       gdk_synthesize_window_state (window,
2892                                    GDK_WINDOW_STATE_ICONIFIED,
2893                                    0);
2894     }
2895 }
2896
2897 static FullscreenSavedGeometry *
2898 get_fullscreen_geometry (GdkWindow *window)
2899 {
2900   return g_object_get_data (G_OBJECT (window), FULLSCREEN_DATA);
2901 }
2902
2903 void
2904 gdk_window_fullscreen (GdkWindow *window)
2905 {
2906   FullscreenSavedGeometry *geometry;
2907   GdkWindowObject *private = (GdkWindowObject *) window;
2908   NSRect frame;
2909
2910   if (GDK_WINDOW_DESTROYED (window) ||
2911       !WINDOW_IS_TOPLEVEL (window))
2912     return;
2913
2914   geometry = get_fullscreen_geometry (window);
2915   if (!geometry)
2916     {
2917       geometry = g_new (FullscreenSavedGeometry, 1);
2918
2919       geometry->x = private->x;
2920       geometry->y = private->y;
2921       geometry->width = private->width;
2922       geometry->height = private->height;
2923
2924       if (!gdk_window_get_decorations (window, &geometry->decor))
2925         geometry->decor = GDK_DECOR_ALL;
2926
2927       g_object_set_data_full (G_OBJECT (window),
2928                               FULLSCREEN_DATA, geometry, 
2929                               g_free);
2930
2931       gdk_window_set_decorations (window, 0);
2932
2933       frame = [[NSScreen mainScreen] frame];
2934       move_resize_window_internal (window,
2935                                    0, 0, 
2936                                    frame.size.width, frame.size.height);
2937     }
2938
2939   SetSystemUIMode (kUIModeAllHidden, kUIOptionAutoShowMenuBar);
2940
2941   gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
2942 }
2943
2944 void
2945 gdk_window_unfullscreen (GdkWindow *window)
2946 {
2947   FullscreenSavedGeometry *geometry;
2948
2949   if (GDK_WINDOW_DESTROYED (window) ||
2950       !WINDOW_IS_TOPLEVEL (window))
2951     return;
2952
2953   geometry = get_fullscreen_geometry (window);
2954   if (geometry)
2955     {
2956       SetSystemUIMode (kUIModeNormal, 0);
2957
2958       move_resize_window_internal (window,
2959                                    geometry->x,
2960                                    geometry->y,
2961                                    geometry->width,
2962                                    geometry->height);
2963       
2964       gdk_window_set_decorations (window, geometry->decor);
2965
2966       g_object_set_data (G_OBJECT (window), FULLSCREEN_DATA, NULL);
2967
2968       gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
2969     }
2970 }
2971
2972 void
2973 gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
2974 {
2975   GdkWindowObject *private = (GdkWindowObject *) window;
2976   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2977   gint level;
2978
2979   g_return_if_fail (GDK_IS_WINDOW (window));
2980
2981   if (GDK_WINDOW_DESTROYED (window) ||
2982       !WINDOW_IS_TOPLEVEL (window))
2983     return;
2984
2985   level = window_type_hint_to_level (gdk_window_get_type_hint (window));
2986   
2987   /* Adjust normal window level by one if necessary. */
2988   [impl->toplevel setLevel: level + (setting ? 1 : 0)];
2989 }
2990
2991 void
2992 gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
2993 {
2994   GdkWindowObject *private = (GdkWindowObject *) window;
2995   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
2996   gint level;
2997
2998   g_return_if_fail (GDK_IS_WINDOW (window));
2999
3000   if (GDK_WINDOW_DESTROYED (window) ||
3001       !WINDOW_IS_TOPLEVEL (window))
3002     return;
3003   
3004   level = window_type_hint_to_level (gdk_window_get_type_hint (window));
3005   
3006   /* Adjust normal window level by one if necessary. */
3007   [impl->toplevel setLevel: level - (setting ? 1 : 0)];
3008 }
3009
3010 GdkWindow *
3011 gdk_window_get_group (GdkWindow *window)
3012 {
3013   g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
3014
3015   if (GDK_WINDOW_DESTROYED (window) ||
3016       !WINDOW_IS_TOPLEVEL (window))
3017     return NULL;
3018
3019   /* FIXME: Implement */
3020
3021   return NULL;
3022 }
3023
3024 void          
3025 gdk_window_set_group (GdkWindow *window, 
3026                       GdkWindow *leader)
3027 {
3028   /* FIXME: Implement */        
3029 }
3030
3031 GdkWindow*
3032 gdk_window_foreign_new_for_display (GdkDisplay      *display,
3033                                     GdkNativeWindow  anid)
3034 {
3035   /* Foreign windows aren't supported in Mac OS X */
3036   return NULL;
3037 }
3038
3039 GdkWindow*
3040 gdk_window_lookup (GdkNativeWindow anid)
3041 {
3042   /* Foreign windows aren't supported in Mac OS X */
3043   return NULL;
3044 }
3045
3046 GdkWindow *
3047 gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
3048 {
3049   /* Foreign windows aren't supported in Mac OS X */
3050   return NULL;
3051 }
3052
3053 void
3054 gdk_window_enable_synchronized_configure (GdkWindow *window)
3055 {
3056 }
3057
3058 void
3059 gdk_window_configure_finished (GdkWindow *window)
3060 {
3061 }
3062
3063 void
3064 gdk_window_destroy_notify (GdkWindow *window)
3065 {
3066   check_grab_destroy (window);
3067 }
3068
3069 void 
3070 _gdk_windowing_window_beep (GdkWindow *window)
3071 {
3072   g_return_if_fail (GDK_IS_WINDOW (window));
3073
3074   gdk_display_beep (_gdk_display);
3075 }
3076
3077 void
3078 gdk_window_set_opacity (GdkWindow *window,
3079                         gdouble    opacity)
3080 {
3081   GdkWindowObject *private = (GdkWindowObject *) window;
3082   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
3083
3084   g_return_if_fail (GDK_IS_WINDOW (window));
3085   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
3086
3087   if (GDK_WINDOW_DESTROYED (window) ||
3088       !WINDOW_IS_TOPLEVEL (window))
3089     return;
3090
3091   if (opacity < 0)
3092     opacity = 0;
3093   else if (opacity > 1)
3094     opacity = 1;
3095
3096   [impl->toplevel setAlphaValue: opacity];
3097 }
3098
3099 void
3100 _gdk_windowing_window_set_composited (GdkWindow *window, gboolean composited)
3101 {
3102 }
3103
3104 GdkRegion *
3105 _gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
3106 {
3107   /* FIXME: implement */
3108   return NULL;
3109 }
3110
3111 GdkRegion *
3112 _gdk_windowing_window_get_shape (GdkWindow *window)
3113 {
3114   /* FIXME: implement */
3115   return NULL;
3116 }
3117
3118 GdkRegion *
3119 _gdk_windowing_window_get_input_shape (GdkWindow *window)
3120 {
3121   /* FIXME: implement */
3122   return NULL;
3123 }
3124
3125 static void
3126 gdk_window_impl_iface_init (GdkWindowImplIface *iface)
3127 {
3128   iface->show = gdk_window_quartz_show;
3129   iface->hide = gdk_window_quartz_hide;
3130   iface->withdraw = gdk_window_quartz_withdraw;
3131   iface->set_events = gdk_window_quartz_set_events;
3132   iface->get_events = gdk_window_quartz_get_events;
3133   iface->raise = gdk_window_quartz_raise;
3134   iface->lower = gdk_window_quartz_lower;
3135   iface->restack_toplevel = gdk_window_quartz_restack_toplevel;
3136   iface->move_resize = gdk_window_quartz_move_resize;
3137   iface->set_background = gdk_window_quartz_set_background;
3138   iface->set_back_pixmap = gdk_window_quartz_set_back_pixmap;
3139   iface->reparent = gdk_window_quartz_reparent;
3140   iface->set_cursor = gdk_window_quartz_set_cursor;
3141   iface->get_geometry = gdk_window_quartz_get_geometry;
3142   iface->get_root_coords = gdk_window_quartz_get_root_coords;
3143   iface->get_pointer = gdk_window_quartz_get_pointer;
3144   iface->get_deskrelative_origin = gdk_window_quartz_get_deskrelative_origin;
3145   iface->shape_combine_region = gdk_window_quartz_shape_combine_region;
3146   iface->input_shape_combine_region = gdk_window_quartz_input_shape_combine_region;
3147   iface->set_static_gravities = gdk_window_quartz_set_static_gravities;
3148   iface->queue_antiexpose = _gdk_quartz_window_queue_antiexpose;
3149   iface->queue_translation = _gdk_quartz_window_queue_translation;
3150   iface->destroy = _gdk_quartz_window_destroy;
3151   iface->input_window_destroy = _gdk_input_window_destroy;
3152   iface->input_window_crossing = _gdk_input_window_crossing;
3153 }