diff --git a/gdk/quartz/GdkQuartzWindow.c b/gdk/quartz/GdkQuartzWindow.c index 3fc35f83ea..6091e7a0b4 100644 --- a/gdk/quartz/GdkQuartzWindow.c +++ b/gdk/quartz/GdkQuartzWindow.c @@ -62,7 +62,7 @@ _gdk_quartz_update_focus_window (window, TRUE); } --(void)windowDidResignMain:(NSNotification *)aNotification +-(void)windowDidResignKey:(NSNotification *)aNotification { GdkWindow *window = [[self contentView] gdkWindow]; diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c index d19ea8848e..98bb4e140c 100644 --- a/gdk/quartz/gdkevents-quartz.c +++ b/gdk/quartz/gdkevents-quartz.c @@ -2,7 +2,7 @@ * * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * Copyright (C) 1998-2002 Tor Lillqvist - * Copyright (C) 2005 Imendio AB + * Copyright (C) 2005-2006 Imendio AB * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -369,8 +369,10 @@ gdk_keyboard_grab (GdkWindow *window, if (_gdk_quartz_keyboard_grab_window) { - generate_grab_broken_event (_gdk_quartz_keyboard_grab_window, - TRUE, FALSE, window); + if (_gdk_quartz_keyboard_grab_window != window) + generate_grab_broken_event (_gdk_quartz_keyboard_grab_window, + TRUE, FALSE, window); + g_object_unref (_gdk_quartz_keyboard_grab_window); } @@ -408,17 +410,17 @@ gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display, } static void -pointer_ungrab_internal (gboolean implicit) +pointer_ungrab_internal (gboolean only_if_implicit) { if (!_gdk_quartz_pointer_grab_window) return; - if (pointer_grab_implicit && !implicit) + if (only_if_implicit && !pointer_grab_implicit) return; g_object_unref (_gdk_quartz_pointer_grab_window); - _gdk_quartz_pointer_grab_window = NULL; + /* FIXME: Send crossing events */ } @@ -563,16 +565,6 @@ apply_filters (GdkWindow *window, return result; } -/* Returns the current keyboard window */ -static GdkWindow * -find_current_keyboard_window (void) -{ - if (_gdk_quartz_keyboard_grab_window && keyboard_grab_owner_events) - return _gdk_quartz_keyboard_grab_window; - - return current_keyboard_window; -} - /* This function checks if the passed in window is interested in the * event mask. If so, it's returned. If not, the event can be propagated * to its parent. @@ -709,17 +701,16 @@ _gdk_quartz_update_focus_window (GdkWindow *window, if (got_focus && window == current_keyboard_window) return; - /* FIXME: Don't do this when grabbed */ - - if (!got_focus) + /* FIXME: Don't do this when grabbed? Or make GdkQuartzWindow + * disallow it in the first place instead? + */ + + if (!got_focus && window == current_keyboard_window) { - if (window == current_keyboard_window) - { event = create_focus_event (current_keyboard_window, FALSE); append_event (event); g_object_unref (current_keyboard_window); current_keyboard_window = NULL; - } } if (got_focus) @@ -997,7 +988,7 @@ _gdk_quartz_send_map_events (GdkWindow *window) GdkWindow * _gdk_quartz_get_mouse_window (void) { - if (_gdk_quartz_pointer_grab_window) + if (_gdk_quartz_pointer_grab_window && !pointer_grab_owner_events) return _gdk_quartz_pointer_grab_window; return current_mouse_window; @@ -1150,6 +1141,8 @@ find_window_for_event (NSEvent *nsevent, gint *x, gint *y) return real_window; } + break; + case NSMouseEntered: { NSPoint point; @@ -1163,9 +1156,9 @@ find_window_for_event (NSEvent *nsevent, gint *x, gint *y) mouse_window = _gdk_quartz_find_child_window_by_point (toplevel, point.x, point.y, x, y); synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, *x, *y); - - break; } + break; + case NSMouseExited: synthesize_crossing_events (_gdk_root, GDK_CROSSING_NORMAL, nsevent, *x, *y); break; @@ -1174,18 +1167,13 @@ find_window_for_event (NSEvent *nsevent, gint *x, gint *y) case NSKeyUp: case NSFlagsChanged: { - GdkWindow *keyboard_window; GdkEventMask event_mask; - GdkWindow *real_window; if (_gdk_quartz_keyboard_grab_window && !keyboard_grab_owner_events) return _gdk_quartz_keyboard_grab_window; - keyboard_window = find_current_keyboard_window (); event_mask = get_event_mask_from_ns_event (nsevent); - real_window = find_window_interested_in_event_mask (keyboard_window, event_mask, TRUE); - - return real_window; + return find_window_interested_in_event_mask (current_keyboard_window, event_mask, TRUE); } break; @@ -1214,24 +1202,18 @@ create_button_event (GdkWindow *window, NSEvent *nsevent, case NSRightMouseDown: case NSOtherMouseDown: type = GDK_BUTTON_PRESS; - button = convert_mouse_button_number ([nsevent buttonNumber]); break; case NSLeftMouseUp: - type = GDK_BUTTON_RELEASE; - button = 1; - break; case NSRightMouseUp: - type = GDK_BUTTON_RELEASE; - button = 3; - break; case NSOtherMouseUp: type = GDK_BUTTON_RELEASE; - button = convert_mouse_button_number ([nsevent buttonNumber]); break; default: g_assert_not_reached (); } + button = convert_mouse_button_number ([nsevent buttonNumber]); + event = gdk_event_new (type); event->button.window = window; event->button.time = get_event_time (nsevent); @@ -1410,7 +1392,38 @@ gdk_event_translate (NSEvent *nsevent) return TRUE; } + /* Catch the case where the entire app loses focus, and break any grabs. */ + if ([nsevent type] == NSAppKitDefined) + { + if ([nsevent subtype] == NSApplicationDeactivatedEventType) + { + if (_gdk_quartz_keyboard_grab_window) + { + generate_grab_broken_event (_gdk_quartz_keyboard_grab_window, + TRUE, FALSE, + NULL); + g_object_unref (_gdk_quartz_keyboard_grab_window); + _gdk_quartz_keyboard_grab_window = NULL; + } + + if (_gdk_quartz_pointer_grab_window) + { + generate_grab_broken_event (_gdk_quartz_pointer_grab_window, + FALSE, pointer_grab_implicit, + NULL); + g_object_unref (_gdk_quartz_pointer_grab_window); + _gdk_quartz_pointer_grab_window = NULL; + } + } + } + window = find_window_for_event (nsevent, &x, &y); + + /* FIXME: During owner_event grabs, we don't find a window when there is a + * click on a no-window widget, which makes popups etc still stay up. Need + * to figure out why that is. + */ + if (!window) return FALSE; @@ -1424,13 +1437,23 @@ gdk_event_translate (NSEvent *nsevent) case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: - /* Emulate implicit grab */ - if (!_gdk_quartz_pointer_grab_window) - { - pointer_grab_internal (window, FALSE, GDK_WINDOW_OBJECT (window)->event_mask, - NULL, NULL, TRUE); - } + { + GdkEventMask event_mask; + /* Emulate implicit grab, when the window has both PRESS and RELEASE + * in its mask, like X (and make it owner_events since that's what + * implicit grabs are like). + */ + event_mask = (GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK); + if (!_gdk_quartz_pointer_grab_window && + (GDK_WINDOW_OBJECT (window)->event_mask & event_mask) == event_mask) + { + pointer_grab_internal (window, TRUE, + GDK_WINDOW_OBJECT (window)->event_mask, + NULL, NULL, TRUE); + } + } + event = create_button_event (window, nsevent, x, y); append_event (event); diff --git a/gdk/quartz/gdkkeys-quartz.c b/gdk/quartz/gdkkeys-quartz.c index bee7cc8113..c148c6d861 100644 --- a/gdk/quartz/gdkkeys-quartz.c +++ b/gdk/quartz/gdkkeys-quartz.c @@ -497,15 +497,14 @@ gdk_keymap_lookup_key (GdkKeymap *keymap, return 0; } - #define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)]) static guint translate_keysym (guint hardware_keycode, gint group, GdkModifierType state, - guint *effective_group, - guint *effective_level) + gint *effective_group, + gint *effective_level) { gint level; guint tmp_keyval; diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h index 88a1ae533e..0116852333 100644 --- a/gdk/quartz/gdkprivate-quartz.h +++ b/gdk/quartz/gdkprivate-quartz.h @@ -1,6 +1,6 @@ /* gdkwindow-quartz.c * - * Copyright (C) 2005 Imendio AB + * Copyright (C) 2005-2006 Imendio AB * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,8 +21,6 @@ #ifndef __GDK_PRIVATE_QUARTZ_H__ #define __GDK_PRIVATE_QUARTZ_H__ -#include - #define GDK_QUARTZ_ALLOC_POOL NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init] #define GDK_QUARTZ_RELEASE_POOL [pool release] @@ -34,6 +32,8 @@ #include "gdkinternals.h" +#include + #define GDK_TYPE_GC_QUARTZ (_gdk_gc_quartz_get_type ()) #define GDK_GC_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_GC_QUARTZ, GdkGCQuartz)) #define GDK_GC_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GC_QUARTZ, GdkGCQuartzClass)) @@ -117,14 +117,14 @@ GdkWindow *_gdk_quartz_get_mouse_window (void); void _gdk_quartz_update_mouse_window (GdkWindow *window); void _gdk_quartz_update_cursor (GdkWindow *window); -GdkImage *_gdk_quartz_copy_to_image (GdkDrawable *drawable, - GdkImage *image, - gint src_x, - gint src_y, - gint dest_x, - gint dest_y, - gint width, - gint height); +GdkImage *_gdk_quartz_copy_to_image (GdkDrawable *drawable, + GdkImage *image, + gint src_x, + gint src_y, + gint dest_x, + gint dest_y, + gint width, + gint height); void _gdk_quartz_send_map_events (GdkWindow *window); diff --git a/gdk/quartz/gdkselection-quartz.c b/gdk/quartz/gdkselection-quartz.c index ddc4f08b1d..8724405a7e 100644 --- a/gdk/quartz/gdkselection-quartz.c +++ b/gdk/quartz/gdkselection-quartz.c @@ -23,6 +23,7 @@ #include #include "gdkselection.h" +#include "gdkproperty.h" gboolean gdk_selection_owner_set_for_display (GdkDisplay *display, diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c index b5dfffa620..7bed32a08b 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -514,9 +514,6 @@ gdk_window_new (GdkWindow *parent, else title = get_default_title (); - if (attributes->window_type == GDK_WINDOW_TEMP) - [impl->toplevel setLevel:NSPopUpMenuWindowLevel]; - gdk_window_set_title (window, title); if (draw_impl->colormap == gdk_screen_get_rgba_colormap (_gdk_screen)) @@ -635,8 +632,6 @@ show_window_internal (GdkWindow *window, gboolean raise) private = (GdkWindowObject *)window; impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); - /* FIXME: We need to raise the window (move it to the top in the list) */ - if (impl->toplevel) { [impl->toplevel orderFront:nil]; @@ -1350,12 +1345,81 @@ void gdk_window_set_type_hint (GdkWindow *window, GdkWindowTypeHint hint) { + GdkWindowImplQuartz *impl; + gint level; + gboolean shadow; + g_return_if_fail (GDK_IS_WINDOW (window)); if (GDK_WINDOW_DESTROYED (window)) return; - GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl)->type_hint = hint; + impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl); + + impl->type_hint = hint; + + /* Match the documentation, only do something if we're not mapped yet. */ + if (GDK_WINDOW_IS_MAPPED (window)) + return; + + switch (hint) + { + case GDK_WINDOW_TYPE_HINT_NORMAL: /* Normal toplevel window */ + case GDK_WINDOW_TYPE_HINT_DIALOG: /* Dialog window */ + case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */ + case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */ + level = NSNormalWindowLevel; + shadow = TRUE; + break; + + case GDK_WINDOW_TYPE_HINT_DOCK: + case GDK_WINDOW_TYPE_HINT_UTILITY: + level = NSFloatingWindowLevel; + shadow = TRUE; + break; + + case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */ + level = NSTornOffMenuWindowLevel; + shadow = TRUE; + break; + + case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */ + level = NSSubmenuWindowLevel; + shadow = TRUE; + break; + + case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN: + level = NSPopUpMenuWindowLevel; + shadow = TRUE; + break; + + case GDK_WINDOW_TYPE_HINT_POPUP_MENU: + case GDK_WINDOW_TYPE_HINT_COMBO: + level = NSPopUpMenuWindowLevel; + shadow = TRUE; + break; + + case GDK_WINDOW_TYPE_HINT_NOTIFICATION: + case GDK_WINDOW_TYPE_HINT_TOOLTIP: + level = NSStatusWindowLevel; + shadow = TRUE; + break; + + case GDK_WINDOW_TYPE_HINT_DND: + level = NSPopUpMenuWindowLevel; + shadow = FALSE; + break; + + default: + level = NSNormalWindowLevel; + shadow = FALSE; + break; + } + + /* Note: The shadow should probably be handled in a theme: + [impl->toplevel setHasShadow:shadow]; + */ + [impl->toplevel setLevel:level]; } GdkWindowTypeHint