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