diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 14f601083..47c4528ec 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -425,6 +425,8 @@ function UIManager:close(widget, refreshtype, refreshregion, refreshdither) -- make it disabled by default and check if any widget wants it disabled or enabled Input.disable_double_tap = true local requested_disable_double_tap = nil + local is_covered = false + local start_idx = 1 -- then remove all references to that widget on stack and refresh for i = #self._window_stack, 1, -1 do if self._window_stack[i].widget == widget then @@ -432,12 +434,23 @@ function UIManager:close(widget, refreshtype, refreshregion, refreshdither) table.remove(self._window_stack, i) dirty = true else - -- If anything else on the stack was dithered, honor the hint - if self._window_stack[i].widget.dithered then + -- If anything else on the stack not already hidden by (i.e., below) a fullscreen widget was dithered, honor the hint + if self._window_stack[i].widget.dithered and not is_covered then refreshdither = true logger.dbg("Lower widget", self._window_stack[i].widget.name or self._window_stack[i].widget.id or tostring(self._window_stack[i].widget), "was dithered, honoring the dithering hint") end + -- Remember the uppermost widget that covers the full screen, so we don't bother calling setDirty on hidden (i.e., lower) widgets in the following dirty loop. + -- _repaint already does that later on to skip the actual paintTo calls, so this ensures we limit the refresh queue to stuff that will actually get painted. + if not is_covered and self._window_stack[i].widget.covers_fullscreen then + is_covered = true + start_idx = i + logger.dbg("Lower widget", self._window_stack[i].widget.name or self._window_stack[i].widget.id or tostring(self._window_stack[i].widget), "covers the full screen") + if i > 1 then + logger.dbg("not refreshing", i-1, "covered widget(s)") + end + end + -- Set double tap to how the topmost specifying widget wants it if requested_disable_double_tap == nil and self._window_stack[i].widget.disable_double_tap ~= nil then requested_disable_double_tap = self._window_stack[i].widget.disable_double_tap @@ -448,8 +461,8 @@ function UIManager:close(widget, refreshtype, refreshregion, refreshdither) Input.disable_double_tap = requested_disable_double_tap end if dirty and not widget.invisible then - -- schedule remaining widgets to be painted - for i = 1, #self._window_stack do + -- schedule the remaining visible (i.e., uncovered) widgets to be painted + for i = start_idx, #self._window_stack do self:setDirty(self._window_stack[i].widget) end self:_refresh(refreshtype, refreshregion, refreshdither)