Input/Device: Refactor Gyro events handling (#9935)

* Get rid of the `canToggleGSensor` Device cap, it's now mandatory for `hasGSensor` devices. (This means Kindles can now toggle the gyro, fix #9136).
* This also means that `Device:toggleGSensor` is now implemented by `Generic`.
* Update the Screen & Gyro rotation constants to be clearer (c.f., https://github.com/koreader/koreader-base/pull/1568) (/!\ This might conceivably break some `rotation_map` user-patches).
* Input: Move the platform-specific gyro handling to Device implementations, and let Input only handle a single, custom protocol (`EV_MSC:MSC_GYRO`).
* Input: Refine the `rotation_map` disable method implemented in 43b021d37c. Instead of directly poking at the internal field, use a new method, `disableRotationMap` (/!\ Again, this might break some `rotation_map` user-patches).
* Input: Minor tweaks to event adjust hooks to make them more modular, allowing the Kobo implementation to build and use a single composite hook. API compatibility maintained with wrappers.
reviewable/pr9938/r1
NiLuJe 1 year ago committed by GitHub
parent 99df719562
commit 788ccac561
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1 +1 @@
Subproject commit 36b88873bf52b087fba59fa37e7e6a0da92efda2 Subproject commit 0d8f7076c9904d2894c03b0a1db7c3f5a92e3267

@ -75,7 +75,7 @@ FileManager.onPhysicalKeyboardDisconnected = FileManager.onPhysicalKeyboardConne
function FileManager:setRotationMode() function FileManager:setRotationMode()
local locked = G_reader_settings:isTrue("lock_rotation") local locked = G_reader_settings:isTrue("lock_rotation")
if not locked then if not locked then
local rotation_mode = G_reader_settings:readSetting("fm_rotation_mode") or Screen.ORIENTATION_PORTRAIT local rotation_mode = G_reader_settings:readSetting("fm_rotation_mode") or Screen.DEVICE_ROTATED_UPRIGHT
self:onSetRotationMode(rotation_mode) self:onSetRotationMode(rotation_mode)
end end
end end

@ -859,9 +859,9 @@ function ReaderView:onReadSettings(config)
else else
-- No doc specific rotation, pickup global defaults for the doc type -- No doc specific rotation, pickup global defaults for the doc type
if self.ui.paging then if self.ui.paging then
rotation_mode = G_reader_settings:readSetting("kopt_rotation_mode") or Screen.ORIENTATION_PORTRAIT rotation_mode = G_reader_settings:readSetting("kopt_rotation_mode") or Screen.DEVICE_ROTATED_UPRIGHT
else else
rotation_mode = G_reader_settings:readSetting("copt_rotation_mode") or Screen.ORIENTATION_PORTRAIT rotation_mode = G_reader_settings:readSetting("copt_rotation_mode") or Screen.DEVICE_ROTATED_UPRIGHT
end end
end end
end end

@ -384,7 +384,8 @@ function Device:_toggleStatusBarVisibility()
-- reset touchTranslate to normal -- reset touchTranslate to normal
self.input:registerEventAdjustHook( self.input:registerEventAdjustHook(
self.input.adjustTouchTranslate, self.input.adjustTouchTranslate,
{x = 0 + self.viewport.x, y = 0 + self.viewport.y}) {x = 0 + self.viewport.x, y = 0 + self.viewport.y}
)
end end
local viewport = Geom:new{x=0, y=statusbar_height, w=width, h=new_height} local viewport = Geom:new{x=0, y=statusbar_height, w=width, h=new_height}
@ -395,7 +396,8 @@ function Device:_toggleStatusBarVisibility()
if is_fullscreen and self.viewport then if is_fullscreen and self.viewport then
self.input:registerEventAdjustHook( self.input:registerEventAdjustHook(
self.input.adjustTouchTranslate, self.input.adjustTouchTranslate,
{x = 0 - self.viewport.x, y = 0 - self.viewport.y}) {x = 0 - self.viewport.x, y = 0 - self.viewport.y}
)
end end
self.fullscreen = is_fullscreen self.fullscreen = is_fullscreen

@ -107,13 +107,9 @@ local Cervantes4 = Cervantes:extend{
-- input events -- input events
function Cervantes:initEventAdjustHooks() function Cervantes:initEventAdjustHooks()
if self.touch_switch_xy then if self.touch_switch_xy and self.touch_mirrored_x then
self.input:registerEventAdjustHook(self.input.adjustTouchSwitchXY)
end
if self.touch_mirrored_x then
self.input:registerEventAdjustHook( self.input:registerEventAdjustHook(
self.input.adjustTouchMirrorX, self.input.adjustTouchSwitchAxesAndMirrorX,
(self.screen:getWidth() - 1) (self.screen:getWidth() - 1)
) )
end end

@ -214,7 +214,7 @@ if Device:hasFrontlight() then
end end
if Device:canToggleGSensor() then if Device:hasGSensor() then
function DeviceListener:onToggleGSensor() function DeviceListener:onToggleGSensor()
_toggleSetting("input_ignore_gsensor") _toggleSetting("input_ignore_gsensor")
Device:toggleGSensor(not G_reader_settings:isTrue("input_ignore_gsensor")) Device:toggleGSensor(not G_reader_settings:isTrue("input_ignore_gsensor"))

@ -61,7 +61,6 @@ local Device = {
canImportFiles = no, canImportFiles = no,
canShareText = no, canShareText = no,
hasGSensor = no, hasGSensor = no,
canToggleGSensor = no,
isGSensorLocked = no, isGSensorLocked = no,
canToggleMassStorage = no, canToggleMassStorage = no,
canToggleChargingLED = no, canToggleChargingLED = no,
@ -206,7 +205,8 @@ function Device:init()
self.screen:setViewport(self.viewport) self.screen:setViewport(self.viewport)
self.input:registerEventAdjustHook( self.input:registerEventAdjustHook(
self.input.adjustTouchTranslate, self.input.adjustTouchTranslate,
{x = 0 - self.viewport.x, y = 0 - self.viewport.y}) {x = 0 - self.viewport.x, y = 0 - self.viewport.y}
)
end end
-- Handle button mappings shenanigans -- Handle button mappings shenanigans
@ -216,8 +216,13 @@ function Device:init()
end end
end end
-- Honor the gyro lock
if self:hasGSensor() then if self:hasGSensor() then
-- Setup our standard gyro event handler (EV_MSC:MSC_GYRO)
if G_reader_settings:nilOrFalse("input_ignore_gsensor") then
self.input.handleGyroEv = self.input.handleMiscGyroEv
end
-- Honor the gyro lock
if G_reader_settings:isTrue("input_lock_gsensor") then if G_reader_settings:isTrue("input_lock_gsensor") then
self:lockGSensor(true) self:lockGSensor(true)
end end
@ -418,8 +423,17 @@ function Device:performHapticFeedback(type) end
-- Device specific method for toggling input events -- Device specific method for toggling input events
function Device:setIgnoreInput(enable) return true end function Device:setIgnoreInput(enable) return true end
-- Device specific method for toggling the GSensor -- Device agnostic method for toggling the GSensor
function Device:toggleGSensor(toggle) end -- (can be reimplemented if need be, but you really, really should try not to. c.f., Kobo, Kindle & PocketBook)
function Device:toggleGSensor(toggle)
if not self:hasGSensor() then
return
end
if self.input then
self.input:toggleGyroEvents(toggle)
end
end
-- Whether or not the GSensor should be locked to the current orientation (i.e. Portrait <-> Inverted Portrait or Landscape <-> Inverted Landscape only) -- Whether or not the GSensor should be locked to the current orientation (i.e. Portrait <-> Inverted Portrait or Landscape <-> Inverted Landscape only)
function Device:lockGSensor(toggle) function Device:lockGSensor(toggle)

@ -984,7 +984,7 @@ function Contact:handlePan()
if msd_distance > gesture_detector.MULTISWIPE_THRESHOLD then if msd_distance > gesture_detector.MULTISWIPE_THRESHOLD then
local pan_ev_multiswipe = pan_ev local pan_ev_multiswipe = pan_ev
-- store a copy of pan_ev without rotation adjustment for multiswipe calculations when rotated -- store a copy of pan_ev without rotation adjustment for multiswipe calculations when rotated
if gesture_detector.screen:getTouchRotation() > gesture_detector.screen.ORIENTATION_PORTRAIT then if gesture_detector.screen:getTouchRotation() > gesture_detector.screen.DEVICE_ROTATED_UPRIGHT then
pan_ev_multiswipe = util.tableDeepCopy(pan_ev) pan_ev_multiswipe = util.tableDeepCopy(pan_ev)
end end
if msd_direction ~= msd_direction_prev then if msd_direction ~= msd_direction_prev then
@ -1335,7 +1335,7 @@ end
--]] --]]
function GestureDetector:adjustGesCoordinate(ges) function GestureDetector:adjustGesCoordinate(ges)
local mode = self.screen:getTouchRotation() local mode = self.screen:getTouchRotation()
if mode == self.screen.ORIENTATION_LANDSCAPE then if mode == self.screen.DEVICE_ROTATED_CLOCKWISE then
-- in landscape mode rotated 90 -- in landscape mode rotated 90
if ges.pos then if ges.pos then
ges.pos.x, ges.pos.y = (self.screen:getWidth() - ges.pos.y), (ges.pos.x) ges.pos.x, ges.pos.y = (self.screen:getWidth() - ges.pos.y), (ges.pos.x)
@ -1367,7 +1367,7 @@ function GestureDetector:adjustGesCoordinate(ges)
end end
logger.dbg("GestureDetector: Landscape translation for ges:", ges.ges, ges.direction) logger.dbg("GestureDetector: Landscape translation for ges:", ges.ges, ges.direction)
end end
elseif mode == self.screen.ORIENTATION_LANDSCAPE_ROTATED then elseif mode == self.screen.DEVICE_ROTATED_COUNTER_CLOCKWISE then
-- in landscape mode rotated 270 -- in landscape mode rotated 270
if ges.pos then if ges.pos then
ges.pos.x, ges.pos.y = (ges.pos.y), (self.screen:getHeight() - ges.pos.x) ges.pos.x, ges.pos.y = (ges.pos.y), (self.screen:getHeight() - ges.pos.x)
@ -1399,7 +1399,7 @@ function GestureDetector:adjustGesCoordinate(ges)
end end
logger.dbg("GestureDetector: Inverted landscape translation for ges:", ges.ges, ges.direction) logger.dbg("GestureDetector: Inverted landscape translation for ges:", ges.ges, ges.direction)
end end
elseif mode == self.screen.ORIENTATION_PORTRAIT_ROTATED then elseif mode == self.screen.DEVICE_ROTATED_UPSIDE_DOWN then
-- in portrait mode rotated 180 -- in portrait mode rotated 180
if ges.pos then if ges.pos then
ges.pos.x, ges.pos.y = (self.screen:getWidth() - ges.pos.x), (self.screen:getHeight() - ges.pos.y) ges.pos.x, ges.pos.y = (self.screen:getWidth() - ges.pos.x), (self.screen:getHeight() - ges.pos.y)

@ -19,42 +19,10 @@ local C = ffi.C
require("ffi/posix_h") require("ffi/posix_h")
require("ffi/linux_input_h") require("ffi/linux_input_h")
-- luacheck: push -- EV_KEY values
-- luacheck: ignore local KEY_PRESS = 1
-- key press event values (KEY.value) local KEY_REPEAT = 2
local EVENT_VALUE_KEY_PRESS = 1 local KEY_RELEASE = 0
local EVENT_VALUE_KEY_REPEAT = 2
local EVENT_VALUE_KEY_RELEASE = 0
-- For Kindle Oasis orientation events (ABS.code)
-- the ABS code of orientation event will be adjusted to -24 from 24 (C.ABS_PRESSURE)
-- as C.ABS_PRESSURE is also used to detect touch input in KOBO devices.
local ABS_OASIS_ORIENTATION = -24
local DEVICE_ORIENTATION_PORTRAIT_LEFT = 15
local DEVICE_ORIENTATION_PORTRAIT_RIGHT = 17
local DEVICE_ORIENTATION_PORTRAIT = 19
local DEVICE_ORIENTATION_PORTRAIT_ROTATED_LEFT = 16
local DEVICE_ORIENTATION_PORTRAIT_ROTATED_RIGHT = 18
local DEVICE_ORIENTATION_PORTRAIT_ROTATED = 20
local DEVICE_ORIENTATION_LANDSCAPE = 21
local DEVICE_ORIENTATION_LANDSCAPE_ROTATED = 22
-- Kindle Oasis 2 & 3 variant
-- c.f., drivers/input/misc/accel/bma2x2.c
local UPWARD_PORTRAIT_UP_INTERRUPT_HAPPENED = 15
local UPWARD_PORTRAIT_DOWN_INTERRUPT_HAPPENED = 16
local UPWARD_LANDSCAPE_LEFT_INTERRUPT_HAPPENED = 17
local UPWARD_LANDSCAPE_RIGHT_INTERRUPT_HAPPENED = 18
-- For the events of the Forma & Libra accelerometers (MSC.value)
-- c.f., drivers/hwmon/mma8x5x.c
local MSC_RAW_GSENSOR_PORTRAIT_DOWN = 0x17
local MSC_RAW_GSENSOR_PORTRAIT_UP = 0x18
local MSC_RAW_GSENSOR_LANDSCAPE_RIGHT = 0x19
local MSC_RAW_GSENSOR_LANDSCAPE_LEFT = 0x1a
-- Not that we care about those, but they are reported, and accurate ;).
local MSC_RAW_GSENSOR_BACK = 0x1b
local MSC_RAW_GSENSOR_FRONT = 0x1c
-- Based on ABS_MT_TOOL_TYPE values on Elan panels -- Based on ABS_MT_TOOL_TYPE values on Elan panels
local TOOL_TYPE_FINGER = 0 local TOOL_TYPE_FINGER = 0
@ -74,7 +42,6 @@ local linux_evdev_type_map = {
[C.EV_FF] = "EV_FF", [C.EV_FF] = "EV_FF",
[C.EV_PWR] = "EV_PWR", [C.EV_PWR] = "EV_PWR",
[C.EV_FF_STATUS] = "EV_FF_STATUS", [C.EV_FF_STATUS] = "EV_FF_STATUS",
[C.EV_MAX] = "EV_MAX",
[C.EV_SDL] = "EV_SDL", [C.EV_SDL] = "EV_SDL",
} }
@ -122,23 +89,23 @@ local linux_evdev_abs_code_map = {
local linux_evdev_msc_code_map = { local linux_evdev_msc_code_map = {
[C.MSC_RAW] = "MSC_RAW", [C.MSC_RAW] = "MSC_RAW",
[C.MSC_GYRO] = "MSC_GYRO",
} }
local linux_evdev_rep_code_map = { local linux_evdev_rep_code_map = {
[C.REP_DELAY] = "REP_DELAY", [C.REP_DELAY] = "REP_DELAY",
[C.REP_PERIOD] = "REP_PERIOD", [C.REP_PERIOD] = "REP_PERIOD",
} }
-- luacheck: pop
local _internal_clipboard_text = nil -- holds the last copied text local _internal_clipboard_text = nil -- holds the last copied text
local Input = { local Input = {
-- must point to the device implementation when instantiating -- must point to the device implementation when instantiating
device = nil, device = nil,
-- this depends on keyboard layout and should be overridden: -- this depends on keyboard layout and should be overridden
event_map = {}, event_map = nil, -- hash
-- adapters are post processing functions that transform a given event to another event -- adapters are post processing functions that transform a given event to another event
event_map_adapter = {}, event_map_adapter = nil, -- hash
-- EV_ABS event to honor for pressure event (if any) -- EV_ABS event to honor for pressure event (if any)
pressure_event = nil, pressure_event = nil,
@ -193,8 +160,8 @@ local Input = {
UsbDevicePlugOut = {}, UsbDevicePlugOut = {},
}, },
-- This might be overloaded or even disabled (post-init) at instance-level, so we don't want any inheritance -- This might be modified at runtime, so we don't want any inheritance
rotation_map = nil, -- nil or a hash rotation_map = nil, -- hash
timer_callbacks = nil, -- instance-specific table, because the object may get destroyed & recreated at runtime timer_callbacks = nil, -- instance-specific table, because the object may get destroyed & recreated at runtime
disable_double_tap = true, disable_double_tap = true,
@ -260,13 +227,20 @@ function Input:init()
input = self, input = self,
} }
if not self.event_map then
self.event_map = {}
end
if not self.event_map_adapter then
self.event_map_adapter = {}
end
-- NOTE: When looking at the device in Portrait mode, that's assuming PgBack is on TOP, and PgFwd on the BOTTOM -- NOTE: When looking at the device in Portrait mode, that's assuming PgBack is on TOP, and PgFwd on the BOTTOM
if not self.rotation_map then if not self.rotation_map then
self.rotation_map = { self.rotation_map = {
[framebuffer.ORIENTATION_PORTRAIT] = {}, [framebuffer.DEVICE_ROTATED_UPRIGHT] = {},
[framebuffer.ORIENTATION_LANDSCAPE] = { Up = "Right", Right = "Down", Down = "Left", Left = "Up", LPgBack = "LPgFwd", LPgFwd = "LPgBack", RPgBack = "RPgFwd", RPgFwd = "RPgBack" }, [framebuffer.DEVICE_ROTATED_CLOCKWISE] = { Up = "Right", Right = "Down", Down = "Left", Left = "Up", LPgBack = "LPgFwd", LPgFwd = "LPgBack", RPgBack = "RPgFwd", RPgFwd = "RPgBack" },
[framebuffer.ORIENTATION_PORTRAIT_ROTATED] = { Up = "Down", Right = "Left", Down = "Up", Left = "Right", LPgFwd = "LPgBack", LPgBack = "LPgFwd", RPgFwd = "RPgBack", RPgBack = "RPgFwd" }, [framebuffer.DEVICE_ROTATED_UPSIDE_DOWN] = { Up = "Down", Right = "Left", Down = "Up", Left = "Right", LPgFwd = "LPgBack", LPgBack = "LPgFwd", RPgFwd = "RPgBack", RPgBack = "RPgFwd" },
[framebuffer.ORIENTATION_LANDSCAPE_ROTATED] = { Up = "Left", Right = "Up", Down = "Right", Left = "Down" } [framebuffer.DEVICE_ROTATED_COUNTER_CLOCKWISE] = { Up = "Left", Right = "Up", Down = "Right", Left = "Down" },
} }
end end
@ -301,6 +275,18 @@ function Input:init()
self._inhibitInputUntil_func = function() self:inhibitInputUntil() end self._inhibitInputUntil_func = function() self:inhibitInputUntil() end
end end
--[[--
Setup a rotation_map that does nothing (for platforms where the events we get are already translated).
--]]
function Input:disableRotationMap()
self.rotation_map = {
[framebuffer.DEVICE_ROTATED_UPRIGHT] = {},
[framebuffer.DEVICE_ROTATED_CLOCKWISE] = {},
[framebuffer.DEVICE_ROTATED_UPSIDE_DOWN] = {},
[framebuffer.DEVICE_ROTATED_COUNTER_CLOCKWISE] = {},
}
end
--[[-- --[[--
Wrapper for FFI input open. Wrapper for FFI input open.
@ -313,22 +299,35 @@ function Input.open(device, is_emu_events)
end end
--[[-- --[[--
Different device models can implement their own hooks Different device models can implement their own hooks and register them.
and register them.
--]] --]]
function Input:registerEventAdjustHook(hook, hook_params) function Input:registerEventAdjustHook(hook, hook_params)
local old = self.eventAdjustHook if self.eventAdjustHook == Input.eventAdjustHook then
self.eventAdjustHook = function(this, ev) -- First custom hook, skip the default NOP
old(this, ev) self.eventAdjustHook = function(this, ev)
hook(this, ev, hook_params) hook(this, ev, hook_params)
end
else
-- We've already got a custom hook, chain 'em
local old = self.eventAdjustHook
self.eventAdjustHook = function(this, ev)
old(this, ev)
hook(this, ev, hook_params)
end
end end
end end
function Input:registerGestureAdjustHook(hook, hook_params) function Input:registerGestureAdjustHook(hook, hook_params)
local old = self.gestureAdjustHook if self.gestureAdjustHook == Input.gestureAdjustHook then
self.gestureAdjustHook = function(this, ges) self.gestureAdjustHook = function(this, ges)
old(this, ges) hook(this, ges, hook_params)
hook(this, ges, hook_params) end
else
local old = self.gestureAdjustHook
self.gestureAdjustHook = function(this, ges)
old(this, ges)
hook(this, ges, hook_params)
end
end end
end end
@ -341,59 +340,77 @@ function Input:gestureAdjustHook(ges)
end end
--- Catalog of predefined hooks. --- Catalog of predefined hooks.
function Input:adjustTouchSwitchXY(ev) -- These are *not* usable directly as hooks, they're just building blocks (c.f., Kobo)
if ev.type == C.EV_ABS then function Input:adjustABS_SwitchXY(ev)
if ev.code == C.ABS_X then if ev.code == C.ABS_X then
ev.code = C.ABS_Y ev.code = C.ABS_Y
elseif ev.code == C.ABS_Y then elseif ev.code == C.ABS_Y then
ev.code = C.ABS_X ev.code = C.ABS_X
elseif ev.code == C.ABS_MT_POSITION_X then elseif ev.code == C.ABS_MT_POSITION_X then
ev.code = C.ABS_MT_POSITION_Y ev.code = C.ABS_MT_POSITION_Y
elseif ev.code == C.ABS_MT_POSITION_Y then elseif ev.code == C.ABS_MT_POSITION_Y then
ev.code = C.ABS_MT_POSITION_X ev.code = C.ABS_MT_POSITION_X
end
end end
end end
function Input:adjustTouchScale(ev, by) function Input:adjustABS_Scale(ev, by)
if ev.type == C.EV_ABS then if ev.code == C.ABS_X or ev.code == C.ABS_MT_POSITION_X then
if ev.code == C.ABS_X or ev.code == C.ABS_MT_POSITION_X then ev.value = by.x * ev.value
ev.value = by.x * ev.value elseif ev.code == C.ABS_Y or ev.code == C.ABS_MT_POSITION_Y then
end ev.value = by.y * ev.value
if ev.code == C.ABS_Y or ev.code == C.ABS_MT_POSITION_Y then
ev.value = by.y * ev.value
end
end end
end end
function Input:adjustTouchMirrorX(ev, max_x) function Input:adjustABS_MirrorX(ev, max_x)
if ev.type == C.EV_ABS if ev.code == C.ABS_X or ev.code == C.ABS_MT_POSITION_X then
and (ev.code == C.ABS_X or ev.code == C.ABS_MT_POSITION_X) then
ev.value = max_x - ev.value ev.value = max_x - ev.value
end end
end end
function Input:adjustTouchMirrorY(ev, max_y) function Input:adjustABS_MirrorY(ev, max_y)
if ev.type == C.EV_ABS if ev.code == C.ABS_Y or ev.code == C.ABS_MT_POSITION_Y then
and (ev.code == C.ABS_Y or ev.code == C.ABS_MT_POSITION_Y) then
ev.value = max_y - ev.value ev.value = max_y - ev.value
end end
end end
function Input:adjustTouchTranslate(ev, by) function Input:adjustABS_SwitchAxesAndMirrorX(ev, max_x)
if ev.code == C.ABS_X then
ev.code = C.ABS_Y
elseif ev.code == C.ABS_Y then
ev.code = C.ABS_X
ev.value = max_x - ev.value
elseif ev.code == C.ABS_MT_POSITION_X then
ev.code = C.ABS_MT_POSITION_Y
elseif ev.code == C.ABS_MT_POSITION_Y then
ev.code = C.ABS_MT_POSITION_X
ev.value = max_x - ev.value
end
end
function Input:adjustABS_Translate(ev, by)
if ev.code == C.ABS_X or ev.code == C.ABS_MT_POSITION_X then
ev.value = by.x + ev.value
elseif ev.code == C.ABS_Y or ev.code == C.ABS_MT_POSITION_Y then
ev.value = by.y + ev.value
end
end
-- These *are* usable directly as hooks
function Input:adjustTouchScale(ev, by)
if ev.type == C.EV_ABS then if ev.type == C.EV_ABS then
if ev.code == C.ABS_X or ev.code == C.ABS_MT_POSITION_X then self:adjustABS_Scale(ev, by)
ev.value = by.x + ev.value end
end end
if ev.code == C.ABS_Y or ev.code == C.ABS_MT_POSITION_Y then
ev.value = by.y + ev.value function Input:adjustTouchSwitchAxesAndMirrorX(ev, max_x)
end if ev.type == C.EV_ABS then
self:adjustABS_SwitchAxesAndMirrorX(ev, max_x)
end end
end end
function Input:adjustKindleOasisOrientation(ev) function Input:adjustTouchTranslate(ev, by)
if ev.type == C.EV_ABS and ev.code == C.ABS_PRESSURE then if ev.type == C.EV_ABS then
ev.code = ABS_OASIS_ORIENTATION self:adjustABS_Translate(ev, by)
end end
end end
@ -548,11 +565,9 @@ function Input:handleKeyBoardEv(ev)
end end
-- take device rotation into account -- take device rotation into account
if self.rotation_map then local rota = self.device.screen:getRotationMode()
local rota = self.device.screen:getRotationMode() if self.rotation_map[rota][keycode] then
if self.rotation_map[rota][keycode] then keycode = self.rotation_map[rota][keycode]
keycode = self.rotation_map[rota][keycode]
end
end end
if self.fake_event_set[keycode] then if self.fake_event_set[keycode] then
@ -573,9 +588,9 @@ function Input:handleKeyBoardEv(ev)
if keycode == "Power" then if keycode == "Power" then
-- Kobo generates Power keycode only, we need to decide whether it's -- Kobo generates Power keycode only, we need to decide whether it's
-- power-on or power-off ourselves. -- power-on or power-off ourselves.
if ev.value == EVENT_VALUE_KEY_PRESS then if ev.value == KEY_PRESS then
return "PowerPress" return "PowerPress"
elseif ev.value == EVENT_VALUE_KEY_RELEASE then elseif ev.value == KEY_RELEASE then
return "PowerRelease" return "PowerRelease"
end end
end end
@ -596,9 +611,9 @@ function Input:handleKeyBoardEv(ev)
-- handle modifier keys -- handle modifier keys
if self.modifiers[keycode] ~= nil then if self.modifiers[keycode] ~= nil then
if ev.value == EVENT_VALUE_KEY_PRESS then if ev.value == KEY_PRESS then
self.modifiers[keycode] = true self.modifiers[keycode] = true
elseif ev.value == EVENT_VALUE_KEY_RELEASE then elseif ev.value == KEY_RELEASE then
self.modifiers[keycode] = false self.modifiers[keycode] = false
end end
return return
@ -606,9 +621,9 @@ function Input:handleKeyBoardEv(ev)
local key = Key:new(keycode, self.modifiers) local key = Key:new(keycode, self.modifiers)
if ev.value == EVENT_VALUE_KEY_PRESS then if ev.value == KEY_PRESS then
return Event:new("KeyPress", key) return Event:new("KeyPress", key)
elseif ev.value == EVENT_VALUE_KEY_REPEAT then elseif ev.value == KEY_REPEAT then
-- NOTE: We only care about repeat events from the pageturn buttons... -- NOTE: We only care about repeat events from the pageturn buttons...
-- And we *definitely* don't want to flood the Event queue with useless SleepCover repeats! -- And we *definitely* don't want to flood the Event queue with useless SleepCover repeats!
if keycode == "LPgBack" if keycode == "LPgBack"
@ -629,7 +644,7 @@ function Input:handleKeyBoardEv(ev)
self.repeat_count = 0 self.repeat_count = 0
end end
end end
elseif ev.value == EVENT_VALUE_KEY_RELEASE then elseif ev.value == KEY_RELEASE then
self.repeat_count = 0 self.repeat_count = 0
return Event:new("KeyRelease", key) return Event:new("KeyRelease", key)
end end
@ -662,9 +677,9 @@ function Input:handlePowerManagementOnlyEv(ev)
if keycode == "Power" then if keycode == "Power" then
-- Kobo generates Power keycode only, we need to decide whether it's -- Kobo generates Power keycode only, we need to decide whether it's
-- power-on or power-off ourselves. -- power-on or power-off ourselves.
if ev.value == EVENT_VALUE_KEY_PRESS then if ev.value == KEY_PRESS then
return "PowerPress" return "PowerPress"
elseif ev.value == EVENT_VALUE_KEY_RELEASE then elseif ev.value == KEY_RELEASE then
return "PowerRelease" return "PowerRelease"
end end
end end
@ -684,7 +699,11 @@ function Input:handleGenericEv(ev)
end end
function Input:handleMiscEv(ev) function Input:handleMiscEv(ev)
-- should be handled by a misc event protocol plugin -- overwritten by device implementation
end
function Input:handleGyroEv(ev)
-- setup by the Generic device implementation (for proper toggle handling)
end end
function Input:handleSdlEv(ev) function Input:handleSdlEv(ev)
@ -886,92 +905,29 @@ function Input:handleTouchEvLegacy(ev)
end end
end end
function Input:handleOasisOrientationEv(ev) --- Accelerometer, in a platform-agnostic, custom format (EV_MSC:MSC_GYRO).
local rotation_mode, screen_mode --- (Translation should be done via registerEventAdjustHook in Device implementations).
if self.device:isZelda() then --- This needs to be called *via handleGyroEv* in a handleMiscEv implementation (c.f., Kobo, Kindle or PocketBook).
if ev.value == UPWARD_PORTRAIT_UP_INTERRUPT_HAPPENED then function Input:handleMiscGyroEv(ev)
-- i.e., UR
rotation_mode = framebuffer.ORIENTATION_PORTRAIT
screen_mode = 'portrait'
elseif ev.value == UPWARD_LANDSCAPE_LEFT_INTERRUPT_HAPPENED then
-- i.e., CW
rotation_mode = framebuffer.ORIENTATION_LANDSCAPE
screen_mode = 'landscape'
elseif ev.value == UPWARD_PORTRAIT_DOWN_INTERRUPT_HAPPENED then
-- i.e., UD
rotation_mode = framebuffer.ORIENTATION_PORTRAIT_ROTATED
screen_mode = 'portrait'
elseif ev.value == UPWARD_LANDSCAPE_RIGHT_INTERRUPT_HAPPENED then
-- i.e., CCW
rotation_mode = framebuffer.ORIENTATION_LANDSCAPE_ROTATED
screen_mode = 'landscape'
end
else
if ev.value == DEVICE_ORIENTATION_PORTRAIT
or ev.value == DEVICE_ORIENTATION_PORTRAIT_LEFT
or ev.value == DEVICE_ORIENTATION_PORTRAIT_RIGHT then
-- i.e., UR
rotation_mode = framebuffer.ORIENTATION_PORTRAIT
screen_mode = 'portrait'
elseif ev.value == DEVICE_ORIENTATION_LANDSCAPE then
-- i.e., CW
rotation_mode = framebuffer.ORIENTATION_LANDSCAPE
screen_mode = 'landscape'
elseif ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED
or ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED_LEFT
or ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED_RIGHT then
-- i.e., UD
rotation_mode = framebuffer.ORIENTATION_PORTRAIT_ROTATED
screen_mode = 'portrait'
elseif ev.value == DEVICE_ORIENTATION_LANDSCAPE_ROTATED then
-- i.e., CCW
rotation_mode = framebuffer.ORIENTATION_LANDSCAPE_ROTATED
screen_mode = 'landscape'
end
end
local old_rotation_mode = self.device.screen:getRotationMode()
if self.device:isGSensorLocked() then
local old_screen_mode = self.device.screen:getScreenMode()
if rotation_mode ~= old_rotation_mode and screen_mode == old_screen_mode then
-- Cheaper than a full SetRotationMode event, as we don't need to re-layout anything.
self.device.screen:setRotationMode(rotation_mode)
local UIManager = require("ui/uimanager")
UIManager:onRotation()
end
else
if rotation_mode ~= old_rotation_mode then
return Event:new("SetRotationMode", rotation_mode)
end
end
end
--- Accelerometer on the Forma/Libra
function Input:handleMiscEvNTX(ev)
local rotation_mode, screen_mode local rotation_mode, screen_mode
if ev.code == C.MSC_RAW then if ev.value == C.DEVICE_ROTATED_UPRIGHT then
if ev.value == MSC_RAW_GSENSOR_PORTRAIT_UP then -- i.e., UR
-- i.e., UR rotation_mode = framebuffer.DEVICE_ROTATED_UPRIGHT
rotation_mode = framebuffer.ORIENTATION_PORTRAIT screen_mode = "portrait"
screen_mode = 'portrait' elseif ev.value == C.DEVICE_ROTATED_CLOCKWISE then
elseif ev.value == MSC_RAW_GSENSOR_LANDSCAPE_RIGHT then -- i.e., CW
-- i.e., CW rotation_mode = framebuffer.DEVICE_ROTATED_CLOCKWISE
rotation_mode = framebuffer.ORIENTATION_LANDSCAPE screen_mode = "landscape"
screen_mode = 'landscape' elseif ev.value == C.DEVICE_ROTATED_UPSIDE_DOWN then
elseif ev.value == MSC_RAW_GSENSOR_PORTRAIT_DOWN then -- i.e., UD
-- i.e., UD rotation_mode = framebuffer.DEVICE_ROTATED_UPSIDE_DOWN
rotation_mode = framebuffer.ORIENTATION_PORTRAIT_ROTATED screen_mode = "portrait"
screen_mode = 'portrait' elseif ev.value == C.DEVICE_ROTATED_COUNTER_CLOCKWISE then
elseif ev.value == MSC_RAW_GSENSOR_LANDSCAPE_LEFT then -- i.e., CCW
-- i.e., CCW rotation_mode = framebuffer.DEVICE_ROTATED_COUNTER_CLOCKWISE
rotation_mode = framebuffer.ORIENTATION_LANDSCAPE_ROTATED screen_mode = "landscape"
screen_mode = 'landscape'
else
-- Discard FRONT/BACK
return
end
else else
-- Discard unhandled event codes, just to future-proof this ;). -- Discard FRONT/BACK
return return
end end
@ -992,28 +948,24 @@ function Input:handleMiscEvNTX(ev)
end end
--- Allow toggling the accelerometer at runtime. --- Allow toggling the accelerometer at runtime.
function Input:toggleMiscEvNTX(toggle) function Input:toggleGyroEvents(toggle)
if toggle == true then if toggle == true then
-- Honor Gyro events -- Honor Gyro events
if not self.isNTXAccelHooked then if self.handleGyroEv ~= self.handleMiscGyroEv then
self.handleMiscEv = self.handleMiscEvNTX self.handleGyroEv = self.handleMiscGyroEv
self.isNTXAccelHooked = true
end end
elseif toggle == false then elseif toggle == false then
-- Ignore Gyro events -- Ignore Gyro events
if self.isNTXAccelHooked then if self.handleGyroEv == self.handleMiscGyroEv then
self.handleMiscEv = self.voidEv self.handleGyroEv = self.voidEv
self.isNTXAccelHooked = false
end end
else else
-- Toggle it -- Toggle it
if self.isNTXAccelHooked then if self.handleGyroEv == self.handleMiscGyroEv then
self.handleMiscEv = self.voidEv self.handleGyroEv = self.voidEv
else else
self.handleMiscEv = self.handleMiscEvNTX self.handleGyroEv = self.handleMiscGyroEv
end end
self.isNTXAccelHooked = not self.isNTXAccelHooked
end end
end end
@ -1096,15 +1048,15 @@ function Input:setupSlotData(value)
end end
function Input:isEvKeyPress(ev) function Input:isEvKeyPress(ev)
return ev.value == EVENT_VALUE_KEY_PRESS return ev.value == KEY_PRESS
end end
function Input:isEvKeyRepeat(ev) function Input:isEvKeyRepeat(ev)
return ev.value == EVENT_VALUE_KEY_REPEAT return ev.value == KEY_REPEAT
end end
function Input:isEvKeyRelease(ev) function Input:isEvKeyRelease(ev)
return ev.value == EVENT_VALUE_KEY_RELEASE return ev.value == KEY_RELEASE
end end
@ -1338,11 +1290,6 @@ function Input:waitEvent(now, deadline)
if handled_ev then if handled_ev then
table.insert(handled, handled_ev) table.insert(handled, handled_ev)
end end
elseif event.type == C.EV_ABS and event.code == ABS_OASIS_ORIENTATION then
local handled_ev = self:handleOasisOrientationEv(event)
if handled_ev then
table.insert(handled, handled_ev)
end
elseif event.type == C.EV_ABS or event.type == C.EV_SYN then elseif event.type == C.EV_ABS or event.type == C.EV_SYN then
local handled_evs = self:handleTouchEv(event) local handled_evs = self:handleTouchEv(event)
-- handleTouchEv only returns an array of Events once it gets a SYN_REPORT, -- handleTouchEv only returns an array of Events once it gets a SYN_REPORT,
@ -1393,23 +1340,17 @@ function Input:inhibitInput(toggle)
self.handleKeyBoardEv = self.handlePowerManagementOnlyEv self.handleKeyBoardEv = self.handlePowerManagementOnlyEv
end end
-- And send everything else to the void -- And send everything else to the void
if not self._oasis_ev_handler then
self._oasis_ev_handler = self.handleOasisOrientationEv
self.handleOasisOrientationEv = self.voidEv
end
if not self._abs_ev_handler then if not self._abs_ev_handler then
self._abs_ev_handler = self.handleTouchEv self._abs_ev_handler = self.handleTouchEv
self.handleTouchEv = self.voidEv self.handleTouchEv = self.voidEv
end end
if not self._msc_ev_handler then -- NOTE: We leave handleMiscEv alone, as some platforms make extensive use of EV_MSC for critical low-level stuff:
if not self.device:isPocketBook() and not self.device:isAndroid() then -- e.g., on PocketBook, it is used to handle InkView task management events (i.e., PM);
-- NOTE: PocketBook is a special snowflake, synthetic Power events are sent as EV_MSC. -- and on Android, for the critical purpose of forwarding Android events to Lua-land.
-- Thankfully, that's all that EV_MSC is used for on that platform. -- The only thing we might want to skip in there are gyro events anyway, which we'll handle separately.
-- NOTE: Android, on the other hand, handles a *lot* of critical stuff over EV_MSC, if not self._gyro_ev_handler then
-- as it's used to communicate between Android and Lua land ;). self._gyro_ev_handler = self.handleGyroEv
self._msc_ev_handler = self.handleMiscEv self.handleGyroEv = self.voidEv
self.handleMiscEv = self.voidEv
end
end end
if not self._sdl_ev_handler then if not self._sdl_ev_handler then
self._sdl_ev_handler = self.handleSdlEv self._sdl_ev_handler = self.handleSdlEv
@ -1429,17 +1370,13 @@ function Input:inhibitInput(toggle)
self.handleKeyBoardEv = self._key_ev_handler self.handleKeyBoardEv = self._key_ev_handler
self._key_ev_handler = nil self._key_ev_handler = nil
end end
if self._oasis_ev_handler then
self.handleOasisOrientationEv = self._oasis_ev_handler
self._oasis_ev_handler = nil
end
if self._abs_ev_handler then if self._abs_ev_handler then
self.handleTouchEv = self._abs_ev_handler self.handleTouchEv = self._abs_ev_handler
self._abs_ev_handler = nil self._abs_ev_handler = nil
end end
if self._msc_ev_handler then if self._gyro_ev_handler then
self.handleMiscEv = self._msc_ev_handler self.handleGyroEv = self._gyro_ev_handler
self._msc_ev_handler = nil self._gyro_ev_handler = nil
end end
if self._sdl_ev_handler then if self._sdl_ev_handler then
self.handleSdlEv = self._sdl_ev_handler self.handleSdlEv = self._sdl_ev_handler

@ -3,6 +3,13 @@ local time = require("ui/time")
local lfs = require("libs/libkoreader-lfs") local lfs = require("libs/libkoreader-lfs")
local logger = require("logger") local logger = require("logger")
-- We're going to need a few <linux/fb.h> & <linux/input.h> constants...
local ffi = require("ffi")
local C = ffi.C
require("ffi/linux_fb_h")
require("ffi/linux_input_h")
require("ffi/posix_h")
local function yes() return true end local function yes() return true end
local function no() return false end -- luacheck: ignore local function no() return false end -- luacheck: ignore
@ -823,6 +830,46 @@ function KindlePaperWhite3:init()
self.input.open("fake_events") self.input.open("fake_events")
end end
-- HAL for gyro orientation switches (EV_ABS:ABS_PRESSURE (?!) w/ custom values to EV_MSC:MSC_GYRO w/ our own custom values)
local function OasisGyroTranslation(this, ev)
local DEVICE_ORIENTATION_PORTRAIT_LEFT = 15
local DEVICE_ORIENTATION_PORTRAIT_RIGHT = 17
local DEVICE_ORIENTATION_PORTRAIT = 19
local DEVICE_ORIENTATION_PORTRAIT_ROTATED_LEFT = 16
local DEVICE_ORIENTATION_PORTRAIT_ROTATED_RIGHT = 18
local DEVICE_ORIENTATION_PORTRAIT_ROTATED = 20
local DEVICE_ORIENTATION_LANDSCAPE = 21
local DEVICE_ORIENTATION_LANDSCAPE_ROTATED = 22
if ev.type == C.EV_ABS and ev.code == C.ABS_PRESSURE then
if ev.value == DEVICE_ORIENTATION_PORTRAIT
or ev.value == DEVICE_ORIENTATION_PORTRAIT_LEFT
or ev.value == DEVICE_ORIENTATION_PORTRAIT_RIGHT then
-- i.e., UR
ev.type = C.EV_MSC
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_UPRIGHT
elseif ev.value == DEVICE_ORIENTATION_LANDSCAPE then
-- i.e., CW
ev.type = C.EV_MSC
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_CLOCKWISE
elseif ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED
or ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED_LEFT
or ev.value == DEVICE_ORIENTATION_PORTRAIT_ROTATED_RIGHT then
-- i.e., UD
ev.type = C.EV_MSC
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_UPSIDE_DOWN
elseif ev.value == DEVICE_ORIENTATION_LANDSCAPE_ROTATED then
-- i.e., CCW
ev.type = C.EV_MSC
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_COUNTER_CLOCKWISE
end
end
end
function KindleOasis:init() function KindleOasis:init()
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self, debug = logger.dbg} self.screen = require("ffi/framebuffer_mxcfb"):new{device = self, debug = logger.dbg}
self.powerd = require("device/kindle/powerd"):new{ self.powerd = require("device/kindle/powerd"):new{
@ -850,14 +897,14 @@ function KindleOasis:init()
"com.lab126.winmgr", "accelerometer") "com.lab126.winmgr", "accelerometer")
local rotation_mode = 0 local rotation_mode = 0
if orientation_code then if orientation_code then
if orientation_code == "V" then if orientation_code == "U" then
rotation_mode = self.screen.ORIENTATION_PORTRAIT rotation_mode = self.screen.DEVICE_ROTATED_UPRIGHT
elseif orientation_code == "R" then elseif orientation_code == "R" then
rotation_mode = self.screen.ORIENTATION_LANDSCAPE rotation_mode = self.screen.DEVICE_ROTATED_CLOCKWISE
elseif orientation_code == "D" then elseif orientation_code == "D" then
rotation_mode = self.screen.ORIENTATION_PORTRAIT_ROTATED rotation_mode = self.screen.DEVICE_ROTATED_UPSIDE_DOWN
elseif orientation_code == "L" then elseif orientation_code == "L" then
rotation_mode = self.screen.ORIENTATION_LANDSCAPE_ROTATED rotation_mode = self.screen.DEVICE_ROTATED_COUNTER_CLOCKWISE
end end
end end
@ -872,7 +919,12 @@ function KindleOasis:init()
Kindle.init(self) Kindle.init(self)
self.input:registerEventAdjustHook(self.input.adjustKindleOasisOrientation) self.input:registerEventAdjustHook(OasisGyroTranslation)
self.input.handleMiscEv = function(this, ev)
if ev.code == C.MSC_GYRO then
return this:handleGyroEv(ev)
end
end
self.input.open(self.touch_dev) self.input.open(self.touch_dev)
self.input.open("/dev/input/by-path/platform-gpiokey.0-event") self.input.open("/dev/input/by-path/platform-gpiokey.0-event")
@ -890,6 +942,39 @@ function KindleOasis:init()
self.input.open("fake_events") self.input.open("fake_events")
end end
-- HAL for gyro orientation switches (EV_ABS:ABS_PRESSURE (?!) w/ custom values to EV_MSC:MSC_GYRO w/ our own custom values)
local function ZeldaGyroTranslation(this, ev)
-- c.f., drivers/input/misc/accel/bma2x2.c
local UPWARD_PORTRAIT_UP_INTERRUPT_HAPPENED = 15
local UPWARD_PORTRAIT_DOWN_INTERRUPT_HAPPENED = 16
local UPWARD_LANDSCAPE_LEFT_INTERRUPT_HAPPENED = 17
local UPWARD_LANDSCAPE_RIGHT_INTERRUPT_HAPPENED = 18
if ev.type == C.EV_ABS and ev.code == C.ABS_PRESSURE then
if ev.value == UPWARD_PORTRAIT_UP_INTERRUPT_HAPPENED then
-- i.e., UR
ev.type = C.EV_MSC
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_UPRIGHT
elseif ev.value == UPWARD_LANDSCAPE_LEFT_INTERRUPT_HAPPENED then
-- i.e., CW
ev.type = C.EV_MSC
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_CLOCKWISE
elseif ev.value == UPWARD_PORTRAIT_DOWN_INTERRUPT_HAPPENED then
-- i.e., UD
ev.type = C.EV_MSC
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_UPSIDE_DOWN
elseif ev.value == UPWARD_LANDSCAPE_RIGHT_INTERRUPT_HAPPENED then
-- i.e., CCW
ev.type = C.EV_MSC
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_COUNTER_CLOCKWISE
end
end
end
function KindleOasis2:init() function KindleOasis2:init()
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self, debug = logger.dbg} self.screen = require("ffi/framebuffer_mxcfb"):new{device = self, debug = logger.dbg}
self.powerd = require("device/kindle/powerd"):new{ self.powerd = require("device/kindle/powerd"):new{
@ -926,13 +1011,13 @@ function KindleOasis2:init()
local rotation_mode = 0 local rotation_mode = 0
if orientation_code then if orientation_code then
if orientation_code == "U" then if orientation_code == "U" then
rotation_mode = self.screen.ORIENTATION_PORTRAIT rotation_mode = self.screen.DEVICE_ROTATED_UPRIGHT
elseif orientation_code == "R" then elseif orientation_code == "R" then
rotation_mode = self.screen.ORIENTATION_LANDSCAPE rotation_mode = self.screen.DEVICE_ROTATED_CLOCKWISE
elseif orientation_code == "D" then elseif orientation_code == "D" then
rotation_mode = self.screen.ORIENTATION_PORTRAIT_ROTATED rotation_mode = self.screen.DEVICE_ROTATED_UPSIDE_DOWN
elseif orientation_code == "L" then elseif orientation_code == "L" then
rotation_mode = self.screen.ORIENTATION_LANDSCAPE_ROTATED rotation_mode = self.screen.DEVICE_ROTATED_COUNTER_CLOCKWISE
end end
end end
@ -947,7 +1032,12 @@ function KindleOasis2:init()
Kindle.init(self) Kindle.init(self)
self.input:registerEventAdjustHook(self.input.adjustKindleOasisOrientation) self.input:registerEventAdjustHook(ZeldaGyroTranslation)
self.input.handleMiscEv = function(this, ev)
if ev.code == C.MSC_GYRO then
return this:handleGyroEv(ev)
end
end
self.input.open(self.touch_dev) self.input.open(self.touch_dev)
self.input.open("/dev/input/by-path/platform-gpio-keys-event") self.input.open("/dev/input/by-path/platform-gpio-keys-event")
@ -997,13 +1087,13 @@ function KindleOasis3:init()
local rotation_mode = 0 local rotation_mode = 0
if orientation_code then if orientation_code then
if orientation_code == "U" then if orientation_code == "U" then
rotation_mode = self.screen.ORIENTATION_PORTRAIT rotation_mode = self.screen.DEVICE_ROTATED_UPRIGHT
elseif orientation_code == "R" then elseif orientation_code == "R" then
rotation_mode = self.screen.ORIENTATION_LANDSCAPE rotation_mode = self.screen.DEVICE_ROTATED_CLOCKWISE
elseif orientation_code == "D" then elseif orientation_code == "D" then
rotation_mode = self.screen.ORIENTATION_PORTRAIT_ROTATED rotation_mode = self.screen.DEVICE_ROTATED_UPSIDE_DOWN
elseif orientation_code == "L" then elseif orientation_code == "L" then
rotation_mode = self.screen.ORIENTATION_LANDSCAPE_ROTATED rotation_mode = self.screen.DEVICE_ROTATED_COUNTER_CLOCKWISE
end end
end end
@ -1018,7 +1108,12 @@ function KindleOasis3:init()
Kindle.init(self) Kindle.init(self)
self.input:registerEventAdjustHook(self.input.adjustKindleOasisOrientation) self.input:registerEventAdjustHook(ZeldaGyroTranslation)
self.input.handleMiscEv = function(this, ev)
if ev.code == C.MSC_GYRO then
return this:handleGyroEv(ev)
end
end
self.input.open(self.touch_dev) self.input.open(self.touch_dev)
self.input.open("/dev/input/by-path/platform-gpio-keys-event") self.input.open("/dev/input/by-path/platform-gpio-keys-event")

@ -378,9 +378,7 @@ local KoboFrost = Kobo:extend{
hasFrontlight = yes, hasFrontlight = yes,
hasKeys = yes, hasKeys = yes,
hasGSensor = yes, hasGSensor = yes,
canToggleGSensor = yes,
touch_snow_protocol = true, touch_snow_protocol = true,
misc_ntx_gsensor_protocol = true,
display_dpi = 300, display_dpi = 300,
hasNaturalLight = yes, hasNaturalLight = yes,
frontlight_settings = { frontlight_settings = {
@ -403,9 +401,7 @@ local KoboStorm = Kobo:extend{
hasFrontlight = yes, hasFrontlight = yes,
hasKeys = yes, hasKeys = yes,
hasGSensor = yes, hasGSensor = yes,
canToggleGSensor = yes,
touch_snow_protocol = true, touch_snow_protocol = true,
misc_ntx_gsensor_protocol = true,
display_dpi = 300, display_dpi = 300,
hasNaturalLight = yes, hasNaturalLight = yes,
frontlight_settings = { frontlight_settings = {
@ -446,9 +442,7 @@ local KoboEuropa = Kobo:extend{
led_uses_channel_3 = true, led_uses_channel_3 = true,
hasFrontlight = yes, hasFrontlight = yes,
hasGSensor = yes, hasGSensor = yes,
canToggleGSensor = yes,
pressure_event = C.ABS_MT_PRESSURE, pressure_event = C.ABS_MT_PRESSURE,
misc_ntx_gsensor_protocol = true,
display_dpi = 227, display_dpi = 227,
boot_rota = C.FB_ROTATE_CCW, boot_rota = C.FB_ROTATE_CCW,
battery_sysfs = "/sys/class/power_supply/battery", battery_sysfs = "/sys/class/power_supply/battery",
@ -467,9 +461,7 @@ local KoboCadmus = Kobo:extend{
hasFrontlight = yes, hasFrontlight = yes,
hasKeys = yes, hasKeys = yes,
hasGSensor = yes, hasGSensor = yes,
canToggleGSensor = yes,
pressure_event = C.ABS_MT_PRESSURE, pressure_event = C.ABS_MT_PRESSURE,
misc_ntx_gsensor_protocol = true,
display_dpi = 300, display_dpi = 300,
hasNaturalLight = yes, hasNaturalLight = yes,
frontlight_settings = { frontlight_settings = {
@ -500,10 +492,8 @@ local KoboIo = Kobo:extend{
hasFrontlight = yes, hasFrontlight = yes,
hasKeys = yes, hasKeys = yes,
hasGSensor = yes, hasGSensor = yes,
canToggleGSensor = yes,
pressure_event = C.ABS_MT_PRESSURE, pressure_event = C.ABS_MT_PRESSURE,
touch_mirrored_x = false, touch_mirrored_x = false,
misc_ntx_gsensor_protocol = true,
display_dpi = 300, display_dpi = 300,
hasNaturalLight = yes, hasNaturalLight = yes,
frontlight_settings = { frontlight_settings = {
@ -908,28 +898,73 @@ function Kobo:setTouchEventHandler()
end end
-- Accelerometer -- Accelerometer
if self.misc_ntx_gsensor_protocol then if self:hasGSensor() then
if G_reader_settings:isTrue("input_ignore_gsensor") then self.input.handleMiscEv = function(this, ev)
self.input.isNTXAccelHooked = false -- As generated by gyroTranslation below
else if ev.code == C.MSC_GYRO then
self.input.handleMiscEv = self.input.handleMiscEvNTX return this:handleGyroEv(ev)
self.input.isNTXAccelHooked = true end
end end
end end
end end
function Kobo:initEventAdjustHooks() -- HAL for gyro orientation switches (NTX's EV_MSC:MSC_RAW w/ custom values to EV_MSC:MSC_GYRO w/ our own custom values)
-- NOTE: adjustTouchSwitchXY needs to be called before adjustTouchMirrorX local function gyroTranslation(ev)
if self.touch_switch_xy then -- c.f., include/uapi/linux/input.h,
self.input:registerEventAdjustHook(self.input.adjustTouchSwitchXY) -- implementations in drivers/hwmon/mma8x5x.c & drivers/input/touchscreen/kx122.c
local MSC_RAW_GSENSOR_PORTRAIT_DOWN = 0x17
local MSC_RAW_GSENSOR_PORTRAIT_UP = 0x18
local MSC_RAW_GSENSOR_LANDSCAPE_RIGHT = 0x19
local MSC_RAW_GSENSOR_LANDSCAPE_LEFT = 0x1a
-- Not that we care about those, but they are reported, and accurate ;).
--[[
local MSC_RAW_GSENSOR_BACK = 0x1b
local MSC_RAW_GSENSOR_FRONT = 0x1c
--]]
if ev.value == MSC_RAW_GSENSOR_PORTRAIT_UP then
-- i.e., UR
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_UPRIGHT
elseif ev.value == MSC_RAW_GSENSOR_LANDSCAPE_RIGHT then
-- i.e., CW
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_CLOCKWISE
elseif ev.value == MSC_RAW_GSENSOR_PORTRAIT_DOWN then
-- i.e., UD
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_UPSIDE_DOWN
elseif ev.value == MSC_RAW_GSENSOR_LANDSCAPE_LEFT then
-- i.e., CCW
ev.code = C.MSC_GYRO
ev.value = C.DEVICE_ROTATED_COUNTER_CLOCKWISE
end end
end
if self.touch_mirrored_x then function Kobo:initEventAdjustHooks()
self.input:registerEventAdjustHook( -- Build a single composite hook, to avoid duplicated branches...
self.input.adjustTouchMirrorX, local koboInputMangling
--- NOTE: This is safe, we enforce the canonical portrait rotation on startup. -- NOTE: touch_switch_xy is *always* true, but not touch_mirrored_x...
(self.screen:getWidth() - 1) if self.touch_switch_xy and self.touch_mirrored_x then
) local max_x = self.screen:getWidth() - 1
koboInputMangling = function(this, ev)
if ev.type == C.EV_ABS then
this:adjustABS_SwitchAxesAndMirrorX(ev, max_x)
elseif ev.type == C.EV_MSC and ev.code == C.MSC_RAW then
gyroTranslation(ev)
end
end
elseif self.touch_switch_xy and not self.touch_mirrored_x then
koboInputMangling = function(this, ev)
if ev.type == C.EV_ABS then
this:adjustABS_SwitchXY(ev)
elseif ev.type == C.EV_MSC and ev.code == C.MSC_RAW then
gyroTranslation(ev)
end
end
end
if koboInputMangling then
self.input:registerEventAdjustHook(koboInputMangling)
end end
end end
@ -1270,14 +1305,6 @@ function Kobo:reboot()
os.execute("sleep 1 && reboot &") os.execute("sleep 1 && reboot &")
end end
function Kobo:toggleGSensor(toggle)
if self:canToggleGSensor() and self.input then
if self.misc_ntx_gsensor_protocol then
self.input:toggleMiscEvNTX(toggle)
end
end
end
function Kobo:toggleChargingLED(toggle) function Kobo:toggleChargingLED(toggle)
-- We have no way of querying the current state from the HW! -- We have no way of querying the current state from the HW!
if toggle == nil then if toggle == nil then

@ -217,13 +217,15 @@ function PocketBook:init()
-- Auto shutdown event from inkview framework, -- Auto shutdown event from inkview framework,
-- gracefully close everything and let the framework shutdown the device. -- gracefully close everything and let the framework shutdown the device.
return "Exit" return "Exit"
elseif ev.code == C.MSC_GYRO then
return this:handleGyroEv(ev)
end end
end, end,
} }
-- If InkView translates buttons for us, disable our own translation map -- If InkView translates buttons for us, disable our own translation map
if self.inkview_translates_buttons then if self.inkview_translates_buttons then
self.input.rotation_map = nil self.input:disableRotationMap()
end end
-- In contrast to kobo/kindle, pocketbook-devices do not use linux/input events directly. -- In contrast to kobo/kindle, pocketbook-devices do not use linux/input events directly.
@ -645,8 +647,8 @@ local PocketBookColorLux = PocketBook:extend{
canUseCBB = no, -- 24bpp canUseCBB = no, -- 24bpp
} }
function PocketBookColorLux:_model_init() function PocketBookColorLux:_model_init()
self.screen.blitbuffer_rotation_mode = self.screen.ORIENTATION_PORTRAIT self.screen.blitbuffer_rotation_mode = self.screen.DEVICE_ROTATED_UPRIGHT
self.screen.native_rotation_mode = self.screen.ORIENTATION_PORTRAIT self.screen.native_rotation_mode = self.screen.DEVICE_ROTATED_UPRIGHT
end end
function PocketBookColorLux._fb_init(fb, finfo, vinfo) function PocketBookColorLux._fb_init(fb, finfo, vinfo)
-- Pocketbook Color Lux reports bits_per_pixel = 8, but actually uses an RGB24 framebuffer -- Pocketbook Color Lux reports bits_per_pixel = 8, but actually uses an RGB24 framebuffer

@ -159,7 +159,7 @@ function Remarkable:init()
-- USB plug/unplug, battery charge/not charging are generated as fake events -- USB plug/unplug, battery charge/not charging are generated as fake events
self.input.open("fake_events") self.input.open("fake_events")
local rotation_mode = self.screen.ORIENTATION_PORTRAIT local rotation_mode = self.screen.DEVICE_ROTATED_UPRIGHT
self.screen.native_rotation_mode = rotation_mode self.screen.native_rotation_mode = rotation_mode
self.screen.cur_rotation_mode = rotation_mode self.screen.cur_rotation_mode = rotation_mode

@ -301,9 +301,8 @@ function Device:init()
end end
if portrait then if portrait then
self.input:registerEventAdjustHook(self.input.adjustTouchSwitchXY)
self.input:registerEventAdjustHook( self.input:registerEventAdjustHook(
self.input.adjustTouchMirrorX, self.input.adjustTouchSwitchAxesAndMirrorX,
(self.screen:getScreenWidth() - 1) (self.screen:getScreenWidth() - 1)
) )
end end

@ -64,7 +64,7 @@ function SonyPRSTUX:init()
self.input.open("fake_events") -- usb plug-in/out and charging/not-charging self.input.open("fake_events") -- usb plug-in/out and charging/not-charging
self.input:registerEventAdjustHook(adjustTouchEvt) self.input:registerEventAdjustHook(adjustTouchEvt)
local rotation_mode = self.screen.ORIENTATION_LANDSCAPE_ROTATED local rotation_mode = self.screen.DEVICE_ROTATED_COUNTER_CLOCKWISE
self.screen.native_rotation_mode = rotation_mode self.screen.native_rotation_mode = rotation_mode
self.screen.cur_rotation_mode = rotation_mode self.screen.cur_rotation_mode = rotation_mode

@ -68,7 +68,7 @@ local settingsList = {
toggle_no_flash_on_second_chapter_page = {category="none", event="ToggleNoFlashOnSecondChapterPage", title=_("Toggle flashing on chapter's 2nd page"), screen=true, condition=Device:hasEinkScreen(), separator=true}, toggle_no_flash_on_second_chapter_page = {category="none", event="ToggleNoFlashOnSecondChapterPage", title=_("Toggle flashing on chapter's 2nd page"), screen=true, condition=Device:hasEinkScreen(), separator=true},
-- Device settings -- Device settings
toggle_gsensor = {category="none", event="ToggleGSensor", title=_("Toggle accelerometer"), device=true, condition=Device:canToggleGSensor()}, toggle_gsensor = {category="none", event="ToggleGSensor", title=_("Toggle accelerometer"), device=true, condition=Device:hasGSensor()},
wifi_on = {category="none", event="InfoWifiOn", title=_("Turn on Wi-Fi"), device=true, condition=Device:hasWifiToggle()}, wifi_on = {category="none", event="InfoWifiOn", title=_("Turn on Wi-Fi"), device=true, condition=Device:hasWifiToggle()},
wifi_off = {category="none", event="InfoWifiOff", title=_("Turn off Wi-Fi"), device=true, condition=Device:hasWifiToggle()}, wifi_off = {category="none", event="InfoWifiOff", title=_("Turn off Wi-Fi"), device=true, condition=Device:hasWifiToggle()},
toggle_wifi = {category="none", event="ToggleWifi", title=_("Toggle Wi-Fi"), device=true, condition=Device:hasWifiToggle()}, toggle_wifi = {category="none", event="ToggleWifi", title=_("Toggle Wi-Fi"), device=true, condition=Device:hasWifiToggle()},

@ -55,7 +55,7 @@ local CreOptions = {
name = "rotation_mode", name = "rotation_mode",
name_text = _("Rotation"), name_text = _("Rotation"),
item_icons_func = function() item_icons_func = function()
if Screen:getRotationMode() == Screen.ORIENTATION_PORTRAIT then if Screen:getRotationMode() == Screen.DEVICE_ROTATED_UPRIGHT then
-- P, 0UR -- P, 0UR
return { return {
"rotation.P.90CCW", "rotation.P.90CCW",
@ -63,7 +63,7 @@ local CreOptions = {
"rotation.P.90CW", "rotation.P.90CW",
"rotation.P.180UD", "rotation.P.180UD",
} }
elseif Screen:getRotationMode() == Screen.ORIENTATION_PORTRAIT_ROTATED then elseif Screen:getRotationMode() == Screen.DEVICE_ROTATED_UPSIDE_DOWN then
-- P, 180UD -- P, 180UD
return { return {
"rotation.P.90CW", "rotation.P.90CW",
@ -71,7 +71,7 @@ local CreOptions = {
"rotation.P.90CCW", "rotation.P.90CCW",
"rotation.P.0UR", "rotation.P.0UR",
} }
elseif Screen:getRotationMode() == Screen.ORIENTATION_LANDSCAPE then elseif Screen:getRotationMode() == Screen.DEVICE_ROTATED_CLOCKWISE then
-- L, 90CW -- L, 90CW
return { return {
"rotation.L.90CCW", "rotation.L.90CCW",
@ -92,8 +92,8 @@ local CreOptions = {
-- For Dispatcher & onMakeDefault's sake -- For Dispatcher & onMakeDefault's sake
labels = {C_("Rotation", "⤹ 90°"), C_("Rotation", "↑ 0°"), C_("Rotation", "⤸ 90°"), C_("Rotation", "↓ 180°")}, labels = {C_("Rotation", "⤹ 90°"), C_("Rotation", "↑ 0°"), C_("Rotation", "⤸ 90°"), C_("Rotation", "↓ 180°")},
alternate = false, alternate = false,
values = {Screen.ORIENTATION_LANDSCAPE_ROTATED, Screen.ORIENTATION_PORTRAIT, Screen.ORIENTATION_LANDSCAPE, Screen.ORIENTATION_PORTRAIT_ROTATED}, values = {Screen.DEVICE_ROTATED_COUNTER_CLOCKWISE, Screen.DEVICE_ROTATED_UPRIGHT, Screen.DEVICE_ROTATED_CLOCKWISE, Screen.DEVICE_ROTATED_UPSIDE_DOWN},
args = {Screen.ORIENTATION_LANDSCAPE_ROTATED, Screen.ORIENTATION_PORTRAIT, Screen.ORIENTATION_LANDSCAPE, Screen.ORIENTATION_PORTRAIT_ROTATED}, args = {Screen.DEVICE_ROTATED_COUNTER_CLOCKWISE, Screen.DEVICE_ROTATED_UPRIGHT, Screen.DEVICE_ROTATED_CLOCKWISE, Screen.DEVICE_ROTATED_UPSIDE_DOWN},
default_arg = 0, default_arg = 0,
current_func = function() return Screen:getRotationMode() end, current_func = function() return Screen:getRotationMode() end,
event = "SetRotationMode", event = "SetRotationMode",

@ -29,7 +29,7 @@ local KoptOptions = {
name = "rotation_mode", name = "rotation_mode",
name_text = _("Rotation"), name_text = _("Rotation"),
item_icons_func = function() item_icons_func = function()
if Screen:getRotationMode() == Screen.ORIENTATION_PORTRAIT then if Screen:getRotationMode() == Screen.DEVICE_ROTATED_UPRIGHT then
-- P, 0UR -- P, 0UR
return { return {
"rotation.P.90CCW", "rotation.P.90CCW",
@ -37,7 +37,7 @@ local KoptOptions = {
"rotation.P.90CW", "rotation.P.90CW",
"rotation.P.180UD", "rotation.P.180UD",
} }
elseif Screen:getRotationMode() == Screen.ORIENTATION_PORTRAIT_ROTATED then elseif Screen:getRotationMode() == Screen.DEVICE_ROTATED_UPSIDE_DOWN then
-- P, 180UD -- P, 180UD
return { return {
"rotation.P.90CW", "rotation.P.90CW",
@ -45,7 +45,7 @@ local KoptOptions = {
"rotation.P.90CCW", "rotation.P.90CCW",
"rotation.P.0UR", "rotation.P.0UR",
} }
elseif Screen:getRotationMode() == Screen.ORIENTATION_LANDSCAPE then elseif Screen:getRotationMode() == Screen.DEVICE_ROTATED_CLOCKWISE then
-- L, 90CW -- L, 90CW
return { return {
"rotation.L.90CCW", "rotation.L.90CCW",
@ -66,8 +66,8 @@ local KoptOptions = {
-- For Dispatcher & onMakeDefault's sake -- For Dispatcher & onMakeDefault's sake
labels = {C_("Rotation", "⤹ 90°"), C_("Rotation", "↑ 0°"), C_("Rotation", "⤸ 90°"), C_("Rotation", "↓ 180°")}, labels = {C_("Rotation", "⤹ 90°"), C_("Rotation", "↑ 0°"), C_("Rotation", "⤸ 90°"), C_("Rotation", "↓ 180°")},
alternate = false, alternate = false,
values = {Screen.ORIENTATION_LANDSCAPE_ROTATED, Screen.ORIENTATION_PORTRAIT, Screen.ORIENTATION_LANDSCAPE, Screen.ORIENTATION_PORTRAIT_ROTATED}, values = {Screen.DEVICE_ROTATED_COUNTER_CLOCKWISE, Screen.DEVICE_ROTATED_UPRIGHT, Screen.DEVICE_ROTATED_CLOCKWISE, Screen.DEVICE_ROTATED_UPSIDE_DOWN},
args = {Screen.ORIENTATION_LANDSCAPE_ROTATED, Screen.ORIENTATION_PORTRAIT, Screen.ORIENTATION_LANDSCAPE, Screen.ORIENTATION_PORTRAIT_ROTATED}, args = {Screen.DEVICE_ROTATED_COUNTER_CLOCKWISE, Screen.DEVICE_ROTATED_UPRIGHT, Screen.DEVICE_ROTATED_CLOCKWISE, Screen.DEVICE_ROTATED_UPSIDE_DOWN},
default_arg = 0, default_arg = 0,
current_func = function() return Screen:getRotationMode() end, current_func = function() return Screen:getRotationMode() end,
event = "SetRotationMode", event = "SetRotationMode",

@ -11,7 +11,7 @@ return {
sub_item_table_func = function() sub_item_table_func = function()
local rotation_table = {} local rotation_table = {}
if Device:hasGSensor() and Device:canToggleGSensor() then if Device:hasGSensor() then
table.insert(rotation_table, { table.insert(rotation_table, {
text = _("Ignore accelerometer rotation events"), text = _("Ignore accelerometer rotation events"),
help_text = _("This will inhibit automatic rotations triggered by your device's gyro."), help_text = _("This will inhibit automatic rotations triggered by your device's gyro."),
@ -64,84 +64,84 @@ When unchecked, the default rotation of the file browser and the default/saved r
table.insert(rotation_table, { table.insert(rotation_table, {
text_func = function() text_func = function()
local text = C_("Rotation", "⤹ 90°") local text = C_("Rotation", "⤹ 90°")
if G_reader_settings:readSetting("fm_rotation_mode") == Screen.ORIENTATION_LANDSCAPE_ROTATED then if G_reader_settings:readSetting("fm_rotation_mode") == Screen.DEVICE_ROTATED_COUNTER_CLOCKWISE then
text = text .. "" text = text .. ""
end end
return text return text
end, end,
checked_func = function() checked_func = function()
return Screen:getRotationMode() == Screen.ORIENTATION_LANDSCAPE_ROTATED return Screen:getRotationMode() == Screen.DEVICE_ROTATED_COUNTER_CLOCKWISE
end, end,
radio = true, radio = true,
callback = function(touchmenu_instance) callback = function(touchmenu_instance)
UIManager:broadcastEvent(Event:new("SetRotationMode", Screen.ORIENTATION_LANDSCAPE_ROTATED)) UIManager:broadcastEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_COUNTER_CLOCKWISE))
if touchmenu_instance then touchmenu_instance:closeMenu() end if touchmenu_instance then touchmenu_instance:closeMenu() end
end, end,
hold_callback = function(touchmenu_instance) hold_callback = function(touchmenu_instance)
G_reader_settings:saveSetting("fm_rotation_mode", Screen.ORIENTATION_LANDSCAPE_ROTATED) G_reader_settings:saveSetting("fm_rotation_mode", Screen.DEVICE_ROTATED_COUNTER_CLOCKWISE)
if touchmenu_instance then touchmenu_instance:updateItems() end if touchmenu_instance then touchmenu_instance:updateItems() end
end, end,
}) })
table.insert(rotation_table, { table.insert(rotation_table, {
text_func = function() text_func = function()
local text = C_("Rotation", "↑ 0°") local text = C_("Rotation", "↑ 0°")
if G_reader_settings:readSetting("fm_rotation_mode") == Screen.ORIENTATION_PORTRAIT then if G_reader_settings:readSetting("fm_rotation_mode") == Screen.DEVICE_ROTATED_UPRIGHT then
text = text .. "" text = text .. ""
end end
return text return text
end, end,
checked_func = function() checked_func = function()
return Screen:getRotationMode() == Screen.ORIENTATION_PORTRAIT return Screen:getRotationMode() == Screen.DEVICE_ROTATED_UPRIGHT
end, end,
radio = true, radio = true,
callback = function(touchmenu_instance) callback = function(touchmenu_instance)
UIManager:broadcastEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT)) UIManager:broadcastEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPRIGHT))
if touchmenu_instance then touchmenu_instance:closeMenu() end if touchmenu_instance then touchmenu_instance:closeMenu() end
end, end,
hold_callback = function(touchmenu_instance) hold_callback = function(touchmenu_instance)
G_reader_settings:saveSetting("fm_rotation_mode", Screen.ORIENTATION_PORTRAIT) G_reader_settings:saveSetting("fm_rotation_mode", Screen.DEVICE_ROTATED_UPRIGHT)
if touchmenu_instance then touchmenu_instance:updateItems() end if touchmenu_instance then touchmenu_instance:updateItems() end
end, end,
}) })
table.insert(rotation_table, { table.insert(rotation_table, {
text_func = function() text_func = function()
local text = C_("Rotation", "⤸ 90°") local text = C_("Rotation", "⤸ 90°")
if G_reader_settings:readSetting("fm_rotation_mode") == Screen.ORIENTATION_LANDSCAPE then if G_reader_settings:readSetting("fm_rotation_mode") == Screen.DEVICE_ROTATED_CLOCKWISE then
text = text .. "" text = text .. ""
end end
return text return text
end, end,
checked_func = function() checked_func = function()
return Screen:getRotationMode() == Screen.ORIENTATION_LANDSCAPE return Screen:getRotationMode() == Screen.DEVICE_ROTATED_CLOCKWISE
end, end,
radio = true, radio = true,
callback = function(touchmenu_instance) callback = function(touchmenu_instance)
UIManager:broadcastEvent(Event:new("SetRotationMode", Screen.ORIENTATION_LANDSCAPE)) UIManager:broadcastEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_CLOCKWISE))
if touchmenu_instance then touchmenu_instance:closeMenu() end if touchmenu_instance then touchmenu_instance:closeMenu() end
end, end,
hold_callback = function(touchmenu_instance) hold_callback = function(touchmenu_instance)
G_reader_settings:saveSetting("fm_rotation_mode", Screen.ORIENTATION_LANDSCAPE) G_reader_settings:saveSetting("fm_rotation_mode", Screen.DEVICE_ROTATED_CLOCKWISE)
if touchmenu_instance then touchmenu_instance:updateItems() end if touchmenu_instance then touchmenu_instance:updateItems() end
end, end,
}) })
table.insert(rotation_table, { table.insert(rotation_table, {
text_func = function() text_func = function()
local text = C_("Rotation", "↓ 180°") local text = C_("Rotation", "↓ 180°")
if G_reader_settings:readSetting("fm_rotation_mode") == Screen.ORIENTATION_PORTRAIT_ROTATED then if G_reader_settings:readSetting("fm_rotation_mode") == Screen.DEVICE_ROTATED_UPSIDE_DOWN then
text = text .. "" text = text .. ""
end end
return text return text
end, end,
checked_func = function() checked_func = function()
return Screen:getRotationMode() == Screen.ORIENTATION_PORTRAIT_ROTATED return Screen:getRotationMode() == Screen.DEVICE_ROTATED_UPSIDE_DOWN
end, end,
radio = true, radio = true,
callback = function(touchmenu_instance) callback = function(touchmenu_instance)
UIManager:broadcastEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT_ROTATED)) UIManager:broadcastEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPSIDE_DOWN))
if touchmenu_instance then touchmenu_instance:closeMenu() end if touchmenu_instance then touchmenu_instance:closeMenu() end
end, end,
hold_callback = function(touchmenu_instance) hold_callback = function(touchmenu_instance)
G_reader_settings:saveSetting("fm_rotation_mode", Screen.ORIENTATION_PORTRAIT_ROTATED) G_reader_settings:saveSetting("fm_rotation_mode", Screen.DEVICE_ROTATED_UPSIDE_DOWN)
if touchmenu_instance then touchmenu_instance:updateItems() end if touchmenu_instance then touchmenu_instance:updateItems() end
end, end,
}) })

@ -628,7 +628,7 @@ function Screensaver:show()
-- Leave Portrait & Inverted Portrait alone, that works just fine. -- Leave Portrait & Inverted Portrait alone, that works just fine.
if bit.band(Device.orig_rotation_mode, 1) == 1 then if bit.band(Device.orig_rotation_mode, 1) == 1 then
-- i.e., only switch to Portrait if we're currently in *any* Landscape orientation (odd number) -- i.e., only switch to Portrait if we're currently in *any* Landscape orientation (odd number)
Screen:setRotationMode(Screen.ORIENTATION_PORTRAIT) Screen:setRotationMode(Screen.DEVICE_ROTATED_UPRIGHT)
else else
Device.orig_rotation_mode = nil Device.orig_rotation_mode = nil
end end

@ -252,7 +252,7 @@ describe("device module", function()
usec = 450565, usec = 450565,
sec = 1471081881 sec = 1471081881
}, },
code = 24, -- C.ABS_PRESSURE -> ABS_OASIS_ORIENTATION code = 24, -- C.ABS_PRESSURE
value = 16 value = 16
} }
}) })

@ -13,10 +13,10 @@ describe("gesturedetector module", function()
multiswipe_directions = direction, multiswipe_directions = direction,
} }
GestureDetector.screen = { GestureDetector.screen = {
ORIENTATION_PORTRAIT = 0, DEVICE_ROTATED_UPRIGHT = 0,
ORIENTATION_LANDSCAPE = 1, DEVICE_ROTATED_CLOCKWISE = 1,
ORIENTATION_PORTRAIT_ROTATED = 2, DEVICE_ROTATED_UPSIDE_DOWN = 2,
ORIENTATION_LANDSCAPE_ROTATED = 3, DEVICE_ROTATED_COUNTER_CLOCKWISE = 3,
} }
GestureDetector.screen.getTouchRotation = function() return rotation_mode end GestureDetector.screen.getTouchRotation = function() return rotation_mode end

@ -22,7 +22,7 @@ describe("Readerrolling module", function()
describe("test in portrait screen mode", function() describe("test in portrait screen mode", function()
it("should goto portrait screen mode", function() it("should goto portrait screen mode", function()
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPRIGHT))
end) end)
it("should goto certain page", function() it("should goto certain page", function()
@ -119,7 +119,7 @@ describe("Readerrolling module", function()
describe("test in landscape screen mode", function() describe("test in landscape screen mode", function()
it("should go to landscape screen mode", function() it("should go to landscape screen mode", function()
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_LANDSCAPE)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_CLOCKWISE))
end) end)
it("should goto certain page", function() it("should goto certain page", function()
for i = 1, 10, 5 do for i = 1, 10, 5 do
@ -167,27 +167,27 @@ describe("Readerrolling module", function()
describe("switching screen mode should not change current page number", function() describe("switching screen mode should not change current page number", function()
teardown(function() teardown(function()
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPRIGHT))
end) end)
it("for portrait-landscape-portrait switching", function() it("for portrait-landscape-portrait switching", function()
for i = 80, 100, 10 do for i = 80, 100, 10 do
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPRIGHT))
rolling:onGotoPage(i) rolling:onGotoPage(i)
assert.are.same(i, rolling.current_page) assert.are.same(i, rolling.current_page)
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_LANDSCAPE)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_CLOCKWISE))
assert.are_not.same(i, rolling.current_page) assert.are_not.same(i, rolling.current_page)
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPRIGHT))
assert.are.same(i, rolling.current_page) assert.are.same(i, rolling.current_page)
end end
end) end)
it("for landscape-portrait-landscape switching", function() it("for landscape-portrait-landscape switching", function()
for i = 110, 130, 10 do for i = 110, 130, 10 do
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_LANDSCAPE)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_CLOCKWISE))
rolling:onGotoPage(i) rolling:onGotoPage(i)
assert.are.same(i, rolling.current_page) assert.are.same(i, rolling.current_page)
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPRIGHT))
assert.are_not.same(i, rolling.current_page) assert.are_not.same(i, rolling.current_page)
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_LANDSCAPE)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_CLOCKWISE))
assert.are.same(i, rolling.current_page) assert.are.same(i, rolling.current_page)
end end
end) end)

@ -18,14 +18,14 @@ describe("ReaderScreenshot module", function()
end) end)
teardown(function() teardown(function()
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPRIGHT))
readerui:closeDocument() readerui:closeDocument()
readerui:onClose() readerui:onClose()
end) end)
it("should get screenshot in portrait", function() it("should get screenshot in portrait", function()
local name = "screenshots/reader_screenshot_portrait.png" local name = "screenshots/reader_screenshot_portrait.png"
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPRIGHT))
UIManager:quit() UIManager:quit()
UIManager:show(readerui) UIManager:show(readerui)
UIManager:scheduleIn(1, function() UIManager:scheduleIn(1, function()
@ -41,7 +41,7 @@ describe("ReaderScreenshot module", function()
it("should get screenshot in landscape", function() it("should get screenshot in landscape", function()
local name = "screenshots/reader_screenshot_landscape.png" local name = "screenshots/reader_screenshot_landscape.png"
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_LANDSCAPE)) readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_CLOCKWISE))
UIManager:quit() UIManager:quit()
UIManager:show(readerui) UIManager:show(readerui)
UIManager:scheduleIn(2, function() UIManager:scheduleIn(2, function()

Loading…
Cancel
Save