Allow locking the gyro to the current screen mode (#6347)

* Allow locking the gyro to the current screen mode (i.e., orientation).
* Tweak the "sticky rota" option to work both ways
* More rotation constant usage instead of magic numbers
reviewable/pr6361/r2
NiLuJe 4 years ago committed by GitHub
parent f9293a67b0
commit 509ee7bb86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -73,9 +73,10 @@ end
-- init should be set to True when starting the FM for the first time
-- (not coming from the reader). This allows the default to be properly set.
function FileManager:setRotationMode(init)
local locked = G_reader_settings:readSetting("lock_rotation")
local locked = G_reader_settings:isTrue("lock_rotation")
local rotation_mode = G_reader_settings:readSetting("fm_rotation_mode") or Screen.ORIENTATION_PORTRAIT
if locked or init then
-- Only enforce the default rotation on first FM open, or when switching to the FM when sticky rota is disabled.
if init or not locked then
self:onSetRotationMode(rotation_mode)
end
end

@ -724,13 +724,19 @@ end
function ReaderView:onReadSettings(config)
self.render_mode = config:readSetting("render_mode") or 0
local locked = G_reader_settings:readSetting("lock_rotation")
local rotation_mode = config:readSetting("rotation_mode")
if not rotation_mode and locked then
if self.ui.document.info.has_pages then
rotation_mode = G_reader_settings:readSetting("kopt_rotation_mode") or 0
else
rotation_mode = G_reader_settings:readSetting("copt_rotation_mode") or 0
local rotation_mode = nil
local locked = G_reader_settings:isTrue("lock_rotation")
-- Keep current rotation by doing nothing when sticky rota is enabled.
if not locked then
-- Honor docsettings's rotation
rotation_mode = config:readSetting("rotation_mode") -- Doc's
if not rotation_mode then
-- No doc specific rotation, pickup global defaults for the doc type
if self.ui.document.info.has_pages then
rotation_mode = G_reader_settings:readSetting("kopt_rotation_mode") or Screen.ORIENTATION_PORTRAIT
else
rotation_mode = G_reader_settings:readSetting("copt_rotation_mode") or Screen.ORIENTATION_PORTRAIT
end
end
end
if rotation_mode then

@ -51,7 +51,9 @@ local Device = {
hasBGRFrameBuffer = no,
canImportFiles = no,
canShareText = no,
hasGSensor = no,
canToggleGSensor = no,
isGSensorLocked = no,
canToggleMassStorage = no,
canUseWAL = yes, -- requires mmap'ed I/O on the target FS
canRestart = yes,
@ -176,6 +178,13 @@ function Device:init()
self:invertButtons()
end
end
-- Honor the gyro lock
if self:hasGSensor() then
if G_reader_settings:isTrue("input_lock_gsensor") then
self:lockGSensor(true)
end
end
end
function Device:setScreenDPI(dpi_override)
@ -246,7 +255,7 @@ function Device:onPowerEvent(ev)
-- Leave Portrait & Inverted Portrait alone, that works just fine.
if bit.band(self.orig_rotation_mode, 1) == 1 then
-- i.e., only switch to Portrait if we're currently in *any* Landscape orientation (odd number)
self.screen:setRotationMode(0)
self.screen:setRotationMode(self.screen.ORIENTATION_PORTRAIT)
else
self.orig_rotation_mode = nil
end
@ -332,6 +341,28 @@ function Device:setIgnoreInput(enable) return true end
-- Device specific method for toggling the GSensor
function Device:toggleGSensor(toggle) 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)
if not self:hasGSensor() then
return
end
if toggle == true then
-- Lock GSensor to current roientation
self.isGSensorLocked = yes
elseif toggle == false then
-- Unlock GSensor
self.isGSensorLocked = no
else
-- Toggle it
if self:isGSensorLocked() then
self.isGSensorLocked = no
else
self.isGSensorLocked = yes
end
end
end
-- Device specific method for set custom light levels
function Device:setScreenBrightness(level) end

@ -601,7 +601,7 @@ function GestureDetector:handlePan(tev)
local pan_ev_multiswipe = pan_ev
-- store a copy of pan_ev without rotation adjustment
-- for multiswipe calculations when rotated
if self.screen.cur_rotation_mode > 0 then
if self.screen.cur_rotation_mode > self.screen.ORIENTATION_PORTRAIT then
pan_ev_multiswipe = util.tableDeepCopy(pan_ev)
end
if msd_direction ~= msd_direction_prev then
@ -743,7 +743,7 @@ function GestureDetector:holdState(tev, hold)
end
end
local ges_coordinate_translation_90 = {
local ges_coordinate_translation_270 = {
north = "west",
south = "east",
east = "north",
@ -763,7 +763,7 @@ local ges_coordinate_translation_180 = {
southeast = "northwest",
southwest = "northeast",
}
local ges_coordinate_translation_270 = {
local ges_coordinate_translation_90 = {
north = "east",
south = "west",
east = "south",
@ -787,8 +787,8 @@ end
@return adjusted gesture.
--]]
function GestureDetector:adjustGesCoordinate(ges)
if self.screen.cur_rotation_mode == 1 then
-- in landscape mode rotated 270
if self.screen.cur_rotation_mode == self.screen.ORIENTATION_LANDSCAPE 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)
end
@ -797,9 +797,9 @@ function GestureDetector:adjustGesCoordinate(ges)
or ges.ges == "two_finger_swipe"
or ges.ges == "two_finger_pan"
then
ges.direction = translateGesDirCoordinate(ges.direction, ges_coordinate_translation_270)
ges.direction = translateGesDirCoordinate(ges.direction, ges_coordinate_translation_90)
if ges.ges == "multiswipe" then
ges.multiswipe_directions = translateMultiswipeGesDirCoordinate(ges.multiswipe_directions, ges_coordinate_translation_270)
ges.multiswipe_directions = translateMultiswipeGesDirCoordinate(ges.multiswipe_directions, ges_coordinate_translation_90)
end
if ges.relative then
ges.relative.x, ges.relative.y = -ges.relative.y, ges.relative.x
@ -814,8 +814,8 @@ function GestureDetector:adjustGesCoordinate(ges)
ges.direction = "horizontal"
end
end
elseif self.screen.cur_rotation_mode == 3 then
-- in landscape mode rotated 90
elseif self.screen.cur_rotation_mode == self.screen.ORIENTATION_LANDSCAPE_ROTATED 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)
end
@ -824,9 +824,9 @@ function GestureDetector:adjustGesCoordinate(ges)
or ges.ges == "two_finger_swipe"
or ges.ges == "two_finger_pan"
then
ges.direction = translateGesDirCoordinate(ges.direction, ges_coordinate_translation_90)
ges.direction = translateGesDirCoordinate(ges.direction, ges_coordinate_translation_270)
if ges.ges == "multiswipe" then
ges.multiswipe_directions = translateMultiswipeGesDirCoordinate(ges.multiswipe_directions, ges_coordinate_translation_90)
ges.multiswipe_directions = translateMultiswipeGesDirCoordinate(ges.multiswipe_directions, ges_coordinate_translation_270)
end
if ges.relative then
ges.relative.x, ges.relative.y = ges.relative.y, -ges.relative.x
@ -841,7 +841,7 @@ function GestureDetector:adjustGesCoordinate(ges)
ges.direction = "horizontal"
end
end
elseif self.screen.cur_rotation_mode == 2 then
elseif self.screen.cur_rotation_mode == self.screen.ORIENTATION_PORTRAIT_ROTATED 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)

@ -657,30 +657,41 @@ function Input:handleOasisOrientationEv(ev)
end
local old_rotation_mode = self.device.screen:getRotationMode()
local old_screen_mode = self.device.screen:getScreenMode()
if rotation_mode ~= old_rotation_mode and screen_mode == old_screen_mode then
self.device.screen:setRotationMode(rotation_mode)
local UIManager = require("ui/uimanager")
UIManager:onRotation()
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, c.f., drivers/hwmon/mma8x5x.c
function Input:handleMiscEvNTX(ev)
local rotation_mode
local rotation_mode, screen_mode
if ev.code == 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
@ -691,22 +702,30 @@ function Input:handleMiscEvNTX(ev)
end
local old_rotation_mode = self.device.screen:getRotationMode()
-- NOTE: See the Oasis version just above us for a variant that's locked to the current ScreenMode.
-- Might be nice to expose the two behaviors to the user, somehow?
if rotation_mode and rotation_mode ~= old_rotation_mode then
return Event:new("SetRotationMode", rotation_mode)
if self.device:isGSensorLocked() then
local old_screen_mode = self.device.screen:getScreenMode()
if rotation_mode and 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 and rotation_mode ~= old_rotation_mode then
return Event:new("SetRotationMode", rotation_mode)
end
end
end
--- Allow toggling the accelerometer at runtime.
function Input:toggleMiscEvNTX(toggle)
if toggle and toggle == true then
if toggle == true then
-- Honor Gyro events
if not self.isNTXAccelHooked then
self.handleMiscEv = self.handleMiscEvNTX
self.isNTXAccelHooked = true
end
elseif toggle and toggle == false then
elseif toggle == false then
-- Ignore Gyro events
if self.isNTXAccelHooked then
self.handleMiscEv = function() end

@ -179,7 +179,7 @@ function Kindle:intoScreenSaver()
-- Leave Portrait & Inverted Portrait alone, that works just fine.
if bit.band(self.orig_rotation_mode, 1) == 1 then
-- i.e., only switch to Portrait if we're currently in *any* Landscape orientation (odd number)
self.screen:setRotationMode(0)
self.screen:setRotationMode(self.screen.ORIENTATION_PORTRAIT)
else
self.orig_rotation_mode = nil
end
@ -371,6 +371,7 @@ local KindleOasis = Kindle:new{
isTouchDevice = yes,
hasFrontlight = yes,
hasKeys = yes,
hasGSensor = yes,
display_dpi = 300,
--[[
-- NOTE: Points to event3 on WiFi devices, event4 on 3G devices...
@ -386,6 +387,7 @@ local KindleOasis2 = Kindle:new{
isTouchDevice = yes,
hasFrontlight = yes,
hasKeys = yes,
hasGSensor = yes,
display_dpi = 300,
touch_dev = "/dev/input/by-path/platform-30a30000.i2c-event",
}

@ -222,6 +222,7 @@ local KoboFrost = Kobo:new{
model = "Kobo_frost",
hasFrontlight = yes,
hasKeys = yes,
hasGSensor = yes,
canToggleGSensor = yes,
touch_snow_protocol = true,
misc_ntx_gsensor_protocol = true,
@ -244,6 +245,7 @@ local KoboStorm = Kobo:new{
model = "Kobo_storm",
hasFrontlight = yes,
hasKeys = yes,
hasGSensor = yes,
canToggleGSensor = yes,
touch_snow_protocol = true,
misc_ntx_gsensor_protocol = true,

@ -148,8 +148,8 @@ function PocketBook:init()
-- fix rotation for Color Lux device
if PocketBook:getDeviceModel() == "PocketBook Color Lux" then
self.screen.blitbuffer_rotation_mode = 0
self.screen.native_rotation_mode = 0
self.screen.blitbuffer_rotation_mode = self.screen.ORIENTATION_PORTRAIT
self.screen.native_rotation_mode = self.screen.ORIENTATION_PORTRAIT
end
os.remove(self.emu_events_dev)

@ -11,9 +11,10 @@ return {
sub_item_table_func = function()
local rotation_table = {}
if Device:canToggleGSensor() then
if Device:hasGSensor() and Device:canToggleGSensor() then
table.insert(rotation_table, {
text = _("Ignore accelerometer rotation events"),
help_text = _("This will inhibit automatic rotations triggered by your device's gyro."),
checked_func = function()
return G_reader_settings:isTrue("input_ignore_gsensor")
end,
@ -24,9 +25,33 @@ return {
})
end
if Device:hasGSensor() then
table.insert(rotation_table, {
text = _("Lock auto rotation to current orientation"),
help_text = _([[
When checked, the gyro will only be honored when switching between the two inverse variants of your current rotation,
i.e., Portrait <-> Inverted Portrait OR Landscape <-> Inverted Landscape.
Switching between (Inverted) Portrait and (Inverted) Landscape will be inhibited.
If you need to do so, you'll have to use the UI toggles.]]),
enabled_func = function()
return G_reader_settings:nilOrFalse("input_ignore_gsensor")
end,
checked_func = function()
return G_reader_settings:isTrue("input_lock_gsensor")
end,
callback = function()
G_reader_settings:flipNilOrFalse("input_lock_gsensor")
Device:lockGSensor(G_reader_settings:isTrue("input_lock_gsensor"))
end,
})
end
table.insert(rotation_table, {
text = _("Keep file browser rotation"),
help_text = _("When checked the rotation of the file browser and the reader will not affect each other"),
text = _("Keep current rotation across views"),
help_text = _([[
When checked, the current rotation will be kept when switching between the file browser and the reader, in both directions, and that no matter what the document's saved rotation or the default reader or file browser rotation may be.
This means that nothing will ever sneak a rotation behind your back, you choose your device's rotation, and it stays that way.
When unchecked, the default rotation of the file browser and the default/saved reader rotation will not affect each other (i.e., they will be honored), and may very well be different.]]),
checked_func = function()
return G_reader_settings:isTrue("lock_rotation")
end,

@ -55,7 +55,7 @@ function UIManager:init()
}
self.poweroff_action = function()
self._entered_poweroff_stage = true;
Screen:setRotationMode(0)
Screen:setRotationMode(Screen.ORIENTATION_PORTRAIT)
require("ui/screensaver"):show("poweroff", _("Powered off"))
if Device:needsScreenRefreshAfterResume() then
Screen:refreshFull()
@ -68,7 +68,7 @@ function UIManager:init()
end
self.reboot_action = function()
self._entered_poweroff_stage = true;
Screen:setRotationMode(0)
Screen:setRotationMode(Screen.ORIENTATION_PORTRAIT)
require("ui/screensaver"):show("reboot", _("Rebooting…"))
if Device:needsScreenRefreshAfterResume() then
Screen:refreshFull()

@ -287,6 +287,7 @@ describe("device module", function()
local kindle_dev = require('device/kindle/device')
assert.is.same("KindleOasis", kindle_dev.model)
kindle_dev:init()
kindle_dev:lockGSensor(true)
kindle_dev.input:waitEvent()
assert.stub(UIManager.onRotation).was_called()

@ -12,7 +12,12 @@ describe("gesturedetector module", function()
direction = direction,
multiswipe_directions = direction,
}
GestureDetector.screen = {}
GestureDetector.screen = {
ORIENTATION_PORTRAIT = 0,
ORIENTATION_LANDSCAPE = 1,
ORIENTATION_PORTRAIT_ROTATED = 2,
ORIENTATION_LANDSCAPE_ROTATED = 3,
}
GestureDetector.screen.cur_rotation_mode = rotation_mode
return GestureDetector:adjustGesCoordinate(ges).direction
@ -25,7 +30,7 @@ describe("gesturedetector module", function()
assert.are.equal("north", adjustTest("two_finger_swipe", "north", 0))
assert.are.equal("north", adjustTest("two_finger_pan", "north", 0))
end)
it("should translate rotation 90", function()
it("should translate rotation 270", function()
assert.are.equal("west", adjustTest("swipe", "north", 3))
assert.are.equal("west", adjustTest("multiswipe", "north", 3))
assert.are.equal("west", adjustTest("pan", "north", 3))
@ -39,7 +44,7 @@ describe("gesturedetector module", function()
assert.are.equal("south", adjustTest("two_finger_swipe", "north", 2))
assert.are.equal("south", adjustTest("two_finger_pan", "north", 2))
end)
it("should translate rotation 270", function()
it("should translate rotation 90", function()
assert.are.equal("east", adjustTest("swipe", "north", 1))
assert.are.equal("east", adjustTest("multiswipe", "north", 1))
assert.are.equal("east", adjustTest("pan", "north", 1))

Loading…
Cancel
Save