diff options
author | Richard Hult <richard@imendio.com> | 2006-07-07 20:19:22 +0000 |
---|---|---|
committer | Richard Hult <rhult@src.gnome.org> | 2006-07-07 20:19:22 +0000 |
commit | 2fbe2ebc9a400eff74f31254c95d5f6bc8b05454 (patch) | |
tree | 49a6801b9e40e12893e0db1ea43a74c1304a66eb /gdk/quartz | |
parent | ca752b0f854870bfd34133c51e79780c2c147c9f (diff) | |
download | gtk+-2fbe2ebc9a400eff74f31254c95d5f6bc8b05454.tar.gz |
Generate a grab broken event when appropriate. Fixes bug #346603, patch
2006-07-07 Richard Hult <richard@imendio.com>
* gdk/quartz/gdkevents-quartz.c: Generate a grab broken event when
appropriate. Fixes bug #346603, patch from Dave Vasilevsky.
* gdk/quartz/gdkevents-quartz.c:
* gdk/quartz/gdkkeys-quartz.c:
* gdk/quartz/gdkprivate-quartz.c: Another patch from Dave Vasilevsky,
fixes bug #346605. Makes modifier key events being sent properly.
Diffstat (limited to 'gdk/quartz')
-rw-r--r-- | gdk/quartz/gdkevents-quartz.c | 92 | ||||
-rw-r--r-- | gdk/quartz/gdkkeys-quartz.c | 87 | ||||
-rw-r--r-- | gdk/quartz/gdkprivate-quartz.h | 2 |
3 files changed, 132 insertions, 49 deletions
diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c index 9f72be90b6..d533d353cf 100644 --- a/gdk/quartz/gdkevents-quartz.c +++ b/gdk/quartz/gdkevents-quartz.c @@ -333,6 +333,28 @@ gdk_event_get_graphics_expose (GdkWindow *window) return NULL; } +static void +generate_grab_broken_event (GdkWindow *window, + gboolean keyboard, + gboolean implicit, + GdkWindow *grab_window) +{ + if (!GDK_WINDOW_DESTROYED (window)) + { + GdkEvent event; + + event.type = GDK_GRAB_BROKEN; + event.grab_broken.window = window; + event.grab_broken.send_event = 0; + event.grab_broken.keyboard = keyboard; + event.grab_broken.implicit = implicit; + event.grab_broken.grab_window = grab_window; + + gdk_event_put (&event); + } +} + + GdkGrabStatus gdk_keyboard_grab (GdkWindow *window, gint owner_events, @@ -342,7 +364,11 @@ gdk_keyboard_grab (GdkWindow *window, g_return_val_if_fail (GDK_IS_WINDOW (window), 0); if (_gdk_quartz_keyboard_grab_window) - gdk_keyboard_ungrab (time); + { + generate_grab_broken_event (_gdk_quartz_keyboard_grab_window, + TRUE, FALSE, window); + g_object_unref (_gdk_quartz_keyboard_grab_window); + } _gdk_quartz_keyboard_grab_window = g_object_ref (window); keyboard_grab_owner_events = owner_events; @@ -454,10 +480,15 @@ gdk_pointer_grab (GdkWindow *window, if (_gdk_quartz_pointer_grab_window) { - if (!pointer_grab_implicit) - return GDK_GRAB_ALREADY_GRABBED; + if (_gdk_quartz_pointer_grab_window == window && !pointer_grab_implicit) + return GDK_GRAB_ALREADY_GRABBED; else - pointer_ungrab_internal (TRUE); + { + if (_gdk_quartz_pointer_grab_window != window) + generate_grab_broken_event (_gdk_quartz_pointer_grab_window, + FALSE, pointer_grab_implicit, window); + pointer_ungrab_internal (TRUE); + } } return pointer_grab_internal (window, owner_events, event_mask, @@ -680,9 +711,18 @@ get_event_mask_from_ns_event (NSEvent *nsevent) return mask; } case NSKeyDown: - return GDK_KEY_PRESS_MASK; case NSKeyUp: - return GDK_KEY_RELEASE_MASK; + case NSFlagsChanged: + { + GdkEventType type = _gdk_quartz_key_event_type (nsevent); + switch (type) + { + case GDK_KEY_PRESS: return GDK_KEY_PRESS_MASK; + case GDK_KEY_RELEASE: return GDK_KEY_RELEASE_MASK; + case GDK_NOTHING: return 0; + default: g_assert_not_reached (); + } + } default: g_assert_not_reached (); } @@ -1137,6 +1177,7 @@ find_window_for_event (NSEvent *nsevent, gint *x, gint *y) case NSKeyDown: case NSKeyUp: + case NSFlagsChanged: { GdkWindow *keyboard_window; GdkEventMask event_mask; @@ -1274,24 +1315,11 @@ create_scroll_event (GdkWindow *window, NSEvent *nsevent, GdkScrollDirection dir } static GdkEvent * -create_key_event (GdkWindow *window, NSEvent *nsevent) +create_key_event (GdkWindow *window, NSEvent *nsevent, GdkEventType type) { - GdkEventType event_type; GdkEvent *event; - switch ([nsevent type]) - { - case NSKeyDown: - event_type = GDK_KEY_PRESS; - break; - case NSKeyUp: - event_type = GDK_KEY_RELEASE; - break; - default: - g_assert_not_reached (); - } - - event = gdk_event_new (event_type); + event = gdk_event_new (type); event->key.window = window; event->key.time = get_event_time (nsevent); event->key.state = get_keyboard_modifiers_from_nsevent (nsevent); @@ -1305,6 +1333,12 @@ create_key_event (GdkWindow *window, NSEvent *nsevent) &event->key.keyval, NULL, NULL, NULL); + GDK_NOTE(EVENTS, + g_message ("key %s:\t\twindow: %p key: %12s %d", + type == GDK_KEY_PRESS ? "press" : "release", + event->key.window, + event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)", + event->key.keyval)); return event; } @@ -1425,11 +1459,17 @@ gdk_event_translate (NSEvent *nsevent) } case NSKeyDown: case NSKeyUp: - event = create_key_event (window, nsevent); - append_event (event); - return TRUE; - break; - + case NSFlagsChanged: + { + GdkEventType type = _gdk_quartz_key_event_type (nsevent); + if (type == GDK_NOTHING) + return FALSE; + + event = create_key_event (window, nsevent, type); + append_event (event); + return TRUE; + break; + } default: NSLog(@"Untranslated: %@", nsevent); } diff --git a/gdk/quartz/gdkkeys-quartz.c b/gdk/quartz/gdkkeys-quartz.c index 0ce4c92184..f3bc8283e8 100644 --- a/gdk/quartz/gdkkeys-quartz.c +++ b/gdk/quartz/gdkkeys-quartz.c @@ -52,6 +52,7 @@ #include <config.h> #include <Carbon/Carbon.h> +#include <AppKit/NSEvent.h> #include "gdk.h" #include "gdkkeysyms.h" @@ -102,30 +103,32 @@ macroman2ucs (unsigned char c) const static struct { guint keycode; guint keyval; + unsigned int modmask; /* So we can tell when a mod key is pressed/released */ } known_keys[] = { - { 55, GDK_Meta_L }, - { 56, GDK_Shift_L }, - { 57, GDK_Caps_Lock }, - { 58, GDK_Alt_L }, - { 59, GDK_Control_L }, - { 60, GDK_Shift_R }, - { 61, GDK_Alt_R }, - { 62, GDK_Control_R }, - { 122, GDK_F1 }, - { 120, GDK_F2 }, - { 99, GDK_F3 }, - { 118, GDK_F4 }, - { 96, GDK_F5 }, - { 97, GDK_F6 }, - { 98, GDK_F7 }, - { 100, GDK_F8 }, - { 101, GDK_F9 }, - { 109, GDK_F10 }, - { 103, GDK_F11 }, - { 111, GDK_F12 }, - { 105, GDK_F13 }, - { 107, GDK_F14 }, - { 113, GDK_F15 }, + { 54, GDK_Meta_R, NSCommandKeyMask }, + { 55, GDK_Meta_L, NSCommandKeyMask }, + { 56, GDK_Shift_L, NSShiftKeyMask }, + { 57, GDK_Caps_Lock, NSAlphaShiftKeyMask }, + { 58, GDK_Alt_L, NSAlternateKeyMask }, + { 59, GDK_Control_L, NSControlKeyMask }, + { 60, GDK_Shift_R, NSShiftKeyMask }, + { 61, GDK_Alt_R, NSAlternateKeyMask }, + { 62, GDK_Control_R, NSControlKeyMask }, + { 122, GDK_F1, 0 }, + { 120, GDK_F2, 0 }, + { 99, GDK_F3, 0 }, + { 118, GDK_F4, 0 }, + { 96, GDK_F5, 0 }, + { 97, GDK_F6, 0 }, + { 98, GDK_F7, 0 }, + { 100, GDK_F8, 0 }, + { 101, GDK_F9, 0 }, + { 109, GDK_F10, 0 }, + { 103, GDK_F11, 0 }, + { 111, GDK_F12, 0 }, + { 105, GDK_F13, 0 }, + { 107, GDK_F14, 0 }, + { 113, GDK_F15, 0 }, }; const static struct { @@ -574,3 +577,41 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap, return TRUE; } + +/* What sort of key event is this? Returns one of + * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored) + */ +GdkEventType _gdk_quartz_key_event_type (NSEvent *event) +{ + unsigned short keycode; + unsigned int flags; + int i; + + switch ([event type]) + { + case NSKeyDown: return GDK_KEY_PRESS; + case NSKeyUp: return GDK_KEY_RELEASE; + case NSFlagsChanged: break; /* Continue... */ + default: g_assert_not_reached (); + } + + /* For flags-changed events, we have to find the special key that caused the + * event, and see if it's in the modifier mask. */ + keycode = [event keyCode]; + flags = [event modifierFlags]; + + for (i = 0; i < G_N_ELEMENTS (known_keys); i++) + { + if (known_keys[i].keycode == keycode) + { + if (flags & known_keys[i].modmask) + return GDK_KEY_PRESS; + else + return GDK_KEY_RELEASE; + } + } + + /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed + * events for no good reason. Ignore them! */ + return GDK_NOTHING; +} diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h index 177d0fbb7f..960844d3b5 100644 --- a/gdk/quartz/gdkprivate-quartz.h +++ b/gdk/quartz/gdkprivate-quartz.h @@ -122,6 +122,8 @@ GdkImage *_gdk_quartz_copy_to_image (GdkDrawable *drawable, void _gdk_quartz_send_map_events (GdkWindow *window); +GdkEventType _gdk_quartz_flags_changed_is_press (NSEvent *event); + extern GdkWindow *_gdk_quartz_keyboard_grab_window; extern GdkWindow *_gdk_quartz_pointer_grab_window; |