Some platforms with horribly broken MT handling (hai, PB) will manage to
screw something up so bad that we end up with slots never running
through initialState on a contact down, so they never get an initial_tev
recorded.
Ensure we do that if necessary when switching a buddy to voidState to
avoid crashes throughout the code, which assumes everything is sane and
doesn't guard accesses to initial_tev
Re: #11196, #10950 & #11111Closes: #11111
@ -139,7 +139,7 @@ function GestureDetector:newContact(slot)
state=Contact.initialState,-- Current state function
slot=slot,-- Current ABS_MT_SLOT value (also its key in the active_contacts hash)
id=-1,-- Current ABS_MT_TRACKING_ID value
initial_tev=nil,-- Copy of the input event table at first contact (i.e., at contact down)
initial_tev=nil,-- Copy of the input event table at first contact (i.e., at contact down [iff the platform is sane, might be a copy of current_tev otherwise])
current_tev=nil,-- Pointer to the current input event table, ref is *stable*, c.f., NOTE in feedEvent below
down=false,-- Contact is down (as opposed to up, i.e., lifted). Only really happens for double-tap handling, in every other case the Contact object is destroyed on lift.
pending_double_tap_timer=false,-- Contact is pending a double_tap timer
@ -379,6 +379,17 @@ function Contact:switchState(state_func, func_arg)
returnstate_func(self,func_arg)
end
-- Unlike switchState, we don't *call* the new state, and we ensure that initial_tev is set,
-- in case initialState never ran on a contact down because the platform screwed up (e.g., PB with broken MT).
-- The rest of the code, in particular the buddy system, assumes initial_tev is always set (and supposedly sane).
functionContact:setState(state_func)
-- NOTE: Safety net for broken platforms that might screw up slot order...
ifnotself.initial_tevthen
self.initial_tev=deepCopyEv(self.current_tev)
end
self.state=state_func
end
functionContact:initialState()
localtev=self.current_tev
@ -483,7 +494,7 @@ function Contact:tapState(new_tap)
-- Mark that slot
self.mt_gesture="tap"
-- Neuter its buddy
buddy_contact.state =Contact.voidState
buddy_contact:setState(Contact.voidState)
buddy_contact.mt_gesture="tap"
localpos0=Geom:new{
@ -513,7 +524,7 @@ function Contact:tapState(new_tap)
logger.dbg("Contact:tapState: Two-contact tap failed to pass the two_finger_tap constraints -> single tap @",tev.x,tev.y)
-- We blew the gesture position/time constraints,
-- neuter buddy and send a single tap on this slot.
buddy_contact.state =Contact.voidState
buddy_contact:setState(Contact.voidState)
gesture_detector:dropContact(self)
return{
@ -714,7 +725,7 @@ function Contact:panState(keep_contact)