diff --git a/changes/2220.bugfix.rst b/changes/2220.bugfix.rst new file mode 100644 index 0000000000..136f7369c2 --- /dev/null +++ b/changes/2220.bugfix.rst @@ -0,0 +1 @@ +Key handling for Insert, Delete, Num Lock, Scroll Lock, and some other esoteric keys was added for GTK and Winforms. Some uses of bare Shift on GTK were also improved. diff --git a/core/src/toga/keys.py b/core/src/toga/keys.py index 6e78728eb8..bbaa8c1942 100644 --- a/core/src/toga/keys.py +++ b/core/src/toga/keys.py @@ -119,6 +119,7 @@ class Key(Enum): HOME = "" END = "" + INSERT = "" DELETE = "" PAGE_UP = "" PAGE_DOWN = "" @@ -128,6 +129,7 @@ class Key(Enum): LEFT = "" RIGHT = "" + NUMLOCK = "" NUMPAD_0 = "numpad:0" NUMPAD_1 = "numpad:1" NUMPAD_2 = "numpad:2" @@ -147,6 +149,11 @@ class Key(Enum): NUMPAD_MULTIPLY = "numpad:*" NUMPAD_PLUS = "numpad:+" + SCROLLLOCK = "" + BEGIN = "" + MENU = "" + PAUSE = "" + def is_printable(self) -> bool: """Does pressing the key result in a printable character?""" return not (self.value.startswith("<") and self.value.endswith(">")) diff --git a/gtk/src/toga_gtk/keys.py b/gtk/src/toga_gtk/keys.py index efda01468f..6a05c5283e 100644 --- a/gtk/src/toga_gtk/keys.py +++ b/gtk/src/toga_gtk/keys.py @@ -102,6 +102,7 @@ Gdk.KEY_X: Key.X, Gdk.KEY_Y: Key.Y, Gdk.KEY_Z: Key.Z, + Gdk.KEY_Caps_Lock: Key.CAPSLOCK, Gdk.KEY_Tab: Key.TAB, Gdk.KEY_bracketleft: Key.OPEN_BRACKET, Gdk.KEY_bracketright: Key.CLOSE_BRACKET, @@ -121,7 +122,10 @@ Gdk.KEY_less: Key.LESS_THAN, Gdk.KEY_greater: Key.GREATER_THAN, Gdk.KEY_question: Key.QUESTION, + Gdk.KEY_Insert: Key.INSERT, Gdk.KEY_Delete: Key.DELETE, + Gdk.KEY_Begin: Key.BEGIN, + Gdk.KEY_Menu: Key.MENU, Gdk.KEY_Home: Key.HOME, Gdk.KEY_End: Key.END, Gdk.KEY_Page_Up: Key.PAGE_UP, @@ -130,6 +134,7 @@ Gdk.KEY_Right: Key.RIGHT, Gdk.KEY_Up: Key.UP, Gdk.KEY_Down: Key.DOWN, + Gdk.KEY_Num_Lock: Key.NUMLOCK, Gdk.KEY_KP_Enter: Key.NUMPAD_ENTER, Gdk.KEY_KP_0: Key.NUMPAD_0, Gdk.KEY_KP_1: Key.NUMPAD_1, @@ -150,11 +155,23 @@ Gdk.KEY_KP_Up: Key.UP, Gdk.KEY_KP_Down: Key.DOWN, Gdk.KEY_KP_Delete: Key.DELETE, + Gdk.KEY_KP_Insert: Key.INSERT, Gdk.KEY_KP_Add: Key.NUMPAD_PLUS, Gdk.KEY_KP_Subtract: Key.NUMPAD_MINUS, Gdk.KEY_KP_Multiply: Key.NUMPAD_MULTIPLY, Gdk.KEY_KP_Divide: Key.NUMPAD_DIVIDE, - Gdk.KEY_KP_Delete: Key.DELETE, + Gdk.KEY_KP_Begin: Key.BEGIN, + Gdk.KEY_Pause: Key.PAUSE, + Gdk.KEY_ISO_Left_Tab: Key.TAB, + Gdk.KEY_Scroll_Lock: Key.SCROLLLOCK, + Gdk.KEY_Shift_L: Key.SHIFT, + Gdk.KEY_Shift_R: Key.SHIFT, + Gdk.KEY_Control_L: Key.MOD_1, + Gdk.KEY_Control_R: Key.MOD_1, + Gdk.KEY_Alt_L: Key.MOD_2, + Gdk.KEY_Alt_R: Key.MOD_2, + Gdk.KEY_Hyper_L: Key.MOD_3, + Gdk.KEY_Hyper_R: Key.MOD_3, } GTK_KEY_NAMES = { @@ -172,7 +189,14 @@ def toga_key(event): """Convert a GDK Key Event into a Toga key.""" - key = GDK_KEYS[event.keyval] + try: + key = GDK_KEYS[event.keyval] + except KeyError: # pragma: no cover + # Ignore any key event code we can't map. This can happen for weird key + # combination (ctrl-alt-tux), and if the X server has weird key + # bindings. If we can't map it, we can't really type it either, so we + # need to no-cover this branch. + return None modifiers = set() diff --git a/winforms/src/toga_winforms/keys.py b/winforms/src/toga_winforms/keys.py index f93bb245cc..abcbdc5276 100644 --- a/winforms/src/toga_winforms/keys.py +++ b/winforms/src/toga_winforms/keys.py @@ -18,6 +18,7 @@ # Key.BACK_QUOTE.value: WinForms.Keys.Oemtilde, # No idea what the code should be Key.MINUS.value: WinForms.Keys.OemMinus, Key.EQUAL.value: WinForms.Keys.Oemplus, + Key.CAPSLOCK.value: WinForms.Keys.CapsLock, Key.TAB.value: WinForms.Keys.Tab, Key.OPEN_BRACKET.value: WinForms.Keys.OemOpenBrackets, Key.CLOSE_BRACKET.value: WinForms.Keys.OemCloseBrackets, @@ -30,13 +31,18 @@ Key.SPACE.value: WinForms.Keys.Space, Key.PAGE_UP.value: WinForms.Keys.PageUp, Key.PAGE_DOWN.value: WinForms.Keys.PageDown, + Key.INSERT.value: WinForms.Keys.Insert, + Key.DELETE.value: WinForms.Keys.Delete, Key.HOME.value: WinForms.Keys.Home, Key.END.value: WinForms.Keys.End, Key.UP.value: WinForms.Keys.Up, Key.DOWN.value: WinForms.Keys.Down, Key.LEFT.value: WinForms.Keys.Left, Key.RIGHT.value: WinForms.Keys.Right, + Key.NUMLOCK.value: WinForms.Keys.NumLock, Key.NUMPAD_DECIMAL_POINT.value: WinForms.Keys.Decimal, + Key.SCROLLLOCK.value: WinForms.Keys.Scroll, + Key.MENU.value: WinForms.Keys.Menu, } WINFORMS_KEYS.update( {str(digit): getattr(WinForms.Keys, f"D{digit}") for digit in range(10)}