Kindle4NT improvements (#3745)

* [device][kindle4] add fake event to kindle4

* modify focusmanager to allow for more complex layout

The focusmanager now naviguate the layout by avoiding nil value
instead of relying on table lenght. It should be completely backward
compatible

* add Dpad naviguation to the touchmenu

* fix crash because virtualkeyboard on non touch device

the kindle4NT has no keyboard nor touch, the fix open the virtual
keyboard so koreader dont crash but it's not useable

* Enable device with keys to use the touchmenu

* Don't get stuck in reader progress statistics plugin

* [underlinecontainer] Fix and remove unused function

References #1898.
pull/3759/head
onde2rock 6 years ago committed by Frans de Jonge
parent 9849d89f0e
commit e8aab49ee9

@ -362,7 +362,12 @@ function FileManager:init()
end
if Device:hasKeys() then
self.key_events.Close = { {"Home"}, doc = "Close file manager" }
self.key_events.Home = { {"Home"}, doc = "go home" }
if not Device:isSDL() then
--if not in the desktop emulator
--remove the old Back key to exit koreader
self.file_chooser.key_events.Close = nil
end
end
self:handleEvent(Event:new("SetDimensions", self.dimen))
@ -788,4 +793,8 @@ function FileManager:moveFile(from, to)
return util.execute(self.mv_bin, from, to) == 0
end
function FileManager:onHome()
return self:goHome()
end
return FileManager

@ -306,7 +306,7 @@ function FileManagerMenu:onShowMenu()
}
local main_menu
if Device:isTouchDevice() then
if Device:isTouchDevice() or Device:hasDPad() then
local TouchMenu = require("ui/widget/touchmenu")
main_menu = TouchMenu:new{
width = Screen:getWidth(),

@ -53,7 +53,6 @@ function ReaderMenu:init()
self.registered_widgets = {}
if Device:hasKeys() then
self.key_events = { Close = { { "Back" }, doc = "close menu" }, }
if Device:isTouchDevice() then
self.key_events.TapShowMenu = { { "Menu" }, doc = "show menu", }
else
@ -241,7 +240,7 @@ function ReaderMenu:onShowReaderMenu(tab_index)
}
local main_menu
if Device:isTouchDevice() then
if Device:isTouchDevice() or Device:hasDPad() then
local TouchMenu = require("ui/widget/touchmenu")
main_menu = TouchMenu:new{
width = Screen:getWidth(),
@ -294,8 +293,10 @@ function ReaderMenu:_getTabIndexFromLocation(ges)
if self.tab_item_table == nil then
self:setUpdateItemTable()
end
if not ges then
return self.last_tab_index
-- if the start position is far right
if ges.pos.x > 2 * Screen:getWidth() / 3 then
elseif ges.pos.x > 2 * Screen:getWidth() / 3 then
return #self.tab_item_table
-- if the start position is far left
elseif ges.pos.x < Screen:getWidth() / 3 then

@ -52,11 +52,6 @@ local T = require("ffi/util").template
local ReaderUI = InputContainer:new{
name = "ReaderUI",
key_events = {
Close = { { "Home" },
doc = "close document", event = "Close" },
},
active_widgets = {},
-- if we have a parent container, it must be referenced for now
@ -97,14 +92,17 @@ function ReaderUI:init()
self.dialog = self
end
self.doc_settings = DocSettings:open(self.document.file)
if Device:hasKeys() then
self.key_events.Back = {
{ "Back" }, doc = "close document",
event = "Close" }
self.key_events.Home = { {"Home"}, doc = "open file browser" }
if Device:isSDL() then
--if in the desktop emulator
--add the old Back key to exit koreader
self.key_events.Close = { {"Back"}, doc = "Exit koreader" }
end
end
self.doc_settings = DocSettings:open(self.document.file)
-- a view container (so it must be child #1!)
-- all paintable widgets need to be a child of reader view
self:registerModule("view", ReaderView:new{
@ -622,4 +620,8 @@ function ReaderUI:dealWithLoadDocumentFailure()
error("crengine failed recognizing or parsing this file: unsupported or invalid document")
end
function ReaderUI:onHome()
return self:showFileManager()
end
return ReaderUI

@ -317,6 +317,7 @@ function Kindle4:init()
}
self.input.open("/dev/input/event0")
self.input.open("/dev/input/event1")
self.input.open("fake_events")
Kindle.init(self)
end

@ -2,6 +2,7 @@ local Blitbuffer = require("ffi/blitbuffer")
local Button = require("ui/widget/button")
local CenterContainer = require("ui/widget/container/centercontainer")
local CloseButton = require("ui/widget/closebutton")
local Device = require("device")
local Font = require("ui/font")
local FrameContainer = require("ui/widget/container/framecontainer")
local Geom = require("ui/geometry")
@ -25,7 +26,7 @@ local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan")
local util = require("util")
local _ = require("gettext")
local Screen = require("device").screen
local Screen = Device.screen
local template = require("ffi/util").template
local stats_book = {}
@ -82,6 +83,15 @@ function BookStatusWidget:init()
show_parent = self,
readonly = self.readonly,
}
if Device:hasKeys() then
self.key_events = {
--don't get locked in on non touch devices
AnyKeyPressed = { { Device.input.group.Any },
seqtext = "any key", doc = "close dialog" }
}
end
local screen_size = Screen:getSize()
self[1] = FrameContainer:new{
width = screen_size.w,

@ -18,10 +18,6 @@ local UnderlineContainer = WidgetContainer:new{
}
function UnderlineContainer:getSize()
return self:getContentSize()
end
function UnderlineContainer:getContentSize()
local contentSize = self[1]:getSize()
return Geom:new{
w = contentSize.w,
@ -36,7 +32,7 @@ function UnderlineContainer:paintTo(bb, x, y)
w = container_size.w,
h = container_size.h
}
local content_size = self:getContentSize()
local content_size = self[1]:getSize()
local p_y = y
if self.vertical_align == "center" then
p_y = math.floor((container_size.h - content_size.h) / 2) + y

@ -9,18 +9,16 @@ supports a 2D model of active elements
e.g.:
layout = {
{ textinput, textinput },
{ okbutton, cancelbutton }
{ textinput, textinput, item },
{ okbutton, cancelbutton, item },
{ nil, item, nil },
{ nil, item, nil },
{ nil, item, nil },
}
this is a dialog with 2 rows. in the top row, there is the
single (!) widget <textinput>. when the focus is in this
group, left/right movement seems (!) to be doing nothing.
in the second row, there are two widgets and you can move
left/right. also, you can go up from both to reach <textinput>,
and from that go down and (depending on internat coordinates)
reach either <okbutton> or <cancelbutton>.
Navigate the layout by trying to avoid not set or nil value.
Provide a simple wrap around in the vertical direction.
The first element of the first table must be valid to ensure
to not get stuck in an invalid position.
but notice that this does _not_ do the layout for you,
it rather defines an abstract layout.
@ -57,30 +55,17 @@ function FocusManager:onFocusMove(args)
end
local current_item = self.layout[self.selected.y][self.selected.x]
while true do
if self.selected.x + dx > #self.layout[self.selected.y]
or self.selected.x + dx < 1 then
break -- abort when we run into horizontal borders
end
-- call widget wrap callbacks in vertical direction
if self.selected.y + dy > #self.layout then
if not self:onWrapLast() then
break
end
elseif self.selected.y + dy < 1 then
if not self:onWrapFirst() then
if not self.layout[self.selected.y + dy] then
--vertical borders, try to wraparound
if not self:wrapAround(dy) then
break
end
elseif not self.layout[self.selected.y + dy][self.selected.x + dx] then
--vertical border, no wraparound
break
else
self.selected.y = self.selected.y + dy
if #self.layout[self.selected.y] == 0 then -- horizontal separator
self.selected.y = self.selected.y + dy -- skip it
end
end
self.selected.x = self.selected.x + dx
if self.selected.x > #self.layout[self.selected.y] then
-- smaller nb of items on new row than on prev row
self.selected.x = #self.layout[self.selected.y]
self.selected.x = self.selected.x + dx
end
if self.layout[self.selected.y][self.selected.x] ~= current_item
@ -88,24 +73,28 @@ function FocusManager:onFocusMove(args)
-- we found a different object to focus
current_item:handleEvent(Event:new("Unfocus"))
self.layout[self.selected.y][self.selected.x]:handleEvent(Event:new("Focus"))
-- trigger a repaint (we need to be the registered widget!)
-- trigger a fast repaint, this seem to not count toward a fullscreen eink resfresh
-- TODO: is this really needed?
UIManager:setDirty(self.show_parent or self, "partial")
UIManager:setDirty(self.show_parent or self, "fast")
break
end
end
return true
end
function FocusManager:onWrapFirst()
self.selected.y = #self.layout
return true
end
function FocusManager:onWrapLast()
self.selected.y = 1
return true
function FocusManager:wrapAround(dy)
--go to the last valid item directly above or below the current item
--return false if none could be found
local y = self.selected.y
while self.layout[y - dy] and self.layout[y - dy][self.selected.x] do
y = y - dy
end
if y ~= self.selected.y then
self.selected.y = y
return true
else
return false
end
end
function FocusManager:getFocusItem()

@ -124,4 +124,19 @@ function IconButton:onHoldIconButton()
return true
end
function IconButton:onFocus()
--quick and dirty, need better way to show focus
self.image.invert=true
return true
end
function IconButton:onUnfocus()
self.image.invert=false
return true
end
function IconButton:onTapSelect()
self:onTapIconButton()
end
return IconButton

@ -88,6 +88,9 @@ if Device.isTouchDevice() then
end)
end
end
elseif not Device.hasKeyboard() then
Keyboard = require("ui/widget/virtualkeyboard")
function InputText:initEventListener() end --do nothing but doesn't crash for now
else
Keyboard = require("ui/widget/physicalkeyboard")
function InputText:initEventListener() end

@ -6,6 +6,8 @@ local Button = require("ui/widget/button")
local CenterContainer = require("ui/widget/container/centercontainer")
local CheckMark = require("ui/widget/checkmark")
local Device = require("device")
local Event = require("ui/event")
local FocusManager = require("ui/widget/focusmanager")
local Font = require("ui/font")
local FrameContainer = require("ui/widget/container/framecontainer")
local Geom = require("ui/geometry")
@ -20,12 +22,14 @@ local RightContainer = require("ui/widget/container/rightcontainer")
local Size = require("ui/size")
local TextWidget = require("ui/widget/textwidget")
local UIManager = require("ui/uimanager")
local UnderlineContainer = require("ui/widget/container/underlinecontainer")
local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan")
local util = require("ffi/util")
local _ = require("gettext")
local Screen = Device.screen
local getMenuText = require("util").getMenuText
local Input = Device.input
local Screen = Device.screen
--[[
TouchMenuItem widget
@ -97,7 +101,27 @@ function TouchMenuItem:init()
},
},
}
self[1] = self.item_frame
self._underline_container = UnderlineContainer:new{
vertical_align = "center",
dimen =self.dimen,
self.item_frame
}
self[1] = self._underline_container
function self:isEnabled()
return item_enabled ~= false and true
end
end
function TouchMenuItem:onFocus()
self._underline_container.color = Blitbuffer.COLOR_BLACK
return true
end
function TouchMenuItem:onUnfocus()
self._underline_container.color = Blitbuffer.COLOR_WHITE
return true
end
function TouchMenuItem:onTapSelect(arg, ges)
@ -202,9 +226,11 @@ function TouchMenuBar:init()
callback = nil,
padding_left = icon_padding,
padding_right = icon_padding,
menu = self.menu,
}
table.insert(self.icon_widgets, ib)
table.insert(self.menu.layout, ib) -- for the focusmanager
-- we have to use local variable here for closure callback
local _start_seg = end_seg + icon_sep_width
@ -319,7 +345,7 @@ end
--[[
TouchMenu widget for hierarchical menus
--]]
local TouchMenu = InputContainer:new{
local TouchMenu = FocusManager:new{
tab_item_table = {},
-- for returnning in multi-level menus
item_table_stack = nil,
@ -351,6 +377,8 @@ function TouchMenu:init()
end
end
self.layout = {}
self.ges_events.TapCloseAllMenus = {
GestureRange:new{
ges = "tap",
@ -368,7 +396,10 @@ function TouchMenu:init()
}
}
self.key_events.Close = { {"Back"}, doc = "close touch menu" }
self.key_events.Back = { {"Back"}, doc = "back to upper menu or close touchmenu" }
self.key_events.NextPage = { {Input.group.PgFwd}, doc = "next page" }
self.key_events.PrevPage = { {Input.group.PgBack}, doc = "previous page" }
self.key_events.Press = { {"Press"}, doc = "chose selected item" }
local icons = {}
for _,v in ipairs(self.tab_item_table) do
@ -509,7 +540,9 @@ function TouchMenu:updateItems()
local old_dimen = self.dimen and self.dimen:copy()
self:_recalculatePageLayout()
self.item_group:clear()
self.layout = {}
table.insert(self.item_group, self.bar)
table.insert(self.layout, self.bar.icon_widgets) --for the focusmanager
for c = 1, self.perpage do
-- calculate index in item_table
@ -526,6 +559,9 @@ function TouchMenu:updateItems()
show_parent = self.show_parent,
}
table.insert(self.item_group, item_tmp)
if item_tmp:isEnabled() then
table.insert(self.layout, {[self.cur_tab] = item_tmp}) --for the focusmanager
end
if item.separator and c ~= self.perpage then
-- insert split line
table.insert(self.item_group, self.split_line)
@ -553,6 +589,7 @@ function TouchMenu:updateItems()
-- recalculate dimen based on new layout
self.dimen.w = self.width
self.dimen.h = self.item_group:getSize().h + self.bordersize*2 + self.padding*2
self.selected = { x = self.cur_tab, y = 1 } --reset the position of the focusmanager
UIManager:setDirty("all", function()
local refresh_dimen =
@ -707,4 +744,12 @@ function TouchMenu:onClose()
self:closeMenu()
end
function TouchMenu:onBack()
self:backToUpperMenu()
end
function TouchMenu:onPress()
self:getFocusItem():handleEvent(Event:new("TapSelect"))
end
return TouchMenu

@ -1,6 +1,7 @@
local Blitbuffer = require("ffi/blitbuffer")
local CenterContainer = require("ui/widget/container/centercontainer")
local CloseButton = require("ui/widget/closebutton")
local Device = require("device")
local Font = require("ui/font")
local FrameContainer = require("ui/widget/container/framecontainer")
local Geom = require("ui/geometry")
@ -18,7 +19,7 @@ local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan")
local util = require("util")
local _ = require("gettext")
local Screen = require("device").screen
local Screen = Device.screen
local LINE_COLOR = Blitbuffer.gray(0.4)
local BG_COLOR = Blitbuffer.gray(0.2)
@ -46,6 +47,13 @@ function ReaderProgress:init()
UIManager:setDirty(self, function()
return "ui", self.dimen
end)
if Device:hasKeys() then
self.key_events = {
--don't get locked in on non touch devices
AnyKeyPressed = { { Device.input.group.Any },
seqtext = "any key", doc = "close dialog" }
}
end
self[1] = FrameContainer:new{
width = self.width,
height = self.height,

Loading…
Cancel
Save