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.
23 #include <Carbon/Carbon.h>
26 #include "gdkdeviceprivate.h"
27 #include "gdkwindowimpl.h"
28 #include "gdkprivate-quartz.h"
29 #include "gdkscreen-quartz.h"
30 #include "gdkinputprivate.h"
33 #include <cairo-quartz.h>
35 static gpointer parent_class;
36 static gpointer root_window_parent_class;
38 static GSList *update_nswindows;
39 static gboolean in_process_all_updates = FALSE;
41 static GSList *main_window_stack;
43 void _gdk_quartz_window_flush (GdkWindowImplQuartz *window_impl);
45 #define FULLSCREEN_DATA "fullscreen-data"
51 GdkWMDecoration decor;
52 } FullscreenSavedGeometry;
55 static void update_toplevel_order (void);
56 static void clear_toplevel_order (void);
58 static FullscreenSavedGeometry *get_fullscreen_geometry (GdkWindow *window);
60 #define WINDOW_IS_TOPLEVEL(window) \
61 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
62 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
63 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
66 gdk_quartz_window_get_nsview (GdkWindow *window)
68 if (GDK_WINDOW_DESTROYED (window))
71 return ((GdkWindowImplQuartz *)window->impl)->view;
75 gdk_quartz_window_get_nswindow (GdkWindow *window)
77 if (GDK_WINDOW_DESTROYED (window))
80 return ((GdkWindowImplQuartz *)window->impl)->toplevel;
84 gdk_window_impl_quartz_get_context (GdkWindowImplQuartz *window_impl,
87 CGContextRef cg_context;
89 if (GDK_WINDOW_DESTROYED (window_impl->wrapper))
92 /* Lock focus when not called as part of a drawRect call. This
93 * is needed when called from outside "real" expose events, for
94 * example for synthesized expose events when realizing windows
95 * and for widgets that send fake expose events like the arrow
96 * buttons in spinbuttons or the position marker in rulers.
98 if (window_impl->in_paint_rect_count == 0)
100 if (![window_impl->view lockFocusIfCanDraw])
104 cg_context = [[NSGraphicsContext currentContext] graphicsPort];
105 CGContextSaveGState (cg_context);
106 CGContextSetAllowsAntialiasing (cg_context, antialias);
108 /* We'll emulate the clipping caused by double buffering here */
109 if (window_impl->begin_paint_count != 0)
115 n_rects = cairo_region_num_rectangles (window_impl->paint_clip_region);
120 cg_rects = g_new (CGRect, n_rects);
122 for (i = 0; i < n_rects; i++)
124 cairo_rectangle_int_t cairo_rect;
125 cairo_region_get_rectangle (window_impl->paint_clip_region,
127 cg_rects[i].origin.x = cairo_rect.x;
128 cg_rects[i].origin.y = cairo_rect.y;
129 cg_rects[i].size.width = cairo_rect.width;
130 cg_rects[i].size.height = cairo_rect.height;
133 CGContextClipToRects (cg_context, cg_rects, n_rects);
135 if (cg_rects != &rect)
143 gdk_window_impl_quartz_release_context (GdkWindowImplQuartz *window_impl,
144 CGContextRef cg_context)
146 CGContextRestoreGState (cg_context);
147 CGContextSetAllowsAntialiasing (cg_context, TRUE);
149 /* See comment in gdk_quartz_window_get_context(). */
150 if (window_impl->in_paint_rect_count == 0)
152 _gdk_quartz_window_flush (window_impl);
153 [window_impl->view unlockFocus];
158 check_grab_unmap (GdkWindow *window)
161 GdkDisplay *display = gdk_window_get_display (window);
162 GdkDeviceManager *device_manager;
164 device_manager = gdk_display_get_device_manager (display);
165 list = gdk_device_manager_list_devices (device_manager,
166 GDK_DEVICE_TYPE_FLOATING);
167 for (l = list; l; l = l->next)
169 _gdk_display_end_device_grab (display, l->data, 0, window, TRUE);
176 check_grab_destroy (GdkWindow *window)
179 GdkDisplay *display = gdk_window_get_display (window);
180 GdkDeviceManager *device_manager;
182 /* Make sure there is no lasting grab in this native window */
183 device_manager = gdk_display_get_device_manager (display);
184 list = gdk_device_manager_list_devices (device_manager,
185 GDK_DEVICE_TYPE_MASTER);
187 for (l = list; l; l = l->next)
189 GdkDeviceGrabInfo *grab;
191 grab = _gdk_display_get_last_device_grab (display, l->data);
192 if (grab && grab->native_window == window)
194 /* Serials are always 0 in quartz, but for clarity: */
195 grab->serial_end = grab->serial_start;
196 grab->implicit_ungrab = TRUE;
204 gdk_window_impl_quartz_finalize (GObject *object)
206 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (object);
208 check_grab_destroy (GDK_WINDOW_IMPL_QUARTZ (object)->wrapper);
210 if (impl->paint_clip_region)
211 cairo_region_destroy (impl->paint_clip_region);
213 if (impl->transient_for)
214 g_object_unref (impl->transient_for);
216 G_OBJECT_CLASS (parent_class)->finalize (object);
219 /* Help preventing "beam sync penalty" where CG makes all graphics code
220 * block until the next vsync if we try to flush (including call display on
221 * a view) too often. We do this by limiting the manual flushing done
222 * outside of expose calls to less than some frequency when measured over
223 * the last 4 flushes. This is a bit arbitray, but seems to make it possible
224 * for some quick manual flushes (such as gtkruler or gimp's marching ants)
225 * without hitting the max flush frequency.
227 * If drawable NULL, no flushing is done, only registering that a flush was
231 _gdk_quartz_window_flush (GdkWindowImplQuartz *window_impl)
233 static struct timeval prev_tv;
234 static gint intervals[4];
239 gettimeofday (&tv, NULL);
240 ms = (tv.tv_sec - prev_tv.tv_sec) * 1000 + (tv.tv_usec - prev_tv.tv_usec) / 1000;
241 intervals[index++ % 4] = ms;
245 ms = intervals[0] + intervals[1] + intervals[2] + intervals[3];
247 /* ~25Hz on average. */
251 [window_impl->toplevel flushWindow];
260 static cairo_user_data_key_t gdk_quartz_cairo_key;
263 GdkWindowImplQuartz *window_impl;
264 CGContextRef cg_context;
265 } GdkQuartzCairoSurfaceData;
268 gdk_quartz_cairo_surface_destroy (void *data)
270 GdkQuartzCairoSurfaceData *surface_data = data;
272 surface_data->window_impl->cairo_surface = NULL;
274 gdk_quartz_window_release_context (surface_data->window_impl,
275 surface_data->cg_context);
277 g_free (surface_data);
280 static cairo_surface_t *
281 gdk_quartz_create_cairo_surface (GdkWindowImplQuartz *impl,
285 CGContextRef cg_context;
286 GdkQuartzCairoSurfaceData *surface_data;
287 cairo_surface_t *surface;
289 cg_context = gdk_quartz_window_get_context (impl, TRUE);
294 surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
295 surface_data->window_impl = impl;
296 surface_data->cg_context = cg_context;
298 surface = cairo_quartz_surface_create_for_cg_context (cg_context,
301 cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
303 gdk_quartz_cairo_surface_destroy);
308 static cairo_surface_t *
309 gdk_quartz_ref_cairo_surface (GdkWindow *window)
311 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
313 if (GDK_WINDOW_DESTROYED (window))
316 if (!impl->cairo_surface)
318 impl->cairo_surface =
319 gdk_quartz_create_cairo_surface (impl,
320 gdk_window_get_width (impl->wrapper),
321 gdk_window_get_height (impl->wrapper));
324 cairo_surface_reference (impl->cairo_surface);
326 return impl->cairo_surface;
330 gdk_window_impl_quartz_init (GdkWindowImplQuartz *impl)
332 impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
336 gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable,
338 const cairo_region_t *region)
340 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
341 cairo_region_t *clipped_and_offset_region;
344 clipped_and_offset_region = cairo_region_copy (region);
346 cairo_region_intersect (clipped_and_offset_region,
347 window->clip_region_with_children);
348 cairo_region_translate (clipped_and_offset_region,
349 window->abs_x, window->abs_y);
351 if (impl->begin_paint_count == 0)
352 impl->paint_clip_region = cairo_region_reference (clipped_and_offset_region);
354 cairo_region_union (impl->paint_clip_region, clipped_and_offset_region);
356 impl->begin_paint_count++;
358 if (cairo_region_is_empty (clipped_and_offset_region))
361 cr = gdk_cairo_create (window);
363 cairo_translate (cr, -window->abs_x, -window->abs_y);
365 gdk_cairo_region (cr, clipped_and_offset_region);
368 while (window->background == NULL && window->parent)
370 cairo_translate (cr, -window->x, window->y);
371 window = window->parent;
374 if (window->background)
375 cairo_set_source (cr, window->background);
377 cairo_set_source_rgba (cr, 0, 0, 0, 0);
379 /* Can use cairo_paint() here, we clipped above */
385 cairo_region_destroy (clipped_and_offset_region);
389 gdk_window_impl_quartz_end_paint (GdkPaintable *paintable)
391 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
393 impl->begin_paint_count--;
395 if (impl->begin_paint_count == 0)
397 cairo_region_destroy (impl->paint_clip_region);
398 impl->paint_clip_region = NULL;
403 _gdk_quartz_window_set_needs_display_in_region (GdkWindow *window,
404 cairo_region_t *region)
406 GdkWindowImplQuartz *impl;
409 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
411 if (!impl->needs_display_region)
412 impl->needs_display_region = cairo_region_create ();
414 cairo_region_union (impl->needs_display_region, region);
416 n_rects = cairo_region_num_rectangles (region);
417 for (i = 0; i < n_rects; i++)
419 cairo_rectangle_int_t rect;
420 cairo_region_get_rectangle (region, i, &rect);
421 [impl->view setNeedsDisplayInRect:NSMakeRect (rect.x, rect.y,
422 rect.width, rect.height)];
427 _gdk_quartz_window_process_updates_recurse (GdkWindow *window,
428 cairo_region_t *region)
430 /* Make sure to only flush each toplevel at most once if we're called
431 * from process_all_updates.
433 if (in_process_all_updates)
437 toplevel = gdk_window_get_effective_toplevel (window);
438 if (toplevel && WINDOW_IS_TOPLEVEL (toplevel))
440 GdkWindowImplQuartz *toplevel_impl;
443 toplevel_impl = (GdkWindowImplQuartz *)toplevel->impl;
444 nswindow = toplevel_impl->toplevel;
446 /* In theory, we could skip the flush disabling, since we only
449 if (nswindow && ![nswindow isFlushWindowDisabled])
452 [nswindow disableFlushWindow];
453 update_nswindows = g_slist_prepend (update_nswindows, nswindow);
458 if (WINDOW_IS_TOPLEVEL (window))
459 _gdk_quartz_window_set_needs_display_in_region (window, region);
461 _gdk_window_process_updates_recurse (window, region);
463 /* NOTE: I'm not sure if we should displayIfNeeded here. It slows down a
464 * lot (since it triggers the beam syncing) and things seem to work
470 _gdk_quartz_display_before_process_all_updates (GdkDisplay *display)
472 in_process_all_updates = TRUE;
474 NSDisableScreenUpdates ();
478 _gdk_quartz_display_after_process_all_updates (GdkDisplay *display)
480 GSList *old_update_nswindows = update_nswindows;
481 GSList *tmp_list = update_nswindows;
483 update_nswindows = NULL;
487 NSWindow *nswindow = tmp_list->data;
489 [[nswindow contentView] displayIfNeeded];
491 _gdk_quartz_window_flush (NULL);
493 [nswindow enableFlushWindow];
494 [nswindow flushWindow];
497 tmp_list = tmp_list->next;
500 g_slist_free (old_update_nswindows);
502 in_process_all_updates = FALSE;
504 NSEnableScreenUpdates ();
508 gdk_window_impl_quartz_paintable_init (GdkPaintableIface *iface)
510 iface->begin_paint_region = gdk_window_impl_quartz_begin_paint_region;
511 iface->end_paint = gdk_window_impl_quartz_end_paint;
515 get_default_title (void)
519 title = g_get_application_name ();
521 title = g_get_prgname ();
527 get_ancestor_coordinates_from_child (GdkWindow *child_window,
530 GdkWindow *ancestor_window,
534 while (child_window != ancestor_window)
536 child_x += child_window->x;
537 child_y += child_window->y;
539 child_window = child_window->parent;
542 *ancestor_x = child_x;
543 *ancestor_y = child_y;
547 _gdk_quartz_window_debug_highlight (GdkWindow *window, gint number)
553 static NSWindow *debug_window[10];
554 static NSRect old_rect[10];
558 g_return_if_fail (number >= 0 && number <= 9);
560 if (window == _gdk_root)
565 if (debug_window[number])
566 [debug_window[number] close];
567 debug_window[number] = NULL;
572 toplevel = gdk_window_get_toplevel (window);
573 get_ancestor_coordinates_from_child (window, 0, 0, toplevel, &x, &y);
575 gdk_window_get_origin (toplevel, &tx, &ty);
579 _gdk_quartz_window_gdk_xy_to_xy (x, y + window->height,
582 rect = NSMakeRect (gx, gy, window->width, window->height);
584 if (debug_window[number] && NSEqualRects (rect, old_rect[number]))
587 old_rect[number] = rect;
589 if (debug_window[number])
590 [debug_window[number] close];
592 debug_window[number] = [[NSWindow alloc] initWithContentRect:rect
593 styleMask:NSBorderlessWindowMask
594 backing:NSBackingStoreBuffered
600 color = [NSColor redColor];
603 color = [NSColor blueColor];
606 color = [NSColor greenColor];
609 color = [NSColor yellowColor];
612 color = [NSColor brownColor];
615 color = [NSColor purpleColor];
618 color = [NSColor blackColor];
622 [debug_window[number] setBackgroundColor:color];
623 [debug_window[number] setAlphaValue:0.4];
624 [debug_window[number] setOpaque:NO];
625 [debug_window[number] setReleasedWhenClosed:YES];
626 [debug_window[number] setIgnoresMouseEvents:YES];
627 [debug_window[number] setLevel:NSFloatingWindowLevel];
629 [debug_window[number] orderFront:nil];
633 _gdk_quartz_window_is_ancestor (GdkWindow *ancestor,
636 if (ancestor == NULL || window == NULL)
639 return (gdk_window_get_parent (window) == ancestor ||
640 _gdk_quartz_window_is_ancestor (ancestor,
641 gdk_window_get_parent (window)));
645 /* See notes on top of gdkscreen-quartz.c */
647 _gdk_quartz_window_gdk_xy_to_xy (gint gdk_x,
652 GdkScreenQuartz *screen_quartz = GDK_SCREEN_QUARTZ (_gdk_screen);
655 *ns_y = screen_quartz->height - gdk_y + screen_quartz->min_y;
658 *ns_x = gdk_x + screen_quartz->min_x;
662 _gdk_quartz_window_xy_to_gdk_xy (gint ns_x,
667 GdkScreenQuartz *screen_quartz = GDK_SCREEN_QUARTZ (_gdk_screen);
670 *gdk_y = screen_quartz->height - ns_y + screen_quartz->min_y;
673 *gdk_x = ns_x - screen_quartz->min_x;
677 _gdk_quartz_window_nspoint_to_gdk_xy (NSPoint point,
681 _gdk_quartz_window_xy_to_gdk_xy (point.x, point.y,
686 find_child_window_helper (GdkWindow *window,
691 gboolean get_toplevel)
693 GdkWindowImplQuartz *impl;
696 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
698 if (window == _gdk_root)
699 update_toplevel_order ();
701 for (l = impl->sorted_children; l; l = l->next)
703 GdkWindow *child = l->data;
704 GdkWindowImplQuartz *child_impl = GDK_WINDOW_IMPL_QUARTZ (child->impl);
707 if (!GDK_WINDOW_IS_MAPPED (child))
710 temp_x = x_offset + child->x;
711 temp_y = y_offset + child->y;
713 /* Special-case the root window. We have to include the title
714 * bar in the checks, otherwise the window below the title bar
715 * will be found i.e. events punch through. (If we can find a
716 * better way to deal with the events in gdkevents-quartz, this
717 * might not be needed.)
719 if (window == _gdk_root)
721 NSRect frame = NSMakeRect (0, 0, 100, 100);
726 mask = [child_impl->toplevel styleMask];
728 /* Get the title bar height. */
729 content = [NSWindow contentRectForFrameRect:frame
731 titlebar_height = frame.size.height - content.size.height;
733 if (titlebar_height > 0 &&
734 x >= temp_x && y >= temp_y - titlebar_height &&
735 x < temp_x + child->width && y < temp_y)
737 /* The root means "unknown" i.e. a window not managed by
740 return (GdkWindow *)_gdk_root;
744 if ((!get_toplevel || (get_toplevel && window == _gdk_root)) &&
745 x >= temp_x && y >= temp_y &&
746 x < temp_x + child->width && y < temp_y + child->height)
748 /* Look for child windows. */
749 return find_child_window_helper (l->data,
759 /* Given a GdkWindow and coordinates relative to it, returns the
760 * innermost subwindow that contains the point. If the coordinates are
761 * outside the passed in window, NULL is returned.
764 _gdk_quartz_window_find_child (GdkWindow *window,
767 gboolean get_toplevel)
769 if (x >= 0 && y >= 0 && x < window->width && y < window->height)
770 return find_child_window_helper (window, x, y, 0, 0, get_toplevel);
777 _gdk_quartz_window_did_become_main (GdkWindow *window)
779 main_window_stack = g_slist_remove (main_window_stack, window);
781 if (window->window_type != GDK_WINDOW_TEMP)
782 main_window_stack = g_slist_prepend (main_window_stack, window);
784 clear_toplevel_order ();
788 _gdk_quartz_window_did_resign_main (GdkWindow *window)
790 GdkWindow *new_window = NULL;
792 if (main_window_stack)
793 new_window = main_window_stack->data;
798 toplevels = gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
800 new_window = toplevels->data;
801 g_list_free (toplevels);
805 new_window != window &&
806 GDK_WINDOW_IS_MAPPED (new_window) &&
807 WINDOW_IS_TOPLEVEL (new_window))
809 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (new_window->impl);
811 [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
814 clear_toplevel_order ();
818 get_nsscreen_for_point (gint x, gint y)
822 NSScreen *screen = NULL;
824 GDK_QUARTZ_ALLOC_POOL;
826 screens = [NSScreen screens];
828 for (i = 0; i < [screens count]; i++)
830 NSRect rect = [[screens objectAtIndex:i] frame];
832 if (x >= rect.origin.x && x <= rect.origin.x + rect.size.width &&
833 y >= rect.origin.y && y <= rect.origin.y + rect.size.height)
835 screen = [screens objectAtIndex:i];
840 GDK_QUARTZ_RELEASE_POOL;
846 _gdk_x11_display_create_window_imp (GdkDisplay *display,
848 GdkWindow *real_parent,
850 GdkEventMask event_mask,
851 GdkWindowAttr *attributes,
852 gint attributes_mask)
854 GdkWindowImplQuartz *impl;
855 GdkWindowImplQuartz *parent_impl;
857 GDK_QUARTZ_ALLOC_POOL;
859 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_QUARTZ, NULL);
860 window->impl = GDK_WINDOW_IMPL (impl);
861 impl->wrapper = window;
863 parent_impl = GDK_WINDOW_IMPL_QUARTZ (window->parent->impl);
865 switch (window->window_type)
867 case GDK_WINDOW_TOPLEVEL:
868 case GDK_WINDOW_TEMP:
869 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
871 /* The common code warns for this case */
872 parent_impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
876 /* Maintain the z-ordered list of children. */
877 if (window->parent != _gdk_root)
878 parent_impl->sorted_children = g_list_prepend (parent_impl->sorted_children, window);
880 clear_toplevel_order ();
882 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
883 (attributes->cursor) :
888 switch (attributes->window_type)
890 case GDK_WINDOW_TOPLEVEL:
891 case GDK_WINDOW_TEMP:
896 NSUInteger style_mask;
900 /* initWithContentRect will place on the mainScreen by default.
901 * We want to select the screen to place on ourselves. We need
902 * to find the screen the window will be on and correct the
903 * content_rect coordinates to be relative to that screen.
905 _gdk_quartz_window_gdk_xy_to_xy (window->x, window->y, &nx, &ny);
907 screen = get_nsscreen_for_point (nx, ny);
908 screen_rect = [screen frame];
909 nx -= screen_rect.origin.x;
910 ny -= screen_rect.origin.y;
912 content_rect = NSMakeRect (nx, ny - window->height,
916 if (attributes->window_type == GDK_WINDOW_TEMP ||
917 attributes->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
919 style_mask = NSBorderlessWindowMask;
923 style_mask = (NSTitledWindowMask |
924 NSClosableWindowMask |
925 NSMiniaturizableWindowMask |
926 NSResizableWindowMask);
929 impl->toplevel = [[GdkQuartzWindow alloc] initWithContentRect:content_rect
931 backing:NSBackingStoreBuffered
935 if (attributes_mask & GDK_WA_TITLE)
936 title = attributes->title;
938 title = get_default_title ();
940 gdk_window_set_title (window, title);
942 if (gdk_window_get_visual (window) == gdk_screen_get_rgba_visual (_gdk_screen))
944 [impl->toplevel setOpaque:NO];
945 [impl->toplevel setBackgroundColor:[NSColor clearColor]];
948 content_rect.origin.x = 0;
949 content_rect.origin.y = 0;
951 impl->view = [[GdkQuartzView alloc] initWithFrame:content_rect];
952 [impl->view setGdkWindow:window];
953 [impl->toplevel setContentView:impl->view];
954 [impl->view release];
958 case GDK_WINDOW_CHILD:
960 GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (window->parent->impl);
962 if (!window->input_only)
964 NSRect frame_rect = NSMakeRect (window->x + window->parent->abs_x,
965 window->y + window->parent->abs_y,
969 impl->view = [[GdkQuartzView alloc] initWithFrame:frame_rect];
971 [impl->view setGdkWindow:window];
973 /* GdkWindows should be hidden by default */
974 [impl->view setHidden:YES];
975 [parent_impl->view addSubview:impl->view];
976 [impl->view release];
982 g_assert_not_reached ();
985 GDK_QUARTZ_RELEASE_POOL;
987 if (attributes_mask & GDK_WA_TYPE_HINT)
988 gdk_window_set_type_hint (window, attributes->type_hint);
992 _gdk_quartz_window_update_position (GdkWindow *window)
996 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
998 GDK_QUARTZ_ALLOC_POOL;
1000 frame_rect = [impl->toplevel frame];
1001 content_rect = [impl->toplevel contentRectForFrameRect:frame_rect];
1003 _gdk_quartz_window_xy_to_gdk_xy (content_rect.origin.x,
1004 content_rect.origin.y + content_rect.size.height,
1005 &window->x, &window->y);
1008 GDK_QUARTZ_RELEASE_POOL;
1012 _gdk_windowing_update_window_sizes (GdkScreen *screen)
1014 GList *windows, *list;
1016 /* The size of the root window is so that it can contain all
1017 * monitors attached to this machine. The monitors are laid out
1018 * within this root window. We calculate the size of the root window
1019 * and the positions of the different monitors in gdkscreen-quartz.c.
1021 * This data is updated when the monitor configuration is changed.
1025 _gdk_root->abs_x = 0;
1026 _gdk_root->abs_y = 0;
1027 _gdk_root->width = gdk_screen_get_width (screen);
1028 _gdk_root->height = gdk_screen_get_height (screen);
1030 windows = gdk_screen_get_toplevel_windows (screen);
1032 for (list = windows; list; list = list->next)
1033 _gdk_quartz_window_update_position (list->data);
1035 g_list_free (windows);
1039 _gdk_windowing_window_init (void)
1041 GdkWindowImplQuartz *impl;
1043 g_assert (_gdk_root == NULL);
1045 _gdk_root = _gdk_display_create_window (_gdk_display);
1047 _gdk_root->impl = g_object_new (_gdk_root_window_impl_quartz_get_type (), NULL);
1048 _gdk_root->impl_window = _gdk_root;
1049 _gdk_root->visual = gdk_screen_get_system_visual (_gdk_screen);
1051 impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
1053 _gdk_windowing_update_window_sizes (_gdk_screen);
1055 _gdk_root->state = 0; /* We don't want GDK_WINDOW_STATE_WITHDRAWN here */
1056 _gdk_root->window_type = GDK_WINDOW_ROOT;
1057 _gdk_root->depth = 24;
1058 _gdk_root->viewable = TRUE;
1060 impl->wrapper = _gdk_root;
1064 gdk_quartz_window_destroy (GdkWindow *window,
1066 gboolean foreign_destroy)
1068 GdkWindowImplQuartz *impl;
1071 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1073 main_window_stack = g_slist_remove (main_window_stack, window);
1075 g_list_free (impl->sorted_children);
1076 impl->sorted_children = NULL;
1078 parent = window->parent;
1081 GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (parent->impl);
1083 parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window);
1086 if (impl->cairo_surface)
1088 cairo_surface_finish (impl->cairo_surface);
1089 cairo_surface_set_user_data (impl->cairo_surface, &gdk_quartz_cairo_key,
1091 impl->cairo_surface = NULL;
1094 if (!recursing && !foreign_destroy)
1096 GDK_QUARTZ_ALLOC_POOL;
1099 [impl->toplevel close];
1100 else if (impl->view)
1101 [impl->view removeFromSuperview];
1103 GDK_QUARTZ_RELEASE_POOL;
1107 static cairo_surface_t *
1108 gdk_window_quartz_resize_cairo_surface (GdkWindow *window,
1109 cairo_surface_t *surface,
1113 /* Quartz surfaces cannot be resized */
1114 cairo_surface_destroy (surface);
1120 gdk_quartz_window_destroy_foreign (GdkWindow *window)
1122 /* Foreign windows aren't supported in OSX. */
1125 /* FIXME: This might be possible to simplify with client-side windows. Also
1126 * note that already_mapped is not used yet, see the x11 backend.
1129 gdk_window_quartz_show (GdkWindow *window, gboolean already_mapped)
1131 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1132 gboolean focus_on_map;
1134 GDK_QUARTZ_ALLOC_POOL;
1136 if (!GDK_WINDOW_IS_MAPPED (window))
1137 focus_on_map = window->focus_on_map;
1139 focus_on_map = TRUE;
1141 if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel)
1145 make_key = (window->accept_focus && focus_on_map &&
1146 window->window_type != GDK_WINDOW_TEMP);
1148 [(GdkQuartzWindow*)impl->toplevel showAndMakeKey:make_key];
1149 clear_toplevel_order ();
1151 _gdk_quartz_events_send_map_event (window);
1155 [impl->view setHidden:NO];
1158 [impl->view setNeedsDisplay:YES];
1160 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_WITHDRAWN, 0);
1162 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1163 gdk_window_maximize (window);
1165 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1166 gdk_window_iconify (window);
1168 if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1169 _gdk_quartz_window_attach_to_parent (window);
1171 GDK_QUARTZ_RELEASE_POOL;
1174 /* Temporarily unsets the parent window, if the window is a
1178 _gdk_quartz_window_detach_from_parent (GdkWindow *window)
1180 GdkWindowImplQuartz *impl;
1182 g_return_if_fail (GDK_IS_WINDOW (window));
1184 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1186 g_return_if_fail (impl->toplevel != NULL);
1188 if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1190 GdkWindowImplQuartz *parent_impl;
1192 parent_impl = GDK_WINDOW_IMPL_QUARTZ (impl->transient_for->impl);
1193 [parent_impl->toplevel removeChildWindow:impl->toplevel];
1194 clear_toplevel_order ();
1198 /* Re-sets the parent window, if the window is a transient. */
1200 _gdk_quartz_window_attach_to_parent (GdkWindow *window)
1202 GdkWindowImplQuartz *impl;
1204 g_return_if_fail (GDK_IS_WINDOW (window));
1206 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1208 g_return_if_fail (impl->toplevel != NULL);
1210 if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
1212 GdkWindowImplQuartz *parent_impl;
1214 parent_impl = GDK_WINDOW_IMPL_QUARTZ (impl->transient_for->impl);
1215 [parent_impl->toplevel addChildWindow:impl->toplevel ordered:NSWindowAbove];
1216 clear_toplevel_order ();
1221 gdk_window_quartz_hide (GdkWindow *window)
1223 GdkWindowImplQuartz *impl;
1225 /* Make sure we're not stuck in fullscreen mode. */
1226 if (get_fullscreen_geometry (window))
1227 SetSystemUIMode (kUIModeNormal, 0);
1229 check_grab_unmap (window);
1231 _gdk_window_clear_update_area (window);
1233 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1235 if (WINDOW_IS_TOPLEVEL (window))
1237 /* Update main window. */
1238 main_window_stack = g_slist_remove (main_window_stack, window);
1239 if ([NSApp mainWindow] == impl->toplevel)
1240 _gdk_quartz_window_did_resign_main (window);
1242 if (impl->transient_for)
1243 _gdk_quartz_window_detach_from_parent (window);
1245 [(GdkQuartzWindow*)impl->toplevel hide];
1247 else if (impl->view)
1249 [impl->view setHidden:YES];
1254 gdk_window_quartz_withdraw (GdkWindow *window)
1256 gdk_window_hide (window);
1260 move_resize_window_internal (GdkWindow *window,
1266 GdkWindowImplQuartz *impl;
1267 GdkRectangle old_visible;
1268 GdkRectangle new_visible;
1269 GdkRectangle scroll_rect;
1270 cairo_region_t *old_region;
1271 cairo_region_t *expose_region;
1274 if (GDK_WINDOW_DESTROYED (window))
1277 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1279 if ((x == -1 || (x == window->x)) &&
1280 (y == -1 || (y == window->y)) &&
1281 (width == -1 || (width == window->width)) &&
1282 (height == -1 || (height == window->height)))
1287 if (!impl->toplevel)
1289 /* The previously visible area of this window in a coordinate
1290 * system rooted at the origin of this window.
1292 old_visible.x = -window->x;
1293 old_visible.y = -window->y;
1295 old_visible.width = window->width;
1296 old_visible.height = window->height;
1301 delta.width = x - window->x;
1311 delta.height = y - window->y;
1320 window->width = width;
1323 window->height = height;
1325 GDK_QUARTZ_ALLOC_POOL;
1329 NSRect content_rect;
1333 _gdk_quartz_window_gdk_xy_to_xy (window->x, window->y + window->height,
1336 content_rect = NSMakeRect (gx, gy, window->width, window->height);
1338 frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
1339 [impl->toplevel setFrame:frame_rect display:YES];
1343 if (!window->input_only)
1347 nsrect = NSMakeRect (window->x, window->y, window->width, window->height);
1349 /* The newly visible area of this window in a coordinate
1350 * system rooted at the origin of this window.
1352 new_visible.x = -window->x;
1353 new_visible.y = -window->y;
1354 new_visible.width = old_visible.width; /* parent has not changed size */
1355 new_visible.height = old_visible.height; /* parent has not changed size */
1357 expose_region = cairo_region_create_rectangle (&new_visible);
1358 old_region = cairo_region_create_rectangle (&old_visible);
1359 cairo_region_subtract (expose_region, old_region);
1361 /* Determine what (if any) part of the previously visible
1362 * part of the window can be copied without a redraw
1364 scroll_rect = old_visible;
1365 scroll_rect.x -= delta.width;
1366 scroll_rect.y -= delta.height;
1367 gdk_rectangle_intersect (&scroll_rect, &old_visible, &scroll_rect);
1369 if (!cairo_region_is_empty (expose_region))
1371 if (scroll_rect.width != 0 && scroll_rect.height != 0)
1373 [impl->view scrollRect:NSMakeRect (scroll_rect.x,
1380 [impl->view setFrame:nsrect];
1382 _gdk_quartz_window_set_needs_display_in_region (window, expose_region);
1386 [impl->view setFrame:nsrect];
1387 [impl->view setNeedsDisplay:YES];
1390 cairo_region_destroy (expose_region);
1391 cairo_region_destroy (old_region);
1395 GDK_QUARTZ_RELEASE_POOL;
1399 window_quartz_move (GdkWindow *window,
1403 g_return_if_fail (GDK_IS_WINDOW (window));
1405 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1408 move_resize_window_internal (window, x, y, -1, -1);
1412 window_quartz_resize (GdkWindow *window,
1416 g_return_if_fail (GDK_IS_WINDOW (window));
1418 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1426 move_resize_window_internal (window, -1, -1, width, height);
1430 window_quartz_move_resize (GdkWindow *window,
1441 move_resize_window_internal (window, x, y, width, height);
1445 gdk_window_quartz_move_resize (GdkWindow *window,
1452 if (with_move && (width < 0 && height < 0))
1453 window_quartz_move (window, x, y);
1457 window_quartz_move_resize (window, x, y, width, height);
1459 window_quartz_resize (window, width, height);
1463 /* FIXME: This might need fixing (reparenting didn't work before client-side
1467 gdk_window_quartz_reparent (GdkWindow *window,
1468 GdkWindow *new_parent,
1472 GdkWindow *old_parent;
1473 GdkWindowImplQuartz *impl, *old_parent_impl, *new_parent_impl;
1474 NSView *view, *new_parent_view;
1476 if (new_parent == _gdk_root)
1478 /* Could be added, just needs implementing. */
1479 g_warning ("Reparenting to root window is not supported yet in the Mac OS X backend");
1483 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1486 new_parent_impl = GDK_WINDOW_IMPL_QUARTZ (new_parent->impl);
1487 new_parent_view = new_parent_impl->view;
1489 old_parent = window->parent;
1490 old_parent_impl = GDK_WINDOW_IMPL_QUARTZ (old_parent->impl);
1494 [view removeFromSuperview];
1495 [new_parent_view addSubview:view];
1499 window->parent = new_parent;
1503 old_parent_impl->sorted_children = g_list_remove (old_parent_impl->sorted_children, window);
1506 new_parent_impl->sorted_children = g_list_prepend (new_parent_impl->sorted_children, window);
1511 /* Get the toplevel ordering from NSApp and update our own list. We do
1512 * this on demand since the NSApp's list is not up to date directly
1513 * after we get windowDidBecomeMain.
1516 update_toplevel_order (void)
1518 GdkWindowImplQuartz *root_impl;
1519 NSEnumerator *enumerator;
1521 GList *toplevels = NULL;
1523 root_impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
1525 if (root_impl->sorted_children)
1528 GDK_QUARTZ_ALLOC_POOL;
1530 enumerator = [[NSApp orderedWindows] objectEnumerator];
1531 while ((nswindow = [enumerator nextObject]))
1535 if (![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
1538 window = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
1539 toplevels = g_list_prepend (toplevels, window);
1542 GDK_QUARTZ_RELEASE_POOL;
1544 root_impl->sorted_children = g_list_reverse (toplevels);
1548 clear_toplevel_order (void)
1550 GdkWindowImplQuartz *root_impl;
1552 root_impl = GDK_WINDOW_IMPL_QUARTZ (_gdk_root->impl);
1554 g_list_free (root_impl->sorted_children);
1555 root_impl->sorted_children = NULL;
1559 gdk_window_quartz_raise (GdkWindow *window)
1561 if (GDK_WINDOW_DESTROYED (window))
1564 if (WINDOW_IS_TOPLEVEL (window))
1566 GdkWindowImplQuartz *impl;
1568 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1569 [impl->toplevel orderFront:impl->toplevel];
1571 clear_toplevel_order ();
1575 GdkWindow *parent = window->parent;
1579 GdkWindowImplQuartz *impl;
1581 impl = (GdkWindowImplQuartz *)parent->impl;
1583 impl->sorted_children = g_list_remove (impl->sorted_children, window);
1584 impl->sorted_children = g_list_prepend (impl->sorted_children, window);
1590 gdk_window_quartz_lower (GdkWindow *window)
1592 if (GDK_WINDOW_DESTROYED (window))
1595 if (WINDOW_IS_TOPLEVEL (window))
1597 GdkWindowImplQuartz *impl;
1599 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1600 [impl->toplevel orderBack:impl->toplevel];
1602 clear_toplevel_order ();
1606 GdkWindow *parent = window->parent;
1610 GdkWindowImplQuartz *impl;
1612 impl = (GdkWindowImplQuartz *)parent->impl;
1614 impl->sorted_children = g_list_remove (impl->sorted_children, window);
1615 impl->sorted_children = g_list_append (impl->sorted_children, window);
1621 gdk_window_quartz_restack_toplevel (GdkWindow *window,
1625 /* FIXME: Implement this */
1629 gdk_window_quartz_set_background (GdkWindow *window,
1630 cairo_pattern_t *pattern)
1632 /* FIXME: We could theoretically set the background color for toplevels
1633 * here. (Currently we draw the background before emitting expose events)
1638 gdk_window_quartz_set_device_cursor (GdkWindow *window,
1642 GdkCursorPrivate *cursor_private;
1645 cursor_private = (GdkCursorPrivate *)cursor;
1647 if (GDK_WINDOW_DESTROYED (window))
1651 nscursor = [NSCursor arrowCursor];
1653 nscursor = cursor_private->nscursor;
1659 gdk_window_quartz_get_geometry (GdkWindow *window,
1665 GdkWindowImplQuartz *impl;
1668 if (GDK_WINDOW_DESTROYED (window))
1671 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
1672 if (window == _gdk_root)
1680 *width = window->width;
1682 *height = window->height;
1684 else if (WINDOW_IS_TOPLEVEL (window))
1686 ns_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
1688 /* This doesn't work exactly as in X. There doesn't seem to be a
1689 * way to get the coords relative to the parent window (usually
1690 * the window frame), but that seems useless except for
1691 * borderless windows where it's relative to the root window. So
1692 * we return (0, 0) (should be something like (0, 22)) for
1693 * windows with borders and the root relative coordinates
1696 if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
1698 _gdk_quartz_window_xy_to_gdk_xy (ns_rect.origin.x,
1699 ns_rect.origin.y + ns_rect.size.height,
1711 *width = ns_rect.size.width;
1713 *height = ns_rect.size.height;
1717 ns_rect = [impl->view frame];
1720 *x = ns_rect.origin.x;
1722 *y = ns_rect.origin.y;
1724 *width = ns_rect.size.width;
1726 *height = ns_rect.size.height;
1731 gdk_window_quartz_get_root_coords (GdkWindow *window,
1737 int tmp_x = 0, tmp_y = 0;
1738 GdkWindow *toplevel;
1739 NSRect content_rect;
1740 GdkWindowImplQuartz *impl;
1742 if (GDK_WINDOW_DESTROYED (window))
1752 if (window == _gdk_root)
1762 toplevel = gdk_window_get_toplevel (window);
1763 impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
1765 content_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
1767 _gdk_quartz_window_xy_to_gdk_xy (content_rect.origin.x,
1768 content_rect.origin.y + content_rect.size.height,
1774 while (window != toplevel)
1776 if (_gdk_window_has_impl ((GdkWindow *)window))
1782 window = window->parent;
1794 gdk_quartz_window_get_root_origin (GdkWindow *window,
1803 gdk_window_get_frame_extents (window, &rect);
1812 /* Returns coordinates relative to the passed in window. */
1814 gdk_window_quartz_get_device_state_helper (GdkWindow *window,
1818 GdkModifierType *mask)
1822 GdkWindow *toplevel;
1823 GdkWindow *found_window;
1825 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
1827 if (GDK_WINDOW_DESTROYED (window))
1835 toplevel = gdk_window_get_toplevel (window);
1837 *mask = _gdk_quartz_events_get_current_event_mask ();
1839 /* Get the y coordinate, needs to be flipped. */
1840 if (window == _gdk_root)
1842 point = [NSEvent mouseLocation];
1843 _gdk_quartz_window_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
1847 GdkWindowImplQuartz *impl;
1850 impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
1851 nswindow = impl->toplevel;
1853 point = [nswindow mouseLocationOutsideOfEventStream];
1856 y_tmp = toplevel->height - point.y;
1858 window = (GdkWindow *)toplevel;
1861 found_window = _gdk_quartz_window_find_child (window, x_tmp, y_tmp,
1864 /* We never return the root window. */
1865 if (found_window == _gdk_root)
1866 found_window = NULL;
1871 return found_window;
1875 gdk_window_quartz_get_device_state (GdkWindow *window,
1879 GdkModifierType *mask)
1881 return gdk_window_quartz_get_device_state_helper (window,
1883 x, y, mask) != NULL;
1886 /* Returns coordinates relative to the root. */
1888 _gdk_windowing_get_device_state (GdkDisplay *display,
1893 GdkModifierType *mask)
1895 g_return_if_fail (display == _gdk_display);
1897 *screen = _gdk_screen;
1898 gdk_window_quartz_get_device_state_helper (_gdk_root, device, x, y, mask);
1901 /* Returns coordinates relative to the found window. */
1903 _gdk_windowing_window_at_pointer (GdkDisplay *display,
1906 GdkModifierType *mask,
1907 gboolean get_toplevel)
1909 GdkWindow *found_window;
1911 GdkModifierType tmp_mask = 0;
1913 found_window = gdk_window_quartz_get_device_state_helper (_gdk_root,
1914 display->core_pointer,
1919 /* The coordinates returned above are relative the root, we want
1920 * coordinates relative the window here.
1922 while (found_window != _gdk_root)
1924 x -= found_window->x;
1925 y -= found_window->y;
1927 found_window = found_window->parent;
1935 /* Mimic the X backend here, -1,-1 for unknown windows. */
1945 /* Requested toplevel, find it. */
1946 /* TODO: This can be implemented more efficient by never
1947 recursing into children in the first place */
1950 /* Convert to toplevel */
1951 while (found_window->parent != NULL &&
1952 found_window->parent->window_type != GDK_WINDOW_ROOT)
1954 *win_x += found_window->x;
1955 *win_y += found_window->y;
1956 found_window = found_window->parent;
1961 return found_window;
1965 _gdk_windowing_window_at_device_position (GdkDisplay *display,
1969 GdkModifierType *mask,
1970 gboolean get_toplevel)
1972 return GDK_DEVICE_GET_CLASS (device)->window_at_position (device,
1980 gdk_window_quartz_get_events (GdkWindow *window)
1982 if (GDK_WINDOW_DESTROYED (window))
1985 return window->event_mask;
1989 gdk_window_quartz_set_events (GdkWindow *window,
1990 GdkEventMask event_mask)
1992 /* The mask is set in the common code. */
1996 gdk_quartz_window_set_urgency_hint (GdkWindow *window,
1999 if (GDK_WINDOW_DESTROYED (window) ||
2000 !WINDOW_IS_TOPLEVEL (window))
2003 /* FIXME: Implement */
2007 gdk_quartz_window_set_geometry_hints (GdkWindow *window,
2008 const GdkGeometry *geometry,
2009 GdkWindowHints geom_mask)
2011 GdkWindowImplQuartz *impl;
2013 g_return_if_fail (geometry != NULL);
2015 if (GDK_WINDOW_DESTROYED (window) ||
2016 !WINDOW_IS_TOPLEVEL (window))
2019 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2020 if (!impl->toplevel)
2023 if (geom_mask & GDK_HINT_POS)
2025 /* FIXME: Implement */
2028 if (geom_mask & GDK_HINT_USER_POS)
2030 /* FIXME: Implement */
2033 if (geom_mask & GDK_HINT_USER_SIZE)
2035 /* FIXME: Implement */
2038 if (geom_mask & GDK_HINT_MIN_SIZE)
2042 size.width = geometry->min_width;
2043 size.height = geometry->min_height;
2045 [impl->toplevel setContentMinSize:size];
2048 if (geom_mask & GDK_HINT_MAX_SIZE)
2052 size.width = geometry->max_width;
2053 size.height = geometry->max_height;
2055 [impl->toplevel setContentMaxSize:size];
2058 if (geom_mask & GDK_HINT_BASE_SIZE)
2060 /* FIXME: Implement */
2063 if (geom_mask & GDK_HINT_RESIZE_INC)
2067 size.width = geometry->width_inc;
2068 size.height = geometry->height_inc;
2070 [impl->toplevel setContentResizeIncrements:size];
2073 if (geom_mask & GDK_HINT_ASPECT)
2075 /* FIXME: Implement */
2078 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2080 /* FIXME: Implement */
2085 gdk_quartz_window_set_title (GdkWindow *window,
2088 GdkWindowImplQuartz *impl;
2090 g_return_if_fail (title != NULL);
2092 if (GDK_WINDOW_DESTROYED (window) ||
2093 !WINDOW_IS_TOPLEVEL (window))
2096 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2100 GDK_QUARTZ_ALLOC_POOL;
2101 [impl->toplevel setTitle:[NSString stringWithUTF8String:title]];
2102 GDK_QUARTZ_RELEASE_POOL;
2107 gdk_quartz_window_set_role (GdkWindow *window,
2110 if (GDK_WINDOW_DESTROYED (window) ||
2111 WINDOW_IS_TOPLEVEL (window))
2114 /* FIXME: Implement */
2118 gdk_quartz_window_set_transient_for (GdkWindow *window,
2121 GdkWindowImplQuartz *window_impl;
2122 GdkWindowImplQuartz *parent_impl;
2124 if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (parent) ||
2125 !WINDOW_IS_TOPLEVEL (window))
2128 window_impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2129 if (!window_impl->toplevel)
2132 GDK_QUARTZ_ALLOC_POOL;
2134 if (window_impl->transient_for)
2136 _gdk_quartz_window_detach_from_parent (window);
2138 g_object_unref (window_impl->transient_for);
2139 window_impl->transient_for = NULL;
2142 parent_impl = GDK_WINDOW_IMPL_QUARTZ (parent->impl);
2143 if (parent_impl->toplevel)
2145 /* We save the parent because it needs to be unset/reset when
2146 * hiding and showing the window.
2149 /* We don't set transients for tooltips, they are already
2150 * handled by the window level being the top one. If we do, then
2151 * the parent window will be brought to the top just because the
2152 * tooltip is, which is not what we want.
2154 if (gdk_window_get_type_hint (window) != GDK_WINDOW_TYPE_HINT_TOOLTIP)
2156 window_impl->transient_for = g_object_ref (parent);
2158 /* We only add the window if it is shown, otherwise it will
2159 * be shown unconditionally here. If it is not shown, the
2160 * window will be added in show() instead.
2162 if (!(window->state & GDK_WINDOW_STATE_WITHDRAWN))
2163 _gdk_quartz_window_attach_to_parent (window);
2167 GDK_QUARTZ_RELEASE_POOL;
2171 gdk_window_quartz_shape_combine_region (GdkWindow *window,
2172 const cairo_region_t *shape,
2176 /* FIXME: Implement */
2180 gdk_window_quartz_input_shape_combine_region (GdkWindow *window,
2181 const cairo_region_t *shape_region,
2185 /* FIXME: Implement */
2189 gdk_quartz_window_set_override_redirect (GdkWindow *window,
2190 gboolean override_redirect)
2192 /* FIXME: Implement */
2196 gdk_quartz_window_set_accept_focus (GdkWindow *window,
2197 gboolean accept_focus)
2199 window->accept_focus = accept_focus != FALSE;
2203 gdk_window_quartz_set_static_gravities (GdkWindow *window,
2204 gboolean use_static)
2206 if (GDK_WINDOW_DESTROYED (window) ||
2207 !WINDOW_IS_TOPLEVEL (window))
2210 /* FIXME: Implement */
2215 gdk_quartz_window_set_focus_on_map (GdkWindow *window,
2216 gboolean focus_on_map)
2218 window->focus_on_map = focus_on_map != FALSE;
2222 gdk_quartz_window_set_icon_name (GdkWindow *window,
2225 /* FIXME: Implement */
2229 gdk_quartz_window_focus (GdkWindow *window,
2232 GdkWindowImplQuartz *impl;
2234 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2236 if (GDK_WINDOW_DESTROYED (window) ||
2237 !WINDOW_IS_TOPLEVEL (window))
2240 if (window->accept_focus && window->window_type != GDK_WINDOW_TEMP)
2242 GDK_QUARTZ_ALLOC_POOL;
2243 [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
2244 clear_toplevel_order ();
2245 GDK_QUARTZ_RELEASE_POOL;
2250 gint window_type_hint_to_level (GdkWindowTypeHint hint)
2254 case GDK_WINDOW_TYPE_HINT_DOCK:
2255 case GDK_WINDOW_TYPE_HINT_UTILITY:
2256 return NSFloatingWindowLevel;
2258 case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
2259 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
2260 return NSTornOffMenuWindowLevel;
2262 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2263 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2264 return NSStatusWindowLevel;
2266 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2267 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2268 case GDK_WINDOW_TYPE_HINT_COMBO:
2269 case GDK_WINDOW_TYPE_HINT_DND:
2270 return NSPopUpMenuWindowLevel;
2272 case GDK_WINDOW_TYPE_HINT_NORMAL: /* Normal toplevel window */
2273 case GDK_WINDOW_TYPE_HINT_DIALOG: /* Dialog window */
2274 case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
2275 case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
2282 return NSNormalWindowLevel;
2286 window_type_hint_to_shadow (GdkWindowTypeHint hint)
2290 case GDK_WINDOW_TYPE_HINT_NORMAL: /* Normal toplevel window */
2291 case GDK_WINDOW_TYPE_HINT_DIALOG: /* Dialog window */
2292 case GDK_WINDOW_TYPE_HINT_DOCK:
2293 case GDK_WINDOW_TYPE_HINT_UTILITY:
2294 case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
2295 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
2296 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2297 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2298 case GDK_WINDOW_TYPE_HINT_COMBO:
2299 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2300 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2303 case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
2304 case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
2305 case GDK_WINDOW_TYPE_HINT_DND:
2317 gdk_quartz_window_set_type_hint (GdkWindow *window,
2318 GdkWindowTypeHint hint)
2320 GdkWindowImplQuartz *impl;
2322 if (GDK_WINDOW_DESTROYED (window) ||
2323 !WINDOW_IS_TOPLEVEL (window))
2326 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2328 impl->type_hint = hint;
2330 /* Match the documentation, only do something if we're not mapped yet. */
2331 if (GDK_WINDOW_IS_MAPPED (window))
2334 [impl->toplevel setHasShadow: window_type_hint_to_shadow (hint)];
2335 [impl->toplevel setLevel: window_type_hint_to_level (hint)];
2338 static GdkWindowTypeHint
2339 gdk_quartz_window_get_type_hint (GdkWindow *window)
2341 if (GDK_WINDOW_DESTROYED (window) ||
2342 !WINDOW_IS_TOPLEVEL (window))
2343 return GDK_WINDOW_TYPE_HINT_NORMAL;
2345 return GDK_WINDOW_IMPL_QUARTZ (window->impl)->type_hint;
2349 gdk_quartz_window_set_modal_hint (GdkWindow *window,
2352 if (GDK_WINDOW_DESTROYED (window) ||
2353 !WINDOW_IS_TOPLEVEL (window))
2356 /* FIXME: Implement */
2360 gdk_quartz_window_set_skip_taskbar_hint (GdkWindow *window,
2361 gboolean skips_taskbar)
2363 if (GDK_WINDOW_DESTROYED (window) ||
2364 !WINDOW_IS_TOPLEVEL (window))
2367 /* FIXME: Implement */
2371 gdk_quartz_window_set_skip_pager_hint (GdkWindow *window,
2372 gboolean skips_pager)
2374 if (GDK_WINDOW_DESTROYED (window) ||
2375 !WINDOW_IS_TOPLEVEL (window))
2378 /* FIXME: Implement */
2382 gdk_quartz_window_begin_resize_drag (GdkWindow *window,
2389 GdkWindowImplQuartz *impl;
2391 g_return_if_fail (GDK_IS_WINDOW (window));
2393 if (edge != GDK_WINDOW_EDGE_SOUTH_EAST)
2395 g_warning ("Resizing is only implemented for GDK_WINDOW_EDGE_SOUTH_EAST on Mac OS");
2399 if (GDK_WINDOW_DESTROYED (window))
2402 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2404 if (!impl->toplevel)
2406 g_warning ("Can't call gdk_window_begin_resize_drag on non-toplevel window");
2410 [(GdkQuartzWindow *)impl->toplevel beginManualResize];
2414 gdk_quartz_window_begin_move_drag (GdkWindow *window,
2420 GdkWindowImplQuartz *impl;
2422 if (GDK_WINDOW_DESTROYED (window) ||
2423 !WINDOW_IS_TOPLEVEL (window))
2426 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2428 if (!impl->toplevel)
2430 g_warning ("Can't call gdk_window_begin_move_drag on non-toplevel window");
2434 [(GdkQuartzWindow *)impl->toplevel beginManualMove];
2438 gdk_quartz_window_set_icon_list (GdkWindow *window,
2441 /* FIXME: Implement */
2445 gdk_quartz_window_get_frame_extents (GdkWindow *window,
2448 GdkWindow *toplevel;
2449 GdkWindowImplQuartz *impl;
2452 g_return_if_fail (rect != NULL);
2460 toplevel = gdk_window_get_effective_toplevel (window);
2461 impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
2463 ns_rect = [impl->toplevel frame];
2465 _gdk_quartz_window_xy_to_gdk_xy (ns_rect.origin.x,
2466 ns_rect.origin.y + ns_rect.size.height,
2467 &rect->x, &rect->y);
2469 rect->width = ns_rect.size.width;
2470 rect->height = ns_rect.size.height;
2474 gdk_quartz_window_set_decorations (GdkWindow *window,
2475 GdkWMDecoration decorations)
2477 GdkWindowImplQuartz *impl;
2478 NSUInteger old_mask, new_mask;
2481 if (GDK_WINDOW_DESTROYED (window) ||
2482 !WINDOW_IS_TOPLEVEL (window))
2485 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2487 if (decorations == 0 || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP ||
2488 impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN )
2490 new_mask = NSBorderlessWindowMask;
2494 /* FIXME: Honor other GDK_DECOR_* flags. */
2495 new_mask = (NSTitledWindowMask | NSClosableWindowMask |
2496 NSMiniaturizableWindowMask | NSResizableWindowMask);
2499 GDK_QUARTZ_ALLOC_POOL;
2501 old_mask = [impl->toplevel styleMask];
2503 /* Note, there doesn't seem to be a way to change this without
2504 * recreating the toplevel. There might be bad side-effects of doing
2505 * that, but it seems alright.
2507 if (old_mask != new_mask)
2511 old_view = [impl->toplevel contentView];
2513 rect = [impl->toplevel frame];
2515 /* Properly update the size of the window when the titlebar is
2518 if (old_mask == NSBorderlessWindowMask &&
2519 new_mask != NSBorderlessWindowMask)
2521 rect = [NSWindow frameRectForContentRect:rect styleMask:new_mask];
2524 else if (old_mask != NSBorderlessWindowMask &&
2525 new_mask == NSBorderlessWindowMask)
2527 rect = [NSWindow contentRectForFrameRect:rect styleMask:old_mask];
2530 impl->toplevel = [impl->toplevel initWithContentRect:rect
2532 backing:NSBackingStoreBuffered
2535 [impl->toplevel setHasShadow: window_type_hint_to_shadow (impl->type_hint)];
2536 [impl->toplevel setLevel: window_type_hint_to_level (impl->type_hint)];
2538 [impl->toplevel setContentView:old_view];
2539 [impl->toplevel setFrame:rect display:YES];
2541 /* Invalidate the window shadow for non-opaque views that have shadow
2542 * enabled, to get the shadow shape updated.
2544 if (![old_view isOpaque] && [impl->toplevel hasShadow])
2545 [(GdkQuartzView*)old_view setNeedsInvalidateShadow:YES];
2548 GDK_QUARTZ_RELEASE_POOL;
2552 gdk_quartz_window_get_decorations (GdkWindow *window,
2553 GdkWMDecoration *decorations)
2555 GdkWindowImplQuartz *impl;
2557 if (GDK_WINDOW_DESTROYED (window) ||
2558 !WINDOW_IS_TOPLEVEL (window))
2561 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2565 /* Borderless is 0, so we can't check it as a bit being set. */
2566 if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
2572 /* FIXME: Honor the other GDK_DECOR_* flags. */
2573 *decorations = GDK_DECOR_ALL;
2581 gdk_quartz_window_set_functions (GdkWindow *window,
2582 GdkWMFunction functions)
2584 g_return_if_fail (GDK_IS_WINDOW (window));
2586 /* FIXME: Implement */
2590 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
2591 cairo_region_t *area)
2597 gdk_quartz_window_stick (GdkWindow *window)
2599 if (GDK_WINDOW_DESTROYED (window) ||
2600 !WINDOW_IS_TOPLEVEL (window))
2605 gdk_quartz_window_unstick (GdkWindow *window)
2607 if (GDK_WINDOW_DESTROYED (window) ||
2608 !WINDOW_IS_TOPLEVEL (window))
2613 gdk_quartz_window_maximize (GdkWindow *window)
2615 GdkWindowImplQuartz *impl;
2617 if (GDK_WINDOW_DESTROYED (window) ||
2618 !WINDOW_IS_TOPLEVEL (window))
2621 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2623 if (GDK_WINDOW_IS_MAPPED (window))
2625 GDK_QUARTZ_ALLOC_POOL;
2627 if (impl->toplevel && ![impl->toplevel isZoomed])
2628 [impl->toplevel zoom:nil];
2630 GDK_QUARTZ_RELEASE_POOL;
2634 gdk_synthesize_window_state (window,
2636 GDK_WINDOW_STATE_MAXIMIZED);
2641 gdk_quartz_window_unmaximize (GdkWindow *window)
2643 GdkWindowImplQuartz *impl;
2645 if (GDK_WINDOW_DESTROYED (window) ||
2646 !WINDOW_IS_TOPLEVEL (window))
2649 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2651 if (GDK_WINDOW_IS_MAPPED (window))
2653 GDK_QUARTZ_ALLOC_POOL;
2655 if (impl->toplevel && [impl->toplevel isZoomed])
2656 [impl->toplevel zoom:nil];
2658 GDK_QUARTZ_RELEASE_POOL;
2662 gdk_synthesize_window_state (window,
2663 GDK_WINDOW_STATE_MAXIMIZED,
2669 gdk_quartz_window_iconify (GdkWindow *window)
2671 GdkWindowImplQuartz *impl;
2673 if (GDK_WINDOW_DESTROYED (window) ||
2674 !WINDOW_IS_TOPLEVEL (window))
2677 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2679 if (GDK_WINDOW_IS_MAPPED (window))
2681 GDK_QUARTZ_ALLOC_POOL;
2684 [impl->toplevel miniaturize:nil];
2686 GDK_QUARTZ_RELEASE_POOL;
2690 gdk_synthesize_window_state (window,
2692 GDK_WINDOW_STATE_ICONIFIED);
2697 gdk_quartz_window_deiconify (GdkWindow *window)
2699 GdkWindowImplQuartz *impl;
2701 if (GDK_WINDOW_DESTROYED (window) ||
2702 !WINDOW_IS_TOPLEVEL (window))
2705 impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2707 if (GDK_WINDOW_IS_MAPPED (window))
2709 GDK_QUARTZ_ALLOC_POOL;
2712 [impl->toplevel deminiaturize:nil];
2714 GDK_QUARTZ_RELEASE_POOL;
2718 gdk_synthesize_window_state (window,
2719 GDK_WINDOW_STATE_ICONIFIED,
2724 static FullscreenSavedGeometry *
2725 get_fullscreen_geometry (GdkWindow *window)
2727 return g_object_get_data (G_OBJECT (window), FULLSCREEN_DATA);
2731 gdk_quartz_window_fullscreen (GdkWindow *window)
2733 FullscreenSavedGeometry *geometry;
2736 if (GDK_WINDOW_DESTROYED (window) ||
2737 !WINDOW_IS_TOPLEVEL (window))
2740 geometry = get_fullscreen_geometry (window);
2743 geometry = g_new (FullscreenSavedGeometry, 1);
2745 geometry->x = window->x;
2746 geometry->y = window->y;
2747 geometry->width = window->width;
2748 geometry->height = window->height;
2750 if (!gdk_window_get_decorations (window, &geometry->decor))
2751 geometry->decor = GDK_DECOR_ALL;
2753 g_object_set_data_full (G_OBJECT (window),
2754 FULLSCREEN_DATA, geometry,
2757 gdk_window_set_decorations (window, 0);
2759 frame = [[NSScreen mainScreen] frame];
2760 move_resize_window_internal (window,
2762 frame.size.width, frame.size.height);
2765 SetSystemUIMode (kUIModeAllHidden, kUIOptionAutoShowMenuBar);
2767 gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
2771 gdk_quarz_window_unfullscreen (GdkWindow *window)
2773 FullscreenSavedGeometry *geometry;
2775 if (GDK_WINDOW_DESTROYED (window) ||
2776 !WINDOW_IS_TOPLEVEL (window))
2779 geometry = get_fullscreen_geometry (window);
2782 SetSystemUIMode (kUIModeNormal, 0);
2784 move_resize_window_internal (window,
2790 gdk_window_set_decorations (window, geometry->decor);
2792 g_object_set_data (G_OBJECT (window), FULLSCREEN_DATA, NULL);
2794 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
2799 gdk_quartz_window_set_keep_above (GdkWindow *window,
2802 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2805 g_return_if_fail (GDK_IS_WINDOW (window));
2807 if (GDK_WINDOW_DESTROYED (window) ||
2808 !WINDOW_IS_TOPLEVEL (window))
2811 level = window_type_hint_to_level (gdk_window_get_type_hint (window));
2813 /* Adjust normal window level by one if necessary. */
2814 [impl->toplevel setLevel: level + (setting ? 1 : 0)];
2818 gdk_quartz_window_set_keep_below (GdkWindow *window,
2821 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2824 g_return_if_fail (GDK_IS_WINDOW (window));
2826 if (GDK_WINDOW_DESTROYED (window) ||
2827 !WINDOW_IS_TOPLEVEL (window))
2830 level = window_type_hint_to_level (gdk_window_get_type_hint (window));
2832 /* Adjust normal window level by one if necessary. */
2833 [impl->toplevel setLevel: level - (setting ? 1 : 0)];
2837 gdk_quartz_window_get_group (GdkWindow *window)
2839 g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
2841 if (GDK_WINDOW_DESTROYED (window) ||
2842 !WINDOW_IS_TOPLEVEL (window))
2845 /* FIXME: Implement */
2851 gdk_quartz_window_set_group (GdkWindow *window,
2854 /* FIXME: Implement */
2858 gdk_quartz_window_enable_synchronized_configure (GdkWindow *window)
2863 gdk_quartz_window_configure_finished (GdkWindow *window)
2868 gdk_quartz_window_destroy_notify (GdkWindow *window)
2870 check_grab_destroy (window);
2874 gdk_quartz_window_set_opacity (GdkWindow *window,
2877 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
2879 g_return_if_fail (GDK_IS_WINDOW (window));
2880 g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
2882 if (GDK_WINDOW_DESTROYED (window) ||
2883 !WINDOW_IS_TOPLEVEL (window))
2888 else if (opacity > 1)
2891 [impl->toplevel setAlphaValue: opacity];
2894 static cairo_region_t *
2895 gdk_quartz_window_get_shape (GdkWindow *window)
2897 /* FIXME: implement */
2901 static cairo_region_t *
2902 gdk_quartz_window_get_input_shape (GdkWindow *window)
2904 /* FIXME: implement */
2910 gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
2912 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2913 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
2914 GdkWindowImplQuartzClass *impl_quartz_class = GDK_WINDOW_IMPL_QUARTZ_CLASS (klass);
2916 parent_class = g_type_class_peek_parent (klass);
2918 object_class->finalize = gdk_window_impl_quartz_finalize;
2920 impl_class->ref_cairo_surface = gdk_quartz_ref_cairo_surface;
2921 impl_class->show = gdk_window_quartz_show;
2922 impl_class->hide = gdk_window_quartz_hide;
2923 impl_class->withdraw = gdk_window_quartz_withdraw;
2924 impl_class->set_events = gdk_window_quartz_set_events;
2925 impl_class->get_events = gdk_window_quartz_get_events;
2926 impl_class->raise = gdk_window_quartz_raise;
2927 impl_class->lower = gdk_window_quartz_lower;
2928 impl_class->restack_toplevel = gdk_window_quartz_restack_toplevel;
2929 impl_class->move_resize = gdk_window_quartz_move_resize;
2930 impl_class->set_background = gdk_window_quartz_set_background;
2931 impl_class->reparent = gdk_window_quartz_reparent;
2932 impl_class->set_device_cursor = gdk_window_quartz_set_device_cursor;
2933 impl_class->get_geometry = gdk_window_quartz_get_geometry;
2934 impl_class->get_root_coords = gdk_window_quartz_get_root_coords;
2935 impl_class->get_device_state = gdk_window_quartz_get_device_state;
2936 impl_class->shape_combine_region = gdk_window_quartz_shape_combine_region;
2937 impl_class->input_shape_combine_region = gdk_window_quartz_input_shape_combine_region;
2938 impl_class->set_static_gravities = gdk_window_quartz_set_static_gravities;
2939 impl_class->queue_antiexpose = _gdk_quartz_window_queue_antiexpose;
2940 impl_class->translate = _gdk_quartz_window_translate;
2941 impl_class->destroy = gdk_quartz_window_destroy;
2942 impl_class->destroy_foreign = gdk_quartz_window_destroy_foreign;
2943 impl_class->resize_cairo_surface = gdk_window_quartz_resize_cairo_surface;
2944 impl_class->get_shape = gdk_quartz_window_get_shape;
2945 impl_class->get_input_shape = gdk_quartz_window_get_input_shape;
2947 impl_quartz_class->get_context = gdk_window_impl_quartz_get_context;
2948 impl_quartz_class->release_context = gdk_window_impl_quartz_release_context;
2952 _gdk_window_impl_quartz_get_type (void)
2954 static GType object_type = 0;
2958 const GTypeInfo object_info =
2960 sizeof (GdkWindowImplQuartzClass),
2961 (GBaseInitFunc) NULL,
2962 (GBaseFinalizeFunc) NULL,
2963 (GClassInitFunc) gdk_window_impl_quartz_class_init,
2964 NULL, /* class_finalize */
2965 NULL, /* class_data */
2966 sizeof (GdkWindowImplQuartz),
2967 0, /* n_preallocs */
2968 (GInstanceInitFunc) gdk_window_impl_quartz_init,
2971 const GInterfaceInfo paintable_info =
2973 (GInterfaceInitFunc) gdk_window_impl_quartz_paintable_init,
2978 object_type = g_type_register_static (GDK_TYPE_WINDOW_IMPL,
2979 "GdkWindowImplQuartz",
2981 g_type_add_interface_static (object_type,
2990 gdk_quartz_window_get_context (GdkWindowImplQuartz *window,
2993 if (!GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->get_context)
2995 g_warning ("%s doesn't implement GdkWindowImplQuartzClass::get_context()",
2996 G_OBJECT_TYPE_NAME (window));
3000 return GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->get_context (window, antialias);
3004 gdk_quartz_window_release_context (GdkWindowImplQuartz *window,
3005 CGContextRef cg_context)
3007 if (!GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->release_context)
3009 g_warning ("%s doesn't implement GdkWindowImplQuartzClass::release_context()",
3010 G_OBJECT_TYPE_NAME (window));
3014 GDK_WINDOW_IMPL_QUARTZ_GET_CLASS (window)->release_context (window, cg_context);
3020 gdk_root_window_impl_quartz_get_context (GdkWindowImplQuartz *window,
3023 CGColorSpaceRef colorspace;
3024 CGContextRef cg_context;
3025 GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (window);
3027 if (GDK_WINDOW_DESTROYED (window_impl->wrapper))
3030 /* We do not have the notion of a root window on OS X. We fake this
3031 * by creating a 1x1 bitmap and return a context to that.
3033 colorspace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
3034 cg_context = CGBitmapContextCreate (NULL,
3035 1, 1, 8, 4, colorspace,
3036 kCGImageAlphaPremultipliedLast);
3037 CGColorSpaceRelease (colorspace);
3043 gdk_root_window_impl_quartz_release_context (GdkWindowImplQuartz *window,
3044 CGContextRef cg_context)
3046 CGContextRelease (cg_context);
3050 gdk_root_window_impl_quartz_class_init (GdkRootWindowImplQuartzClass *klass)
3052 GdkWindowImplQuartzClass *window_quartz_class = GDK_WINDOW_IMPL_QUARTZ_CLASS (klass);
3054 root_window_parent_class = g_type_class_peek_parent (klass);
3056 drawable_quartz_class->get_context = gdk_root_window_impl_quartz_get_context;
3057 drawable_quartz_class->release_context = gdk_root_window_impl_quartz_release_context;
3059 impl_class->focus = gdk_quartz_window_focus;
3060 impl_class->set_type_hint = gdk_quartz_window_set_type_hint;
3061 impl_class->get_type_hint = gdk_quartz_window_get_type_hint;
3062 impl_class->set_modal_hint = gdk_quartz_window_set_modal_hint;
3063 impl_class->set_skip_taskbar_hint = gdk_quartz_window_set_skip_taskbar_hint;
3064 impl_class->set_skip_pager_hint = gdk_quartz_window_set_skip_pager_hint;
3065 impl_class->set_urgency_hint = gdk_quartz_window_set_urgency_hint;
3066 impl_class->set_geometry_hints = gdk_quartz_window_set_geometry_hints;
3067 impl_class->set_title = gdk_quartz_window_set_title;
3068 impl_class->set_role = gdk_quartz_window_set_role;
3069 impl_class->set_startup_id = _gdk_quartz_window_set_startup_id;
3070 impl_class->set_transient_for = gdk_quartz_window_set_transient_for;
3071 impl_class->get_root_origin = gdk_quartz_window_get_root_origin;
3072 impl_class->get_frame_extents = gdk_quartz_window_get_frame_extents;
3073 impl_class->set_override_redirect = gdk_quartz_window_set_override_redirect;
3074 impl_class->set_accept_focus = gdk_quartz_window_set_accept_focus;
3075 impl_class->set_focus_on_map = gdk_quartz_window_set_focus_on_map;
3076 impl_class->set_icon_list = gdk_quartz_window_set_icon_list;
3077 impl_class->set_icon_name = gdk_quartz_window_set_icon_name;
3078 impl_class->iconify = gdk_quartz_window_iconify;
3079 impl_class->deiconify = gdk_quartz_window_deiconify;
3080 impl_class->stick = gdk_quartz_window_stick;
3081 impl_class->unstick = gdk_quartz_window_unstick;
3082 impl_class->maximize = gdk_quartz_window_maximize;
3083 impl_class->unmaximize = gdk_quartz_window_unmaximize;
3084 impl_class->fullscreen = gdk_quartz_window_fullscreen;
3085 impl_class->unfullscreen = gdk_quartz_window_unfullscreen;
3086 impl_class->set_keep_above = gdk_quartz_window_set_keep_above;
3087 impl_class->set_keep_below = gdk_quartz_window_set_keep_below;
3088 impl_class->get_group = gdk_quartz_window_get_group;
3089 impl_class->set_group = gdk_quartz_window_set_group;
3090 impl_class->set_decorations = gdk_quartz_window_set_decorations;
3091 impl_class->get_decorations = gdk_quartz_window_get_decorations;
3092 impl_class->set_functions = gdk_quartz_window_set_functions;
3093 impl_class->set_functions = gdk_quartz_window_set_functions;
3094 impl_class->begin_resize_drag = gdk_quartz_window_begin_resize_drag;
3095 impl_class->begin_move_drag = gdk_quartz_window_begin_move_drag;
3096 impl_class->enable_synchronized_configure = gdk_quartz_window_enable_synchronized_configure;
3097 impl_class->configure_finished = gdk_quartz_window_configure_finished;
3098 impl_class->set_opacity = gdk_quartz_window_set_opacity;
3099 impl_class->destroy_notify = gdk_quartz_window_destroy_notify;
3100 impl_class->register_dnd = _gdk_quartz_window_register_dnd;
3101 impl_class->drag_begin = _gdk_quartz_window_drag_begin;
3102 impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
3106 gdk_root_window_impl_quartz_init (GdkRootWindowImplQuartz *impl)
3111 _gdk_root_window_impl_quartz_get_type (void)
3113 static GType object_type = 0;
3117 const GTypeInfo object_info =
3119 sizeof (GdkRootWindowImplQuartzClass),
3120 (GBaseInitFunc) NULL,
3121 (GBaseFinalizeFunc) NULL,
3122 (GClassInitFunc) gdk_root_window_impl_quartz_class_init,
3123 NULL, /* class_finalize */
3124 NULL, /* class_data */
3125 sizeof (GdkRootWindowImplQuartz),
3126 0, /* n_preallocs */
3127 (GInstanceInitFunc) gdk_root_window_impl_quartz_init,
3130 object_type = g_type_register_static (GDK_TYPE_WINDOW_IMPL_QUARTZ,
3131 "GdkRootWindowQuartz",