summaryrefslogtreecommitdiff
path: root/gdk/quartz
diff options
context:
space:
mode:
Diffstat (limited to 'gdk/quartz')
-rw-r--r--gdk/quartz/gdkevents-quartz.c92
-rw-r--r--gdk/quartz/gdkkeys-quartz.c87
-rw-r--r--gdk/quartz/gdkprivate-quartz.h2
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;