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