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