Input: Followup tweaks to #7415 (#7478)

* Actually load librt properly on old Linux systems (fix #7472)
* Made sure SDL & Android honored timeouts properly in some edgy (or not so edgy, in SDL's case) cases (c.f., https://github.com/koreader/koreader-base/pull/1343).
* Try harder not to consume a timer callback when the timerfd backend is in use and `select` timed out *not* because of a timerfd expiring. This would take some particularly heinous timing to reproduce (e.g., a timerfd set, but a task deadline expiring *before* it). May or may not help with #7473.
* Decode `BTN_` KEY codes in verbose debug logs.
* Fix MultiTouch on the H2O (GestureDetector was hard-coding the two slots as 0 & 1, but the H2O kernel is a special snowflake that doesn't use slot 0, instead switching to slot 1 & 2).
reviewable/pr7480/r1
NiLuJe 3 years ago committed by GitHub
parent dfc9d16a19
commit 8a923e3e77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1 +1 @@
Subproject commit bfbc8a3e5c40a2d85653de1e4b93dc64cc8aea2a
Subproject commit 514167d44d8969127f3a05ceed0030e234b22b83

@ -205,18 +205,21 @@ function GestureDetector:isHold(t1, t2)
end
function GestureDetector:isTwoFingerTap()
if self.last_tevs[0] == nil or self.last_tevs[1] == nil then
local s1 = self.input.main_finger_slot
local s2 = self.input.main_finger_slot + 1
if self.last_tevs[s1] == nil or self.last_tevs[s2] == nil then
return false
end
local x_diff0 = math.abs(self.last_tevs[0].x - self.first_tevs[0].x)
local x_diff1 = math.abs(self.last_tevs[1].x - self.first_tevs[1].x)
local y_diff0 = math.abs(self.last_tevs[0].y - self.first_tevs[0].y)
local y_diff1 = math.abs(self.last_tevs[1].y - self.first_tevs[1].y)
local tv_diff0 = self.last_tevs[0].timev - self.first_tevs[0].timev
local x_diff0 = math.abs(self.last_tevs[s1].x - self.first_tevs[s1].x)
local x_diff1 = math.abs(self.last_tevs[s2].x - self.first_tevs[s2].x)
local y_diff0 = math.abs(self.last_tevs[s1].y - self.first_tevs[s1].y)
local y_diff1 = math.abs(self.last_tevs[s2].y - self.first_tevs[s2].y)
local tv_diff0 = self.last_tevs[s1].timev - self.first_tevs[s1].timev
if not tv_diff0:isPositive() then
tv_diff0 = TimeVal:new{ sec = math.huge }
end
local tv_diff1 = self.last_tevs[1].timev - self.first_tevs[1].timev
local tv_diff1 = self.last_tevs[s2].timev - self.first_tevs[s2].timev
if not tv_diff1:isPositive() then
tv_diff1 = TimeVal:new{ sec = math.huge }
end
@ -424,17 +427,19 @@ function GestureDetector:tapState(tev)
logger.dbg("in tap state...")
local slot = tev.slot
if tev.id == -1 then
local s1 = self.input.main_finger_slot
local s2 = self.input.main_finger_slot + 1
-- end of tap event
if self.detectings[0] and self.detectings[1] then
if self.detectings[s1] and self.detectings[s2] then
if self:isTwoFingerTap() then
local pos0 = Geom:new{
x = self.last_tevs[0].x,
y = self.last_tevs[0].y,
x = self.last_tevs[s1].x,
y = self.last_tevs[s1].y,
w = 0, h = 0,
}
local pos1 = Geom:new{
x = self.last_tevs[1].x,
y = self.last_tevs[1].y,
x = self.last_tevs[s2].x,
y = self.last_tevs[s2].y,
w = 0, h = 0,
}
local tap_span = pos0:distance(pos1)
@ -592,7 +597,9 @@ function GestureDetector:panState(tev)
if tev.id == -1 then
-- end of pan, signal swipe gesture if necessary
if self:isSwipe(slot) then
if self.detectings[0] and self.detectings[1] then
local s1 = self.input.main_finger_slot
local s2 = self.input.main_finger_slot + 1
if self.detectings[s1] and self.detectings[s2] then
local ges_ev = self:handleTwoFingerPan(tev)
self:clearStates()
if ges_ev then
@ -665,7 +672,9 @@ end
function GestureDetector:handlePan(tev)
local slot = tev.slot
if self.detectings[0] and self.detectings[1] then
local s1 = self.input.main_finger_slot
local s2 = self.input.main_finger_slot + 1
if self.detectings[s1] and self.detectings[s2] then
return self:handleTwoFingerPan(tev)
else
local pan_direction, pan_distance = self:getPath(slot)
@ -768,10 +777,12 @@ function GestureDetector:handlePan(tev)
end
function GestureDetector:handleTwoFingerPan(tev)
local s1 = self.input.main_finger_slot
local s2 = self.input.main_finger_slot + 1
-- triggering slot
local tslot = tev.slot
-- reference slot
local rslot = tslot == 1 and 0 or 1
local rslot = tslot == s2 and s1 or s2
local tpan_dir, tpan_dis = self:getPath(tslot)
local tstart_pos = Geom:new{
x = self.first_tevs[tslot].x,
@ -839,7 +850,9 @@ function GestureDetector:handlePanRelease(tev)
pos = release_pos,
time = tev.timev,
}
if self.detectings[0] and self.detectings[1] then
local s1 = self.input.main_finger_slot
local s2 = self.input.main_finger_slot + 1
if self.detectings[s1] and self.detectings[s2] then
logger.dbg("two finger pan release detected")
pan_ev.ges = "two_finger_pan_release"
self:clearStates()

@ -82,6 +82,14 @@ local linux_evdev_syn_code_map = {
[C.SYN_DROPPED] = "SYN_DROPPED",
}
local linux_evdev_key_code_map = {
[C.BTN_TOOL_PEN] = "BTN_TOOL_PEN",
[C.BTN_TOOL_FINGER] = "BTN_TOOL_FINGER",
[C.BTN_TOOL_RUBBER] = "BTN_TOOL_RUBBER",
[C.BTN_TOUCH] = "BTN_TOUCH",
[C.BTN_STYLUS] = "BTN_STYLUS",
}
local linux_evdev_abs_code_map = {
[C.ABS_X] = "ABS_X",
[C.ABS_Y] = "ABS_Y",
@ -98,6 +106,8 @@ local linux_evdev_abs_code_map = {
[C.ABS_MT_BLOB_ID] = "ABS_MT_BLOB_ID",
[C.ABS_MT_TRACKING_ID] = "ABS_MT_TRACKING_ID",
[C.ABS_MT_PRESSURE] = "ABS_MT_PRESSURE",
[C.ABS_TILT_X] = "ABS_TILT_X",
[C.ABS_TILT_Y] = "ABS_TILT_Y",
[C.ABS_MT_DISTANCE] = "ABS_MT_DISTANCE",
[C.ABS_MT_TOOL_X] = "ABS_MT_TOOL_X",
[C.ABS_MT_TOOL_Y] = "ABS_MT_TOOL_Y",
@ -111,6 +121,8 @@ local linux_evdev_msc_code_map = {
local _internal_clipboard_text = nil -- holds the last copied text
local Input = {
-- must point to the device implementation when instantiating
device = nil,
-- this depends on keyboard layout and should be overridden:
event_map = {},
-- adapters are post processing functions that transform a given event to another event
@ -173,13 +185,10 @@ local Input = {
repeat_count = 0,
-- touch state:
main_finger_slot = 0,
cur_slot = 0,
MTSlots = {},
ev_slots = {
[0] = {
slot = 0,
}
},
ev_slots = {},
gesture_detector = nil,
-- simple internal clipboard implementation, can be overidden to use system clipboard
@ -203,6 +212,17 @@ function Input:new(o)
end
function Input:init()
-- Handle default finger slot
if self.device.main_finger_slot then
self.main_finger_slot = self.device.main_finger_slot
self.cur_slot = self.device.main_finger_slot
end
self.ev_slots = {
[self.main_finger_slot] = {
slot = self.main_finger_slot,
},
}
self.gesture_detector = GestureDetector:new{
screen = self.device.screen,
input = self,
@ -930,11 +950,13 @@ function Input:waitEvent(now, deadline)
while #self.timer_callbacks > 0 do
-- Choose the earliest deadline between the next timer deadline, and our full timeout deadline.
local deadline_is_timer = false
local with_timerfd = false
local poll_deadline
-- If the timer's deadline is handled via timerfd, that's easy
if self.timer_callbacks[1].timerfd then
-- We use the ultimate deadline, as the kernel will just signal us when the timer expires during polling.
poll_deadline = deadline
with_timerfd = true
else
if not deadline then
-- If we don't actually have a full timeout deadline, just honor the timer's.
@ -973,10 +995,25 @@ function Input:waitEvent(now, deadline)
-- If we've drained all pending input events, causing waitForEvent to time out, check our timers
if ok == false and ev == C.ETIME then
-- Check whether the earliest timer to finalize a Gesture detection is up.
-- If we were woken up by a timerfd, or if our actual select deadline was the timer itself,
-- we're guaranteed to have reached it.
-- But if it was a task deadline instead, we to have to check it against the current time.
if timerfd or (deadline_is_timer or TimeVal:now() >= self.timer_callbacks[1].deadline) then
local consume_callback = false
if timerfd then
-- If we were woken up by a timerfd, that means the timerfd backend is in use, of course,
-- and it also means that we're guaranteed to have reached its deadline.
consume_callback = true
elseif not with_timerfd then
-- On systems where the timerfd backend is *NOT* in use, we have a few more cases to handle...
if deadline_is_timer then
-- We're only guaranteed to have blown the timer's deadline
-- when our actual select deadline *was* the timer's!
consume_callback = true
elseif TimeVal:now() >= self.timer_callbacks[1].deadline then
-- But if it was a task deadline instead, we to have to check the timer's against the current time,
-- to double-check whether we blew it or not.
consume_callback = true
end
end
if consume_callback then
local touch_ges = self.timer_callbacks[1].callback()
table.remove(self.timer_callbacks, 1)
-- If it was a timerfd, we also need to close the fd.
@ -1055,7 +1092,7 @@ function Input:waitEvent(now, deadline)
if ev.type == C.EV_KEY then
logger.dbg(string.format(
"key event => code: %d (%s), value: %s, time: %d.%d",
ev.code, self.event_map[ev.code], ev.value,
ev.code, self.event_map[ev.code] or linux_evdev_key_code_map[ev.code], ev.value,
ev.time.sec, ev.time.usec))
elseif ev.type == C.EV_SYN then
logger.dbg(string.format(

@ -93,8 +93,6 @@ local KoboDaylight = Kobo:new{
local KoboDahlia = Kobo:new{
model = "Kobo_dahlia",
hasFrontlight = yes,
-- NOTE: The hardware can technically track 2 different fingers, but we don't seem to be able to figure it out...
hasMultitouch = no,
touch_phoenix_protocol = true,
-- There's no slot 0, the first finger gets assigned slot 1, and the second slot 2
main_finger_slot = 1,
@ -347,16 +345,6 @@ function Kobo:init()
}
self.wakeup_mgr = WakeupMgr:new()
-- Tweak initial slot, if necessary
if self.main_finger_slot then
self.input.cur_slot = self.main_finger_slot
self.input.ev_slots = {
[self.main_finger_slot] = {
slot = self.main_finger_slot,
}
}
end
Generic.init(self)
-- When present, event2 is the raw accelerometer data (3-Axis Orientation/Motion Detection)

Loading…
Cancel
Save