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