VirtualKeyboard: Revamp visibility handling (#10852)

Move as much of the state tracking as possible inside VirtualKeyboard itself.
InputDialog unfortunately needs an internal tracking of this state because it needs to know about it *before* the VK is shown, so we have to keep a bit of duplication in there, although we do try much harder to keep everything in sync (at least at function call edges), and to keep the damage contained to, essentially, the toggle button's handler.

(Followup to #10803 & #10850)
This commit is contained in:
NiLuJe
2023-09-01 22:51:41 +02:00
committed by GitHub
parent 4d620d9fd2
commit 4cc620b702
7 changed files with 211 additions and 83 deletions

View File

@@ -32,9 +32,8 @@ local InputText = InputContainer:extend{
focused = true,
parent = nil, -- parent dialog that will be set dirty
edit_callback = nil, -- called with true when text modified, false on init or text re-set
scroll_callback = nil, -- called with (low, high) when view is scrolled (cf ScrollTextWidget)
scroll_callback = nil, -- called with (low, high) when view is scrolled (c.f., ScrollTextWidget)
scroll_by_pan = false, -- allow scrolling by lines with Pan (needs scroll=true)
manage_keyboard_state = true, -- manage keyboard hidden/shown state
width = nil,
height = nil, -- when nil, will be set to original text height (possibly
@@ -54,7 +53,10 @@ local InputText = InputContainer:extend{
auto_para_direction = false,
alignment_strict = false,
readonly = nil, -- will not support a Keyboard widget if true
-- for internal use
keyboard = nil, -- Keyboard widget (either VirtualKeyboard or PhysicalKeyboard)
text_widget = nil, -- Text Widget for cursor movement, possibly a ScrollTextWidget
charlist = nil, -- table of individual chars from input string
charpos = nil, -- position of the cursor, where a new char would be inserted
@@ -65,7 +67,6 @@ local InputText = InputContainer:extend{
for_measurement_only = nil, -- When the widget is a one-off used to compute text height
do_select = false, -- to start text selection
selection_start_pos = nil, -- selection start position
is_keyboard_hidden = true, -- to be able to show the keyboard again when it was hidden. (On init, it's the caller's responsibility to call onShowKeyboard, as far as we're concerned, it's hidden)
}
-- These may be (internally) overloaded as needed, depending on Device capabilities.
@@ -73,6 +74,11 @@ function InputText:initEventListener() end
function InputText:onFocus() end
function InputText:onUnfocus() end
-- Resync our position state with our text widget's actual state
function InputText:resyncPos()
self.charpos, self.top_line_num = self.text_widget:getCharPos()
end
local function initTouchEvents()
if Device:isTouchDevice() then
function InputText:initEventListener()
@@ -133,8 +139,8 @@ local function initTouchEvents()
if self.parent.onSwitchFocus then
self.parent:onSwitchFocus(self)
else
if self.is_keyboard_hidden and self.manage_keyboard_state then
self:onShowKeyboard()
if self.keyboard then
self.keyboard:showKeyboard()
end
end
-- zh keyboard with candidates shown here has _frame_textwidget.dimen = nil.
@@ -144,7 +150,7 @@ local function initTouchEvents()
local x = ges.pos.x - self._frame_textwidget.dimen.x - textwidget_offset
local y = ges.pos.y - self._frame_textwidget.dimen.y - textwidget_offset
self.text_widget:moveCursorToXY(x, y, true) -- restrict_to_view=true
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
return true
end
@@ -512,7 +518,7 @@ function InputText:initTextBox(text, char_added)
}
end
-- Get back possibly modified charpos and virtual_line_num
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
self._frame_textwidget = FrameContainer:new{
bordersize = self.bordersize,
@@ -676,22 +682,27 @@ dbg:guard(InputText, "onTextInput",
end)
function InputText:onShowKeyboard(ignore_first_hold_release)
Device:startTextInput()
if self.is_keyboard_hidden or not self.manage_keyboard_state then
self.keyboard.ignore_first_hold_release = ignore_first_hold_release
UIManager:show(self.keyboard)
self.is_keyboard_hidden = false
if self.keyboard then
self.keyboard:showKeyboard(ignore_first_hold_release)
end
return true
end
function InputText:onCloseKeyboard()
Device:stopTextInput()
if self.keyboard then
self.keyboard:hideKeyboard()
end
end
if not self.is_keyboard_hidden or not self.manage_keyboard_state then
UIManager:close(self.keyboard)
self.is_keyboard_hidden = true
function InputText:isKeyboardVisible()
if self.keyboard then
return self.keyboard:isVisible()
end
end
function InputText:lockKeyboard(toggle)
if self.keyboard then
return self.keyboard:lockVisibility(toggle)
end
end
@@ -873,71 +884,71 @@ end
function InputText:leftChar()
if self.charpos == 1 then return end
self.text_widget:moveCursorLeft()
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:rightChar()
if self.charpos > #self.charlist then return end
self.text_widget:moveCursorRight()
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:goToStartOfLine()
local new_pos = select(1, self:getStringPos({"\n", "\r"}, {"\n", "\r"}))
self.text_widget:moveCursorToCharPos(new_pos)
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:goToEndOfLine()
local new_pos = select(2, self:getStringPos({"\n", "\r"}, {"\n", "\r"})) + 1
self.text_widget:moveCursorToCharPos(new_pos)
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:goToHome()
self.text_widget:moveCursorHome()
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:goToEnd()
self.text_widget:moveCursorEnd()
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:moveCursorToCharPos(char_pos)
self.text_widget:moveCursorToCharPos(char_pos)
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:upLine()
self.text_widget:moveCursorUp()
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:downLine()
if #self.charlist == 0 then return end -- Avoid cursor moving within a hint.
self.text_widget:moveCursorDown()
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:scrollDown()
self.text_widget:scrollDown()
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:scrollUp()
self.text_widget:scrollUp()
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:scrollToTop()
self.text_widget:scrollToTop()
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:scrollToBottom()
self.text_widget:scrollToBottom()
self.charpos, self.top_line_num = self.text_widget:getCharPos()
self:resyncPos()
end
function InputText:clear()