diff --git a/frontend/apps/reader/modules/readerconfig.lua b/frontend/apps/reader/modules/readerconfig.lua index 19717d8c5..690f49bbc 100644 --- a/frontend/apps/reader/modules/readerconfig.lua +++ b/frontend/apps/reader/modules/readerconfig.lua @@ -81,6 +81,7 @@ end function ReaderConfig:onShowConfigMenu() self.config_dialog = ConfigDialog:new{ + covers_footer = true, -- hint for UIManager:repaintReaderFooter dimen = self.dimen:copy(), document = self.document, ui = self.ui, diff --git a/frontend/apps/reader/modules/readerfooter.lua b/frontend/apps/reader/modules/readerfooter.lua index 551da9f7e..9c5ea25fa 100644 --- a/frontend/apps/reader/modules/readerfooter.lua +++ b/frontend/apps/reader/modules/readerfooter.lua @@ -1795,11 +1795,13 @@ function ReaderFooter:_updateFooterText(force_repaint, force_recompute) -- Unfortunately, it's not a modal (we never show() it), so it's not in the window stack, -- instead, it's baked inside ReaderUI, so it gets slightly trickier... -- NOTE: self.view.footer -> self ;). - UIManager:setDirty(self.view.footer, function() - return "ui", refresh_dim - end) - -- c.f., ReaderView:paintTo() - UIManager:widgetRepaint(self.view.footer, 0, 0) + if UIManager:repaintReaderFooter(self.view.footer) then + -- NOTE: repaintReaderFooter will sometimes choose *not* to repaint, in which case, + -- we don't want to generate a bogus setDirty call ;). + UIManager:setDirty(self.view.footer, function() + return "ui", refresh_dim + end) + end else UIManager:setDirty(self.view.dialog, function() return "ui", refresh_dim @@ -2005,6 +2007,16 @@ function ReaderFooter:onSuspend() end end +-- We want to be able to disable auto_refresh_time when displaying *some* non-fullscreen widgets on top of ReaderUI, +-- otherwise it'll happily keep on ticking and drawing on top of stuff it ought not to... (#6616) +--- @note: If the widget actually makes it to UIManager's window stack (i.e., it's passed to UIManager:show()), +--- it's generally simpler to set covers_footer when initializing the Widget object. +-- Since these Events are not currently in use, comment the handlers out ;). +--[[ +ReaderFooter.onDisableFooterAutoRefresh = ReaderFooter.onSuspend +ReaderFooter.onRestoreFooterAutoRefresh = ReaderFooter.onResume +--]] + function ReaderFooter:onFrontlightStateChanged() if self.settings.frontlight then self:onUpdateFooter(true) diff --git a/frontend/apps/reader/modules/readerlink.lua b/frontend/apps/reader/modules/readerlink.lua index 0afc15d75..6c259372b 100644 --- a/frontend/apps/reader/modules/readerlink.lua +++ b/frontend/apps/reader/modules/readerlink.lua @@ -1263,6 +1263,7 @@ function ReaderLink:showAsFootnotePopup(link, neglect_current_location) local FootnoteWidget = require("ui/widget/footnotewidget") local popup popup = FootnoteWidget:new{ + covers_footer = true, -- hint for UIManager:repaintReaderFooter html = html, doc_font_size = Screen:scaleBySize(self.ui.font.font_size), doc_margins = self.ui.document:getPageMargins(), diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 77e6a9618..7c56bc4e3 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -1045,6 +1045,16 @@ function UIManager:_repaint() end end + -- Show IDs of covered widgets when debugging + --[[ + if start_idx > 1 then + for i = 1, start_idx-1 do + local widget = self._window_stack[i] + logger.dbg("NOT painting widget:", widget.widget.name or widget.widget.id or tostring(widget)) + end + end + --]] + for i = start_idx, #self._window_stack do local widget = self._window_stack[i] -- paint if current widget or any widget underneath is dirty @@ -1141,6 +1151,43 @@ function UIManager:widgetRepaint(widget, x, y) widget:paintTo(Screen.bb, x, y) end +-- Now, this one is basically widgetRepaint, but tailored for a very, +-- very specific use-case related to ReaderFooter:setupAutoRefreshTime +-- (c.f., #6648) +function UIManager:repaintReaderFooter(readerfooter_widget) + if not readerfooter_widget then return false end + + -- Don't repaint if there's another widget than ReaderUI flagged as covers_fullscreen being shown, + -- or if a non-fullscreen widget is flagged as covers_footer. + -- This isn't particularly pretty, but, oh, well (#6616). + local skip_repaint = false + -- c.f., UIManager:_repaint + for i = #self._window_stack, 1, -1 do + local widget = self._window_stack[i].widget + if widget.covers_fullscreen then + if widget.name and widget.name == "ReaderUI" then -- luacheck: ignore + -- NOP (i.e., continue) + else + skip_repaint = true + logger.dbg("Skipping ReaderFooter repaint, because something covers ReaderUI") + break + end + elseif widget.covers_footer then + skip_repaint = true + logger.dbg("Skipping ReaderFooter repaint, because something covers ReaderFooter") + break + end + end + if skip_repaint then return false end + + logger.dbg("Explicit ReaderFooter repaint:", readerfooter_widget.name or readerfooter_widget.id or tostring(readerfooter_widget)) + -- c.f., ReaderView:paintTo() + readerfooter_widget:paintTo(Screen.bb, 0, 0) + + -- Inform the caller that we did, in fact, repaint it. + return true +end + function UIManager:setInputTimeout(timeout) self.INPUT_TIMEOUT = timeout or 200*1000 end @@ -1178,6 +1225,8 @@ function UIManager:handleInput() repeat wait_until, now = self:_checkTasks() --dbg("---------------------------------------------------") + --dbg("wait_until", wait_until) + --dbg("now", now) --dbg("exec stack", self._task_queue) --dbg("window stack", self._window_stack) --dbg("dirty stack", self._dirty)