diff --git a/gdk/quartz/gdkdevice-core-quartz.c b/gdk/quartz/gdkdevice-core-quartz.c index a8fd34f224..4fd2ae940c 100644 --- a/gdk/quartz/gdkdevice-core-quartz.c +++ b/gdk/quartz/gdkdevice-core-quartz.c @@ -228,11 +228,9 @@ gdk_quartz_device_core_query_state_helper (GdkWindow *window, } else { - GdkWindowImplQuartz *impl; NSWindow *nswindow; - impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl); - nswindow = impl->toplevel; + nswindow = gdk_quartz_window_search_for_nearest_nswindow (window); point = [nswindow mouseLocationOutsideOfEventStream]; diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c index 1b43add865..891dfd4cea 100644 --- a/gdk/quartz/gdkevents-quartz.c +++ b/gdk/quartz/gdkevents-quartz.c @@ -387,7 +387,7 @@ get_window_point_from_screen_point (GdkWindow *window, NSPoint point; GdkQuartzNSWindow *nswindow; - nswindow = (GdkQuartzNSWindow*)(((GdkWindowImplQuartz *)window->impl)->toplevel); + nswindow = gdk_quartz_window_search_for_nearest_nswindow (window); point = [nswindow convertPointFromScreen:screen_point]; *x = point.x; *y = window->height - point.y; @@ -658,18 +658,25 @@ find_toplevel_under_pointer (GdkDisplay *display, } - if (toplevel) - { - get_window_point_from_screen_point (toplevel, screen_point, x, y); - /* If the coordinates are out of window bounds, this toplevel is not - * under the pointer and we thus return NULL. This can occur when - * toplevel under pointer has not yet been updated due to a very recent - * window resize. Alternatively, we should no longer be relying on - * the toplevel_under_pointer value which is maintained in gdkwindow.c. - */ - if (*x < 0 || *y < 0 || *x >= toplevel->width || *y >= toplevel->height) - return NULL; - } + if (toplevel == NULL) + return NULL; + + /* + * Root window type does not need translation, but also does not have + * an associated NSWindow and therefore can't translate screen points + */ + if (toplevel == _gdk_root) + return toplevel; + + get_window_point_from_screen_point (toplevel, screen_point, x, y); + /* If the coordinates are out of window bounds, this toplevel is not + * under the pointer and we thus return NULL. This can occur when + * toplevel under pointer has not yet been updated due to a very recent + * window resize. Alternatively, we should no longer be relying on + * the toplevel_under_pointer value which is maintained in gdkwindow.c. + */ + if (*x < 0 || *y < 0 || *x >= toplevel->width || *y >= toplevel->height) + return NULL; return toplevel; } @@ -793,7 +800,7 @@ find_toplevel_for_mouse_event (NSEvent *nsevent, toplevel = toplevel_under_pointer; - toplevel_impl = (GdkWindowImplQuartz *)toplevel->impl; + toplevel_impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl); *x = x_tmp; *y = y_tmp; @@ -1405,7 +1412,7 @@ test_resize (NSEvent *event, GdkWindow *toplevel, gint x, gint y) /* Resizing from the resize indicator only begins if an GDK_QUARTZ_LEFT_MOUSE_BUTTON * event is received in the resizing area. */ - toplevel_impl = (GdkWindowImplQuartz *)toplevel->impl; + toplevel_impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl); if ([toplevel_impl->toplevel showsResizeIndicator]) if ([event type] == GDK_QUARTZ_LEFT_MOUSE_DOWN && [toplevel_impl->toplevel showsResizeIndicator]) diff --git a/gdk/quartz/gdkglcontext-quartz.c b/gdk/quartz/gdkglcontext-quartz.c index a244d66e43..ddd18e1e7c 100644 --- a/gdk/quartz/gdkglcontext-quartz.c +++ b/gdk/quartz/gdkglcontext-quartz.c @@ -28,7 +28,7 @@ #include "gdkquartzglcontext.h" #include "gdkquartzwindow.h" #include "gdkprivate-quartz.h" -#include "gdkquartz-cocoa-access.h" +#include "gdkinternal-quartz.h" #include "gdkinternals.h" @@ -138,7 +138,7 @@ gdk_quartz_window_create_gl_context (GdkWindow *window, if (attached) { - NSView *view = gdk_quartz_window_get_nsview (window); + NSView *view = gdk_quartz_window_search_for_nearest_nsview (window); if ([view respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) [view setWantsBestResolutionOpenGLSurface:YES]; diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c index 4419975dc4..a9bc6c6504 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -125,22 +125,74 @@ gdk_quartz_window_init (GdkQuartzWindow *quartz_window) * GdkQuartzWindowImpl */ -NSView * -gdk_quartz_window_get_nsview (GdkWindow *window) +static inline NSObject * +gdk_quartz_window_search_for_nearest_nsobject (GdkWindow *window, bool get_nswindow_instead_of_nsview) { + GdkWindow *onscreen_window = window; + NSObject *nsobject = NULL; + if (GDK_WINDOW_DESTROYED (window)) return NULL; - return ((GdkWindowImplQuartz *)window->impl)->view; + /* + * if window is type GDK_WINDOW_OFFSCREEN + * you need to get the embedder in order to find the NSView + * see: gdkdevice.c:1461 + */ + while (1) + { + g_return_val_if_fail (onscreen_window != NULL, NULL); + + if (GDK_IS_WINDOW_IMPL_QUARTZ (onscreen_window->impl)) + { + if (get_nswindow_instead_of_nsview) + nsobject = GDK_WINDOW_IMPL_QUARTZ (onscreen_window->impl)->toplevel; + else + nsobject = GDK_WINDOW_IMPL_QUARTZ (onscreen_window->impl)->view; + + if (nsobject != NULL) + break; + } + + if (onscreen_window->window_type == GDK_WINDOW_OFFSCREEN) + onscreen_window = gdk_offscreen_window_get_embedder (onscreen_window); + else + onscreen_window = onscreen_window->parent; + } + + g_return_val_if_fail (nsobject != NULL, NULL); + + return nsobject; +} + +NSView * +gdk_quartz_window_search_for_nearest_nsview (GdkWindow *window) +{ + return (NSView *)gdk_quartz_window_search_for_nearest_nsobject (window, FALSE); +} + +NSWindow * +gdk_quartz_window_search_for_nearest_nswindow (GdkWindow *window) +{ + return (NSWindow *)gdk_quartz_window_search_for_nearest_nsobject (window, TRUE); +} + +NSView * +gdk_quartz_window_get_nsview (GdkWindow *window) +{ + if (GDK_WINDOW_DESTROYED (window) || !GDK_IS_WINDOW_IMPL_QUARTZ (window->impl)) + return NULL; + + return GDK_WINDOW_IMPL_QUARTZ (window->impl)->view; } NSWindow * gdk_quartz_window_get_nswindow (GdkWindow *window) { - if (GDK_WINDOW_DESTROYED (window)) + if (GDK_WINDOW_DESTROYED (window) || !GDK_IS_WINDOW_IMPL_QUARTZ (window->impl)) return NULL; - return ((GdkWindowImplQuartz *)window->impl)->toplevel; + return GDK_WINDOW_IMPL_QUARTZ (window->impl)->toplevel; } static CGContextRef @@ -220,9 +272,12 @@ gdk_window_impl_quartz_finalize (GObject *object) g_object_unref (impl->transient_for); if (impl->view) - [[NSNotificationCenter defaultCenter] removeObserver: impl->toplevel - name: @"NSViewFrameDidChangeNotification" - object: impl->view]; + { + [[NSNotificationCenter defaultCenter] removeObserver: impl->toplevel + name: @"NSViewFrameDidChangeNotification" + object: impl->view]; + [impl->view release]; + } G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -319,6 +374,8 @@ static void gdk_window_impl_quartz_init (GdkWindowImplQuartz *impl) { impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL; + impl->view = NULL; + impl->toplevel = NULL; } static gboolean @@ -369,7 +426,7 @@ _gdk_quartz_window_process_updates_recurse (GdkWindow *window, GdkWindowImplQuartz *toplevel_impl; NSWindow *nswindow; - toplevel_impl = (GdkWindowImplQuartz *)toplevel->impl; + toplevel_impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl); nswindow = toplevel_impl->toplevel; #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 /* In theory, we could skip the flush disabling, since we only @@ -877,9 +934,6 @@ _gdk_quartz_display_create_window_impl (GdkDisplay *display, (attributes->cursor) : NULL)); - impl->view = NULL; - impl->toplevel = NULL; - if (attributes_mask & GDK_WA_TYPE_HINT) { type_hint = attributes->type_hint; @@ -959,7 +1013,6 @@ _gdk_quartz_display_create_window_impl (GdkDisplay *display, selector: @selector (windowDidResize:) name: @"NSViewFrameDidChangeNotification" object: impl->view]; - [impl->view release]; } break; @@ -981,7 +1034,6 @@ _gdk_quartz_display_create_window_impl (GdkDisplay *display, /* GdkWindows should be hidden by default */ [impl->view setHidden:YES]; [parent_impl->view addSubview:impl->view]; - [impl->view release]; } } break; @@ -1580,7 +1632,7 @@ gdk_window_quartz_raise (GdkWindow *window) { GdkWindowImplQuartz *impl; - impl = (GdkWindowImplQuartz *)parent->impl; + impl = GDK_WINDOW_IMPL_QUARTZ (parent->impl); impl->sorted_children = g_list_remove (impl->sorted_children, window); impl->sorted_children = g_list_prepend (impl->sorted_children, window); @@ -1611,7 +1663,7 @@ gdk_window_quartz_lower (GdkWindow *window) { GdkWindowImplQuartz *impl; - impl = (GdkWindowImplQuartz *)parent->impl; + impl = GDK_WINDOW_IMPL_QUARTZ (parent->impl); impl->sorted_children = g_list_remove (impl->sorted_children, window); impl->sorted_children = g_list_append (impl->sorted_children, window); diff --git a/gdk/quartz/gdkwindow-quartz.h b/gdk/quartz/gdkwindow-quartz.h index de9a5ebccf..34e64855a5 100644 --- a/gdk/quartz/gdkwindow-quartz.h +++ b/gdk/quartz/gdkwindow-quartz.h @@ -87,6 +87,11 @@ CGContextRef gdk_quartz_window_get_context (GdkWindowImplQuartz *window, void gdk_quartz_window_release_context (GdkWindowImplQuartz *window, CGContextRef context); +_GDK_EXTERN /* Required for immmodule.cache */ +NSView * gdk_quartz_window_search_for_nearest_nsview (GdkWindow *window); +_GDK_EXTERN /* Required for immmodule.cache */ +NSWindow * gdk_quartz_window_search_for_nearest_nswindow (GdkWindow *window); + /* Root window implementation for Quartz */ diff --git a/gtk/gtkdnd-quartz.c b/gtk/gtkdnd-quartz.c index 3460de6edd..225c9353d2 100644 --- a/gtk/gtkdnd-quartz.c +++ b/gtk/gtkdnd-quartz.c @@ -42,7 +42,7 @@ #include "gtkintl.h" #include "gtkquartz.h" #include "gdk/quartz/gdkquartz.h" -#include "gdk/quartz/gdkquartz-cocoa-access.h" +#include "gdk/quartz/gdkinternal-quartz.h" #include "gdk/quartz/gdkquartz-gtk-only.h" #include "gdk/quartz/gdkquartzdnd.h" #include "gtkselectionprivate.h" @@ -364,7 +364,7 @@ get_toplevel_nswindow (GtkWidget *widget) return NULL; if (gtk_widget_is_toplevel (toplevel) && window) - return [gdk_quartz_window_get_nsview (window) window]; + return [gdk_quartz_window_search_for_nearest_nsview (window) window]; else return NULL; } diff --git a/gtk/gtkfilechoosernativequartz.c b/gtk/gtkfilechoosernativequartz.c index fb5abd5390..e295143b97 100644 --- a/gtk/gtkfilechoosernativequartz.c +++ b/gtk/gtkfilechoosernativequartz.c @@ -40,7 +40,7 @@ #include "gtklabel.h" #include "gtkfilechooserentry.h" #include "gtkfilefilterprivate.h" -#include +#include "gdk/quartz/gdkinternal-quartz.h" #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 typedef struct { @@ -533,7 +533,7 @@ gtk_file_chooser_native_quartz_show (GtkFileChooserNative *self) if (transient_for) { gtk_widget_realize (GTK_WIDGET (transient_for)); - data->parent = gdk_quartz_window_get_nswindow (gtk_widget_get_window (GTK_WIDGET (transient_for))); + data->parent = gdk_quartz_window_search_for_nearest_nswindow (gtk_widget_get_window (GTK_WIDGET (transient_for))); if (gtk_native_dialog_get_modal (GTK_NATIVE_DIALOG (self))) data->modal = TRUE; diff --git a/modules/input/imquartz.c b/modules/input/imquartz.c index bdee6da2f4..084e04f603 100644 --- a/modules/input/imquartz.c +++ b/modules/input/imquartz.c @@ -227,7 +227,7 @@ quartz_filter_keypress (GtkIMContext *context, return gtk_im_context_filter_keypress (qc->slave, event); } - nsview = gdk_quartz_window_get_nsview (qc->client_window); + nsview = gdk_quartz_window_search_for_nearest_nsview (qc->client_window); win = (GdkWindow *)[(GdkQuartzView *)[[nsevent window] contentView] gdkWindow]; GTK_NOTE (MISC, g_print ("client_window: %p, win: %p, nsview: %p\n", @@ -272,7 +272,7 @@ discard_preedit (GtkIMContext *context) if (!GDK_IS_QUARTZ_WINDOW (qc->client_window)) return; - NSView *nsview = gdk_quartz_window_get_nsview (qc->client_window); + NSView *nsview = gdk_quartz_window_search_for_nearest_nsview (qc->client_window); if (!nsview) return; @@ -361,8 +361,17 @@ quartz_set_cursor_location (GtkIMContext *context, GdkRectangle *area) if (!GDK_IS_QUARTZ_WINDOW (qc->client_window)) return; - nsview = gdk_quartz_window_get_nsview (qc->client_window); - win = (GdkWindow *)[ (GdkQuartzView*)nsview gdkWindow]; + nsview = gdk_quartz_window_search_for_nearest_nsview (qc->client_window); + if (nsview == NULL) + return; + + win = (GdkWindow *)[(GdkQuartzView*)nsview gdkWindow]; + if (win == NULL) + { + g_warning ("quartz_set_cursor_location received NULL gdkWindow"); + return; + } + g_object_set_data (G_OBJECT (win), GIC_CURSOR_RECT, qc->cursor_rect); }