diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c index a5ffa58120..23c1b6f184 100644 --- a/gdk/quartz/gdkevents-quartz.c +++ b/gdk/quartz/gdkevents-quartz.c @@ -160,7 +160,16 @@ void gdk_display_pointer_ungrab (GdkDisplay *display, guint32 time) { - _gdk_display_unset_has_pointer_grab (display, FALSE, FALSE, time); + GdkPointerGrabInfo *grab; + + grab = _gdk_display_get_last_pointer_grab (display); + if (grab) + { + /* Serials are always 0 in quartz, but for clarity: */ + grab->serial_end = 0; + } + + _gdk_display_pointer_grab_update (display, 0); } GdkGrabStatus @@ -171,21 +180,29 @@ gdk_pointer_grab (GdkWindow *window, GdkCursor *cursor, guint32 time) { - GdkWindow *toplevel; + GdkWindow *native; g_return_val_if_fail (GDK_IS_WINDOW (window), 0); g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0); - toplevel = gdk_window_get_toplevel (window); + native = gdk_window_get_toplevel (window); - _gdk_display_set_has_pointer_grab (_gdk_display, - window, - toplevel, - owner_events, - event_mask, - 0, - time, - FALSE); + /* TODO: What do we do for offscreens and their children? We need to proxy the grab somehow */ + if (!GDK_IS_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (native)->impl)) + return GDK_GRAB_SUCCESS; + + if (!_gdk_window_has_impl (window) && + !gdk_window_is_viewable (window)) + return GDK_GRAB_NOT_VIEWABLE; + + _gdk_display_add_pointer_grab (_gdk_display, + window, + native, + owner_events, + event_mask, + 0, + time, + FALSE); return GDK_GRAB_SUCCESS; } @@ -193,14 +210,20 @@ gdk_pointer_grab (GdkWindow *window, static void break_all_grabs (guint32 time) { + GdkPointerGrabInfo *grab; + if (_gdk_display->keyboard_grab.window) _gdk_display_unset_has_keyboard_grab (_gdk_display, FALSE); - if (_gdk_display->pointer_grab.window) - _gdk_display_unset_has_pointer_grab (_gdk_display, - TRUE, - FALSE, - time); + grab = _gdk_display_get_last_pointer_grab (_gdk_display); + if (grab) + { + /* Serials are always 0 in quartz, but for clarity: */ + grab->serial_end = 0; + grab->implicit_ungrab = TRUE; + } + + _gdk_display_pointer_grab_update (_gdk_display, 0); } static void @@ -457,11 +480,14 @@ _gdk_quartz_events_send_map_event (GdkWindow *window) GdkWindow * _gdk_quartz_events_get_mouse_window (gboolean consider_grabs) { + GdkPointerGrabInfo *grab; + if (!consider_grabs) return current_mouse_window; - if (_gdk_display->pointer_grab.window && !_gdk_display->pointer_grab.owner_events) - return _gdk_display->pointer_grab.window; + grab = _gdk_display_get_last_pointer_grab (_gdk_display); + if (grab && grab->window && !grab->owner_events) + return grab->window; return current_mouse_window; } @@ -754,6 +780,7 @@ find_window_for_ns_event (NSEvent *nsevent, case NSOtherMouseDragged: { GdkDisplay *display; + GdkPointerGrabInfo *grab; display = gdk_drawable_get_display (toplevel); @@ -769,20 +796,21 @@ find_window_for_ns_event (NSEvent *nsevent, * This means we first try the owner, then the grab window, * then give up. */ - if (display->pointer_grab.window) + grab = _gdk_display_get_last_pointer_grab (display); + if (grab && grab->window) { - if (display->pointer_grab.owner_events) + if (grab->owner_events) return toplevel; /* Finally check the grab window. */ - if (display->pointer_grab.event_mask & get_event_mask_from_ns_event (nsevent)) + if (grab->event_mask & get_event_mask_from_ns_event (nsevent)) { GdkWindow *grab_toplevel; GdkWindowObject *grab_private; NSPoint point; NSWindow *grab_nswindow; - grab_toplevel = gdk_window_get_toplevel (display->pointer_grab.window); + grab_toplevel = gdk_window_get_toplevel (grab->window); grab_private = (GdkWindowObject *)grab_toplevel; point = [[nsevent window] convertBaseToScreen:[nsevent locationInWindow]]; @@ -1182,50 +1210,6 @@ _gdk_quartz_events_get_current_event_mask (void) return current_event_mask; } -#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \ - GDK_BUTTON2_MASK | \ - GDK_BUTTON3_MASK | \ - GDK_BUTTON4_MASK | \ - GDK_BUTTON5_MASK) - -static void -button_event_check_implicit_grab (GdkWindow *window, - GdkEvent *event, - NSEvent *nsevent) -{ - GdkDisplay *display = gdk_drawable_get_display (window); - - /* track implicit grabs for button presses */ - switch (event->type) - { - case GDK_BUTTON_PRESS: - if (!display->pointer_grab.window) - { - _gdk_display_set_has_pointer_grab (display, - window, - window, - FALSE, - gdk_window_get_events (window), - 0, /* serial */ - event->button.time, - TRUE); - } - break; - - case GDK_BUTTON_RELEASE: - if (display->pointer_grab.window && - display->pointer_grab.implicit && - (current_button_state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0) - { - _gdk_display_unset_has_pointer_grab (display, TRUE, TRUE, - event->button.time); - } - break; - default: - g_assert_not_reached (); - } -} - static gboolean gdk_event_translate (GdkEvent *event, NSEvent *nsevent) @@ -1374,14 +1358,12 @@ gdk_event_translate (GdkEvent *event, case NSRightMouseDown: case NSOtherMouseDown: fill_button_event (window, event, nsevent, x, y, x_root, y_root); - button_event_check_implicit_grab (window, event, nsevent); break; case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: fill_button_event (window, event, nsevent, x, y, x_root, y_root); - button_event_check_implicit_grab (window, event, nsevent); break; case NSLeftMouseDragged: diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c index f6ab1fcd20..814bcacc58 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -138,11 +138,53 @@ gdk_window_impl_quartz_get_context (GdkDrawable *drawable, return cg_context; } +static void +check_grab_unmap (GdkWindow *window) +{ + GdkDisplay *display = gdk_drawable_get_display (window); + + _gdk_display_end_pointer_grab (display, 0, window, TRUE); + + if (display->keyboard_grab.window) + { + GdkWindowObject *private = GDK_WINDOW_OBJECT (window); + GdkWindowObject *tmp = GDK_WINDOW_OBJECT (display->keyboard_grab.window); + + while (tmp && tmp != private) + tmp = tmp->parent; + + if (tmp) + _gdk_display_unset_has_keyboard_grab (display, TRUE); + } +} + +static void +check_grab_destroy (GdkWindow *window) +{ + GdkDisplay *display = gdk_drawable_get_display (window); + GdkPointerGrabInfo *grab; + + /* Make sure there is no lasting grab in this native window */ + grab = _gdk_display_get_last_pointer_grab (display); + if (grab && grab->native_window == window) + { + /* Serials are always 0 in quartz, but for clarity: */ + grab->serial_end = grab->serial_start; + grab->implicit_ungrab = TRUE; + } + + if (window == display->keyboard_grab.native_window && + display->keyboard_grab.window != NULL) + _gdk_display_unset_has_keyboard_grab (display, TRUE); +} + static void gdk_window_impl_quartz_finalize (GObject *object) { GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (object); + check_grab_destroy (GDK_DRAWABLE_IMPL_QUARTZ (object)->wrapper); + if (impl->nscursor) [impl->nscursor release]; @@ -950,15 +992,6 @@ _gdk_quartz_window_destroy (GdkWindow *window, parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window); } - /* If the destroyed window was targeted for a pointer or keyboard - * grab, release the grab. - */ - if (window == _gdk_display->pointer_grab.window) - gdk_pointer_ungrab (0); - - if (window == _gdk_display->keyboard_grab.window) - gdk_keyboard_ungrab (0); - _gdk_quartz_drawable_finish (GDK_DRAWABLE (impl)); mouse_window = _gdk_quartz_events_get_mouse_window (FALSE); @@ -1096,6 +1129,8 @@ gdk_window_quartz_hide (GdkWindow *window) if (get_fullscreen_geometry (window)) SetSystemUIMode (kUIModeNormal, 0); + check_grab_unmap (window); + mouse_window = _gdk_quartz_events_get_mouse_window (FALSE); if (window == mouse_window || _gdk_quartz_window_is_ancestor (window, mouse_window)) @@ -1121,12 +1156,6 @@ gdk_window_quartz_hide (GdkWindow *window) { [impl->view setHidden:YES]; } - - if (window == _gdk_display->pointer_grab.window) - gdk_pointer_ungrab (0); - - if (window == _gdk_display->keyboard_grab.window) - gdk_keyboard_ungrab (0); } void @@ -2809,6 +2838,7 @@ gdk_window_configure_finished (GdkWindow *window) void gdk_window_destroy_notify (GdkWindow *window) { + check_grab_destroy (window); } void