Merge pull request #1217 from hwhw/master

Refactor refresh
pull/1240/head v2014.11.25-nightly
Huang Xin 10 years ago
commit 9ef2c91103

@ -1 +1 @@
Subproject commit 89a3711b68cbe5abffc91529d009e1e27c3a1c73
Subproject commit ffdcfc5e5d91f427002bbd0e51ece7e86cbf8ea1

@ -36,7 +36,7 @@ function FileManager:init()
face = Font:getFace("tfont", 24),
text = self.title,
},
VerticalSpan:new{ width = Screen:scaleByDPI(10) }
VerticalSpan:new{ width = Screen:scaleBySize(10) }
}
local g_show_hidden = G_reader_settings:readSetting("show_hidden")

@ -20,7 +20,7 @@ local PageCropDialog = VerticalGroup:new{
cancel_text = "Cancel",
ok_callback = function() end,
cancel_callback = function() end,
button_width = math.floor(Screen:scaleByDPI(70)),
button_width = math.floor(Screen:scaleBySize(70)),
}
function PageCropDialog:init()

@ -96,7 +96,7 @@ function ReaderDictionary:showDict(word, results, box)
word = word,
results = results,
dictionary = self.default_dictionary,
width = Screen:getWidth() - Screen:scaleByDPI(80),
width = Screen:getWidth() - Screen:scaleBySize(80),
word_box = box,
-- differentiate between dict and wiki
wiki = self.wiki,

@ -81,7 +81,7 @@ function ReaderFont:onReadSettings(config)
self.font_size = config:readSetting("font_size")
or DCREREADER_CONFIG_DEFAULT_FONT_SIZE or 22
self.ui.document:setFontSize(Screen:scaleByDPI(self.font_size))
self.ui.document:setFontSize(Screen:scaleBySize(self.font_size))
self.font_embolden = config:readSetting("font_embolden")
or G_reader_settings:readSetting("copt_font_weight") or 0
@ -149,7 +149,7 @@ function ReaderFont:onSetFontSize(new_size)
text = _("Set font size to ")..self.font_size,
timeout = 1,
})
self.ui.document:setFontSize(Screen:scaleByDPI(new_size))
self.ui.document:setFontSize(Screen:scaleBySize(new_size))
self.ui:handleEvent(Event:new("UpdatePos"))
return true

@ -27,9 +27,9 @@ local ReaderFooter = InputContainer:new{
progress_text = nil,
text_font_face = "ffont",
text_font_size = DMINIBAR_FONT_SIZE,
bar_height = Screen:scaleByDPI(DMINIBAR_HEIGHT),
height = Screen:scaleByDPI(DMINIBAR_CONTAINER_HEIGHT),
padding = Screen:scaleByDPI(10),
bar_height = Screen:scaleBySize(DMINIBAR_HEIGHT),
height = Screen:scaleBySize(DMINIBAR_CONTAINER_HEIGHT),
padding = Screen:scaleBySize(10),
}
function ReaderFooter:init()

@ -17,7 +17,7 @@ local ReaderPaging = InputContainer:new{
visible_area = nil,
page_area = nil,
show_overlap_enable = nil,
overlap = Screen:scaleByDPI(DOVERLAPPIXELS),
overlap = Screen:scaleBySize(DOVERLAPPIXELS),
page_flipping_mode = false,
bookmark_flipping_mode = false,

@ -20,14 +20,14 @@ function ReaderScreenshot:init()
TapDiagonal = {
GestureRange:new{
ges = "two_finger_tap",
scale = {diagonal - Screen:scaleByDPI(200), diagonal},
scale = {diagonal - Screen:scaleBySize(200), diagonal},
rate = 1.0,
}
},
SwipeDiagonal = {
GestureRange:new{
ges = "swipe",
scale = {diagonal - Screen:scaleByDPI(200), diagonal},
scale = {diagonal - Screen:scaleBySize(200), diagonal},
rate = 1.0,
}
},

@ -244,14 +244,14 @@ function ReaderToc:onShowToc()
-- update collapsible state
self.expand_button = Button:new{
icon = "resources/icons/appbar.control.expand.png",
width = Screen:scaleByDPI(30),
width = Screen:scaleBySize(30),
bordersize = 0,
show_parent = self,
}
self.collapse_button = Button:new{
icon = "resources/icons/appbar.control.collapse.png",
width = Screen:scaleByDPI(30),
width = Screen:scaleBySize(30),
bordersize = 0,
show_parent = self,
}

@ -157,10 +157,10 @@ function ReaderTypeset:makeDefaultFloatingPunctuation()
end
function ReaderTypeset:onSetPageMargins(margins)
local left = Screen:scaleByDPI(margins[1])
local top = Screen:scaleByDPI(margins[2])
local right = Screen:scaleByDPI(margins[3])
local bottom = Screen:scaleByDPI(margins[4])
local left = Screen:scaleBySize(margins[1])
local top = Screen:scaleBySize(margins[2])
local right = Screen:scaleBySize(margins[3])
local bottom = Screen:scaleBySize(margins[4])
self.ui.document:setPageMargins(left, top, right, bottom)
self.ui:handleEvent(Event:new("UpdatePos"))
return true

@ -41,8 +41,8 @@ local ReaderView = OverlapGroup:new{
page_states = {},
scroll_mode = "vertical",
page_gap = {
width = Screen:scaleByDPI(8),
height = Screen:scaleByDPI(8),
width = Screen:scaleBySize(8),
height = Screen:scaleBySize(8),
color = Blitbuffer.gray(0.5),
},
-- DjVu page rendering mode (used in djvu.c:drawPage())

@ -1,6 +1,7 @@
local Generic = require("device/generic/device")
local isAndroid, android = pcall(require, "android")
local ffi = require("ffi")
local DEBUG = require("dbg")
local function yes() return true end
@ -12,14 +13,19 @@ local Device = Generic:new{
}
function Device:init()
self.screen = require("device/screen"):new{device = self}
self.screen = require("ffi/framebuffer_android"):new{device = self}
self.powerd = require("device/android/powerd"):new{device = self}
self.input = require("device/input"):new{
device = self,
event_map = require("device/android/event_map"),
handleMiscEv = function(self, ev)
DEBUG("Android application event", ev.code)
if ev.code == ffi.C.APP_CMD_SAVE_STATE then
return "SaveState"
elseif ev.code == ffi.C.APP_CMD_GAINED_FOCUS then
self.device.screen:refreshFull()
elseif ev.code == ffi.C.APP_CMD_WINDOW_REDRAW_NEEDED then
self.device.screen:refreshFull()
end
end,
}
@ -37,7 +43,7 @@ function Device:init()
self.isTouchDevice = yes
end
Generic:init()
Generic.init(self)
end
return Device

@ -13,13 +13,19 @@ local Device = Generic:new{
}
function Device:init()
self.screen = require("device/screen"):new{device = self}
self.input = require("device/input"):new{
device = self,
event_map = util.haveSDL2()
and require("device/emulator/event_map_sdl2")
or require("device/emulator/event_map_sdl"),
}
if util.haveSDL2() then
self.screen = require("ffi/framebuffer_SDL2_0"):new{device = self}
self.input = require("device/input"):new{
device = self,
event_map = require("device/emulator/event_map_sdl2"),
}
else
self.screen = require("ffi/framebuffer_SDL1_2"):new{device = self}
self.input = require("device/input"):new{
device = self,
event_map = require("device/emulator/event_map_sdl"),
}
end
Generic.init(self)
end

@ -40,8 +40,10 @@ end
function Device:init()
if not self.screen then
self.screen = require("device/screen"):new{device = self}
error("screen/framebuffer must be implemented")
end
self.screen.debug = DEBUG
if not self.input then
self.input = require("device/input"):new{device = self}
end

@ -69,7 +69,7 @@ local KindleVoyage = Kindle:new{
}
function Kindle2:init()
self.screen = require("device/screen"):new{device = self}
self.screen = require("ffi/framebuffer_einkfb"):new{device = self}
self.input = require("device/input"):new{
device = self,
event_map = require("device/kindle/event_map_keyboard"),
@ -79,7 +79,7 @@ function Kindle2:init()
end
function KindleDXG:init()
self.screen = require("device/screen"):new{device = self}
self.screen = require("ffi/framebuffer_einkfb"):new{device = self}
self.input = require("device/input"):new{
device = self,
event_map = require("device/kindle/event_map_keyboard"),
@ -90,7 +90,7 @@ function KindleDXG:init()
end
function Kindle3:init()
self.screen = require("device/screen"):new{device = self}
self.screen = require("ffi/framebuffer_einkfb"):new{device = self}
self.input = require("device/input"):new{
device = self,
event_map = require("device/kindle/event_map_keyboard"),
@ -101,7 +101,7 @@ function Kindle3:init()
end
function Kindle4:init()
self.screen = require("device/screen"):new{device = self}
self.screen = require("ffi/framebuffer_einkfb"):new{device = self}
self.input = require("device/input"):new{
device = self,
event_map = require("device/kindle/event_map_kindle4"),
@ -114,7 +114,7 @@ end
local ABS_MT_POSITION_X = 53
local ABS_MT_POSITION_Y = 54
function KindleTouch:init()
self.screen = require("device/screen"):new{device = self}
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self}
self.powerd = require("device/kindle/powerd"):new{
device = self,
batt_capacity_file = "/sys/devices/system/yoshi_battery/yoshi_battery0/battery_capacity",
@ -138,7 +138,7 @@ function KindleTouch:init()
end
function KindlePaperWhite:init()
self.screen = require("device/screen"):new{device = self}
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self}
self.powerd = require("device/kindle/powerd"):new{
device = self,
fl_intensity_file = "/sys/devices/system/fl_tps6116x/fl_tps6116x0/fl_intensity",
@ -153,7 +153,7 @@ function KindlePaperWhite:init()
end
function KindlePaperWhite2:init()
self.screen = require("device/screen"):new{device = self}
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self}
self.powerd = require("device/kindle/powerd"):new{
device = self,
fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness",
@ -168,7 +168,7 @@ function KindlePaperWhite2:init()
end
function KindleBasic:init()
self.screen = require("device/screen"):new{device = self}
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self}
self.powerd = require("device/kindle/powerd"):new{
device = self,
batt_capacity_file = "/sys/devices/system/wario_battery/wario_battery0/battery_capacity",
@ -183,7 +183,7 @@ function KindleBasic:init()
end
function KindleVoyage:init()
self.screen = require("device/screen"):new{device = self}
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self}
self.powerd = require("device/kindle/powerd"):new{
device = self,
fl_intensity_file = "/sys/class/backlight/max77696-bl/brightness",

@ -58,7 +58,7 @@ local KoboPhoenix = Kobo:new{
}
function Kobo:init()
self.screen = require("device/screen"):new{device = self}
self.screen = require("ffi/framebuffer_mxcfb"):new{device = self}
self.powerd = require("device/kobo/powerd"):new{device = self}
self.input = require("device/input"):new{
device = self,

@ -1,246 +0,0 @@
local Blitbuffer = require("ffi/blitbuffer")
local einkfb = require("ffi/framebuffer")
local Geom = require("ui/geometry")
local util = require("ffi/util")
local DEBUG = require("dbg")
--[[
Codes for rotation modes:
1 for no rotation,
2 for landscape with bottom on the right side of screen, etc.
2
+--------------+
| +----------+ |
| | | |
| | Freedom! | |
| | | |
| | | |
3 | | | | 1
| | | |
| | | |
| +----------+ |
| |
| |
+--------------+
0
--]]
local Screen = {
cur_rotation_mode = 0,
native_rotation_mode = nil,
blitbuffer_rotation_mode = 0,
bb = nil,
saved_bb = nil,
screen_size = Geom:new(),
viewport = nil,
fb = einkfb.open("/dev/fb0"),
-- will be set upon loading by Device class:
device = nil,
}
function Screen:new(o)
local o = o or {}
setmetatable(o, self)
self.__index = self
if o.init then o:init() end
return o
end
function Screen:init()
self.bb = self.fb.bb
self.blitbuffer_rotation_mode = self.bb:getRotation()
-- asking the framebuffer for orientation is error prone,
-- so we do this simple heuristic (for now)
self.screen_size.w = self.bb:getWidth()
self.screen_size.h = self.bb:getHeight()
if self.screen_size.w > self.screen_size.h then
self.native_rotation_mode = 1
self.screen_size.w, self.screen_size.h = self.screen_size.h, self.screen_size.w
else
self.native_rotation_mode = 0
end
self.cur_rotation_mode = self.native_rotation_mode
end
--[[
set a rectangle that represents the area of the screen we are working on
--]]
function Screen:setViewport(viewport)
self.viewport = self.screen_size:intersect(viewport)
self.bb = self.fb.bb:viewport(
self.viewport.x, self.viewport.y,
self.viewport.w, self.viewport.h)
end
function Screen:refresh(refresh_type, waveform_mode, wait_for_marker, x, y, w, h)
if self.viewport and x and y then
--[[
we need to adapt the coordinates when we have a viewport.
this adaptation depends on the rotation:
0,0 fb.w
+---+---------------------------+---+
| |v.y v.y| |
|v.x| |vx2|
+---+---------------------------+---+
| | v.w | |
| | | |
| | | |
| |v.h (viewport) | |
| | | | fb.h
| | | |
| | | |
| | | |
+---+---------------------------+---+
|v.x| |vx2|
| |vy2 vy2| |
+---+---------------------------+---+
The viewport offset v.y/v.x only applies when rotation is 0 degrees.
For other rotations (0,0 is in one of the other edges), we need to
recalculate the offsets.
--]]
local vx2 = self.screen_size.w - (self.viewport.x + self.viewport.w)
local vy2 = self.screen_size.h - (self.viewport.y + self.viewport.h)
if self.cur_rotation_mode == 0 then
-- (0,0) is at top left of screen
x = x + self.viewport.x
y = y + self.viewport.y
elseif self.cur_rotation_mode == 1 then
-- (0,0) is at bottom left of screen
x = x + vy2
y = y + self.viewport.x
elseif self.cur_rotation_mode == 2 then
-- (0,0) is at bottom right of screen
x = x + vx2
y = y + vy2
else
-- (0,0) is at top right of screen
x = x + self.viewport.y
y = y + vx2
end
end
self.fb:refresh(refresh_type, waveform_mode, wait_for_marker, x, y, w, h)
end
function Screen:getSize()
return Geom:new{w = self.bb:getWidth(), h = self.bb:getHeight()}
end
function Screen:getWidth()
return self.bb:getWidth()
end
function Screen:getScreenWidth()
return self.screen_size.w
end
function Screen:getScreenHeight()
return self.screen_size.h
end
function Screen:getHeight()
return self.bb:getHeight()
end
function Screen:getDPI()
if self.dpi == nil then
self.dpi = G_reader_settings:readSetting("screen_dpi")
end
if self.dpi == nil then
self.dpi = self.device.display_dpi
end
if self.dpi == nil then
self.dpi = 160
end
return self.dpi
end
function Screen:setDPI(dpi)
G_reader_settings:saveSetting("screen_dpi", dpi)
end
function Screen:scaleByDPI(px)
local dpi = self:getDPI()
-- larger screen needs larger scale
local size_scale = math.min(self:getWidth(), self:getHeight())/dpi/3.6
-- scaled positive px should also be positive
return math.ceil(px * size_scale * dpi/167)
end
function Screen:getRotationMode()
return self.cur_rotation_mode
end
function Screen:getScreenMode()
if self:getWidth() > self:getHeight() then
return "landscape"
else
return "portrait"
end
end
function Screen:setRotationMode(mode)
self.bb:rotateAbsolute(-90 * (mode - self.native_rotation_mode - self.blitbuffer_rotation_mode))
if self.viewport then
self.fb.bb:setRotation(self.bb:getRotation())
end
self.cur_rotation_mode = mode
end
function Screen:setScreenMode(mode)
if mode == "portrait" then
if self.cur_rotation_mode ~= 0 then
self:setRotationMode(0)
end
elseif mode == "landscape" then
if self.cur_rotation_mode == 0 or self.cur_rotation_mode == 2 then
self:setRotationMode(DLANDSCAPE_CLOCKWISE_ROTATION and 1 or 3)
elseif self.cur_rotation_mode == 1 or self.cur_rotation_mode == 3 then
self:setRotationMode((self.cur_rotation_mode + 2) % 4)
end
end
end
function Screen:toggleNightMode()
self.bb:invert()
if self.viewport then
-- invert and blank out the full framebuffer when we are working on a viewport
self.fb.bb:invert()
self.fb.bb:fill(Blitbuffer.COLOR_WHITE)
end
end
function Screen:saveCurrentBB()
if self.saved_bb then self.saved_bb:free() end
self.saved_bb = self.bb:copy()
end
function Screen:restoreFromSavedBB()
if self.saved_bb then
self.bb:blitFullFrom(self.saved_bb)
-- free data
self.saved_bb:free()
self.saved_bb = nil
end
end
function Screen:shot(filename)
DEBUG("write PNG file", filename)
self.bb:writePNG(filename)
end
function Screen:close()
DEBUG("close screen framebuffer")
self.fb:close()
end
return Screen

@ -919,10 +919,10 @@ function KoptInterface:getLinkFromPosition(doc, pageno, pos)
local link = page_links[i]
-- enlarge tappable link box
local lbox = Geom:new{
x = link.x0 - Screen:scaleByDPI(5),
y = link.y0 - Screen:scaleByDPI(5),
w = link.x1 - link.x0 + Screen:scaleByDPI(10),
h = link.y1 - link.y0 + Screen:scaleByDPI(10)
x = link.x0 - Screen:scaleBySize(5),
y = link.y0 - Screen:scaleBySize(5),
w = link.x1 - link.x0 + Screen:scaleBySize(10),
h = link.y1 - link.y0 + Screen:scaleBySize(10)
}
if inside_box(pos, lbox) and link.page then
return link, lbox

@ -56,7 +56,7 @@ function Font:getFace(font, size)
-- original size before scaling by screen DPI
local orig_size = size
local size = Screen:scaleByDPI(size)
local size = Screen:scaleBySize(size)
local face = self.faces[font..size]
-- build face if not found

@ -6,52 +6,8 @@ local util = require("ffi/util")
local DEBUG = require("dbg")
local _ = require("gettext")
-- cf. koreader-base/ffi-cdecl/include/mxcfb-kindle.h (UPDATE_MODE_* applies to Kobo, too)
local UPDATE_MODE_PARTIAL = 0x0
local UPDATE_MODE_FULL = 0x1
-- Kindle waveform update modes
local WAVEFORM_MODE_INIT = 0x0 -- Screen goes to white (clears)
local WAVEFORM_MODE_DU = 0x1 -- Grey->white/grey->black
local WAVEFORM_MODE_GC16 = 0x2 -- High fidelity (flashing)
local WAVEFORM_MODE_GC4 = WAVEFORM_MODE_GC16 -- For compatibility
local WAVEFORM_MODE_GC16_FAST = 0x3 -- Medium fidelity
local WAVEFORM_MODE_A2 = 0x4 -- Faster but even lower fidelity
local WAVEFORM_MODE_GL16 = 0x5 -- High fidelity from white transition
local WAVEFORM_MODE_GL16_FAST = 0x6 -- Medium fidelity from white transition
-- Kindle FW >= 5.3
local WAVEFORM_MODE_DU4 = 0x7 -- Medium fidelity 4 level of gray direct update
-- Kindle PW2
local WAVEFORM_MODE_REAGL = 0x8 -- Ghost compensation waveform
local WAVEFORM_MODE_REAGLD = 0x9 -- Ghost compensation waveform with dithering
-- Kindle Basic/Kindle Voyage
local WAVEFORM_MODE_GL4 = 0xA -- 2-bit from white transition
-- TODO: Use me in night mode on those devices?
local WAVEFORM_MODE_GL16_INV = 0xB -- High fidelity for black transition
-- Kobo waveform update modes
local NTX_WFM_MODE_INIT = 0x0 -- WAVEFORM_MODE_INIT
local NTX_WFM_MODE_DU = 0x1 -- WAVEFORM_MODE_DU
local NTX_WFM_MODE_GC16 = 0x2 -- WAVEFORM_MODE_GC16
local NTX_WFM_MODE_GC4 = 0x3 -- WAVEFORM_MODE_GC4
local NTX_WFM_MODE_A2 = 0x4 -- WAVEFORM_MODE_A2
local NTX_WFM_MODE_GL16 = 0x5 -- WAVEFORM_MODE_GL16
local NTX_WFM_MODE_GLR16 = 0x6 -- WAVEFORM_MODE_REAGL
local NTX_WFM_MODE_GLD16 = 0x7 -- WAVEFORM_MODE_REAGLD
-- Common
local WAVEFORM_MODE_AUTO = 0x101
-- there is only one instance of this
local UIManager = {
default_refresh_type = UPDATE_MODE_PARTIAL,
default_waveform_mode = WAVEFORM_MODE_GC16, -- high fidelity waveform
fast_waveform_mode = WAVEFORM_MODE_A2,
full_refresh_waveform_mode = WAVEFORM_MODE_GC16,
partial_refresh_waveform_mode = WAVEFORM_MODE_GC16,
wait_for_every_marker = false,
wait_for_ui_markers = false,
-- force to repaint all the widget is stack, will be reset to false
-- after each ui loop
repaint_all = false,
@ -114,29 +70,6 @@ function UIManager:init()
if KOBO_LIGHT_ON_START and tonumber(KOBO_LIGHT_ON_START) > -1 then
Device:getPowerDevice():setIntensity( math.max( math.min(KOBO_LIGHT_ON_START,100) ,0) )
end
-- Emulate the stock reader's refresh behavior...
self.full_refresh_waveform_mode = NTX_WFM_MODE_GC16
-- Request REAGLD waveform mode on devices that support it (Aura & H2O)
if Device.model == "Kobo_phoenix" or Device.model == "Kobo_dahlia" then
self.partial_refresh_waveform_mode = NTX_WFM_MODE_GLD16
-- Since Kobo doesn't have MXCFB_WAIT_FOR_UPDATE_SUBMISSION, enabling this currently has no effect :).
self.wait_for_every_marker = true
-- NOTE: The H2O appears to be the odd duck out... Nickel uses AUTO for PARTIAL updates instead of asking for REAGLD specifically...
-- If we try to ask for FULL REAGLD updates, like on the Aura and the PW2, we get a black flash!
-- The driver appears to be using some custom Kobo logic (that they only enable in their producttion build?) altering the behavior of AUTO to favor REAGL modes...
-- Long story short: do the same as nickel: use AUTO, and hope for the best...
if Device.model == "Kobo_dahlia" then
self.partial_refresh_waveform_mode = WAVEFORM_MODE_AUTO
end
else
-- Let the driver handle it on those models (asking for NTX_WFM_MODE_GL16 appears to be a very bad idea, #1146)
self.partial_refresh_waveform_mode = WAVEFORM_MODE_AUTO
self.wait_for_every_marker = false
-- NOTE: Let's see if a bit of waiting works around potential timing issues on Kobos when doing *UI* refreshes in fast succession. (Not a concern on Kindle, where we have MXCFB_WAIT_FOR_UPDATE_SUBMISSION).
self.wait_for_ui_markers = true
end
-- Let the driver decide what to do with PARTIAL UI updates...
self.default_waveform_mode = WAVEFORM_MODE_AUTO
elseif Device:isKindle() then
self.event_handlers["IntoSS"] = function()
self:sendEvent(Event:new("FlushSettings"))
@ -153,35 +86,6 @@ function UIManager:init()
Device:usbPlugOut()
self:sendEvent(Event:new("NotCharging"))
end
-- Emulate the stock reader's refresh behavior...
--[[
NOTE: For ref, on a Touch (debugPaint & a patched strace are your friend!):
UI: flash: GC16_FAST, non-flash: AUTO (prefers GC16_FAST)
Reader: When flash: if to/from img: GC16, else GC16_FAST; when non-flash: AUTO (seems to prefer GL16_FAST); Waiting for marker only on flash
On a PW2:
UI: flash: GC16_FAST, non-flash: AUTO (prefers GC16_FAST)
Reader: When flash: if to/from img: GC16, else GC16_FAST; when non-flash: REAGL (w/ UPDATE_MODE_FULL!); Always waits for marker
Note that the bottom status bar region is refreshed separately, right after the screen, as a PARTIAL, AUTO (GC16_FAST) update, and it's this marker that's waited after...
Non flash lasts longer (dual timeout: 14pgs / 7mins).
--]]
-- We don't really have an easy way to know if we're refreshing the UI, or a page, or if said page contains an image, so go with the highest fidelity option
-- We spend much more time in the reader than the UI, and our UI isn't very graphic anyway, so we'll follow the reader's behaviour above all
self.full_refresh_waveform_mode = WAVEFORM_MODE_GC16
-- Request REAGL waveform mode on devices that support it (PW2, KT2, KV) [FIXME: Is that actually true of the KT2?]
if Device.model == "KindlePaperWhite2" or Device.model == "KindleBasic" or Device.model == "KindleVoyage" then
self.partial_refresh_waveform_mode = WAVEFORM_MODE_REAGL
-- We need to wait for every update marker when using REAGL waveform modes. That mostly means we always use MXCFB_WAIT_FOR_UPDATE_SUBMISSION.
self.wait_for_every_marker = true
else
self.partial_refresh_waveform_mode = WAVEFORM_MODE_GL16_FAST
-- NOTE: Or we could go back to what KOReader did before fa55acc in koreader-base, which was also to use AUTO ;).
-- That said, we *should* be making more or less the same decisions as AUTO on our own, if I followed things correctly...
--self.partial_refresh_waveform_mode = WAVEFORM_MODE_AUTO
-- Only wait for update markers on FULL updates
self.wait_for_every_marker = false
end
-- Default to GC16_FAST (will be used for PARTIAL UI updates)
self.default_waveform_mode = WAVEFORM_MODE_GC16_FAST
end
end
@ -217,6 +121,7 @@ function UIManager:close(widget)
return
end
DEBUG("close widget", widget.id)
-- TODO: Why do we the following?
Input.disable_double_tap = DGESDETECT_DISABLE_DOUBLE_TAP
local dirty = false
for i = #self._window_stack, 1, -1 do
@ -383,105 +288,78 @@ end
-- repaint dirty widgets
function UIManager:repaint()
-- flag in which we will record if we did any repaints at all
-- will trigger a refresh if set.
local dirty = false
local request_full_refresh = false
local force_full_refresh = false
local force_partial_refresh = 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
-- paint if repaint_all is request
-- paint also if current widget or any widget underneath is dirty
if self.repaint_all or dirty or self._dirty[widget.widget] then
widget.widget:paintTo(Screen.bb, widget.x, widget.y)
if self._dirty[widget.widget] == "auto" then
-- Most likely a 'reader' refresh. 'request' in the sense once we hit our FULL_REFRESH_COUNT ;).
request_full_refresh = true
end
-- self._dirty[widget.widget] may also be "auto"
if self._dirty[widget.widget] == "full" then
force_full_refresh = true
end
if self._dirty[widget.widget] == "partial" then
elseif self._dirty[widget.widget] == "partial" then
force_partial_refresh = true
end
if self._dirty[widget.widget] == "fast" then
elseif self._dirty[widget.widget] == "fast" then
force_fast_refresh = true
end
-- and remove from list after painting
self._dirty[widget.widget] = nil
-- trigger repaint
dirty = true
end
end
if self.full_refresh then
dirty = true
force_full_refresh = true
end
if self.partial_refresh then
dirty = true
force_partial_refresh = true
end
self.repaint_all = false
self.full_refresh = false
self.partial_refresh = false
local refresh_type = self.default_refresh_type
local waveform_mode = self.default_waveform_mode
local wait_for_marker = self.wait_for_every_marker
if dirty then
if force_partial_refresh or force_fast_refresh or self.update_regions_func then
refresh_type = UPDATE_MODE_PARTIAL
-- Override wait_for_marker if we need to enable the Kobo timing workaround on UI refreshes
if self.wait_for_ui_markers then
wait_for_marker = true
end
-- select proper refresh mode
-- TODO: fix this. We should probably do separate refreshes
-- by regional refreshes (e.g. fast refresh, some partial refreshes)
-- and full-screen full refresh
local refresh
if force_fast_refresh then
refresh = Screen.refreshFast
elseif force_partial_refresh then
refresh = Screen.refreshPartial
elseif force_full_refresh or self.refresh_count == self.FULL_REFRESH_COUNT - 1 then
refresh_type = UPDATE_MODE_FULL
end
-- Handle the waveform mode selection...
if refresh_type == UPDATE_MODE_FULL then
waveform_mode = self.full_refresh_waveform_mode
refresh = Screen.refreshFull
-- a full refresh will reset the counter which leads to an automatic full refresh
self.refresh_count = 0
else
waveform_mode = self.partial_refresh_waveform_mode
end
if force_fast_refresh then
waveform_mode = self.fast_waveform_mode
-- FIXME: Should we also avoid doing an MXCFB_WAIT_FOR_UPDATE_SUBMISSION for this update?
--wait_for_marker = false
end
-- If the device is REAGL-aware, we're specifically asking for a REAGL update, and we're doing a PARTIAL *reader* refresh, apply some trickery to match the stock reader's behavior
-- (On most device, REAGL updates are always FULL, but there's no black flash. On devices where this isn't the case [H2O], we're letting the driver do the job by using AUTO).
if not force_partial_refresh and not force_fast_refresh and refresh_type == UPDATE_MODE_PARTIAL and (waveform_mode == WAVEFORM_MODE_REAGL or waveform_mode == NTX_WFM_MODE_GLD16) then
refresh_type = UPDATE_MODE_FULL
end
-- On the other hand, if we asked for a PARTIAL *UI* refresh, fall back to the default waveform mode, which is tailored per-device to hopefully be more appropriate in this instance than the one we use in the reader.
if force_partial_refresh then
-- NOTE: Using default_waveform_mode might seem counter-intuitive when we have partial_refresh_waveform_mode, but partial_refresh_waveform_mode is mostly there as a means to flag REAGL-aware devices ;).
-- Here, we're actually interested in handling PARTIAL, regional (be it properly flagged or not) updates, and not the PARTIAL updates from the reader that actually refresh the whole screen (i.e., those between black flashes).
waveform_mode = self.default_waveform_mode
-- 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
local update_regions = self.update_regions_func()
for _, update_region in ipairs(update_regions) do
-- in some rare cases update region has 1 pixel offset
Screen:refresh(refresh_type, waveform_mode, wait_for_marker,
update_region.x-1, update_region.y-1,
refresh(Screen, update_region.x-1, update_region.y-1,
update_region.w+2, update_region.h+2)
end
self.update_regions_func = nil
else
Screen:refresh(refresh_type, waveform_mode, wait_for_marker)
end
-- REAGL refreshes are always FULL (but without a black flash), but we want to keep our black flash timeout working, so don't reset the counter on FULL REAGL refreshes...
if refresh_type == UPDATE_MODE_FULL and waveform_mode ~= WAVEFORM_MODE_REAGL and waveform_mode ~= NTX_WFM_MODE_GLD16 then
self.refresh_count = 0
elseif not force_partial_refresh and not force_full_refresh and not self.update_regions_func then
self.refresh_count = (self.refresh_count + 1)%self.FULL_REFRESH_COUNT
refresh(Screen)
end
end
self.update_regions_func = nil
end
-- this is the main loop of the UI controller

@ -15,8 +15,8 @@ local ButtonTable = VerticalGroup:new{
{text="Cancel", enabled=false, callback=nil},
},
},
sep_width = Screen:scaleByDPI(1),
padding = Screen:scaleByDPI(2),
sep_width = Screen:scaleBySize(1),
padding = Screen:scaleBySize(2),
zero_sep = false,
button_font_face = "cfont",
@ -66,7 +66,7 @@ function ButtonTable:init()
end
function ButtonTable:addHorizontalSep()
table.insert(self, VerticalSpan:new{ width = Screen:scaleByDPI(2) })
table.insert(self, VerticalSpan:new{ width = Screen:scaleBySize(2) })
table.insert(self, LineWidget:new{
background = Blitbuffer.gray(0.5),
dimen = Geom:new{
@ -74,7 +74,7 @@ function ButtonTable:addHorizontalSep()
h = self.sep_width,
}
})
table.insert(self, VerticalSpan:new{ width = Screen:scaleByDPI(2) })
table.insert(self, VerticalSpan:new{ width = Screen:scaleBySize(2) })
end
return ButtonTable

@ -161,7 +161,7 @@ function ConfigOption:init()
-- fill vertical group of config tab
local vertical_group = VerticalGroup:new{}
table.insert(vertical_group, VerticalSpan:new{
width = Screen:scaleByDPI(default_option_padding),
width = Screen:scaleBySize(default_option_padding),
})
local show_advanced = G_reader_settings:readSetting("show_advanced") or false
for c = 1, #self.options do
@ -173,10 +173,10 @@ function ConfigOption:init()
local name_font_size = self.options[c].name_font_size and self.options[c].name_font_size or default_name_font_size
local item_font_face = self.options[c].item_font_face and self.options[c].item_font_face or "cfont"
local item_font_size = self.options[c].item_font_size and self.options[c].item_font_size or default_item_font_size
local option_height = Screen:scaleByDPI(self.options[c].height and self.options[c].height or default_option_height)
local option_height = Screen:scaleBySize(self.options[c].height and self.options[c].height or default_option_height)
local item_spacing_with = self.options[c].spacing and self.options[c].spacing or default_items_spacing
local items_spacing = HorizontalSpan:new{
width = Screen:scaleByDPI(item_spacing_with)
width = Screen:scaleBySize(item_spacing_with)
}
local horizontal_group = HorizontalGroup:new{}
if self.options[c].name_text then
@ -284,7 +284,7 @@ function ConfigOption:init()
local max_item_spacing = (Screen:getWidth() * item_align -
middle_item:getSize().w * items_count) / items_count
local items_spacing = HorizontalSpan:new{
width = math.min(max_item_spacing, Screen:scaleByDPI(item_spacing_with))
width = math.min(max_item_spacing, Screen:scaleBySize(item_spacing_with))
}
for d = 1, #self.options[c].item_text do
local option_item = nil
@ -334,7 +334,7 @@ function ConfigOption:init()
local max_item_spacing = (Screen:getWidth() * item_align -
first_item:getSize().w * items_count) / items_count
local items_spacing = HorizontalSpan:new{
width = math.min(max_item_spacing, Screen:scaleByDPI(item_spacing_with))
width = math.min(max_item_spacing, Screen:scaleBySize(item_spacing_with))
}
for d = 1, #self.options[c].item_icons do
local option_item = OptionIconItem:new{
@ -362,7 +362,7 @@ function ConfigOption:init()
if self.options[c].toggle then
local max_toggle_width = Screen:getWidth() / 2
local toggle_width = Screen:scaleByDPI(self.options[c].width or 216)
local toggle_width = Screen:scaleBySize(self.options[c].width or 216)
local switch = ToggleSwitch:new{
width = math.min(max_toggle_width, toggle_width),
font_face = item_font_face,

@ -41,13 +41,13 @@ local DictQuickLookup = InputContainer:new{
-- box of highlighted word, quick lookup window tries to not hide the word
word_box = nil,
title_padding = Screen:scaleByDPI(5),
title_margin = Screen:scaleByDPI(2),
word_padding = Screen:scaleByDPI(5),
word_margin = Screen:scaleByDPI(2),
definition_padding = Screen:scaleByDPI(2),
definition_margin = Screen:scaleByDPI(2),
button_padding = Screen:scaleByDPI(14),
title_padding = Screen:scaleBySize(5),
title_margin = Screen:scaleBySize(2),
word_padding = Screen:scaleBySize(5),
word_margin = Screen:scaleBySize(2),
definition_padding = Screen:scaleBySize(2),
definition_margin = Screen:scaleBySize(2),
button_padding = Screen:scaleBySize(14),
}
function DictQuickLookup:init()
@ -202,7 +202,7 @@ function DictQuickLookup:update()
--background = Blitbuffer.gray(0.5),
dimen = Geom:new{
w = button_table:getSize().w + self.button_padding,
h = Screen:scaleByDPI(2),
h = Screen:scaleBySize(2),
}
}
@ -252,7 +252,7 @@ function DictQuickLookup:update()
dimen = self.region,
FrameContainer:new{
bordersize = 0,
padding = Screen:scaleByDPI(5),
padding = Screen:scaleBySize(5),
self.dict_frame,
}
}

@ -27,11 +27,11 @@ local InputDialog = InputContainer:new{
title_face = Font:getFace("tfont", 22),
input_face = Font:getFace("cfont", 20),
title_padding = Screen:scaleByDPI(5),
title_margin = Screen:scaleByDPI(2),
input_padding = Screen:scaleByDPI(10),
input_margin = Screen:scaleByDPI(10),
button_padding = Screen:scaleByDPI(14),
title_padding = Screen:scaleBySize(5),
title_margin = Screen:scaleBySize(2),
input_padding = Screen:scaleBySize(10),
input_margin = Screen:scaleBySize(10),
button_padding = Screen:scaleBySize(14),
}
function InputDialog:init()
@ -76,7 +76,7 @@ function InputDialog:init()
--background = Blitbuffer.gray(0.5),
dimen = Geom:new{
w = self.button_table:getSize().w + self.button_padding,
h = Screen:scaleByDPI(2),
h = Screen:scaleBySize(2),
}
}

@ -323,7 +323,7 @@ local Menu = FocusManager:new{
width = 500,
-- height will be calculated according to item number if not given
height = nil,
header_padding = Screen:scaleByDPI(10),
header_padding = Screen:scaleBySize(10),
dimen = Geom:new{},
item_table = {},
item_shortcuts = {
@ -359,7 +359,7 @@ function Menu:_recalculateDimen()
self.dimen.w = self.width
self.item_dimen = Geom:new{
w = self.dimen.w,
h = Screen:scaleByDPI(46), -- hardcoded for now
h = Screen:scaleBySize(46), -- hardcoded for now
}
-- if height not given, dynamically calculate it
self.dimen.h = self.height or (#self.item_table + 2) * self.item_dimen.h
@ -418,7 +418,7 @@ function Menu:init()
show_parent = self,
}
self.page_info_spacer = HorizontalSpan:new{
width = Screen:scaleByDPI(32),
width = Screen:scaleBySize(32),
}
self.page_info_left_chev:hide()
self.page_info_right_chev:hide()
@ -449,7 +449,7 @@ function Menu:init()
self.page_return_arrow:hide()
self.return_button = HorizontalGroup:new{
HorizontalSpan:new{
width = Screen:scaleByDPI(5),
width = Screen:scaleBySize(5),
},
self.page_return_arrow,
}

@ -19,8 +19,8 @@ local ScrollTextWidget = InputContainer:new{
fgcolor = Blitbuffer.COLOR_BLACK,
width = 400,
height = 20,
scroll_bar_width = Screen:scaleByDPI(6),
text_scroll_span = Screen:scaleByDPI(6),
scroll_bar_width = Screen:scaleBySize(6),
text_scroll_span = Screen:scaleBySize(6),
dialog = nil,
}
@ -38,12 +38,12 @@ function ScrollTextWidget:init()
enable = visible_line_count < total_line_count,
low = 0,
high = visible_line_count/total_line_count,
width = Screen:scaleByDPI(6),
width = Screen:scaleBySize(6),
height = self.height,
}
local horizontal_group = HorizontalGroup:new{}
table.insert(horizontal_group, self.text_widget)
table.insert(horizontal_group, HorizontalSpan:new{width = Screen:scaleByDPI(6)})
table.insert(horizontal_group, HorizontalSpan:new{width = Screen:scaleBySize(6)})
table.insert(horizontal_group, self.v_scroll_bar)
self[1] = horizontal_group
self.dimen = Geom:new(self[1]:getSize())

@ -25,8 +25,8 @@ function ToggleLabel:paintTo(bb, x, y)
end
local ToggleSwitch = InputContainer:new{
width = Screen:scaleByDPI(216),
height = Screen:scaleByDPI(30),
width = Screen:scaleBySize(216),
height = Screen:scaleBySize(30),
bgcolor = Blitbuffer.COLOR_WHITE, -- unfoused item color
fgcolor = Blitbuffer.gray(0.5), -- focused item color
font_face = "cfont",

@ -149,16 +149,16 @@ local TouchMenuBar = InputContainer:new{
}
function TouchMenuBar:init()
local icon_sep_width = Screen:scaleByDPI(2)
local icon_sep_width = Screen:scaleBySize(2)
local icons_sep_width = icon_sep_width * (#self.icons + 1)
-- we assume all icons are of the same width
local ib = IconButton:new{icon_file = self.icons[1]}
local content_width = ib:getSize().w * #self.icons + icons_sep_width
local spacing_width = (self.width - content_width)/(#self.icons*2)
local spacing = HorizontalSpan:new{
width = math.min(spacing_width, Screen:scaleByDPI(20))
width = math.min(spacing_width, Screen:scaleBySize(20))
}
self.height = ib:getSize().h + Screen:scaleByDPI(10)
self.height = ib:getSize().h + Screen:scaleBySize(10)
self.show_parent = self.show_parent or self
self.bar_icon_group = HorizontalGroup:new{}
-- build up image widget for menu icon bar
@ -192,7 +192,7 @@ function TouchMenuBar:init()
self.bar_sep = LineWidget:new{
dimen = Geom:new{
w = self.width,
h = Screen:scaleByDPI(2),
h = Screen:scaleBySize(2),
},
empty_segments = {
{
@ -205,7 +205,7 @@ function TouchMenuBar:init()
local icon_sep = LineWidget:new{
style = k == 1 and "solid" or "none",
dimen = Geom:new{
w = Screen:scaleByDPI(2),
w = Screen:scaleBySize(2),
h = self.height,
}
}
@ -258,9 +258,9 @@ local TouchMenu = InputContainer:new{
-- for returnning in multi-level menus
item_table_stack = nil,
item_table = nil,
item_height = Screen:scaleByDPI(50),
bordersize = Screen:scaleByDPI(2),
padding = Screen:scaleByDPI(5),
item_height = Screen:scaleBySize(50),
bordersize = Screen:scaleBySize(2),
padding = Screen:scaleBySize(5),
fface = Font:getFace("ffont", 20),
width = nil,
height = nil,
@ -353,7 +353,7 @@ function TouchMenu:init()
end,
}
local footer_width = self.width - self.padding*2 - self.bordersize*2
local footer_height = up_button:getSize().h + Screen:scaleByDPI(2)
local footer_height = up_button:getSize().h + Screen:scaleBySize(2)
self.footer = HorizontalGroup:new{
LeftContainer:new{
dimen = Geom:new{ w = footer_width*0.33, h = footer_height},
@ -450,7 +450,7 @@ function TouchMenu:updateItems()
end -- if i <= self.items
end -- for c=1, self.perpage
table.insert(self.item_group, VerticalSpan:new{width = Screen:scaleByDPI(2)})
table.insert(self.item_group, VerticalSpan:new{width = Screen:scaleBySize(2)})
table.insert(self.item_group, self.footer)
self.page_info_text.text = util.template(_("Page %1 of %2"), self.page, self.page_num)
self.page_info_left_chev:showHide(self.page_num > 1)

@ -155,7 +155,7 @@ local VirtualKeyboard = InputContainer:new{
height = 256,
bordersize = 2,
padding = 2,
key_padding = Screen:scaleByDPI(6),
key_padding = Screen:scaleBySize(6),
}
function VirtualKeyboard:init()

Loading…
Cancel
Save