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