diff --git a/frontend/device/generic/device.lua b/frontend/device/generic/device.lua index 6386adee0..d325a48cb 100644 --- a/frontend/device/generic/device.lua +++ b/frontend/device/generic/device.lua @@ -268,10 +268,6 @@ function Device:onPowerEvent(ev) end end self:resume() - -- Restore to previous rotation mode, if need be. - if self.orig_rotation_mode then - self.screen:setRotationMode(self.orig_rotation_mode) - end Screensaver:close() if self:needsScreenRefreshAfterResume() then UIManager:scheduleIn(1, function() self.screen:refreshFull() end) @@ -293,40 +289,7 @@ function Device:onPowerEvent(ev) logger.dbg("Suspending...") -- Add the current state of the SleepCover flag... logger.dbg("Sleep cover is", self.is_cover_closed and "closed" or "open") - -- Let Screensaver set its widget up, so we get accurate info down the line in case fallbacks kick in... Screensaver:setup() - -- Mostly always suspend in Portrait/Inverted Portrait mode... - -- ... except when we just show an InfoMessage or when the screensaver - -- is disabled, as it plays badly with Landscape mode (c.f., #4098 and #5290). - -- We also exclude full-screen widgets that work fine in Landscape mode, - -- like ReadingProgress and BookStatus (c.f., #5724) - if Screensaver:modeExpectsPortrait() then - self.orig_rotation_mode = self.screen:getRotationMode() - -- 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(self.screen.ORIENTATION_PORTRAIT) - else - self.orig_rotation_mode = nil - end - - -- On eInk, if we're using a screensaver mode that shows an image, - -- flash the screen to white first, to eliminate ghosting. - if self:hasEinkScreen() and Screensaver:modeIsImage() then - if Screensaver:withBackground() then - self.screen:clear() - end - self.screen:refreshFull() - - -- On Kobo, on sunxi SoCs with a recent kernel, wait a tiny bit more to avoid weird refresh glitches... - if self:isKobo() and self:isSunxi() then - ffiUtil.usleep(150 * 1000) - end - end - else - -- nil it, in case user switched ScreenSaver modes during our lifetime. - self.orig_rotation_mode = nil - end Screensaver:show() -- NOTE: show() will return well before the refresh ioctl is even *sent*: -- the only thing it's done is *enqueued* the refresh in UIManager's stack. diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 2ebdce56e..761690467 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -228,36 +228,7 @@ function Kindle:intoScreenSaver() if self:supportsScreensaver() then -- NOTE: Meaning this is not a SO device ;) local Screensaver = require("ui/screensaver") - -- NOTE: Pilefered from Device:onPowerEvent @ frontend/device/generic/device.lua - -- Let Screensaver set its widget up, so we get accurate info down the line in case fallbacks kick in... Screensaver:setup() - -- Mostly always suspend in Portrait/Inverted Portrait mode... - -- ... except when we just show an InfoMessage or when the screensaver - -- is disabled, as it plays badly with Landscape mode (c.f., #4098 and #5290). - -- We also exclude full-screen widgets that work fine in Landscape mode, - -- like ReadingProgress and BookStatus (c.f., #5724) - if Screensaver:modeExpectsPortrait() then - self.orig_rotation_mode = self.screen:getRotationMode() - -- 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(self.screen.ORIENTATION_PORTRAIT) - else - self.orig_rotation_mode = nil - end - - -- On eInk, if we're using a screensaver mode that shows an image, - -- flash the screen to white first, to eliminate ghosting. - if self:hasEinkScreen() and Screensaver:modeIsImage() then - if Screensaver:withBackground() then - self.screen:clear() - end - self.screen:refreshFull() - end - else - -- nil it, in case user switched ScreenSaver modes during our lifetime. - self.orig_rotation_mode = nil - end Screensaver:show() else -- Let the native system handle screensavers on SO devices... @@ -276,10 +247,6 @@ function Kindle:outofScreenSaver() if self.screen_saver_mode == true then if self:supportsScreensaver() then local Screensaver = require("ui/screensaver") - -- Restore to previous rotation mode, if need be. - if self.orig_rotation_mode then - self.screen:setRotationMode(self.orig_rotation_mode) - end Screensaver:close() -- And redraw everything in case the framework managed to screw us over... local UIManager = require("ui/uimanager") diff --git a/frontend/ui/screensaver.lua b/frontend/ui/screensaver.lua index 614b466d8..396df7960 100644 --- a/frontend/ui/screensaver.lua +++ b/frontend/ui/screensaver.lua @@ -21,8 +21,9 @@ local UIManager = require("ui/uimanager") local lfs = require("libs/libkoreader-lfs") local logger = require("logger") local _ = require("gettext") +local ffiUtil = require("ffi/util") +local T = ffiUtil.template local Screen = Device.screen -local T = require("ffi/util").template -- Default settings if G_reader_settings:hasNot("screensaver_show_message") then @@ -564,6 +565,39 @@ function Screensaver:show() return end + -- We mostly always suspend in Portrait/Inverted Portrait mode... + -- ... except when we just show an InfoMessage or when the screensaver + -- is disabled, as it plays badly with Landscape mode (c.f., #4098 and #5290). + -- We also exclude full-screen widgets that work fine in Landscape mode, + -- like ReadingProgress and BookStatus (c.f., #5724) + if self:modeExpectsPortrait() then + Device.orig_rotation_mode = Screen:getRotationMode() + -- 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) + else + Device.orig_rotation_mode = nil + end + + -- On eInk, if we're using a screensaver mode that shows an image, + -- flash the screen to white first, to eliminate ghosting. + if Device:hasEinkScreen() and self:modeIsImage() then + if self:withBackground() then + Screen:clear() + end + Screen:refreshFull() + + -- On Kobo, on sunxi SoCs with a recent kernel, wait a tiny bit more to avoid weird refresh glitches... + if Device:isKobo() and Device:isSunxi() then + ffiUtil.usleep(150 * 1000) + end + end + else + -- nil it, in case user switched ScreenSaver modes during our lifetime. + Device.orig_rotation_mode = nil + end + -- Build the main widget for the effective mode, all the sanity checks were handled in setup local widget = nil if self.screensaver_type == "cover" then @@ -712,6 +746,18 @@ function Screensaver:show() end end +function Screensaver:close_widget() + logger.dbg("close screensaver") + if self.screensaver_widget then + UIManager:close(self.screensaver_widget) + self.screensaver_widget = nil + end + + if self.delayed_close then + self.delayed_close = nil + end +end + function Screensaver:close() if self.screensaver_widget == nil then return @@ -720,19 +766,10 @@ function Screensaver:close() local screensaver_delay = G_reader_settings:readSetting("screensaver_delay") local screensaver_delay_number = tonumber(screensaver_delay) if screensaver_delay_number then - UIManager:scheduleIn(screensaver_delay_number, function() - logger.dbg("close screensaver") - if self.screensaver_widget then - UIManager:close(self.screensaver_widget) - self.screensaver_widget = nil - end - end) + UIManager:scheduleIn(screensaver_delay_number, self.close_widget, self) + self.delayed_close = true elseif screensaver_delay == "disable" then - logger.dbg("close screensaver") - if self.screensaver_widget then - UIManager:close(self.screensaver_widget) - self.screensaver_widget = nil - end + self:close_widget() else logger.dbg("tap to exit from screensaver") end diff --git a/frontend/ui/widget/screensaverwidget.lua b/frontend/ui/widget/screensaverwidget.lua index 774e23389..89abc6788 100644 --- a/frontend/ui/widget/screensaverwidget.lua +++ b/frontend/ui/widget/screensaverwidget.lua @@ -72,6 +72,13 @@ function ScreenSaverWidget:onTap(_, ges) end function ScreenSaverWidget:onClose() + -- If we happened to shortcut a delayed close via user input, unschedule it to avoid a spurious refresh. + local Screensaver = require("ui/screensaver") + if Screensaver.delayed_close then + UIManager:unschedule(Screensaver.close_widget) + Screensaver.delayed_close = nil + end + UIManager:close(self) return true end @@ -82,8 +89,15 @@ function ScreenSaverWidget:onAnyKeyPressed() end function ScreenSaverWidget:onCloseWidget() + -- Restore to previous rotation mode, if need be. + if Device.orig_rotation_mode then + Screen:setRotationMode(Device.orig_rotation_mode) + Device.orig_rotation_mode = nil + end + + -- Make it full-screen (self.main_frame.dimen might be in a different orientation, and it's already full-screen anyway...) UIManager:setDirty(nil, function() - return "full", self.main_frame.dimen + return "full" end) -- Will come after the Resume event, iff screensaver_delay is set.