From 1f6af80817bd9ce55201555817d4ce5e7f8f319c Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 24 Jul 2019 14:31:20 +0200 Subject: [PATCH] [feat] Make gesture intervals configurable (#5138) Discussion: #4842 Close: #4842 --- .../apps/reader/modules/readergesture.lua | 140 ++++++++++++++++++ frontend/device/gesturedetector.lua | 51 ++++++- .../ui/elements/filemanager_menu_order.lua | 1 + frontend/ui/elements/reader_menu_order.lua | 1 + frontend/ui/widget/spinwidget.lua | 15 ++ 5 files changed, 200 insertions(+), 8 deletions(-) diff --git a/frontend/apps/reader/modules/readergesture.lua b/frontend/apps/reader/modules/readergesture.lua index 200cf4483..d3023add0 100644 --- a/frontend/apps/reader/modules/readergesture.lua +++ b/frontend/apps/reader/modules/readergesture.lua @@ -359,6 +359,146 @@ function ReaderGesture:addToMainMenu(menu_items) }, }, } + menu_items.gesture_intervals = { + text = _("Gesture intervals"), + sub_item_table = { + { + text = _("Double tap interval"), + callback = function() + local SpinWidget = require("ui/widget/spinwidget") + local GestureDetector = require("device/gesturedetector") + local items = SpinWidget:new{ + text = T(_([[ +Set double tap interval in miliseconds. +The interval value can range from 100 (0.1 seconds) to 2000 (2 seconds). +Default value: %1]]), GestureDetector.DOUBLE_TAP_INTERVAL/1000), + width = Screen:getWidth() * 0.6, + value = GestureDetector:getInterval("ges_double_tap_interval")/1000, + value_min = 100, + value_max = 2000, + value_step = 100, + value_hold_step = 500, + ok_text = _("Set interval"), + title_text = _("Double tap interval"), + default_value = GestureDetector.DOUBLE_TAP_INTERVAL/1000, + callback = function(spin) + G_reader_settings:saveSetting("ges_double_tap_interval", spin.value*1000) + GestureDetector:setNewInterval("ges_double_tap_interval", spin.value*1000) + end + } + UIManager:show(items) + end, + }, + { + text = _("Two finger tap duration"), + callback = function() + local SpinWidget = require("ui/widget/spinwidget") + local GestureDetector = require("device/gesturedetector") + local items = SpinWidget:new{ + text = T(_([[ +Set two finger tap duration in miliseconds. +The duration value can range from 100 (0.1 seconds) to 2000 (2 seconds). +Default value: %1]]), GestureDetector.TWO_FINGER_TAP_DURATION/1000), + width = Screen:getWidth() * 0.6, + value = GestureDetector:getInterval("ges_two_finger_tap_duration")/1000, + value_min = 100, + value_max = 2000, + value_step = 100, + value_hold_step = 500, + ok_text = _("Set duration"), + title_text = _("Two finger tap duration"), + default_value = GestureDetector.TWO_FINGER_TAP_DURATION/1000, + callback = function(spin) + G_reader_settings:saveSetting("ges_two_finger_tap_duration", spin.value*1000) + GestureDetector:setNewInterval("ges_two_finger_tap_duration", spin.value*1000) + end + } + UIManager:show(items) + end, + }, + { + text = _("Hold interval"), + callback = function() + local SpinWidget = require("ui/widget/spinwidget") + local GestureDetector = require("device/gesturedetector") + local items = SpinWidget:new{ + text = T(_([[ +Set hold interval in miliseconds. +The interval value can range from 100 (0.1 seconds) to 2000 (2 seconds). +Default value: %1]]), GestureDetector.HOLD_INTERVAL/1000), + width = Screen:getWidth() * 0.6, + value = GestureDetector:getInterval("ges_hold_interval")/1000, + value_min = 100, + value_max = 2000, + value_step = 100, + value_hold_step = 500, + ok_text = _("Set interval"), + title_text = _("Hold interval"), + default_value = GestureDetector.HOLD_INTERVAL/1000, + callback = function(spin) + G_reader_settings:saveSetting("ges_hold_interval", spin.value*1000) + GestureDetector:setNewInterval("ges_hold_interval", spin.value*1000) + end + } + UIManager:show(items) + end, + }, + { + text = _("Pan delay interval"), + callback = function() + local SpinWidget = require("ui/widget/spinwidget") + local GestureDetector = require("device/gesturedetector") + local items = SpinWidget:new{ + text = T(_([[ +Set pan delay interval in miliseconds. +The interval value can range from 100 (0.1 seconds) to 2000 (2 seconds). +Default value: %1]]), GestureDetector.PAN_DELAYED_INTERVAL/1000), + width = Screen:getWidth() * 0.6, + value = GestureDetector:getInterval("ges_pan_delayed_interval")/1000, + value_min = 100, + value_max = 2000, + value_step = 100, + value_hold_step = 500, + ok_text = _("Set interval"), + title_text = _("Pan delay interval"), + default_value = GestureDetector.PAN_DELAYED_INTERVAL/1000, + callback = function(spin) + G_reader_settings:saveSetting("ges_pan_delayed_interval", spin.value*1000) + GestureDetector:setNewInterval("ges_pan_delayed_interval", spin.value*1000) + end + } + UIManager:show(items) + end, + }, + { + text = _("Swipe interval"), + callback = function() + local SpinWidget = require("ui/widget/spinwidget") + local GestureDetector = require("device/gesturedetector") + local items = SpinWidget:new{ + text = T(_([[ +Set swipe interval in miliseconds. +The interval value can range from 100 (0.1 seconds) to 2000 (2 seconds). +Default value: %1]]), GestureDetector.SWIPE_INTERVAL/1000), + width = Screen:getWidth() * 0.6, + value = GestureDetector:getInterval("ges_swipe_interval")/1000, + value_min = 100, + value_max = 2000, + value_step = 100, + value_hold_step = 500, + ok_text = _("Set interval"), + title_text = _("Swipe interval"), + default_value = GestureDetector.SWIPE_INTERVAL/1000, + callback = function(spin) + G_reader_settings:saveSetting("ges_swipe_interval", spin.value*1000) + GestureDetector:setNewInterval("ges_swipe_interval", spin.value*1000) + end + } + UIManager:show(items) + end, + }, + } + } local twoFingerSwipeTextFunc = function(gesture, friendly_name) local action_name = gesture_manager[gesture] ~= "nothing" and action_strings[gesture_manager[gesture]] or _("Available") diff --git a/frontend/device/gesturedetector.lua b/frontend/device/gesturedetector.lua index 68d12b794..835a0c639 100644 --- a/frontend/device/gesturedetector.lua +++ b/frontend/device/gesturedetector.lua @@ -47,10 +47,17 @@ local TimeVal = require("ui/timeval") local logger = require("logger") local util = require("util") +-- all the time parameters are in us +local ges_double_tap_interval = G_reader_settings:readSetting("ges_double_tap_interval") or 300 * 1000 +local ges_two_finger_tap_duration = G_reader_settings:readSetting("ges_two_finger_tap_duration") or 300 * 1000 +local ges_hold_interval = G_reader_settings:readSetting("ges_hold_interval") or 500 * 1000 +local ges_pan_delayed_interval = G_reader_settings:readSetting("ges_pan_delayed_interval") or 500 * 1000 +local ges_swipe_interval = G_reader_settings:readSetting("ges_swipe_interval") or 900 * 1000 + local GestureDetector = { -- must be initialized with the Input singleton class input = nil, - -- all the time parameters are in us + -- default values (all the time parameters are in us) DOUBLE_TAP_INTERVAL = 300 * 1000, TWO_FINGER_TAP_DURATION = 300 * 1000, HOLD_INTERVAL = 500 * 1000, @@ -141,7 +148,7 @@ function GestureDetector:isDoubleTap(tap1, tap2) return ( math.abs(tap1.x - tap2.x) < self.DOUBLE_TAP_DISTANCE and math.abs(tap1.y - tap2.y) < self.DOUBLE_TAP_DISTANCE and - (tv_diff.sec == 0 and (tv_diff.usec) < self.DOUBLE_TAP_INTERVAL) + (tv_diff.sec == 0 and (tv_diff.usec) < ges_double_tap_interval) ) end @@ -160,8 +167,8 @@ function GestureDetector:isTwoFingerTap() x_diff1 < self.TWO_FINGER_TAP_REGION and y_diff0 < self.TWO_FINGER_TAP_REGION and y_diff1 < self.TWO_FINGER_TAP_REGION and - tv_diff0.sec == 0 and tv_diff0.usec < self.TWO_FINGER_TAP_DURATION and - tv_diff1.sec == 0 and tv_diff1.usec < self.TWO_FINGER_TAP_DURATION + tv_diff0.sec == 0 and tv_diff0.usec < ges_two_finger_tap_duration and + tv_diff1.sec == 0 and tv_diff1.usec < ges_two_finger_tap_duration ) end @@ -200,7 +207,7 @@ end function GestureDetector:isSwipe(slot) if not self.first_tevs[slot] or not self.last_tevs[slot] then return end local tv_diff = self.last_tevs[slot].timev - self.first_tevs[slot].timev - if (tv_diff.sec == 0) and (tv_diff.usec < self.SWIPE_INTERVAL) then + if (tv_diff.sec == 0) and (tv_diff.usec < ges_swipe_interval) then local x_diff = self.last_tevs[slot].x - self.first_tevs[slot].x local y_diff = self.last_tevs[slot].y - self.first_tevs[slot].y if x_diff ~= 0 or y_diff ~= 0 then @@ -234,6 +241,34 @@ function GestureDetector:clearState(slot) self.multiswipe_type = nil end +function GestureDetector:setNewInterval(type, interval) + if type == "ges_double_tap_interval" then + ges_double_tap_interval = interval + elseif type == "ges_two_finger_tap_duration" then + ges_two_finger_tap_duration = interval + elseif type == "ges_hold_interval" then + ges_hold_interval = interval + elseif type == "ges_pan_delayed_interval" then + ges_pan_delayed_interval = interval + elseif type == "ges_swipe_interval" then + ges_swipe_interval = interval + end +end + +function GestureDetector:getInterval(type) + if type == "ges_double_tap_interval" then + return ges_double_tap_interval + elseif type == "ges_two_finger_tap_duration" then + return ges_two_finger_tap_duration + elseif type == "ges_hold_interval" then + return ges_hold_interval + elseif type == "ges_pan_delayed_interval" then + return ges_pan_delayed_interval + elseif type == "ges_swipe_interval" then + return ges_swipe_interval + end +end + function GestureDetector:clearStates() self:clearState(0) self:clearState(1) @@ -348,7 +383,7 @@ function GestureDetector:handleDoubleTap(tev) -- deadline should be calculated by adding current tap time and the interval local deadline = cur_tap.timev + TimeVal:new{ sec = 0, - usec = not self.input.disable_double_tap and self.DOUBLE_TAP_INTERVAL or 0, + usec = not self.input.disable_double_tap and ges_double_tap_interval or 0, } self.input:setTimeout(function() logger.dbg("in tap timer", self.last_taps[slot] ~= nil) @@ -374,7 +409,7 @@ function GestureDetector:handleNonTap(tev) self.states[slot] = self.tapState logger.dbg("set up hold timer") local deadline = tev.timev + TimeVal:new{ - sec = 0, usec = self.HOLD_INTERVAL + sec = 0, usec = ges_hold_interval } self.input:setTimeout(function() if self.states[slot] == self.tapState then @@ -514,7 +549,7 @@ function GestureDetector:handlePan(tev) -- delayed pan, used where necessary to reduce potential activation of panning -- when swiping is intended (e.g., for the menu or for multiswipe) - if not ((tv_diff.sec == 0) and (tv_diff.usec < self.PAN_DELAYED_INTERVAL)) then + if not ((tv_diff.sec == 0) and (tv_diff.usec < ges_pan_delayed_interval)) then pan_ev.relative_delayed.x = tev.x - self.first_tevs[slot].x pan_ev.relative_delayed.y = tev.y - self.first_tevs[slot].y pan_ev.distance_delayed = pan_distance diff --git a/frontend/ui/elements/filemanager_menu_order.lua b/frontend/ui/elements/filemanager_menu_order.lua index 0e88589ba..131659ffb 100644 --- a/frontend/ui/elements/filemanager_menu_order.lua +++ b/frontend/ui/elements/filemanager_menu_order.lua @@ -77,6 +77,7 @@ local order = { taps_and_gestures = { "gesture_manager", "frontlight_gesture_controller", + "gesture_intervals", "----------------------------", "menu_activate", "screen_disable_double_tab", diff --git a/frontend/ui/elements/reader_menu_order.lua b/frontend/ui/elements/reader_menu_order.lua index 1a1b78c95..c983313e4 100644 --- a/frontend/ui/elements/reader_menu_order.lua +++ b/frontend/ui/elements/reader_menu_order.lua @@ -96,6 +96,7 @@ local order = { taps_and_gestures = { "gesture_manager", "frontlight_gesture_controller", + "gesture_intervals", "----------------------------", "follow_links", "----------------------------", diff --git a/frontend/ui/widget/spinwidget.lua b/frontend/ui/widget/spinwidget.lua index cfe80bdfc..c236aa83f 100644 --- a/frontend/ui/widget/spinwidget.lua +++ b/frontend/ui/widget/spinwidget.lua @@ -33,6 +33,9 @@ local SpinWidget = InputContainer:new{ value_hold_step = 4, ok_text = _("OK"), cancel_text = _("Cancel"), + -- set this to see extra default button + default_value = nil, + defaults_text = _("Use default"), } function SpinWidget:init() @@ -123,6 +126,18 @@ function SpinWidget:update() } } + if self.default_value then + table.insert(buttons,{ + { + text = self.defaults_text, + callback = function() + value_widget.value = self.default_value + value_widget:update() + end, + }, + }) + end + local ok_cancel_buttons = ButtonTable:new{ width = self.width - 2*Size.padding.default, buttons = buttons,