mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
A few Kobo input tweaks (#4450)
* Fix the Touch input probe on Trilogy devices that depend on the touch_probe_ev_epoch_time quirk (fix #630) * Expose a "Pageturn button inversion" feature in the Navigation menu (for all devices with keys) (fix #4446) * Allow ignoring the accelerometer on the Forma (Screen > Ignore accelerometer rotation events; also available from the Gesture Manager) (fix #4451) * Fix SleepCover handling on the Forma (fix #4457) * Make isWifiOn a tiny bit more accurate (check the actual WiFi module instead of sdio_wifi_pwr) * Move all flash related Screen options to the eInk submenu
This commit is contained in:
@@ -8,7 +8,7 @@ local _ = require("gettext")
|
||||
|
||||
local default_gesture = {
|
||||
tap_right_bottom_corner = "nothing",
|
||||
tap_left_bottom_corner = Device.hasFrontlight() and "toggle_frontlight" or "nothing",
|
||||
tap_left_bottom_corner = Device:hasFrontlight() and "toggle_frontlight" or "nothing",
|
||||
short_diagonal_swipe = "full_refresh",
|
||||
}
|
||||
|
||||
@@ -70,7 +70,8 @@ function ReaderGesture:buildMenu(ges, default)
|
||||
{_("Reading progress"), "reading_progress", ReaderGesture.getReaderProgress ~= nil},
|
||||
{_("Full screen refresh"), "full_refresh", true},
|
||||
{_("Night mode"), "night_mode", true},
|
||||
{_("Toggle frontlight"), "toggle_frontlight", Device.hasFrontlight()},
|
||||
{_("Toggle frontlight"), "toggle_frontlight", Device:hasFrontlight()},
|
||||
{_("Toggle accelerometer"), "toggle_gsensor", Device:canToggleGSensor()},
|
||||
}
|
||||
local return_menu = {}
|
||||
-- add default action to the top of the submenu
|
||||
@@ -190,15 +191,19 @@ function ReaderGesture:gestureAction(action)
|
||||
UIManager:setDirty("all", "full")
|
||||
elseif action == "bookmarks" then
|
||||
self.ui:handleEvent(Event:new("ShowBookmark"))
|
||||
elseif action =="page_update_up10" then
|
||||
elseif action == "page_update_up10" then
|
||||
self:pageUpdate(10)
|
||||
elseif action =="page_update_down10" then
|
||||
elseif action == "page_update_down10" then
|
||||
self:pageUpdate(-10)
|
||||
elseif action =="folder_up" then
|
||||
elseif action == "folder_up" then
|
||||
self.ui.file_chooser:changeToPath(string.format("%s/..", self.ui.file_chooser.path))
|
||||
elseif action =="toggle_frontlight" then
|
||||
elseif action == "toggle_frontlight" then
|
||||
Device:getPowerDevice():toggleFrontlight()
|
||||
self:onShowFLOnOff()
|
||||
elseif action == "toggle_gsensor" then
|
||||
G_reader_settings:flipNilOrFalse("input_ignore_gsensor")
|
||||
Device:toggleGSensor()
|
||||
self:onGSensorToggle()
|
||||
end
|
||||
return true
|
||||
end
|
||||
@@ -233,4 +238,19 @@ function ReaderGesture:onShowFLOnOff()
|
||||
return true
|
||||
end
|
||||
|
||||
function ReaderGesture:onGSensorToggle()
|
||||
local Notification = require("ui/widget/notification")
|
||||
local new_text
|
||||
if G_reader_settings:isTrue("input_ignore_gsensor") then
|
||||
new_text = _("Accelerometer rotation events will now be ignored.")
|
||||
else
|
||||
new_text = _("Accelerometer rotation events will now be honored.")
|
||||
end
|
||||
UIManager:show(Notification:new{
|
||||
text = new_text,
|
||||
timeout = 1.0,
|
||||
})
|
||||
return true
|
||||
end
|
||||
|
||||
return ReaderGesture
|
||||
|
||||
@@ -27,6 +27,7 @@ local Device = {
|
||||
hasClipboard = no,
|
||||
hasColorScreen = no,
|
||||
hasBGRFrameBuffer = no,
|
||||
canToggleGSensor = no,
|
||||
|
||||
-- use these only as a last resort. We should abstract the functionality
|
||||
-- and have device dependent implementations in the corresponting
|
||||
@@ -65,6 +66,27 @@ function Device:new(o)
|
||||
return o
|
||||
end
|
||||
|
||||
-- Inverts PageTurn button mappings
|
||||
-- NOTE: For ref. on Kobo, stored by Nickel in the [Reading] section as invertPageTurnButtons=true
|
||||
function Device:invertButtons()
|
||||
if self:hasKeys() and self.input and self.input.event_map then
|
||||
for key, value in pairs(self.input.event_map) do
|
||||
if value == "LPgFwd" then
|
||||
self.input.event_map[key] = "LPgBack"
|
||||
elseif value == "LPgBack" then
|
||||
self.input.event_map[key] = "LPgFwd"
|
||||
elseif value == "RPgFwd" then
|
||||
self.input.event_map[key] = "RPgBack"
|
||||
elseif value == "RPgBack" then
|
||||
self.input.event_map[key] = "RPgFwd"
|
||||
end
|
||||
end
|
||||
|
||||
-- NOTE: We currently leave self.input.rotation_map alone,
|
||||
-- which will definitely yield fairly stupid mappings in Landscape...
|
||||
end
|
||||
end
|
||||
|
||||
function Device:init()
|
||||
assert(self ~= nil)
|
||||
if not self.screen then
|
||||
@@ -99,6 +121,13 @@ function Device:init()
|
||||
self.input.adjustTouchTranslate,
|
||||
{x = 0 - self.viewport.x, y = 0 - self.viewport.y})
|
||||
end
|
||||
|
||||
-- Handle button mappings shenanigans
|
||||
if self:hasKeys() then
|
||||
if G_reader_settings:isTrue("input_invert_page_turn_keys") then
|
||||
self:invertButtons()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Device:getPowerDevice()
|
||||
@@ -207,6 +236,9 @@ function Device:setDateTime(year, month, day, hour, min, sec) end
|
||||
-- Device specific method if any setting needs being saved
|
||||
function Device:saveSettings() end
|
||||
|
||||
-- Device specific method for toggling the GSensor
|
||||
function Device:toggleGSensor() end
|
||||
|
||||
--[[
|
||||
prepare for application shutdown
|
||||
--]]
|
||||
|
||||
@@ -659,6 +659,16 @@ function Input:handleMiscEvNTX(ev)
|
||||
end
|
||||
end
|
||||
|
||||
-- Allow toggling it at runtime
|
||||
function Input:toggleMiscEvNTX()
|
||||
if self.isNTXAccelHooked then
|
||||
self.handleMiscEv = function() end
|
||||
else
|
||||
self.handleMiscEv = self.handleMiscEvNTX
|
||||
end
|
||||
|
||||
self.isNTXAccelHooked = not self.isNTXAccelHooked
|
||||
end
|
||||
|
||||
-- helpers for touch event data management:
|
||||
|
||||
@@ -705,6 +715,10 @@ function Input:isEvKeyPress(ev)
|
||||
return ev.value == EVENT_VALUE_KEY_PRESS
|
||||
end
|
||||
|
||||
function Input:isEvKeyRepeat(ev)
|
||||
return ev.value == EVENT_VALUE_KEY_REPEAT
|
||||
end
|
||||
|
||||
function Input:isEvKeyRelease(ev)
|
||||
return ev.value == EVENT_VALUE_KEY_RELEASE
|
||||
end
|
||||
|
||||
@@ -207,6 +207,7 @@ local KoboFrost = Kobo:new{
|
||||
model = "Kobo_frost",
|
||||
hasFrontlight = yes,
|
||||
hasKeys = yes,
|
||||
canToggleGSensor = yes,
|
||||
touch_snow_protocol = true,
|
||||
misc_ntx_gsensor_protocol = true,
|
||||
display_dpi = 300,
|
||||
@@ -222,6 +223,24 @@ local KoboFrost = Kobo:new{
|
||||
},
|
||||
}
|
||||
|
||||
-- This function will update itself after the first touch event
|
||||
local probeEvEpochTime
|
||||
probeEvEpochTime = function(self, ev)
|
||||
local now = TimeVal:now()
|
||||
-- This check should work as long as main UI loop is not blocked for more
|
||||
-- than 10 minute before handling the first touch event.
|
||||
if ev.time.sec <= now.sec - 600 then
|
||||
-- time is seconds since boot, force it to epoch
|
||||
probeEvEpochTime = function(_, _ev)
|
||||
_ev.time = TimeVal:now()
|
||||
end
|
||||
ev.time = now
|
||||
else
|
||||
-- time is already epoch time, no need to do anything
|
||||
probeEvEpochTime = function(_, _) end
|
||||
end
|
||||
end
|
||||
|
||||
function Kobo:init()
|
||||
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self, debug = logger.dbg}
|
||||
-- NOTE: Something about the extra work needed to handle RGB565 conversions is making the JIT optimizer crazy when doing
|
||||
@@ -252,7 +271,7 @@ function Kobo:init()
|
||||
SleepCover = function(ev)
|
||||
if self.input:isEvKeyPress(ev) then
|
||||
return "SleepCoverClosed"
|
||||
else
|
||||
elseif self.input:isEvKeyRelease(ev) then
|
||||
return "SleepCoverOpened"
|
||||
end
|
||||
end,
|
||||
@@ -278,6 +297,15 @@ function Kobo:init()
|
||||
else
|
||||
-- if touch probe is required, we postpone EventAdjustHook
|
||||
-- initialization to when self:touchScreenProbe is called
|
||||
-- Except we may need bits of EventAdjustHook for stuff to be functional, so,
|
||||
-- re-order things in the most horrible way possible!
|
||||
if self.touch_probe_ev_epoch_time then
|
||||
self.input:registerEventAdjustHook(function(_, ev)
|
||||
probeEvEpochTime(_, ev)
|
||||
end)
|
||||
-- And don't do it again during the real initEventAdjustHooks ;)
|
||||
self.touch_probe_ev_epoch_time = nil
|
||||
end
|
||||
self.touchScreenProbe = function()
|
||||
-- if user has not set KOBO_TOUCH_MIRRORED yet
|
||||
if KOBO_TOUCH_MIRRORED == nil then
|
||||
@@ -349,30 +377,12 @@ function Kobo:initNetworkManager(NetworkMgr)
|
||||
-- NOTE: Cheap-ass way of checking if WiFi seems to be enabled...
|
||||
-- Since the crux of the issues lies in race-y module unloading, this is perfectly fine for our usage.
|
||||
function NetworkMgr:isWifiOn()
|
||||
return 0 == os.execute("lsmod | grep -q sdio_wifi_pwr")
|
||||
return 0 == os.execute("lsmod | grep -q " .. os.getenv("WIFI_MODULE") or "sdio_wifi_pwr")
|
||||
end
|
||||
end
|
||||
|
||||
function Kobo:supportsScreensaver() return true end
|
||||
|
||||
local probeEvEpochTime
|
||||
-- this function will update itself after the first touch event
|
||||
probeEvEpochTime = function(self, ev)
|
||||
local now = TimeVal:now()
|
||||
-- This check should work as long as main UI loop is not blocked for more
|
||||
-- than 10 minute before handling the first touch event.
|
||||
if ev.time.sec <= now.sec - 600 then
|
||||
-- time is seconds since boot, force it to epoch
|
||||
probeEvEpochTime = function(_, _ev)
|
||||
_ev.time = TimeVal:now()
|
||||
end
|
||||
ev.time = now
|
||||
else
|
||||
-- time is already epoch time, no need to do anything
|
||||
probeEvEpochTime = function(_, _) end
|
||||
end
|
||||
end
|
||||
|
||||
local ABS_MT_TRACKING_ID = 57
|
||||
local EV_ABS = 3
|
||||
local adjustTouchAlyssum = function(self, ev)
|
||||
@@ -421,7 +431,12 @@ function Kobo:initEventAdjustHooks()
|
||||
|
||||
-- Accelerometer on the Forma
|
||||
if self.misc_ntx_gsensor_protocol then
|
||||
if G_reader_settings:isTrue("input_ignore_gsensor") then
|
||||
self.input.isNTXAccelHooked = false
|
||||
else
|
||||
self.input.handleMiscEv = self.input.handleMiscEvNTX
|
||||
self.input.isNTXAccelHooked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -672,6 +687,15 @@ function Kobo:reboot()
|
||||
os.execute("reboot")
|
||||
end
|
||||
|
||||
function Kobo:toggleGSensor()
|
||||
if self:canToggleGSensor() and self.input then
|
||||
-- Currently only supported on the Forma
|
||||
if self.misc_ntx_gsensor_protocol then
|
||||
self.input:toggleMiscEvNTX()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------- device probe ------------
|
||||
|
||||
local codename = Kobo:getCodeName()
|
||||
|
||||
@@ -112,10 +112,11 @@ common_settings.screen = {
|
||||
require("ui/elements/screen_eink_opt_menu_table"),
|
||||
require("ui/elements/menu_activate"),
|
||||
require("ui/elements/screen_disable_double_tap_table"),
|
||||
require("ui/elements/flash_ui"),
|
||||
require("ui/elements/flash_keyboard"),
|
||||
},
|
||||
}
|
||||
if Device:canToggleGSensor() then
|
||||
table.insert(common_settings.screen.sub_item_table, require("ui/elements/screen_toggle_gsensor"))
|
||||
end
|
||||
if Screen.isColorScreen() then
|
||||
table.insert(common_settings.screen.sub_item_table, 3, require("ui/elements/screen_color_menu_table"))
|
||||
common_settings.screen.sub_item_table[3].separator = true
|
||||
@@ -199,6 +200,16 @@ if Device:hasKeys() then
|
||||
G_reader_settings:flipNilOrTrue("enable_back_history")
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = _("Invert page turn buttons"),
|
||||
checked_func = function()
|
||||
return G_reader_settings:isTrue("input_invert_page_turn_keys")
|
||||
end,
|
||||
callback = function()
|
||||
G_reader_settings:flipNilOrFalse("input_invert_page_turn_keys")
|
||||
Device:invertButtons()
|
||||
end,
|
||||
},
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
@@ -13,6 +13,8 @@ local eink_settings_table = {
|
||||
G_reader_settings:saveSetting("low_pan_rate", Screen.low_pan_rate)
|
||||
end,
|
||||
},
|
||||
require("ui/elements/flash_ui"),
|
||||
require("ui/elements/flash_keyboard"),
|
||||
{
|
||||
text = _("Avoid mandatory black flashes in UI"),
|
||||
checked_func = function() return G_reader_settings:isTrue("avoid_flashing_ui") end,
|
||||
@@ -20,7 +22,6 @@ local eink_settings_table = {
|
||||
G_reader_settings:flipNilOrFalse("avoid_flashing_ui")
|
||||
end,
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
13
frontend/ui/elements/screen_toggle_gsensor.lua
Normal file
13
frontend/ui/elements/screen_toggle_gsensor.lua
Normal file
@@ -0,0 +1,13 @@
|
||||
local Device = require("device")
|
||||
local _ = require("gettext")
|
||||
|
||||
return {
|
||||
text = _("Ignore accelerometer rotation events"),
|
||||
checked_func = function()
|
||||
return G_reader_settings:isTrue("input_ignore_gsensor")
|
||||
end,
|
||||
callback = function()
|
||||
G_reader_settings:flipNilOrFalse("input_ignore_gsensor")
|
||||
Device:toggleGSensor()
|
||||
end,
|
||||
}
|
||||
@@ -80,9 +80,10 @@ describe("device module", function()
|
||||
kobo_dev:init()
|
||||
local Screen = kobo_dev.screen
|
||||
|
||||
kobo_dev.touch_probe_ev_epoch_time = false
|
||||
assert.is.same("Kobo_trilogy", kobo_dev.model)
|
||||
assert.truthy(kobo_dev:needsTouchScreenProbe())
|
||||
-- This gets reset to nil during Kobo:init() since #4450
|
||||
assert.falsy(kobo_dev.touch_probe_ev_epoch_time)
|
||||
G_reader_settings:saveSetting("kobo_touch_switch_xy", true)
|
||||
kobo_dev:touchScreenProbe()
|
||||
local x, y = Screen:getWidth()-5, 10
|
||||
@@ -94,11 +95,13 @@ describe("device module", function()
|
||||
type = EV_ABS,
|
||||
code = ABS_X,
|
||||
value = y,
|
||||
time = TimeVal:now(),
|
||||
}
|
||||
local ev_y = {
|
||||
type = EV_ABS,
|
||||
code = ABS_Y,
|
||||
value = Screen:getWidth()-x,
|
||||
time = TimeVal:now(),
|
||||
}
|
||||
|
||||
kobo_dev.input:eventAdjustHook(ev_x)
|
||||
@@ -110,7 +113,6 @@ describe("device module", function()
|
||||
|
||||
-- reset eventAdjustHook
|
||||
kobo_dev.input.eventAdjustHook = function() end
|
||||
kobo_dev.touch_probe_ev_epoch_time = true
|
||||
end)
|
||||
|
||||
it("should setup eventAdjustHooks properly for trilogy with non-epoch ev time", function()
|
||||
@@ -121,16 +123,21 @@ describe("device module", function()
|
||||
return osgetenv(key)
|
||||
end
|
||||
end)
|
||||
|
||||
package.loaded['device/kobo/device'] = nil
|
||||
local kobo_dev = require("device/kobo/device")
|
||||
kobo_dev:init()
|
||||
local Screen = kobo_dev.screen
|
||||
|
||||
assert.is.same("Kobo_trilogy", kobo_dev.model)
|
||||
assert.truthy(kobo_dev:needsTouchScreenProbe())
|
||||
-- This gets reset to nil during Kobo:init() since #4450
|
||||
assert.falsy(kobo_dev.touch_probe_ev_epoch_time)
|
||||
kobo_dev:touchScreenProbe()
|
||||
local x, y = Screen:getWidth()-5, 10
|
||||
local EV_ABS = 3
|
||||
local ABS_X = 00
|
||||
local ABS_Y = 01
|
||||
-- mirror x, then switch_xy
|
||||
local ev_x = {
|
||||
type = EV_ABS,
|
||||
code = ABS_X,
|
||||
@@ -144,16 +151,13 @@ describe("device module", function()
|
||||
time = {sec = 1000}
|
||||
}
|
||||
|
||||
assert.truthy(kobo_dev.touch_probe_ev_epoch_time)
|
||||
G_reader_settings:saveSetting("kobo_touch_switch_xy", true)
|
||||
kobo_dev:touchScreenProbe()
|
||||
|
||||
kobo_dev.input:eventAdjustHook(ev_x)
|
||||
kobo_dev.input:eventAdjustHook(ev_y)
|
||||
local cur_sec = TimeVal:now().sec
|
||||
assert.truthy(cur_sec - ev_x.time.sec < 10)
|
||||
assert.truthy(cur_sec - ev_y.time.sec < 10)
|
||||
|
||||
-- reset eventAdjustHook
|
||||
kobo_dev.input.eventAdjustHook = function() end
|
||||
end)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user