From 23482e3cf460c80b75542f6ef2d3e81b7be19d41 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 14 Feb 2019 20:39:32 +0530 Subject: [PATCH] macOS: Allow assigning only the left or right :kbd:`Option` key to work as the :kbd:`Alt` key. See :opt:`macos_option_as_alt` for details Fixes #1022 --- docs/changelog.rst | 3 +++ glfw/cocoa_platform.h | 2 +- glfw/cocoa_window.m | 2 +- glfw/glfw.py | 2 +- kitty/cocoa_window.m | 9 +++++++++ kitty/config_data.py | 25 +++++++++++++++++++++---- kitty/glfw-wrapper.h | 10 +++++----- kitty/glfw.c | 9 +++++++-- kitty/state.c | 2 +- kitty/state.h | 3 ++- 10 files changed, 51 insertions(+), 16 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 5d33d2c2e..f2f3db999 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -30,6 +30,9 @@ To update |kitty|, :doc:`follow the instructions `. - macOS: Workaround for cocoa bug that could cause the mouse cursor to become hidden in other applications in rare circumstances (:iss:`1218`) +- macOS: Allow assigning only the left or right :kbd:`Option` key to work as the + :kbd:`Alt` key. See :opt:`macos_option_as_alt` for details (:iss:`1022`) + - Fix using remote control to set cursor text color causing errors when creating new windows (:iss:`1326`) diff --git a/glfw/cocoa_platform.h b/glfw/cocoa_platform.h index 0f96e5d29..da6074a63 100644 --- a/glfw/cocoa_platform.h +++ b/glfw/cocoa_platform.h @@ -35,7 +35,7 @@ typedef void* id; #endif typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; -typedef int (* GLFWcocoatextinputfilterfun)(int,int,int); +typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int, unsigned long); typedef int (* GLFWapplicationshouldhandlereopenfun)(int); typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*); diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 5352fc6d8..8db72fdf5 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -818,7 +818,7 @@ is_ascii_control_char(char x) { const NSUInteger flags = [event modifierFlags]; const int mods = translateFlags(flags); const int key = translateKey(scancode, GLFW_TRUE); - const GLFWbool process_text = !window->ns.textInputFilterCallback || window->ns.textInputFilterCallback(key, mods, scancode) != 1; + const GLFWbool process_text = !window->ns.textInputFilterCallback || window->ns.textInputFilterCallback(key, mods, scancode, flags) != 1; _glfw.ns.text[0] = 0; if (!_glfw.ns.unicodeData) { // Using the cocoa API for key handling is disabled, as there is no diff --git a/glfw/glfw.py b/glfw/glfw.py index 7dc31eb4c..f28792804 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -196,7 +196,7 @@ const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callbac {} -typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int); +typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long); typedef int (* GLFWapplicationshouldhandlereopenfun)(int); typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*); typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id); diff --git a/kitty/cocoa_window.m b/kitty/cocoa_window.m index c0f501a14..bcba45926 100644 --- a/kitty/cocoa_window.m +++ b/kitty/cocoa_window.m @@ -348,6 +348,15 @@ cocoa_make_window_resizable(void *w, bool resizable) { return true; } +#define NSLeftAlternateKeyMask (0x000020 | NSEventModifierFlagOption) +#define NSRightAlternateKeyMask (0x000040 | NSEventModifierFlagOption) + +bool +cocoa_alt_option_key_pressed(NSUInteger flags) { + NSUInteger q = (OPT(macos_option_as_alt) == 1) ? NSRightAlternateKeyMask : NSLeftAlternateKeyMask; + return ((q & flags) == q) ? true : false; +} + void cocoa_focus_window(void *w) { NSWindow *window = (NSWindow*)w; diff --git a/kitty/config_data.py b/kitty/config_data.py index c9e542e03..192fad64f 100644 --- a/kitty/config_data.py +++ b/kitty/config_data.py @@ -9,7 +9,8 @@ from gettext import gettext as _ from . import fast_data_types as defines from .conf.definition import option_func from .conf.utils import ( - choices, positive_float, positive_int, to_cmdline, to_color, unit_float + choices, positive_float, positive_int, to_bool, to_cmdline, to_color, + unit_float ) from .constants import config_dir, is_macos from .fast_data_types import CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE @@ -809,11 +810,27 @@ incompatible with :opt:`background_opacity`. If you want to use both, you are probably better off just hiding the titlebar with :opt:`hide_window_decorations`. ''')) -o('macos_option_as_alt', True, long_text=_(''' -Use the option key as an alt key. With this set to no, kitty will use + +def macos_option_as_alt(x): + x = x.lower() + if x == 'both': + return 0b11 + if x == 'left': + return 0b10 + if x == 'right': + return 0b01 + if to_bool(x): + return 0b11 + return 0 + + +o('macos_option_as_alt', 0b11, option_type=macos_option_as_alt, long_text=_(''' +Use the option key as an alt key. With this set to :code:`no`, kitty will use the macOS native :kbd:`Option+Key` = unicode character behavior. This will break any :kbd:`Alt+key` keyboard shortcuts in your terminal programs, but you -can use the macOS unicode input technique. +can use the macOS unicode input technique. You can use the values: +:code:`left`, :code:`right`, or :code:`both` to use only the left, right or +both Option keys as Alt. ''')) o('macos_hide_from_tasks', False, long_text=_(''' diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index eaf03ab02..e776027ca 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -923,9 +923,9 @@ typedef void (* GLFWerrorfun)(int,const char*); * * @param[in] window The window that was moved. * @param[in] xpos The new x-coordinate, in screen coordinates, of the - * upper-left corner of the client area of the window. + * upper-left corner of the content area of the window. * @param[in] ypos The new y-coordinate, in screen coordinates, of the - * upper-left corner of the client area of the window. + * upper-left corner of the content area of the window. * * @sa @ref window_pos * @sa @ref glfwSetWindowPosCallback @@ -1102,9 +1102,9 @@ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); * * @param[in] window The window that received the event. * @param[in] xpos The new cursor x-coordinate, relative to the left edge of - * the client area. + * the content area. * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the - * client area. + * content area. * * @sa @ref cursor_pos * @sa @ref glfwSetCursorPosCallback @@ -1391,7 +1391,7 @@ typedef struct GLFWgamepadstate */ -typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int); +typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long); typedef int (* GLFWapplicationshouldhandlereopenfun)(int); typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*); typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id); diff --git a/kitty/glfw.c b/kitty/glfw.c index de9b2e10a..a4ba13fc0 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -14,6 +14,7 @@ extern bool cocoa_toggle_fullscreen(void *w, bool); extern void cocoa_create_global_menu(void); extern void cocoa_set_hide_from_tasks(void); extern void cocoa_set_titlebar_color(void *w, color_type color); +extern bool cocoa_alt_option_key_pressed(unsigned long); #if GLFW_KEY_LAST >= MAX_KEY_COUNT @@ -421,8 +422,12 @@ toggle_fullscreen_for_os_window(OSWindow *w) { #ifdef __APPLE__ static int -filter_option(int key UNUSED, int mods, unsigned int scancode UNUSED) { - return ((mods == GLFW_MOD_ALT) || (mods == (GLFW_MOD_ALT | GLFW_MOD_SHIFT))) ? 1 : 0; +filter_option(int key UNUSED, int mods, unsigned int scancode UNUSED, unsigned long flags) { + if ((mods == GLFW_MOD_ALT) || (mods == (GLFW_MOD_ALT | GLFW_MOD_SHIFT))) { + if (OPT(macos_option_as_alt) == 3) return 1; + if (cocoa_alt_option_key_pressed(flags)) return 1; + } + return 0; } static GLFWwindow *application_quit_canary = NULL; diff --git a/kitty/state.c b/kitty/state.c index 0118b62f5..1ef4211f2 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -388,7 +388,7 @@ PYWRAP1(set_options) { S(sync_to_monitor, PyObject_IsTrue); S(close_on_child_death, PyObject_IsTrue); S(window_alert_on_bell, PyObject_IsTrue); - S(macos_option_as_alt, PyObject_IsTrue); + S(macos_option_as_alt, PyLong_AsUnsignedLong); S(macos_traditional_fullscreen, PyObject_IsTrue); S(macos_quit_when_last_window_closed, PyObject_IsTrue); S(macos_show_window_title_in_menubar, PyObject_IsTrue); diff --git a/kitty/state.h b/kitty/state.h index 7c2b5d1de..951a209fa 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -24,7 +24,8 @@ typedef struct { color_type url_color, background, active_border_color, inactive_border_color, bell_border_color; double repaint_delay, input_delay; bool focus_follows_mouse, hide_window_decorations; - bool macos_option_as_alt, macos_hide_from_tasks, macos_quit_when_last_window_closed, macos_window_resizable, macos_traditional_fullscreen, macos_show_window_title_in_menubar; + bool macos_hide_from_tasks, macos_quit_when_last_window_closed, macos_window_resizable, macos_traditional_fullscreen, macos_show_window_title_in_menubar; + unsigned int macos_option_as_alt; float macos_thicken_font; int adjust_line_height_px, adjust_column_width_px; float adjust_line_height_frac, adjust_column_width_frac;