From 0afc496a5f46c401116b17d10974f2363aab8b86 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 1 Sep 2015 19:10:29 +0100 Subject: [PATCH] Work around OS X GTK treating Option as an AltGr key. If I'm using Option as the Meta key, I want to suppress OS X GTK's default behaviour of treating it as an AltGr-oid which changes the keyval and Unicode translation of alphabetic keys. So on OS X I enable a somewhat bodgy workaround which retranslates from the hardware keycode as if the Option modifier had not been active at the time, and use that as the character to prefix Esc to. This is a bit nasty because I have to hardwire group = 0 in the call to gdk_keymap_translate_keyboard_state(), whereas in principle what I wanted was group = (whatever would have resulted from everything else in the key event other than MOD1). However, in practice, they seem to be the same, so this will do for the moment. --- unix/gtkwin.c | 42 ++++++++++++++++++++++++++++++++++++++++-- unix/unix.h | 2 ++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 8e809054..e75afb75 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -996,8 +996,19 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) event->keyval == GDK_KEY_KP_Page_Up)) { /* nethack mode; do nothing */ } else { - if (gtk_im_context_filter_keypress(inst->imc, event)) - return TRUE; +#ifdef META_MANUAL_MASK + if (event->state & META_MANUAL_MASK & inst->meta_mod_mask) { + /* + * If this key event had a Meta modifier bit set which + * is also in META_MANUAL_MASK, that means passing + * such an event to the GtkIMContext will be unhelpful + * (it will eat the keystroke and turn it into + * something not what we wanted). + */ + } else +#endif + if (gtk_im_context_filter_keypress(inst->imc, event)) + return TRUE; } /* @@ -1043,6 +1054,33 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) if (event->state & inst->meta_mod_mask) { start = 0; if (end == 1) end = 0; + +#ifdef META_MANUAL_MASK + if (event->state & META_MANUAL_MASK) { + /* + * Key events which have a META_MANUAL_MASK meta bit + * set may have a keyval reflecting that, e.g. on OS X + * the Option key acts as an AltGr-like modifier and + * causes different Unicode characters to be output. + * + * To work around this, we clear the dangerous + * modifier bit and retranslate from the hardware + * keycode as if the key had been pressed without that + * modifier. Then we prefix Esc to *that*. + */ + guint new_keyval; + GdkModifierType consumed; + if (gdk_keymap_translate_keyboard_state + (gdk_keymap_get_for_display(gdk_display_get_default()), + event->hardware_keycode, event->state & ~META_MANUAL_MASK, + 0, &new_keyval, NULL, NULL, &consumed)) { + ucsoutput[0] = '\033'; + ucsoutput[1] = gdk_keyval_to_unicode(new_keyval); + use_ucsoutput = TRUE; + end = 2; + } + } +#endif } else start = 1; diff --git a/unix/unix.h b/unix/unix.h index 3fe7d7f6..1c8f2e8d 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -25,6 +25,8 @@ #define NO_PTY_PRE_INIT /* OS X gets very huffy if we try to set[ug]id */ #define SET_NONBLOCK_VIA_OPENPT /* work around missing fcntl functionality */ #define OSX_META_KEY_CONFIG /* two possible Meta keys to choose from */ +/* this potential one of the Meta keys needs manual handling */ +#define META_MANUAL_MASK (GDK_MOD1_MASK) #endif struct Filename {