2
0
mirror of https://github.com/koreader/koreader synced 2024-11-11 19:11:14 +00:00

UIManager: Handle covers_fullscreen properly in close (#6828)

* When closing a widget, stop sending setDirty call for widgets lower on
the stack as soon as we hit a full-screen one.

This prevents inflated refresh regions when closing stuff on top of a
stack of multiple covers_fullscreen widgets (i.e., InfoMessages on top
of the Favorites page on top of the FM, for instance).

And, while we're there, also prevent getting infected by dithered
widgets when they're below a non dithered full-screen widget (the exact
same examples works, if the underlying FM page requires dithering).
This commit is contained in:
NiLuJe 2020-10-26 12:28:00 +01:00 committed by GitHub
parent 982702fdc1
commit 8e1c6c8409
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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)