diff --git a/frontend/device/generic/device.lua b/frontend/device/generic/device.lua index 45071e142..fadc9e6d8 100644 --- a/frontend/device/generic/device.lua +++ b/frontend/device/generic/device.lua @@ -66,6 +66,10 @@ local Device = { canPowerOff = no, canAssociateFileExtensions = no, + -- Start and stop text input mode (e.g. open soft keyboard, etc) + startTextInput = function() end, + stopTextInput = function() end, + -- use these only as a last resort. We should abstract the functionality -- and have device dependent implementations in the corresponting -- device//device.lua file diff --git a/frontend/device/sdl/device.lua b/frontend/device/sdl/device.lua index 67de0f252..41fc0cd1c 100644 --- a/frontend/device/sdl/device.lua +++ b/frontend/device/sdl/device.lua @@ -65,6 +65,8 @@ local Device = Generic:new{ hasColorScreen = yes, hasEinkScreen = no, canSuspend = no, + startTextInput = SDL.startTextInput, + stopTextInput = SDL.stopTextInput, canOpenLink = getLinkOpener, openLink = function(self, link) local enabled, tool = getLinkOpener() @@ -169,6 +171,7 @@ function Device:init() local UIManager = require("ui/uimanager") -- SDL events can remain cdata but are almost completely transparent + local SDL_TEXTINPUT = 771 local SDL_MOUSEWHEEL = 1027 local SDL_MULTIGESTURE = 2050 local SDL_DROPFILE = 4096 @@ -266,6 +269,8 @@ function Device:init() elseif ev.code == SDL_WINDOWEVENT_MOVED then self.window.left = ev.value.data1 self.window.top = ev.value.data2 + elseif ev.code == SDL_TEXTINPUT then + UIManager:broadcastEvent(Event:new("TextInput", ev.value)) end end, hasClipboardText = function() diff --git a/frontend/device/sdl/event_map_sdl2.lua b/frontend/device/sdl/event_map_sdl2.lua index 27271c9c3..d2a6679ec 100644 --- a/frontend/device/sdl/event_map_sdl2.lua +++ b/frontend/device/sdl/event_map_sdl2.lua @@ -1,39 +1,86 @@ return { - [ 4] = "A", [ 5] = "B", [ 6] = "C", [ 7] = "D", [ 8] = "E", [ 9] = "F", - [10] = "G", [11] = "H", [12] = "I", [13] = "J", [14] = "K", [15] = "L", - [16] = "M", [17] = "N", [18] = "O", [19] = "P", [20] = "Q", [21] = "R", - [22] = "S", [23] = "T", [24] = "U", [25] = "V", [26] = "W", [27] = "X", - [28] = "Y", [29] = "Z", [30] = "1", [31] = "2", [32] = "3", [33] = "4", - [34] = "5", [35] = "6", [36] = "7", [37] = "8", [38] = "9", [39] = "0", - - [43] = "Tab", -- Tab - [42] = "Backspace", -- Backspace - [41] = "Back", -- Escape - [40] = "Press", -- Enter - [225] = "Shift", -- left shift - [55] = ".", - [56] = "/", - [229] = "Sym", -- right shift key - [226] = "Alt", -- left alt - [44] = " ", -- Spacebar - [58] = "Menu", -- F[1] - [59] = "Power", -- F[2] - [61] = "F4", -- F[4] - [63] = "LPgBack", -- F[6] - [64] = "LPgFwd", -- F[7] - [68] = "VPlus", -- F[11] - [69] = "VMinus", -- F[12] - [230] = "AA", -- right alt key - [74] = "Home", -- Home - [82] = "Up", -- arrow up - [75] = "RPgBack", -- normal PageUp - [80] = "Left", -- arrow left - [79] = "Right", -- arrow right - [77] = "End", -- End (above arrows) - [81] = "Down", -- arrow down - [78] = "RPgFwd", -- normal PageDown - [76] = "Del", -- Delete - [101] = "ContextMenu", -- Context menu key - [224] = "Ctrl", -- Left Ctrl - [228] = "Ctrl", -- Right Ctrl + + [ 97] = "A", [ 98] = "B", [ 99] = "C", [100] = "D", [101] = "E", [102] = "F", + [103] = "G", [104] = "H", [105] = "I", [106] = "J", [107] = "K", [108] = "L", + [109] = "M", [110] = "N", [111] = "O", [112] = "P", [113] = "Q", [114] = "R", + [115] = "S", [116] = "T", [117] = "U", [118] = "V", [119] = "W", [120] = "X", + [121] = "Y", [122] = "Z", + + [48] = "0", [49] = "1", [50] = "2", [51] = "3", [52] = "4", + [53] = "5", [54] = "6", [55] = "7", [56] = "8", [57] = "9", + + [33] = "!", + [34] = "\"", + [35] = "#", + [36] = "$", + [37] = "#", + [38] = "&", + [39] = "'", + [40] = "(", + [41] = ")", + [42] = "*", + [43] = "+", + [44] = ",", + [45] = "-", + [46] = ".", + [47] = "/", + + [58] = ":", + [59] = ";", + [60] = "<", + [61] = "=", + [62] = ">", + [63] = "?", + [64] = "@", + + [91] = "[", + [92] = "\\", + [93] = "]", + [94] = "^", + [95] = "_", + [96] = "`", + + [ 8] = "Backspace", -- Backpace + [ 9] = "Tab", -- Tab + [13] = "Press", -- Enter + [27] = "Back", -- Escape + [32] = " ", -- Spacebar + [127] = "Del", + + [1073741882] = "Menu", -- F[1] + [1073741883] = "Power", -- F[2] + [1073741884] = "F3", -- F[3] + [1073741885] = "F4", -- F[4] + [1073741886] = "F5", -- F[5] + [1073741887] = "LPgBack", -- F[6] + [1073741888] = "LPgFwd", -- F[7] + [1073741889] = "F8", -- F[8] + [1073741890] = "F9", -- F[9] + [1073741891] = "F10", -- F[10] + [1073741892] = "VPlus", -- F[11] + [1073741893] = "VMinus", -- F[12] + + [1073742049] = "Shift", -- left shift + [1073742053] = "Sym", -- right shift + [1073742050] = "Alt", -- left alt + [1073742054] = "AA", -- right alt key + [1073741925] = "ContextMenu", -- Context menu key + [0x400000E0] = "Ctrl", -- Left Ctrl + [0x400000E4] = "Ctrl", -- Right Ctrl + [1073742051] = "Win", -- Left Win/Cmd + [1073742055] = "Win", -- Right Win/Cmd + + [1073741906] = "Up", -- arrow up + [1073741899] = "RPgBack", -- normal PageUp + [1073741904] = "Left", -- arrow left + [1073741903] = "Right", -- arrow right + [1073741905] = "Down", -- arrow down + [1073741902] = "RPgFwd", -- normal PageDown + + [1073741898] = "Home", + [1073741901] = "End", + [1073741897] = "Insert", + + [1073741894] = "PrintScreen", + [1073741895] = "ScrollLock", } diff --git a/frontend/ui/widget/inputtext.lua b/frontend/ui/widget/inputtext.lua index b9af9f5bd..3c982ae78 100644 --- a/frontend/ui/widget/inputtext.lua +++ b/frontend/ui/widget/inputtext.lua @@ -422,7 +422,46 @@ function InputText:focus() self._frame_textwidget.color = Blitbuffer.COLOR_BLACK end +-- Handle real keypresses from a physical keyboard, even if the virtual keyboard +-- is shown. Mostly likely to be in the emulator, but could be Android + BT +-- keyboard, or a "coder's keyboard" Android input method. +function InputText:onKeyPress(key) + if key["Backspace"] then + self:delChar() + elseif key["Del"] then + self:rightChar() + self:delChar() + elseif key["Left"] then + self:leftChar() + elseif key["Right"] then + self:rightChar() + elseif key["End"] then + self:goToEnd() + elseif key["Home"] then + self:goToHome() + elseif key["Ctrl"] and not key["Shift"] and not key["Alt"] then + if key["U"] then + self:delToStartOfLine() + elseif key["H"] then + self:delChar() + end + else + return false + end + + return true +end + +-- Handle text coming directly as text from the Device layer (eg. soft keyboard +-- or via SDL's keyboard mapping). +function InputText:onTextInput(text) + self:addChars(text) + return true +end + function InputText:onShowKeyboard(ignore_first_hold_release) + Device:startTextInput() + self.keyboard.ignore_first_hold_release = ignore_first_hold_release UIManager:show(self.keyboard) return true @@ -430,6 +469,7 @@ end function InputText:onCloseKeyboard() UIManager:close(self.keyboard) + Device:stopTextInput() end function InputText:onCloseWidget() @@ -523,6 +563,14 @@ function InputText:rightChar() self.charpos, self.top_line_num = self.text_widget:getCharPos() end +function InputText:goToHome() + self.text_widget:moveCursorToCharPos(1) +end + +function InputText:goToEnd() + self.text_widget:moveCursorToCharPos(0) +end + function InputText:upLine() self.text_widget:moveCursorUp() self.charpos, self.top_line_num = self.text_widget:getCharPos()