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