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.
pull/9938/head
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()
local locked = G_reader_settings:isTrue("lock_rotation")
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)
end
end

@ -859,9 +859,9 @@ function ReaderView:onReadSettings(config)
else
-- No doc specific rotation, pickup global defaults for the doc type
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
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

@ -384,7 +384,8 @@ function Device:_toggleStatusBarVisibility()
-- reset touchTranslate to normal
self.input:registerEventAdjustHook(
self.input.adjustTouchTranslate,
{x = 0 + self.viewport.x, y = 0 + self.viewport.y})
{x = 0 + self.viewport.x, y = 0 + self.viewport.y}
)
end
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
self.input:registerEventAdjustHook(
self.input.adjustTouchTranslate,
{x = 0 - self.viewport.x, y = 0 - self.viewport.y})
{x = 0 - self.viewport.x, y = 0 - self.viewport.y}
)
end
self.fullscreen = is_fullscreen

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

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

@ -61,7 +61,6 @@ local Device = {
canImportFiles = no,
canShareText = no,
hasGSensor = no,
canToggleGSensor = no,
isGSensorLocked = no,
canToggleMassStorage = no,
canToggleChargingLED = no,
@ -206,7 +205,8 @@ function Device:init()
self.screen:setViewport(self.viewport)
self.input:registerEventAdjustHook(
self.input.adjustTouchTranslate,
{x = 0 - self.viewport.x, y = 0 - self.viewport.y})
{x = 0 - self.viewport.x, y = 0 - self.viewport.y}
)
end
-- Handle button mappings shenanigans
@ -216,8 +216,13 @@ function Device:init()
end
end
-- Honor the gyro lock
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
self:lockGSensor(true)
end
@ -418,8 +423,17 @@ function Device:performHapticFeedback(type) end
-- Device specific method for toggling input events
function Device:setIgnoreInput(enable) return true end
-- Device specific method for toggling the GSensor
function Device:toggleGSensor(toggle) end
-- Device agnostic method for toggling the GSensor
-- (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)
function Device:lockGSensor(toggle)

@ -984,7 +984,7 @@ function Contact:handlePan()
if msd_distance > gesture_detector.MULTISWIPE_THRESHOLD then
local pan_ev_multiswipe = pan_ev
-- 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)
end
if msd_direction ~= msd_direction_prev then
@ -1335,7 +1335,7 @@ end
--]]
function GestureDetector:adjustGesCoordinate(ges)
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
if ges.pos then
ges.pos.x, ges.pos.y = (self.screen:getWidth() - ges.pos.y), (ges.pos.x)
@ -1367,7 +1367,7 @@ function GestureDetector:adjustGesCoordinate(ges)
end
logger.dbg("GestureDetector: Landscape translation for ges:", ges.ges, ges.direction)
end
elseif mode == self.screen.ORIENTATION_LANDSCAPE_ROTATED then
elseif mode == self.screen.DEVICE_ROTATED_COUNTER_CLOCKWISE then
-- in landscape mode rotated 270
if ges.pos then
ges.pos.x, ges.pos.y = (ges.pos.y), (self.screen:getHeight() - ges.pos.x)
@ -1399,7 +1399,7 @@ function GestureDetector:adjustGesCoordinate(ges)
end
logger.dbg("GestureDetector: Inverted landscape translation for ges:", ges.ges, ges.direction)
end
elseif mode == self.screen.ORIENTATION_PORTRAIT_ROTATED then
elseif mode == self.screen.DEVICE_ROTATED_UPSIDE_DOWN then
-- in portrait mode rotated 180
if ges.pos then
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/linux_input_h")
-- luacheck: push
-- luacheck: ignore
-- key press event values (KEY.value)
local EVENT_VALUE_KEY_PRESS = 1
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
-- EV_KEY values
local KEY_PRESS = 1
local KEY_REPEAT = 2
local KEY_RELEASE = 0
-- Based on ABS_MT_TOOL_TYPE values on Elan panels
local TOOL_TYPE_FINGER = 0
@ -74,7 +42,6 @@ local linux_evdev_type_map = {
[C.EV_FF] = "EV_FF",
[C.EV_PWR] = "EV_PWR",
[C.EV_FF_STATUS] = "EV_FF_STATUS",
[C.EV_MAX] = "EV_MAX",
[C.EV_SDL] = "EV_SDL",
}
@ -122,23 +89,23 @@ local linux_evdev_abs_code_map = {
local linux_evdev_msc_code_map = {
[C.MSC_RAW] = "MSC_RAW",
[C.MSC_GYRO] = "MSC_GYRO",
}
local linux_evdev_rep_code_map = {
[C.REP_DELAY] = "REP_DELAY",
[C.REP_PERIOD] = "REP_PERIOD",
}
-- luacheck: pop
local _internal_clipboard_text = nil -- holds the last copied text
local Input = {
-- must point to the device implementation when instantiating
device = nil,
-- this depends on keyboard layout and should be overridden:
event_map = {},
-- this depends on keyboard layout and should be overridden
event_map = nil, -- hash
-- 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)
pressure_event = nil,
@ -193,8 +160,8 @@ local Input = {
UsbDevicePlugOut = {},
},
-- This might be overloaded or even disabled (post-init) at instance-level, so we don't want any inheritance
rotation_map = nil, -- nil or a hash
-- This might be modified at runtime, so we don't want any inheritance
rotation_map = nil, -- hash
timer_callbacks = nil, -- instance-specific table, because the object may get destroyed & recreated at runtime
disable_double_tap = true,
@ -260,13 +227,20 @@ function Input:init()
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
if not self.rotation_map then
self.rotation_map = {
[framebuffer.ORIENTATION_PORTRAIT] = {},
[framebuffer.ORIENTATION_LANDSCAPE] = { 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.ORIENTATION_LANDSCAPE_ROTATED] = { Up = "Left", Right = "Up", Down = "Right", Left = "Down" }
[framebuffer.DEVICE_ROTATED_UPRIGHT] = {},
[framebuffer.DEVICE_ROTATED_CLOCKWISE] = { Up = "Right", Right = "Down", Down = "Left", Left = "Up", LPgBack = "LPgFwd", LPgFwd = "LPgBack", RPgBack = "RPgFwd", RPgFwd = "RPgBack" },
[framebuffer.DEVICE_ROTATED_UPSIDE_DOWN] = { Up = "Down", Right = "Left", Down = "Up", Left = "Right", LPgFwd = "LPgBack", LPgBack = "LPgFwd", RPgFwd = "RPgBack", RPgBack = "RPgFwd" },
[framebuffer.DEVICE_ROTATED_COUNTER_CLOCKWISE] = { Up = "Left", Right = "Up", Down = "Right", Left = "Down" },
}
end
@ -301,6 +275,18 @@ function Input:init()
self._inhibitInputUntil_func = function() self:inhibitInputUntil() 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.
@ -313,22 +299,35 @@ function Input.open(device, is_emu_events)
end
--[[--
Different device models can implement their own hooks
and register them.
Different device models can implement their own hooks and register them.
--]]
function Input:registerEventAdjustHook(hook, hook_params)
local old = self.eventAdjustHook
self.eventAdjustHook = function(this, ev)
old(this, ev)
hook(this, ev, hook_params)
if self.eventAdjustHook == Input.eventAdjustHook then
-- First custom hook, skip the default NOP
self.eventAdjustHook = function(this, ev)
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
function Input:registerGestureAdjustHook(hook, hook_params)
local old = self.gestureAdjustHook
self.gestureAdjustHook = function(this, ges)
old(this, ges)
hook(this, ges, hook_params)
if self.gestureAdjustHook == Input.gestureAdjustHook then
self.gestureAdjustHook = function(this, ges)
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
@ -341,59 +340,77 @@ function Input:gestureAdjustHook(ges)
end
--- Catalog of predefined hooks.
function Input:adjustTouchSwitchXY(ev)
if ev.type == C.EV_ABS then
if ev.code == C.ABS_X then
ev.code = C.ABS_Y
elseif ev.code == C.ABS_Y then
ev.code = C.ABS_X
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
end
-- These are *not* usable directly as hooks, they're just building blocks (c.f., Kobo)
function Input:adjustABS_SwitchXY(ev)
if ev.code == C.ABS_X then
ev.code = C.ABS_Y
elseif ev.code == C.ABS_Y then
ev.code = C.ABS_X
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
end
end
function Input:adjustTouchScale(ev, by)
if ev.type == C.EV_ABS then
if ev.code == C.ABS_X or ev.code == C.ABS_MT_POSITION_X then
ev.value = by.x * ev.value
end
if ev.code == C.ABS_Y or ev.code == C.ABS_MT_POSITION_Y then
ev.value = by.y * ev.value
end
function Input:adjustABS_Scale(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
function Input:adjustTouchMirrorX(ev, max_x)
if ev.type == C.EV_ABS
and (ev.code == C.ABS_X or ev.code == C.ABS_MT_POSITION_X) then
function Input:adjustABS_MirrorX(ev, max_x)
if ev.code == C.ABS_X or ev.code == C.ABS_MT_POSITION_X then
ev.value = max_x - ev.value
end
end
function Input:adjustTouchMirrorY(ev, max_y)
if ev.type == C.EV_ABS
and (ev.code == C.ABS_Y or ev.code == C.ABS_MT_POSITION_Y) then
function Input:adjustABS_MirrorY(ev, max_y)
if ev.code == C.ABS_Y or ev.code == C.ABS_MT_POSITION_Y then
ev.value = max_y - ev.value
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.code == C.ABS_X or ev.code == C.ABS_MT_POSITION_X then
ev.value = by.x + ev.value
end
if ev.code == C.ABS_Y or ev.code == C.ABS_MT_POSITION_Y then
ev.value = by.y + ev.value
end
self:adjustABS_Scale(ev, by)
end
end
function Input:adjustTouchSwitchAxesAndMirrorX(ev, max_x)
if ev.type == C.EV_ABS then
self:adjustABS_SwitchAxesAndMirrorX(ev, max_x)
end
end
function Input:adjustKindleOasisOrientation(ev)
if ev.type == C.EV_ABS and ev.code == C.ABS_PRESSURE then
ev.code = ABS_OASIS_ORIENTATION
function Input:adjustTouchTranslate(ev, by)
if ev.type == C.EV_ABS then
self:adjustABS_Translate(ev, by)
end
end
@ -548,11 +565,9 @@ function Input:handleKeyBoardEv(ev)
end
-- take device rotation into account
if self.rotation_map then
local rota = self.device.screen:getRotationMode()
if self.rotation_map[rota][keycode] then
keycode = self.rotation_map[rota][keycode]
end
local rota = self.device.screen:getRotationMode()
if self.rotation_map[rota][keycode] then
keycode = self.rotation_map[rota][keycode]
end
if self.fake_event_set[keycode] then
@ -573,9 +588,9 @@ function Input:handleKeyBoardEv(ev)
if keycode == "Power" then
-- Kobo generates Power keycode only, we need to decide whether it's
-- power-on or power-off ourselves.
if ev.value == EVENT_VALUE_KEY_PRESS then
if ev.value == KEY_PRESS then
return "PowerPress"
elseif ev.value == EVENT_VALUE_KEY_RELEASE then
elseif ev.value == KEY_RELEASE then
return "PowerRelease"
end
end
@ -596,9 +611,9 @@ function Input:handleKeyBoardEv(ev)
-- handle modifier keys
if self.modifiers[keycode] ~= nil then
if ev.value == EVENT_VALUE_KEY_PRESS then
if ev.value == KEY_PRESS then
self.modifiers[keycode] = true
elseif ev.value == EVENT_VALUE_KEY_RELEASE then
elseif ev.value == KEY_RELEASE then
self.modifiers[keycode] = false
end
return
@ -606,9 +621,9 @@ function Input:handleKeyBoardEv(ev)
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)
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...
-- And we *definitely* don't want to flood the Event queue with useless SleepCover repeats!
if keycode == "LPgBack"
@ -629,7 +644,7 @@ function Input:handleKeyBoardEv(ev)
self.repeat_count = 0
end
end
elseif ev.value == EVENT_VALUE_KEY_RELEASE then
elseif ev.value == KEY_RELEASE then
self.repeat_count = 0
return Event:new("KeyRelease", key)
end
@ -662,9 +677,9 @@ function Input:handlePowerManagementOnlyEv(ev)
if keycode == "Power" then
-- Kobo generates Power keycode only, we need to decide whether it's
-- power-on or power-off ourselves.
if ev.value == EVENT_VALUE_KEY_PRESS then
if ev.value == KEY_PRESS then
return "PowerPress"
elseif ev.value == EVENT_VALUE_KEY_RELEASE then
elseif ev.value == KEY_RELEASE then
return "PowerRelease"
end
end
@ -684,7 +699,11 @@ function Input:handleGenericEv(ev)
end
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
function Input:handleSdlEv(ev)
@ -886,92 +905,29 @@ function Input:handleTouchEvLegacy(ev)
end
end
function Input:handleOasisOrientationEv(ev)
local rotation_mode, screen_mode
if self.device:isZelda() then
if ev.value == UPWARD_PORTRAIT_UP_INTERRUPT_HAPPENED then
-- 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)
--- Accelerometer, in a platform-agnostic, custom format (EV_MSC:MSC_GYRO).
--- (Translation should be done via registerEventAdjustHook in Device implementations).
--- This needs to be called *via handleGyroEv* in a handleMiscEv implementation (c.f., Kobo, Kindle or PocketBook).
function Input:handleMiscGyroEv(ev)
local rotation_mode, screen_mode
if ev.code == C.MSC_RAW then
if ev.value == MSC_RAW_GSENSOR_PORTRAIT_UP then
-- i.e., UR
rotation_mode = framebuffer.ORIENTATION_PORTRAIT
screen_mode = 'portrait'
elseif ev.value == MSC_RAW_GSENSOR_LANDSCAPE_RIGHT then
-- i.e., CW
rotation_mode = framebuffer.ORIENTATION_LANDSCAPE
screen_mode = 'landscape'
elseif ev.value == MSC_RAW_GSENSOR_PORTRAIT_DOWN then
-- i.e., UD
rotation_mode = framebuffer.ORIENTATION_PORTRAIT_ROTATED
screen_mode = 'portrait'
elseif ev.value == MSC_RAW_GSENSOR_LANDSCAPE_LEFT then
-- i.e., CCW
rotation_mode = framebuffer.ORIENTATION_LANDSCAPE_ROTATED
screen_mode = 'landscape'
else
-- Discard FRONT/BACK
return
end
if ev.value == C.DEVICE_ROTATED_UPRIGHT then
-- i.e., UR
rotation_mode = framebuffer.DEVICE_ROTATED_UPRIGHT
screen_mode = "portrait"
elseif ev.value == C.DEVICE_ROTATED_CLOCKWISE then
-- i.e., CW
rotation_mode = framebuffer.DEVICE_ROTATED_CLOCKWISE
screen_mode = "landscape"
elseif ev.value == C.DEVICE_ROTATED_UPSIDE_DOWN then
-- i.e., UD
rotation_mode = framebuffer.DEVICE_ROTATED_UPSIDE_DOWN
screen_mode = "portrait"
elseif ev.value == C.DEVICE_ROTATED_COUNTER_CLOCKWISE then
-- i.e., CCW
rotation_mode = framebuffer.DEVICE_ROTATED_COUNTER_CLOCKWISE
screen_mode = "landscape"
else
-- Discard unhandled event codes, just to future-proof this ;).
-- Discard FRONT/BACK
return
end
@ -992,28 +948,24 @@ function Input:handleMiscEvNTX(ev)
end
--- Allow toggling the accelerometer at runtime.
function Input:toggleMiscEvNTX(toggle)
function Input:toggleGyroEvents(toggle)
if toggle == true then
-- Honor Gyro events
if not self.isNTXAccelHooked then
self.handleMiscEv = self.handleMiscEvNTX
self.isNTXAccelHooked = true
if self.handleGyroEv ~= self.handleMiscGyroEv then
self.handleGyroEv = self.handleMiscGyroEv
end
elseif toggle == false then
-- Ignore Gyro events
if self.isNTXAccelHooked then
self.handleMiscEv = self.voidEv
self.isNTXAccelHooked = false
if self.handleGyroEv == self.handleMiscGyroEv then
self.handleGyroEv = self.voidEv
end
else
-- Toggle it
if self.isNTXAccelHooked then
self.handleMiscEv = self.voidEv
if self.handleGyroEv == self.handleMiscGyroEv then
self.handleGyroEv = self.voidEv
else
self.handleMiscEv = self.handleMiscEvNTX
self.handleGyroEv = self.handleMiscGyroEv
end
self.isNTXAccelHooked = not self.isNTXAccelHooked
end
end
@ -1096,15 +1048,15 @@ function Input:setupSlotData(value)
end
function Input:isEvKeyPress(ev)
return ev.value == EVENT_VALUE_KEY_PRESS
return ev.value == KEY_PRESS
end
function Input:isEvKeyRepeat(ev)
return ev.value == EVENT_VALUE_KEY_REPEAT
return ev.value == KEY_REPEAT
end
function Input:isEvKeyRelease(ev)
return ev.value == EVENT_VALUE_KEY_RELEASE
return ev.value == KEY_RELEASE
end
@ -1338,11 +1290,6 @@ function Input:waitEvent(now, deadline)
if handled_ev then
table.insert(handled, handled_ev)
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
local handled_evs = self:handleTouchEv(event)
-- 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
end
-- 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
self._abs_ev_handler = self.handleTouchEv
self.handleTouchEv = self.voidEv
end
if not self._msc_ev_handler then
if not self.device:isPocketBook() and not self.device:isAndroid() then
-- NOTE: PocketBook is a special snowflake, synthetic Power events are sent as EV_MSC.
-- Thankfully, that's all that EV_MSC is used for on that platform.
-- NOTE: Android, on the other hand, handles a *lot* of critical stuff over EV_MSC,
-- as it's used to communicate between Android and Lua land ;).
self._msc_ev_handler = self.handleMiscEv
self.handleMiscEv = self.voidEv
end
-- NOTE: We leave handleMiscEv alone, as some platforms make extensive use of EV_MSC for critical low-level stuff:
-- e.g., on PocketBook, it is used to handle InkView task management events (i.e., PM);
-- and on Android, for the critical purpose of forwarding Android events to Lua-land.
-- The only thing we might want to skip in there are gyro events anyway, which we'll handle separately.
if not self._gyro_ev_handler then
self._gyro_ev_handler = self.handleGyroEv
self.handleGyroEv = self.voidEv
end
if not self._sdl_ev_handler then
self._sdl_ev_handler = self.handleSdlEv
@ -1429,17 +1370,13 @@ function Input:inhibitInput(toggle)
self.handleKeyBoardEv = self._key_ev_handler
self._key_ev_handler = nil
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
self.handleTouchEv = self._abs_ev_handler
self._abs_ev_handler = nil
end
if self._msc_ev_handler then
self.handleMiscEv = self._msc_ev_handler
self._msc_ev_handler = nil
if self._gyro_ev_handler then
self.handleGyroEv = self._gyro_ev_handler
self._gyro_ev_handler = nil
end
if self._sdl_ev_handler then
self.handleSdlEv = self._sdl_ev_handler

@ -3,6 +3,13 @@ local time = require("ui/time")
local lfs = require("libs/libkoreader-lfs")
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 no() return false end -- luacheck: ignore
@ -823,6 +830,46 @@ function KindlePaperWhite3:init()
self.input.open("fake_events")
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()
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self, debug = logger.dbg}
self.powerd = require("device/kindle/powerd"):new{
@ -850,14 +897,14 @@ function KindleOasis:init()
"com.lab126.winmgr", "accelerometer")
local rotation_mode = 0
if orientation_code then
if orientation_code == "V" then
rotation_mode = self.screen.ORIENTATION_PORTRAIT
if orientation_code == "U" then
rotation_mode = self.screen.DEVICE_ROTATED_UPRIGHT
elseif orientation_code == "R" then
rotation_mode = self.screen.ORIENTATION_LANDSCAPE
rotation_mode = self.screen.DEVICE_ROTATED_CLOCKWISE
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
rotation_mode = self.screen.ORIENTATION_LANDSCAPE_ROTATED
rotation_mode = self.screen.DEVICE_ROTATED_COUNTER_CLOCKWISE
end
end
@ -872,7 +919,12 @@ function KindleOasis:init()
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("/dev/input/by-path/platform-gpiokey.0-event")
@ -890,6 +942,39 @@ function KindleOasis:init()
self.input.open("fake_events")
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()
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self, debug = logger.dbg}
self.powerd = require("device/kindle/powerd"):new{
@ -926,13 +1011,13 @@ function KindleOasis2:init()
local rotation_mode = 0
if orientation_code then
if orientation_code == "U" then
rotation_mode = self.screen.ORIENTATION_PORTRAIT
rotation_mode = self.screen.DEVICE_ROTATED_UPRIGHT
elseif orientation_code == "R" then
rotation_mode = self.screen.ORIENTATION_LANDSCAPE
rotation_mode = self.screen.DEVICE_ROTATED_CLOCKWISE
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
rotation_mode = self.screen.ORIENTATION_LANDSCAPE_ROTATED
rotation_mode = self.screen.DEVICE_ROTATED_COUNTER_CLOCKWISE
end
end
@ -947,7 +1032,12 @@ function KindleOasis2:init()
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("/dev/input/by-path/platform-gpio-keys-event")
@ -997,13 +1087,13 @@ function KindleOasis3:init()
local rotation_mode = 0
if orientation_code then
if orientation_code == "U" then
rotation_mode = self.screen.ORIENTATION_PORTRAIT
rotation_mode = self.screen.DEVICE_ROTATED_UPRIGHT
elseif orientation_code == "R" then
rotation_mode = self.screen.ORIENTATION_LANDSCAPE
rotation_mode = self.screen.DEVICE_ROTATED_CLOCKWISE
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
rotation_mode = self.screen.ORIENTATION_LANDSCAPE_ROTATED
rotation_mode = self.screen.DEVICE_ROTATED_COUNTER_CLOCKWISE
end
end
@ -1018,7 +1108,12 @@ function KindleOasis3:init()
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("/dev/input/by-path/platform-gpio-keys-event")

@ -378,9 +378,7 @@ local KoboFrost = Kobo:extend{
hasFrontlight = yes,
hasKeys = yes,
hasGSensor = yes,
canToggleGSensor = yes,
touch_snow_protocol = true,
misc_ntx_gsensor_protocol = true,
display_dpi = 300,
hasNaturalLight = yes,
frontlight_settings = {
@ -403,9 +401,7 @@ local KoboStorm = Kobo:extend{
hasFrontlight = yes,
hasKeys = yes,
hasGSensor = yes,
canToggleGSensor = yes,
touch_snow_protocol = true,
misc_ntx_gsensor_protocol = true,
display_dpi = 300,
hasNaturalLight = yes,
frontlight_settings = {
@ -446,9 +442,7 @@ local KoboEuropa = Kobo:extend{
led_uses_channel_3 = true,
hasFrontlight = yes,
hasGSensor = yes,
canToggleGSensor = yes,
pressure_event = C.ABS_MT_PRESSURE,
misc_ntx_gsensor_protocol = true,
display_dpi = 227,
boot_rota = C.FB_ROTATE_CCW,
battery_sysfs = "/sys/class/power_supply/battery",
@ -467,9 +461,7 @@ local KoboCadmus = Kobo:extend{
hasFrontlight = yes,
hasKeys = yes,
hasGSensor = yes,
canToggleGSensor = yes,
pressure_event = C.ABS_MT_PRESSURE,
misc_ntx_gsensor_protocol = true,
display_dpi = 300,
hasNaturalLight = yes,
frontlight_settings = {
@ -500,10 +492,8 @@ local KoboIo = Kobo:extend{
hasFrontlight = yes,
hasKeys = yes,
hasGSensor = yes,
canToggleGSensor = yes,
pressure_event = C.ABS_MT_PRESSURE,
touch_mirrored_x = false,
misc_ntx_gsensor_protocol = true,
display_dpi = 300,
hasNaturalLight = yes,
frontlight_settings = {
@ -908,28 +898,73 @@ function Kobo:setTouchEventHandler()
end
-- Accelerometer
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
if self:hasGSensor() then
self.input.handleMiscEv = function(this, ev)
-- As generated by gyroTranslation below
if ev.code == C.MSC_GYRO then
return this:handleGyroEv(ev)
end
end
end
end
function Kobo:initEventAdjustHooks()
-- NOTE: adjustTouchSwitchXY needs to be called before adjustTouchMirrorX
if self.touch_switch_xy then
self.input:registerEventAdjustHook(self.input.adjustTouchSwitchXY)
-- HAL for gyro orientation switches (NTX's EV_MSC:MSC_RAW w/ custom values to EV_MSC:MSC_GYRO w/ our own custom values)
local function gyroTranslation(ev)
-- c.f., include/uapi/linux/input.h,
-- 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
if self.touch_mirrored_x then
self.input:registerEventAdjustHook(
self.input.adjustTouchMirrorX,
--- NOTE: This is safe, we enforce the canonical portrait rotation on startup.
(self.screen:getWidth() - 1)
)
function Kobo:initEventAdjustHooks()
-- Build a single composite hook, to avoid duplicated branches...
local koboInputMangling
-- NOTE: touch_switch_xy is *always* true, but not touch_mirrored_x...
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
@ -1270,14 +1305,6 @@ function Kobo:reboot()
os.execute("sleep 1 && reboot &")
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)
-- We have no way of querying the current state from the HW!
if toggle == nil then

@ -217,13 +217,15 @@ function PocketBook:init()
-- Auto shutdown event from inkview framework,
-- gracefully close everything and let the framework shutdown the device.
return "Exit"
elseif ev.code == C.MSC_GYRO then
return this:handleGyroEv(ev)
end
end,
}
-- If InkView translates buttons for us, disable our own translation map
if self.inkview_translates_buttons then
self.input.rotation_map = nil
self.input:disableRotationMap()
end
-- 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
}
function PocketBookColorLux:_model_init()
self.screen.blitbuffer_rotation_mode = self.screen.ORIENTATION_PORTRAIT
self.screen.native_rotation_mode = self.screen.ORIENTATION_PORTRAIT
self.screen.blitbuffer_rotation_mode = self.screen.DEVICE_ROTATED_UPRIGHT
self.screen.native_rotation_mode = self.screen.DEVICE_ROTATED_UPRIGHT
end
function PocketBookColorLux._fb_init(fb, finfo, vinfo)
-- 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
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.cur_rotation_mode = rotation_mode

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

@ -64,7 +64,7 @@ function SonyPRSTUX:init()
self.input.open("fake_events") -- usb plug-in/out and charging/not-charging
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.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},
-- 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_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()},

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

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

@ -11,7 +11,7 @@ return {
sub_item_table_func = function()
local rotation_table = {}
if Device:hasGSensor() and Device:canToggleGSensor() then
if Device:hasGSensor() then
table.insert(rotation_table, {
text = _("Ignore accelerometer rotation events"),
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, {
text_func = function()
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 .. ""
end
return text
end,
checked_func = function()
return Screen:getRotationMode() == Screen.ORIENTATION_LANDSCAPE_ROTATED
return Screen:getRotationMode() == Screen.DEVICE_ROTATED_COUNTER_CLOCKWISE
end,
radio = true,
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
end,
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
end,
})
table.insert(rotation_table, {
text_func = function()
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 .. ""
end
return text
end,
checked_func = function()
return Screen:getRotationMode() == Screen.ORIENTATION_PORTRAIT
return Screen:getRotationMode() == Screen.DEVICE_ROTATED_UPRIGHT
end,
radio = true,
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
end,
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
end,
})
table.insert(rotation_table, {
text_func = function()
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 .. ""
end
return text
end,
checked_func = function()
return Screen:getRotationMode() == Screen.ORIENTATION_LANDSCAPE
return Screen:getRotationMode() == Screen.DEVICE_ROTATED_CLOCKWISE
end,
radio = true,
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
end,
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
end,
})
table.insert(rotation_table, {
text_func = function()
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 .. ""
end
return text
end,
checked_func = function()
return Screen:getRotationMode() == Screen.ORIENTATION_PORTRAIT_ROTATED
return Screen:getRotationMode() == Screen.DEVICE_ROTATED_UPSIDE_DOWN
end,
radio = true,
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
end,
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
end,
})

@ -628,7 +628,7 @@ function Screensaver:show()
-- Leave Portrait & Inverted Portrait alone, that works just fine.
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)
Screen:setRotationMode(Screen.ORIENTATION_PORTRAIT)
Screen:setRotationMode(Screen.DEVICE_ROTATED_UPRIGHT)
else
Device.orig_rotation_mode = nil
end

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

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

@ -22,7 +22,7 @@ describe("Readerrolling module", function()
describe("test in 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)
it("should goto certain page", function()
@ -119,7 +119,7 @@ describe("Readerrolling module", function()
describe("test in 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)
it("should goto certain page", function()
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()
teardown(function()
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT))
readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPRIGHT))
end)
it("for portrait-landscape-portrait switching", function()
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)
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)
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT))
readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPRIGHT))
assert.are.same(i, rolling.current_page)
end
end)
it("for landscape-portrait-landscape switching", function()
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)
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)
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_LANDSCAPE))
readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_CLOCKWISE))
assert.are.same(i, rolling.current_page)
end
end)

@ -18,14 +18,14 @@ describe("ReaderScreenshot module", function()
end)
teardown(function()
readerui:handleEvent(Event:new("SetRotationMode", Screen.ORIENTATION_PORTRAIT))
readerui:handleEvent(Event:new("SetRotationMode", Screen.DEVICE_ROTATED_UPRIGHT))
readerui:closeDocument()
readerui:onClose()
end)
it("should get screenshot in portrait", function()
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:show(readerui)
UIManager:scheduleIn(1, function()
@ -41,7 +41,7 @@ describe("ReaderScreenshot module", function()
it("should get screenshot in landscape", function()
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:show(readerui)
UIManager:scheduleIn(2, function()

Loading…
Cancel
Save