mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
UIManager: Don't block gestures for new widgets when input is disabled (#11122)
They'll be disabled again when the widget in question is dismissed. This exposes a couple of semi-obvious but edge-casey footguns to the user, but a hardened implementation is way uglier. See PR for details.
This commit is contained in:
@@ -355,4 +355,10 @@ function DeviceListener:onFullRefresh()
|
||||
UIManager:setDirty(nil, "full")
|
||||
end
|
||||
|
||||
-- On resume, make sure we restore Gestures handling in InputContainer, to avoid confusion for scatter-brained users ;).
|
||||
-- It's also helpful when the IgnoreTouchInput event is emitted by Dispatcher through other means than Gestures.
|
||||
function DeviceListener:onResume()
|
||||
UIManager:setIgnoreTouchInput(false)
|
||||
end
|
||||
|
||||
return DeviceListener
|
||||
|
||||
@@ -753,6 +753,9 @@ function Screensaver:show()
|
||||
widget = addOverlayMessage(widget, message_height, self.overlay_message)
|
||||
end
|
||||
|
||||
-- NOTE: Make sure InputContainer gestures are not disabled, to prevent stupid interactions with UIManager on close.
|
||||
UIManager:setIgnoreTouchInput(false)
|
||||
|
||||
if widget then
|
||||
self.screensaver_widget = ScreenSaverWidget:new{
|
||||
widget = widget,
|
||||
|
||||
@@ -42,6 +42,7 @@ local UIManager = {
|
||||
_gated_quit = nil,
|
||||
_prevent_standby_count = 0,
|
||||
_prev_prevent_standby_count = 0,
|
||||
_input_gestures_disabled = false,
|
||||
|
||||
event_hook = require("ui/hook_container"):new()
|
||||
}
|
||||
@@ -113,6 +114,12 @@ function UIManager:init()
|
||||
self:unsetRunForeverMode()
|
||||
end
|
||||
|
||||
-- Crappy wrapper because of circular dependencies
|
||||
function UIManager:setIgnoreTouchInput(state)
|
||||
local InputContainer = require("ui/widget/container/inputcontainer")
|
||||
InputContainer:setIgnoreTouchInput(state)
|
||||
end
|
||||
|
||||
--[[--
|
||||
Registers and shows a widget.
|
||||
|
||||
@@ -165,6 +172,13 @@ function UIManager:show(widget, refreshtype, refreshregion, x, y, refreshdither)
|
||||
Input.disable_double_tap = widget.disable_double_tap ~= false
|
||||
-- a widget may override tap interval (when it doesn't, nil restores the default)
|
||||
Input.tap_interval_override = widget.tap_interval_override
|
||||
-- If input was disabled, re-enable it while this widget is shown so we can actually interact with it.
|
||||
-- The only thing that could actually call show in this state is something automatic, so we need to be able to deal with it.
|
||||
if UIManager._input_gestures_disabled then
|
||||
logger.dbg("Gestures were disabled, temporarily re-enabling them to allow interaction with widget")
|
||||
self:setIgnoreTouchInput(false)
|
||||
widget._restored_input_gestures = true
|
||||
end
|
||||
end
|
||||
|
||||
--[[--
|
||||
@@ -245,6 +259,10 @@ function UIManager:close(widget, refreshtype, refreshregion, refreshdither)
|
||||
end
|
||||
self:_refresh(refreshtype, refreshregion, refreshdither)
|
||||
end
|
||||
if widget._restored_input_gestures then
|
||||
logger.dbg("Widget is gone, disabling gesture handling again")
|
||||
self:setIgnoreTouchInput(true)
|
||||
end
|
||||
end
|
||||
|
||||
--- Shift the execution times of all scheduled tasks.
|
||||
|
||||
@@ -41,6 +41,7 @@ local Geom = require("ui/geometry")
|
||||
local GestureRange = require("ui/gesturerange")
|
||||
local UIManager = require("ui/uimanager")
|
||||
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
||||
local logger = require("logger")
|
||||
local Screen = Device.screen
|
||||
local _ = require("gettext")
|
||||
|
||||
@@ -304,41 +305,56 @@ end
|
||||
-- [1] The most common implementation you'll see is a NOP for ReaderUI modules that defer gesture handling to ReaderUI.
|
||||
-- Notification also implements a simple one to dismiss notifications on any user input,
|
||||
-- which is something that doesn't impede our goal, which is why we don't need to deal with it.
|
||||
function InputContainer:onIgnoreTouchInput(toggle)
|
||||
local Notification = require("ui/widget/notification")
|
||||
if toggle == false then
|
||||
-- Restore the proper onGesture handler if we disabled it
|
||||
if InputContainer._onGesture then
|
||||
InputContainer.onGesture = InputContainer._onGesture
|
||||
InputContainer._onGesture = nil
|
||||
Notification:notify("Restored touch input")
|
||||
end
|
||||
elseif toggle == true then
|
||||
function InputContainer:setIgnoreTouchInput(state)
|
||||
logger.dbg("InputContainer:setIgnoreTouchInput", state)
|
||||
if state == true then
|
||||
-- Replace the onGesture handler w/ the minimal one if that's not already the case
|
||||
if not InputContainer._onGesture then
|
||||
InputContainer._onGesture = InputContainer.onGesture
|
||||
InputContainer.onGesture = InputContainer._onGestureFiltered
|
||||
Notification:notify("Disabled touch input")
|
||||
-- Notify UIManager so it knows what to do if a random popup shows up
|
||||
UIManager._input_gestures_disabled = true
|
||||
logger.dbg("Disabled InputContainer gesture handler")
|
||||
|
||||
-- Notify our caller that the state changed
|
||||
return true
|
||||
end
|
||||
elseif state == false then
|
||||
-- Restore the proper onGesture handler if we disabled it
|
||||
if InputContainer._onGesture then
|
||||
InputContainer.onGesture = InputContainer._onGesture
|
||||
InputContainer._onGesture = nil
|
||||
UIManager._input_gestures_disabled = false
|
||||
logger.dbg("Restored InputContainer gesture handler")
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- We did not actually change the state
|
||||
return false
|
||||
end
|
||||
|
||||
-- And the matching Event handler
|
||||
function InputContainer:onIgnoreTouchInput(toggle)
|
||||
local Notification = require("ui/widget/notification")
|
||||
if toggle == true then
|
||||
if self:setIgnoreTouchInput(true) then
|
||||
Notification:notify(_("Disabled touch input"))
|
||||
end
|
||||
elseif toggle == false then
|
||||
if self:setIgnoreTouchInput(false) then
|
||||
Notification:notify(_("Restored touch input"))
|
||||
end
|
||||
else
|
||||
-- Toggle the current state
|
||||
if InputContainer._onGesture then
|
||||
return self:onIgnoreTouchInput(false)
|
||||
else
|
||||
return self:onIgnoreTouchInput(true)
|
||||
end
|
||||
return self:onIgnoreTouchInput(not UIManager._input_gestures_disabled)
|
||||
end
|
||||
|
||||
-- We only affect the base class, once is enough ;).
|
||||
return true
|
||||
end
|
||||
|
||||
function InputContainer:onResume()
|
||||
-- Always restore touch input on resume, to avoid confusion for scatter-brained users ;).
|
||||
-- It's also helpful when the IgnoreTouchInput event is emitted by Dispatcher through other means than Gestures.
|
||||
self:onIgnoreTouchInput(false)
|
||||
end
|
||||
|
||||
function InputContainer:onInput(input, ignore_first_hold_release)
|
||||
local InputDialog = require("ui/widget/inputdialog")
|
||||
self.input_dialog = InputDialog:new{
|
||||
|
||||
Reference in New Issue
Block a user