Kobo: Refactor various aspects of the Kaleido/MTK support (#12221)

* UIManager: Let the fb backend deal with Kaleido wfm promotion. This fixes a number of quirks that poisoned the refresh queue with spurious full-screen refreshes. See https://github.com/koreader/koreader-base/pull/1865 for more details.
* This also means we now disable Kaleido waveform modes when color rendering is disabled (remember to trash your thumbnail cache if you don't want to mix color w/ grayscale thumbnails, though).
* UIManager: Merge refreshes that share an edge, because that was driving me nuts (and would have most likely been merged by the kernel anyway). A perfect test-case is the FM, which trips two separate refreshes because of its title bar.
* ReaderFlipping: Use sensible dimensions, so that we only refresh the icon's region.
* ReaderBookmark: Only refresh the dogear instead of the whole page when toggling bookmarks.
* NetworkSetting: Make it a real boy, so it consistently refreshes properly on dismiss instead of relying on UIManager saving the day.
* Kobo: Aggressively prevent *both* suspend & standby while MTK devices are plugged-in, as both will horribly implode the kernel (we previously only prevent standby while charging).
* Kobo: Switch to 8bpp on B&W MTK devices (or when color rendering is disabled on Kaleido panels).
This commit is contained in:
NiLuJe
2024-07-28 01:19:40 +02:00
committed by GitHub
parent 761cf18222
commit d59c837714
21 changed files with 149 additions and 87 deletions

2
base

Submodule base updated: b820ba51df...d57f85950f

View File

@@ -551,7 +551,7 @@ To:
}, },
}, },
} }
if Device:isKobo() and not Device:isSunxi() then if Device:isKobo() and not Device:isSunxi() and not Device:hasColorScreen() then
table.insert(self.menu_items.developer_options.sub_item_table, { table.insert(self.menu_items.developer_options.sub_item_table, {
text = _("Disable forced 8-bit pixel depth"), text = _("Disable forced 8-bit pixel depth"),
checked_func = function() checked_func = function()

View File

@@ -310,9 +310,15 @@ end
function ReaderBookmark:onToggleBookmark() function ReaderBookmark:onToggleBookmark()
self:toggleBookmark() self:toggleBookmark()
self.view.footer:onUpdateFooter(self.view.footer_visible)
self.view.dogear:onSetDogearVisibility(not self.view.dogear_visible) self.view.dogear:onSetDogearVisibility(not self.view.dogear_visible)
UIManager:setDirty(self.view.dialog, "ui") -- Refresh the dogear first, because it might inherit ReaderUI refresh hints.
UIManager:setDirty(self.view.dialog, function()
return "ui",
self.view.dogear:getRefreshRegion()
end)
-- And ask for a footer refresh, in case we have bookmark_count enabled.
-- Assuming the footer is visible, it'll request a refresh regardless, but the EPDC should optimize it out if no content actually changed.
self.view.footer:onUpdateFooter(self.view.footer_visible)
return true return true
end end

View File

@@ -20,6 +20,7 @@ function ReaderDogear:init()
self.dogear_min_size = math.ceil(math.min(Screen:getWidth(), Screen:getHeight()) * (1/40)) self.dogear_min_size = math.ceil(math.min(Screen:getWidth(), Screen:getHeight()) * (1/40))
self.dogear_max_size = math.ceil(math.min(Screen:getWidth(), Screen:getHeight()) * (1/32)) self.dogear_max_size = math.ceil(math.min(Screen:getWidth(), Screen:getHeight()) * (1/32))
self.dogear_size = nil self.dogear_size = nil
self.icon = nil
self.dogear_y_offset = 0 self.dogear_y_offset = 0
self.top_pad = nil self.top_pad = nil
self:setupDogear() self:setupDogear()
@@ -35,16 +36,17 @@ function ReaderDogear:setupDogear(new_dogear_size)
if self[1] then if self[1] then
self[1]:free() self[1]:free()
end end
self.icon = IconWidget:new{
icon = "dogear.alpha",
rotation_angle = BD.mirroredUILayout() and 90 or 0,
width = self.dogear_size,
height = self.dogear_size,
alpha = true, -- Keep the alpha layer intact
}
self.top_pad = VerticalSpan:new{width = self.dogear_y_offset} self.top_pad = VerticalSpan:new{width = self.dogear_y_offset}
self.vgroup = VerticalGroup:new{ self.vgroup = VerticalGroup:new{
self.top_pad, self.top_pad,
IconWidget:new{ self.icon,
icon = "dogear.alpha",
rotation_angle = BD.mirroredUILayout() and 90 or 0,
width = self.dogear_size,
height = self.dogear_size,
alpha = true, -- Keep the alpha layer intact
}
} }
self[1] = RightContainer:new{ self[1] = RightContainer:new{
dimen = Geom:new{w = Screen:getWidth(), h = self.dogear_y_offset + self.dogear_size}, dimen = Geom:new{w = Screen:getWidth(), h = self.dogear_y_offset + self.dogear_size},
@@ -111,11 +113,13 @@ function ReaderDogear:onChangeViewMode()
end end
function ReaderDogear:resetLayout() function ReaderDogear:resetLayout()
local new_screen_width = Screen:getWidth() -- NOTE: RightContainer aligns to the right of its *own* width...
if new_screen_width == self._last_screen_width then return end self[1].dimen.w = Screen:getWidth()
self._last_screen_width = new_screen_width end
self[1].dimen.w = new_screen_width function ReaderDogear:getRefreshRegion()
-- We can't use self.dimen because of the width/height quirks of Left/RightContainer, so use the IconWidget's...
return self.icon.dimen
end end
function ReaderDogear:onSetDogearVisibility(visible) function ReaderDogear:onSetDogearVisibility(visible)

View File

@@ -43,15 +43,16 @@ function ReaderFlipping:init()
dimen = Geom:new{w = Screen:getWidth(), h = self.flipping_widget:getSize().h}, dimen = Geom:new{w = Screen:getWidth(), h = self.flipping_widget:getSize().h},
self.flipping_widget, self.flipping_widget,
} }
self:resetLayout()
end end
function ReaderFlipping:resetLayout() function ReaderFlipping:resetLayout()
local new_screen_width = Screen:getWidth() -- NOTE: LeftContainer aligns to the left of its *own* width (and will handle RTL mirroring, so we can't cheat)...
if new_screen_width == self._last_screen_width then return end self[1].dimen.w = Screen:getWidth()
self._last_screen_width = new_screen_width end
self[1].dimen.w = new_screen_width function ReaderFlipping:getRefreshRegion()
-- We can't use self.dimen because of the width/height quirks of Left/RightContainer, so use the IconWidget's...
return self[1][1].dimen
end end
function ReaderFlipping:getRollingRenderingStateIconWidget() function ReaderFlipping:getRollingRenderingStateIconWidget()

View File

@@ -1214,7 +1214,7 @@ function ReaderHighlight:_resetHoldTimer(clear)
self.long_hold_reached_action = function() self.long_hold_reached_action = function()
self.long_hold_reached = true self.long_hold_reached = true
-- Have ReaderView redraw and refresh ReaderFlipping and our state icon, avoiding flashes -- Have ReaderView redraw and refresh ReaderFlipping and our state icon, avoiding flashes
UIManager:setDirty(self.dialog, "ui", self.view.flipping.dimen) UIManager:setDirty(self.dialog, "ui", self.view.flipping:getRefreshRegion())
end end
end end
-- Unschedule if already set -- Unschedule if already set
@@ -1251,7 +1251,7 @@ function ReaderHighlight:_resetHoldTimer(clear)
if self.long_hold_reached then if self.long_hold_reached then
self.long_hold_reached = false self.long_hold_reached = false
-- Have ReaderView redraw and refresh ReaderFlipping with our state icon removed -- Have ReaderView redraw and refresh ReaderFlipping with our state icon removed
UIManager:setDirty(self.dialog, "ui", self.view.flipping.dimen) UIManager:setDirty(self.dialog, "ui", self.view.flipping:getRefreshRegion())
end end
end end

View File

@@ -1863,7 +1863,7 @@ function ReaderRolling:setupRerenderingAutomation()
if self.rendering_state ~= prev_state then if self.rendering_state ~= prev_state then
logger.dbg("_stepRerenderingAutomation", prev_state, ">", self.rendering_state) logger.dbg("_stepRerenderingAutomation", prev_state, ">", self.rendering_state)
-- Have ReaderView redraw and refresh ReaderFlipping and our state icon, avoiding flashes -- Have ReaderView redraw and refresh ReaderFlipping and our state icon, avoiding flashes
UIManager:setDirty(self.view.dialog, "ui", self.view.flipping.dimen) UIManager:setDirty(self.view.dialog, "ui", self.view.flipping:getRefreshRegion())
end end
if reschedule then if reschedule then
UIManager:scheduleIn(1, self._stepRerenderingAutomation) UIManager:scheduleIn(1, self._stepRerenderingAutomation)

View File

@@ -264,10 +264,6 @@ function ReaderView:paintTo(bb, x, y)
if self.ui.paging then if self.ui.paging then
if self.document.hw_dithering then if self.document.hw_dithering then
self.dialog.dithered = true self.dialog.dithered = true
-- Assume we're going to be showing colorful stuff on kaleido panels...
if Device:hasKaleidoWfm() then
UIManager:setDirty(nil, "color")
end
end end
else else
-- Whereas for CRe, -- Whereas for CRe,
@@ -278,15 +274,14 @@ function ReaderView:paintTo(bb, x, y)
-- Which is why we remember the stats of the *previous* page. -- Which is why we remember the stats of the *previous* page.
self.img_count, self.img_coverage = img_count, img_coverage self.img_count, self.img_coverage = img_count, img_coverage
if img_coverage >= 0.075 or coverage_diff >= 0.075 then if img_coverage >= 0.075 or coverage_diff >= 0.075 then
self.dialog.dithered = true -- Request dithering on the actual page with image content
if img_coverage >= 0.075 then
self.dialog.dithered = true
end
-- Request a flashing update while we're at it, but only if it's the first time we're painting it -- Request a flashing update while we're at it, but only if it's the first time we're painting it
if self.state.drawn == false and G_reader_settings:nilOrTrue("refresh_on_pages_with_images") then if self.state.drawn == false and G_reader_settings:nilOrTrue("refresh_on_pages_with_images") then
UIManager:setDirty(nil, "full") UIManager:setDirty(nil, "full")
end end
-- On Kaleido panels, we'll want to use GCC16 on the actual image, always...
if Device:hasKaleidoWfm() and img_coverage >= 0.075 then
UIManager:setDirty(nil, "color")
end
end end
self.state.drawn = true self.state.drawn = true
end end

View File

@@ -1230,6 +1230,14 @@ end
--- The function to put the device into standby, with enabled touchscreen. --- The function to put the device into standby, with enabled touchscreen.
-- max_duration ... maximum time for the next standby, can wake earlier (e.g. Tap, Button ...) -- max_duration ... maximum time for the next standby, can wake earlier (e.g. Tap, Button ...)
function Kobo:standby(max_duration) function Kobo:standby(max_duration)
-- On MTK, any suspend/standby attempt while plugged-in will hang the kernel... -_-"
-- NOTE: isCharging is still true while isCharged!
if self:isMTK() and self.powerd:isCharging() then
logger.info("Kobo standby: skipping the standby request for now: device is plugged in and would otherwise crash!")
return
end
-- NOTE: Switch to the performance CPU governor, in order to speed up the resume process so as to lower its latency cost... -- NOTE: Switch to the performance CPU governor, in order to speed up the resume process so as to lower its latency cost...
-- (It won't have any impact on power efficiency *during* suspend, so there's not really any drawback). -- (It won't have any impact on power efficiency *during* suspend, so there's not really any drawback).
self:performanceCPUGovernor() self:performanceCPUGovernor()
@@ -1301,6 +1309,20 @@ function Kobo:standby(max_duration)
end end
function Kobo:suspend() function Kobo:suspend()
-- On MTK, any suspend/standby attempt while plugged-in will hang the kernel... -_-"
-- NOTE: isCharging is still true while isCharged!
if self:isMTK() and self.powerd:isCharging() then
logger.info("Kobo suspend: skipping the suspend request for now: device is plugged in and would otherwise crash!")
-- Do the usual scheduling dance, so we get a chance to fire the UnexpectedWakeupLimit event...
UIManager:unschedule(self.checkUnexpectedWakeup)
self.unexpected_wakeup_count = self.unexpected_wakeup_count + 1
logger.dbg("Kobo suspend: scheduling unexpected wakeup guard")
UIManager:scheduleIn(15, self.checkUnexpectedWakeup, self)
return
end
logger.info("Kobo suspend: going to sleep . . .") logger.info("Kobo suspend: going to sleep . . .")
UIManager:unschedule(self.checkUnexpectedWakeup) UIManager:unschedule(self.checkUnexpectedWakeup)
-- NOTE: Sleep as little as possible here, sleeping has a tendency to make -- NOTE: Sleep as little as possible here, sleeping has a tendency to make

View File

@@ -1,5 +1,6 @@
local Device = require("device")
local Event = require("ui/event") local Event = require("ui/event")
local Screen = require("device").screen local Screen = Device.screen
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local CanvasContext = require("document/canvascontext") local CanvasContext = require("document/canvascontext")
local _ = require("gettext") local _ = require("gettext")
@@ -15,5 +16,11 @@ return {
G_reader_settings:saveSetting("color_rendering", new_val) G_reader_settings:saveSetting("color_rendering", new_val)
CanvasContext:setColorRenderingEnabled(new_val) CanvasContext:setColorRenderingEnabled(new_val)
UIManager:broadcastEvent(Event:new("ColorRenderingUpdate")) UIManager:broadcastEvent(Event:new("ColorRenderingUpdate"))
-- On color Kobos, we can use this opportunity to swap to 8bpp, so, request a restart.
-- NOTE: Unfortunately, that doesn't help alleviate moire effect on affected patterns,
-- so I guess that comes from some physical aspect of the screen layers...
if Device:isKobo() and Device:hasColorScreen() then
UIManager:askForRestart()
end
end end
} }

View File

@@ -183,7 +183,7 @@ function Geom:intersect(rect_b)
end end
--[[-- --[[--
Returns true if self does not share any area with rect_b Returns true if self does not share any area or edge with rect_b
@tparam Geom rect_b @tparam Geom rect_b
]] ]]
@@ -208,6 +208,32 @@ function Geom:intersectWith(rect_b)
return not self:notIntersectWith(rect_b) return not self:notIntersectWith(rect_b)
end end
--[[--
Returns true if self does not share any area with rect_b
@tparam Geom rect_b
]]
function Geom:notOpenIntersectWith(rect_b)
if not rect_b or rect_b:area() == 0 then return true end
if (self.x > (rect_b.x + rect_b.w))
or (self.y > (rect_b.y + rect_b.h))
or (rect_b.x > (self.x + self.w))
or (rect_b.y > (self.y + self.h)) then
return true
end
return false
end
--[[--
Returns true if self geom shares area or an edge with rect_b.
@tparam Geom rect_b
]]
function Geom:openIntersectWith(rect_b)
return not self:notOpenIntersectWith(rect_b)
end
--[[-- --[[--
Set size of dimension or rectangle to size of given dimension/rectangle. Set size of dimension or rectangle to size of given dimension/rectangle.

View File

@@ -690,7 +690,7 @@ function Screensaver:show()
self.screensaver_widget.modal = true self.screensaver_widget.modal = true
self.screensaver_widget.dithered = true self.screensaver_widget.dithered = true
UIManager:show(self.screensaver_widget, Device:hasKaleidoWfm() and "color" or "full") UIManager:show(self.screensaver_widget, "full")
end end
-- Setup the gesture lock through an additional invisible widget, so that it works regardless of the configuration. -- Setup the gesture lock through an additional invisible widget, so that it works regardless of the configuration.

View File

@@ -138,7 +138,7 @@ For more details about refreshtype, refreshregion & refreshdither see the descri
If refreshtype is omitted, no refresh will be enqueued at this time. If refreshtype is omitted, no refresh will be enqueued at this time.
@param widget a @{ui.widget.widget|widget} object @param widget a @{ui.widget.widget|widget} object
@string refreshtype `"color"`, `"colortext"`, `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (optional) @string refreshtype `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (optional)
@param refreshregion a rectangle @{ui.geometry.Geom|Geom} object (optional, requires refreshtype to be set) @param refreshregion a rectangle @{ui.geometry.Geom|Geom} object (optional, requires refreshtype to be set)
@int x horizontal screen offset (optional, `0` if omitted) @int x horizontal screen offset (optional, `0` if omitted)
@int y vertical screen offset (optional, `0` if omitted) @int y vertical screen offset (optional, `0` if omitted)
@@ -195,7 +195,7 @@ For more details about refreshtype, refreshregion & refreshdither see the descri
If refreshtype is omitted, no extra refresh will be enqueued at this time, leaving only those from the uncovered widgets. If refreshtype is omitted, no extra refresh will be enqueued at this time, leaving only those from the uncovered widgets.
@param widget a @{ui.widget.widget|widget} object @param widget a @{ui.widget.widget|widget} object
@string refreshtype `"color"`, `"colortext"`, `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (optional) @string refreshtype `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (optional)
@param refreshregion a rectangle @{ui.geometry.Geom|Geom} object (optional, requires refreshtype to be set) @param refreshregion a rectangle @{ui.geometry.Geom|Geom} object (optional, requires refreshtype to be set)
@bool refreshdither `true` if the refresh requires dithering (optional, requires refreshtype to be set) @bool refreshdither `true` if the refresh requires dithering (optional, requires refreshtype to be set)
@see setDirty @see setDirty
@@ -464,10 +464,6 @@ It just appends stuff to the paint and/or refresh queues.
Here's a quick rundown of what each refreshtype should be used for: Here's a quick rundown of what each refreshtype should be used for:
* `color`: high-fidelity flashing refresh for color image content on Kaleido panels.
Maps to partial on unsupported devices, as such, better used conditionally behind a Device:hasKaleidoWfm check.
* `colortext`: REAGL refresh for color text (e.g., highlights) on Kaleido panels.
Maps to partial on unsupported devices, as such, better used conditionally behind a Device:hasKaleidoWfm check.
* `full`: high-fidelity flashing refresh (e.g., large images). * `full`: high-fidelity flashing refresh (e.g., large images).
Highest quality, but highest latency. Highest quality, but highest latency.
Don't abuse if you only want a flash (in this case, prefer `flashui` or `flashpartial`). Don't abuse if you only want a flash (in this case, prefer `flashui` or `flashpartial`).
@@ -566,7 +562,7 @@ UIManager:setDirty(self.widget, "partial", Geom:new{x=10,y=10,w=100,h=50})
UIManager:setDirty(self.widget, function() return "ui", self.someelement.dimen end) UIManager:setDirty(self.widget, function() return "ui", self.someelement.dimen end)
@param widget a window-level widget object, `"all"`, or `nil` @param widget a window-level widget object, `"all"`, or `nil`
@param refreshtype `"color"`, `"colortext"`, `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (or a lambda, see description above) @param refreshtype `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (or a lambda, see description above)
@param refreshregion a rectangle @{ui.geometry.Geom|Geom} object (optional, omitting it means the region will cover the full screen) @param refreshregion a rectangle @{ui.geometry.Geom|Geom} object (optional, omitting it means the region will cover the full screen)
@bool refreshdither `true` if widget requires dithering (optional) @bool refreshdither `true` if widget requires dithering (optional)
]] ]]
@@ -1058,7 +1054,7 @@ function UIManager:getElapsedTimeSinceBoot()
end end
-- precedence of refresh modes: -- precedence of refresh modes:
local refresh_modes = { a2 = 1, fast = 2, ui = 3, partial = 4, ["[ui]"] = 5, ["[partial]"] = 6, flashui = 7, flashpartial = 8, full = 9, colortext = 10, color = 11 } local refresh_modes = { a2 = 1, fast = 2, ui = 3, partial = 4, ["[ui]"] = 5, ["[partial]"] = 6, flashui = 7, flashpartial = 8, full = 9 }
-- NOTE: We might want to introduce a "force_a2" that points to fast, but has the highest priority, -- NOTE: We might want to introduce a "force_a2" that points to fast, but has the highest priority,
-- for the few cases where we might *really* want to enforce fast (for stuff like panning or skimming?). -- for the few cases where we might *really* want to enforce fast (for stuff like panning or skimming?).
-- refresh methods in framebuffer implementation -- refresh methods in framebuffer implementation
@@ -1072,8 +1068,6 @@ local refresh_methods = {
flashui = Screen.refreshFlashUI, flashui = Screen.refreshFlashUI,
flashpartial = Screen.refreshFlashPartial, flashpartial = Screen.refreshFlashPartial,
full = Screen.refreshFull, full = Screen.refreshFull,
colortext = Screen.refreshColorText,
color = Screen.refreshColor,
} }
--[[ --[[
@@ -1111,7 +1105,7 @@ Widgets call this in their `paintTo()` method in order to notify
UIManager that a certain part of the screen is to be refreshed. UIManager that a certain part of the screen is to be refreshed.
@string mode @string mode
refresh mode (`"color"`, `"colortext"`, `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"`) refresh mode (`"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"`)
@param region @param region
A rectangle @{ui.geometry.Geom|Geom} object that specifies the region to be updated. A rectangle @{ui.geometry.Geom|Geom} object that specifies the region to be updated.
Optional, update will affect whole screen if not specified. Optional, update will affect whole screen if not specified.
@@ -1124,23 +1118,21 @@ UIManager that a certain part of the screen is to be refreshed.
]] ]]
function UIManager:_refresh(mode, region, dither) function UIManager:_refresh(mode, region, dither)
if not mode then if not mode then
-- If we're trying to float a dither hint up from a lower widget after a close, mode might be nil... -- This is most likely from a `show` or `close` that wasn't passed specific refresh details,
-- So use the lowest priority refresh mode (short of fast, because that'd do half-toning). -- (which is the vast majority of them), in which case we drop it to avoid enqueuing a useless full-screen refresh.
if dither then return
mode = "ui"
else
-- Otherwise, this is most likely from a `show` or `close` that wasn't passed specific refresh details,
-- (which is the vast majority of them), in which case we drop it to avoid enqueuing a useless full-screen refresh.
return
end
end end
-- Downgrade all refreshes to "fast" when ReaderPaging or ReaderScrolling have set this flag -- Downgrade all refreshes to "fast" when ReaderPaging or ReaderScrolling have set this flag
if self.currently_scrolling then if self.currently_scrolling then
mode = "fast" mode = "fast"
end end
-- Reset the refresh counter on any explicit full refresh
if not region and mode == "full" then if not region and mode == "full" then
self.refresh_count = 0 -- reset counter on explicit full refresh self.refresh_count = 0
end end
-- Handle downgrading flashing modes to non-flashing modes, according to user settings. -- Handle downgrading flashing modes to non-flashing modes, according to user settings.
-- NOTE: Do it before "full" promotion and collision checks/update_mode. -- NOTE: Do it before "full" promotion and collision checks/update_mode.
if G_reader_settings:isTrue("avoid_flashing_ui") then if G_reader_settings:isTrue("avoid_flashing_ui") then
@@ -1191,9 +1183,9 @@ function UIManager:_refresh(mode, region, dither)
-- as well as a few actually effective merges -- as well as a few actually effective merges
-- (e.g., the disappearance of a selection HL with the following menu update). -- (e.g., the disappearance of a selection HL with the following menu update).
for i, refresh in ipairs(self._refresh_stack) do for i, refresh in ipairs(self._refresh_stack) do
-- Check for collision with refreshes that are already enqueued -- Check for collisions with refreshes that are already enqueued.
-- NOTE: intersect *means* intersect: we won't merge edge-to-edge regions (but the EPDC probably will). -- NOTE: We use the open range variant, as we want to combine rectangles that share an edge (like the EPDC).
if region:intersectWith(refresh.region) then if region:openIntersectWith(refresh.region) then
-- combine both refreshes' regions -- combine both refreshes' regions
local combined = region:combine(refresh.region) local combined = region:combine(refresh.region)
-- update the mode, if needed -- update the mode, if needed
@@ -1291,8 +1283,8 @@ function UIManager:_repaint()
end end
self._refresh_func_stack = {} self._refresh_func_stack = {}
-- we should have at least one refresh if we did repaint. If we don't, we -- We should have at least one refresh if we did repaint.
-- add one now and log a warning if we are debugging -- If we don't, add one now and log a warning if we are debugging.
if dirty and not self._refresh_stack[1] then if dirty and not self._refresh_stack[1] then
logger.dbg("no refresh got enqueued. Will do a partial full screen refresh, which might be inefficient") logger.dbg("no refresh got enqueued. Will do a partial full screen refresh, which might be inefficient")
self:_refresh("partial") self:_refresh("partial")

View File

@@ -19,7 +19,9 @@ function LeftContainer:paintTo(bb, x, y)
if BD.mirroredUILayout() and self.allow_mirroring then if BD.mirroredUILayout() and self.allow_mirroring then
x = x + (self.dimen.w - contentSize.w) -- as in RightContainer x = x + (self.dimen.w - contentSize.w) -- as in RightContainer
end end
self[1]:paintTo(bb, x , y + math.floor((self.dimen.h - contentSize.h)/2)) self.dimen.x = x
self.dimen.y = y + math.floor((self.dimen.h - contentSize.h)/2)
self[1]:paintTo(bb, self.dimen.x, self.dimen.y)
end end
return LeftContainer return LeftContainer

View File

@@ -20,9 +20,9 @@ function RightContainer:paintTo(bb, x, y)
x = x + (self.dimen.w - contentSize.w) x = x + (self.dimen.w - contentSize.w)
-- else: keep x, as in LeftContainer -- else: keep x, as in LeftContainer
end end
self[1]:paintTo(bb, self.dimen.x = x
x, self.dimen.y = y + math.floor((self.dimen.h - contentSize.h)/2)
y + math.floor((self.dimen.h - contentSize.h)/2)) self[1]:paintTo(bb, self.dimen.x, self.dimen.y)
end end
return RightContainer return RightContainer

View File

@@ -369,7 +369,8 @@ function ImageViewer:update()
self.main_frame.radius = not self.fullscreen and 8 or nil self.main_frame.radius = not self.fullscreen and 8 or nil
-- NOTE: We use UI instead of partial, because we do NOT want to end up using a REAGL waveform... -- NOTE: We use UI instead of partial, because we do NOT want to end up using a REAGL waveform...
local wfm_mode = Device:hasKaleidoWfm() and "color" or "ui" -- ...except on Kaleido panels ;).
local wfm_mode = Device:hasKaleidoWfm() and "partial" or "ui"
-- NOTE: Disabling dithering here makes for a perfect test-case of how well it works: -- NOTE: Disabling dithering here makes for a perfect test-case of how well it works:
-- page turns will show color quantization artefacts (i.e., banding) like crazy, -- page turns will show color quantization artefacts (i.e., banding) like crazy,
-- while a long touch will trigger a dithered, flashing full-refresh that'll make everything shiny :). -- while a long touch will trigger a dithered, flashing full-refresh that'll make everything shiny :).

View File

@@ -458,7 +458,7 @@ function NetworkSetting:init()
self.pagination:setProgress(curr_page/total_pages) self.pagination:setProgress(curr_page/total_pages)
-- self.page_text:setText(curr_page .. "/" .. total_pages) -- self.page_text:setText(curr_page .. "/" .. total_pages)
UIManager:setDirty(self, function() UIManager:setDirty(self, function()
return "ui", self.dimen return "ui", self.popup.dimen
end) end)
end end
}, },
@@ -496,7 +496,7 @@ function NetworkSetting:init()
if connected_item ~= nil then if connected_item ~= nil then
obtainIP() obtainIP()
if G_reader_settings:nilOrTrue("auto_dismiss_wifi_scan") then if G_reader_settings:nilOrTrue("auto_dismiss_wifi_scan") then
UIManager:close(self, "ui", self.dimen) UIManager:close(self)
end end
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{
text = T(_("Connected to network %1"), BD.wrap(connected_item.display_ssid)), text = T(_("Connected to network %1"), BD.wrap(connected_item.display_ssid)),
@@ -527,6 +527,7 @@ function NetworkSetting:onCloseWidget()
if not NetworkMgr.pending_connectivity_check then if not NetworkMgr.pending_connectivity_check then
NetworkMgr.pending_connection = false NetworkMgr.pending_connection = false
end end
UIManager:setDirty(nil, "ui", self.popup.dimen)
end end
return NetworkSetting return NetworkSetting

View File

@@ -54,7 +54,7 @@ end
function ScreenSaverWidget:onShow() function ScreenSaverWidget:onShow()
UIManager:setDirty(self, function() UIManager:setDirty(self, function()
return Device:hasKaleidoWfm() and "color" or "full", self.main_frame.dimen return "full", self.main_frame.dimen
end) end)
return true return true
end end

View File

@@ -332,12 +332,17 @@ ko_do_fbdepth() {
fi fi
# On color panels, we target 32bpp for, well, color, and sane addressing (it also happens to be their default) ;o). # On color panels, we target 32bpp for, well, color, and sane addressing (it also happens to be their default) ;o).
# Also, the current lineup of MTK + Kaleido devices doesn't even *support* switching to 8bpp anymore.
eval "$(./fbink -e | tr ';' '\n' | grep -e hasColorPanel | tr '\n' ';')" eval "$(./fbink -e | tr ';' '\n' | grep -e hasColorPanel | tr '\n' ';')"
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [ "${hasColorPanel}" = "1" ]; then if [ "${hasColorPanel}" = "1" ]; then
echo "Switching fb bitdepth to 32bpp & rotation to Portrait" >>crash.log 2>&1 # If color rendering has been disabled by the user, switch to 8bpp to completely skip CFA processing
./fbdepth -d 32 -R UR >>crash.log 2>&1 if grep -q '\["color_rendering"\] = false' 'settings.reader.lua' 2>/dev/null; then
echo "Switching fb bitdepth to 8bpp (to disable CFA) & rotation to Portrait" >>crash.log 2>&1
./fbdepth -d 8 -R UR >>crash.log 2>&1
else
echo "Switching fb bitdepth to 32bpp & rotation to Portrait" >>crash.log 2>&1
./fbdepth -d 32 -R UR >>crash.log 2>&1
fi
return return
fi fi

View File

@@ -239,16 +239,16 @@ function ListMenuItem:update()
height_overflow_show_ellipsis = true, height_overflow_show_ellipsis = true,
} }
widget = OverlapGroup:new{ widget = OverlapGroup:new{
dimen = dimen, dimen = dimen:copy(),
LeftContainer:new{ LeftContainer:new{
dimen = dimen, dimen = dimen:copy(),
HorizontalGroup:new{ HorizontalGroup:new{
HorizontalSpan:new{ width = pad_width }, HorizontalSpan:new{ width = pad_width },
wleft, wleft,
} }
}, },
RightContainer:new{ RightContainer:new{
dimen = dimen, dimen = dimen:copy(),
HorizontalGroup:new{ HorizontalGroup:new{
wright, wright,
HorizontalSpan:new{ width = pad_width }, HorizontalSpan:new{ width = pad_width },
@@ -639,7 +639,7 @@ function ListMenuItem:update()
end end
local wmain = LeftContainer:new{ local wmain = LeftContainer:new{
dimen = dimen, dimen = dimen:copy(),
VerticalGroup:new{ VerticalGroup:new{
wtitle, wtitle,
wauthors, wauthors,
@@ -648,7 +648,7 @@ function ListMenuItem:update()
-- Build the final widget -- Build the final widget
widget = OverlapGroup:new{ widget = OverlapGroup:new{
dimen = dimen, dimen = dimen:copy(),
} }
if self.do_cover_image then if self.do_cover_image then
-- add left widget -- add left widget
@@ -673,13 +673,13 @@ function ListMenuItem:update()
end end
-- add padded main widget -- add padded main widget
table.insert(widget, LeftContainer:new{ table.insert(widget, LeftContainer:new{
dimen = dimen, dimen = dimen:copy(),
wmain wmain
}) })
-- add right widget -- add right widget
if wright then if wright then
table.insert(widget, RightContainer:new{ table.insert(widget, RightContainer:new{
dimen = dimen, dimen = dimen:copy(),
HorizontalGroup:new{ HorizontalGroup:new{
wright, wright,
HorizontalSpan:new{ width = wright_right_padding }, HorizontalSpan:new{ width = wright_right_padding },
@@ -758,7 +758,7 @@ function ListMenuItem:update()
fontsize_no_bookinfo = fontsize_no_bookinfo - fontsize_dec_step fontsize_no_bookinfo = fontsize_no_bookinfo - fontsize_dec_step
until text_widget:getSize().h <= dimen.h until text_widget:getSize().h <= dimen.h
widget = LeftContainer:new{ widget = LeftContainer:new{
dimen = dimen, dimen = dimen:copy(),
HorizontalGroup:new{ HorizontalGroup:new{
HorizontalSpan:new{ width = Screen:scaleBySize(10) }, HorizontalSpan:new{ width = Screen:scaleBySize(10) },
text_widget text_widget
@@ -766,10 +766,10 @@ function ListMenuItem:update()
} }
if wright then -- last read date, in History, even for deleted files if wright then -- last read date, in History, even for deleted files
widget = OverlapGroup:new{ widget = OverlapGroup:new{
dimen = dimen, dimen = dimen:copy(),
widget, widget,
RightContainer:new{ RightContainer:new{
dimen = dimen, dimen = dimen:copy(),
HorizontalGroup:new{ HorizontalGroup:new{
wright, wright,
HorizontalSpan:new{ width = wright_right_padding }, HorizontalSpan:new{ width = wright_right_padding },

View File

@@ -202,14 +202,14 @@ if G_reader_settings:isTrue("color_rendering") and not Device:hasColorScreen() t
text = _("Color rendering is mistakenly enabled on your grayscale device.\nThis will subtly break some features, and adversely affect performance."), text = _("Color rendering is mistakenly enabled on your grayscale device.\nThis will subtly break some features, and adversely affect performance."),
cancel_text = _("Ignore"), cancel_text = _("Ignore"),
cancel_callback = function() cancel_callback = function()
return return
end, end,
ok_text = _("Disable"), ok_text = _("Disable"),
ok_callback = function() ok_callback = function()
local Event = require("ui/event") local Event = require("ui/event")
G_reader_settings:delSetting("color_rendering") G_reader_settings:delSetting("color_rendering")
CanvasContext:setColorRenderingEnabled(false) CanvasContext:setColorRenderingEnabled(false)
UIManager:broadcastEvent(Event:new("ColorRenderingUpdate")) UIManager:broadcastEvent(Event:new("ColorRenderingUpdate"))
end, end,
}) })
end end