diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index 7b68a62b4..ccc55f895 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -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 diff --git a/frontend/apps/filemanager/filemanagermenu.lua b/frontend/apps/filemanager/filemanagermenu.lua index baf7e5164..655c3e15a 100644 --- a/frontend/apps/filemanager/filemanagermenu.lua +++ b/frontend/apps/filemanager/filemanagermenu.lua @@ -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(), diff --git a/frontend/apps/reader/modules/readermenu.lua b/frontend/apps/reader/modules/readermenu.lua index 48435b117..9d5628f41 100644 --- a/frontend/apps/reader/modules/readermenu.lua +++ b/frontend/apps/reader/modules/readermenu.lua @@ -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 diff --git a/frontend/apps/reader/readerui.lua b/frontend/apps/reader/readerui.lua index fcdd67cee..5132d6211 100644 --- a/frontend/apps/reader/readerui.lua +++ b/frontend/apps/reader/readerui.lua @@ -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 diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 37c331f71..3586835cd 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -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 diff --git a/frontend/ui/widget/bookstatuswidget.lua b/frontend/ui/widget/bookstatuswidget.lua index e0f61652a..41f901451 100644 --- a/frontend/ui/widget/bookstatuswidget.lua +++ b/frontend/ui/widget/bookstatuswidget.lua @@ -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, diff --git a/frontend/ui/widget/container/underlinecontainer.lua b/frontend/ui/widget/container/underlinecontainer.lua index e61579421..68e75848e 100644 --- a/frontend/ui/widget/container/underlinecontainer.lua +++ b/frontend/ui/widget/container/underlinecontainer.lua @@ -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 diff --git a/frontend/ui/widget/focusmanager.lua b/frontend/ui/widget/focusmanager.lua index 2912b2416..a2f3f449a 100644 --- a/frontend/ui/widget/focusmanager.lua +++ b/frontend/ui/widget/focusmanager.lua @@ -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 . 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 , -and from that go down and (depending on internat coordinates) -reach either or . +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() diff --git a/frontend/ui/widget/iconbutton.lua b/frontend/ui/widget/iconbutton.lua index 8558ad95c..e7967d419 100644 --- a/frontend/ui/widget/iconbutton.lua +++ b/frontend/ui/widget/iconbutton.lua @@ -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 diff --git a/frontend/ui/widget/inputtext.lua b/frontend/ui/widget/inputtext.lua index fa6786fde..5b0262c61 100644 --- a/frontend/ui/widget/inputtext.lua +++ b/frontend/ui/widget/inputtext.lua @@ -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 diff --git a/frontend/ui/widget/touchmenu.lua b/frontend/ui/widget/touchmenu.lua index 60896424b..68270bab8 100644 --- a/frontend/ui/widget/touchmenu.lua +++ b/frontend/ui/widget/touchmenu.lua @@ -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 diff --git a/plugins/statistics.koplugin/readerprogress.lua b/plugins/statistics.koplugin/readerprogress.lua index 5c2bf8d1b..5237e62a3 100644 --- a/plugins/statistics.koplugin/readerprogress.lua +++ b/plugins/statistics.koplugin/readerprogress.lua @@ -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,