diff --git a/base b/base index bfbc8a3e5..514167d44 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit bfbc8a3e5c40a2d85653de1e4b93dc64cc8aea2a +Subproject commit 514167d44d8969127f3a05ceed0030e234b22b83 diff --git a/frontend/device/gesturedetector.lua b/frontend/device/gesturedetector.lua index c7ea97769..a138fbd32 100644 --- a/frontend/device/gesturedetector.lua +++ b/frontend/device/gesturedetector.lua @@ -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() diff --git a/frontend/device/input.lua b/frontend/device/input.lua index 949975a55..b0b12cf70 100644 --- a/frontend/device/input.lua +++ b/frontend/device/input.lua @@ -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( diff --git a/frontend/device/kobo/device.lua b/frontend/device/kobo/device.lua index 4a5595787..3732c212c 100644 --- a/frontend/device/kobo/device.lua +++ b/frontend/device/kobo/device.lua @@ -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)