mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Merge pull request #806 from chrox/two_finger_pan
add fine tuning of bbox by swipe gesture
This commit is contained in:
@@ -224,87 +224,18 @@ end
|
||||
this method handles both single and double tap
|
||||
--]]
|
||||
function GestureDetector:tapState(tev)
|
||||
DEBUG("in tap state...")
|
||||
DEBUG("in tap state...", tev)
|
||||
local slot = tev.slot
|
||||
if slot == 1 then
|
||||
if tev.id == -1 and self.last_tevs[0] ~= nil then
|
||||
if self:isTwoFingerTap(self.last_tevs[0], tev) then
|
||||
local pos0 = Geom:new{
|
||||
x = self.last_tevs[0].x,
|
||||
y = self.last_tevs[0].y,
|
||||
w = 0, h = 0,
|
||||
}
|
||||
local pos1 = Geom:new{
|
||||
x = tev.x,
|
||||
y = tev.y,
|
||||
w = 0, h = 0,
|
||||
}
|
||||
local ges_ev = {
|
||||
ges = "two_finger_tap",
|
||||
span = pos0:distance(pos1),
|
||||
time = tev.timev,
|
||||
}
|
||||
DEBUG("two-finger tap detected with span", pos0:distance(pos1))
|
||||
self:clearState(0)
|
||||
self:clearState(1)
|
||||
return ges_ev
|
||||
else
|
||||
self:clearState(0)
|
||||
self:clearState(1)
|
||||
end
|
||||
if tev.id == -1 then
|
||||
return self:handleTwoFingerTap(tev)
|
||||
else
|
||||
return self:handleNonTap(tev)
|
||||
end
|
||||
elseif tev.id == -1 then
|
||||
-- end of tap event
|
||||
if self.last_tevs[slot] ~= nil then
|
||||
local ges_ev = {
|
||||
-- default to single tap
|
||||
ges = "tap",
|
||||
pos = Geom:new{
|
||||
x = self.last_tevs[slot].x,
|
||||
y = self.last_tevs[slot].y,
|
||||
w = 0, h = 0,
|
||||
},
|
||||
time = tev.timev,
|
||||
}
|
||||
-- cur_tap is used for double tap detection
|
||||
local cur_tap = {
|
||||
x = tev.x,
|
||||
y = tev.y,
|
||||
timev = tev.timev,
|
||||
}
|
||||
|
||||
if self.last_taps[slot] ~= nil and
|
||||
self:isDoubleTap(self.last_taps[slot], cur_tap) then
|
||||
-- it is a double tap
|
||||
self:clearState(slot)
|
||||
ges_ev.ges = "double_tap"
|
||||
self.last_taps[slot] = nil
|
||||
DEBUG("double tap detected in slot", slot)
|
||||
return ges_ev
|
||||
end
|
||||
|
||||
-- set current tap to last tap
|
||||
self.last_taps[slot] = cur_tap
|
||||
|
||||
DEBUG("set up tap timer")
|
||||
-- deadline should be calculated by adding current tap time and the interval
|
||||
local deadline = cur_tap.timev + TimeVal:new{
|
||||
sec = 0, usec = self.DOUBLE_TAP_INTERVAL,
|
||||
}
|
||||
Input:setTimeout(function()
|
||||
DEBUG("in tap timer", self.last_taps[slot] ~= nil)
|
||||
-- double tap will set last_tap to nil so if it is not, then
|
||||
-- user must only tapped once
|
||||
if self.last_taps[slot] ~= nil then
|
||||
self.last_taps[slot] = nil
|
||||
-- we are using closure here
|
||||
DEBUG("single tap detected in slot", slot)
|
||||
return ges_ev
|
||||
end
|
||||
end, deadline)
|
||||
-- we are already at the end of touch event
|
||||
-- so reset the state
|
||||
self:clearState(slot)
|
||||
return self:handleDoubleTap(tev)
|
||||
else
|
||||
-- last tev in this slot is cleared by last two finger tap
|
||||
self:clearState(slot)
|
||||
@@ -318,7 +249,95 @@ function GestureDetector:tapState(tev)
|
||||
time = tev.timev,
|
||||
}
|
||||
end
|
||||
elseif self.states[slot] ~= self.tapState then
|
||||
else
|
||||
return self:handleNonTap(tev)
|
||||
end
|
||||
end
|
||||
|
||||
function GestureDetector:handleTwoFingerTap(tev)
|
||||
if self.last_tevs[0] ~= nil and self:isTwoFingerTap(self.last_tevs[0], tev) then
|
||||
local pos0 = Geom:new{
|
||||
x = self.last_tevs[0].x,
|
||||
y = self.last_tevs[0].y,
|
||||
w = 0, h = 0,
|
||||
}
|
||||
local pos1 = Geom:new{
|
||||
x = tev.x,
|
||||
y = tev.y,
|
||||
w = 0, h = 0,
|
||||
}
|
||||
local ges_ev = {
|
||||
ges = "two_finger_tap",
|
||||
pos = pos0,
|
||||
span = pos0:distance(pos1),
|
||||
time = tev.timev,
|
||||
}
|
||||
DEBUG("two-finger tap detected with span", pos0:distance(pos1))
|
||||
self:clearState(0)
|
||||
self:clearState(1)
|
||||
return ges_ev
|
||||
else
|
||||
self:clearState(0)
|
||||
self:clearState(1)
|
||||
end
|
||||
end
|
||||
|
||||
function GestureDetector:handleDoubleTap(tev)
|
||||
local slot = tev.slot
|
||||
local ges_ev = {
|
||||
-- default to single tap
|
||||
ges = "tap",
|
||||
pos = Geom:new{
|
||||
x = self.last_tevs[slot].x,
|
||||
y = self.last_tevs[slot].y,
|
||||
w = 0, h = 0,
|
||||
},
|
||||
time = tev.timev,
|
||||
}
|
||||
-- cur_tap is used for double tap detection
|
||||
local cur_tap = {
|
||||
x = tev.x,
|
||||
y = tev.y,
|
||||
timev = tev.timev,
|
||||
}
|
||||
|
||||
if self.last_taps[slot] ~= nil and
|
||||
self:isDoubleTap(self.last_taps[slot], cur_tap) then
|
||||
-- it is a double tap
|
||||
self:clearState(slot)
|
||||
ges_ev.ges = "double_tap"
|
||||
self.last_taps[slot] = nil
|
||||
DEBUG("double tap detected in slot", slot)
|
||||
return ges_ev
|
||||
end
|
||||
|
||||
-- set current tap to last tap
|
||||
self.last_taps[slot] = cur_tap
|
||||
|
||||
DEBUG("set up tap timer")
|
||||
-- deadline should be calculated by adding current tap time and the interval
|
||||
local deadline = cur_tap.timev + TimeVal:new{
|
||||
sec = 0, usec = self.DOUBLE_TAP_INTERVAL,
|
||||
}
|
||||
Input:setTimeout(function()
|
||||
DEBUG("in tap timer", self.last_taps[slot] ~= nil)
|
||||
-- double tap will set last_tap to nil so if it is not, then
|
||||
-- user must only tapped once
|
||||
if self.last_taps[slot] ~= nil then
|
||||
self.last_taps[slot] = nil
|
||||
-- we are using closure here
|
||||
DEBUG("single tap detected in slot", slot)
|
||||
return ges_ev
|
||||
end
|
||||
end, deadline)
|
||||
-- we are already at the end of touch event
|
||||
-- so reset the state
|
||||
self:clearState(slot)
|
||||
end
|
||||
|
||||
function GestureDetector:handleNonTap(tev)
|
||||
local slot = tev.slot
|
||||
if self.states[slot] ~= self.tapState then
|
||||
-- switched from other state, probably from initialState
|
||||
-- we return nil in this case
|
||||
self.states[slot] = self.tapState
|
||||
@@ -405,6 +424,10 @@ function GestureDetector:panState(tev)
|
||||
y = self.last_tevs[slot].y,
|
||||
w = 0, h = 0,
|
||||
}
|
||||
if self.detectings[0] and self.detectings[1] then
|
||||
pan_ev.ges = "two_finger_pan"
|
||||
DEBUG("two finger pan detected")
|
||||
end
|
||||
return pan_ev
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@ function ReaderScreenshot:init()
|
||||
Screenshot = {
|
||||
GestureRange:new{
|
||||
ges = "two_finger_tap",
|
||||
scale = {diagonal - scaleByDPI(80), diagonal},
|
||||
scale = {diagonal - scaleByDPI(100), diagonal},
|
||||
rate = 1.0,
|
||||
}
|
||||
},
|
||||
|
||||
@@ -21,11 +21,10 @@ function BBoxWidget:init()
|
||||
range = self.view.dimen,
|
||||
}
|
||||
},
|
||||
PanAdjust = {
|
||||
SwipeAdjust = {
|
||||
GestureRange:new{
|
||||
ges = "pan",
|
||||
ges = "swipe",
|
||||
range = self.view.dimen,
|
||||
rate = 3.0, -- emit up to 3 evs per second
|
||||
}
|
||||
},
|
||||
HoldAdjust = {
|
||||
@@ -95,7 +94,7 @@ function BBoxWidget:inPageArea(ges)
|
||||
return not ges.pos:notIntersectWith(page_dimen)
|
||||
end
|
||||
|
||||
function BBoxWidget:adjustScreenBBox(ges)
|
||||
function BBoxWidget:adjustScreenBBox(ges, relative)
|
||||
--DEBUG("adjusting crop bbox with pos", ges.pos)
|
||||
if not self:inPageArea(ges) then return end
|
||||
local bbox = self.screen_bbox
|
||||
@@ -129,13 +128,53 @@ function BBoxWidget:adjustScreenBBox(ges)
|
||||
upper_left.x = ges.pos.x
|
||||
bottom_right.y = ges.pos.y
|
||||
elseif nearest == upper_center then
|
||||
upper_left.y = ges.pos.y
|
||||
if relative then
|
||||
local delta = 0
|
||||
if ges.direction == "up" then
|
||||
delta = -ges.distance / 5
|
||||
elseif ges.direction == "down" then
|
||||
delta = ges.distance / 5
|
||||
end
|
||||
upper_left.y = upper_left.y + delta
|
||||
else
|
||||
upper_left.y = ges.pos.y
|
||||
end
|
||||
elseif nearest == right_center then
|
||||
bottom_right.x = ges.pos.x
|
||||
if relative then
|
||||
local delta = 0
|
||||
if ges.direction == "left" then
|
||||
delta = -ges.distance / 5
|
||||
elseif ges.direction == "right" then
|
||||
delta = ges.distance / 5
|
||||
end
|
||||
bottom_right.x = bottom_right.x + delta
|
||||
else
|
||||
bottom_right.x = ges.pos.x
|
||||
end
|
||||
elseif nearest == bottom_center then
|
||||
bottom_right.y = ges.pos.y
|
||||
if relative then
|
||||
local delta = 0
|
||||
if ges.direction == "up" then
|
||||
delta = -ges.distance / 5
|
||||
elseif ges.direction == "down" then
|
||||
delta = ges.distance / 5
|
||||
end
|
||||
bottom_right.y = bottom_right.y + delta
|
||||
else
|
||||
bottom_right.y = ges.pos.y
|
||||
end
|
||||
elseif nearest == left_center then
|
||||
upper_left.x = ges.pos.x
|
||||
if relative then
|
||||
local delta = 0
|
||||
if ges.direction == "left" then
|
||||
delta = -ges.distance / 5
|
||||
elseif ges.direction == "right" then
|
||||
delta = ges.distance / 5
|
||||
end
|
||||
upper_left.x = upper_left.x + delta
|
||||
else
|
||||
upper_left.x = ges.pos.x
|
||||
end
|
||||
end
|
||||
self.screen_bbox = {
|
||||
x0 = math.round(upper_left.x),
|
||||
@@ -156,8 +195,8 @@ function BBoxWidget:onTapAdjust(arg, ges)
|
||||
return true
|
||||
end
|
||||
|
||||
function BBoxWidget:onPanAdjust(arg, ges)
|
||||
self:adjustScreenBBox(ges)
|
||||
function BBoxWidget:onSwipeAdjust(arg, ges)
|
||||
self:adjustScreenBBox(ges, true)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user