From dc253b3c51ac621f894653d0f04aef7d8f9ba8f1 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 1 Sep 2015 19:00:25 +0100 Subject: [PATCH] On OS X, be able to configure either Option or Command as Meta. Personally I like using Command as the Esc-prefixing Meta key in terminal sessions, because it occupies the same physical keyboard position as the Alt key that I'm used to using on non-Macs. OS X Terminal uses Option for that purpose (freeing up Command for the conventional Mac keyboard shortcuts, of course), so I anticipate differences of opinion. Hence, here's a pair of OSX-specific config options which permit a user to set either, or neither, or both of those modifier keys to function as the terminal Meta key. --- putty.h | 2 ++ settings.c | 8 ++++++++ unix/gtkcfg.c | 16 ++++++++++++++++ unix/gtkwin.c | 22 ++++++++++++++++------ unix/unix.h | 1 + 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/putty.h b/putty.h index 4d15448d..15ec5b99 100644 --- a/putty.h +++ b/putty.h @@ -751,6 +751,8 @@ void cleanup_exit(int); X(INT, NONE, erase_to_scrollback) \ X(INT, NONE, compose_key) \ X(INT, NONE, ctrlaltkeys) \ + X(INT, NONE, osx_option_meta) \ + X(INT, NONE, osx_command_meta) \ X(STR, NONE, wintitle) /* initial window title */ \ /* Terminal options */ \ X(INT, NONE, savelines) \ diff --git a/settings.c b/settings.c index de74a2b7..07ee4123 100644 --- a/settings.c +++ b/settings.c @@ -531,6 +531,10 @@ void save_open_settings(void *sesskey, Conf *conf) write_setting_i(sesskey, "AltOnly", conf_get_int(conf, CONF_alt_only)); write_setting_i(sesskey, "ComposeKey", conf_get_int(conf, CONF_compose_key)); write_setting_i(sesskey, "CtrlAltKeys", conf_get_int(conf, CONF_ctrlaltkeys)); +#ifdef OSX_META_KEY_CONFIG + write_setting_i(sesskey, "OSXOptionMeta", conf_get_int(conf, CONF_osx_option_meta)); + write_setting_i(sesskey, "OSXCommandMeta", conf_get_int(conf, CONF_osx_command_meta)); +#endif write_setting_i(sesskey, "TelnetKey", conf_get_int(conf, CONF_telnet_keyboard)); write_setting_i(sesskey, "TelnetRet", conf_get_int(conf, CONF_telnet_newline)); write_setting_i(sesskey, "LocalEcho", conf_get_int(conf, CONF_localecho)); @@ -833,6 +837,10 @@ void load_open_settings(void *sesskey, Conf *conf) gppi(sesskey, "AltOnly", 0, conf, CONF_alt_only); gppi(sesskey, "ComposeKey", 0, conf, CONF_compose_key); gppi(sesskey, "CtrlAltKeys", 1, conf, CONF_ctrlaltkeys); +#ifdef OSX_META_KEY_CONFIG + gppi(sesskey, "OSXOptionMeta", 1, conf, CONF_osx_option_meta); + gppi(sesskey, "OSXCommandMeta", 0, conf, CONF_osx_command_meta); +#endif gppi(sesskey, "TelnetKey", 0, conf, CONF_telnet_keyboard); gppi(sesskey, "TelnetRet", 1, conf, CONF_telnet_newline); gppi(sesskey, "LocalEcho", AUTO, conf, CONF_localecho); diff --git a/unix/gtkcfg.c b/unix/gtkcfg.c index 958a3f66..4307176f 100644 --- a/unix/gtkcfg.c +++ b/unix/gtkcfg.c @@ -129,6 +129,22 @@ void gtk_setup_config_box(struct controlbox *b, int midsession, void *win) conf_checkbox_handler, I(CONF_utf8_override)); +#ifdef OSX_META_KEY_CONFIG + /* + * On OS X, there are multiple reasonable opinions about whether + * Option or Command (or both, or neither) should act as a Meta + * key, or whether they should have their normal OS functions. + */ + s = ctrl_getset(b, "Terminal/Keyboard", "meta", + "Choose the Meta key:"); + ctrl_checkbox(s, "Option key acts as Meta", 'p', + HELPCTX(no_help), + conf_checkbox_handler, I(CONF_osx_option_meta)); + ctrl_checkbox(s, "Command key acts as Meta", 'm', + HELPCTX(no_help), + conf_checkbox_handler, I(CONF_osx_command_meta)); +#endif + if (!midsession) { /* * Allow the user to specify the window class as part of the saved diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 3d7486c4..8e809054 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -133,6 +133,7 @@ struct gui_data { int window_border; int cursor_type; int drawtype; + int meta_mod_mask; }; static void cache_conf_values(struct gui_data *inst) @@ -140,6 +141,15 @@ static void cache_conf_values(struct gui_data *inst) inst->bold_style = conf_get_int(inst->conf, CONF_bold_style); inst->window_border = conf_get_int(inst->conf, CONF_window_border); inst->cursor_type = conf_get_int(inst->conf, CONF_cursor_type); +#ifdef OSX_META_KEY_CONFIG + inst->meta_mod_mask = 0; + if (conf_get_int(inst->conf, CONF_osx_option_meta)) + inst->meta_mod_mask |= GDK_MOD1_MASK; + if (conf_get_int(inst->conf, CONF_osx_command_meta)) + inst->meta_mod_mask |= GDK_MOD2_MASK; +#else + inst->meta_mod_mask = GDK_MOD1_MASK; +#endif } struct draw_ctx { @@ -834,12 +844,12 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) } /* - * If we're seeing a numberpad key press with Mod1 down, + * If we're seeing a numberpad key press with Meta down, * consider adding it to alt_keycode if that's sensible. - * Anything _else_ with Mod1 down cancels any possibility + * Anything _else_ with Meta down cancels any possibility * of an ALT keycode: we set alt_keycode to -2. */ - if ((event->state & GDK_MOD1_MASK) && inst->alt_keycode != -2) { + if ((event->state & inst->meta_mod_mask) && inst->alt_keycode != -2) { int digit = -1; switch (event->keyval) { case GDK_KEY_KP_0: case GDK_KEY_KP_Insert: digit = 0; break; @@ -1030,7 +1040,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) output[lenof(output)-1] = '\0'; end = strlen(output); } - if (event->state & GDK_MOD1_MASK) { + if (event->state & inst->meta_mod_mask) { start = 0; if (end == 1) end = 0; } else @@ -1515,7 +1525,7 @@ gboolean button_internal(struct gui_data *inst, guint32 timestamp, shift = state & GDK_SHIFT_MASK; ctrl = state & GDK_CONTROL_MASK; - alt = state & GDK_MOD1_MASK; + alt = state & inst->meta_mod_mask; raw_mouse_mode = send_raw_mouse && !(shift && conf_get_int(inst->conf, @@ -1613,7 +1623,7 @@ gint motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) shift = event->state & GDK_SHIFT_MASK; ctrl = event->state & GDK_CONTROL_MASK; - alt = event->state & GDK_MOD1_MASK; + alt = event->state & inst->meta_mod_mask; if (event->state & GDK_BUTTON1_MASK) button = MBT_LEFT; else if (event->state & GDK_BUTTON2_MASK) diff --git a/unix/unix.h b/unix/unix.h index 6f97901a..3fe7d7f6 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -24,6 +24,7 @@ #define NOT_X_WINDOWS /* of course, all the X11 stuff should be disabled */ #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 */ #endif struct Filename {