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:
NiLuJe
2023-11-22 18:56:47 +01:00
committed by GitHub
parent f92c0eae3b
commit bc7ea8602e
4 changed files with 65 additions and 22 deletions

View File

@@ -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{