mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
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.
This commit is contained in:
2
base
2
base
Submodule base updated: 36b88873bf...0d8f7076c9
@@ -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: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
|
||||
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:adjustTouchTranslate(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
|
||||
end
|
||||
end
|
||||
|
||||
function Input:adjustKindleOasisOrientation(ev)
|
||||
if ev.type == C.EV_ABS and ev.code == C.ABS_PRESSURE then
|
||||
ev.code = ABS_OASIS_ORIENTATION
|
||||
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)
|
||||
--- 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 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
|
||||
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
|
||||
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
|
||||
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
|
||||
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)
|
||||
end
|
||||
-- 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 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)
|
||||
)
|
||||
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
|
||||
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user