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, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
25 #include <gdk/gdkdeviceprivate.h>
26 #include <gdk/gdkdisplayprivate.h>
28 #include "gdkwindowimpl.h"
29 #include "gdkprivate-quartz.h"
30 #include "gdkquartzscreen.h"
31 #include "gdkquartzcursor.h"
33 #include <Carbon/Carbon.h>
36 #include <cairo-quartz.h>
38 static gpointer parent_class;
39 static gpointer root_window_parent_class;
41 static GSList *update_nswindows;
42 static gboolean in_process_all_updates = FALSE;
44 static GSList *main_window_stack;
46 void _gdk_quartz_window_flush (GdkWindowImplQuartz *window_impl);
48 #define FULLSCREEN_DATA "fullscreen-data"
54 GdkWMDecoration decor;
55 } FullscreenSavedGeometry;
58 static void update_toplevel_order (void);
59 static void clear_toplevel_order (void);
61 static FullscreenSavedGeometry *get_fullscreen_geometry (GdkWindow *window);
63 #define WINDOW_IS_TOPLEVEL(window) \
64 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
65 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
66 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
72 struct _GdkQuartzWindow
77 struct _GdkQuartzWindowClass
79 GdkWindowClass parent_class;
82 G_DEFINE_TYPE (GdkQuartzWindow, gdk_quartz_window, GDK_TYPE_WINDOW);
85 gdk_quartz_window_class_init (GdkQuartzWindowClass *quartz_window_class)
90 gdk_quartz_window_init (GdkQuartzWindow *quartz_window)
100 gdk_quartz_window_get_nsview (GdkWindow *window)
102 if (GDK_WINDOW_DESTROYED (window))
105 return ((GdkWindowImplQuartz *)window->impl)->view;
109 gdk_quartz_window_get_nswindow (GdkWindow *window)
111 if (GDK_WINDOW_DESTROYED (window))
114 return ((GdkWindowImplQuartz *)window->impl)->toplevel;
118 gdk_window_impl_quartz_get_context (GdkWindowImplQuartz *window_impl,
121 CGContextRef cg_context;
123 if (GDK_WINDOW_DESTROYED (window_impl->wrapper))
126 /* Lock focus when not called as part of a drawRect call. This
127 * is needed when called from outside "real" expose events, for
128 * example for synthesized expose events when realizing windows
129 * and for widgets that send fake expose events like the arrow
130 * buttons in spinbuttons or the position marker in rulers.
132 if (window_impl->in_paint_rect_count == 0)
134 if (![window_impl->view lockFocusIfCanDraw])
138 cg_context = [[NSGraphicsContext currentContext] graphicsPort];
139 CGContextSaveGState (cg_context);
140 CGContextSetAllowsAntialiasing (cg_context, antialias);
142 /* We'll emulate the clipping caused by double buffering here */
143 if (window_impl->begin_paint_count != 0)
149 n_rects = cairo_region_num_rectangles (window_impl->paint_clip_region);
154 cg_rects = g_new (CGRect, n_rects);
156 for (i = 0; i < n_rects; i++)
158 cairo_rectangle_int_t cairo_rect;
159 cairo_region_get_rectangle (window_impl->paint_clip_region,
161 cg_rects[i].origin.x = cairo_rect.x;
162 cg_rects[i].origin.y = cairo_rect.y;
163 cg_rects[i].size.width = cairo_rect.width;
164 cg_rects[i].size.height = cairo_rect.height;
167 CGContextClipToRects (cg_context, cg_rects, n_rects);
169 if (cg_rects != &rect)
177 gdk_window_impl_quartz_release_context (GdkWindowImplQuartz *window_impl,
178 CGContextRef cg_context)
180 CGContextRestoreGState (cg_context);
181 CGContextSetAllowsAntialiasing (cg_context, TRUE);
183 /* See comment in gdk_quartz_window_get_context(). */
184 if (window_impl->in_paint_rect_count == 0)
186 _gdk_quartz_window_flush (window_impl);
187 [window_impl->view unlockFocus];
192 check_grab_unmap (GdkWindow *window)
195 GdkDisplay *display = gdk_window_get_display (window);
196 GdkDeviceManager *device_manager;
198 device_manager = gdk_display_get_device_manager (display);
199 list = gdk_device_manager_list_devices (device_manager,
200 GDK_DEVICE_TYPE_FLOATING);
201 for (l = list; l; l = l->next)
203 _gdk_display_end_device_grab (display, l->data, 0, window, TRUE);
210 check_grab_destroy (GdkWindow *window)
213 GdkDisplay *display = gdk_window_get_display (window);
214 GdkDeviceManager *device_manager;
216 /* Make sure there is no lasting grab in this native window */
217 device_manager = gdk_display_get_device_manager (display);
218 list = gdk_device_manager_list_devices (device_manager,
219 GDK_DEVICE_TYPE_MASTER);
221 for (l = list; l; l = l->next)
223 GdkDeviceGrabInfo *grab;
225 grab = _gdk_display_get_last_device_grab (display, l->data);
226 if (grab && grab->native_window == window)
228 /* Serials are always 0 in quartz, but for clarity: */
229 grab->serial_end = grab->serial_start;
230 grab->implicit_ungrab = TRUE;
238 gdk_window_impl_quartz_finalize (GObject *object)
240 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (object);
242 check_grab_destroy (GDK_WINDOW_IMPL_QUARTZ (object)->wrapper);
244 if (impl->paint_clip_region)
245 cairo_region_destroy (impl->paint_clip_region);
247 if (impl->transient_for)
248 g_object_unref (impl->transient_for);
250 G_OBJECT_CLASS (parent_class)->finalize (object);
253 /* Help preventing "beam sync penalty" where CG makes all graphics code
254 * block until the next vsync if we try to flush (including call display on
255 * a view) too often. We do this by limiting the manual flushing done
256 * outside of expose calls to less than some frequency when measured over
257 * the last 4 flushes. This is a bit arbitray, but seems to make it possible
258 * for some quick manual flushes (such as gtkruler or gimp's marching ants)
259 * without hitting the max flush frequency.
261 * If drawable NULL, no flushing is done, only registering that a flush was
265 _gdk_quartz_window_flush (GdkWindowImplQuartz *window_impl)
267 static struct timeval prev_tv;
268 static gint intervals[4];
273 gettimeofday (&tv, NULL);
274 ms = (tv.tv_sec - prev_tv.tv_sec) * 1000 + (tv.tv_usec - prev_tv.tv_usec) / 1000;
275 intervals[index++ % 4] = ms;
279 ms = intervals[0] + intervals[1] + intervals[2] + intervals[3];
281 /* ~25Hz on average. */
285 [window_impl->toplevel flushWindow];
294 static cairo_user_data_key_t gdk_quartz_cairo_key;
297 GdkWindowImplQuartz *window_impl;
298 CGContextRef cg_context;
299 } GdkQuartzCairoSurfaceData;
302 gdk_quartz_cairo_surface_destroy (void *data)
304 GdkQuartzCairoSurfaceData *surface_data = data;
306 surface_data->window_impl->cairo_surface = NULL;
308 gdk_quartz_window_release_context (surface_data->window_impl,
309 surface_data->cg_context);
311 g_free (surface_data);
314 static cairo_surface_t *
315 gdk_quartz_create_cairo_surface (GdkWindowImplQuartz *impl,
319 CGContextRef cg_context;
320 GdkQuartzCairoSurfaceData *surface_data;
321 cairo_surface_t *surface;
323 cg_context = gdk_quartz_window_get_context (impl, TRUE);
328 surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
329 surface_data->window_impl = impl;
330 surface_data->cg_context = cg_context;
332 surface = cairo_quartz_surface_create_for_cg_context (cg_context,
335 cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
337 gdk_quartz_cairo_surface_destroy);
342 static cairo_surface_t *
343 gdk_quartz_ref_cairo_surface (GdkWindow *window)
345 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
347 if (GDK_WINDOW_DESTROYED (window))
350 if (!impl->cairo_surface)
352 impl->cairo_surface =
353 gdk_quartz_create_cairo_surface (impl,
354 gdk_window_get_width (impl->wrapper),
355 gdk_window_get_height (impl->wrapper));
358 cairo_surface_reference (impl->cairo_surface);
360 return impl->cairo_surface;
364 gdk_window_impl_quartz_init (GdkWindowImplQuartz *impl)
366 impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
370 gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable,
372 const cairo_region_t *region)
374 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
375 cairo_region_t *clipped_and_offset_region;
378 clipped_and_offset_region = cairo_region_copy (region);
380 cairo_region_intersect (clipped_and_offset_region,
381 window->clip_region_with_children);
382 cairo_region_translate (clipped_and_offset_region,
383 window->abs_x, window->abs_y);
385 if (impl->begin_paint_count == 0)
386 impl->paint_clip_region = cairo_region_reference (clipped_and_offset_region);
388 cairo_region_union (impl->paint_clip_region, clipped_and_offset_region);
390 impl->begin_paint_count++;
392 if (cairo_region_is_empty (clipped_and_offset_region))
395 cr = gdk_cairo_create (window);
397 cairo_translate (cr, -window->abs_x, -window->abs_y);
399 gdk_cairo_region (cr, clipped_and_offset_region);
402 while (window->background == NULL && window->parent)
404 cairo_translate (cr, -window->x, window->y);
405 window = window->parent;
408 if (window->background)
409 cairo_set_source (cr, window->background);
411 cairo_set_source_rgba (cr, 0, 0, 0, 0);
413 /* Can use cairo_paint() here, we clipped above */
419 cairo_region_destroy (clipped_and_offset_region);
423 gdk_window_impl_quartz_end_paint (GdkPaintable *paintable)
425 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
427 impl->begin_paint_count--;
429 if (impl->begin_paint_count == 0)
431 cairo_region_destroy (impl->paint_clip_region);
432 impl->paint_clip_region = NULL;
437 gdk_quartz_window_set_needs_display_in_region (GdkWindow *window,
438 cairo_region_t *region)
440 GdkWindowImplQuartz *impl;
443 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
445 if (!impl->needs_display_region)
446 impl->needs_display_region = cairo_region_create ();
448 cairo_region_union (impl->needs_display_region, region);
450 n_rects = cairo_region_num_rectangles (region);
451 for (i = 0; i < n_rects; i++)
453 cairo_rectangle_int_t rect;
454 cairo_region_get_rectangle (region, i, &rect);
455 [impl->view setNeedsDisplayInRect:NSMakeRect (rect.x, rect.y,
456 rect.width, rect.height)];
461 _gdk_quartz_window_process_updates_recurse (GdkWindow *window,
462 cairo_region_t *region)
464 /* Make sure to only flush each toplevel at most once if we're called
465 * from process_all_updates.
467 if (in_process_all_updates)
471 toplevel = gdk_window_get_effective_toplevel (window);
472 if (toplevel && WINDOW_IS_TOPLEVEL (toplevel))
474 GdkWindowImplQuartz *toplevel_impl;
477 toplevel_impl = (GdkWindowImplQuartz *)toplevel->impl;
478 nswindow = toplevel_impl->toplevel;
480 /* In theory, we could skip the flush disabling, since we only
483 if (nswindow && ![nswindow isFlushWindowDisabled])
486 [nswindow disableFlushWindow];
487 update_nswindows = g_slist_prepend (update_nswindows, nswindow);
492 if (WINDOW_IS_TOPLEVEL (window))
493 gdk_quartz_window_set_needs_display_in_region (window, region);
495 _gdk_window_process_updates_recurse (window, region);
497 /* NOTE: I'm not sure if we should displayIfNeeded here. It slows down a
498 * lot (since it triggers the beam syncing) and things seem to work
504 _gdk_quartz_display_before_process_all_updates (GdkDisplay *display)
506 in_process_all_updates = TRUE;
508 NSDisableScreenUpdates ();
512 _gdk_quartz_display_after_process_all_updates (GdkDisplay *display)
514 GSList *old_update_nswindows = update_nswindows;
515 GSList *tmp_list = update_nswindows;
517 update_nswindows = NULL;
521 NSWindow *nswindow = tmp_list->data;
523 [[nswindow contentView] displayIfNeeded];
525 _gdk_quartz_window_flush (NULL);
527 [nswindow enableFlushWindow];
528 [nswindow flushWindow];
531 tmp_list = tmp_list->next;
534 g_slist_free (old_update_nswindows);
536 in_process_all_updates = FALSE;
538 NSEnableScreenUpdates ();
542 gdk_window_impl_quartz_paintable_init (GdkPaintableIface *iface)
544 iface->begin_paint_region = gdk_window_impl_quartz_begin_paint_region;
545 iface->end_paint = gdk_window_impl_quartz_end_paint;
549 get_default_title (void)
553 title = g_get_application_name ();
555 title = g_get_prgname ();
561 get_ancestor_coordinates_from_child (GdkWindow *child_window,
564 GdkWindow *ancestor_window,
568 while (child_window != ancestor_window)
570 child_x += child_window->x;
571 child_y += child_window->y;
573 child_window = child_window->parent;
576 *ancestor_x = child_x;
577 *ancestor_y = child_y;
581 _gdk_quartz_window_debug_highlight (GdkWindow *window, gint number)
587 static NSWindow *debug_window[10];
588 static NSRect old_rect[10];
592 g_return_if_fail (number >= 0 && number <= 9);
594 if (window == _gdk_root)
599 if (debug_window[number])
600 [debug_window[number] close];
601 debug_window[number] = NULL;
606 toplevel = gdk_window_get_toplevel (window);
607 get_ancestor_coordinates_from_child (window, 0, 0, toplevel, &x, &y);
609 gdk_window_get_origin (toplevel, &tx, &ty);
613 _gdk_quartz_window_gdk_xy_to_xy (x, y + window->height,
616 rect = NSMakeRect (gx, gy, window->width, window->height);
618 if (debug_window[number] && NSEqualRects (rect, old_rect[number]))
621 old_rect[number] = rect;
623 if (debug_window[number])
624 [debug_window[number] close];
626 debug_window[number] = [[NSWindow alloc] initWithContentRect:rect
627 styleMask:NSBorderlessWindowMask
628 backing:NSBackingStoreBuffered
634 color = [NSColor redColor];
637 color = [NSColor blueColor];
640 color = [NSColor greenColor];
643 color = [NSColor yellowColor];
646 color = [NSColor brownColor];
649 color = [NSColor purpleColor];
652 color = [NSColor blackColor];
656 [debug_window[number] setBackgroundColor:color];
657 [debug_window[number] setAlphaValue:0.4];
658 [debug_window[number] setOpaque:NO];
659 [debug_window[number] setReleasedWhenClosed:YES];
660 [debug_window[number] setIgnoresMouseEvents:YES];
661 [debug_window[number] setLevel:NSFloatingWindowLevel];
663 [debug_window[number] orderFront:nil];
667 _gdk_quartz_window_is_ancestor (GdkWindow *ancestor,
670 if (ancestor == NULL || window == NULL)
673 return (gdk_window_get_parent (window) == ancestor ||
674 _gdk_quartz_window_is_ancestor (ancestor,
675 gdk_window_get_parent (window)));
679 /* See notes on top of gdkscreen-quartz.c */
681 _gdk_quartz_window_gdk_xy_to_xy (gint gdk_x,
686 GdkQuartzScreen *screen_quartz = GDK_QUARTZ_SCREEN (_gdk_screen);
689 *ns_y = screen_quartz->height - gdk_y + screen_quartz->min_y;
692 *ns_x = gdk_x + screen_quartz->min_x;
696 _gdk_quartz_window_xy_to_gdk_xy (gint ns_x,
701 GdkQuartzScreen *screen_quartz = GDK_QUARTZ_SCREEN (_gdk_screen);
704 *gdk_y = screen_quartz->height - ns_y + screen_quartz->min_y;
707 *gdk_x = ns_x - screen_quartz->min_x;
711 _gdk_quartz_window_nspoint_to_gdk_xy (NSPoint point,
715 _gdk_quartz_window_xy_to_gdk_xy (point.x, point.y,
720 find_child_window_helper (GdkWindow *window,
725 gboolean get_toplevel)
727 GdkWindowImplQuartz *impl;
730 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
732 if (window == _gdk_root)
733 update_toplevel_order ();
735 for (l = impl->sorted_children; l; l = l->next)
737 GdkWindow *child = l->data;
738 GdkWindowImplQuartz *child_impl = GDK_WINDOW_IMPL_QUARTZ (child->impl);
741 if (!GDK_WINDOW_IS_MAPPED (child))
744 temp_x = x_offset + child->x;
745 temp_y = y_offset + child->y;
747 /* Special-case the root window. We have to include the title
748 * bar in the checks, otherwise the window below the title bar
749 * will be found i.e. events punch through. (If we can find a
750 * better way to deal with the events in gdkevents-quartz, this
751 * might not be needed.)
753 if (window == _gdk_root)
755 NSRect frame = NSMakeRect (0, 0, 100, 100);
760 mask = [child_impl->toplevel styleMask];
762 /* Get the title bar height. */
763 content = [NSWindow contentRectForFrameRect:frame
765 titlebar_height = frame.size.height - content.size.height;
767 if (titlebar_height > 0 &&
768 x >= temp_x && y >= temp_y - titlebar_height &&
769 x < temp_x + child->width && y < temp_y)
771 /* The root means "unknown" i.e. a window not managed by
774 return (GdkWindow *)_gdk_root;
778 if ((!get_toplevel || (get_toplevel && window == _gdk_root)) &&
779 x >= temp_x && y >= temp_y &&
780 x < temp_x + child->width && y < temp_y + child->height)
782 /* Look for child windows. */
783 return find_child_window_helper (l->data,
793 /* Given a GdkWindow and coordinates relative to it, returns the
794 * innermost subwindow that contains the point. If the coordinates are
795 * outside the passed in window, NULL is returned.
798 _gdk_quartz_window_find_child (GdkWindow *window,
801 gboolean get_toplevel)
803 if (x >= 0 && y >= 0 && x < window->width && y < window->height)
804 return find_child_window_helper (window, x, y, 0, 0, get_toplevel);
811 _gdk_quartz_window_did_become_main (GdkWindow *window)
813 main_window_stack = g_slist_remove (main_window_stack, window);
815 if (window->window_type != GDK_WINDOW_TEMP)
816 main_window_stack = g_slist_prepend (main_window_stack, window);
818 clear_toplevel_order ();
822 _gdk_quartz_window_did_resign_main (GdkWindow *window)
824 GdkWindow *new_window = NULL;
826 if (main_window_stack)
827 new_window = main_window_stack->data;
832 toplevels = gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
834 new_window = toplevels->data;
835 g_list_free (toplevels);
839 new_window != window &&
840 GDK_WINDOW_IS_MAPPED (new_window) &&
841 WINDOW_IS_TOPLEVEL (new_window))
843 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (new_window->impl);
845 [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
848 clear_toplevel_order ();
852 get_nsscreen_for_point (gint x, gint y)
856 NSScreen *screen = NULL;
858 GDK_QUARTZ_ALLOC_POOL;
860 screens = [NSScreen screens];
862 for (i = 0; i < [screens count]; i++)
864 NSRect rect = [[screens objectAtIndex:i] frame];
866 if (x >= rect.origin.x && x <= rect.origin.x + rect.size.width &&
867 y >= rect.origin.y && y <= rect.origin.y + rect.size.height)
869 screen = [screens objectAtIndex:i];
874 GDK_QUARTZ_RELEASE_POOL;
880 _gdk_quartz_display_create_window_impl (GdkDisplay *display,
882 GdkWindow *real_parent,
884 GdkEventMask event_mask,
885 GdkWindowAttr *attributes,
886 gint attributes_mask)
888 GdkWindowImplQuartz *impl;
889 GdkWindowImplQuartz *parent_impl;
891 GDK_QUARTZ_ALLOC_POOL;
893 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_QUARTZ, NULL);
894 window->impl = GDK_WINDOW_IMPL (impl);
895 impl->wrapper = window;
897 parent_impl = GDK_WINDOW_IMPL_QUARTZ (window->parent->impl);
899 switch (window->window_type)
901 case GDK_WINDOW_TOPLEVEL:
902 case GDK_WINDOW_TEMP:
903 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
905 /* The common code warns for this case */
906 parent_impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
910 /* Maintain the z-ordered list of children. */
911 if (window->parent != _gdk_root)
912 parent_impl->sorted_children = g_list_prepend (parent_impl->sorted_children, window);
914 clear_toplevel_order ();
916 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
917 (attributes->cursor) :
922 switch (attributes->window_type)
924 case GDK_WINDOW_TOPLEVEL:
925 case GDK_WINDOW_TEMP:
930 NSUInteger style_mask;
934 /* initWithContentRect will place on the mainScreen by default.
935 * We want to select the screen to place on ourselves. We need
936 * to find the screen the window will be on and correct the
937 * content_rect coordinates to be relative to that screen.
939 _gdk_quartz_window_gdk_xy_to_xy (window->x, window->y, &nx, &ny);
941 screen = get_nsscreen_for_point (nx, ny);
942 screen_rect = [screen frame];
943 nx -= screen_rect.origin.x;
944 ny -= screen_rect.origin.y;
946 content_rect = NSMakeRect (nx, ny - window->height,
950 if (attributes->window_type == GDK_WINDOW_TEMP ||
951 attributes->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
953 style_mask = NSBorderlessWindowMask;
957 style_mask = (NSTitledWindowMask |
958 NSClosableWindowMask |
959 NSMiniaturizableWindowMask |
960 NSResizableWindowMask);
963 impl->toplevel = [[GdkQuartzNSWindow alloc] initWithContentRect:content_rect
965 backing:NSBackingStoreBuffered
969 if (attributes_mask & GDK_WA_TITLE)
970 title = attributes->title;
972 title = get_default_title ();
974 gdk_window_set_title (window, title);
976 if (gdk_window_get_visual (window) == gdk_screen_get_rgba_visual (_gdk_screen))
978 [impl->toplevel setOpaque:NO];
979 [impl->toplevel setBackgroundColor:[NSColor clearColor]];
982 content_rect.origin.x = 0;
983 content_rect.origin.y = 0;
985 impl->view = [[GdkQuartzView alloc] initWithFrame:content_rect];
986 [impl->view setGdkWindow:window];
987 [impl->toplevel setContentView:impl->view];
988 [impl->view release];
992 case GDK_WINDOW_CHILD:
994 GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (window->parent->impl);
996 if (!window->input_only)
998 NSRect frame_rect = NSMakeRect (window->x + window->parent->abs_x,
999 window->y + window->parent->abs_y,
1003 impl->view = [[GdkQuartzView alloc] initWithFrame:frame_rect];
1005 [impl->view setGdkWindow:window];
1007 /* GdkWindows should be hidden by default */
1008 [impl->view setHidden:YES];
1009 [parent_impl->view addSubview:impl->view];
1010 [impl->view release];
1016 g_assert_not_reached ();
1019 GDK_QUARTZ_RELEASE_POOL;
1021 if (attributes_mask & GDK_WA_TYPE_HINT)
1022 gdk_window_set_type_hint (window, attributes->type_hint);
1026 _gdk_quartz_window_update_position (GdkWindow *window)
1029 NSRect content_rect;
1030 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1032 GDK_QUARTZ_ALLOC_POOL;
1034 frame_rect = [impl->toplevel frame];
1035 content_rect = [impl->toplevel contentRectForFrameRect:frame_rect];
1037 _gdk_quartz_window_xy_to_gdk_xy (content_rect.origin.x,
1038 content_rect.origin.y + content_rect.size.height,
1039 &window->x, &window->y);
1042 GDK_QUARTZ_RELEASE_POOL;
1046 _gdk_quartz_window_init_windowing (GdkDisplay *display,
1049 GdkWindowImplQuartz *impl;
1051 g_assert (_gdk_root == NULL);
1053 _gdk_root = _gdk_display_create_window (display);
1055 _gdk_root->impl = g_object_new (_gdk_root_window_impl_quartz_get_type (), NULL);
1056 _gdk_root->impl_window = _gdk_root;
1057 _gdk_root->visual = gdk_screen_get_system_visual (screen);
1059 impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
1061 _gdk_quartz_screen_update_window_sizes (screen);
1063 _gdk_root->state = 0; /* We don't want GDK_WINDOW_STATE_WITHDRAWN here */
1064 _gdk_root->window_type = GDK_WINDOW_ROOT;
1065 _gdk_root->depth = 24;
1066 _gdk_root->viewable = TRUE;
1068 impl->wrapper = _gdk_root;
1072 gdk_quartz_window_destroy (GdkWindow *window,
1074 gboolean foreign_destroy)
1076 GdkWindowImplQuartz *impl;
1079 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1081 main_window_stack = g_slist_remove (main_window_stack, window);
1083 g_list_free (impl->sorted_children);
1084 impl->sorted_children = NULL;
1086 parent = window->parent;
1089 GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (parent->impl);
1091 parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window);
1094 if (impl->cairo_surface)
1096 cairo_surface_finish (impl->cairo_surface);
1097 cairo_surface_set_user_data (impl->cairo_surface, &gdk_quartz_cairo_key,
1099 impl->cairo_surface = NULL;
1102 if (!recursing && !foreign_destroy)
1104 GDK_QUARTZ_ALLOC_POOL;
1107 [impl->toplevel close];
1108 else if (impl->view)
1109 [impl->view removeFromSuperview];
1111 GDK_QUARTZ_RELEASE_POOL;
1115 static cairo_surface_t *
1116 gdk_window_quartz_resize_cairo_surface (GdkWindow *window,
1117 cairo_surface_t *surface,
1121 /* Quartz surfaces cannot be resized */
1122 cairo_surface_destroy (surface);
1128 gdk_quartz_window_destroy_foreign (GdkWindow *window)
1130 /* Foreign windows aren't supported in OSX. */
1133 /* FIXME: This might be possible to simplify with client-side windows. Also
1134 * note that already_mapped is not used yet, see the x11 backend.
1137 gdk_window_quartz_show (GdkWindow *window, gboolean already_mapped)
1139 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1140 gboolean focus_on_map;
1142 GDK_QUARTZ_ALLOC_POOL;
1144 if (!GDK_WINDOW_IS_MAPPED (window))
1145 focus_on_map = window->focus_on_map;
1147 focus_on_map = TRUE;
1149 if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel)
1153 make_key = (window->accept_focus && focus_on_map &&
1154 window->window_type != GDK_WINDOW_TEMP);
1156 [(GdkQuartzNSWindow*)impl->toplevel showAndMakeKey:make_key];
1157 clear_toplevel_order ();
1159 _gdk_quartz_events_send_map_event (window);
1163 [impl->view setHidden:NO];
1166 [impl->view setNeedsDisplay:YES];
1168 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_WITHDRAWN, 0);
1170 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1171 gdk_window_maximize (window);
1173 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1174 gdk_window_iconify (window);
1176 if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1177 _gdk_quartz_window_attach_to_parent (window);
1179 GDK_QUARTZ_RELEASE_POOL;
1182 /* Temporarily unsets the parent window, if the window is a
1186 _gdk_quartz_window_detach_from_parent (GdkWindow *window)
1188 GdkWindowImplQuartz *impl;
1190 g_return_if_fail (GDK_IS_WINDOW (window));
1192 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1194 g_return_if_fail (impl->toplevel != NULL);
1196 if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1198 GdkWindowImplQuartz *parent_impl;
1200 parent_impl = GDK_WINDOW_IMPL_QUARTZ (impl->transient_for->impl);
1201 [parent_impl->toplevel removeChildWindow:impl->toplevel];
1202 clear_toplevel_order ();
1206 /* Re-sets the parent window, if the window is a transient. */
1208 _gdk_quartz_window_attach_to_parent (GdkWindow *window)
1210 GdkWindowImplQuartz *impl;
1212 g_return_if_fail (GDK_IS_WINDOW (window));
1214 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1216 g_return_if_fail (impl->toplevel != NULL);
1218 if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1220 GdkWindowImplQuartz *parent_impl;
1222 parent_impl = GDK_WINDOW_IMPL_QUARTZ (impl->transient_for->impl);
1223 [parent_impl->toplevel addChildWindow:impl->toplevel ordered:NSWindowAbove];
1224 clear_toplevel_order ();
1229 gdk_window_quartz_hide (GdkWindow *window)
1231 GdkWindowImplQuartz *impl;
1233 /* Make sure we're not stuck in fullscreen mode. */
1234 if (get_fullscreen_geometry (window))
1235 SetSystemUIMode (kUIModeNormal, 0);
1237 check_grab_unmap (window);
1239 _gdk_window_clear_update_area (window);
1241 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1243 if (WINDOW_IS_TOPLEVEL (window))
1245 /* Update main window. */
1246 main_window_stack = g_slist_remove (main_window_stack, window);
1247 if ([NSApp mainWindow] == impl->toplevel)
1248 _gdk_quartz_window_did_resign_main (window);
1250 if (impl->transient_for)
1251 _gdk_quartz_window_detach_from_parent (window);
1253 [(GdkQuartzNSWindow*)impl->toplevel hide];
1255 else if (impl->view)
1257 [impl->view setHidden:YES];
1262 gdk_window_quartz_withdraw (GdkWindow *window)
1264 gdk_window_hide (window);
1268 move_resize_window_internal (GdkWindow *window,
1274 GdkWindowImplQuartz *impl;
1275 GdkRectangle old_visible;
1276 GdkRectangle new_visible;
1277 GdkRectangle scroll_rect;
1278 cairo_region_t *old_region;
1279 cairo_region_t *expose_region;
1282 if (GDK_WINDOW_DESTROYED (window))
1285 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1287 if ((x == -1 || (x == window->x)) &&
1288 (y == -1 || (y == window->y)) &&
1289 (width == -1 || (width == window->width)) &&
1290 (height == -1 || (height == window->height)))
1295 if (!impl->toplevel)
1297 /* The previously visible area of this window in a coordinate
1298 * system rooted at the origin of this window.
1300 old_visible.x = -window->x;
1301 old_visible.y = -window->y;
1303 old_visible.width = window->width;
1304 old_visible.height = window->height;
1309 delta.width = x - window->x;
1319 delta.height = y - window->y;
1328 window->width = width;
1331 window->height = height;
1333 GDK_QUARTZ_ALLOC_POOL;
1337 NSRect content_rect;
1341 _gdk_quartz_window_gdk_xy_to_xy (window->x, window->y + window->height,
1344 content_rect = NSMakeRect (gx, gy, window->width, window->height);
1346 frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
1347 [impl->toplevel setFrame:frame_rect display:YES];
1351 if (!window->input_only)
1355 nsrect = NSMakeRect (window->x, window->y, window->width, window->height);
1357 /* The newly visible area of this window in a coordinate
1358 * system rooted at the origin of this window.
1360 new_visible.x = -window->x;
1361 new_visible.y = -window->y;
1362 new_visible.width = old_visible.width; /* parent has not changed size */
1363 new_visible.height = old_visible.height; /* parent has not changed size */
1365 expose_region = cairo_region_create_rectangle (&new_visible);
1366 old_region = cairo_region_create_rectangle (&old_visible);
1367 cairo_region_subtract (expose_region, old_region);
1369 /* Determine what (if any) part of the previously visible
1370 * part of the window can be copied without a redraw
1372 scroll_rect = old_visible;
1373 scroll_rect.x -= delta.width;
1374 scroll_rect.y -= delta.height;
1375 gdk_rectangle_intersect (&scroll_rect, &old_visible, &scroll_rect);
1377 if (!cairo_region_is_empty (expose_region))
1379 if (scroll_rect.width != 0 && scroll_rect.height != 0)
1381 [impl->view scrollRect:NSMakeRect (scroll_rect.x,
1388 [impl->view setFrame:nsrect];
1390 gdk_quartz_window_set_needs_display_in_region (window, expose_region);
1394 [impl->view setFrame:nsrect];
1395 [impl->view setNeedsDisplay:YES];
1398 cairo_region_destroy (expose_region);
1399 cairo_region_destroy (old_region);
1403 GDK_QUARTZ_RELEASE_POOL;
1407 window_quartz_move (GdkWindow *window,
1411 g_return_if_fail (GDK_IS_WINDOW (window));
1413 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1416 move_resize_window_internal (window, x, y, -1, -1);
1420 window_quartz_resize (GdkWindow *window,
1424 g_return_if_fail (GDK_IS_WINDOW (window));
1426 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1434 move_resize_window_internal (window, -1, -1, width, height);
1438 window_quartz_move_resize (GdkWindow *window,
1449 move_resize_window_internal (window, x, y, width, height);
1453 gdk_window_quartz_move_resize (GdkWindow *window,
1460 if (with_move && (width < 0 && height < 0))
1461 window_quartz_move (window, x, y);
1465 window_quartz_move_resize (window, x, y, width, height);
1467 window_quartz_resize (window, width, height);
1471 /* FIXME: This might need fixing (reparenting didn't work before client-side
1475 gdk_window_quartz_reparent (GdkWindow *window,
1476 GdkWindow *new_parent,
1480 GdkWindow *old_parent;
1481 GdkWindowImplQuartz *impl, *old_parent_impl, *new_parent_impl;
1482 NSView *view, *new_parent_view;
1484 if (new_parent == _gdk_root)
1486 /* Could be added, just needs implementing. */
1487 g_warning ("Reparenting to root window is not supported yet in the Mac OS X backend");
1491 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1494 new_parent_impl = GDK_WINDOW_IMPL_QUARTZ (new_parent->impl);
1495 new_parent_view = new_parent_impl->view;
1497 old_parent = window->parent;
1498 old_parent_impl = GDK_WINDOW_IMPL_QUARTZ (old_parent->impl);
1502 [view removeFromSuperview];
1503 [new_parent_view addSubview:view];
1507 window->parent = new_parent;
1511 old_parent_impl->sorted_children = g_list_remove (old_parent_impl->sorted_children, window);
1514 new_parent_impl->sorted_children = g_list_prepend (new_parent_impl->sorted_children, window);
1519 /* Get the toplevel ordering from NSApp and update our own list. We do
1520 * this on demand since the NSApp's list is not up to date directly
1521 * after we get windowDidBecomeMain.
1524 update_toplevel_order (void)
1526 GdkWindowImplQuartz *root_impl;
1527 NSEnumerator *enumerator;
1529 GList *toplevels = NULL;
1531 root_impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
1533 if (root_impl->sorted_children)
1536 GDK_QUARTZ_ALLOC_POOL;
1538 enumerator = [[NSApp orderedWindows] objectEnumerator];
1539 while ((nswindow = [enumerator nextObject]))
1543 if (![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
1546 window = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
1547 toplevels = g_list_prepend (toplevels, window);
1550 GDK_QUARTZ_RELEASE_POOL;
1552 root_impl->sorted_children = g_list_reverse (toplevels);
1556 clear_toplevel_order (void)
1558 GdkWindowImplQuartz *root_impl;
1560 root_impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
1562 g_list_free (root_impl->sorted_children);
1563 root_impl->sorted_children = NULL;
1567 gdk_window_quartz_raise (GdkWindow *window)
1569 if (GDK_WINDOW_DESTROYED (window))
1572 if (WINDOW_IS_TOPLEVEL (window))
1574 GdkWindowImplQuartz *impl;
1576 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1577 [impl->toplevel orderFront:impl->toplevel];
1579 clear_toplevel_order ();
1583 GdkWindow *parent = window->parent;
1587 GdkWindowImplQuartz *impl;
1589 impl = (GdkWindowImplQuartz *)parent->impl;
1591 impl->sorted_children = g_list_remove (impl->sorted_children, window);
1592 impl->sorted_children = g_list_prepend (impl->sorted_children, window);
1598 gdk_window_quartz_lower (GdkWindow *window)
1600 if (GDK_WINDOW_DESTROYED (window))
1603 if (WINDOW_IS_TOPLEVEL (window))
1605 GdkWindowImplQuartz *impl;
1607 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1608 [impl->toplevel orderBack:impl->toplevel];
1610 clear_toplevel_order ();
1614 GdkWindow *parent = window->parent;
1618 GdkWindowImplQuartz *impl;
1620 impl = (GdkWindowImplQuartz *)parent->impl;
1622 impl->sorted_children = g_list_remove (impl->sorted_children, window);
1623 impl->sorted_children = g_list_append (impl->sorted_children, window);
1629 gdk_window_quartz_restack_toplevel (GdkWindow *window,
1633 /* FIXME: Implement this */
1637 gdk_window_quartz_set_background (GdkWindow *window,
1638 cairo_pattern_t *pattern)
1640 /* FIXME: We could theoretically set the background color for toplevels
1641 * here. (Currently we draw the background before emitting expose events)
1646 gdk_window_quartz_set_device_cursor (GdkWindow *window,
1652 if (GDK_WINDOW_DESTROYED (window))
1655 nscursor = _gdk_quartz_cursor_get_ns_cursor (cursor);
1661 gdk_window_quartz_get_geometry (GdkWindow *window,
1667 GdkWindowImplQuartz *impl;
1670 if (GDK_WINDOW_DESTROYED (window))
1673 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1674 if (window == _gdk_root)
1682 *width = window->width;
1684 *height = window->height;
1686 else if (WINDOW_IS_TOPLEVEL (window))
1688 ns_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
1690 /* This doesn't work exactly as in X. There doesn't seem to be a
1691 * way to get the coords relative to the parent window (usually
1692 * the window frame), but that seems useless except for
1693 * borderless windows where it's relative to the root window. So
1694 * we return (0, 0) (should be something like (0, 22)) for
1695 * windows with borders and the root relative coordinates
1698 if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
1700 _gdk_quartz_window_xy_to_gdk_xy (ns_rect.origin.x,
1701 ns_rect.origin.y + ns_rect.size.height,
1713 *width = ns_rect.size.width;
1715 *height = ns_rect.size.height;
1719 ns_rect = [impl->view frame];
1722 *x = ns_rect.origin.x;
1724 *y = ns_rect.origin.y;
1726 *width = ns_rect.size.width;
1728 *height = ns_rect.size.height;
1733 gdk_window_quartz_get_root_coords (GdkWindow *window,
1739 int tmp_x = 0, tmp_y = 0;
1740 GdkWindow *toplevel;
1741 NSRect content_rect;
1742 GdkWindowImplQuartz *impl;
1744 if (GDK_WINDOW_DESTROYED (window))
1754 if (window == _gdk_root)
1764 toplevel = gdk_window_get_toplevel (window);
1765 impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
1767 content_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
1769 _gdk_quartz_window_xy_to_gdk_xy (content_rect.origin.x,
1770 content_rect.origin.y + content_rect.size.height,
1776 while (window != toplevel)
1778 if (_gdk_window_has_impl ((GdkWindow *)window))
1784 window = window->parent;
1796 gdk_quartz_window_get_root_origin (GdkWindow *window,
1805 gdk_window_get_frame_extents (window, &rect);
1814 /* Returns coordinates relative to the passed in window. */
1816 gdk_window_quartz_get_device_state_helper (GdkWindow *window,
1820 GdkModifierType *mask)
1824 GdkWindow *toplevel;
1825 GdkWindow *found_window;
1827 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1829 if (GDK_WINDOW_DESTROYED (window))
1837 toplevel = gdk_window_get_toplevel (window);
1839 *mask = _gdk_quartz_events_get_current_event_mask ();
1841 /* Get the y coordinate, needs to be flipped. */
1842 if (window == _gdk_root)
1844 point = [NSEvent mouseLocation];
1845 _gdk_quartz_window_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
1849 GdkWindowImplQuartz *impl;
1852 impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
1853 nswindow = impl->toplevel;
1855 point = [nswindow mouseLocationOutsideOfEventStream];
1858 y_tmp = toplevel->height - point.y;
1860 window = (GdkWindow *)toplevel;
1863 found_window = _gdk_quartz_window_find_child (window, x_tmp, y_tmp,
1866 /* We never return the root window. */
1867 if (found_window == _gdk_root)
1868 found_window = NULL;
1873 return found_window;
1877 gdk_window_quartz_get_device_state (GdkWindow *window,
1881 GdkModifierType *mask)
1883 return gdk_window_quartz_get_device_state_helper (window,
1885 x, y, mask) != NULL;
1888 /* Returns coordinates relative to the root. */
1890 _gdk_windowing_get_device_state (GdkDisplay *display,
1895 GdkModifierType *mask)
1897 g_return_if_fail (display == _gdk_display);
1899 *screen = _gdk_screen;
1900 gdk_window_quartz_get_device_state_helper (_gdk_root, device, x, y, mask);
1903 /* Returns coordinates relative to the found window. */
1905 _gdk_windowing_window_at_pointer (GdkDisplay *display,
1908 GdkModifierType *mask,
1909 gboolean get_toplevel)
1911 GdkWindow *found_window;
1913 GdkModifierType tmp_mask = 0;
1915 found_window = gdk_window_quartz_get_device_state_helper (_gdk_root,
1916 display->core_pointer,
1921 /* The coordinates returned above are relative the root, we want
1922 * coordinates relative the window here.
1924 while (found_window != _gdk_root)
1926 x -= found_window->x;
1927 y -= found_window->y;
1929 found_window = found_window->parent;
1937 /* Mimic the X backend here, -1,-1 for unknown windows. */
1947 /* Requested toplevel, find it. */
1948 /* TODO: This can be implemented more efficient by never
1949 recursing into children in the first place */
1952 /* Convert to toplevel */
1953 while (found_window->parent != NULL &&
1954 found_window->parent->window_type != GDK_WINDOW_ROOT)
1956 *win_x += found_window->x;
1957 *win_y += found_window->y;
1958 found_window = found_window->parent;
1963 return found_window;
1967 _gdk_windowing_window_at_device_position (GdkDisplay *display,
1971 GdkModifierType *mask,
1972 gboolean get_toplevel)
1974 return GDK_DEVICE_GET_CLASS (device)->window_at_position (device,
1982 gdk_window_quartz_get_events (GdkWindow *window)
1984 if (GDK_WINDOW_DESTROYED (window))
1987 return window->event_mask;
1991 gdk_window_quartz_set_events (GdkWindow *window,
1992 GdkEventMask event_mask)
1994 /* The mask is set in the common code. */
1998 gdk_quartz_window_set_urgency_hint (GdkWindow *window,
2001 if (GDK_WINDOW_DESTROYED (window) ||
2002 !WINDOW_IS_TOPLEVEL (window))
2005 /* FIXME: Implement */
2009 gdk_quartz_window_set_geometry_hints (GdkWindow *window,
2010 const GdkGeometry *geometry,
2011 GdkWindowHints geom_mask)
2013 GdkWindowImplQuartz *impl;
2015 g_return_if_fail (geometry != NULL);
2017 if (GDK_WINDOW_DESTROYED (window) ||
2018 !WINDOW_IS_TOPLEVEL (window))
2021 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2022 if (!impl->toplevel)
2025 if (geom_mask & GDK_HINT_POS)
2027 /* FIXME: Implement */
2030 if (geom_mask & GDK_HINT_USER_POS)
2032 /* FIXME: Implement */
2035 if (geom_mask & GDK_HINT_USER_SIZE)
2037 /* FIXME: Implement */
2040 if (geom_mask & GDK_HINT_MIN_SIZE)
2044 size.width = geometry->min_width;
2045 size.height = geometry->min_height;
2047 [impl->toplevel setContentMinSize:size];
2050 if (geom_mask & GDK_HINT_MAX_SIZE)
2054 size.width = geometry->max_width;
2055 size.height = geometry->max_height;
2057 [impl->toplevel setContentMaxSize:size];
2060 if (geom_mask & GDK_HINT_BASE_SIZE)
2062 /* FIXME: Implement */
2065 if (geom_mask & GDK_HINT_RESIZE_INC)
2069 size.width = geometry->width_inc;
2070 size.height = geometry->height_inc;
2072 [impl->toplevel setContentResizeIncrements:size];
2075 if (geom_mask & GDK_HINT_ASPECT)
2077 /* FIXME: Implement */
2080 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2082 /* FIXME: Implement */
2087 gdk_quartz_window_set_title (GdkWindow *window,
2090 GdkWindowImplQuartz *impl;
2092 g_return_if_fail (title != NULL);
2094 if (GDK_WINDOW_DESTROYED (window) ||
2095 !WINDOW_IS_TOPLEVEL (window))
2098 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2102 GDK_QUARTZ_ALLOC_POOL;
2103 [impl->toplevel setTitle:[NSString stringWithUTF8String:title]];
2104 GDK_QUARTZ_RELEASE_POOL;
2109 gdk_quartz_window_set_role (GdkWindow *window,
2112 if (GDK_WINDOW_DESTROYED (window) ||
2113 WINDOW_IS_TOPLEVEL (window))
2116 /* FIXME: Implement */
2120 gdk_quartz_window_set_startup_id (GdkWindow *window,
2121 const gchar *startup_id)
2123 /* FIXME: Implement? */
2127 gdk_quartz_window_set_transient_for (GdkWindow *window,
2130 GdkWindowImplQuartz *window_impl;
2131 GdkWindowImplQuartz *parent_impl;
2133 if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (parent) ||
2134 !WINDOW_IS_TOPLEVEL (window))
2137 window_impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2138 if (!window_impl->toplevel)
2141 GDK_QUARTZ_ALLOC_POOL;
2143 if (window_impl->transient_for)
2145 _gdk_quartz_window_detach_from_parent (window);
2147 g_object_unref (window_impl->transient_for);
2148 window_impl->transient_for = NULL;
2151 parent_impl = GDK_WINDOW_IMPL_QUARTZ (parent->impl);
2152 if (parent_impl->toplevel)
2154 /* We save the parent because it needs to be unset/reset when
2155 * hiding and showing the window.
2158 /* We don't set transients for tooltips, they are already
2159 * handled by the window level being the top one. If we do, then
2160 * the parent window will be brought to the top just because the
2161 * tooltip is, which is not what we want.
2163 if (gdk_window_get_type_hint (window) != GDK_WINDOW_TYPE_HINT_TOOLTIP)
2165 window_impl->transient_for = g_object_ref (parent);
2167 /* We only add the window if it is shown, otherwise it will
2168 * be shown unconditionally here. If it is not shown, the
2169 * window will be added in show() instead.
2171 if (!(window->state & GDK_WINDOW_STATE_WITHDRAWN))
2172 _gdk_quartz_window_attach_to_parent (window);
2176 GDK_QUARTZ_RELEASE_POOL;
2180 gdk_window_quartz_shape_combine_region (GdkWindow *window,
2181 const cairo_region_t *shape,
2185 /* FIXME: Implement */
2189 gdk_window_quartz_input_shape_combine_region (GdkWindow *window,
2190 const cairo_region_t *shape_region,
2194 /* FIXME: Implement */
2198 gdk_quartz_window_set_override_redirect (GdkWindow *window,
2199 gboolean override_redirect)
2201 /* FIXME: Implement */
2205 gdk_quartz_window_set_accept_focus (GdkWindow *window,
2206 gboolean accept_focus)
2208 window->accept_focus = accept_focus != FALSE;
2212 gdk_window_quartz_set_static_gravities (GdkWindow *window,
2213 gboolean use_static)
2215 if (GDK_WINDOW_DESTROYED (window) ||
2216 !WINDOW_IS_TOPLEVEL (window))
2219 /* FIXME: Implement */
2224 gdk_quartz_window_queue_antiexpose (GdkWindow *window,
2225 cairo_region_t *area)
2231 gdk_quartz_window_translate (GdkWindow *window,
2232 cairo_region_t *area,
2236 cairo_region_t *invalidate, *scrolled;
2237 GdkWindowImplQuartz *impl = (GdkWindowImplQuartz *)window->impl;
2238 GdkRectangle extents;
2240 cairo_region_get_extents (area, &extents);
2242 [impl->view scrollRect:NSMakeRect (extents.x - dx, extents.y - dy,
2243 extents.width, extents.height)
2244 by:NSMakeSize (dx, dy)];
2246 if (impl->needs_display_region)
2248 cairo_region_t *intersection;
2250 /* Invalidate already invalidated area that was moved at new
2253 intersection = cairo_region_copy (impl->needs_display_region);
2254 cairo_region_intersect (intersection, area);
2255 cairo_region_translate (intersection, dx, dy);
2257 gdk_quartz_window_set_needs_display_in_region (window, intersection);
2258 cairo_region_destroy (intersection);
2261 /* Calculate newly exposed area that needs invalidation */
2262 scrolled = cairo_region_copy (area);
2263 cairo_region_translate (scrolled, dx, dy);
2265 invalidate = cairo_region_copy (area);
2266 cairo_region_subtract (invalidate, scrolled);
2267 cairo_region_destroy (scrolled);
2269 gdk_quartz_window_set_needs_display_in_region (window, invalidate);
2270 cairo_region_destroy (invalidate);
2274 gdk_quartz_window_set_focus_on_map (GdkWindow *window,
2275 gboolean focus_on_map)
2277 window->focus_on_map = focus_on_map != FALSE;
2281 gdk_quartz_window_set_icon_name (GdkWindow *window,
2284 /* FIXME: Implement */
2288 gdk_quartz_window_focus (GdkWindow *window,
2291 GdkWindowImplQuartz *impl;
2293 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2295 if (GDK_WINDOW_DESTROYED (window) ||
2296 !WINDOW_IS_TOPLEVEL (window))
2299 if (window->accept_focus && window->window_type != GDK_WINDOW_TEMP)
2301 GDK_QUARTZ_ALLOC_POOL;
2302 [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
2303 clear_toplevel_order ();
2304 GDK_QUARTZ_RELEASE_POOL;
2309 gint window_type_hint_to_level (GdkWindowTypeHint hint)
2313 case GDK_WINDOW_TYPE_HINT_DOCK:
2314 case GDK_WINDOW_TYPE_HINT_UTILITY:
2315 return NSFloatingWindowLevel;
2317 case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
2318 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
2319 return NSTornOffMenuWindowLevel;
2321 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2322 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2323 return NSStatusWindowLevel;
2325 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2326 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2327 case GDK_WINDOW_TYPE_HINT_COMBO:
2328 case GDK_WINDOW_TYPE_HINT_DND:
2329 return NSPopUpMenuWindowLevel;
2331 case GDK_WINDOW_TYPE_HINT_NORMAL: /* Normal toplevel window */
2332 case GDK_WINDOW_TYPE_HINT_DIALOG: /* Dialog window */
2333 case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
2334 case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
2341 return NSNormalWindowLevel;
2345 window_type_hint_to_shadow (GdkWindowTypeHint hint)
2349 case GDK_WINDOW_TYPE_HINT_NORMAL: /* Normal toplevel window */
2350 case GDK_WINDOW_TYPE_HINT_DIALOG: /* Dialog window */
2351 case GDK_WINDOW_TYPE_HINT_DOCK:
2352 case GDK_WINDOW_TYPE_HINT_UTILITY:
2353 case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
2354 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
2355 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2356 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2357 case GDK_WINDOW_TYPE_HINT_COMBO:
2358 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2359 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2362 case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
2363 case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
2364 case GDK_WINDOW_TYPE_HINT_DND:
2376 gdk_quartz_window_set_type_hint (GdkWindow *window,
2377 GdkWindowTypeHint hint)
2379 GdkWindowImplQuartz *impl;
2381 if (GDK_WINDOW_DESTROYED (window) ||
2382 !WINDOW_IS_TOPLEVEL (window))
2385 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2387 impl->type_hint = hint;
2389 /* Match the documentation, only do something if we're not mapped yet. */
2390 if (GDK_WINDOW_IS_MAPPED (window))
2393 [impl->toplevel setHasShadow: window_type_hint_to_shadow (hint)];
2394 [impl->toplevel setLevel: window_type_hint_to_level (hint)];
2397 static GdkWindowTypeHint
2398 gdk_quartz_window_get_type_hint (GdkWindow *window)
2400 if (GDK_WINDOW_DESTROYED (window) ||
2401 !WINDOW_IS_TOPLEVEL (window))
2402 return GDK_WINDOW_TYPE_HINT_NORMAL;
2404 return GDK_WINDOW_IMPL_QUARTZ (window->impl)->type_hint;
2408 gdk_quartz_window_set_modal_hint (GdkWindow *window,
2411 if (GDK_WINDOW_DESTROYED (window) ||
2412 !WINDOW_IS_TOPLEVEL (window))
2415 /* FIXME: Implement */
2419 gdk_quartz_window_set_skip_taskbar_hint (GdkWindow *window,
2420 gboolean skips_taskbar)
2422 if (GDK_WINDOW_DESTROYED (window) ||
2423 !WINDOW_IS_TOPLEVEL (window))
2426 /* FIXME: Implement */
2430 gdk_quartz_window_set_skip_pager_hint (GdkWindow *window,
2431 gboolean skips_pager)
2433 if (GDK_WINDOW_DESTROYED (window) ||
2434 !WINDOW_IS_TOPLEVEL (window))
2437 /* FIXME: Implement */
2441 gdk_quartz_window_begin_resize_drag (GdkWindow *window,
2448 GdkWindowImplQuartz *impl;
2450 g_return_if_fail (GDK_IS_WINDOW (window));
2452 if (edge != GDK_WINDOW_EDGE_SOUTH_EAST)
2454 g_warning ("Resizing is only implemented for GDK_WINDOW_EDGE_SOUTH_EAST on Mac OS");
2458 if (GDK_WINDOW_DESTROYED (window))
2461 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2463 if (!impl->toplevel)
2465 g_warning ("Can't call gdk_window_begin_resize_drag on non-toplevel window");
2469 [(GdkQuartzNSWindow *)impl->toplevel beginManualResize];
2473 gdk_quartz_window_begin_move_drag (GdkWindow *window,
2479 GdkWindowImplQuartz *impl;
2481 if (GDK_WINDOW_DESTROYED (window) ||
2482 !WINDOW_IS_TOPLEVEL (window))
2485 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2487 if (!impl->toplevel)
2489 g_warning ("Can't call gdk_window_begin_move_drag on non-toplevel window");
2493 [(GdkQuartzNSWindow *)impl->toplevel beginManualMove];
2497 gdk_quartz_window_set_icon_list (GdkWindow *window,
2500 /* FIXME: Implement */
2504 gdk_quartz_window_get_frame_extents (GdkWindow *window,
2507 GdkWindow *toplevel;
2508 GdkWindowImplQuartz *impl;
2511 g_return_if_fail (rect != NULL);
2519 toplevel = gdk_window_get_effective_toplevel (window);
2520 impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
2522 ns_rect = [impl->toplevel frame];
2524 _gdk_quartz_window_xy_to_gdk_xy (ns_rect.origin.x,
2525 ns_rect.origin.y + ns_rect.size.height,
2526 &rect->x, &rect->y);
2528 rect->width = ns_rect.size.width;
2529 rect->height = ns_rect.size.height;
2533 gdk_quartz_window_set_decorations (GdkWindow *window,
2534 GdkWMDecoration decorations)
2536 GdkWindowImplQuartz *impl;
2537 NSUInteger old_mask, new_mask;
2540 if (GDK_WINDOW_DESTROYED (window) ||
2541 !WINDOW_IS_TOPLEVEL (window))
2544 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2546 if (decorations == 0 || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP ||
2547 impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN )
2549 new_mask = NSBorderlessWindowMask;
2553 /* FIXME: Honor other GDK_DECOR_* flags. */
2554 new_mask = (NSTitledWindowMask | NSClosableWindowMask |
2555 NSMiniaturizableWindowMask | NSResizableWindowMask);
2558 GDK_QUARTZ_ALLOC_POOL;
2560 old_mask = [impl->toplevel styleMask];
2562 if (old_mask != new_mask)
2566 old_view = [impl->toplevel contentView];
2568 rect = [impl->toplevel frame];
2570 /* Properly update the size of the window when the titlebar is
2573 if (old_mask == NSBorderlessWindowMask &&
2574 new_mask != NSBorderlessWindowMask)
2576 rect = [NSWindow frameRectForContentRect:rect styleMask:new_mask];
2579 else if (old_mask != NSBorderlessWindowMask &&
2580 new_mask == NSBorderlessWindowMask)
2582 rect = [NSWindow contentRectForFrameRect:rect styleMask:old_mask];
2585 /* Note, before OS 10.6 there doesn't seem to be a way to change this without
2586 * recreating the toplevel. There might be bad side-effects of doing
2587 * that, but it seems alright.
2589 #if MAC_OS_X_VERSION_MIN_ALLOWED > MAC_OS_X_VERSION_10_5
2590 if ([impl->toplevel respondsToSelector:@selector(setStyleMask:)])
2592 [impl->toplevel setStyleMask:new_mask];
2597 [impl->toplevel release];
2598 impl->toplevel = [[GdkQuartzNSWindow alloc] initWithContentRect:rect
2600 backing:NSBackingStoreBuffered
2602 [impl->toplevel setHasShadow: window_type_hint_to_shadow (impl->type_hint)];
2603 [impl->toplevel setLevel: window_type_hint_to_level (impl->type_hint)];
2604 [impl->toplevel setContentView:old_view];
2607 [impl->toplevel setFrame:rect display:YES];
2609 /* Invalidate the window shadow for non-opaque views that have shadow
2610 * enabled, to get the shadow shape updated.
2612 if (![old_view isOpaque] && [impl->toplevel hasShadow])
2613 [(GdkQuartzView*)old_view setNeedsInvalidateShadow:YES];
2616 GDK_QUARTZ_RELEASE_POOL;
2620 gdk_quartz_window_get_decorations (GdkWindow *window,
2621 GdkWMDecoration *decorations)
2623 GdkWindowImplQuartz *impl;
2625 if (GDK_WINDOW_DESTROYED (window) ||
2626 !WINDOW_IS_TOPLEVEL (window))
2629 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2633 /* Borderless is 0, so we can't check it as a bit being set. */
2634 if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
2640 /* FIXME: Honor the other GDK_DECOR_* flags. */
2641 *decorations = GDK_DECOR_ALL;
2649 gdk_quartz_window_set_functions (GdkWindow *window,
2650 GdkWMFunction functions)
2652 g_return_if_fail (GDK_IS_WINDOW (window));
2654 /* FIXME: Implement */
2658 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
2659 cairo_region_t *area)
2665 gdk_quartz_window_stick (GdkWindow *window)
2667 if (GDK_WINDOW_DESTROYED (window) ||
2668 !WINDOW_IS_TOPLEVEL (window))
2673 gdk_quartz_window_unstick (GdkWindow *window)
2675 if (GDK_WINDOW_DESTROYED (window) ||
2676 !WINDOW_IS_TOPLEVEL (window))
2681 gdk_quartz_window_maximize (GdkWindow *window)
2683 GdkWindowImplQuartz *impl;
2685 if (GDK_WINDOW_DESTROYED (window) ||
2686 !WINDOW_IS_TOPLEVEL (window))
2689 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2691 if (GDK_WINDOW_IS_MAPPED (window))
2693 GDK_QUARTZ_ALLOC_POOL;
2695 if (impl->toplevel && ![impl->toplevel isZoomed])
2696 [impl->toplevel zoom:nil];
2698 GDK_QUARTZ_RELEASE_POOL;
2702 gdk_synthesize_window_state (window,
2704 GDK_WINDOW_STATE_MAXIMIZED);
2709 gdk_quartz_window_unmaximize (GdkWindow *window)
2711 GdkWindowImplQuartz *impl;
2713 if (GDK_WINDOW_DESTROYED (window) ||
2714 !WINDOW_IS_TOPLEVEL (window))
2717 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2719 if (GDK_WINDOW_IS_MAPPED (window))
2721 GDK_QUARTZ_ALLOC_POOL;
2723 if (impl->toplevel && [impl->toplevel isZoomed])
2724 [impl->toplevel zoom:nil];
2726 GDK_QUARTZ_RELEASE_POOL;
2730 gdk_synthesize_window_state (window,
2731 GDK_WINDOW_STATE_MAXIMIZED,
2737 gdk_quartz_window_iconify (GdkWindow *window)
2739 GdkWindowImplQuartz *impl;
2741 if (GDK_WINDOW_DESTROYED (window) ||
2742 !WINDOW_IS_TOPLEVEL (window))
2745 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2747 if (GDK_WINDOW_IS_MAPPED (window))
2749 GDK_QUARTZ_ALLOC_POOL;
2752 [impl->toplevel miniaturize:nil];
2754 GDK_QUARTZ_RELEASE_POOL;
2758 gdk_synthesize_window_state (window,
2760 GDK_WINDOW_STATE_ICONIFIED);
2765 gdk_quartz_window_deiconify (GdkWindow *window)
2767 GdkWindowImplQuartz *impl;
2769 if (GDK_WINDOW_DESTROYED (window) ||
2770 !WINDOW_IS_TOPLEVEL (window))
2773 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2775 if (GDK_WINDOW_IS_MAPPED (window))
2777 GDK_QUARTZ_ALLOC_POOL;
2780 [impl->toplevel deminiaturize:nil];
2782 GDK_QUARTZ_RELEASE_POOL;
2786 gdk_synthesize_window_state (window,
2787 GDK_WINDOW_STATE_ICONIFIED,
2792 static FullscreenSavedGeometry *
2793 get_fullscreen_geometry (GdkWindow *window)
2795 return g_object_get_data (G_OBJECT (window), FULLSCREEN_DATA);
2799 gdk_quartz_window_fullscreen (GdkWindow *window)
2801 FullscreenSavedGeometry *geometry;
2804 if (GDK_WINDOW_DESTROYED (window) ||
2805 !WINDOW_IS_TOPLEVEL (window))
2808 geometry = get_fullscreen_geometry (window);
2811 geometry = g_new (FullscreenSavedGeometry, 1);
2813 geometry->x = window->x;
2814 geometry->y = window->y;
2815 geometry->width = window->width;
2816 geometry->height = window->height;
2818 if (!gdk_window_get_decorations (window, &geometry->decor))
2819 geometry->decor = GDK_DECOR_ALL;
2821 g_object_set_data_full (G_OBJECT (window),
2822 FULLSCREEN_DATA, geometry,
2825 gdk_window_set_decorations (window, 0);
2827 frame = [[NSScreen mainScreen] frame];
2828 move_resize_window_internal (window,
2830 frame.size.width, frame.size.height);
2833 SetSystemUIMode (kUIModeAllHidden, kUIOptionAutoShowMenuBar);
2835 gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
2839 gdk_quartz_window_unfullscreen (GdkWindow *window)
2841 FullscreenSavedGeometry *geometry;
2843 if (GDK_WINDOW_DESTROYED (window) ||
2844 !WINDOW_IS_TOPLEVEL (window))
2847 geometry = get_fullscreen_geometry (window);
2850 SetSystemUIMode (kUIModeNormal, 0);
2852 move_resize_window_internal (window,
2858 gdk_window_set_decorations (window, geometry->decor);
2860 g_object_set_data (G_OBJECT (window), FULLSCREEN_DATA, NULL);
2862 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
2867 gdk_quartz_window_set_keep_above (GdkWindow *window,
2870 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2873 g_return_if_fail (GDK_IS_WINDOW (window));
2875 if (GDK_WINDOW_DESTROYED (window) ||
2876 !WINDOW_IS_TOPLEVEL (window))
2879 level = window_type_hint_to_level (gdk_window_get_type_hint (window));
2881 /* Adjust normal window level by one if necessary. */
2882 [impl->toplevel setLevel: level + (setting ? 1 : 0)];
2886 gdk_quartz_window_set_keep_below (GdkWindow *window,
2889 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2892 g_return_if_fail (GDK_IS_WINDOW (window));
2894 if (GDK_WINDOW_DESTROYED (window) ||
2895 !WINDOW_IS_TOPLEVEL (window))
2898 level = window_type_hint_to_level (gdk_window_get_type_hint (window));
2900 /* Adjust normal window level by one if necessary. */
2901 [impl->toplevel setLevel: level - (setting ? 1 : 0)];
2905 gdk_quartz_window_get_group (GdkWindow *window)
2907 g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
2909 if (GDK_WINDOW_DESTROYED (window) ||
2910 !WINDOW_IS_TOPLEVEL (window))
2913 /* FIXME: Implement */
2919 gdk_quartz_window_set_group (GdkWindow *window,
2922 /* FIXME: Implement */
2926 gdk_quartz_window_enable_synchronized_configure (GdkWindow *window)
2931 gdk_quartz_window_configure_finished (GdkWindow *window)
2936 gdk_quartz_window_destroy_notify (GdkWindow *window)
2938 check_grab_destroy (window);
2942 gdk_quartz_window_set_opacity (GdkWindow *window,
2945 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2947 g_return_if_fail (GDK_IS_WINDOW (window));
2948 g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
2950 if (GDK_WINDOW_DESTROYED (window) ||
2951 !WINDOW_IS_TOPLEVEL (window))
2956 else if (opacity > 1)
2959 [impl->toplevel setAlphaValue: opacity];
2962 static cairo_region_t *
2963 gdk_quartz_window_get_shape (GdkWindow *window)
2965 /* FIXME: implement */
2969 static cairo_region_t *
2970 gdk_quartz_window_get_input_shape (GdkWindow *window)
2972 /* FIXME: implement */
2978 gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
2980 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2981 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
2982 GdkWindowImplQuartzClass *impl_quartz_class = GDK_WINDOW_IMPL_QUARTZ_CLASS (klass);
2984 parent_class = g_type_class_peek_parent (klass);
2986 object_class->finalize = gdk_window_impl_quartz_finalize;
2988 impl_class->ref_cairo_surface = gdk_quartz_ref_cairo_surface;
2989 impl_class->show = gdk_window_quartz_show;
2990 impl_class->hide = gdk_window_quartz_hide;
2991 impl_class->withdraw = gdk_window_quartz_withdraw;
2992 impl_class->set_events = gdk_window_quartz_set_events;
2993 impl_class->get_events = gdk_window_quartz_get_events;
2994 impl_class->raise = gdk_window_quartz_raise;
2995 impl_class->lower = gdk_window_quartz_lower;
2996 impl_class->restack_toplevel = gdk_window_quartz_restack_toplevel;
2997 impl_class->move_resize = gdk_window_quartz_move_resize;
2998 impl_class->set_background = gdk_window_quartz_set_background;
2999 impl_class->reparent = gdk_window_quartz_reparent;
3000 impl_class->set_device_cursor = gdk_window_quartz_set_device_cursor;
3001 impl_class->get_geometry = gdk_window_quartz_get_geometry;
3002 impl_class->get_root_coords = gdk_window_quartz_get_root_coords;
3003 impl_class->get_device_state = gdk_window_quartz_get_device_state;
3004 impl_class->shape_combine_region = gdk_window_quartz_shape_combine_region;
3005 impl_class->input_shape_combine_region = gdk_window_quartz_input_shape_combine_region;
3006 impl_class->set_static_gravities = gdk_window_quartz_set_static_gravities;
3007 impl_class->queue_antiexpose = gdk_quartz_window_queue_antiexpose;
3008 impl_class->translate = gdk_quartz_window_translate;
3009 impl_class->destroy = gdk_quartz_window_destroy;
3010 impl_class->destroy_foreign = gdk_quartz_window_destroy_foreign;
3011 impl_class->resize_cairo_surface = gdk_window_quartz_resize_cairo_surface;
3012 impl_class->get_shape = gdk_quartz_window_get_shape;
3013 impl_class->get_input_shape = gdk_quartz_window_get_input_shape;
3015 impl_class->focus = gdk_quartz_window_focus;
3016 impl_class->set_type_hint = gdk_quartz_window_set_type_hint;
3017 impl_class->get_type_hint = gdk_quartz_window_get_type_hint;
3018 impl_class->set_modal_hint = gdk_quartz_window_set_modal_hint;
3019 impl_class->set_skip_taskbar_hint = gdk_quartz_window_set_skip_taskbar_hint;
3020 impl_class->set_skip_pager_hint = gdk_quartz_window_set_skip_pager_hint;
3021 impl_class->set_urgency_hint = gdk_quartz_window_set_urgency_hint;
3022 impl_class->set_geometry_hints = gdk_quartz_window_set_geometry_hints;
3023 impl_class->set_title = gdk_quartz_window_set_title;
3024 impl_class->set_role = gdk_quartz_window_set_role;
3025 impl_class->set_startup_id = gdk_quartz_window_set_startup_id;
3026 impl_class->set_transient_for = gdk_quartz_window_set_transient_for;
3027 impl_class->get_root_origin = gdk_quartz_window_get_root_origin;
3028 impl_class->get_frame_extents = gdk_quartz_window_get_frame_extents;
3029 impl_class->set_override_redirect = gdk_quartz_window_set_override_redirect;
3030 impl_class->set_accept_focus = gdk_quartz_window_set_accept_focus;
3031 impl_class->set_focus_on_map = gdk_quartz_window_set_focus_on_map;
3032 impl_class->set_icon_list = gdk_quartz_window_set_icon_list;
3033 impl_class->set_icon_name = gdk_quartz_window_set_icon_name;
3034 impl_class->iconify = gdk_quartz_window_iconify;
3035 impl_class->deiconify = gdk_quartz_window_deiconify;
3036 impl_class->stick = gdk_quartz_window_stick;
3037 impl_class->unstick = gdk_quartz_window_unstick;
3038 impl_class->maximize = gdk_quartz_window_maximize;
3039 impl_class->unmaximize = gdk_quartz_window_unmaximize;
3040 impl_class->fullscreen = gdk_quartz_window_fullscreen;
3041 impl_class->unfullscreen = gdk_quartz_window_unfullscreen;
3042 impl_class->set_keep_above = gdk_quartz_window_set_keep_above;
3043 impl_class->set_keep_below = gdk_quartz_window_set_keep_below;
3044 impl_class->get_group = gdk_quartz_window_get_group;
3045 impl_class->set_group = gdk_quartz_window_set_group;
3046 impl_class->set_decorations = gdk_quartz_window_set_decorations;
3047 impl_class->get_decorations = gdk_quartz_window_get_decorations;
3048 impl_class->set_functions = gdk_quartz_window_set_functions;
3049 impl_class->set_functions = gdk_quartz_window_set_functions;
3050 impl_class->begin_resize_drag = gdk_quartz_window_begin_resize_drag;
3051 impl_class->begin_move_drag = gdk_quartz_window_begin_move_drag;
3052 impl_class->enable_synchronized_configure = gdk_quartz_window_enable_synchronized_configure;
3053 impl_class->configure_finished = gdk_quartz_window_configure_finished;
3054 impl_class->set_opacity = gdk_quartz_window_set_opacity;
3055 impl_class->destroy_notify = gdk_quartz_window_destroy_notify;
3056 impl_class->register_dnd = _gdk_quartz_window_register_dnd;
3057 impl_class->drag_begin = _gdk_quartz_window_drag_begin;
3058 impl_class->process_updates_recurse = _gdk_quartz_window_process_updates_recurse;
3059 impl_class->sync_rendering = _gdk_quartz_window_sync_rendering;
3060 impl_class->simulate_key = _gdk_quartz_window_simulate_key;
3061 impl_class->simulate_button = _gdk_quartz_window_simulate_button;
3062 impl_class->get_property = _gdk_quartz_window_get_property;
3063 impl_class->change_property = _gdk_quartz_window_change_property;
3064 impl_class->delete_property = _gdk_quartz_window_delete_property;
3067 impl_quartz_class->get_context = gdk_window_impl_quartz_get_context;
3068 impl_quartz_class->release_context = gdk_window_impl_quartz_release_context;
3072 _gdk_window_impl_quartz_get_type (void)
3074 static GType object_type = 0;
3078 const GTypeInfo object_info =
3080 sizeof (GdkWindowImplQuartzClass),
3081 (GBaseInitFunc) NULL,
3082 (GBaseFinalizeFunc) NULL,
3083 (GClassInitFunc) gdk_window_impl_quartz_class_init,
3084 NULL, /* class_finalize */
3085 NULL, /* class_data */
3086 sizeof (GdkWindowImplQuartz),
3087 0, /* n_preallocs */
3088 (GInstanceInitFunc) gdk_window_impl_quartz_init,
3091 const GInterfaceInfo paintable_info =
3093 (GInterfaceInitFunc) gdk_window_impl_quartz_paintable_init,
3098 object_type = g_type_register_static (GDK_TYPE_WINDOW_IMPL,
3099 "GdkWindowImplQuartz",
3101 g_type_add_interface_static (object_type,
3110 gdk_quartz_window_get_context (GdkWindowImplQuartz *window,
3113 if (!GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->get_context)
3115 g_warning ("%s doesn't implement GdkWindowImplQuartzClass::get_context()",
3116 G_OBJECT_TYPE_NAME (window));
3120 return GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->get_context (window, antialias);
3124 gdk_quartz_window_release_context (GdkWindowImplQuartz *window,
3125 CGContextRef cg_context)
3127 if (!GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->release_context)
3129 g_warning ("%s doesn't implement GdkWindowImplQuartzClass::release_context()",
3130 G_OBJECT_TYPE_NAME (window));
3134 GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->release_context (window, cg_context);
3140 gdk_root_window_impl_quartz_get_context (GdkWindowImplQuartz *window,
3143 CGColorSpaceRef colorspace;
3144 CGContextRef cg_context;
3145 GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (window);
3147 if (GDK_WINDOW_DESTROYED (window_impl->wrapper))
3150 /* We do not have the notion of a root window on OS X. We fake this
3151 * by creating a 1x1 bitmap and return a context to that.
3153 colorspace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
3154 cg_context = CGBitmapContextCreate (NULL,
3155 1, 1, 8, 4, colorspace,
3156 kCGImageAlphaPremultipliedLast);
3157 CGColorSpaceRelease (colorspace);
3163 gdk_root_window_impl_quartz_release_context (GdkWindowImplQuartz *window,
3164 CGContextRef cg_context)
3166 CGContextRelease (cg_context);
3170 gdk_root_window_impl_quartz_class_init (GdkRootWindowImplQuartzClass *klass)
3172 GdkWindowImplQuartzClass *window_quartz_class = GDK_WINDOW_IMPL_QUARTZ_CLASS (klass);
3174 root_window_parent_class = g_type_class_peek_parent (klass);
3176 window_quartz_class->get_context = gdk_root_window_impl_quartz_get_context;
3177 window_quartz_class->release_context = gdk_root_window_impl_quartz_release_context;
3181 gdk_root_window_impl_quartz_init (GdkRootWindowImplQuartz *impl)
3186 _gdk_root_window_impl_quartz_get_type (void)
3188 static GType object_type = 0;
3192 const GTypeInfo object_info =
3194 sizeof (GdkRootWindowImplQuartzClass),
3195 (GBaseInitFunc) NULL,
3196 (GBaseFinalizeFunc) NULL,
3197 (GClassInitFunc) gdk_root_window_impl_quartz_class_init,
3198 NULL, /* class_finalize */
3199 NULL, /* class_data */
3200 sizeof (GdkRootWindowImplQuartz),
3201 0, /* n_preallocs */
3202 (GInstanceInitFunc) gdk_root_window_impl_quartz_init,
3205 object_type = g_type_register_static (GDK_TYPE_WINDOW_IMPL_QUARTZ,
3206 "GdkRootWindowQuartz",