3 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * Copyright (C) 2005-2007 Imendio AB
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.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
23 #include <gdk/gdkdeviceprivate.h>
24 #include <gdk/gdkdisplayprivate.h>
26 #include "gdkwindowimpl.h"
27 #include "gdkprivate-quartz.h"
28 #include "gdkquartzscreen.h"
29 #include "gdkquartzcursor.h"
31 #include <Carbon/Carbon.h>
34 #include <cairo-quartz.h>
36 static gpointer parent_class;
37 static gpointer root_window_parent_class;
39 static GSList *update_nswindows;
40 static gboolean in_process_all_updates = FALSE;
42 static GSList *main_window_stack;
44 void _gdk_quartz_window_flush (GdkWindowImplQuartz *window_impl);
46 #define FULLSCREEN_DATA "fullscreen-data"
52 GdkWMDecoration decor;
53 } FullscreenSavedGeometry;
56 static void update_toplevel_order (void);
57 static void clear_toplevel_order (void);
59 static FullscreenSavedGeometry *get_fullscreen_geometry (GdkWindow *window);
61 #define WINDOW_IS_TOPLEVEL(window) \
62 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
63 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
64 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
70 struct _GdkQuartzWindow
75 struct _GdkQuartzWindowClass
77 GdkWindowClass parent_class;
80 G_DEFINE_TYPE (GdkQuartzWindow, gdk_quartz_window, GDK_TYPE_WINDOW);
83 gdk_quartz_window_class_init (GdkQuartzWindowClass *quartz_window_class)
88 gdk_quartz_window_init (GdkQuartzWindow *quartz_window)
98 gdk_quartz_window_get_nsview (GdkWindow *window)
100 if (GDK_WINDOW_DESTROYED (window))
103 return ((GdkWindowImplQuartz *)window->impl)->view;
107 gdk_quartz_window_get_nswindow (GdkWindow *window)
109 if (GDK_WINDOW_DESTROYED (window))
112 return ((GdkWindowImplQuartz *)window->impl)->toplevel;
116 gdk_window_impl_quartz_get_context (GdkWindowImplQuartz *window_impl,
119 CGContextRef cg_context;
121 if (GDK_WINDOW_DESTROYED (window_impl->wrapper))
124 /* Lock focus when not called as part of a drawRect call. This
125 * is needed when called from outside "real" expose events, for
126 * example for synthesized expose events when realizing windows
127 * and for widgets that send fake expose events like the arrow
128 * buttons in spinbuttons or the position marker in rulers.
130 if (window_impl->in_paint_rect_count == 0)
132 if (![window_impl->view lockFocusIfCanDraw])
136 cg_context = [[NSGraphicsContext currentContext] graphicsPort];
137 CGContextSaveGState (cg_context);
138 CGContextSetAllowsAntialiasing (cg_context, antialias);
140 /* We'll emulate the clipping caused by double buffering here */
141 if (window_impl->begin_paint_count != 0)
147 n_rects = cairo_region_num_rectangles (window_impl->paint_clip_region);
152 cg_rects = g_new (CGRect, n_rects);
154 for (i = 0; i < n_rects; i++)
156 cairo_rectangle_int_t cairo_rect;
157 cairo_region_get_rectangle (window_impl->paint_clip_region,
159 cg_rects[i].origin.x = cairo_rect.x;
160 cg_rects[i].origin.y = cairo_rect.y;
161 cg_rects[i].size.width = cairo_rect.width;
162 cg_rects[i].size.height = cairo_rect.height;
165 CGContextClipToRects (cg_context, cg_rects, n_rects);
167 if (cg_rects != &rect)
175 gdk_window_impl_quartz_release_context (GdkWindowImplQuartz *window_impl,
176 CGContextRef cg_context)
178 CGContextRestoreGState (cg_context);
179 CGContextSetAllowsAntialiasing (cg_context, TRUE);
181 /* See comment in gdk_quartz_window_get_context(). */
182 if (window_impl->in_paint_rect_count == 0)
184 _gdk_quartz_window_flush (window_impl);
185 [window_impl->view unlockFocus];
190 check_grab_unmap (GdkWindow *window)
193 GdkDisplay *display = gdk_window_get_display (window);
194 GdkDeviceManager *device_manager;
196 device_manager = gdk_display_get_device_manager (display);
197 list = gdk_device_manager_list_devices (device_manager,
198 GDK_DEVICE_TYPE_FLOATING);
199 for (l = list; l; l = l->next)
201 _gdk_display_end_device_grab (display, l->data, 0, window, TRUE);
208 check_grab_destroy (GdkWindow *window)
211 GdkDisplay *display = gdk_window_get_display (window);
212 GdkDeviceManager *device_manager;
214 /* Make sure there is no lasting grab in this native window */
215 device_manager = gdk_display_get_device_manager (display);
216 list = gdk_device_manager_list_devices (device_manager,
217 GDK_DEVICE_TYPE_MASTER);
219 for (l = list; l; l = l->next)
221 GdkDeviceGrabInfo *grab;
223 grab = _gdk_display_get_last_device_grab (display, l->data);
224 if (grab && grab->native_window == window)
226 /* Serials are always 0 in quartz, but for clarity: */
227 grab->serial_end = grab->serial_start;
228 grab->implicit_ungrab = TRUE;
236 gdk_window_impl_quartz_finalize (GObject *object)
238 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (object);
240 check_grab_destroy (GDK_WINDOW_IMPL_QUARTZ (object)->wrapper);
242 if (impl->paint_clip_region)
243 cairo_region_destroy (impl->paint_clip_region);
245 if (impl->transient_for)
246 g_object_unref (impl->transient_for);
248 G_OBJECT_CLASS (parent_class)->finalize (object);
251 /* Help preventing "beam sync penalty" where CG makes all graphics code
252 * block until the next vsync if we try to flush (including call display on
253 * a view) too often. We do this by limiting the manual flushing done
254 * outside of expose calls to less than some frequency when measured over
255 * the last 4 flushes. This is a bit arbitray, but seems to make it possible
256 * for some quick manual flushes (such as gtkruler or gimp's marching ants)
257 * without hitting the max flush frequency.
259 * If drawable NULL, no flushing is done, only registering that a flush was
263 _gdk_quartz_window_flush (GdkWindowImplQuartz *window_impl)
265 static struct timeval prev_tv;
266 static gint intervals[4];
271 gettimeofday (&tv, NULL);
272 ms = (tv.tv_sec - prev_tv.tv_sec) * 1000 + (tv.tv_usec - prev_tv.tv_usec) / 1000;
273 intervals[index++ % 4] = ms;
277 ms = intervals[0] + intervals[1] + intervals[2] + intervals[3];
279 /* ~25Hz on average. */
283 [window_impl->toplevel flushWindow];
292 static cairo_user_data_key_t gdk_quartz_cairo_key;
295 GdkWindowImplQuartz *window_impl;
296 CGContextRef cg_context;
297 } GdkQuartzCairoSurfaceData;
300 gdk_quartz_cairo_surface_destroy (void *data)
302 GdkQuartzCairoSurfaceData *surface_data = data;
304 surface_data->window_impl->cairo_surface = NULL;
306 gdk_quartz_window_release_context (surface_data->window_impl,
307 surface_data->cg_context);
309 g_free (surface_data);
312 static cairo_surface_t *
313 gdk_quartz_create_cairo_surface (GdkWindowImplQuartz *impl,
317 CGContextRef cg_context;
318 GdkQuartzCairoSurfaceData *surface_data;
319 cairo_surface_t *surface;
321 cg_context = gdk_quartz_window_get_context (impl, TRUE);
326 surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
327 surface_data->window_impl = impl;
328 surface_data->cg_context = cg_context;
330 surface = cairo_quartz_surface_create_for_cg_context (cg_context,
333 cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
335 gdk_quartz_cairo_surface_destroy);
340 static cairo_surface_t *
341 gdk_quartz_ref_cairo_surface (GdkWindow *window)
343 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
345 if (GDK_WINDOW_DESTROYED (window))
348 if (!impl->cairo_surface)
350 impl->cairo_surface =
351 gdk_quartz_create_cairo_surface (impl,
352 gdk_window_get_width (impl->wrapper),
353 gdk_window_get_height (impl->wrapper));
356 cairo_surface_reference (impl->cairo_surface);
358 return impl->cairo_surface;
362 gdk_window_impl_quartz_init (GdkWindowImplQuartz *impl)
364 impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
368 gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable,
370 const cairo_region_t *region)
372 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
373 cairo_region_t *clipped_and_offset_region;
376 clipped_and_offset_region = cairo_region_copy (region);
378 cairo_region_intersect (clipped_and_offset_region,
379 window->clip_region_with_children);
380 cairo_region_translate (clipped_and_offset_region,
381 window->abs_x, window->abs_y);
383 if (impl->begin_paint_count == 0)
384 impl->paint_clip_region = cairo_region_reference (clipped_and_offset_region);
386 cairo_region_union (impl->paint_clip_region, clipped_and_offset_region);
388 impl->begin_paint_count++;
390 if (cairo_region_is_empty (clipped_and_offset_region))
393 cr = gdk_cairo_create (window);
395 cairo_translate (cr, -window->abs_x, -window->abs_y);
397 gdk_cairo_region (cr, clipped_and_offset_region);
400 while (window->background == NULL && window->parent)
402 cairo_translate (cr, -window->x, window->y);
403 window = window->parent;
406 if (window->background)
407 cairo_set_source (cr, window->background);
409 cairo_set_source_rgba (cr, 0, 0, 0, 0);
411 /* Can use cairo_paint() here, we clipped above */
417 cairo_region_destroy (clipped_and_offset_region);
421 gdk_window_impl_quartz_end_paint (GdkPaintable *paintable)
423 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
425 impl->begin_paint_count--;
427 if (impl->begin_paint_count == 0)
429 cairo_region_destroy (impl->paint_clip_region);
430 impl->paint_clip_region = NULL;
435 gdk_quartz_window_set_needs_display_in_region (GdkWindow *window,
436 cairo_region_t *region)
438 GdkWindowImplQuartz *impl;
441 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
443 if (!impl->needs_display_region)
444 impl->needs_display_region = cairo_region_create ();
446 cairo_region_union (impl->needs_display_region, region);
448 n_rects = cairo_region_num_rectangles (region);
449 for (i = 0; i < n_rects; i++)
451 cairo_rectangle_int_t rect;
452 cairo_region_get_rectangle (region, i, &rect);
453 [impl->view setNeedsDisplayInRect:NSMakeRect (rect.x, rect.y,
454 rect.width, rect.height)];
459 _gdk_quartz_window_process_updates_recurse (GdkWindow *window,
460 cairo_region_t *region)
462 /* Make sure to only flush each toplevel at most once if we're called
463 * from process_all_updates.
465 if (in_process_all_updates)
469 toplevel = gdk_window_get_effective_toplevel (window);
470 if (toplevel && WINDOW_IS_TOPLEVEL (toplevel))
472 GdkWindowImplQuartz *toplevel_impl;
475 toplevel_impl = (GdkWindowImplQuartz *)toplevel->impl;
476 nswindow = toplevel_impl->toplevel;
478 /* In theory, we could skip the flush disabling, since we only
481 if (nswindow && ![nswindow isFlushWindowDisabled])
484 [nswindow disableFlushWindow];
485 update_nswindows = g_slist_prepend (update_nswindows, nswindow);
490 if (WINDOW_IS_TOPLEVEL (window))
491 gdk_quartz_window_set_needs_display_in_region (window, region);
493 _gdk_window_process_updates_recurse (window, region);
495 /* NOTE: I'm not sure if we should displayIfNeeded here. It slows down a
496 * lot (since it triggers the beam syncing) and things seem to work
502 _gdk_quartz_display_before_process_all_updates (GdkDisplay *display)
504 in_process_all_updates = TRUE;
506 NSDisableScreenUpdates ();
510 _gdk_quartz_display_after_process_all_updates (GdkDisplay *display)
512 GSList *old_update_nswindows = update_nswindows;
513 GSList *tmp_list = update_nswindows;
515 update_nswindows = NULL;
519 NSWindow *nswindow = tmp_list->data;
521 [[nswindow contentView] displayIfNeeded];
523 _gdk_quartz_window_flush (NULL);
525 [nswindow enableFlushWindow];
526 [nswindow flushWindow];
529 tmp_list = tmp_list->next;
532 g_slist_free (old_update_nswindows);
534 in_process_all_updates = FALSE;
536 NSEnableScreenUpdates ();
540 gdk_window_impl_quartz_paintable_init (GdkPaintableIface *iface)
542 iface->begin_paint_region = gdk_window_impl_quartz_begin_paint_region;
543 iface->end_paint = gdk_window_impl_quartz_end_paint;
547 get_default_title (void)
551 title = g_get_application_name ();
553 title = g_get_prgname ();
559 get_ancestor_coordinates_from_child (GdkWindow *child_window,
562 GdkWindow *ancestor_window,
566 while (child_window != ancestor_window)
568 child_x += child_window->x;
569 child_y += child_window->y;
571 child_window = child_window->parent;
574 *ancestor_x = child_x;
575 *ancestor_y = child_y;
579 _gdk_quartz_window_debug_highlight (GdkWindow *window, gint number)
585 static NSWindow *debug_window[10];
586 static NSRect old_rect[10];
590 g_return_if_fail (number >= 0 && number <= 9);
592 if (window == _gdk_root)
597 if (debug_window[number])
598 [debug_window[number] close];
599 debug_window[number] = NULL;
604 toplevel = gdk_window_get_toplevel (window);
605 get_ancestor_coordinates_from_child (window, 0, 0, toplevel, &x, &y);
607 gdk_window_get_origin (toplevel, &tx, &ty);
611 _gdk_quartz_window_gdk_xy_to_xy (x, y + window->height,
614 rect = NSMakeRect (gx, gy, window->width, window->height);
616 if (debug_window[number] && NSEqualRects (rect, old_rect[number]))
619 old_rect[number] = rect;
621 if (debug_window[number])
622 [debug_window[number] close];
624 debug_window[number] = [[NSWindow alloc] initWithContentRect:rect
625 styleMask:NSBorderlessWindowMask
626 backing:NSBackingStoreBuffered
632 color = [NSColor redColor];
635 color = [NSColor blueColor];
638 color = [NSColor greenColor];
641 color = [NSColor yellowColor];
644 color = [NSColor brownColor];
647 color = [NSColor purpleColor];
650 color = [NSColor blackColor];
654 [debug_window[number] setBackgroundColor:color];
655 [debug_window[number] setAlphaValue:0.4];
656 [debug_window[number] setOpaque:NO];
657 [debug_window[number] setReleasedWhenClosed:YES];
658 [debug_window[number] setIgnoresMouseEvents:YES];
659 [debug_window[number] setLevel:NSFloatingWindowLevel];
661 [debug_window[number] orderFront:nil];
665 _gdk_quartz_window_is_ancestor (GdkWindow *ancestor,
668 if (ancestor == NULL || window == NULL)
671 return (gdk_window_get_parent (window) == ancestor ||
672 _gdk_quartz_window_is_ancestor (ancestor,
673 gdk_window_get_parent (window)));
677 /* See notes on top of gdkscreen-quartz.c */
679 _gdk_quartz_window_gdk_xy_to_xy (gint gdk_x,
684 GdkQuartzScreen *screen_quartz = GDK_QUARTZ_SCREEN (_gdk_screen);
687 *ns_y = screen_quartz->height - gdk_y + screen_quartz->min_y;
690 *ns_x = gdk_x + screen_quartz->min_x;
694 _gdk_quartz_window_xy_to_gdk_xy (gint ns_x,
699 GdkQuartzScreen *screen_quartz = GDK_QUARTZ_SCREEN (_gdk_screen);
702 *gdk_y = screen_quartz->height - ns_y + screen_quartz->min_y;
705 *gdk_x = ns_x - screen_quartz->min_x;
709 _gdk_quartz_window_nspoint_to_gdk_xy (NSPoint point,
713 _gdk_quartz_window_xy_to_gdk_xy (point.x, point.y,
718 find_child_window_helper (GdkWindow *window,
723 gboolean get_toplevel)
725 GdkWindowImplQuartz *impl;
728 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
730 if (window == _gdk_root)
731 update_toplevel_order ();
733 for (l = impl->sorted_children; l; l = l->next)
735 GdkWindow *child = l->data;
736 GdkWindowImplQuartz *child_impl = GDK_WINDOW_IMPL_QUARTZ (child->impl);
739 if (!GDK_WINDOW_IS_MAPPED (child))
742 temp_x = x_offset + child->x;
743 temp_y = y_offset + child->y;
745 /* Special-case the root window. We have to include the title
746 * bar in the checks, otherwise the window below the title bar
747 * will be found i.e. events punch through. (If we can find a
748 * better way to deal with the events in gdkevents-quartz, this
749 * might not be needed.)
751 if (window == _gdk_root)
753 NSRect frame = NSMakeRect (0, 0, 100, 100);
758 mask = [child_impl->toplevel styleMask];
760 /* Get the title bar height. */
761 content = [NSWindow contentRectForFrameRect:frame
763 titlebar_height = frame.size.height - content.size.height;
765 if (titlebar_height > 0 &&
766 x >= temp_x && y >= temp_y - titlebar_height &&
767 x < temp_x + child->width && y < temp_y)
769 /* The root means "unknown" i.e. a window not managed by
772 return (GdkWindow *)_gdk_root;
776 if ((!get_toplevel || (get_toplevel && window == _gdk_root)) &&
777 x >= temp_x && y >= temp_y &&
778 x < temp_x + child->width && y < temp_y + child->height)
780 /* Look for child windows. */
781 return find_child_window_helper (l->data,
791 /* Given a GdkWindow and coordinates relative to it, returns the
792 * innermost subwindow that contains the point. If the coordinates are
793 * outside the passed in window, NULL is returned.
796 _gdk_quartz_window_find_child (GdkWindow *window,
799 gboolean get_toplevel)
801 if (x >= 0 && y >= 0 && x < window->width && y < window->height)
802 return find_child_window_helper (window, x, y, 0, 0, get_toplevel);
809 _gdk_quartz_window_did_become_main (GdkWindow *window)
811 main_window_stack = g_slist_remove (main_window_stack, window);
813 if (window->window_type != GDK_WINDOW_TEMP)
814 main_window_stack = g_slist_prepend (main_window_stack, window);
816 clear_toplevel_order ();
820 _gdk_quartz_window_did_resign_main (GdkWindow *window)
822 GdkWindow *new_window = NULL;
824 if (main_window_stack)
825 new_window = main_window_stack->data;
830 toplevels = gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
832 new_window = toplevels->data;
833 g_list_free (toplevels);
837 new_window != window &&
838 GDK_WINDOW_IS_MAPPED (new_window) &&
839 WINDOW_IS_TOPLEVEL (new_window))
841 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (new_window->impl);
843 [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
846 clear_toplevel_order ();
850 get_nsscreen_for_point (gint x, gint y)
854 NSScreen *screen = NULL;
856 GDK_QUARTZ_ALLOC_POOL;
858 screens = [NSScreen screens];
860 for (i = 0; i < [screens count]; i++)
862 NSRect rect = [[screens objectAtIndex:i] frame];
864 if (x >= rect.origin.x && x <= rect.origin.x + rect.size.width &&
865 y >= rect.origin.y && y <= rect.origin.y + rect.size.height)
867 screen = [screens objectAtIndex:i];
872 GDK_QUARTZ_RELEASE_POOL;
878 _gdk_quartz_display_create_window_impl (GdkDisplay *display,
880 GdkWindow *real_parent,
882 GdkEventMask event_mask,
883 GdkWindowAttr *attributes,
884 gint attributes_mask)
886 GdkWindowImplQuartz *impl;
887 GdkWindowImplQuartz *parent_impl;
889 GDK_QUARTZ_ALLOC_POOL;
891 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_QUARTZ, NULL);
892 window->impl = GDK_WINDOW_IMPL (impl);
893 impl->wrapper = window;
895 parent_impl = GDK_WINDOW_IMPL_QUARTZ (window->parent->impl);
897 switch (window->window_type)
899 case GDK_WINDOW_TOPLEVEL:
900 case GDK_WINDOW_TEMP:
901 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
903 /* The common code warns for this case */
904 parent_impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
908 /* Maintain the z-ordered list of children. */
909 if (window->parent != _gdk_root)
910 parent_impl->sorted_children = g_list_prepend (parent_impl->sorted_children, window);
912 clear_toplevel_order ();
914 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
915 (attributes->cursor) :
920 switch (attributes->window_type)
922 case GDK_WINDOW_TOPLEVEL:
923 case GDK_WINDOW_TEMP:
928 NSUInteger style_mask;
932 /* initWithContentRect will place on the mainScreen by default.
933 * We want to select the screen to place on ourselves. We need
934 * to find the screen the window will be on and correct the
935 * content_rect coordinates to be relative to that screen.
937 _gdk_quartz_window_gdk_xy_to_xy (window->x, window->y, &nx, &ny);
939 screen = get_nsscreen_for_point (nx, ny);
940 screen_rect = [screen frame];
941 nx -= screen_rect.origin.x;
942 ny -= screen_rect.origin.y;
944 content_rect = NSMakeRect (nx, ny - window->height,
948 if (attributes->window_type == GDK_WINDOW_TEMP ||
949 attributes->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
951 style_mask = NSBorderlessWindowMask;
955 style_mask = (NSTitledWindowMask |
956 NSClosableWindowMask |
957 NSMiniaturizableWindowMask |
958 NSResizableWindowMask);
961 impl->toplevel = [[GdkQuartzNSWindow alloc] initWithContentRect:content_rect
963 backing:NSBackingStoreBuffered
967 if (attributes_mask & GDK_WA_TITLE)
968 title = attributes->title;
970 title = get_default_title ();
972 gdk_window_set_title (window, title);
974 if (gdk_window_get_visual (window) == gdk_screen_get_rgba_visual (_gdk_screen))
976 [impl->toplevel setOpaque:NO];
977 [impl->toplevel setBackgroundColor:[NSColor clearColor]];
980 content_rect.origin.x = 0;
981 content_rect.origin.y = 0;
983 impl->view = [[GdkQuartzView alloc] initWithFrame:content_rect];
984 [impl->view setGdkWindow:window];
985 [impl->toplevel setContentView:impl->view];
986 [impl->view release];
990 case GDK_WINDOW_CHILD:
992 GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (window->parent->impl);
994 if (!window->input_only)
996 NSRect frame_rect = NSMakeRect (window->x + window->parent->abs_x,
997 window->y + window->parent->abs_y,
1001 impl->view = [[GdkQuartzView alloc] initWithFrame:frame_rect];
1003 [impl->view setGdkWindow:window];
1005 /* GdkWindows should be hidden by default */
1006 [impl->view setHidden:YES];
1007 [parent_impl->view addSubview:impl->view];
1008 [impl->view release];
1014 g_assert_not_reached ();
1017 GDK_QUARTZ_RELEASE_POOL;
1019 if (attributes_mask & GDK_WA_TYPE_HINT)
1020 gdk_window_set_type_hint (window, attributes->type_hint);
1024 _gdk_quartz_window_update_position (GdkWindow *window)
1027 NSRect content_rect;
1028 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1030 GDK_QUARTZ_ALLOC_POOL;
1032 frame_rect = [impl->toplevel frame];
1033 content_rect = [impl->toplevel contentRectForFrameRect:frame_rect];
1035 _gdk_quartz_window_xy_to_gdk_xy (content_rect.origin.x,
1036 content_rect.origin.y + content_rect.size.height,
1037 &window->x, &window->y);
1040 GDK_QUARTZ_RELEASE_POOL;
1044 _gdk_quartz_window_init_windowing (GdkDisplay *display,
1047 GdkWindowImplQuartz *impl;
1049 g_assert (_gdk_root == NULL);
1051 _gdk_root = _gdk_display_create_window (display);
1053 _gdk_root->impl = g_object_new (_gdk_root_window_impl_quartz_get_type (), NULL);
1054 _gdk_root->impl_window = _gdk_root;
1055 _gdk_root->visual = gdk_screen_get_system_visual (screen);
1057 impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
1059 _gdk_quartz_screen_update_window_sizes (screen);
1061 _gdk_root->state = 0; /* We don't want GDK_WINDOW_STATE_WITHDRAWN here */
1062 _gdk_root->window_type = GDK_WINDOW_ROOT;
1063 _gdk_root->depth = 24;
1064 _gdk_root->viewable = TRUE;
1066 impl->wrapper = _gdk_root;
1070 gdk_quartz_window_destroy (GdkWindow *window,
1072 gboolean foreign_destroy)
1074 GdkWindowImplQuartz *impl;
1077 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1079 main_window_stack = g_slist_remove (main_window_stack, window);
1081 g_list_free (impl->sorted_children);
1082 impl->sorted_children = NULL;
1084 parent = window->parent;
1087 GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (parent->impl);
1089 parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window);
1092 if (impl->cairo_surface)
1094 cairo_surface_finish (impl->cairo_surface);
1095 cairo_surface_set_user_data (impl->cairo_surface, &gdk_quartz_cairo_key,
1097 impl->cairo_surface = NULL;
1100 if (!recursing && !foreign_destroy)
1102 GDK_QUARTZ_ALLOC_POOL;
1105 [impl->toplevel close];
1106 else if (impl->view)
1107 [impl->view removeFromSuperview];
1109 GDK_QUARTZ_RELEASE_POOL;
1113 static cairo_surface_t *
1114 gdk_window_quartz_resize_cairo_surface (GdkWindow *window,
1115 cairo_surface_t *surface,
1119 /* Quartz surfaces cannot be resized */
1120 cairo_surface_destroy (surface);
1126 gdk_quartz_window_destroy_foreign (GdkWindow *window)
1128 /* Foreign windows aren't supported in OSX. */
1131 /* FIXME: This might be possible to simplify with client-side windows. Also
1132 * note that already_mapped is not used yet, see the x11 backend.
1135 gdk_window_quartz_show (GdkWindow *window, gboolean already_mapped)
1137 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1138 gboolean focus_on_map;
1140 GDK_QUARTZ_ALLOC_POOL;
1142 if (!GDK_WINDOW_IS_MAPPED (window))
1143 focus_on_map = window->focus_on_map;
1145 focus_on_map = TRUE;
1147 if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel)
1151 make_key = (window->accept_focus && focus_on_map &&
1152 window->window_type != GDK_WINDOW_TEMP);
1154 [(GdkQuartzNSWindow*)impl->toplevel showAndMakeKey:make_key];
1155 clear_toplevel_order ();
1157 _gdk_quartz_events_send_map_event (window);
1161 [impl->view setHidden:NO];
1164 [impl->view setNeedsDisplay:YES];
1166 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_WITHDRAWN, 0);
1168 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1169 gdk_window_maximize (window);
1171 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1172 gdk_window_iconify (window);
1174 if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1175 _gdk_quartz_window_attach_to_parent (window);
1177 GDK_QUARTZ_RELEASE_POOL;
1180 /* Temporarily unsets the parent window, if the window is a
1184 _gdk_quartz_window_detach_from_parent (GdkWindow *window)
1186 GdkWindowImplQuartz *impl;
1188 g_return_if_fail (GDK_IS_WINDOW (window));
1190 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1192 g_return_if_fail (impl->toplevel != NULL);
1194 if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1196 GdkWindowImplQuartz *parent_impl;
1198 parent_impl = GDK_WINDOW_IMPL_QUARTZ (impl->transient_for->impl);
1199 [parent_impl->toplevel removeChildWindow:impl->toplevel];
1200 clear_toplevel_order ();
1204 /* Re-sets the parent window, if the window is a transient. */
1206 _gdk_quartz_window_attach_to_parent (GdkWindow *window)
1208 GdkWindowImplQuartz *impl;
1210 g_return_if_fail (GDK_IS_WINDOW (window));
1212 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1214 g_return_if_fail (impl->toplevel != NULL);
1216 if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1218 GdkWindowImplQuartz *parent_impl;
1220 parent_impl = GDK_WINDOW_IMPL_QUARTZ (impl->transient_for->impl);
1221 [parent_impl->toplevel addChildWindow:impl->toplevel ordered:NSWindowAbove];
1222 clear_toplevel_order ();
1227 gdk_window_quartz_hide (GdkWindow *window)
1229 GdkWindowImplQuartz *impl;
1231 /* Make sure we're not stuck in fullscreen mode. */
1232 if (get_fullscreen_geometry (window))
1233 SetSystemUIMode (kUIModeNormal, 0);
1235 check_grab_unmap (window);
1237 _gdk_window_clear_update_area (window);
1239 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1241 if (WINDOW_IS_TOPLEVEL (window))
1243 /* Update main window. */
1244 main_window_stack = g_slist_remove (main_window_stack, window);
1245 if ([NSApp mainWindow] == impl->toplevel)
1246 _gdk_quartz_window_did_resign_main (window);
1248 if (impl->transient_for)
1249 _gdk_quartz_window_detach_from_parent (window);
1251 [(GdkQuartzNSWindow*)impl->toplevel hide];
1253 else if (impl->view)
1255 [impl->view setHidden:YES];
1260 gdk_window_quartz_withdraw (GdkWindow *window)
1262 gdk_window_hide (window);
1266 move_resize_window_internal (GdkWindow *window,
1272 GdkWindowImplQuartz *impl;
1273 GdkRectangle old_visible;
1274 GdkRectangle new_visible;
1275 GdkRectangle scroll_rect;
1276 cairo_region_t *old_region;
1277 cairo_region_t *expose_region;
1280 if (GDK_WINDOW_DESTROYED (window))
1283 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1285 if ((x == -1 || (x == window->x)) &&
1286 (y == -1 || (y == window->y)) &&
1287 (width == -1 || (width == window->width)) &&
1288 (height == -1 || (height == window->height)))
1293 if (!impl->toplevel)
1295 /* The previously visible area of this window in a coordinate
1296 * system rooted at the origin of this window.
1298 old_visible.x = -window->x;
1299 old_visible.y = -window->y;
1301 old_visible.width = window->width;
1302 old_visible.height = window->height;
1307 delta.width = x - window->x;
1317 delta.height = y - window->y;
1326 window->width = width;
1329 window->height = height;
1331 GDK_QUARTZ_ALLOC_POOL;
1335 NSRect content_rect;
1339 _gdk_quartz_window_gdk_xy_to_xy (window->x, window->y + window->height,
1342 content_rect = NSMakeRect (gx, gy, window->width, window->height);
1344 frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
1345 [impl->toplevel setFrame:frame_rect display:YES];
1349 if (!window->input_only)
1353 nsrect = NSMakeRect (window->x, window->y, window->width, window->height);
1355 /* The newly visible area of this window in a coordinate
1356 * system rooted at the origin of this window.
1358 new_visible.x = -window->x;
1359 new_visible.y = -window->y;
1360 new_visible.width = old_visible.width; /* parent has not changed size */
1361 new_visible.height = old_visible.height; /* parent has not changed size */
1363 expose_region = cairo_region_create_rectangle (&new_visible);
1364 old_region = cairo_region_create_rectangle (&old_visible);
1365 cairo_region_subtract (expose_region, old_region);
1367 /* Determine what (if any) part of the previously visible
1368 * part of the window can be copied without a redraw
1370 scroll_rect = old_visible;
1371 scroll_rect.x -= delta.width;
1372 scroll_rect.y -= delta.height;
1373 gdk_rectangle_intersect (&scroll_rect, &old_visible, &scroll_rect);
1375 if (!cairo_region_is_empty (expose_region))
1377 if (scroll_rect.width != 0 && scroll_rect.height != 0)
1379 [impl->view scrollRect:NSMakeRect (scroll_rect.x,
1386 [impl->view setFrame:nsrect];
1388 gdk_quartz_window_set_needs_display_in_region (window, expose_region);
1392 [impl->view setFrame:nsrect];
1393 [impl->view setNeedsDisplay:YES];
1396 cairo_region_destroy (expose_region);
1397 cairo_region_destroy (old_region);
1401 GDK_QUARTZ_RELEASE_POOL;
1405 window_quartz_move (GdkWindow *window,
1409 g_return_if_fail (GDK_IS_WINDOW (window));
1411 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1414 move_resize_window_internal (window, x, y, -1, -1);
1418 window_quartz_resize (GdkWindow *window,
1422 g_return_if_fail (GDK_IS_WINDOW (window));
1424 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1432 move_resize_window_internal (window, -1, -1, width, height);
1436 window_quartz_move_resize (GdkWindow *window,
1447 move_resize_window_internal (window, x, y, width, height);
1451 gdk_window_quartz_move_resize (GdkWindow *window,
1458 if (with_move && (width < 0 && height < 0))
1459 window_quartz_move (window, x, y);
1463 window_quartz_move_resize (window, x, y, width, height);
1465 window_quartz_resize (window, width, height);
1469 /* FIXME: This might need fixing (reparenting didn't work before client-side
1473 gdk_window_quartz_reparent (GdkWindow *window,
1474 GdkWindow *new_parent,
1478 GdkWindow *old_parent;
1479 GdkWindowImplQuartz *impl, *old_parent_impl, *new_parent_impl;
1480 NSView *view, *new_parent_view;
1482 if (new_parent == _gdk_root)
1484 /* Could be added, just needs implementing. */
1485 g_warning ("Reparenting to root window is not supported yet in the Mac OS X backend");
1489 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1492 new_parent_impl = GDK_WINDOW_IMPL_QUARTZ (new_parent->impl);
1493 new_parent_view = new_parent_impl->view;
1495 old_parent = window->parent;
1496 old_parent_impl = GDK_WINDOW_IMPL_QUARTZ (old_parent->impl);
1500 [view removeFromSuperview];
1501 [new_parent_view addSubview:view];
1505 window->parent = new_parent;
1509 old_parent_impl->sorted_children = g_list_remove (old_parent_impl->sorted_children, window);
1512 new_parent_impl->sorted_children = g_list_prepend (new_parent_impl->sorted_children, window);
1517 /* Get the toplevel ordering from NSApp and update our own list. We do
1518 * this on demand since the NSApp's list is not up to date directly
1519 * after we get windowDidBecomeMain.
1522 update_toplevel_order (void)
1524 GdkWindowImplQuartz *root_impl;
1525 NSEnumerator *enumerator;
1527 GList *toplevels = NULL;
1529 root_impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
1531 if (root_impl->sorted_children)
1534 GDK_QUARTZ_ALLOC_POOL;
1536 enumerator = [[NSApp orderedWindows] objectEnumerator];
1537 while ((nswindow = [enumerator nextObject]))
1541 if (![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
1544 window = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
1545 toplevels = g_list_prepend (toplevels, window);
1548 GDK_QUARTZ_RELEASE_POOL;
1550 root_impl->sorted_children = g_list_reverse (toplevels);
1554 clear_toplevel_order (void)
1556 GdkWindowImplQuartz *root_impl;
1558 root_impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
1560 g_list_free (root_impl->sorted_children);
1561 root_impl->sorted_children = NULL;
1565 gdk_window_quartz_raise (GdkWindow *window)
1567 if (GDK_WINDOW_DESTROYED (window))
1570 if (WINDOW_IS_TOPLEVEL (window))
1572 GdkWindowImplQuartz *impl;
1574 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1575 [impl->toplevel orderFront:impl->toplevel];
1577 clear_toplevel_order ();
1581 GdkWindow *parent = window->parent;
1585 GdkWindowImplQuartz *impl;
1587 impl = (GdkWindowImplQuartz *)parent->impl;
1589 impl->sorted_children = g_list_remove (impl->sorted_children, window);
1590 impl->sorted_children = g_list_prepend (impl->sorted_children, window);
1596 gdk_window_quartz_lower (GdkWindow *window)
1598 if (GDK_WINDOW_DESTROYED (window))
1601 if (WINDOW_IS_TOPLEVEL (window))
1603 GdkWindowImplQuartz *impl;
1605 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1606 [impl->toplevel orderBack:impl->toplevel];
1608 clear_toplevel_order ();
1612 GdkWindow *parent = window->parent;
1616 GdkWindowImplQuartz *impl;
1618 impl = (GdkWindowImplQuartz *)parent->impl;
1620 impl->sorted_children = g_list_remove (impl->sorted_children, window);
1621 impl->sorted_children = g_list_append (impl->sorted_children, window);
1627 gdk_window_quartz_restack_toplevel (GdkWindow *window,
1631 GdkWindowImplQuartz *impl;
1634 impl = GDK_WINDOW_IMPL_QUARTZ (sibling->impl);
1635 sibling_num = [impl->toplevel windowNumber];
1637 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1640 [impl->toplevel orderWindow:NSWindowAbove relativeTo:sibling_num];
1642 [impl->toplevel orderWindow:NSWindowBelow relativeTo:sibling_num];
1646 gdk_window_quartz_set_background (GdkWindow *window,
1647 cairo_pattern_t *pattern)
1649 /* FIXME: We could theoretically set the background color for toplevels
1650 * here. (Currently we draw the background before emitting expose events)
1655 gdk_window_quartz_set_device_cursor (GdkWindow *window,
1661 if (GDK_WINDOW_DESTROYED (window))
1664 nscursor = _gdk_quartz_cursor_get_ns_cursor (cursor);
1670 gdk_window_quartz_get_geometry (GdkWindow *window,
1676 GdkWindowImplQuartz *impl;
1679 if (GDK_WINDOW_DESTROYED (window))
1682 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1683 if (window == _gdk_root)
1691 *width = window->width;
1693 *height = window->height;
1695 else if (WINDOW_IS_TOPLEVEL (window))
1697 ns_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
1699 /* This doesn't work exactly as in X. There doesn't seem to be a
1700 * way to get the coords relative to the parent window (usually
1701 * the window frame), but that seems useless except for
1702 * borderless windows where it's relative to the root window. So
1703 * we return (0, 0) (should be something like (0, 22)) for
1704 * windows with borders and the root relative coordinates
1707 if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
1709 _gdk_quartz_window_xy_to_gdk_xy (ns_rect.origin.x,
1710 ns_rect.origin.y + ns_rect.size.height,
1722 *width = ns_rect.size.width;
1724 *height = ns_rect.size.height;
1728 ns_rect = [impl->view frame];
1731 *x = ns_rect.origin.x;
1733 *y = ns_rect.origin.y;
1735 *width = ns_rect.size.width;
1737 *height = ns_rect.size.height;
1742 gdk_window_quartz_get_root_coords (GdkWindow *window,
1748 int tmp_x = 0, tmp_y = 0;
1749 GdkWindow *toplevel;
1750 NSRect content_rect;
1751 GdkWindowImplQuartz *impl;
1753 if (GDK_WINDOW_DESTROYED (window))
1763 if (window == _gdk_root)
1773 toplevel = gdk_window_get_toplevel (window);
1774 impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
1776 content_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
1778 _gdk_quartz_window_xy_to_gdk_xy (content_rect.origin.x,
1779 content_rect.origin.y + content_rect.size.height,
1785 while (window != toplevel)
1787 if (_gdk_window_has_impl ((GdkWindow *)window))
1793 window = window->parent;
1805 gdk_quartz_window_get_root_origin (GdkWindow *window,
1814 gdk_window_get_frame_extents (window, &rect);
1823 /* Returns coordinates relative to the passed in window. */
1825 gdk_window_quartz_get_device_state_helper (GdkWindow *window,
1829 GdkModifierType *mask)
1833 GdkWindow *toplevel;
1834 GdkWindow *found_window;
1836 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1838 if (GDK_WINDOW_DESTROYED (window))
1846 toplevel = gdk_window_get_toplevel (window);
1848 *mask = _gdk_quartz_events_get_current_keyboard_modifiers () |
1849 _gdk_quartz_events_get_current_mouse_modifiers ();
1851 /* Get the y coordinate, needs to be flipped. */
1852 if (window == _gdk_root)
1854 point = [NSEvent mouseLocation];
1855 _gdk_quartz_window_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
1859 GdkWindowImplQuartz *impl;
1862 impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
1863 nswindow = impl->toplevel;
1865 point = [nswindow mouseLocationOutsideOfEventStream];
1868 y_tmp = toplevel->height - point.y;
1870 window = (GdkWindow *)toplevel;
1873 found_window = _gdk_quartz_window_find_child (window, x_tmp, y_tmp,
1876 /* We never return the root window. */
1877 if (found_window == _gdk_root)
1878 found_window = NULL;
1883 return found_window;
1887 gdk_window_quartz_get_device_state (GdkWindow *window,
1891 GdkModifierType *mask)
1893 return gdk_window_quartz_get_device_state_helper (window,
1895 x, y, mask) != NULL;
1898 /* Returns coordinates relative to the root. */
1900 _gdk_windowing_get_device_state (GdkDisplay *display,
1905 GdkModifierType *mask)
1907 g_return_if_fail (display == _gdk_display);
1909 *screen = _gdk_screen;
1910 gdk_window_quartz_get_device_state_helper (_gdk_root, device, x, y, mask);
1913 /* Returns coordinates relative to the found window. */
1915 _gdk_windowing_window_at_pointer (GdkDisplay *display,
1918 GdkModifierType *mask,
1919 gboolean get_toplevel)
1921 GdkWindow *found_window;
1923 GdkModifierType tmp_mask = 0;
1925 found_window = gdk_window_quartz_get_device_state_helper (_gdk_root,
1926 display->core_pointer,
1931 /* The coordinates returned above are relative the root, we want
1932 * coordinates relative the window here.
1934 while (found_window != _gdk_root)
1936 x -= found_window->x;
1937 y -= found_window->y;
1939 found_window = found_window->parent;
1947 /* Mimic the X backend here, -1,-1 for unknown windows. */
1957 /* Requested toplevel, find it. */
1958 /* TODO: This can be implemented more efficient by never
1959 recursing into children in the first place */
1962 /* Convert to toplevel */
1963 while (found_window->parent != NULL &&
1964 found_window->parent->window_type != GDK_WINDOW_ROOT)
1966 *win_x += found_window->x;
1967 *win_y += found_window->y;
1968 found_window = found_window->parent;
1973 return found_window;
1977 _gdk_windowing_window_at_device_position (GdkDisplay *display,
1981 GdkModifierType *mask,
1982 gboolean get_toplevel)
1984 return GDK_DEVICE_GET_CLASS (device)->window_at_position (device,
1992 gdk_window_quartz_get_events (GdkWindow *window)
1994 if (GDK_WINDOW_DESTROYED (window))
1997 return window->event_mask;
2001 gdk_window_quartz_set_events (GdkWindow *window,
2002 GdkEventMask event_mask)
2004 /* The mask is set in the common code. */
2008 gdk_quartz_window_set_urgency_hint (GdkWindow *window,
2011 if (GDK_WINDOW_DESTROYED (window) ||
2012 !WINDOW_IS_TOPLEVEL (window))
2015 /* FIXME: Implement */
2019 gdk_quartz_window_set_geometry_hints (GdkWindow *window,
2020 const GdkGeometry *geometry,
2021 GdkWindowHints geom_mask)
2023 GdkWindowImplQuartz *impl;
2025 g_return_if_fail (geometry != NULL);
2027 if (GDK_WINDOW_DESTROYED (window) ||
2028 !WINDOW_IS_TOPLEVEL (window))
2031 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2032 if (!impl->toplevel)
2035 if (geom_mask & GDK_HINT_POS)
2037 /* FIXME: Implement */
2040 if (geom_mask & GDK_HINT_USER_POS)
2042 /* FIXME: Implement */
2045 if (geom_mask & GDK_HINT_USER_SIZE)
2047 /* FIXME: Implement */
2050 if (geom_mask & GDK_HINT_MIN_SIZE)
2054 size.width = geometry->min_width;
2055 size.height = geometry->min_height;
2057 [impl->toplevel setContentMinSize:size];
2060 if (geom_mask & GDK_HINT_MAX_SIZE)
2064 size.width = geometry->max_width;
2065 size.height = geometry->max_height;
2067 [impl->toplevel setContentMaxSize:size];
2070 if (geom_mask & GDK_HINT_BASE_SIZE)
2072 /* FIXME: Implement */
2075 if (geom_mask & GDK_HINT_RESIZE_INC)
2079 size.width = geometry->width_inc;
2080 size.height = geometry->height_inc;
2082 [impl->toplevel setContentResizeIncrements:size];
2085 if (geom_mask & GDK_HINT_ASPECT)
2087 /* FIXME: Implement */
2090 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2092 /* FIXME: Implement */
2097 gdk_quartz_window_set_title (GdkWindow *window,
2100 GdkWindowImplQuartz *impl;
2102 g_return_if_fail (title != NULL);
2104 if (GDK_WINDOW_DESTROYED (window) ||
2105 !WINDOW_IS_TOPLEVEL (window))
2108 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2112 GDK_QUARTZ_ALLOC_POOL;
2113 [impl->toplevel setTitle:[NSString stringWithUTF8String:title]];
2114 GDK_QUARTZ_RELEASE_POOL;
2119 gdk_quartz_window_set_role (GdkWindow *window,
2122 if (GDK_WINDOW_DESTROYED (window) ||
2123 WINDOW_IS_TOPLEVEL (window))
2126 /* FIXME: Implement */
2130 gdk_quartz_window_set_startup_id (GdkWindow *window,
2131 const gchar *startup_id)
2133 /* FIXME: Implement? */
2137 gdk_quartz_window_set_transient_for (GdkWindow *window,
2140 GdkWindowImplQuartz *window_impl;
2141 GdkWindowImplQuartz *parent_impl;
2143 if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (parent) ||
2144 !WINDOW_IS_TOPLEVEL (window))
2147 window_impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2148 if (!window_impl->toplevel)
2151 GDK_QUARTZ_ALLOC_POOL;
2153 if (window_impl->transient_for)
2155 _gdk_quartz_window_detach_from_parent (window);
2157 g_object_unref (window_impl->transient_for);
2158 window_impl->transient_for = NULL;
2161 parent_impl = GDK_WINDOW_IMPL_QUARTZ (parent->impl);
2162 if (parent_impl->toplevel)
2164 /* We save the parent because it needs to be unset/reset when
2165 * hiding and showing the window.
2168 /* We don't set transients for tooltips, they are already
2169 * handled by the window level being the top one. If we do, then
2170 * the parent window will be brought to the top just because the
2171 * tooltip is, which is not what we want.
2173 if (gdk_window_get_type_hint (window) != GDK_WINDOW_TYPE_HINT_TOOLTIP)
2175 window_impl->transient_for = g_object_ref (parent);
2177 /* We only add the window if it is shown, otherwise it will
2178 * be shown unconditionally here. If it is not shown, the
2179 * window will be added in show() instead.
2181 if (!(window->state & GDK_WINDOW_STATE_WITHDRAWN))
2182 _gdk_quartz_window_attach_to_parent (window);
2186 GDK_QUARTZ_RELEASE_POOL;
2190 gdk_window_quartz_shape_combine_region (GdkWindow *window,
2191 const cairo_region_t *shape,
2195 /* FIXME: Implement */
2199 gdk_window_quartz_input_shape_combine_region (GdkWindow *window,
2200 const cairo_region_t *shape_region,
2204 /* FIXME: Implement */
2208 gdk_quartz_window_set_override_redirect (GdkWindow *window,
2209 gboolean override_redirect)
2211 /* FIXME: Implement */
2215 gdk_quartz_window_set_accept_focus (GdkWindow *window,
2216 gboolean accept_focus)
2218 window->accept_focus = accept_focus != FALSE;
2222 gdk_window_quartz_set_static_gravities (GdkWindow *window,
2223 gboolean use_static)
2225 if (GDK_WINDOW_DESTROYED (window) ||
2226 !WINDOW_IS_TOPLEVEL (window))
2229 /* FIXME: Implement */
2234 gdk_quartz_window_queue_antiexpose (GdkWindow *window,
2235 cairo_region_t *area)
2241 gdk_quartz_window_translate (GdkWindow *window,
2242 cairo_region_t *area,
2246 cairo_region_t *invalidate, *scrolled;
2247 GdkWindowImplQuartz *impl = (GdkWindowImplQuartz *)window->impl;
2248 GdkRectangle extents;
2250 cairo_region_get_extents (area, &extents);
2252 [impl->view scrollRect:NSMakeRect (extents.x - dx, extents.y - dy,
2253 extents.width, extents.height)
2254 by:NSMakeSize (dx, dy)];
2256 if (impl->needs_display_region)
2258 cairo_region_t *intersection;
2260 /* Invalidate already invalidated area that was moved at new
2263 intersection = cairo_region_copy (impl->needs_display_region);
2264 cairo_region_intersect (intersection, area);
2265 cairo_region_translate (intersection, dx, dy);
2267 gdk_quartz_window_set_needs_display_in_region (window, intersection);
2268 cairo_region_destroy (intersection);
2271 /* Calculate newly exposed area that needs invalidation */
2272 scrolled = cairo_region_copy (area);
2273 cairo_region_translate (scrolled, dx, dy);
2275 invalidate = cairo_region_copy (area);
2276 cairo_region_subtract (invalidate, scrolled);
2277 cairo_region_destroy (scrolled);
2279 gdk_quartz_window_set_needs_display_in_region (window, invalidate);
2280 cairo_region_destroy (invalidate);
2284 gdk_quartz_window_set_focus_on_map (GdkWindow *window,
2285 gboolean focus_on_map)
2287 window->focus_on_map = focus_on_map != FALSE;
2291 gdk_quartz_window_set_icon_name (GdkWindow *window,
2294 /* FIXME: Implement */
2298 gdk_quartz_window_focus (GdkWindow *window,
2301 GdkWindowImplQuartz *impl;
2303 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2305 if (GDK_WINDOW_DESTROYED (window) ||
2306 !WINDOW_IS_TOPLEVEL (window))
2309 if (window->accept_focus && window->window_type != GDK_WINDOW_TEMP)
2311 GDK_QUARTZ_ALLOC_POOL;
2312 [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
2313 clear_toplevel_order ();
2314 GDK_QUARTZ_RELEASE_POOL;
2319 window_type_hint_to_level (GdkWindowTypeHint hint)
2321 /* the order in this switch statement corresponds to the actual
2322 * stacking order: the first group is top, the last group is bottom
2326 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2327 case GDK_WINDOW_TYPE_HINT_COMBO:
2328 case GDK_WINDOW_TYPE_HINT_DND:
2329 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2330 return NSPopUpMenuWindowLevel;
2332 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2333 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2334 return NSStatusWindowLevel;
2336 case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
2337 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
2338 return NSTornOffMenuWindowLevel;
2340 case GDK_WINDOW_TYPE_HINT_DOCK:
2341 case GDK_WINDOW_TYPE_HINT_UTILITY:
2342 return NSFloatingWindowLevel;
2344 case GDK_WINDOW_TYPE_HINT_NORMAL: /* Normal toplevel window */
2345 case GDK_WINDOW_TYPE_HINT_DIALOG: /* Dialog window */
2346 case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
2347 case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
2354 return NSNormalWindowLevel;
2358 window_type_hint_to_shadow (GdkWindowTypeHint hint)
2362 case GDK_WINDOW_TYPE_HINT_NORMAL: /* Normal toplevel window */
2363 case GDK_WINDOW_TYPE_HINT_DIALOG: /* Dialog window */
2364 case GDK_WINDOW_TYPE_HINT_DOCK:
2365 case GDK_WINDOW_TYPE_HINT_UTILITY:
2366 case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
2367 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
2368 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2369 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2370 case GDK_WINDOW_TYPE_HINT_COMBO:
2371 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2372 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2375 case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
2376 case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
2377 case GDK_WINDOW_TYPE_HINT_DND:
2388 window_type_hint_to_hides_on_deactivate (GdkWindowTypeHint hint)
2392 case GDK_WINDOW_TYPE_HINT_UTILITY:
2393 case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
2394 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2395 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2396 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2407 gdk_quartz_window_set_type_hint (GdkWindow *window,
2408 GdkWindowTypeHint hint)
2410 GdkWindowImplQuartz *impl;
2412 if (GDK_WINDOW_DESTROYED (window) ||
2413 !WINDOW_IS_TOPLEVEL (window))
2416 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2418 impl->type_hint = hint;
2420 /* Match the documentation, only do something if we're not mapped yet. */
2421 if (GDK_WINDOW_IS_MAPPED (window))
2424 [impl->toplevel setHasShadow: window_type_hint_to_shadow (hint)];
2425 [impl->toplevel setLevel: window_type_hint_to_level (hint)];
2426 [impl->toplevel setHidesOnDeactivate: window_type_hint_to_hides_on_deactivate (hint)];
2429 static GdkWindowTypeHint
2430 gdk_quartz_window_get_type_hint (GdkWindow *window)
2432 if (GDK_WINDOW_DESTROYED (window) ||
2433 !WINDOW_IS_TOPLEVEL (window))
2434 return GDK_WINDOW_TYPE_HINT_NORMAL;
2436 return GDK_WINDOW_IMPL_QUARTZ (window->impl)->type_hint;
2440 gdk_quartz_window_set_modal_hint (GdkWindow *window,
2443 if (GDK_WINDOW_DESTROYED (window) ||
2444 !WINDOW_IS_TOPLEVEL (window))
2447 /* FIXME: Implement */
2451 gdk_quartz_window_set_skip_taskbar_hint (GdkWindow *window,
2452 gboolean skips_taskbar)
2454 if (GDK_WINDOW_DESTROYED (window) ||
2455 !WINDOW_IS_TOPLEVEL (window))
2458 /* FIXME: Implement */
2462 gdk_quartz_window_set_skip_pager_hint (GdkWindow *window,
2463 gboolean skips_pager)
2465 if (GDK_WINDOW_DESTROYED (window) ||
2466 !WINDOW_IS_TOPLEVEL (window))
2469 /* FIXME: Implement */
2473 gdk_quartz_window_begin_resize_drag (GdkWindow *window,
2481 GdkWindowImplQuartz *impl;
2483 g_return_if_fail (GDK_IS_WINDOW (window));
2485 if (edge != GDK_WINDOW_EDGE_SOUTH_EAST)
2487 g_warning ("Resizing is only implemented for GDK_WINDOW_EDGE_SOUTH_EAST on Mac OS");
2491 if (GDK_WINDOW_DESTROYED (window))
2494 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2496 if (!impl->toplevel)
2498 g_warning ("Can't call gdk_window_begin_resize_drag on non-toplevel window");
2502 [(GdkQuartzNSWindow *)impl->toplevel beginManualResize];
2506 gdk_quartz_window_begin_move_drag (GdkWindow *window,
2513 GdkWindowImplQuartz *impl;
2515 if (GDK_WINDOW_DESTROYED (window) ||
2516 !WINDOW_IS_TOPLEVEL (window))
2519 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2521 if (!impl->toplevel)
2523 g_warning ("Can't call gdk_window_begin_move_drag on non-toplevel window");
2527 [(GdkQuartzNSWindow *)impl->toplevel beginManualMove];
2531 gdk_quartz_window_set_icon_list (GdkWindow *window,
2534 /* FIXME: Implement */
2538 gdk_quartz_window_get_frame_extents (GdkWindow *window,
2541 GdkWindow *toplevel;
2542 GdkWindowImplQuartz *impl;
2545 g_return_if_fail (rect != NULL);
2553 toplevel = gdk_window_get_effective_toplevel (window);
2554 impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
2556 ns_rect = [impl->toplevel frame];
2558 _gdk_quartz_window_xy_to_gdk_xy (ns_rect.origin.x,
2559 ns_rect.origin.y + ns_rect.size.height,
2560 &rect->x, &rect->y);
2562 rect->width = ns_rect.size.width;
2563 rect->height = ns_rect.size.height;
2566 /* Fake protocol to make gcc think that it's OK to call setStyleMask
2567 even if it isn't. We check to make sure before actually calling
2570 @protocol CanSetStyleMask
2571 - (void)setStyleMask:(int)mask;
2575 gdk_quartz_window_set_decorations (GdkWindow *window,
2576 GdkWMDecoration decorations)
2578 GdkWindowImplQuartz *impl;
2579 NSUInteger old_mask, new_mask;
2582 if (GDK_WINDOW_DESTROYED (window) ||
2583 !WINDOW_IS_TOPLEVEL (window))
2586 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2588 if (decorations == 0 || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP ||
2589 impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN )
2591 new_mask = NSBorderlessWindowMask;
2595 /* FIXME: Honor other GDK_DECOR_* flags. */
2596 new_mask = (NSTitledWindowMask | NSClosableWindowMask |
2597 NSMiniaturizableWindowMask | NSResizableWindowMask);
2600 GDK_QUARTZ_ALLOC_POOL;
2602 old_mask = [impl->toplevel styleMask];
2604 if (old_mask != new_mask)
2608 old_view = [[impl->toplevel contentView] retain];
2610 rect = [impl->toplevel frame];
2612 /* Properly update the size of the window when the titlebar is
2615 if (old_mask == NSBorderlessWindowMask &&
2616 new_mask != NSBorderlessWindowMask)
2618 rect = [NSWindow frameRectForContentRect:rect styleMask:new_mask];
2621 else if (old_mask != NSBorderlessWindowMask &&
2622 new_mask == NSBorderlessWindowMask)
2624 rect = [NSWindow contentRectForFrameRect:rect styleMask:old_mask];
2627 /* Note, before OS 10.6 there doesn't seem to be a way to change this
2628 * without recreating the toplevel. From 10.6 onward, a simple call to
2629 * setStyleMask takes care of most of this, except for ensuring that the
2632 if ([impl->toplevel respondsToSelector:@selector(setStyleMask:)])
2634 NSString *title = [impl->toplevel title];
2636 [(id<CanSetStyleMask>)impl->toplevel setStyleMask:new_mask];
2638 /* It appears that unsetting and then resetting NSTitledWindowMask
2639 * does not reset the title in the title bar as might be expected.
2641 * In theory we only need to set this if new_mask includes
2642 * NSTitledWindowMask. This behaved extremely oddly when
2643 * conditionalized upon that and since it has no side effects (i.e.
2644 * if NSTitledWindowMask is not requested, the title will not be
2645 * displayed) just do it unconditionally.
2647 [impl->toplevel setTitle:title];
2651 NSString *title = [impl->toplevel title];
2652 NSColor *bg = [impl->toplevel backgroundColor];
2653 NSScreen *screen = [impl->toplevel screen];
2655 /* Make sure the old window is closed, recall that releasedWhenClosed
2656 * is set on GdkQuartzWindows.
2658 [impl->toplevel close];
2660 impl->toplevel = [[GdkQuartzNSWindow alloc] initWithContentRect:rect
2662 backing:NSBackingStoreBuffered
2665 [impl->toplevel setHasShadow: window_type_hint_to_shadow (impl->type_hint)];
2666 [impl->toplevel setLevel: window_type_hint_to_level (impl->type_hint)];
2667 [impl->toplevel setTitle:title];
2668 [impl->toplevel setBackgroundColor:bg];
2669 [impl->toplevel setHidesOnDeactivate: window_type_hint_to_hides_on_deactivate (impl->type_hint)];
2670 [impl->toplevel setContentView:old_view];
2673 if (new_mask == NSBorderlessWindowMask)
2674 [impl->toplevel setContentSize:rect.size];
2676 [impl->toplevel setFrame:rect display:YES];
2678 /* Invalidate the window shadow for non-opaque views that have shadow
2679 * enabled, to get the shadow shape updated.
2681 if (![old_view isOpaque] && [impl->toplevel hasShadow])
2682 [(GdkQuartzView*)old_view setNeedsInvalidateShadow:YES];
2687 GDK_QUARTZ_RELEASE_POOL;
2691 gdk_quartz_window_get_decorations (GdkWindow *window,
2692 GdkWMDecoration *decorations)
2694 GdkWindowImplQuartz *impl;
2696 if (GDK_WINDOW_DESTROYED (window) ||
2697 !WINDOW_IS_TOPLEVEL (window))
2700 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2704 /* Borderless is 0, so we can't check it as a bit being set. */
2705 if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
2711 /* FIXME: Honor the other GDK_DECOR_* flags. */
2712 *decorations = GDK_DECOR_ALL;
2720 gdk_quartz_window_set_functions (GdkWindow *window,
2721 GdkWMFunction functions)
2723 g_return_if_fail (GDK_IS_WINDOW (window));
2725 /* FIXME: Implement */
2729 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
2730 cairo_region_t *area)
2736 gdk_quartz_window_stick (GdkWindow *window)
2738 if (GDK_WINDOW_DESTROYED (window) ||
2739 !WINDOW_IS_TOPLEVEL (window))
2744 gdk_quartz_window_unstick (GdkWindow *window)
2746 if (GDK_WINDOW_DESTROYED (window) ||
2747 !WINDOW_IS_TOPLEVEL (window))
2752 gdk_quartz_window_maximize (GdkWindow *window)
2754 GdkWindowImplQuartz *impl;
2756 if (GDK_WINDOW_DESTROYED (window) ||
2757 !WINDOW_IS_TOPLEVEL (window))
2760 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2762 if (GDK_WINDOW_IS_MAPPED (window))
2764 GDK_QUARTZ_ALLOC_POOL;
2766 if (impl->toplevel && ![impl->toplevel isZoomed])
2767 [impl->toplevel zoom:nil];
2769 GDK_QUARTZ_RELEASE_POOL;
2773 gdk_synthesize_window_state (window,
2775 GDK_WINDOW_STATE_MAXIMIZED);
2780 gdk_quartz_window_unmaximize (GdkWindow *window)
2782 GdkWindowImplQuartz *impl;
2784 if (GDK_WINDOW_DESTROYED (window) ||
2785 !WINDOW_IS_TOPLEVEL (window))
2788 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2790 if (GDK_WINDOW_IS_MAPPED (window))
2792 GDK_QUARTZ_ALLOC_POOL;
2794 if (impl->toplevel && [impl->toplevel isZoomed])
2795 [impl->toplevel zoom:nil];
2797 GDK_QUARTZ_RELEASE_POOL;
2801 gdk_synthesize_window_state (window,
2802 GDK_WINDOW_STATE_MAXIMIZED,
2808 gdk_quartz_window_iconify (GdkWindow *window)
2810 GdkWindowImplQuartz *impl;
2812 if (GDK_WINDOW_DESTROYED (window) ||
2813 !WINDOW_IS_TOPLEVEL (window))
2816 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2818 if (GDK_WINDOW_IS_MAPPED (window))
2820 GDK_QUARTZ_ALLOC_POOL;
2823 [impl->toplevel miniaturize:nil];
2825 GDK_QUARTZ_RELEASE_POOL;
2829 gdk_synthesize_window_state (window,
2831 GDK_WINDOW_STATE_ICONIFIED);
2836 gdk_quartz_window_deiconify (GdkWindow *window)
2838 GdkWindowImplQuartz *impl;
2840 if (GDK_WINDOW_DESTROYED (window) ||
2841 !WINDOW_IS_TOPLEVEL (window))
2844 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2846 if (GDK_WINDOW_IS_MAPPED (window))
2848 GDK_QUARTZ_ALLOC_POOL;
2851 [impl->toplevel deminiaturize:nil];
2853 GDK_QUARTZ_RELEASE_POOL;
2857 gdk_synthesize_window_state (window,
2858 GDK_WINDOW_STATE_ICONIFIED,
2863 static FullscreenSavedGeometry *
2864 get_fullscreen_geometry (GdkWindow *window)
2866 return g_object_get_data (G_OBJECT (window), FULLSCREEN_DATA);
2870 gdk_quartz_window_fullscreen (GdkWindow *window)
2872 FullscreenSavedGeometry *geometry;
2873 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2876 if (GDK_WINDOW_DESTROYED (window) ||
2877 !WINDOW_IS_TOPLEVEL (window))
2880 geometry = get_fullscreen_geometry (window);
2883 geometry = g_new (FullscreenSavedGeometry, 1);
2885 geometry->x = window->x;
2886 geometry->y = window->y;
2887 geometry->width = window->width;
2888 geometry->height = window->height;
2890 if (!gdk_window_get_decorations (window, &geometry->decor))
2891 geometry->decor = GDK_DECOR_ALL;
2893 g_object_set_data_full (G_OBJECT (window),
2894 FULLSCREEN_DATA, geometry,
2897 gdk_window_set_decorations (window, 0);
2899 frame = [[impl->toplevel screen] frame];
2900 move_resize_window_internal (window,
2902 frame.size.width, frame.size.height);
2903 [impl->toplevel setContentSize:frame.size];
2904 [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
2906 clear_toplevel_order ();
2909 SetSystemUIMode (kUIModeAllHidden, kUIOptionAutoShowMenuBar);
2911 gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
2915 gdk_quartz_window_unfullscreen (GdkWindow *window)
2917 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2918 FullscreenSavedGeometry *geometry;
2920 if (GDK_WINDOW_DESTROYED (window) ||
2921 !WINDOW_IS_TOPLEVEL (window))
2924 geometry = get_fullscreen_geometry (window);
2927 SetSystemUIMode (kUIModeNormal, 0);
2929 move_resize_window_internal (window,
2935 gdk_window_set_decorations (window, geometry->decor);
2937 g_object_set_data (G_OBJECT (window), FULLSCREEN_DATA, NULL);
2939 [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
2940 clear_toplevel_order ();
2942 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
2947 gdk_quartz_window_set_keep_above (GdkWindow *window,
2950 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2953 g_return_if_fail (GDK_IS_WINDOW (window));
2955 if (GDK_WINDOW_DESTROYED (window) ||
2956 !WINDOW_IS_TOPLEVEL (window))
2959 level = window_type_hint_to_level (gdk_window_get_type_hint (window));
2961 /* Adjust normal window level by one if necessary. */
2962 [impl->toplevel setLevel: level + (setting ? 1 : 0)];
2966 gdk_quartz_window_set_keep_below (GdkWindow *window,
2969 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2972 g_return_if_fail (GDK_IS_WINDOW (window));
2974 if (GDK_WINDOW_DESTROYED (window) ||
2975 !WINDOW_IS_TOPLEVEL (window))
2978 level = window_type_hint_to_level (gdk_window_get_type_hint (window));
2980 /* Adjust normal window level by one if necessary. */
2981 [impl->toplevel setLevel: level - (setting ? 1 : 0)];
2985 gdk_quartz_window_get_group (GdkWindow *window)
2987 g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
2989 if (GDK_WINDOW_DESTROYED (window) ||
2990 !WINDOW_IS_TOPLEVEL (window))
2993 /* FIXME: Implement */
2999 gdk_quartz_window_set_group (GdkWindow *window,
3002 /* FIXME: Implement */
3006 gdk_quartz_window_destroy_notify (GdkWindow *window)
3008 check_grab_destroy (window);
3012 gdk_quartz_window_set_opacity (GdkWindow *window,
3015 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
3017 g_return_if_fail (GDK_IS_WINDOW (window));
3018 g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
3020 if (GDK_WINDOW_DESTROYED (window) ||
3021 !WINDOW_IS_TOPLEVEL (window))
3026 else if (opacity > 1)
3029 [impl->toplevel setAlphaValue: opacity];
3032 static cairo_region_t *
3033 gdk_quartz_window_get_shape (GdkWindow *window)
3035 /* FIXME: implement */
3039 static cairo_region_t *
3040 gdk_quartz_window_get_input_shape (GdkWindow *window)
3042 /* FIXME: implement */
3048 gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
3050 GObjectClass *object_class = G_OBJECT_CLASS (klass);
3051 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
3052 GdkWindowImplQuartzClass *impl_quartz_class = GDK_WINDOW_IMPL_QUARTZ_CLASS (klass);
3054 parent_class = g_type_class_peek_parent (klass);
3056 object_class->finalize = gdk_window_impl_quartz_finalize;
3058 impl_class->ref_cairo_surface = gdk_quartz_ref_cairo_surface;
3059 impl_class->show = gdk_window_quartz_show;
3060 impl_class->hide = gdk_window_quartz_hide;
3061 impl_class->withdraw = gdk_window_quartz_withdraw;
3062 impl_class->set_events = gdk_window_quartz_set_events;
3063 impl_class->get_events = gdk_window_quartz_get_events;
3064 impl_class->raise = gdk_window_quartz_raise;
3065 impl_class->lower = gdk_window_quartz_lower;
3066 impl_class->restack_toplevel = gdk_window_quartz_restack_toplevel;
3067 impl_class->move_resize = gdk_window_quartz_move_resize;
3068 impl_class->set_background = gdk_window_quartz_set_background;
3069 impl_class->reparent = gdk_window_quartz_reparent;
3070 impl_class->set_device_cursor = gdk_window_quartz_set_device_cursor;
3071 impl_class->get_geometry = gdk_window_quartz_get_geometry;
3072 impl_class->get_root_coords = gdk_window_quartz_get_root_coords;
3073 impl_class->get_device_state = gdk_window_quartz_get_device_state;
3074 impl_class->shape_combine_region = gdk_window_quartz_shape_combine_region;
3075 impl_class->input_shape_combine_region = gdk_window_quartz_input_shape_combine_region;
3076 impl_class->set_static_gravities = gdk_window_quartz_set_static_gravities;
3077 impl_class->queue_antiexpose = gdk_quartz_window_queue_antiexpose;
3078 impl_class->translate = gdk_quartz_window_translate;
3079 impl_class->destroy = gdk_quartz_window_destroy;
3080 impl_class->destroy_foreign = gdk_quartz_window_destroy_foreign;
3081 impl_class->resize_cairo_surface = gdk_window_quartz_resize_cairo_surface;
3082 impl_class->get_shape = gdk_quartz_window_get_shape;
3083 impl_class->get_input_shape = gdk_quartz_window_get_input_shape;
3085 impl_class->focus = gdk_quartz_window_focus;
3086 impl_class->set_type_hint = gdk_quartz_window_set_type_hint;
3087 impl_class->get_type_hint = gdk_quartz_window_get_type_hint;
3088 impl_class->set_modal_hint = gdk_quartz_window_set_modal_hint;
3089 impl_class->set_skip_taskbar_hint = gdk_quartz_window_set_skip_taskbar_hint;
3090 impl_class->set_skip_pager_hint = gdk_quartz_window_set_skip_pager_hint;
3091 impl_class->set_urgency_hint = gdk_quartz_window_set_urgency_hint;
3092 impl_class->set_geometry_hints = gdk_quartz_window_set_geometry_hints;
3093 impl_class->set_title = gdk_quartz_window_set_title;
3094 impl_class->set_role = gdk_quartz_window_set_role;
3095 impl_class->set_startup_id = gdk_quartz_window_set_startup_id;
3096 impl_class->set_transient_for = gdk_quartz_window_set_transient_for;
3097 impl_class->get_root_origin = gdk_quartz_window_get_root_origin;
3098 impl_class->get_frame_extents = gdk_quartz_window_get_frame_extents;
3099 impl_class->set_override_redirect = gdk_quartz_window_set_override_redirect;
3100 impl_class->set_accept_focus = gdk_quartz_window_set_accept_focus;
3101 impl_class->set_focus_on_map = gdk_quartz_window_set_focus_on_map;
3102 impl_class->set_icon_list = gdk_quartz_window_set_icon_list;
3103 impl_class->set_icon_name = gdk_quartz_window_set_icon_name;
3104 impl_class->iconify = gdk_quartz_window_iconify;
3105 impl_class->deiconify = gdk_quartz_window_deiconify;
3106 impl_class->stick = gdk_quartz_window_stick;
3107 impl_class->unstick = gdk_quartz_window_unstick;
3108 impl_class->maximize = gdk_quartz_window_maximize;
3109 impl_class->unmaximize = gdk_quartz_window_unmaximize;
3110 impl_class->fullscreen = gdk_quartz_window_fullscreen;
3111 impl_class->unfullscreen = gdk_quartz_window_unfullscreen;
3112 impl_class->set_keep_above = gdk_quartz_window_set_keep_above;
3113 impl_class->set_keep_below = gdk_quartz_window_set_keep_below;
3114 impl_class->get_group = gdk_quartz_window_get_group;
3115 impl_class->set_group = gdk_quartz_window_set_group;
3116 impl_class->set_decorations = gdk_quartz_window_set_decorations;
3117 impl_class->get_decorations = gdk_quartz_window_get_decorations;
3118 impl_class->set_functions = gdk_quartz_window_set_functions;
3119 impl_class->set_functions = gdk_quartz_window_set_functions;
3120 impl_class->begin_resize_drag = gdk_quartz_window_begin_resize_drag;
3121 impl_class->begin_move_drag = gdk_quartz_window_begin_move_drag;
3122 impl_class->set_opacity = gdk_quartz_window_set_opacity;
3123 impl_class->destroy_notify = gdk_quartz_window_destroy_notify;
3124 impl_class->register_dnd = _gdk_quartz_window_register_dnd;
3125 impl_class->drag_begin = _gdk_quartz_window_drag_begin;
3126 impl_class->process_updates_recurse = _gdk_quartz_window_process_updates_recurse;
3127 impl_class->sync_rendering = _gdk_quartz_window_sync_rendering;
3128 impl_class->simulate_key = _gdk_quartz_window_simulate_key;
3129 impl_class->simulate_button = _gdk_quartz_window_simulate_button;
3130 impl_class->get_property = _gdk_quartz_window_get_property;
3131 impl_class->change_property = _gdk_quartz_window_change_property;
3132 impl_class->delete_property = _gdk_quartz_window_delete_property;
3135 impl_quartz_class->get_context = gdk_window_impl_quartz_get_context;
3136 impl_quartz_class->release_context = gdk_window_impl_quartz_release_context;
3140 _gdk_window_impl_quartz_get_type (void)
3142 static GType object_type = 0;
3146 const GTypeInfo object_info =
3148 sizeof (GdkWindowImplQuartzClass),
3149 (GBaseInitFunc) NULL,
3150 (GBaseFinalizeFunc) NULL,
3151 (GClassInitFunc) gdk_window_impl_quartz_class_init,
3152 NULL, /* class_finalize */
3153 NULL, /* class_data */
3154 sizeof (GdkWindowImplQuartz),
3155 0, /* n_preallocs */
3156 (GInstanceInitFunc) gdk_window_impl_quartz_init,
3159 const GInterfaceInfo paintable_info =
3161 (GInterfaceInitFunc) gdk_window_impl_quartz_paintable_init,
3166 object_type = g_type_register_static (GDK_TYPE_WINDOW_IMPL,
3167 "GdkWindowImplQuartz",
3169 g_type_add_interface_static (object_type,
3178 gdk_quartz_window_get_context (GdkWindowImplQuartz *window,
3181 if (!GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->get_context)
3183 g_warning ("%s doesn't implement GdkWindowImplQuartzClass::get_context()",
3184 G_OBJECT_TYPE_NAME (window));
3188 return GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->get_context (window, antialias);
3192 gdk_quartz_window_release_context (GdkWindowImplQuartz *window,
3193 CGContextRef cg_context)
3195 if (!GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->release_context)
3197 g_warning ("%s doesn't implement GdkWindowImplQuartzClass::release_context()",
3198 G_OBJECT_TYPE_NAME (window));
3202 GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->release_context (window, cg_context);
3208 gdk_root_window_impl_quartz_get_context (GdkWindowImplQuartz *window,
3211 CGColorSpaceRef colorspace;
3212 CGContextRef cg_context;
3213 GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (window);
3215 if (GDK_WINDOW_DESTROYED (window_impl->wrapper))
3218 /* We do not have the notion of a root window on OS X. We fake this
3219 * by creating a 1x1 bitmap and return a context to that.
3221 colorspace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
3222 cg_context = CGBitmapContextCreate (NULL,
3223 1, 1, 8, 4, colorspace,
3224 kCGImageAlphaPremultipliedLast);
3225 CGColorSpaceRelease (colorspace);
3231 gdk_root_window_impl_quartz_release_context (GdkWindowImplQuartz *window,
3232 CGContextRef cg_context)
3234 CGContextRelease (cg_context);
3238 gdk_root_window_impl_quartz_class_init (GdkRootWindowImplQuartzClass *klass)
3240 GdkWindowImplQuartzClass *window_quartz_class = GDK_WINDOW_IMPL_QUARTZ_CLASS (klass);
3242 root_window_parent_class = g_type_class_peek_parent (klass);
3244 window_quartz_class->get_context = gdk_root_window_impl_quartz_get_context;
3245 window_quartz_class->release_context = gdk_root_window_impl_quartz_release_context;
3249 gdk_root_window_impl_quartz_init (GdkRootWindowImplQuartz *impl)
3254 _gdk_root_window_impl_quartz_get_type (void)
3256 static GType object_type = 0;
3260 const GTypeInfo object_info =
3262 sizeof (GdkRootWindowImplQuartzClass),
3263 (GBaseInitFunc) NULL,
3264 (GBaseFinalizeFunc) NULL,
3265 (GClassInitFunc) gdk_root_window_impl_quartz_class_init,
3266 NULL, /* class_finalize */
3267 NULL, /* class_data */
3268 sizeof (GdkRootWindowImplQuartz),
3269 0, /* n_preallocs */
3270 (GInstanceInitFunc) gdk_root_window_impl_quartz_init,
3273 object_type = g_type_register_static (GDK_TYPE_WINDOW_IMPL_QUARTZ,
3274 "GdkRootWindowQuartz",