[feat, UX] Support the virtualKeyboard on non touch-device (#3796)

* [VirtualKeyboard] Add support for keynaviguation

Also rename the variable "layout" to "keyboard_layout" because conflict
with the layout from the focusmanager

* Make the goto dialog compatible with key naviguation

My solution is to change the order of the widget. The last one will the
virtualkeybard so it catch all the keybinding, and below it, make the
dialog "is_always_active = true" so it can receive touch event.

* Correctly show the virtual keyboard on dpad devices

* change the order to call the virtualKeyboard so it end up on top

* Handle the multi input dialog

* Support reopening the virtualKeyboard by the Press key

* add check focusmanager

* Fix https://github.com/koreader/koreader/issues/3797

* MultiInputDialog : Now work on non touch-device

* Set the virtualkeyboard to be a modal widget

* Fix the layout in multiinputwidget

* Fix for the various combination of
hasKeys,hasDpad,isTouchDevice

* [Focusmanager] Better handling of malformed layout
pull/3817/head
onde2rock 6 years ago committed by Frans de Jonge
parent 6c3ace9940
commit e502bf04d3

@ -111,8 +111,8 @@ function DropBox:config(item, callback)
height = Screen:getHeight() * 0.2, height = Screen:getHeight() * 0.2,
input_type = "text", input_type = "text",
} }
self.settings_dialog:onShowKeyboard()
UIManager:show(self.settings_dialog) UIManager:show(self.settings_dialog)
self.settings_dialog:onShowKeyboard()
end end
function DropBox:info(token) function DropBox:info(token)

@ -140,8 +140,8 @@ function Ftp:config(item, callback)
height = Screen:getHeight() * 0.2, height = Screen:getHeight() * 0.2,
input_type = "text", input_type = "text",
} }
self.settings_dialog:onShowKeyboard()
UIManager:show(self.settings_dialog) UIManager:show(self.settings_dialog)
self.settings_dialog:onShowKeyboard()
end end
function Ftp:info(item) function Ftp:info(item)

@ -264,8 +264,8 @@ function FileManager:init()
}, },
}}, }},
} }
fileManager.rename_dialog:onShowKeyboard()
UIManager:show(fileManager.rename_dialog) UIManager:show(fileManager.rename_dialog)
fileManager.rename_dialog:onShowKeyboard()
end, end,
} }
}, },
@ -404,8 +404,8 @@ function FileManager:tapPlus()
} }
}, },
} }
self.input_dialog:onShowKeyboard()
UIManager:show(self.input_dialog) UIManager:show(self.input_dialog)
self.input_dialog:onShowKeyboard()
end, end,
}, },
}, },

@ -138,8 +138,8 @@ function FileSearcher:showSearch()
}, },
}, },
} }
self.search_dialog:onShowKeyboard()
UIManager:show(self.search_dialog) UIManager:show(self.search_dialog)
self.search_dialog:onShowKeyboard()
end end
function FileSearcher:showSearchResults() function FileSearcher:showSearchResults()

@ -205,8 +205,8 @@ function Search:ShowSearch()
width = Screen:getWidth() * 0.8, width = Screen:getWidth() * 0.8,
height = Screen:getHeight() * 0.2, height = Screen:getHeight() * 0.2,
} }
self.search_dialog:onShowKeyboard()
UIManager:show(self.search_dialog) UIManager:show(self.search_dialog)
self.search_dialog:onShowKeyboard()
else else
if self.error then if self.error then
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{

@ -154,8 +154,8 @@ function SetDefaults:init()
input_type = setting_type, input_type = setting_type,
width = Screen:getWidth() * 0.95, width = Screen:getWidth() * 0.95,
} }
self.set_dialog:onShowKeyboard()
UIManager:show(self.set_dialog) UIManager:show(self.set_dialog)
self.set_dialog:onShowKeyboard()
end end
table.insert(self.results, { table.insert(self.results, {
@ -205,8 +205,8 @@ function SetDefaults:init()
width = Screen:getWidth() * 0.95, width = Screen:getWidth() * 0.95,
height = Screen:getHeight() * 0.2, height = Screen:getHeight() * 0.2,
} }
self.set_dialog:onShowKeyboard()
UIManager:show(self.set_dialog) UIManager:show(self.set_dialog)
self.set_dialog:onShowKeyboard()
end end
table.insert(self.results, { table.insert(self.results, {
@ -244,8 +244,8 @@ function SetDefaults:init()
input_type = setting_type, input_type = setting_type,
width = Screen:getWidth() * 0.95, width = Screen:getWidth() * 0.95,
} }
self.set_dialog:onShowKeyboard()
UIManager:show(self.set_dialog) UIManager:show(self.set_dialog)
self.set_dialog:onShowKeyboard()
end end
table.insert(self.results, { table.insert(self.results, {

@ -482,8 +482,8 @@ function ReaderBookmark:renameBookmark(item, from_highlight)
} }
}, },
} }
self.input:onShowKeyboard()
UIManager:show(self.input) UIManager:show(self.input)
self.input:onShowKeyboard()
end end
function ReaderBookmark:toggleBookmark(pn_or_xp) function ReaderBookmark:toggleBookmark(pn_or_xp)

@ -84,8 +84,8 @@ function ReaderGoto:onShowGotoDialog()
}, },
input_type = "number", input_type = "number",
} }
self.goto_dialog:onShowKeyboard()
UIManager:show(self.goto_dialog) UIManager:show(self.goto_dialog)
self.goto_dialog:onShowKeyboard()
end end
function ReaderGoto:onShowSkimtoDialog() function ReaderGoto:onShowSkimtoDialog()

@ -58,8 +58,8 @@ function ReaderWikipedia:lookupInput()
} }
}, },
} }
self.input_dialog:onShowKeyboard()
UIManager:show(self.input_dialog) UIManager:show(self.input_dialog)
self.input_dialog:onShowKeyboard()
end end
function ReaderWikipedia:addToMainMenu(menu_items) function ReaderWikipedia:addToMainMenu(menu_items)
@ -165,8 +165,8 @@ function ReaderWikipedia:addToMainMenu(menu_items)
} }
}, },
} }
wikilang_input:onShowKeyboard()
UIManager:show(wikilang_input) UIManager:show(wikilang_input)
wikilang_input:onShowKeyboard()
end, end,
}, },
{ -- setting used by dictquicklookup { -- setting used by dictquicklookup

@ -521,8 +521,8 @@ function ReaderUI:unlockDocumentWithPassword(document, try_again)
}, },
text_type = "password", text_type = "password",
} }
self.password_dialog:onShowKeyboard()
UIManager:show(self.password_dialog) UIManager:show(self.password_dialog)
self.password_dialog:onShowKeyboard()
end end
function ReaderUI:onVerifyPassword(document) function ReaderUI:onVerifyPassword(document)

@ -130,8 +130,8 @@ function Screensaver:setMessage()
}, },
}, },
} }
self.input_dialog:onShowKeyboard()
UIManager:show(self.input_dialog) UIManager:show(self.input_dialog)
self.input_dialog:onShowKeyboard()
end end
function Screensaver:show(event, fallback_message) function Screensaver:show(event, fallback_message)

@ -476,8 +476,8 @@ function UIManager:sendEvent(event)
end end
if widget.widget.is_always_active then if widget.widget.is_always_active then
-- active widgets will handle this event -- active widgets will handle this event
-- Note: is_always_active widgets currently are vitualkeyboard and -- Note: is_always_active widgets currently are widgets that want to show a keyboard
-- readerconfig -- and readerconfig
checked_widgets[widget] = true checked_widgets[widget] = true
if widget.widget:handleEvent(event) then return end if widget.widget:handleEvent(event) then return end
end end

@ -575,8 +575,8 @@ function BookStatusWidget:onSwitchFocus(inputbox)
}, },
}, },
} }
self.note_dialog:onShowKeyboard()
UIManager:show(self.note_dialog) UIManager:show(self.note_dialog)
self.note_dialog:onShowKeyboard()
end end
function BookStatusWidget:closeInputDialog() function BookStatusWidget:closeInputDialog()

@ -85,7 +85,7 @@ function ButtonTable:init()
end end
end -- end for each button line end -- end for each button line
self:addHorizontalSep(true, false, false) self:addHorizontalSep(true, false, false)
if Device:hasDPad() or Device:hasKeyboard() then if Device:hasKeys() then
self.layout = self.buttons_layout self.layout = self.buttons_layout
self.layout[1][1]:onFocus() self.layout[1][1]:onFocus()
self.key_events.SelectByKeyPress = { {{"Press", "Enter"}} } self.key_events.SelectByKeyPress = { {{"Press", "Enter"}} }

@ -236,8 +236,8 @@ function InputContainer:onInput(input)
}, },
}, },
} }
self.input_dialog:onShowKeyboard()
UIManager:show(self.input_dialog) UIManager:show(self.input_dialog)
self.input_dialog:onShowKeyboard()
end end
function InputContainer:closeInputDialog() function InputContainer:closeInputDialog()

@ -860,8 +860,8 @@ function DictQuickLookup:lookupInputWord(hint)
} }
}, },
} }
self.input_dialog:onShowKeyboard()
UIManager:show(self.input_dialog) UIManager:show(self.input_dialog)
self.input_dialog:onShowKeyboard()
end end
function DictQuickLookup:inputLookup() function DictQuickLookup:inputLookup()

@ -1,3 +1,4 @@
local Device = require("device")
local Event = require("ui/event") local Event = require("ui/event")
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local logger = require("logger") local logger = require("logger")
@ -33,13 +34,15 @@ function FocusManager:init()
if not self.selected then if not self.selected then
self.selected = { x = 1, y = 1 } self.selected = { x = 1, y = 1 }
end end
self.key_events = { if Device:hasKeys() then
-- these will all generate the same event, just with different arguments self.key_events = {
FocusUp = { {"Up"}, doc = "move focus up", event = "FocusMove", args = {0, -1} }, -- these will all generate the same event, just with different arguments
FocusDown = { {"Down"}, doc = "move focus down", event = "FocusMove", args = {0, 1} }, FocusUp = { {"Up"}, doc = "move focus up", event = "FocusMove", args = {0, -1} },
FocusLeft = { {"Left"}, doc = "move focus left", event = "FocusMove", args = {-1, 0} }, FocusDown = { {"Down"}, doc = "move focus down", event = "FocusMove", args = {0, 1} },
FocusRight = { {"Right"}, doc = "move focus right", event = "FocusMove", args = {1, 0} }, FocusLeft = { {"Left"}, doc = "move focus left", event = "FocusMove", args = {-1, 0} },
} FocusRight = { {"Right"}, doc = "move focus right", event = "FocusMove", args = {1, 0} },
}
end
end end
function FocusManager:onFocusMove(args) function FocusManager:onFocusMove(args)
@ -62,7 +65,9 @@ function FocusManager:onFocusMove(args)
end end
elseif not self.layout[self.selected.y + dy][self.selected.x] then elseif not self.layout[self.selected.y + dy][self.selected.x] then
--inner horizontal border, trying to be clever and step down --inner horizontal border, trying to be clever and step down
self:_verticalStep(dy) if not self:_verticalStep(dy) then
break
end
elseif not self.layout[self.selected.y + dy][self.selected.x + dx] then elseif not self.layout[self.selected.y + dy][self.selected.x + dx] then
--vertical border, no wraparound --vertical border, no wraparound
break break
@ -97,7 +102,7 @@ function FocusManager:_wrapAround(dy)
self.selected.y = y self.selected.y = y
if not self.layout[self.selected.y][self.selected.x] then if not self.layout[self.selected.y][self.selected.x] then
--call verticalStep on the current line to perform the search --call verticalStep on the current line to perform the search
self:_verticalStep(0) return self:_verticalStep(0)
end end
return true return true
else else
@ -107,6 +112,10 @@ end
function FocusManager:_verticalStep(dy) function FocusManager:_verticalStep(dy)
local x = self.selected.x local x = self.selected.x
if type(self.layout[self.selected.y + dy]) ~= "table" or self.layout[self.selected.y + dy] == {} then
logger.err("[FocusManager] : Malformed layout")
return false
end
--looking for the item on the line below, the closest on the left side --looking for the item on the line below, the closest on the left side
while not self.layout[self.selected.y + dy][x] do while not self.layout[self.selected.y + dy][x] do
x = x - 1 x = x - 1
@ -120,6 +129,7 @@ function FocusManager:_verticalStep(dy)
end end
self.selected.x = x self.selected.x = x
self.selected.y = self.selected.y + dy self.selected.y = self.selected.y + dy
return true
end end
function FocusManager:getFocusItem() function FocusManager:getFocusItem()

@ -18,8 +18,8 @@ Example:
show_icon = false, show_icon = false,
timeout = 5, -- This widget will vanish in 5 seconds. timeout = 5, -- This widget will vanish in 5 seconds.
} }
sample_input:onShowKeyboard()
UIManager:show(sample_input) UIManager:show(sample_input)
sample_input:onShowKeyboard()
]] ]]
local Blitbuffer = require("ffi/blitbuffer") local Blitbuffer = require("ffi/blitbuffer")

@ -34,8 +34,8 @@ Example:
} }
}, },
} }
sample_input:onShowKeyboard()
UIManager:show(sample_input) UIManager:show(sample_input)
sample_input:onShowKeyboard()
If it would take the user more than half a minute to recover from a mistake, If it would take the user more than half a minute to recover from a mistake,
a "Cancel" button <em>must</em> be added to the dialog. The cancellation button a "Cancel" button <em>must</em> be added to the dialog. The cancellation button
@ -50,6 +50,7 @@ longer than three words it should just read "OK".
local Blitbuffer = require("ffi/blitbuffer") local Blitbuffer = require("ffi/blitbuffer")
local ButtonTable = require("ui/widget/buttontable") local ButtonTable = require("ui/widget/buttontable")
local CenterContainer = require("ui/widget/container/centercontainer") local CenterContainer = require("ui/widget/container/centercontainer")
local Device = require("device")
local Font = require("ui/font") local Font = require("ui/font")
local FrameContainer = require("ui/widget/container/framecontainer") local FrameContainer = require("ui/widget/container/framecontainer")
local Geom = require("ui/geometry") local Geom = require("ui/geometry")
@ -64,9 +65,10 @@ local TextWidget = require("ui/widget/textwidget")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local VerticalGroup = require("ui/widget/verticalgroup") local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan") local VerticalSpan = require("ui/widget/verticalspan")
local Screen = require("device").screen local Screen = Device.screen
local InputDialog = InputContainer:new{ local InputDialog = InputContainer:new{
is_always_active = true,
title = "", title = "",
input = "", input = "",
input_hint = "", input_hint = "",
@ -195,6 +197,10 @@ function InputDialog:init()
} }
} }
} }
if Device:hasKeys() then
--little hack to piggyback on the layout of the button_table to handle the new InputText
table.insert(self.button_table.layout, 1, {self._input_widget})
end
self[1] = CenterContainer:new{ self[1] = CenterContainer:new{
dimen = Geom:new{ dimen = Geom:new{

@ -39,58 +39,76 @@ local InputText = InputContainer:new{
} }
-- only use PhysicalKeyboard if the device does not have touch screen -- only use PhysicalKeyboard if the device does not have touch screen
if Device.isTouchDevice() then if Device.isTouchDevice() or Device.hasDPad() then
Keyboard = require("ui/widget/virtualkeyboard") Keyboard = require("ui/widget/virtualkeyboard")
function InputText:initEventListener() if Device.isTouchDevice() then
self.ges_events = { function InputText:initEventListener()
TapTextBox = { self.ges_events = {
GestureRange:new{ TapTextBox = {
ges = "tap", GestureRange:new{
range = self.dimen ges = "tap",
} range = self.dimen
}, }
HoldTextBox = { },
GestureRange:new{ HoldTextBox = {
ges = "hold", GestureRange:new{
range = self.dimen ges = "hold",
} range = self.dimen
}, }
} },
end }
end
function InputText:onTapTextBox(arg, ges) function InputText:onTapTextBox(arg, ges)
if self.parent.onSwitchFocus then if self.parent.onSwitchFocus then
self.parent:onSwitchFocus(self) self.parent:onSwitchFocus(self)
end
local x = ges.pos.x - self._frame_textwidget.dimen.x - self.bordersize - self.padding
local y = ges.pos.y - self._frame_textwidget.dimen.y - self.bordersize - self.padding
if x > 0 and y > 0 then
self.charpos = self.text_widget:moveCursor(x, y)
UIManager:setDirty(self.parent, function()
return "ui", self.dimen
end)
end
end end
local x = ges.pos.x - self._frame_textwidget.dimen.x - self.bordersize - self.padding
local y = ges.pos.y - self._frame_textwidget.dimen.y - self.bordersize - self.padding function InputText:onHoldTextBox(arg, ges)
if x > 0 and y > 0 then if self.parent.onSwitchFocus then
self.charpos = self.text_widget:moveCursor(x, y) self.parent:onSwitchFocus(self)
UIManager:setDirty(self.parent, function() end
return "ui", self.dimen local x = ges.pos.x - self._frame_textwidget.dimen.x - self.bordersize - self.padding
end) local y = ges.pos.y - self._frame_textwidget.dimen.y - self.bordersize - self.padding
if x > 0 and y > 0 then
self.charpos = self.text_widget:moveCursor(x, y)
if Device:hasClipboard() and Device.input.hasClipboardText() then
self:addChars(Device.input.getClipboardText())
end
UIManager:setDirty(self.parent, function()
return "ui", self.dimen
end)
end
end end
end end
if Device.hasKeys() then
if not InputText.initEventListener then
function InputText:initEventListener() end
end
function InputText:onHoldTextBox(arg, ges) function InputText:onFocus()
if self.parent.onSwitchFocus then --Event called by the focusmanager
self.parent:onSwitchFocus(self) self.key_events.ShowKeyboard = { {"Press"}, doc = "show keyboard" }
self:focus()
return true
end end
local x = ges.pos.x - self._frame_textwidget.dimen.x - self.bordersize - self.padding
local y = ges.pos.y - self._frame_textwidget.dimen.y - self.bordersize - self.padding function InputText:onUnfocus()
if x > 0 and y > 0 then --Event called by the focusmanager
self.charpos = self.text_widget:moveCursor(x, y) self.key_events = {}
if Device:hasClipboard() and Device.input.hasClipboardText() then self:unfocus()
self:addChars(Device.input.getClipboardText()) return true
end
UIManager:setDirty(self.parent, function()
return "ui", self.dimen
end)
end end
end end
elseif not Device.hasKeyboard() then
Keyboard = require("ui/widget/virtualkeyboard")
function InputText:initEventListener() end --do nothing but doesn't crash for now
else else
Keyboard = require("ui/widget/physicalkeyboard") Keyboard = require("ui/widget/physicalkeyboard")
function InputText:initEventListener() end function InputText:initEventListener() end
@ -219,8 +237,9 @@ function InputText:initKeyboard()
if self.input_type == "number" then if self.input_type == "number" then
keyboard_layout = 4 keyboard_layout = 4
end end
self.key_events = nil
self.keyboard = Keyboard:new{ self.keyboard = Keyboard:new{
layout = keyboard_layout, keyboard_layout = keyboard_layout,
inputbox = self, inputbox = self,
width = Screen:getWidth(), width = Screen:getWidth(),
} }
@ -229,17 +248,18 @@ end
function InputText:unfocus() function InputText:unfocus()
self.focused = false self.focused = false
self.text_widget:unfocus() self.text_widget:unfocus()
self[1].color = Blitbuffer.COLOR_GREY self._frame_textwidget.color = Blitbuffer.COLOR_GREY
end end
function InputText:focus() function InputText:focus()
self.focused = true self.focused = true
self.text_widget:focus() self.text_widget:focus()
self[1].color = Blitbuffer.COLOR_BLACK self._frame_textwidget.color = Blitbuffer.COLOR_BLACK
end end
function InputText:onShowKeyboard() function InputText:onShowKeyboard()
UIManager:show(self.keyboard) UIManager:show(self.keyboard)
return true
end end
function InputText:onCloseKeyboard() function InputText:onCloseKeyboard()

@ -48,6 +48,10 @@ function MultiInputDialog:init()
scroll = false, scroll = false,
parent = self, parent = self,
} }
if Device:hasKeys() then
--little hack to piggyback on the layout of the button_table to handle the new InputText
table.insert(self.button_table.layout, #self.button_table.layout, {input_field[k]})
end
if field.description then if field.description then
input_description[k] = FrameContainer:new{ input_description[k] = FrameContainer:new{
padding = self.description_padding, padding = self.description_padding,
@ -76,6 +80,10 @@ function MultiInputDialog:init()
}) })
end end
if Device:hasKeys() then
--remove the not needed hack in inputdialog
table.remove(self.button_table.layout, 1)
end
-- Add same vertical space after than before InputText -- Add same vertical space after than before InputText
table.insert(VerticalGroupData,CenterContainer:new{ table.insert(VerticalGroupData,CenterContainer:new{
dimen = Geom:new{ dimen = Geom:new{
@ -131,8 +139,6 @@ function MultiInputDialog:onSwitchFocus(inputbox)
self._input_widget = inputbox self._input_widget = inputbox
self._input_widget:focus() self._input_widget:focus()
self._input_widget:onShowKeyboard() self._input_widget:onShowKeyboard()
UIManager:show(self)
end end
return MultiInputDialog return MultiInputDialog

@ -300,8 +300,8 @@ function NetworkItem:onEditNetwork()
}, },
}, },
} }
password_input:onShowKeyboard()
UIManager:show(password_input) UIManager:show(password_input)
password_input:onShowKeyboard()
return true return true
end end
@ -331,8 +331,8 @@ function NetworkItem:onAddNetwork()
}, },
}, },
} }
password_input:onShowKeyboard()
UIManager:show(password_input) UIManager:show(password_input)
password_input:onShowKeyboard()
return true return true
end end

@ -139,8 +139,8 @@ function NumberPickerWidget:paintWidget()
}, },
}, },
} }
input:onShowKeyboard()
UIManager:show(input) UIManager:show(input)
input:onShowKeyboard()
end end
end end

@ -146,8 +146,8 @@ function OPDSBrowser:addNewCatalog()
width = Screen:getWidth() * 0.95, width = Screen:getWidth() * 0.95,
height = Screen:getHeight() * 0.2, height = Screen:getHeight() * 0.2,
} }
self.add_server_dialog:onShowKeyboard()
UIManager:show(self.add_server_dialog) UIManager:show(self.add_server_dialog)
self.add_server_dialog:onShowKeyboard()
end end
function OPDSBrowser:editCalibreServer() function OPDSBrowser:editCalibreServer()
@ -187,8 +187,8 @@ function OPDSBrowser:editCalibreServer()
width = Screen:getWidth() * 0.95, width = Screen:getWidth() * 0.95,
height = Screen:getHeight() * 0.2, height = Screen:getHeight() * 0.2,
} }
self.add_server_dialog:onShowKeyboard()
UIManager:show(self.add_server_dialog) UIManager:show(self.add_server_dialog)
self.add_server_dialog:onShowKeyboard()
end end
function OPDSBrowser:genItemTableFromRoot() function OPDSBrowser:genItemTableFromRoot()
@ -322,8 +322,8 @@ function OPDSBrowser:fetchWithLogin(host, callback)
height = Screen:getHeight() * 0.4, height = Screen:getHeight() * 0.4,
} }
self.login_dialog:onShowKeyboard()
UIManager:show(self.login_dialog) UIManager:show(self.login_dialog)
self.login_dialog:onShowKeyboard()
end end
function OPDSBrowser:closeDialog() function OPDSBrowser:closeDialog()
@ -679,8 +679,8 @@ function OPDSBrowser:editOPDSServer(item)
width = Screen:getWidth() * 0.95, width = Screen:getWidth() * 0.95,
height = Screen:getHeight() * 0.2, height = Screen:getHeight() * 0.2,
} }
self.edit_server_dialog:onShowKeyboard()
UIManager:show(self.edit_server_dialog) UIManager:show(self.edit_server_dialog)
self.edit_server_dialog:onShowKeyboard()
end end
function OPDSBrowser:deleteOPDSServer(item) function OPDSBrowser:deleteOPDSServer(item)

@ -2,6 +2,8 @@ local Blitbuffer = require("ffi/blitbuffer")
local BottomContainer = require("ui/widget/container/bottomcontainer") local BottomContainer = require("ui/widget/container/bottomcontainer")
local CenterContainer = require("ui/widget/container/centercontainer") local CenterContainer = require("ui/widget/container/centercontainer")
local Device = require("device") local Device = require("device")
local Event = require("ui/event")
local FocusManager = require("ui/widget/focusmanager")
local Font = require("ui/font") local Font = require("ui/font")
local FrameContainer = require("ui/widget/container/framecontainer") local FrameContainer = require("ui/widget/container/framecontainer")
local Geom = require("ui/geometry") local Geom = require("ui/geometry")
@ -112,6 +114,14 @@ function VirtualKey:update_keyboard()
end) end)
end end
function VirtualKey:onFocus()
self[1].invert = true
end
function VirtualKey:onUnfocus()
self[1].invert = false
end
function VirtualKey:onTapSelect() function VirtualKey:onTapSelect()
if self.flash_keyboard then if self.flash_keyboard then
self[1].invert = true self[1].invert = true
@ -149,8 +159,8 @@ function VirtualKey:invert(invert)
self:update_keyboard() self:update_keyboard()
end end
local VirtualKeyboard = InputContainer:new{ local VirtualKeyboard = FocusManager:new{
is_always_active = true, modal = true,
disable_double_tap = true, disable_double_tap = true,
inputbox = nil, inputbox = nil,
KEYS = {}, -- table to store layouts KEYS = {}, -- table to store layouts
@ -160,11 +170,12 @@ local VirtualKeyboard = InputContainer:new{
umlautmode_keys = {}, umlautmode_keys = {},
min_layout = 2, min_layout = 2,
max_layout = 12, max_layout = 12,
layout = 2, keyboard_layout = 2,
shiftmode = false, shiftmode = false,
symbolmode = false, symbolmode = false,
utf8mode = false, utf8mode = false,
umlautmode = false, umlautmode = false,
layout = {},
width = Screen:scaleBySize(600), width = Screen:scaleBySize(600),
height = nil, height = nil,
@ -191,7 +202,21 @@ function VirtualKeyboard:init()
self.utf8mode_keys = keyboard.utf8mode_keys self.utf8mode_keys = keyboard.utf8mode_keys
self.umlautmode_keys = keyboard.umlautmode_keys self.umlautmode_keys = keyboard.umlautmode_keys
self.height = Screen:scaleBySize(64 * #self.KEYS) self.height = Screen:scaleBySize(64 * #self.KEYS)
self:initLayout(self.layout) self:initLayout(self.keyboard_layout)
if Device:hasKeys() then
self.key_events.PressKey = { {"Press"}, doc = "select key" }
self.key_events.Close = { {"Back"}, doc = "close keyboard" }
end
end
function VirtualKeyboard:onClose()
UIManager:close(self)
return true
end
function VirtualKeyboard:onPressKey()
self:getFocusItem():handleEvent(Event:new("TapSelect"))
return true
end end
function VirtualKeyboard:_refresh() function VirtualKeyboard:_refresh()
@ -223,19 +248,20 @@ function VirtualKeyboard:initLayout(layout)
-- to be sure layout is selected properly -- to be sure layout is selected properly
layout = math.max(layout, self.min_layout) layout = math.max(layout, self.min_layout)
layout = math.min(layout, self.max_layout) layout = math.min(layout, self.max_layout)
self.layout = layout self.keyboard_layout = layout
-- fill the layout modes -- fill the layout modes
self.shiftmode = (layout == 1 or layout == 3 or layout == 5 or layout == 7 or layout == 9 or layout == 11) self.shiftmode = (layout == 1 or layout == 3 or layout == 5 or layout == 7 or layout == 9 or layout == 11)
self.symbolmode = (layout == 3 or layout == 4 or layout == 7 or layout == 8 or layout == 11 or layout == 12) self.symbolmode = (layout == 3 or layout == 4 or layout == 7 or layout == 8 or layout == 11 or layout == 12)
self.utf8mode = (layout == 5 or layout == 6 or layout == 7 or layout == 8) self.utf8mode = (layout == 5 or layout == 6 or layout == 7 or layout == 8)
self.umlautmode = (layout == 9 or layout == 10 or layout == 11 or layout == 12) self.umlautmode = (layout == 9 or layout == 10 or layout == 11 or layout == 12)
else -- or, without input parameter, restore layout from current layout modes else -- or, without input parameter, restore layout from current layout modes
self.layout = VKLayout(self.shiftmode, self.symbolmode, self.utf8mode, self.umlautmode) self.keyboard_layout = VKLayout(self.shiftmode, self.symbolmode, self.utf8mode, self.umlautmode)
end end
self:addKeys() self:addKeys()
end end
function VirtualKeyboard:addKeys() function VirtualKeyboard:addKeys()
self.layout = {}
local base_key_width = math.floor((self.width - (#self.KEYS[1] + 1)*self.key_padding - 2*self.padding)/#self.KEYS[1]) local base_key_width = math.floor((self.width - (#self.KEYS[1] + 1)*self.key_padding - 2*self.padding)/#self.KEYS[1])
local base_key_height = math.floor((self.height - (#self.KEYS + 1)*self.key_padding - 2*self.padding)/#self.KEYS) local base_key_height = math.floor((self.height - (#self.KEYS + 1)*self.key_padding - 2*self.padding)/#self.KEYS)
local h_key_padding = HorizontalSpan:new{width = self.key_padding} local h_key_padding = HorizontalSpan:new{width = self.key_padding}
@ -243,14 +269,15 @@ function VirtualKeyboard:addKeys()
local vertical_group = VerticalGroup:new{} local vertical_group = VerticalGroup:new{}
for i = 1, #self.KEYS do for i = 1, #self.KEYS do
local horizontal_group = HorizontalGroup:new{} local horizontal_group = HorizontalGroup:new{}
local layout_horizontal = {}
for j = 1, #self.KEYS[i] do for j = 1, #self.KEYS[i] do
local width_factor = self.KEYS[i][j].width or 1.0 local width_factor = self.KEYS[i][j].width or 1.0
local key_width = math.floor((base_key_width + self.key_padding) * width_factor) local key_width = math.floor((base_key_width + self.key_padding) * width_factor)
- self.key_padding - self.key_padding
local key_height = base_key_height local key_height = base_key_height
local label = self.KEYS[i][j].label or self.KEYS[i][j][self.layout] local label = self.KEYS[i][j].label or self.KEYS[i][j][self.keyboard_layout]
local key = VirtualKey:new{ local key = VirtualKey:new{
key = self.KEYS[i][j][self.layout], key = self.KEYS[i][j][self.keyboard_layout],
icon = self.KEYS[i][j].icon, icon = self.KEYS[i][j].icon,
label = label, label = label,
keyboard = self, keyboard = self,
@ -258,11 +285,13 @@ function VirtualKeyboard:addKeys()
height = key_height, height = key_height,
} }
table.insert(horizontal_group, key) table.insert(horizontal_group, key)
table.insert(layout_horizontal, key)
if j ~= #self.KEYS[i] then if j ~= #self.KEYS[i] then
table.insert(horizontal_group, h_key_padding) table.insert(horizontal_group, h_key_padding)
end end
end end
table.insert(vertical_group, horizontal_group) table.insert(vertical_group, horizontal_group)
table.insert(self.layout, layout_horizontal)
if i ~= #self.KEYS then if i ~= #self.KEYS then
table.insert(vertical_group, v_key_padding) table.insert(vertical_group, v_key_padding)
end end

@ -216,8 +216,8 @@ function EvernoteExporter:login()
height = Screen:getHeight() * 0.4, height = Screen:getHeight() * 0.4,
} }
self.login_dialog:onShowKeyboard()
UIManager:show(self.login_dialog) UIManager:show(self.login_dialog)
self.login_dialog:onShowKeyboard()
end end
function EvernoteExporter:closeDialog() function EvernoteExporter:closeDialog()

@ -143,8 +143,8 @@ How to generate a key and a secret key:
height = Screen:getHeight() * 0.2, height = Screen:getHeight() * 0.2,
input_type = "text", input_type = "text",
} }
self.settings_dialog:onShowKeyboard()
UIManager:show(self.settings_dialog) UIManager:show(self.settings_dialog)
self.settings_dialog:onShowKeyboard()
end end
function Goodreads:saveSettings(fields) function Goodreads:saveSettings(fields)
@ -227,8 +227,8 @@ function Goodreads:search(search_type)
} }
}, },
} }
search_input:onShowKeyboard()
UIManager:show(search_input) UIManager:show(search_input)
search_input:onShowKeyboard()
end end
return Goodreads return Goodreads

@ -290,8 +290,8 @@ function KOSync:login()
height = Screen:getHeight() * 0.4, height = Screen:getHeight() * 0.4,
} }
self.login_dialog:onShowKeyboard()
UIManager:show(self.login_dialog) UIManager:show(self.login_dialog)
self.login_dialog:onShowKeyboard()
end end
function KOSync:closeDialog() function KOSync:closeDialog()

@ -153,8 +153,8 @@ function PerceptionExpander:showSettingsDialog()
width = Screen:getWidth() * 0.8, width = Screen:getWidth() * 0.8,
height = Screen:getHeight() * 0.3, height = Screen:getHeight() * 0.3,
} }
self.settings_dialog:onShowKeyboard()
UIManager:show(self.settings_dialog) UIManager:show(self.settings_dialog)
self.settings_dialog:onShowKeyboard()
end end
function PerceptionExpander:addToMainMenu(menu_items) function PerceptionExpander:addToMainMenu(menu_items)

@ -662,8 +662,8 @@ function ReaderStatistics:updateSettings()
height = Screen:getHeight() * 0.2, height = Screen:getHeight() * 0.2,
input_type = "number", input_type = "number",
} }
self.settings_dialog:onShowKeyboard()
UIManager:show(self.settings_dialog) UIManager:show(self.settings_dialog)
self.settings_dialog:onShowKeyboard()
end end
function ReaderStatistics:addToMainMenu(menu_items) function ReaderStatistics:addToMainMenu(menu_items)

@ -39,8 +39,8 @@ function Terminal:start()
end, end,
}}}, }}},
} }
self.input:onShowKeyboard()
UIManager:show(self.input) UIManager:show(self.input)
self.input:onShowKeyboard()
end end
function Terminal:execute() function Terminal:execute()

Loading…
Cancel
Save