Merge pull request #1783 from houqp/keyboard

support input for keyboard only devices like kindle k3 and dxg
pull/1784/head
Huang Xin 8 years ago
commit 1c64335e7d

2
.gitignore vendored

@ -30,6 +30,7 @@ i18n
/.project /.project
koreader-android-arm-linux-androideabi koreader-android-arm-linux-androideabi
koreader-kindle-legacy-arm-kindle-linux-gnueabi
koreader-kindle-arm-linux-gnueabi koreader-kindle-arm-linux-gnueabi
koreader-kobo-arm-linux-gnueabihf koreader-kobo-arm-linux-gnueabihf
koreader-emulator-i686-w64-mingw32 koreader-emulator-i686-w64-mingw32
@ -37,4 +38,3 @@ koreader-emulator-x86_64-linux-gnu
koreader-emulator-x86_64-pc-linux-gnu koreader-emulator-x86_64-pc-linux-gnu
koreader-pocketbook-arm-obreey-linux-gnueabi koreader-pocketbook-arm-obreey-linux-gnueabi
koreader-ubuntu-touch-arm-linux-gnueabihf koreader-ubuntu-touch-arm-linux-gnueabihf

@ -54,10 +54,10 @@ all: $(if $(ANDROID),,$(KOR_BASE)/$(OUTPUT_DIR)/luajit)
rm -f $(INSTALL_DIR)/koreader/git-rev; echo $(VERSION) > $(INSTALL_DIR)/koreader/git-rev rm -f $(INSTALL_DIR)/koreader/git-rev; echo $(VERSION) > $(INSTALL_DIR)/koreader/git-rev
ifneq ($(or $(EMULATE_READER),$(WIN32)),) ifneq ($(or $(EMULATE_READER),$(WIN32)),)
cp -f $(KOR_BASE)/ev_replay.py $(INSTALL_DIR)/koreader/ cp -f $(KOR_BASE)/ev_replay.py $(INSTALL_DIR)/koreader/
# create symlink instead of copying files in development mode @echo "[*] create symlink instead of copying files in development mode"
cd $(INSTALL_DIR)/koreader && \ cd $(INSTALL_DIR)/koreader && \
ln -sf ../../$(KOR_BASE)/$(OUTPUT_DIR)/* . ln -sf ../../$(KOR_BASE)/$(OUTPUT_DIR)/* .
# install front spec only for the emulator @echo "[*] install front spec only for the emulator"
cd $(INSTALL_DIR)/koreader/spec && test -e front || \ cd $(INSTALL_DIR)/koreader/spec && test -e front || \
ln -sf ../../../../spec ./front ln -sf ../../../../spec ./front
cd $(INSTALL_DIR)/koreader/spec/front/unit && test -e data || \ cd $(INSTALL_DIR)/koreader/spec/front/unit && test -e data || \
@ -73,15 +73,16 @@ ifdef ANDROID
ln -sf ../../$(ANDROID_DIR)/*.lua . ln -sf ../../$(ANDROID_DIR)/*.lua .
endif endif
ifdef WIN32 ifdef WIN32
# install runtime libraries for win32 @echo "[*] Install runtime libraries for win32..."
cd $(INSTALL_DIR)/koreader && cp ../../$(WIN32_DIR)/*.dll . cd $(INSTALL_DIR)/koreader && cp ../../$(WIN32_DIR)/*.dll .
endif endif
# install plugins @echo "[*] Install plugins"
cp -r plugins/* $(INSTALL_DIR)/koreader/plugins/ cp -r plugins/* $(INSTALL_DIR)/koreader/plugins/
@echo "[*] Installresources"
cp -rpL resources/fonts/* $(INSTALL_DIR)/koreader/fonts/ cp -rpL resources/fonts/* $(INSTALL_DIR)/koreader/fonts/
install -d $(INSTALL_DIR)/koreader/{screenshots,data/{dict,tessdata},fonts/host,ota} install -d $(INSTALL_DIR)/koreader/{screenshots,data/{dict,tessdata},fonts/host,ota}
ifeq ($(or $(EMULATE_READER),$(WIN32)),) ifeq ($(or $(EMULATE_READER),$(WIN32)),)
# clean up, remove unused files for releases @echo "[*] Clean up, remove unused files for releases"
rm -rf $(INSTALL_DIR)/koreader/data/{cr3.ini,cr3skin-format.txt,desktop,devices,manual} rm -rf $(INSTALL_DIR)/koreader/data/{cr3.ini,cr3skin-format.txt,desktop,devices,manual}
rm -rf $(INSTALL_DIR)/koreader/fonts/droid/DroidSansFallbackFull.ttf rm -rf $(INSTALL_DIR)/koreader/fonts/droid/DroidSansFallbackFull.ttf
endif endif
@ -286,6 +287,8 @@ androidupdate: all
update: update:
ifeq ($(TARGET), kindle) ifeq ($(TARGET), kindle)
make kindleupdate make kindleupdate
else ifeq ($(TARGET), kindle-legacy)
make kindleupdate
else ifeq ($(TARGET), kobo) else ifeq ($(TARGET), kobo)
make koboupdate make koboupdate
else ifeq ($(TARGET), pocketbook) else ifeq ($(TARGET), pocketbook)

@ -112,44 +112,35 @@ Getting the source
``` ```
git clone https://github.com/koreader/koreader.git git clone https://github.com/koreader/koreader.git
cd koreader && make fetchthirdparty cd koreader && ./kodev fetch-thirdparty
``` ```
Building, Running and Testing Building, Running and Testing
============================= =============================
For EReader devices (kindle, kobo, pocketbook) For EReader devices (kindle, kobo, pocketbook, ubuntu-touch)
--------------------- ---------------------
To build installable package for Kindle: To build installable package for Kindle:
``` ```
make TARGET=kindle clean update ./kodev release kindle
``` ```
To build installable package for Kobo: To build installable package for Kobo:
``` ```
make TARGET=kobo clean update ./kodev release kobo
``` ```
To build installable package for PocketBook you need first to obtain the SDK To build installable package for PocketBook:
from PocketBook:
``` ```
make pocketbook-toolchain ./kodev release pocketbook
```
then similarly with Kindle and Kobo building run this command:
```
make TARGET=pocketbook clean update
``` ```
To build installable package for Ubuntu Touch To build installable package for Ubuntu Touch
``` ```
make TARGET=ubuntu-touch clean update ./kodev release ubuntu-touch
``` ```
To run, you must call the script `reader.lua`. Run it without arguments to see
usage notes. Note that the script and the `luajit` binary must be in the same
directory.
You may checkout our [nightlybuild script][nb-script] to see how to build a You may checkout our [nightlybuild script][nb-script] to see how to build a
package from scratch. package from scratch.
@ -159,15 +150,9 @@ For Android devices
Make sure the "android" and "ndk-build" tools are in your PATH variable Make sure the "android" and "ndk-build" tools are in your PATH variable
and the NDK variable points to the root directory of the Android NDK. and the NDK variable points to the root directory of the Android NDK.
First, run this command to make a standalone android cross compiling toolchain Then, run this command to build installable package for Android:
from NDK:
```
make android-toolchain
```
Then, build installable package for Android:
``` ```
make TARGET=android clean androidupdate ./kodev release android
``` ```
For emulating KOReader on Linux and Windows For emulating KOReader on Linux and Windows
@ -175,21 +160,20 @@ For emulating KOReader on Linux and Windows
To build an emulator on current Linux machine just run: To build an emulator on current Linux machine just run:
``` ```
make clean && make ./kodev build
``` ```
If you want to compile the emulator for Windows you need to run: If you want to compile the emulator for Windows you need to run:
``` ```
make TARGET=win32 clean && make TARGET=win32 ./kodev build win32
``` ```
To run Koreader on your developing machine To run Koreader on your developing machine
(you may need to change $(MACHINE) to the arch of your machine such as 'x86_64'):
``` ```
cd koreader-emulator-$(MACHINE)/koreader && ./reader.lua -d ../../test ./kodev run ./test
``` ```
To run unit tests in KOReader: To run unit tests:
``` ```
make test make test
``` ```

@ -1 +1 @@
Subproject commit e7c0c2fee99e0162b568dec97a351e226697a4a2 Subproject commit 8b751543a9292315fedc6d6e95fcf333bbd4f7e9

@ -249,7 +249,7 @@ function ReaderFooter:getDataFromStatistics(title, pages)
local statistics_data = self.ui.doc_settings:readSetting("stats") local statistics_data = self.ui.doc_settings:readSetting("stats")
local sec = 'na' local sec = 'na'
if statistics_data and statistics_data.performance_in_pages then if statistics_data and statistics_data.performance_in_pages then
local read_pages = util.tablelength(statistics_data.performance_in_pages) local read_pages = util.tableSize(statistics_data.performance_in_pages)
local average_time_per_page = statistics_data.total_time_in_sec / read_pages local average_time_per_page = statistics_data.total_time_in_sec / read_pages
sec = util.secondsToClock(pages * average_time_per_page, true) sec = util.secondsToClock(pages * average_time_per_page, true)
end end

@ -1,4 +1,4 @@
local isAndroid, android = pcall(require, "android") local isAndroid, _ = pcall(require, "android")
local util = require("ffi/util") local util = require("ffi/util")
local function probeDevice() local function probeDevice()

@ -1,10 +1,7 @@
local Event = require("ui/event") local Event = require("ui/event")
local TimeVal = require("ui/timeval") local TimeVal = require("ui/timeval")
local input = require("ffi/input") local input = require("ffi/input")
local util = require("ffi/util")
local Math = require("optmath")
local DEBUG = require("dbg") local DEBUG = require("dbg")
local ffi = require("ffi")
local _ = require("gettext") local _ = require("gettext")
local Key = require("device/key") local Key = require("device/key")
local GestureDetector = require("device/gesturedetector") local GestureDetector = require("device/gesturedetector")

@ -108,6 +108,7 @@ function KindleDXG:init()
device = self, device = self,
event_map = require("device/kindle/event_map_keyboard"), event_map = require("device/kindle/event_map_keyboard"),
} }
self.keyboard_layout = require("device/kindle/keyboard_layout")
self.input.open("/dev/input/event0") self.input.open("/dev/input/event0")
self.input.open("/dev/input/event1") self.input.open("/dev/input/event1")
Kindle.init(self) Kindle.init(self)
@ -124,6 +125,7 @@ function Kindle3:init()
device = self, device = self,
event_map = require("device/kindle/event_map_keyboard"), event_map = require("device/kindle/event_map_keyboard"),
} }
self.keyboard_layout = require("device/kindle/keyboard_layout")
self.input.open("/dev/input/event0") self.input.open("/dev/input/event0")
self.input.open("/dev/input/event1") self.input.open("/dev/input/event1")
Kindle.init(self) Kindle.init(self)

@ -0,0 +1,14 @@
return {
[1] = {
"Q", "W", "E", "R", "T", "Y", "U", "I", "Q", "P",
},
[2] = {
"A", "S", "D", "F", "G", "H", "J", "K", "L", "Del",
},
[3] = {
"Z", "X", "C", "V", "B", "N", "M", ".", "Sym", "Enter",
},
[4] = {
"Sym", "Alt", "space", "Aa", "Home", "Back",
},
}

@ -1,5 +1,4 @@
local Generic = require("device/generic/device") local Generic = require("device/generic/device")
local lfs = require("libs/libkoreader-lfs")
local Geom = require("ui/geometry") local Geom = require("ui/geometry")
local DEBUG = require("dbg") local DEBUG = require("dbg")

@ -16,6 +16,10 @@ local Device = Generic:new{
needsScreenRefreshAfterResume = no, needsScreenRefreshAfterResume = no,
} }
if os.getenv("DISABLE_TOUCH") == "1" then
Device.isTouchDevice = no
end
function Device:init() function Device:init()
-- allows to set a viewport via environment variable -- allows to set a viewport via environment variable
-- syntax is Lua table syntax, e.g. EMULATE_READER_VIEWPORT="{x=10,w=550,y=5,h=790}" -- syntax is Lua table syntax, e.g. EMULATE_READER_VIEWPORT="{x=10,w=550,y=5,h=790}"
@ -42,6 +46,8 @@ function Device:init()
} }
end end
self.keyboard_layout = require("device/sdl/keyboard_layout")
if portrait then if portrait then
self.input:registerEventAdjustHook(self.input.adjustTouchSwitchXY) self.input:registerEventAdjustHook(self.input.adjustTouchSwitchXY)
self.input:registerEventAdjustHook( self.input:registerEventAdjustHook(

@ -0,0 +1,14 @@
return {
[1] = {
"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
},
[2] = {
"A", "S", "D", "F", "G", "H", "J", "K", "L", "Del",
},
[3] = {
"Z", "X", "C", "V", "B", "N", "M", ".", "Sym", "Enter",
},
[4] = {
"Sym", "Alt", "space", "Aa", "Home", "Back",
},
}

@ -85,7 +85,7 @@ end
-- modal widget should be always on the top -- modal widget should be always on the top
-- for refreshtype & refreshregion see description of setDirty() -- for refreshtype & refreshregion see description of setDirty()
function UIManager:show(widget, refreshtype, refreshregion, x, y) function UIManager:show(widget, refreshtype, refreshregion, x, y)
DEBUG("show widget", widget.id) DEBUG("show widget", widget._name)
self._running = true self._running = true
local window = {x = x or 0, y = y or 0, widget = widget} local window = {x = x or 0, y = y or 0, widget = widget}
-- put this window on top of the toppest non-modal window -- put this window on top of the toppest non-modal window

@ -3,7 +3,6 @@ local UIManager = require("ui/uimanager")
local Screen = require("device").screen local Screen = require("device").screen
local Geom = require("ui/geometry") local Geom = require("ui/geometry")
local Event = require("ui/event") local Event = require("ui/event")
local DEBUG = require("dbg")
local _ = require("gettext") local _ = require("gettext")
--[[ --[[
@ -51,19 +50,21 @@ function InputContainer:_init()
end end
function InputContainer:paintTo(bb, x, y) function InputContainer:paintTo(bb, x, y)
if self[1] == nil then
return
end
if not self.dimen then if not self.dimen then
local content_size = self[1]:getSize() local content_size = self[1]:getSize()
self.dimen = Geom:new{w = content_size.w, h = content_size.h} self.dimen = Geom:new{w = content_size.w, h = content_size.h}
end end
self.dimen.x = x self.dimen.x = x
self.dimen.y = y self.dimen.y = y
if self[1] then if self.vertical_align == "center" then
if self.vertical_align == "center" then local content_size = self[1]:getSize()
local content_size = self[1]:getSize() self[1]:paintTo(bb, x, y + math.floor((self.dimen.h - content_size.h)/2))
self[1]:paintTo(bb, x, y + math.floor((self.dimen.h - content_size.h)/2)) else
else self[1]:paintTo(bb, x, y)
self[1]:paintTo(bb, x, y)
end
end end
end end
@ -87,7 +88,6 @@ end
function InputContainer:onGesture(ev) function InputContainer:onGesture(ev)
for name, gsseq in pairs(self.ges_events) do for name, gsseq in pairs(self.ges_events) do
for _, gs_range in ipairs(gsseq) do for _, gs_range in ipairs(gsseq) do
--DEBUG("gs_range", gs_range)
if gs_range:match(ev) then if gs_range:match(ev) then
local eventname = gsseq.event or name local eventname = gsseq.event or name
return self:handleEvent(Event:new(eventname, gsseq.args, ev)) return self:handleEvent(Event:new(eventname, gsseq.args, ev))
@ -97,6 +97,10 @@ function InputContainer:onGesture(ev)
end end
function InputContainer:onInput(input) function InputContainer:onInput(input)
if self.enter_callback == nil then
return
end
local InputDialog = require("ui/widget/inputdialog") local InputDialog = require("ui/widget/inputdialog")
self.input_dialog = InputDialog:new{ self.input_dialog = InputDialog:new{
title = input.title or "", title = input.title or "",

@ -0,0 +1,8 @@
local WidgetContainer = require("ui/widget/container/widgetcontainer")
--[[
TopContainer contains its content (1 widget) at the top of its own dimensions
--]]
local TopContainer = WidgetContainer:new()
return TopContainer

@ -54,7 +54,7 @@ function InputDialog:init()
width = self.width, width = self.width,
} }
} }
self.input = InputText:new{ self.input_widget = InputText:new{
text = self.input, text = self.input,
hint = self.input_hint, hint = self.input_hint,
face = self.input_face, face = self.input_face,
@ -95,9 +95,9 @@ function InputDialog:init()
CenterContainer:new{ CenterContainer:new{
dimen = Geom:new{ dimen = Geom:new{
w = self.title_bar:getSize().w, w = self.title_bar:getSize().w,
h = self.input:getSize().h, h = self.input_widget:getSize().h,
}, },
self.input, self.input_widget,
}, },
-- buttons -- buttons
CenterContainer:new{ CenterContainer:new{
@ -113,7 +113,7 @@ function InputDialog:init()
self[1] = CenterContainer:new{ self[1] = CenterContainer:new{
dimen = Geom:new{ dimen = Geom:new{
w = Screen:getWidth(), w = Screen:getWidth(),
h = Screen:getHeight() - self.input:getKeyboardDimen().h, h = Screen:getHeight() - self.input_widget:getKeyboardDimen().h,
}, },
self.dialog_frame, self.dialog_frame,
} }
@ -132,15 +132,15 @@ function InputDialog:onCloseWidget()
end end
function InputDialog:onShowKeyboard() function InputDialog:onShowKeyboard()
self.input:onShowKeyboard() self.input_widget:onShowKeyboard()
end end
function InputDialog:getInputText() function InputDialog:getInputText()
return self.input:getText() return self.input_widget:getText()
end end
function InputDialog:onClose() function InputDialog:onClose()
self.input:onCloseKeyboard() self.input_widget:onCloseKeyboard()
end end
return InputDialog return InputDialog

@ -1,15 +1,15 @@
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local FrameContainer = require("ui/widget/container/framecontainer")
local ScrollTextWidget = require("ui/widget/scrolltextwidget") local ScrollTextWidget = require("ui/widget/scrolltextwidget")
local TextBoxWidget = require("ui/widget/textboxwidget") local TextBoxWidget = require("ui/widget/textboxwidget")
local FrameContainer = require("ui/widget/container/framecontainer")
local VirtualKeyboard = require("ui/widget/virtualkeyboard")
local GestureRange = require("ui/gesturerange") local GestureRange = require("ui/gesturerange")
local Blitbuffer = require("ffi/blitbuffer")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local Device = require("device") local Device = require("device")
local Screen = require("device").screen local Screen = Device.screen
local Font = require("ui/font") local Font = require("ui/font")
local util = require("ffi/util") local util = require("ffi/util")
local Blitbuffer = require("ffi/blitbuffer") local Keyboard
local InputText = InputContainer:new{ local InputText = InputContainer:new{
text = "", text = "",
@ -32,10 +32,10 @@ local InputText = InputContainer:new{
focused = true, focused = true,
} }
function InputText:init() -- only use PhysicalKeyboard if the device does not have touch screen
self:initTextBox(self.text) if Device.isTouchDevice() then
self:initKeyboard() Keyboard = require("ui/widget/virtualkeyboard")
if Device:isTouchDevice() then function InputText:initEventListener()
self.ges_events = { self.ges_events = {
TapTextBox = { TapTextBox = {
GestureRange:new{ GestureRange:new{
@ -45,6 +45,21 @@ function InputText:init()
} }
} }
end end
function InputText:onTapTextBox()
if self.parent.onSwitchFocus then
self.parent:onSwitchFocus(self)
end
end
else
Keyboard = require("ui/widget/physicalkeyboard")
function InputText:initEventListener() end
end
function InputText:init()
self:initTextBox(self.text)
self:initKeyboard()
self:initEventListener()
end end
function InputText:initTextBox(text) function InputText:initTextBox(text)
@ -112,20 +127,13 @@ function InputText:initKeyboard()
if self.input_type == "number" then if self.input_type == "number" then
keyboard_layout = 3 keyboard_layout = 3
end end
self.keyboard = VirtualKeyboard:new{ self.keyboard = Keyboard:new{
layout = keyboard_layout, layout = keyboard_layout,
inputbox = self, inputbox = self,
width = Screen:getWidth(), width = Screen:getWidth(),
height = math.max(Screen:getWidth(), Screen:getHeight())*0.33,
} }
end end
function InputText:onTapTextBox()
if self.parent.onSwitchFocus then
self.parent:onSwitchFocus(self)
end
end
function InputText:unfocus() function InputText:unfocus()
self.focused = false self.focused = false
self[1].color = Blitbuffer.gray(0.5) self[1].color = Blitbuffer.gray(0.5)

@ -0,0 +1,172 @@
local CenterContainer = require("ui/widget/container/centercontainer")
local BottomContainer = require("ui/widget/container/bottomcontainer")
local TopContainer = require("ui/widget/container/topcontainer")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local InputContainer = require("ui/widget/container/inputcontainer")
local FrameContainer = require("ui/widget/container/framecontainer")
local HorizontalGroup = require("ui/widget/horizontalgroup")
local HorizontalSpan = require("ui/widget/horizontalspan")
local VerticalGroup = require("ui/widget/verticalgroup")
local TextWidget = require("ui/widget/textwidget")
local Blitbuffer = require("ffi/blitbuffer")
local Device = require("device")
local Font = require("ui/font")
local Screen = Device.screen
local Geom = require("ui/geometry")
local util = require("util")
local DEBUG = require("dbg")
local PhysicalNumericKey = WidgetContainer:new{
key = nil,
label = nil,
physical_key_label = nil,
keyboard = nil,
callback = nil,
mapping = nil,
width = nil,
height = nil,
bordersize = 2,
face = Font:getFace("infont", 22),
pkey_face = Font:getFace("infont", 14),
}
function PhysicalNumericKey:init()
local label_widget = TextWidget:new{
text = self.label,
face = self.face,
}
self[1] = FrameContainer:new{
margin = 0,
bordersize = self.bordersize,
background = Blitbuffer.COLOR_WHITE,
radius = 5,
padding = 0,
CenterContainer:new{
dimen = Geom:new{
w = self.width - 2*self.bordersize,
h = self.height - 2*self.bordersize,
},
VerticalGroup:new{
label_widget,
TextWidget:new{
fgcolor = Blitbuffer.COLOR_GREY,
text = self.physical_key_label,
face = self.pkey_face,
},
}
},
}
self.dimen = Geom:new{
w = self.width,
h = self.height,
}
end
-- start of PhysicalKeyboard
local PhysicalKeyboard = InputContainer:new{
is_always_active = true,
inputbox = nil, -- expect ui/widget/inputtext instance
bordersize = 2,
padding = 2,
height = math.max(Screen:getWidth(), Screen:getHeight())*0.33,
key_padding = Screen:scaleBySize(6),
}
function PhysicalKeyboard:init()
local all_keys = {}
for _,row in ipairs(Device.keyboard_layout) do
util.arrayAppend(all_keys, row)
end
self.key_events = {
KeyPress = { { all_keys }, }
}
self.dimen = Geom:new{ w = 0, h = 0 }
self:setType(self.inputbox.input_type)
end
function PhysicalKeyboard:setType(t)
if t == "number" then
self.mapping = {
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}
}
self.key_transformer = {}
for i,row in ipairs(self.mapping) do
for j,key in ipairs(row) do
local pkey = Device.keyboard_layout[i][j]
self.key_transformer[pkey] = self.mapping[i][j]
end
end
self:setupNumericMappingUI()
else
-- default mapping
self.mapping = Device.keyboard_layout
end
end
function PhysicalKeyboard:onKeyPress(ev)
local key = ev.key
if key == "Back" then
DEBUG("TODO: exit keyboard")
elseif key == "Del" then
self.inputbox:delChar()
else
if self.key_transformer then
key = self.key_transformer[key]
end
self.inputbox:addChar(key)
end
end
function PhysicalKeyboard:setupNumericMappingUI()
local key_rows = VerticalGroup:new{}
local key_margin = 1
local row_len = #self.mapping[1]
local base_key_width = math.floor((self.width - row_len*(self.key_padding+2*key_margin) - 2*self.padding)/10)
local base_key_height = math.floor((self.height - self.key_padding - 2*self.padding)/4)
local key_width = math.floor(base_key_width + self.key_padding)
for i, kb_row in ipairs(self.mapping) do
local row = HorizontalGroup:new{}
for j, key in ipairs(kb_row) do
if j > 1 then
table.insert(row, HorizontalSpan:new{width=key_margin*2})
end
table.insert(row, PhysicalNumericKey:new{
label = key,
physical_key_label = Device.keyboard_layout[i][j],
width = key_width,
height = base_key_height,
})
end
table.insert(key_rows, row)
end
local keyboard_frame = FrameContainer:new{
margin = 0,
bordersize = 0,
radius = 0,
padding = self.padding,
TopContainer:new{
dimen = Geom:new{
w = self.width - 2*self.bordersize -2*self.padding,
h = self.height - 2*self.bordersize -2*self.padding,
},
key_rows,
}
}
self[1] = BottomContainer:new{
dimen = Screen:getSize(),
keyboard_frame,
}
self.dimen = keyboard_frame:getSize()
end
return PhysicalKeyboard

@ -10,8 +10,8 @@ local ImageWidget = require("ui/widget/imagewidget")
local TextWidget = require("ui/widget/textwidget") local TextWidget = require("ui/widget/textwidget")
local Font = require("ui/font") local Font = require("ui/font")
local Geom = require("ui/geometry") local Geom = require("ui/geometry")
local Screen = require("device").screen
local Device = require("device") local Device = require("device")
local Screen = Device.screen
local GestureRange = require("ui/gesturerange") local GestureRange = require("ui/gesturerange")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local DEBUG = require("dbg") local DEBUG = require("dbg")
@ -26,7 +26,7 @@ local VirtualKey = InputContainer:new{
callback = nil, callback = nil,
width = nil, width = nil,
height = nil, height = math.max(Screen:getWidth(), Screen:getHeight())*0.33,
bordersize = 2, bordersize = 2,
face = Font:getFace("infont", 22), face = Font:getFace("infont", 22),
} }

@ -46,7 +46,7 @@ function util.gsplit(str, pattern, capture)
end) end)
end end
--https://gist.github.com/jesseadams/791673 -- https://gist.github.com/jesseadams/791673
function util.secondsToClock(seconds, withoutSeconds) function util.secondsToClock(seconds, withoutSeconds)
seconds = tonumber(seconds) seconds = tonumber(seconds)
if seconds == 0 or seconds ~= seconds then if seconds == 0 or seconds ~= seconds then
@ -66,10 +66,18 @@ function util.secondsToClock(seconds, withoutSeconds)
end end
end end
function util.tablelength(T) -- returns number of keys in a table
function util.tableSize(T)
local count = 0 local count = 0
for _ in pairs(T) do count = count + 1 end for _ in pairs(T) do count = count + 1 end
return count return count
end end
-- append all elements from t2 into t1
function util.arrayAppend(t1, t2)
for _,v in ipairs(t2) do
table.insert(t1, v)
end
end
return util return util

272
kodev

@ -0,0 +1,272 @@
#!/bin/bash
CURDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
function setup_env {
files=("./koreader-emulator-*/koreader")
export EMU_DIR=${files[0]}
}
function kodev-fetch-thirdparty {
make fetchthirdparty
}
SUPPORTED_TARGETS="
kindle For kindle with touch support
kindle-legacy For kindle2/3/4/DXG
kobo
android
pocketbook
ubuntu-touch
emu (*default) If no TARGET is given, assume emulator
win32
"
function kodev-build {
BUILD_HELP_MSG="
usage: build <TARGET>
TARGET:
${SUPPORTED_TARGETS}"
case $1 in
-h | --help)
echo "${BUILD_HELP_MSG}"
exit 0
;;
kindle)
make TARGET=kindle
;;
kobo)
make TARGET=kobo
;;
kindle-legacy)
make TARGET=kindle-legacy
;;
android)
if [ ! -d ${CURDIR}/base/toolchain/android-toolchain ]; then
make android-toolchain
fi
make TARGET=android
;;
pocketbook)
if [ ! -d ${CURDIR}/base/toolchain/pocketbook-toolchain ]; then
make pocketbook-toolchain
fi
make TARGET=pocketbook
;;
ubuntu-touch)
make TARGET=ubuntu-touch
;;
win32)
make TARGET=win32
;;
*)
make
setup_env
;;
esac
}
function kodev-clean {
CLEAN_HELP_MSG="
usage: clean <TARGET>
TARGET:
${SUPPORTED_TARGETS}"
case $1 in
-h | --help)
echo "${CLEAN_HELP_MSG}"
exit 0
;;
kindle)
make TARGET=kindle clean
;;
kobo)
make TARGET=kobo clean
;;
kindle-legacy)
make TARGET=kindle-legacy clean
;;
android)
make TARGET=android clean
;;
pocketbook)
make TARGET=pocketbook clean
;;
ubuntu-touch)
make TARGET=ubuntu-touch clean
;;
win32)
make TARGET=win32 clean
;;
*)
make clean
;;
esac
}
function kodev-release {
# SUPPORTED_RELEASE_TARGETS=$(echo ${SUPPORTED_TARGETS} | sed 's/win32//')
SUPPORTED_RELEASE_TARGETS="${SUPPORTED_TARGETS/emu*/""}"
RELEASE_HELP_MSG="
usage: release <TARGET>
TARGET:
${SUPPORTED_RELEASE_TARGETS}"
if [ $# -lt 1 ]; then
echo "${RELEASE_HELP_MSG}"
exit 1
fi
case $1 in
-h | --help)
echo "${RELEASE_HELP_MSG}"
exit 0
;;
kindle)
kodev-build kindle
make TARGET=kindle update
;;
kobo)
kodev-build kobo
make TARGET=kobo update
;;
kindle-legacy)
kodev-build kindle-legacy
make TARGET=kindle-legacy update
;;
android)
kodev-build android
make TARGET=android update
;;
pocketbook)
kodev-build pocketbook
make TARGET=pocketbook update
;;
ubuntu-touch)
kodev-build pocketbook
make TARGET=ubuntu-touch update
;;
*)
echo "Unsupported target for release: $1."
echo "${RELEASE_HELP_MSG}"
exit 1
;;
esac
}
function kodev-wbuilder {
kodev-build
echo "[*] Running wbuilder.lua..."
pushd ${EMU_DIR}
EMULATE_READER_W=540 EMULATE_READER_H=720 ./luajit ./utils/wbuilder.lua
popd
}
function kodev-run {
RUN_HELP_MSG="
usage: run <OPTIONS> <ARGS>
OPTIONS:
--no-build run reader without rebuilding
--disable-touch use this if you want to simulate keyboard only devices
"
while [[ $1 == '--'* ]]; do
PARAM=`echo $1 | awk -F= '{print $1}'`
VALUE=`echo $1 | awk -F= '{print $2}'`
case $PARAM in
--disable-touch)
export DISABLE_TOUCH=1
;;
--no-build)
no_build=true
;;
-h | --help)
echo "${RUN_HELP_MSG}"
exit 0
;;
*)
echo "ERROR: unknown option \"$PARAM\""
echo "${RUN_HELP_MSG}"
exit 1
;;
esac
shift
done
if [ ! ${no_build} ]; then
echo "[*] Building KOReader..."
kodev-build
else
setup_env
fi
echo "[*] Running KOReader..."
pushd ${EMU_DIR}
if [ $# -lt 1 ]; then
args=${CURDIR}/test
else
args="$1"
[[ $args != /* ]] && args="${CURDIR}/$1"
fi
EMULATE_READER_W=540 EMULATE_READER_H=720 ./reader.lua -d $args
popd
}
HELP_MSG="
usage: $0 COMMAND <ARGS>
Supported commands:
build Build KOReader
clean Clean KOReader build
run Run KOReader
wbuilder Run wbuilder.lua script (useful for building new UI widget)
"
if [ $# -lt 1 ]; then
echo "Missing command."
echo "${HELP_MSG}"
exit 1
fi
case $1 in
fetch-thirdparty)
kodev-fetch-thirdparty
;;
clean)
shift 1
kodev-clean $@
;;
build)
shift 1
kodev-build $@
;;
release)
shift 1
kodev-release $@
;;
wbuilder)
kodev-wbuilder
;;
run)
shift 1
kodev-run $@
;;
--help | -h)
echo "${HELP_MSG}"
exit 0
;;
*)
echo "Unknown command: $1."
echo "${HELP_MSG}"
exit 1
;;
esac

@ -235,7 +235,7 @@ function ReaderStatistics:updateCurrentStat()
dates[os.date("%Y-%m-%d", k)] = "" dates[os.date("%Y-%m-%d", k)] = ""
end end
local read_pages = util.tablelength(self.data.performance_in_pages) local read_pages = util.tableSize(self.data.performance_in_pages)
local current_page = self.ui.document:getCurrentPage() local current_page = self.ui.document:getCurrentPage()
local average_time_per_page = self.data.total_time_in_sec / read_pages local average_time_per_page = self.data.total_time_in_sec / read_pages
@ -244,7 +244,7 @@ function ReaderStatistics:updateCurrentStat()
table.insert(stats, { text = _("Total time"), mandatory = util.secondsToClock(self.data.total_time_in_sec, false) }) table.insert(stats, { text = _("Total time"), mandatory = util.secondsToClock(self.data.total_time_in_sec, false) })
table.insert(stats, { text = _("Total highlights"), mandatory = self.data.highlights }) table.insert(stats, { text = _("Total highlights"), mandatory = self.data.highlights })
table.insert(stats, { text = _("Total notes"), mandatory = self.data.notes }) table.insert(stats, { text = _("Total notes"), mandatory = self.data.notes })
table.insert(stats, { text = _("Total days"), mandatory = util.tablelength(dates) }) table.insert(stats, { text = _("Total days"), mandatory = util.tableSize(dates) })
table.insert(stats, { text = _("Average time per page"), mandatory = util.secondsToClock(average_time_per_page, false) }) table.insert(stats, { text = _("Average time per page"), mandatory = util.secondsToClock(average_time_per_page, false) })
table.insert(stats, { text = _("Read pages/Total pages"), mandatory = read_pages .. "/" .. self.data.pages }) table.insert(stats, { text = _("Read pages/Total pages"), mandatory = read_pages .. "/" .. self.data.pages })
return stats return stats

@ -34,10 +34,13 @@ local TouchMenu = require("ui/widget/touchmenu")
local InputText = require("ui/widget/inputtext") local InputText = require("ui/widget/inputtext")
local DocumentRegistry = require("document/documentregistry") local DocumentRegistry = require("document/documentregistry")
local ReaderUI = require("apps/reader/readerui") local ReaderUI = require("apps/reader/readerui")
local Dbg = require("dbg") local DEBUG = require("dbg")
local Device = require("device") local Device = require("device")
local Screen = require("device").screen local Screen = require("device").screen
local Blitbuffer = require("ffi/blitbuffer") local Blitbuffer = require("ffi/blitbuffer")
local InputText = require("ui/widget/inputtext")
DEBUG:turnOn()
----------------------------------------------------- -----------------------------------------------------
-- widget that paints the grid on the background -- widget that paints the grid on the background
@ -260,9 +263,8 @@ readerwindow = CenterContainer:new{
reader = ReaderUI:new{ reader = ReaderUI:new{
dialog = readerwindow, dialog = readerwindow,
dimen = Geom:new{ w = Screen:getWidth() - 100, h = Screen:getHeight() - 100 }, dimen = Geom:new{ w = Screen:getWidth() - 100, h = Screen:getHeight() - 100 },
document = DocumentRegistry:openDocument("test/2col.pdf") document = DocumentRegistry:openDocument("spec/front/unit/data/2col.pdf")
--document = DocumentRegistry:openDocument("test/djvu3spec.djvu") --document = DocumentRegistry:openDocument("spec/front/unit/data/djvu3spec.djvu")
--document = DocumentRegistry:openDocument("./README.TXT")
} }
readerwindow[1][1] = reader readerwindow[1][1] = reader
@ -341,9 +343,14 @@ touch_menu = TouchMenu:new{
}, },
} }
inputtext = InputText:new{ local TestInputText = InputText:new{
width = 400, width = 400,
height = 300, enter_callback = function() print("Entered") end,
scroll = false,
input_type = "number",
parent = {
onSwitchFocus = false,
},
} }
----------------------------------------------------------------------- -----------------------------------------------------------------------
@ -358,6 +365,7 @@ UIManager:show(Clock:new())
--UIManager:show(readerwindow) --UIManager:show(readerwindow)
--UIManager:show(touch_menu) --UIManager:show(touch_menu)
--UIManager:show(keyboard) --UIManager:show(keyboard)
-- UIManager:show(inputtext) UIManager:show(TestInputText)
TestInputText:onShowKeyboard()
UIManager:run() UIManager:run()
Loading…
Cancel
Save