Merge pull request #1306 from hwhw/master

Refresh refactoring, frontend/UIManager side
pull/1309/head
Huang Xin 10 years ago
commit a485141324

@ -1 +1 @@
Subproject commit a3c50378bbab8ef89066dd2511099f8e21fbbaf7 Subproject commit e135c5e8b2994edf1d8ef0eb81e09516022706c3

@ -148,7 +148,6 @@ function ReaderCropping:exitPageCrop(confirmed)
else else
self:setCropZoomMode(confirmed) self:setCropZoomMode(confirmed)
end end
UIManager.repaint_all = true
end end
function ReaderCropping:setCropZoomMode(confirmed) function ReaderCropping:setCropZoomMode(confirmed)

@ -267,22 +267,19 @@ function ReaderFooter:onTapFooter(arg, ges)
self.mode = 0 self.mode = 0
end end
self:applyFooterMode() self:applyFooterMode()
local region = Geom:new{
x = 0,
y = Screen:getHeight() - self.height,
w = Screen:getWidth(),
h = self.height
}
UIManager.update_regions_func = function()
return {region}
end
end end
if self.pageno then if self.pageno then
self:updateFooterPage() self:updateFooterPage()
else else
self:updateFooterPos() self:updateFooterPos()
end end
UIManager:setDirty(self.view.dialog, "partial") local region = Geom:new{
x = 0,
y = Screen:getHeight() - self.height,
w = Screen:getWidth(),
h = self.height
}
UIManager:setDirty(self.view.dialog, "partial", region)
G_reader_settings:saveSetting("reader_footer_mode", self.mode) G_reader_settings:saveSetting("reader_footer_mode", self.mode)
return true return true
end end

@ -120,7 +120,6 @@ function ReaderHighlight:clear()
else else
self.ui.document:clearSelection() self.ui.document:clearSelection()
end end
UIManager:setDirty(self.dialog, "full")
if self.hold_pos then if self.hold_pos then
self.hold_pos = nil self.hold_pos = nil
self.selected_text = nil self.selected_text = nil
@ -240,13 +239,9 @@ function ReaderHighlight:onHold(arg, ges)
table.insert(boxes, self.selected_word.sbox) table.insert(boxes, self.selected_word.sbox)
self.view.highlight.temp[self.hold_pos.page] = boxes self.view.highlight.temp[self.hold_pos.page] = boxes
end end
--[[
UIManager.update_regions_func = function()
DEBUG("update ReaderHighlight onHold region", self.selected_word.sbox)
return {self.selected_word.sbox}
end
--]]
UIManager:setDirty(self.dialog, "partial") UIManager:setDirty(self.dialog, "partial")
-- TODO: only mark word?
-- UIManager:setDirty(self.dialog, "partial", self.selected_word.sbox)
end end
return true return true
end end
@ -265,7 +260,12 @@ function ReaderHighlight:onHoldPan(arg, ges)
self.holdpan_pos = self.view:screenToPageTransform(ges.pos) self.holdpan_pos = self.view:screenToPageTransform(ges.pos)
DEBUG("holdpan position in page", self.holdpan_pos) DEBUG("holdpan position in page", self.holdpan_pos)
local old_text = self.selected_text and self.selected_text.text
self.selected_text = self.ui.document:getTextFromPositions(self.hold_pos, self.holdpan_pos) self.selected_text = self.ui.document:getTextFromPositions(self.hold_pos, self.holdpan_pos)
if self.selected_text and old_text and old_text == self.selected_text.text then
-- no modification
return
end
DEBUG("selected text:", self.selected_text) DEBUG("selected text:", self.selected_text)
if self.selected_text then if self.selected_text then
self.view.highlight.temp[self.hold_pos.page] = self.selected_text.sboxes self.view.highlight.temp[self.hold_pos.page] = self.selected_text.sboxes

@ -314,7 +314,8 @@ function ReaderPaging:onSwipe(arg, ges)
self:onPagingRel(-1) self:onPagingRel(-1)
end end
else else
UIManager.full_refresh = true -- trigger full refresh
UIManager:setDirty(nil, "full")
end end
end end
@ -343,7 +344,8 @@ function ReaderPaging:onPanRelease(arg, ges)
end end
else else
self.last_pan_relative_y = 0 self.last_pan_relative_y = 0
UIManager.full_refresh = true -- trigger full refresh
UIManager:setDirty(nil, "full")
end end
end end
@ -649,7 +651,7 @@ function ReaderPaging:onScrollPageRel(diff)
end end
-- update current pageno to the very last part in current view -- update current pageno to the very last part in current view
self:gotoPage(self.view.page_states[#self.view.page_states].page, "scrolling") self:gotoPage(self.view.page_states[#self.view.page_states].page, "scrolling")
UIManager:setDirty(self.view.dialog) UIManager:setDirty(self.view.dialog, "partial")
end end
function ReaderPaging:onGotoPageRel(diff) function ReaderPaging:onGotoPageRel(diff)

@ -389,7 +389,7 @@ function ReaderRolling:updatePos()
self.old_page = new_page self.old_page = new_page
self.ui:handleEvent(Event:new("UpdateToc")) self.ui:handleEvent(Event:new("UpdateToc"))
end end
UIManager.repaint_all = true UIManager:setDirty(self.view.dialog, "partial")
end end
--[[ --[[

@ -42,7 +42,8 @@ function ReaderScreenshot:onScreenshot(filename)
timeout = 2, timeout = 2,
}) })
Screen:shot(screenshot_name) Screen:shot(screenshot_name)
UIManager.full_refresh = true -- trigger full refresh
UIManager:setDirty(nil, "full")
return true return true
end end

@ -71,6 +71,7 @@ function ReaderSearch:onShowSearchDialog(text)
} }
local res = do_search(self.searchFromCurrent, text, 0)() local res = do_search(self.searchFromCurrent, text, 0)()
UIManager:show(self.search_dialog) UIManager:show(self.search_dialog)
-- TODO: regional
UIManager:setDirty(self.dialog, "partial") UIManager:setDirty(self.dialog, "partial")
return true return true
end end

@ -508,7 +508,7 @@ function ReaderView:recalculate()
self.state.offset.x = (self.dimen.w - self.visible_area.w) / 2 self.state.offset.x = (self.dimen.w - self.visible_area.w) / 2
end end
-- flag a repaint so self:paintTo will be called -- flag a repaint so self:paintTo will be called
UIManager:setDirty(self.dialog) UIManager:setDirty(self.dialog, "partial")
end end
function ReaderView:PanningUpdate(dx, dy) function ReaderView:PanningUpdate(dx, dy)
@ -517,7 +517,7 @@ function ReaderView:PanningUpdate(dx, dy)
self.visible_area:offsetWithin(self.page_area, dx, dy) self.visible_area:offsetWithin(self.page_area, dx, dy)
if self.visible_area ~= old then if self.visible_area ~= old then
-- flag a repaint -- flag a repaint
UIManager:setDirty(self.dialog) UIManager:setDirty(self.dialog, "partial")
DEBUG("on pan: page_area", self.page_area) DEBUG("on pan: page_area", self.page_area)
DEBUG("on pan: visible_area", self.visible_area) DEBUG("on pan: visible_area", self.visible_area)
self.ui:handleEvent( self.ui:handleEvent(
@ -534,7 +534,7 @@ function ReaderView:PanningStart(x, y)
self.visible_area = self.panning_visible_area:copy() self.visible_area = self.panning_visible_area:copy()
self.visible_area:offsetWithin(self.page_area, x, y) self.visible_area:offsetWithin(self.page_area, x, y)
self.ui:handleEvent(Event:new("ViewRecalculate", self.visible_area, self.page_area)) self.ui:handleEvent(Event:new("ViewRecalculate", self.visible_area, self.page_area))
UIManager:setDirty(self.dialog) UIManager:setDirty(self.dialog, "partial")
end end
function ReaderView:PanningStop() function ReaderView:PanningStop()
@ -546,7 +546,7 @@ function ReaderView:SetZoomCenter(x, y)
self.visible_area:centerWithin(self.page_area, x, y) self.visible_area:centerWithin(self.page_area, x, y)
if self.visible_area ~= old then if self.visible_area ~= old then
self.ui:handleEvent(Event:new("ViewRecalculate", self.visible_area, self.page_area)) self.ui:handleEvent(Event:new("ViewRecalculate", self.visible_area, self.page_area))
UIManager:setDirty(self.dialog) UIManager:setDirty(self.dialog, "partial")
end end
end end

@ -16,6 +16,7 @@ if Device:hasFrontlight() then
end, end,
}) })
end end
table.insert(common_settings, { table.insert(common_settings, {
text = _("Night mode"), text = _("Night mode"),
checked_func = function() return G_reader_settings:readSetting("night_mode") end, checked_func = function() return G_reader_settings:readSetting("night_mode") end,
@ -37,7 +38,7 @@ table.insert(common_settings, {
sub_item_table = { sub_item_table = {
require("ui/elements/screen_dpi_menu_table"), require("ui/elements/screen_dpi_menu_table"),
require("ui/elements/screen_eink_opt_menu_table"), require("ui/elements/screen_eink_opt_menu_table"),
UIManager:getRefreshMenuTable(), require("ui/elements/refresh_menu_table"),
}, },
}) })
table.insert(common_settings, Language:getLangMenuTable()) table.insert(common_settings, Language:getLangMenuTable())

@ -0,0 +1,71 @@
local UIManager = require("ui/uimanager")
local util = require("ffi/util")
local _ = require("gettext")
local function custom_1() return G_reader_settings:readSetting("refresh_rate_1") or 12 end
local function custom_2() return G_reader_settings:readSetting("refresh_rate_2") or 22 end
local function custom_3() return G_reader_settings:readSetting("refresh_rate_3") or 99 end
local function custom_input(name)
return {
title = _("Input page number for a full refresh"),
type = "number",
hint = "(1 - 99)",
callback = function(input)
local rate = tonumber(input)
G_reader_settings:saveSetting(name, rate)
UIManager:setRefreshRate(rate)
end,
}
end
return {
text = _("E-ink full refresh rate"),
sub_item_table = {
{
text = _("Every page"),
checked_func = function() return UIManager:getRefreshRate() == 1 end,
callback = function() UIManager:setRefreshRate(1) end,
},
{
text = _("Every 6 pages"),
checked_func = function() return UIManager:getRefreshRate() == 6 end,
callback = function() UIManager:setRefreshRate(6) end,
},
{
text_func = function()
return util.template(
_("Custom 1: %1 pages"),
custom_1()
)
end,
checked_func = function() return UIManager:getRefreshRate() == custom_1() end,
callback = function() UIManager:setRefreshRate(custom_1()) end,
hold_input = custom_input("refresh_rate_1")
},
{
text_func = function()
return util.template(
_("Custom 2: %1 pages"),
custom_2()
)
end,
checked_func = function() return UIManager:getRefreshRate() == custom_2() end,
callback = function() UIManager:setRefreshRate(custom_2()) end,
hold_input = custom_input("refresh_rate_2")
},
{
text_func = function()
return util.template(
_("Custom 3: %1 pages"),
custom_3()
)
end,
checked_func = function() return UIManager:getRefreshRate() == custom_3() end,
callback = function() UIManager:setRefreshRate(custom_3()) end,
hold_input = custom_input("refresh_rate_3")
},
}
}

@ -2,26 +2,16 @@ local Device = require("device")
local Screen = Device.screen local Screen = Device.screen
local Input = require("device").input local Input = require("device").input
local Event = require("ui/event") local Event = require("ui/event")
local Geom = require("ui/geometry")
local util = require("ffi/util") local util = require("ffi/util")
local DEBUG = require("dbg") local DEBUG = require("dbg")
local _ = require("gettext") local _ = require("gettext")
-- there is only one instance of this -- there is only one instance of this
local UIManager = { local UIManager = {
-- force to repaint all the widget is stack, will be reset to false
-- after each ui loop
repaint_all = false,
-- force to do full refresh, will be reset to false
-- after each ui loop
full_refresh = false,
-- force to do partial refresh, will be reset to false
-- after each ui loop
partial_refresh = false,
-- trigger a full refresh when counter reaches FULL_REFRESH_COUNT -- trigger a full refresh when counter reaches FULL_REFRESH_COUNT
FULL_REFRESH_COUNT = G_reader_settings:readSetting("full_refresh_count") or DRCOUNTMAX, FULL_REFRESH_COUNT = G_reader_settings:readSetting("full_refresh_count") or DRCOUNTMAX,
refresh_count = 0, refresh_count = 0,
-- only update specific regions of the screen
update_regions_func = nil,
event_handlers = nil, event_handlers = nil,
@ -31,6 +21,8 @@ local UIManager = {
_execution_stack_dirty = false, _execution_stack_dirty = false,
_dirty = {}, _dirty = {},
_zeromqs = {}, _zeromqs = {},
_refresh_stack = {},
_refresh_func_stack = {},
} }
function UIManager:init() function UIManager:init()
@ -105,7 +97,7 @@ function UIManager:show(widget, x, y)
end end
end end
-- and schedule it to be painted -- and schedule it to be painted
self:setDirty(widget) self:setDirty(widget, "partial")
-- tell the widget that it is shown now -- tell the widget that it is shown now
widget:handleEvent(Event:new("Show")) widget:handleEvent(Event:new("Show"))
-- check if this widget disables double tap gesture -- check if this widget disables double tap gesture
@ -135,7 +127,7 @@ function UIManager:close(widget)
if dirty then if dirty then
-- schedule remaining widgets to be painted -- schedule remaining widgets to be painted
for i = 1, #self._window_stack do for i = 1, #self._window_stack do
self:setDirty(self._window_stack[i].widget) self:setDirty(self._window_stack[i].widget, "partial")
end end
end end
end end
@ -176,16 +168,49 @@ function UIManager:unschedule(action)
end end
end end
-- register a widget to be repainted --[[
function UIManager:setDirty(widget, refresh_type) register a widget to be repainted and enqueue a refresh
-- "auto": request full refresh
-- "full": force full refresh the second parameter (refreshtype) can either specify a refreshtype
-- "partial": partial refresh (optionally in combination with a refreshregion - which is suggested)
if not refresh_type then or a function that returns refreshtype AND refreshregion and is called
refresh_type = "auto" after painting the widget.
end
E.g.:
UIManager:setDirty(self.widget, "partial")
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)
--]]
function UIManager:setDirty(widget, refreshtype, refreshregion)
if widget then if widget then
self._dirty[widget] = refresh_type if widget == "all" then
-- special case: set all top-level widgets as being "dirty".
for i = 1, #self._window_stack do
self._dirty[self._window_stack[i].widget] = true
end
else
self._dirty[widget] = true
if DEBUG.is_on then
-- when debugging, we check if we get handed a valid widget,
-- which would be a dialog that was previously passed via show()
local found = false
for i = 1, #self._window_stack do
if self._window_stack[i].widget == widget then found = true end
end
if not found then
DEBUG("INFO: invalid widget for setDirty()", debug.traceback())
end
end
end
end
-- handle refresh information
if not refreshtype then return end
if type(refreshtype) == "function" then
-- callback, will be issued after painting
table.insert(self._refresh_func_stack, refreshtype)
else
-- otherwise, enqueue refresh
self:_refresh(refreshtype, refreshregion)
end end
end end
@ -252,7 +277,7 @@ function UIManager:sendEvent(event)
end end
end end
function UIManager:checkTasks() function UIManager:_checkTasks()
local now = { util.gettime() } local now = { util.gettime() }
-- check if we have timed events in our queue and search next one -- check if we have timed events in our queue and search next one
@ -286,36 +311,85 @@ function UIManager:checkTasks()
return wait_until, now return wait_until, now
end end
-- precedence of refresh modes:
local refresh_modes = { fast = 1, ui = 2, partial = 3, full = 4 }
-- refresh methods in framebuffer implementation
local refresh_methods = {
fast = "refreshFast",
ui = "refreshUI",
partial = "refreshPartial",
full = "refreshFull",
}
--[[
refresh mode comparision
will return the mode that takes precedence
--]]
local function update_mode(mode1, mode2)
if refresh_modes[mode1] > refresh_modes[mode2] then
return mode1
else
return mode2
end
end
--[[
enqueue a refresh
Widgets call this in their paintTo() method in order to notify
UIManager that a certain part of the screen is to be refreshed.
mode: refresh mode ("full", "partial", "ui", "fast")
region: Rect() that specifies the region to be updated
optional, update will affect whole screen if not specified.
Note that this should be the exception.
--]]
function UIManager:_refresh(mode, region)
-- default mode is partial
mode = mode or "partial"
-- special case: full screen partial update
-- will get promoted every self.FULL_REFRESH_COUNT updates
if not region and mode == "partial" then
self.refresh_count = (self.refresh_count + 1) % self.FULL_REFRESH_COUNT
if self.refresh_count == self.FULL_REFRESH_COUNT - 1 then
DEBUG("promote refresh to full refresh")
mode = "full"
end
end
-- if no region is specified, define default region
region = region or Geom:new{w=Screen:getWidth(), h=Screen:getHeight()}
for i = 1, #self._refresh_stack do
-- check for collision with updates that are already enqueued
if region:intersectWith(self._refresh_stack[i].region) then
-- combine both refreshes' regions
local combined = region:combine(self._refresh_stack[i].region)
-- update the mode, if needed
local mode = update_mode(mode, self._refresh_stack[i].mode)
-- remove colliding update
table.remove(self._refresh_stack, i)
-- and try again with combined data
return self:_refresh(mode, combined)
end
end
-- if we hit no (more) collides, enqueue the update
table.insert(self._refresh_stack, {mode = mode, region = region})
end
-- repaint dirty widgets -- repaint dirty widgets
function UIManager:repaint() function UIManager:_repaint()
-- flag in which we will record if we did any repaints at all -- flag in which we will record if we did any repaints at all
-- will trigger a refresh if set. -- will trigger a refresh if set.
local dirty = false local dirty = false
-- we use this to record requests for certain refresh types
-- TODO: fix this, see below
local force_full_refresh = self.full_refresh
self.full_refresh = false
local force_partial_refresh = self.partial_refresh
self.partial_refresh = false
local force_fast_refresh = false
for _, widget in ipairs(self._window_stack) do for _, widget in ipairs(self._window_stack) do
-- paint if repaint_all is request -- paint if current widget or any widget underneath is dirty
-- paint also if current widget or any widget underneath is dirty if dirty or self._dirty[widget.widget] then
if self.repaint_all or dirty or self._dirty[widget.widget] then -- pass hint to widget that we got when setting widget dirty
widget.widget:paintTo(Screen.bb, widget.x, widget.y) -- the widget can use this to decide which parts should be refreshed
widget.widget:paintTo(Screen.bb, widget.x, widget.y, self._dirty[widget.widget])
-- self._dirty[widget.widget] may also be "auto"
if self._dirty[widget.widget] == "full" then
force_full_refresh = true
elseif self._dirty[widget.widget] == "partial" then
force_partial_refresh = true
elseif self._dirty[widget.widget] == "fast" then
force_fast_refresh = true
end
-- and remove from list after painting -- and remove from list after painting
self._dirty[widget.widget] = nil self._dirty[widget.widget] = nil
@ -324,42 +398,30 @@ function UIManager:repaint()
dirty = true dirty = true
end end
end end
self.repaint_all = false
if dirty then -- execute pending refresh functions
-- select proper refresh mode for _, refreshfunc in ipairs(self._refresh_func_stack) do
-- TODO: fix this. We should probably do separate refreshes local refreshtype, region = refreshfunc()
-- by regional refreshes (e.g. fast refresh, some partial refreshes) if refreshtype then self:_refresh(refreshtype, region) end
-- and full-screen full refresh end
local refresh self._refresh_func_stack = {}
if force_fast_refresh then -- we should have at least one refresh if we did repaint.
refresh = Screen.refreshFast -- If we don't, we add one now and print a warning if we
elseif force_partial_refresh then -- are debugging
refresh = Screen.refreshPartial if dirty and #self._refresh_stack == 0 then
elseif force_full_refresh or self.refresh_count == self.FULL_REFRESH_COUNT - 1 then DEBUG("WARNING: no refresh got enqueued. Will do a partial full screen refresh, which might be inefficient")
refresh = Screen.refreshFull self:_refresh("partial")
-- a full refresh will reset the counter which leads to an automatic full refresh end
self.refresh_count = 0
else
-- default
refresh = Screen.refreshPartial
-- increment refresh counter in this case
self.refresh_count = (self.refresh_count + 1) % self.FULL_REFRESH_COUNT
end
if self.update_regions_func then -- execute refreshes:
local update_regions = self.update_regions_func() for _, refresh in ipairs(self._refresh_stack) do
for _, update_region in ipairs(update_regions) do DEBUG("triggering refresh", refresh)
-- in some rare cases update region has 1 pixel offset Screen[refresh_methods[refresh.mode]](Screen,
refresh(Screen, update_region.x-1, update_region.y-1, refresh.region.x - 1, refresh.region.y - 1,
update_region.w+2, update_region.h+2) refresh.region.w + 2, refresh.region.h + 2)
end
self.update_regions_func = nil
else
refresh(Screen)
end
end end
self._refresh_stack = {}
end end
-- this is the main loop of the UI controller -- this is the main loop of the UI controller
@ -373,7 +435,7 @@ function UIManager:run()
-- that will be honored when calculating the time to wait -- that will be honored when calculating the time to wait
-- for input events: -- for input events:
repeat repeat
wait_until, now = self:checkTasks() wait_until, now = self:_checkTasks()
--DEBUG("---------------------------------------------------") --DEBUG("---------------------------------------------------")
--DEBUG("exec stack", self._execution_stack) --DEBUG("exec stack", self._execution_stack)
@ -388,7 +450,7 @@ function UIManager:run()
return nil return nil
end end
self:repaint() self:_repaint()
until not self._execution_stack_dirty until not self._execution_stack_dirty
-- wait for next event -- wait for next event
@ -431,72 +493,6 @@ function UIManager:run()
end end
end end
function UIManager:getRefreshMenuTable()
local function custom_1() return G_reader_settings:readSetting("refresh_rate_1") or 12 end
local function custom_2() return G_reader_settings:readSetting("refresh_rate_2") or 22 end
local function custom_3() return G_reader_settings:readSetting("refresh_rate_3") or 99 end
local function custom_input(name)
return {
title = _("Input page number for a full refresh"),
type = "number",
hint = "(1 - 99)",
callback = function(input)
local rate = tonumber(input)
G_reader_settings:saveSetting(name, rate)
UIManager:setRefreshRate(rate)
end,
}
end
return {
text = _("E-ink full refresh rate"),
sub_item_table = {
{
text = _("Every page"),
checked_func = function() return UIManager:getRefreshRate() == 1 end,
callback = function() UIManager:setRefreshRate(1) end,
},
{
text = _("Every 6 pages"),
checked_func = function() return UIManager:getRefreshRate() == 6 end,
callback = function() UIManager:setRefreshRate(6) end,
},
{
text_func = function()
return util.template(
_("Custom 1: %1 pages"),
custom_1()
)
end,
checked_func = function() return UIManager:getRefreshRate() == custom_1() end,
callback = function() UIManager:setRefreshRate(custom_1()) end,
hold_input = custom_input("refresh_rate_1")
},
{
text_func = function()
return util.template(
_("Custom 2: %1 pages"),
custom_2()
)
end,
checked_func = function() return UIManager:getRefreshRate() == custom_2() end,
callback = function() UIManager:setRefreshRate(custom_2()) end,
hold_input = custom_input("refresh_rate_2")
},
{
text_func = function()
return util.template(
_("Custom 3: %1 pages"),
custom_3()
)
end,
checked_func = function() return UIManager:getRefreshRate() == custom_3() end,
callback = function() UIManager:setRefreshRate(custom_3()) end,
hold_input = custom_input("refresh_rate_3")
},
}
}
end
UIManager:init() UIManager:init()
return UIManager return UIManager

@ -190,7 +190,7 @@ function BBoxWidget:adjustScreenBBox(ges, relative)
y1 = Math.round(bottom_right.y) y1 = Math.round(bottom_right.y)
} }
UIManager.repaint_all = true UIManager:setDirty("all")
end end
function BBoxWidget:getModifiedPageBBox() function BBoxWidget:getModifiedPageBBox()

@ -154,16 +154,16 @@ function Button:onTapSelectButton()
if self.enabled and self.callback then if self.enabled and self.callback then
UIManager:scheduleIn(0.0, function() UIManager:scheduleIn(0.0, function()
self[1].invert = true self[1].invert = true
UIManager.update_regions_func = function() UIManager:setDirty(self.show_parent, function()
return {self[1].dimen} return "partial", self[1].dimen
end end)
UIManager.repaint_all = true -- FIXME: Why?
UIManager:setDirty(self.show_parent, "partial")
end) end)
UIManager:scheduleIn(0.1, function() UIManager:scheduleIn(0.1, function()
self.callback() self.callback()
self[1].invert = false self[1].invert = false
UIManager:setDirty(self.show_parent, "partial") UIManager:setDirty(self.show_parent, function()
return "partial", self[1].dimen
end)
end) end)
end end
return true return true

@ -70,10 +70,9 @@ function OptionTextItem:onTapSelect()
self.config:onConfigChoose(self.values, self.name, self.config:onConfigChoose(self.values, self.name,
self.event, self.args, self.event, self.args,
self.events, self.current_item) self.events, self.current_item)
UIManager.update_regions_func = function() UIManager:setDirty(self.config, function()
return {self[1].dimen} return "partial", self[1].dimen
end end)
UIManager:setDirty(self.config, "partial")
return true return true
end end
@ -125,10 +124,9 @@ function OptionIconItem:onTapSelect()
self.config:onConfigChoose(self.values, self.name, self.config:onConfigChoose(self.values, self.name,
self.event, self.args, self.event, self.args,
self.events, self.current_item) self.events, self.current_item)
UIManager.update_regions_func = function() UIManager:setDirty(self.config, function()
return {self[1].dimen} return "partial", self[1].dimen
end end)
UIManager:setDirty(self.config, "partial")
return true return true
end end
@ -524,8 +522,14 @@ end
function ConfigDialog:onShowConfigPanel(index) function ConfigDialog:onShowConfigPanel(index)
self.panel_index = index self.panel_index = index
local old_dimen = self.dialog_frame.dimen and self.dialog_frame.dimen:copy()
self:update() self:update()
UIManager.repaint_all = true UIManager:setDirty("all", function()
local refresh_dimen =
old_dimen and old_dimen:combine(self.dialog_frame.dimen)
or self.dialog_frame.dimen
return "partial", refresh_dimen
end)
return true return true
end end
@ -563,7 +567,7 @@ function ConfigDialog:onConfigChoose(values, name, event, args, events, position
if events then if events then
self:onConfigEvents(events, position) self:onConfigEvents(events, position)
end end
UIManager.repaint_all = true UIManager:setDirty("all")
end) end)
end end

@ -256,8 +256,7 @@ function DictQuickLookup:update()
self.dict_frame, self.dict_frame,
} }
} }
UIManager.repaint_all = true UIManager:setDirty("all", "partial")
UIManager.partial_refresh = true
end end
function DictQuickLookup:isPrevDictAvaiable() function DictQuickLookup:isPrevDictAvaiable()

@ -80,6 +80,7 @@ function FocusManager:onFocusMove(args)
current_item:handleEvent(Event:new("Unfocus")) current_item:handleEvent(Event:new("Unfocus"))
self.layout[self.selected.y][self.selected.x]:handleEvent(Event:new("Focus")) self.layout[self.selected.y][self.selected.x]:handleEvent(Event:new("Focus"))
-- trigger a repaint (we need to be the registered widget!) -- trigger a repaint (we need to be the registered widget!)
-- TODO: is this really needed?
UIManager:setDirty(self.show_parent or self, "partial") UIManager:setDirty(self.show_parent or self, "partial")
break break
end end

@ -43,16 +43,17 @@ end
function IconButton:onTapClickButton() function IconButton:onTapClickButton()
UIManager:scheduleIn(0.0, function() UIManager:scheduleIn(0.0, function()
self.image.invert = true self.image.invert = true
UIManager.update_regions_func = function() UIManager:setDirty(self.show_parent, function()
return {self[1].dimen} return "partial", self[1].dimen
end end)
UIManager:setDirty(self.show_parent, "partial")
end) end)
-- make sure button reacts before doing callback -- make sure button reacts before doing callback
UIManager:scheduleIn(0.1, function() UIManager:scheduleIn(0.1, function()
self.callback() self.callback()
self.image.invert = false self.image.invert = false
UIManager:setDirty(self.show_parent, "partial") UIManager:setDirty(self.show_parent, function()
return "partial", self[1].dimen
end)
end) end)
return true return true
end end

@ -116,8 +116,8 @@ function InputDialog:init()
}, },
self.dialog_frame, self.dialog_frame,
} }
UIManager.repaint_all = true -- do a full refresh - is this really needed?
UIManager.full_refresh = true UIManager:setDirty("all", "full")
end end
function InputDialog:onShowKeyboard() function InputDialog:onShowKeyboard()

@ -154,7 +154,9 @@ function InputText:addChar(char)
table.insert(self.charlist, self.charpos, char) table.insert(self.charlist, self.charpos, char)
self.charpos = self.charpos + 1 self.charpos = self.charpos + 1
self:initTextBox(table.concat(self.charlist)) self:initTextBox(table.concat(self.charlist))
UIManager:setDirty(self.parent, "partial") UIManager:setDirty(self.parent, function()
return "ui", self.dimen
end)
end end
function InputText:delChar() function InputText:delChar()
@ -162,12 +164,14 @@ function InputText:delChar()
self.charpos = self.charpos - 1 self.charpos = self.charpos - 1
table.remove(self.charlist, self.charpos) table.remove(self.charlist, self.charpos)
self:initTextBox(table.concat(self.charlist)) self:initTextBox(table.concat(self.charlist))
UIManager:setDirty(self.parent, "partial") UIManager:setDirty(self.parent, "ui")
end end
function InputText:clear() function InputText:clear()
self:initTextBox("") self:initTextBox("")
UIManager:setDirty(self.parent, "partial") UIManager:setDirty(self.parent, function()
return "ui", self.dimen
end)
end end
function InputText:getText() function InputText:getText()
@ -176,7 +180,9 @@ end
function InputText:setText(text) function InputText:setText(text)
self:initTextBox(text) self:initTextBox(text)
UIManager:setDirty(self.parent, "partial") UIManager:setDirty(self.parent, function()
return "partial", self.dimen
end)
end end
return InputText return InputText

@ -87,8 +87,7 @@ function LoginDialog:init()
}, },
self.dialog_frame, self.dialog_frame,
} }
UIManager.repaint_all = true UIManager:setDirty("all", "full")
UIManager.full_refresh = true
end end
function LoginDialog:getCredential() function LoginDialog:getCredential()

@ -283,6 +283,7 @@ end
function MenuItem:onTapSelect(arg, ges) function MenuItem:onTapSelect(arg, ges)
local pos = self:getGesPosition(ges) local pos = self:getGesPosition(ges)
self[1].invert = true self[1].invert = true
-- TODO: regional refresh
UIManager:setDirty(self.show_parent, "partial") UIManager:setDirty(self.show_parent, "partial")
UIManager:scheduleIn(0.1, function() UIManager:scheduleIn(0.1, function()
self[1].invert = false self[1].invert = false
@ -295,6 +296,7 @@ end
function MenuItem:onHoldSelect(arg, ges) function MenuItem:onHoldSelect(arg, ges)
local pos = self:getGesPosition(ges) local pos = self:getGesPosition(ges)
self[1].invert = true self[1].invert = true
-- TODO: regional refresh
UIManager:setDirty(self.show_parent, "partial") UIManager:setDirty(self.show_parent, "partial")
UIManager:scheduleIn(0.1, function() UIManager:scheduleIn(0.1, function()
self[1].invert = false self[1].invert = false
@ -574,6 +576,7 @@ function Menu:init()
end end
function Menu:updateItems(select_number) function Menu:updateItems(select_number)
local old_dimen = self.dimen and self.dimen:copy()
-- self.layout must be updated for focusmanager -- self.layout must be updated for focusmanager
self.layout = {} self.layout = {}
self.item_group:clear() self.item_group:clear()
@ -648,9 +651,12 @@ function Menu:updateItems(select_number)
self.page_info_text.text = _("no choices available") self.page_info_text.text = _("no choices available")
end end
-- nicolua UIManager:setDirty("all", function()
-- FIXME: dirty hack to clear previous menus local refresh_dimen =
UIManager:setDirty(self.show_parent or self) old_dimen and old_dimen:combine(self.dimen)
or self.dimen
return "partial", refresh_dimen
end)
end end
--[[ --[[

@ -79,8 +79,7 @@ function MultiInputDialog:init()
}, },
self.dialog_frame, self.dialog_frame,
} }
UIManager.repaint_all = true UIManager:setDirty("all", "full")
UIManager.full_refresh = true
end end
function MultiInputDialog:getFields() function MultiInputDialog:getFields()

@ -77,10 +77,9 @@ function ScrollTextWidget:onScrollText(arg, ges)
self.text_widget:scrollUp() self.text_widget:scrollUp()
self:updateScrollBar(self.text_widget) self:updateScrollBar(self.text_widget)
end end
UIManager.update_regions_func = function() UIManager:setDirty(self.dialog, function()
return {self.dimen} return "partial", self.dimen
end end)
UIManager:setDirty(self.dialog, "partial")
end end
return ScrollTextWidget return ScrollTextWidget

@ -144,10 +144,9 @@ function ToggleSwitch:onTapSelect(arg, gev)
--]] --]]
self.config:onConfigChoose(self.values, self.name, self.config:onConfigChoose(self.values, self.name,
self.event, self.args, self.events, self.position) self.event, self.args, self.events, self.position)
UIManager.update_regions_func = function() UIManager:setDirty(self.config, function()
return {self.dimen} return "partial", self.dimen
end end)
UIManager:setDirty(self.config, "partial")
return true return true
end end

@ -98,17 +98,18 @@ function TouchMenuItem:onTapSelect(arg, ges)
UIManager:scheduleIn(0.0, function() UIManager:scheduleIn(0.0, function()
self.item_frame.invert = true self.item_frame.invert = true
UIManager.update_regions_func = function() UIManager:setDirty(self.show_parent, function()
return {self.dimen} return "partial", self.dimen
end end)
UIManager:setDirty(self.show_parent, "partial")
end) end)
UIManager:scheduleIn(0.1, function() UIManager:scheduleIn(0.1, function()
self.menu:onMenuSelect(self.item) self.menu:onMenuSelect(self.item)
end) end)
UIManager:scheduleIn(0.5, function() UIManager:scheduleIn(0.5, function()
self.item_frame.invert = false self.item_frame.invert = false
UIManager:setDirty(self.show_parent, "partial") UIManager:setDirty(self.show_parent, function()
return "partial", self.dimen
end)
end) end)
return true return true
end end
@ -122,17 +123,18 @@ function TouchMenuItem:onHoldSelect(arg, ges)
UIManager:scheduleIn(0.0, function() UIManager:scheduleIn(0.0, function()
self.item_frame.invert = true self.item_frame.invert = true
UIManager.update_regions_func = function() UIManager:setDirty(self.show_parent, function()
return {self.dimen} return "partial", self.dimen
end end)
UIManager:setDirty(self.show_parent, "partial")
end) end)
UIManager:scheduleIn(0.1, function() UIManager:scheduleIn(0.1, function()
self.menu:onMenuHold(self.item) self.menu:onMenuHold(self.item)
end) end)
UIManager:scheduleIn(0.5, function() UIManager:scheduleIn(0.5, function()
self.item_frame.invert = false self.item_frame.invert = false
UIManager:setDirty(self.show_parent, "partial") UIManager:setDirty(self.show_parent, function()
return "partial", self.dimen
end)
end) end)
return true return true
end end
@ -406,6 +408,7 @@ function TouchMenu:_recalculateDimen()
end end
function TouchMenu:updateItems() function TouchMenu:updateItems()
local old_dimen = self.dimen and self.dimen:copy()
self:_recalculateDimen() self:_recalculateDimen()
self.item_group:clear() self.item_group:clear()
table.insert(self.item_group, self.bar) table.insert(self.item_group, self.bar)
@ -458,9 +461,13 @@ function TouchMenu:updateItems()
self.page_info_left_chev:enableDisable(self.page > 1) self.page_info_left_chev:enableDisable(self.page > 1)
self.page_info_right_chev:enableDisable(self.page < self.page_num) self.page_info_right_chev:enableDisable(self.page < self.page_num)
self.time_info.text = os.date("%H:%M").." @ "..Device:getPowerDevice():getCapacity().."%" self.time_info.text = os.date("%H:%M").." @ "..Device:getPowerDevice():getCapacity().."%"
-- FIXME: this is a dirty hack to clear previous menus
-- refer to issue #664 (in kindlepdfviewer) UIManager:setDirty("all", function()
UIManager.repaint_all = true local refresh_dimen =
old_dimen and old_dimen:combine(self.dimen)
or self.dimen
return "partial", refresh_dimen
end)
end end
function TouchMenu:switchMenuTab(tab_num) function TouchMenu:switchMenuTab(tab_num)
@ -489,6 +496,8 @@ function TouchMenu:backToUpperMenu()
self.item_table = table.remove(self.item_table_stack) self.item_table = table.remove(self.item_table_stack)
self.page = 1 self.page = 1
self:updateItems() self:updateItems()
else
self:closeMenu()
end end
end end

@ -96,21 +96,22 @@ function VirtualKey:init()
end end
function VirtualKey:update_keyboard() function VirtualKey:update_keyboard()
UIManager.update_regions_func = function() UIManager:setDirty(self.keyboard, function()
DEBUG("update key region", self[1].dimen) DEBUG("update key region", self[1].dimen)
return {self[1].dimen} return "ui", self[1].dimen
end end)
UIManager:setDirty(self.keyboard, "partial")
end end
function VirtualKey:update_keyboard_inputbox() function VirtualKey:update_keyboard_inputbox()
local inputbox = self.keyboard.inputbox local inputbox = self.keyboard.inputbox
UIManager.update_regions_func = function() UIManager:setDirty(self.keyboard, function()
DEBUG("update keyboard and inputbox", self[1].dimen, inputbox.dimen) DEBUG("update inputbox", inputbox.dimen)
return {self[1].dimen, inputbox.dimen} return "ui", inputbox.dimen
end end)
UIManager:setDirty(inputbox, "partial") UIManager:setDirty(self.keyboard, function()
UIManager:setDirty(self.keyboard, "partial") DEBUG("update keyboard", self[1].dimen)
return "ui", self[1].dimen
end)
end end
function VirtualKey:onTapSelect() function VirtualKey:onTapSelect()
@ -318,8 +319,13 @@ function VirtualKeyboard:setLayout(key)
if self.utf8mode then self.umlautmode = false end if self.utf8mode then self.umlautmode = false end
end end
self:initLayout() self:initLayout()
UIManager.update_regions_func = nil UIManager:setDirty(self, function()
UIManager:setDirty(self, "partial") -- correct coordinates of keyboard
local dimen = self.dimen:copy()
dimen.y = Screen:getHeight() - dimen.h
DEBUG("update keyboard layout", dimen)
return "partial", dimen
end)
end end
function VirtualKeyboard:addChar(key) function VirtualKeyboard:addChar(key)

@ -0,0 +1,19 @@
./apps/reader/modules/readerfooter.lua: UIManager.update_regions_func = function()
./apps/reader/modules/readerhighlight.lua: UIManager.update_regions_func = function()
./ui/widget/button.lua: UIManager.update_regions_func = function()
./ui/widget/iconbutton.lua: UIManager.update_regions_func = function()
./ui/widget/dictquicklookup.lua: UIManager.update_regions_func = function()
./ui/widget/scrolltextwidget.lua: UIManager.update_regions_func = function()
./ui/widget/touchmenu.lua: UIManager.update_regions_func = function()
./ui/widget/touchmenu.lua: UIManager.update_regions_func = function()
./ui/widget/virtualkeyboard.lua: UIManager.update_regions_func = function()
./ui/widget/virtualkeyboard.lua: UIManager.update_regions_func = function()
./ui/widget/virtualkeyboard.lua: UIManager.update_regions_func = nil
./ui/widget/toggleswitch.lua: UIManager.update_regions_func = function()
./ui/widget/configdialog.lua: UIManager.update_regions_func = function()
./ui/widget/configdialog.lua: UIManager.update_regions_func = function()
./ui/uimanager.lua: update_regions_func = nil,
./ui/uimanager.lua: if self.update_regions_func then
./ui/uimanager.lua: local update_regions = self.update_regions_func()
./ui/uimanager.lua: for _, update_region in ipairs(update_regions) do
./ui/uimanager.lua: self.update_regions_func = nil
Loading…
Cancel
Save