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