GestureDetector: Make two_finger pans & swipes report the same sort of data than their standard brethren (#10649)

Namely, that swipes report the gesture's *starting* coordinates as `pos` (for hit-detection purposes), while pans (and basically everything else) use the *lift* coordinates (as well as provide a relative vector).

In each case, we now also provide a separate `start_pos`/`end_pos`, in case handlers need finer-grained data (e.g., anchoring UI elements to a swipe's lift coordinates).
reviewable/pr10671/r1
NiLuJe 11 months ago committed by GitHub
parent b4000d84a5
commit 4194244951
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -722,6 +722,13 @@ function Contact:panState(keep_contact)
-- Only accept gestures that require both contacts to have been lifted
if ges_ev.ges == "two_finger_pan" then
ges_ev.ges = "two_finger_swipe"
-- Swap from pan semantics to swipe semantics
ges_ev.pos = ges_ev._start_pos
ges_ev._start_pos = nil
ges_ev.start_pos = nil
ges_ev.end_pos = ges_ev._end_pos
ges_ev._end_pos = nil
ges_ev.relative = nil
elseif ges_ev.ges == "inward_pan" then
ges_ev.ges = "pinch"
elseif ges_ev.ges == "outward_pan" then
@ -873,6 +880,12 @@ function Contact:handleSwipe()
w = 0,
h = 0,
}
local end_pos = Geom:new{
x = tev.x,
y = tev.y,
w = 0,
h = 0,
}
local ges = "swipe"
local multiswipe_directions
@ -893,8 +906,13 @@ function Contact:handleSwipe()
gesture_detector:dropContact(self)
return {
ges = ges,
-- use first pan tev coordination as swipe start point
-- NOTE: Unlike every other gesture, we use the *contact* point as the gesture's position,
-- instead of the *lift* point, mainly because that's what makes the most sense
-- from a hit-detection standpoint (c.f., `GestureRange:match` & `InputContainer:onGesture`),
-- and that's 99% of the use-cases where the position actually matters for a swipe.
pos = start_pos,
-- And for those rare cases that need it, we provide the lift point separately.
end_pos = end_pos,
direction = swipe_direction,
multiswipe_directions = multiswipe_directions,
distance = swipe_distance,
@ -932,27 +950,26 @@ function Contact:handlePan()
local pan_ev = {
ges = "pan",
relative = {
-- default to pan 0
x = 0,
y = 0,
x = tev.x - self.initial_tev.x,
y = tev.y - self.initial_tev.y,
},
start_pos = Geom:new{
x = self.initial_tev.x,
y = self.initial_tev.y,
w = 0,
h = 0,
},
pos = Geom:new{
x = tev.x,
y = tev.y,
w = 0,
h = 0,
},
pos = nil,
direction = pan_direction,
distance = pan_distance,
time = tev.timev,
}
-- Regular pan
pan_ev.relative.x = tev.x - self.initial_tev.x
pan_ev.relative.y = tev.y - self.initial_tev.y
pan_ev.pos = Geom:new{
x = tev.x,
y = tev.y,
w = 0,
h = 0,
}
local msd_cnt = #self.multiswipe_directions
local msd_direction_prev = (msd_cnt > 0) and self.multiswipe_directions[msd_cnt][1] or ""
local prev_ms_ev, fake_initial_tev
@ -1070,9 +1087,21 @@ function Contact:handleTwoFingerPan(buddy_contact)
-- We'll also want to remember the span between both contacts on start & end for some gestures
local start_distance = tstart_pos:distance(rstart_pos)
local end_distance = tend_pos:distance(rend_pos)
-- NOTE: "pan" and "hold_pan" use the current/end point as pos,
-- but swipe reports pos as the *starting* point (c.f., `Contact:handleSwipe`).
-- Since this table will be used for both pans and two_finger_swipe (via panState),
-- we stuff a bunch of extra info in there to swap it around as-needed...
local ges_ev = {
ges = "two_finger_pan",
pos = start_point,
relative = {
x = end_point.x - start_point.x,
y = end_point.y - start_point.y,
},
-- Default to the pan semantics, c.f., note above
pos = end_point,
start_pos = start_point,
_start_pos = start_point,
_end_pos = end_point,
distance = avg_distance,
direction = tpan_dir,
time = self.current_tev.timev,
@ -1080,8 +1109,18 @@ function Contact:handleTwoFingerPan(buddy_contact)
if tpan_dir ~= rpan_dir then
if start_distance > end_distance then
ges_ev.ges = "inward_pan"
-- Use the end pos (this is the default already)
ges_ev._start_pos = nil
ges_ev._end_pos = nil
else
ges_ev.ges = "outward_pan"
-- Use the start pos, it'll make more sense than the midpoint of the current contacts,
-- given the potentially wide span between the two...
ges_ev.pos = ges_ev._start_pos
ges_ev._start_pos = nil
ges_ev.start_pos = nil
ges_ev.end_pos = ges_ev._end_pos
ges_ev._end_pos = nil
end
ges_ev.direction = gesture_detector.DIRECTION_TABLE[tpan_dir]
-- Use the the sum of both contacts' travel for the distance
@ -1089,6 +1128,8 @@ function Contact:handleTwoFingerPan(buddy_contact)
-- Some handlers might also want to know the distance between the two contacts on lift & down.
ges_ev.span = end_distance
ges_ev.start_span = start_distance
-- Drop unnecessary field
ges_ev.relative = nil
elseif self.state == Contact.holdState then
ges_ev.ges = "two_finger_hold_pan"
-- Flag 'em for holdState to discriminate with two_finger_hold_release
@ -1130,6 +1171,14 @@ function Contact:handlePanRelease(keep_contact)
logger.dbg("Contact:handlePanRelease: two_finger_pan_release detected")
pan_ev.ges = "two_finger_pan_release"
-- The pan itself used the midpoint between the two contacts, keep doing that.
local buddy_pos = Geom:new{
x = buddy_contact.current_tev.x,
y = buddy_contact.current_tev.y,
w = 0,
h = 0,
}
pan_ev.pos = release_pos:midpoint(buddy_pos)
-- Don't drop buddy, voidState will handle it
-- NOTE: This is yet another rotate hack, emanating from voidState into panState.
if not keep_contact then

Loading…
Cancel
Save