diff --git a/frontend/apps/reader/modules/readercoptlistener.lua b/frontend/apps/reader/modules/readercoptlistener.lua index 4226baebd..2c06947cd 100644 --- a/frontend/apps/reader/modules/readercoptlistener.lua +++ b/frontend/apps/reader/modules/readercoptlistener.lua @@ -90,11 +90,26 @@ function ReaderCoptListener:onTimeFormatChanged() self.ui.document._document:setIntProperty("window.status.clock.12hours", G_reader_settings:isTrue("twelve_hour_clock") and 1 or 0) end +function ReaderCoptListener:shouldHeaderBeRepainted() + local n = 1 + local widget = UIManager:getNthTopWidget(n) + while widget do + if widget.name == "ReaderUI" then + return true + elseif widget.covers_fullscreen then + return false + end + n = n + 1 + widget = UIManager:getNthTopWidget(n) + end + return false +end + function ReaderCoptListener:updateHeader() -- Have crengine display accurate time and battery on its next drawing self.ui.document:resetBufferCache() -- be sure next repaint is a redrawing -- Force a refresh if we're not hidden behind another widget - if UIManager:getTopWidget() == "ReaderUI" then + if self:shouldHeaderBeRepainted() then UIManager:setDirty(self.view.dialog, "ui", Geom:new{ x = 0, y = 0, diff --git a/frontend/apps/reader/modules/readerdevicestatus.lua b/frontend/apps/reader/modules/readerdevicestatus.lua index 90eb7ac80..6f1a3f9e2 100644 --- a/frontend/apps/reader/modules/readerdevicestatus.lua +++ b/frontend/apps/reader/modules/readerdevicestatus.lua @@ -70,7 +70,7 @@ function ReaderDeviceStatus:init() UIManager:close(self.memory_confirm_box) end if Device:canRestart() then - if UIManager:getTopWidget() == "ReaderUI" + if UIManager:getNthTopWidget().name == "ReaderUI" and G_reader_settings:isTrue("device_status_memory_auto_restart") then UIManager:show(InfoMessage:new{ text = _("High memory usage!\n\nKOReader is restarting…"), diff --git a/frontend/apps/reader/modules/readerfooter.lua b/frontend/apps/reader/modules/readerfooter.lua index f332398da..6355189c0 100644 --- a/frontend/apps/reader/modules/readerfooter.lua +++ b/frontend/apps/reader/modules/readerfooter.lua @@ -771,6 +771,22 @@ function ReaderFooter:unscheduleFooterAutoRefresh() UIManager:unschedule(self.autoRefreshFooter) end +function ReaderFooter:shouldBeRepainted() + local n = 1 + local widget = UIManager:getNthTopWidget(n) + while widget do + if widget.name == "ReaderUI" then + return true + elseif widget.covers_fullscreen or widget.covers_footer then + -- (e.g. the virtual keyboard sets widget_covers_footer == true) + return false + end + n = n + 1 + widget = UIManager:getNthTopWidget(n) + end + return false +end + function ReaderFooter:rescheduleFooterAutoRefreshIfNeeded() if not self.autoRefreshFooter then -- Create this function the first time we're called @@ -779,13 +795,8 @@ function ReaderFooter:rescheduleFooterAutoRefreshIfNeeded() -- (We want to avoid the footer to be painted over a widget covering it - we would -- be fine refreshing it if the widget is not covering it, but this is hard to -- guess from here.) - if UIManager:getTopWidget() == "ReaderUI" then - self:onUpdateFooter(self.view.footer_visible) - else - logger.dbg("Skipping ReaderFooter repaint, because ReaderUI is not the top-level widget") - -- NOTE: We *do* keep its content up-to-date, though - self:onUpdateFooter() - end + self:onUpdateFooter(self.view.footer_visible and self:shouldBeRepainted()) + self:rescheduleFooterAutoRefreshIfNeeded() -- schedule (or not) next refresh end end @@ -2462,21 +2473,12 @@ end -- Used by event handlers that can trip without direct UI interaction... function ReaderFooter:maybeUpdateFooter() -- ...so we need to avoid stomping over unsuspecting widgets (usually, ScreenSaver). - if UIManager:getTopWidget() == "ReaderUI" then - self:onUpdateFooter(self.view.footer_visible) - else - self:onUpdateFooter() - end + self:onUpdateFooter(self.view.footer_visible and self:shouldBeRepainted()) end +-- is the same as maybeUpdateFooter function ReaderFooter:onFrontlightStateChanged() - -- Custom variant of maybeUpdateFooter that *also* whitelists the FL widget... - local top_wg = UIManager:getTopWidget() - if top_wg == "ReaderUI" or top_wg == "FrontLightWidget" then - self:onUpdateFooter(self.view.footer_visible) - else - self:onUpdateFooter() - end + self:onUpdateFooter(self.view.footer_visible and self:shouldBeRepainted()) end function ReaderFooter:onNetworkConnected() diff --git a/frontend/apps/reader/modules/readerstatus.lua b/frontend/apps/reader/modules/readerstatus.lua index 2c005c036..f19a3cc63 100644 --- a/frontend/apps/reader/modules/readerstatus.lua +++ b/frontend/apps/reader/modules/readerstatus.lua @@ -54,7 +54,7 @@ function ReaderStatus:onEndOfBook() self:onMarkBook(true) end - if (settings == "pop-up" or settings == nil) and UIManager:getTopWidget() ~= "end_document" then + if (settings == "pop-up" or settings == nil) and UIManager:getNthTopWidget().name ~= "end_document" then local buttons = { { { diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 131921215..f56ac26c1 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -721,15 +721,16 @@ function UIManager:ToggleNightMode(night_mode) end end ---- Get top widget (name if possible, ref otherwise). -function UIManager:getTopWidget() - if not self._window_stack[1] then - -- No widgets in the stack, bye! +--- Get n.th topmost widget +function UIManager:getNthTopWidget(n) + n = n and n-1 or 0 + if #self._window_stack - n < 1 then + -- No or not enough widgets in the stack, bye! return nil end - local widget = self._window_stack[#self._window_stack].widget - return widget.name or widget + local widget = self._window_stack[#self._window_stack - n].widget + return widget end --[[-- diff --git a/frontend/ui/widget/inputdialog.lua b/frontend/ui/widget/inputdialog.lua index a91bab307..db98cd147 100644 --- a/frontend/ui/widget/inputdialog.lua +++ b/frontend/ui/widget/inputdialog.lua @@ -430,7 +430,7 @@ function InputDialog:init() h = self.screen_height - keyboard_height, }, ignore_if_over = "height", - frame + frame, } if Device:isTouchDevice() then -- is used to hide the keyboard with a tap outside of inputbox self.ges_events.Tap = { diff --git a/frontend/ui/widget/sortwidget.lua b/frontend/ui/widget/sortwidget.lua index 7e571cb42..2a215a845 100644 --- a/frontend/ui/widget/sortwidget.lua +++ b/frontend/ui/widget/sortwidget.lua @@ -75,7 +75,7 @@ function SortItemWidget:init() w = self.width, h = self.height, }, - HorizontalGroup:new { + HorizontalGroup:new{ align = "center", CenterContainer:new{ dimen = Geom:new{ w = checked_widget:getSize().w }, @@ -146,6 +146,10 @@ function SortWidget:init() w = self.width or Screen:getWidth(), h = self.height or Screen:getHeight(), } + if self.dimen.h == Screen:getHeight() then + self.covers_footer = true + end + if Device:hasKeys() then self.key_events.Close = { { Device.input.group.Back } } self.key_events.NextPage = { { Device.input.group.PgFwd } } diff --git a/frontend/ui/widget/virtualkeyboard.lua b/frontend/ui/widget/virtualkeyboard.lua index 3cea9e186..9d9e299d8 100644 --- a/frontend/ui/widget/virtualkeyboard.lua +++ b/frontend/ui/widget/virtualkeyboard.lua @@ -755,6 +755,7 @@ end local VirtualKeyboard = FocusManager:extend{ name = "VirtualKeyboard", + covers_footer = true, modal = true, disable_double_tap = true, inputbox = nil, diff --git a/plugins/autodim.koplugin/main.lua b/plugins/autodim.koplugin/main.lua index b42e33b0c..eaec00a20 100644 --- a/plugins/autodim.koplugin/main.lua +++ b/plugins/autodim.koplugin/main.lua @@ -5,7 +5,6 @@ Plugin for automatic dimming of the frontlight after an idle period. --]]-- local Device = require("device") -local Event = require("ui/event") local FFIUtil = require("ffi/util") local SpinWidget = require("ui/widget/spinwidget") local UIManager = require("ui/uimanager") @@ -41,8 +40,6 @@ function AutoDim:init() self.isCurrentlyDimming = false -- true during or after the dimming ramp self.last_ramp_scheduling_time = nil -- holds start time of the next scheduled ramp task self.trap_widget = nil - - self.top_widget_before_dim = nil end function AutoDim:addToMainMenu(menu_items) @@ -182,7 +179,6 @@ end function AutoDim:restoreFrontlight() if self.autodim_save_fl then Powerd:setIntensity(self.autodim_save_fl) - self:updateFooter(true) self.autodim_save_fl = nil end end @@ -272,19 +268,6 @@ function AutoDim:onFrontlightTurnedOff() self:_schedule_autodim_task() -- reschedule end -function AutoDim:updateFooter(clear) - -- update footer only if it is not covered by another widget - if self.top_widget_before_dim == "ReaderUI" or - (self.top_widget_before_dim ~= "ConfigDialog" and self.top_widget_before_dim ~= "ScreenSaver" - and self.top_widget_before_dim ~= "VirtualKeyboard") then - - UIManager:broadcastEvent(Event:new("UpdateFooter", self.view and self.view.footer_visible or false)) - end - if clear then - self.top_widget_before_dim = nil - end -end - function AutoDim:autodim_task() if self.isCurrentlyDimming then return end if Powerd:isFrontlightOff() then @@ -313,9 +296,6 @@ function AutoDim:autodim_task() end } - -- This is the active widget before showing self.trap_widget - self.top_widget_before_dim = UIManager:getTopWidget() - UIManager:show(self.trap_widget) -- suppress taps during dimming -- calculate time until the next decrease step @@ -344,7 +324,7 @@ function AutoDim:ramp_task() self.ramp_event_countdown = self.ramp_event_countdown - 1 if self.ramp_event_countdown <= 0 then -- Update footer on every self.ramp_event_countdown call - self:updateFooter() + UIManager:broadcastEvent("UpdateFooter") self.ramp_event_countdown = self.ramp_event_countdown_startvalue self.last_ramp_scheduling_time = nil end diff --git a/plugins/autoturn.koplugin/main.lua b/plugins/autoturn.koplugin/main.lua index 8c8570bf8..204632d69 100644 --- a/plugins/autoturn.koplugin/main.lua +++ b/plugins/autoturn.koplugin/main.lua @@ -32,7 +32,7 @@ function AutoTurn:_schedule() local delay = self.last_action_time + time.s(self.autoturn_sec) - UIManager:getTime() if delay <= 0 then - if UIManager:getTopWidget() == "ReaderUI" then + if UIManager:getNthTopWidget().name == "ReaderUI" then logger.dbg("AutoTurn: go to next page") self.ui:handleEvent(Event:new("GotoViewRel", self.autoturn_distance)) self.last_action_time = UIManager:getTime() diff --git a/plugins/vocabbuilder.koplugin/main.lua b/plugins/vocabbuilder.koplugin/main.lua index 6914dee0e..26c0fc29a 100644 --- a/plugins/vocabbuilder.koplugin/main.lua +++ b/plugins/vocabbuilder.koplugin/main.lua @@ -64,8 +64,8 @@ local function resetButtonOnLookupWindow() return elseif obj.is_wiki then -- make wiki window have the same button_tweak as its presenting dictionary window - local widget = UIManager:getSecondTopmostWidget() - if widget.tweak_buttons_func then + local widget = UIManager:getNthTopWidget(2) + if widget and widget.tweak_buttons_func then widget:tweak_buttons_func(buttons) end return @@ -1179,6 +1179,10 @@ function VocabularyBuilderWidget:init() w = self.width or Screen:getWidth(), h = self.height or Screen:getHeight(), } + if self.dimen.h == Screen:getHeight() then + self.covers_footer = true + end + if Device:hasKeys() then self.key_events.Close = { { Device.input.group.Back } } self.key_events.NextPage = { { Device.input.group.PgFwd } } diff --git a/spec/unit/readerpaging_spec.lua b/spec/unit/readerpaging_spec.lua index f2a0cfa53..0d61e9f71 100644 --- a/spec/unit/readerpaging_spec.lua +++ b/spec/unit/readerpaging_spec.lua @@ -6,6 +6,8 @@ describe("Readerpaging module", function() setup(function() require("commonrequire") UIManager = require("ui/uimanager") + stub(UIManager, "getNthTopWidget") + UIManager.getNthTopWidget.returns({}) Event = require("ui/event") DocumentRegistry = require("document/documentregistry") ReaderUI = require("apps/reader/readerui") diff --git a/spec/unit/readerrolling_spec.lua b/spec/unit/readerrolling_spec.lua index 8cfe62aa8..a3438eb51 100644 --- a/spec/unit/readerrolling_spec.lua +++ b/spec/unit/readerrolling_spec.lua @@ -1,9 +1,12 @@ describe("Readerrolling module", function() - local DocumentRegistry, ReaderUI, Event, Screen + local DocumentRegistry, UIManager, ReaderUI, Event, Screen local readerui, rolling setup(function() require("commonrequire") + UIManager = require("ui/uimanager") + stub(UIManager, "getNthTopWidget") + UIManager.getNthTopWidget.returns({}) DocumentRegistry = require("document/documentregistry") ReaderUI = require("apps/reader/readerui") Event = require("ui/event")