first demo of screen rotate

pull/2/merge
Qingping Hou 11 years ago
parent 78691fd499
commit d4ff6f9291

@ -83,11 +83,14 @@ function Device:intoScreenSaver()
--os.execute("echo 'screensaver in' >> /mnt/us/event_test.txt")
if self.charging_mode == false and self.screen_saver_mode == false then
Screen:saveCurrentBB()
--msg = InfoMessage:new{"Going into screensaver... "}
msg = InfoMessage:new{
text = "Going into screensaver... ",
timeout = 2,
}
--UIManager:show(msg)
Screen.kpv_rotation_mode = Screen.cur_rotation_mode
Screen.fb:setOrientation(Screen.native_rotation_mode)
--Screen.kpv_rotation_mode = Screen.cur_rotation_mode
--Screen.fb:setOrientation(Screen.native_rotation_mode)
--util.sleep(1)
--os.execute("killall -cont cvm")
self.screen_saver_mode = true
@ -99,11 +102,11 @@ end
function Device:outofScreenSaver()
--os.execute("echo 'screensaver out' >> /mnt/us/event_test.txt")
if self.screen_saver_mode == true and self.charging_mode == false then
util.usleep(1500000)
--util.usleep(1500000)
--os.execute("killall -stop cvm")
Screen.fb:setOrientation(Screen.kpv_rotation_mode)
--Screen.fb:setOrientation(Screen.kpv_rotation_mode)
Screen:restoreFromSavedBB()
Screen.fb:refresh(0)
Screen:refresh(0)
end
self.screen_saver_mode = false
end
@ -112,13 +115,14 @@ function Device:usbPlugIn()
--os.execute("echo 'usb in' >> /mnt/us/event_test.txt")
if self.charging_mode == false and self.screen_saver_mode == false then
Screen:saveCurrentBB()
Screen.kpv_rotation_mode = Screen.cur_rotation_mode
Screen.fb:setOrientation(Screen.native_rotation_mode)
msg = InfoMessage:new{"Going into USB mode... "}
UIManager:show(msg)
util.sleep(1)
UIManager:close(msg)
os.execute("killall -cont cvm")
--Screen.kpv_rotation_mode = Screen.cur_rotation_mode
--Screen.fb:setOrientation(Screen.native_rotation_mode)
msg = InfoMessage:new{
text = "Going into USB mode... ",
timeout = 2,
}
--util.sleep(1)
--os.execute("killall -cont cvm")
end
self.charging_mode = true
end
@ -126,11 +130,11 @@ end
function Device:usbPlugOut()
--os.execute("echo 'usb out' >> /mnt/us/event_test.txt")
if self.charging_mode == true and self.screen_saver_mode == false then
util.usleep(1500000)
os.execute("killall -stop cvm")
Screen.fb:setOrientation(Screen.kpv_rotation_mode)
--util.usleep(1500000)
--os.execute("killall -stop cvm")
--Screen.fb:setOrientation(Screen.kpv_rotation_mode)
Screen:restoreFromSavedBB()
Screen.fb:refresh(0)
Screen:refresh(0)
end
--@TODO signal filemanager for file changes 13.06 2012 (houqp)

@ -33,14 +33,22 @@ Currently supported gestures:
* pan
* swipe
Single tap event from kernel example:
You change the state machine by feeding it touch events, i.e. calling
GestureDetector:feedEvent(tev).
MT_TRACK_ID: 0
MT_X: 222
MT_Y: 207
SYN REPORT
MT_TRACK_ID: -1
SYN REPORT
a touch event should have following format:
tev = {
slot = 1,
id = 46,
x = 0,
y = 1,
timev = TimeVal:new{...},
}
Don't confuse tev with raw evs from kernel, tev is build according to ev.
GestureDetector:feedEvent(tev) will return a detection result when you
feed a touch release event to it.
--]]
GestureDetector = {
@ -54,41 +62,22 @@ GestureDetector = {
track_id = {},
ev_stack = {},
cur_ev = {},
-- latest feeded touch event
last_ev = {},
is_ev_start = false,
first_ev = nil,
state = function(self, ev)
self:switchState("initialState", ev)
end,
last_ev_timev = nil,
last_tap = nil, -- for single/double tap
}
function GestureDetector:feedEvent(ev)
--DEBUG(ev.type, ev.code, ev.value, ev.time)
if ev.type == EV_SYN then
if ev.code == SYN_REPORT then
self.cur_ev.timev = TimeVal:new(ev.time)
local re = self.state(self, self.cur_ev)
self.last_ev_timev = self.cur_ev.timev
if re ~= nil then
return re
end
self.cur_ev = {}
end
elseif ev.type == EV_ABS then
if ev.code == ABS_MT_SLOT then
self.cur_ev.slot = ev.value
elseif ev.code == ABS_MT_TRACKING_ID then
self.cur_ev.id = ev.value
elseif ev.code == ABS_MT_POSITION_X then
self.cur_ev.x = ev.value
elseif ev.code == ABS_MT_POSITION_Y then
self.cur_ev.y = ev.value
end
function GestureDetector:feedEvent(tev)
if tev.id ~= -1 then
self.last_ev = tev
end
return self.state(self, tev)
end
function GestureDetector:deepCopyEv(ev)
@ -120,11 +109,11 @@ end
compare last_pan with self.first_ev
if it is a swipe, return direction of swipe gesture.
--]]
function GestureDetector:isSwipe(last_pan_ev)
local tv_diff = self.first_ev.timev - last_pan_ev.timev
function GestureDetector:isSwipe()
local tv_diff = self.first_ev.timev - self.last_ev.timev
if (tv_diff.sec == 0) and (tv_diff.usec < self.SWIPE_INTERVAL) then
x_diff = last_pan_ev.x - self.first_ev.x
y_diff = last_pan_ev.y - self.first_ev.y
x_diff = self.last_ev.x - self.first_ev.x
y_diff = self.last_ev.y - self.first_ev.y
if x_diff == 0 and y_diff == 0 then
return nil
end
@ -157,10 +146,8 @@ function GestureDetector:switchState(state_new, ev)
end
function GestureDetector:clearState()
self.cur_x = nil
self.cur_y = nil
self.state = self.initialState
self.cur_ev = {}
self.last_ev = {}
self.is_ev_start = false
self.first_ev = nil
end
@ -196,15 +183,15 @@ function GestureDetector:tapState(ev)
-- default to single tap
ges = "tap",
pos = Geom:new{
x = self.cur_x,
y = self.cur_y,
x = self.last_ev.x,
y = self.last_ev.y,
w = 0, h = 0,
}
}
-- cur_tap is used for double tap detection
local cur_tap = {
x = self.cur_x,
y = self.cur_y,
x = self.last_ev.x,
y = self.last_ev.y,
timev = ev.timev,
}
@ -221,7 +208,7 @@ function GestureDetector:tapState(ev)
self.last_tap = cur_tap
DEBUG("set up tap timer")
local deadline = self.cur_ev.timev + TimeVal:new{
local deadline = self.last_ev.timev + TimeVal:new{
sec = 0, usec = self.DOUBLE_TAP_INTERVAL,
}
Input:setTimeout(function()
@ -241,10 +228,8 @@ function GestureDetector:tapState(ev)
-- switched from other state, probably from initialState
-- we return nil in this case
self.state = self.tapState
self.cur_x = ev.x
self.cur_y = ev.y
DEBUG("set up hold timer")
local deadline = self.cur_ev.timev + TimeVal:new{
local deadline = self.last_ev.timev + TimeVal:new{
sec = 0, usec = self.HOLD_INTERVAL
}
Input:setTimeout(function()
@ -269,16 +254,7 @@ function GestureDetector:panState(ev)
DEBUG("in pan state...")
if ev.id == -1 then
-- end of pan, signal swipe gesture if necessary
-- we need to construct a complete_last_ev because
-- the x or y of ev might be nil.
local complete_last_ev = self:deepCopyEv(ev)
if not complete_last_ev.x then
complete_last_ev.x = self.cur_x
end
if not complete_last_ev.y then
complete_last_ev.y = self.cur_y
end
swipe_direct = self:isSwipe(complete_last_ev)
swipe_direct = self:isSwipe()
if swipe_direct then
local start_pos = Geom:new{
x = self.first_ev.x,
@ -309,19 +285,14 @@ function GestureDetector:panState(ev)
},
pos = nil,
}
if ev.x then
pan_ev.relative.x = ev.x - self.cur_x
self.cur_x = ev.x
end
if ev.y then
pan_ev.relative.y = ev.y - self.cur_y
self.cur_y = ev.y
end
pan_ev.relative.x = ev.x - self.last_ev.x
pan_ev.relative.y = ev.y - self.last_ev.y
pan_ev.pos = Geom:new{
x = self.cur_x,
y = self.cur_y,
x = self.last_ev.x,
y = self.last_ev.y,
w = 0, h = 0,
}
self.last_ev = ev
return pan_ev
end
end
@ -330,13 +301,13 @@ function GestureDetector:holdState(ev)
DEBUG("in hold state...")
-- when we switch to hold state, we pass no ev
-- so ev = nil
if not ev and self.cur_x and self.cur_y then
if not ev and self.last_ev.x and self.last_ev.y then
self.state = self.holdState
return {
ges = "hold",
pos = Geom:new{
x = self.cur_x,
y = self.cur_y,
x = self.last_ev.x,
y = self.last_ev.y,
w = 0, h = 0,
}
}
@ -347,8 +318,8 @@ function GestureDetector:holdState(ev)
return {
ges = "hold_release",
pos = Geom:new{
x = self.cur_x,
y = self.cur_y,
x = self.last_ev.x,
y = self.last_ev.y,
w = 0, h = 0,
}
}

@ -9,14 +9,15 @@ it vanishes on key press or after a given timeout
InfoMessage = InputContainer:new{
face = Font:getFace("infofont", 25),
text = "",
timeout = nil,
key_events = {
AnyKeyPressed = { { Input.group.Any }, seqtext = "any key", doc = "close dialog" }
}
timeout = nil, -- in seconds
}
function InfoMessage:init()
if Device:hasKeyboard() then
key_events = {
AnyKeyPressed = { { Input.group.Any }, seqtext = "any key", doc = "close dialog" }
}
end
-- we construct the actual content here because self.text is only available now
self[1] = CenterContainer:new{
dimen = Screen:getSize(),

@ -122,7 +122,13 @@ end
an interface to get input events
]]
Input = {
event_map = {
event_map = {},
rotation = 0,
timer_callbacks = {},
}
function Input:initKeyMap()
self.event_map = {
[2] = "1", [3] = "2", [4] = "3", [5] = "4", [6] = "5", [7] = "6", [8] = "7", [9] = "8", [10] = "9", [11] = "0",
[16] = "Q", [17] = "W", [18] = "E", [19] = "R", [20] = "T", [21] = "Y", [22] = "U", [23] = "I", [24] = "O", [25] = "P",
[30] = "A", [31] = "S", [32] = "D", [33] = "F", [34] = "G", [35] = "H", [36] = "J", [37] = "K", [38] = "L", [14] = "Del",
@ -157,13 +163,8 @@ Input = {
[191] = "RPgFwd", -- K[3] & k[4]
[193] = "LPgFwd", -- K[3] only
[194] = "Press", -- K[3] & k[4]
[10000] = "IntoSS", -- go into screen saver
[10001] = "OutOfSS", -- go out of screen saver
[10020] = "Charging",
[10021] = "NotCharging",
},
sdl_event_map = {
}
self.sdl_event_map = {
[10] = "1", [11] = "2", [12] = "3", [13] = "4", [14] = "5", [15] = "6", [16] = "7", [17] = "8", [18] = "9", [19] = "0",
[24] = "Q", [25] = "W", [26] = "E", [27] = "R", [28] = "T", [29] = "Y", [30] = "U", [31] = "I", [32] = "O", [33] = "P",
[38] = "A", [39] = "S", [40] = "D", [41] = "F", [42] = "G", [43] = "H", [44] = "J", [45] = "K", [46] = "L",
@ -192,21 +193,19 @@ Input = {
[116] = "Down", -- arrow down
[117] = "RPgFwd", -- normal PageDown
[119] = "Del", -- Delete
},
rotation = 0,
rotation_map = {
}
self.rotation_map = {
[0] = {},
[1] = { Up = "Right", Right = "Down", Down = "Left", Left = "Up" },
[2] = { Up = "Down", Right = "Left", Down = "Up", Left = "Right" },
[3] = { Up = "Left", Right = "Up", Down = "Right", Left = "Down" }
},
modifiers = {
}
self.modifiers = {
Alt = false,
Shift = false
},
}
-- these groups are just helpers:
group = {
self.group = {
Cursor = { "Up", "Down", "Left", "Right" },
PgFwd = { "RPgFwd", "LPgFwd" },
PgBack = { "RPgBack", "LPgBack" },
@ -237,13 +236,31 @@ Input = {
"Back", "Enter", "Sym", "AA", "Menu", "Home", "Del",
"LPgBack", "RPgBack", "LPgFwd", "RPgFwd"
}
},
}
end
timer_callbacks = {},
}
function Input:initTouchState()
self.cur_ev = {}
end
function Input:init()
-- Screen module must have been initilized by now.
self.rotation = Screen.fb:getOrientation()
if Device:hasKeyboard() then
self:initKeyMap()
end
if Device:isTouchDevice() then
self:initTouchState()
end
-- set up fake event map
self.event_map[10000] = "IntoSS" -- go into screen saver
self.event_map[10001] = "OutOfSS" -- go out of screen saver
self.event_map[10020] = "Charging"
self.event_map[10021] = "NotCharging"
if util.isEmulated()==1 then
self:initKeyMap()
os.remove("emu_event")
os.execute("mkfifo emu_event")
input.open("emu_event")
@ -327,6 +344,86 @@ function Input:setTimeout(cb, tv_out)
end
end
function Input:handleKeyBoardEv(ev)
local keycode = self.event_map[ev.code]
if not keycode then
-- do not handle keypress for keys we don't know
return
end
-- take device rotation into account
if self.rotation_map[self.rotation][keycode] then
keycode = self.rotation_map[self.rotation][keycode]
end
if keycode == "IntoSS" or keycode == "OutOfSS"
or keycode == "Charging" or keycode == "NotCharging" then
return keycode
end
-- handle modifier keys
if self.modifiers[keycode] ~= nil then
if ev.value == EVENT_VALUE_KEY_PRESS then
self.modifiers[keycode] = true
elseif ev.value == EVENT_VALUE_KEY_RELEASE then
self.modifiers[keycode] = false
end
return
end
local key = Key:new(keycode, self.modifiers)
if ev.value == EVENT_VALUE_KEY_PRESS then
return Event:new("KeyPress", key)
elseif ev.value == EVENT_VALUE_KEY_RELEASE then
return Event:new("KeyRelease", key)
end
end
--[[
parse each touch ev from kernel and build up tev.
tev will be sent to GestureDetector:feedEvent
Events for a single tap motion from Linux kernel (MT protocol B):
MT_TRACK_ID: 0
MT_X: 222
MT_Y: 207
SYN REPORT
MT_TRACK_ID: -1
SYN REPORT
Notice that each line is a single event.
--]]
function Input:handleTouchEv(ev)
if ev.type == EV_SYN then
if ev.code == SYN_REPORT then
self.cur_ev.timev = TimeVal:new(ev.time)
--self.cur_x = self.cur_ev.x or self.cur_x
--self.cur_y = self.cur_ev.y or self.cur_y
-- send ev to state machine
local touch_ges = GestureDetector:feedEvent(self.cur_ev)
--self.last_ev_timev = self.cur_ev.timev
--self.cur_ev = {}
if touch_ges then
return Event:new("Gesture",
Screen:adjustGesCoordinate(touch_ges)
)
end
end
elseif ev.type == EV_ABS then
if ev.code == ABS_MT_SLOT then
self.cur_ev.slot = ev.value
elseif ev.code == ABS_MT_TRACKING_ID then
self.cur_ev.id = ev.value
elseif ev.code == ABS_MT_POSITION_X then
self.cur_ev.x = ev.value
elseif ev.code == ABS_MT_POSITION_Y then
self.cur_ev.y = ev.value
end
end
end
function Input:waitEvent(timeout_us, timeout_s)
-- wrapper for input.waitForEvents that will retry for some cases
local ok, ev
@ -344,14 +441,16 @@ function Input:waitEvent(timeout_us, timeout_s)
if ((not timeout_us and not timeout_s) or tv_now < wait_deadline) then
-- check whether timer is up
if tv_now >= self.timer_callbacks[1].deadline then
local ges = self.timer_callbacks[1].callback()
local touch_ges = self.timer_callbacks[1].callback()
table.remove(self.timer_callbacks, 1)
if ges then
if touch_ges then
-- Do we really need to clear all setTimeout after
-- decided a gesture? FIXME
Input.timer_callbacks = {}
return Event:new("Gesture", ges)
end -- EOF if ges
return Event:new("Gesture",
Screen:adjustGesCoordinate(touch_ges)
)
end -- EOF if touch_ges
end -- EOF if deadline reached
else
break
@ -376,47 +475,13 @@ function Input:waitEvent(timeout_us, timeout_s)
break
end
end
if ok and ev then
ev = self:eventAdjustHook(ev)
if ev.type == EV_KEY then
local keycode = self.event_map[ev.code]
if not keycode then
-- do not handle keypress for keys we don't know
return
end
-- take device rotation into account
if self.rotation_map[self.rotation][keycode] then
keycode = self.rotation_map[self.rotation][keycode]
end
if keycode == "IntoSS" or keycode == "OutOfSS"
or keycode == "Charging" or keycode == "NotCharging" then
return keycode
end
-- handle modifier keys
if self.modifiers[keycode] ~= nil then
if ev.value == EVENT_VALUE_KEY_PRESS then
self.modifiers[keycode] = true
elseif ev.value == EVENT_VALUE_KEY_RELEASE then
self.modifiers[keycode] = false
end
return
end
local key = Key:new(keycode, self.modifiers)
if ev.value == EVENT_VALUE_KEY_PRESS then
return Event:new("KeyPress", key)
elseif ev.value == EVENT_VALUE_KEY_RELEASE then
return Event:new("KeyRelease", key)
end
return self:handleKeyBoardEv(ev)
elseif ev.type == EV_ABS or ev.type == EV_SYN then
local touch_ges = GestureDetector:feedEvent(ev)
if touch_ges then
return Event:new("Gesture", touch_ges)
end
return self:handleTouchEv(ev)
else
-- some other kind of event that we do not know yet
return Event:new("GenericInput", ev)

@ -8,13 +8,14 @@ Notification = InputContainer:new{
face = Font:getFace("infofont", 20),
text = "Null Message",
timeout = nil,
key_events = {
AnyKeyPressed = { { Input.group.Any }, seqtext = "any key", doc = "close dialog" }
}
}
function Notification:init()
if Device:hasKeyboard() then
key_events = {
AnyKeyPressed = { { Input.group.Any }, seqtext = "any key", doc = "close dialog" }
}
end
-- we construct the actual content here because self.text is only available now
self[1] = CenterContainer:new{
dimen = Geom:new{

@ -12,23 +12,25 @@ function ReaderBookmark:init()
{ "B" },
doc = "show bookmarks" },
}
elseif Device:isTouchDevice() then
self.ges_events = {
AddBookmark = {
GestureRange:new{
ges = "double_tap",
range = Geom:new{
x = Screen:getWidth()/2, y = 0,
w = Screen:getWidth()/2,
h = Screen:getHeight()/2
}
}
},
}
end
self.ui.menu:registerToMainMenu(self)
end
function ReaderBookmark:initGesListener()
self.ges_events = {
AddBookmark = {
GestureRange:new{
ges = "double_tap",
range = Geom:new{
x = Screen:getWidth()/2, y = 0,
w = Screen:getWidth()/2,
h = Screen:getHeight()/2
}
}
},
}
end
function ReaderBookmark:onReadSettings(config)
self.bookmarks = config:readSetting("bookmarks") or {}
end
@ -38,7 +40,10 @@ function ReaderBookmark:onCloseDocument()
end
function ReaderBookmark:onSetDimensions(dimen)
self.dimen = dimen
-- update listening according to new screen dimen
if Device:isTouchDevice() then
self:initGesListener()
end
end
function ReaderBookmark:onAddBookmark()

@ -55,20 +55,25 @@ ReaderConfig = InputContainer:new{
}
function ReaderConfig:init()
if Device:isTouchDevice() then
self.ges_events = {
TapShowConfigMenu = {
GestureRange:new{
ges = "tap",
range = self.dimen:copy(),
}
}
}
else
if Device:hasKeyboard() then
self.key_events = {
ShowConfigMenu = { { "AA" }, doc = "show config dialog" },
}
end
if Device:isTouchDevice() then
self:initGesListener()
end
end
function ReaderConfig:initGesListener()
self.ges_events = {
TapShowConfigMenu = {
GestureRange:new{
ges = "tap",
range = self.dimen:copy(),
}
}
}
end
function ReaderConfig:onShowConfigMenu()
@ -107,8 +112,15 @@ function ReaderConfig:onTapShowConfigMenu()
end
function ReaderConfig:onSetDimensions(dimen)
-- update gesture listenning range according to new screen orientation
self:init()
-- update listening according to new screen dimen
--@TODO do we really need to new a Geom everytime? 02.02 2013 (houqp)
self.dimen = Geom:new{
x = 0,
y = 7*Screen:getHeight()/8,
w = Screen:getWidth(),
h = Screen:getHeight()/8,
}
self:initGesListener()
end
function ReaderConfig:onReadSettings(config)

@ -1,4 +1,5 @@
ReaderMenu = InputContainer:new{
_name = "ReaderMenu",
item_table = {},
registered_widgets = {},
}
@ -7,42 +8,44 @@ function ReaderMenu:init()
self.item_table = {}
self.registered_widgets = {}
if Device:isTouchDevice() then
self.ges_events = {
TapShowMenu = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = 0, y = 0,
w = Screen:getWidth(),
h = Screen:getHeight()/4,
}
}
},
}
else
if Device:hasKeyboard() then
self.key_events = {
ShowMenu = { { "Menu" }, doc = "show menu" },
}
end
end
function ReaderMenu:initGesListener()
self.ges_events = {
TapShowMenu = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = 0, y = 0,
w = Screen:getWidth(),
h = Screen:getHeight()/4,
}
}
},
}
end
function ReaderMenu:setUpdateItemTable()
table.insert(self.item_table, {
text = "Screen rotate",
sub_item_table = {
{
text = "rotate 90 degree clockwise",
text = "landscape",
callback = function()
--Screen:screenRotate("clockwise")
Screen:setViewMode("landscape")
self.ui:handleEvent(
Event:new("SetDimensions", Screen:getSize()))
end
},
{
text = "rotate 90 degree anticlockwise",
text = "portrait",
callback = function()
--Screen:screenRotate("anticlockwise")
Screen:setViewMode("portrait")
self.ui:handleEvent(
Event:new("SetDimensions", Screen:getSize()))
end
@ -101,8 +104,10 @@ function ReaderMenu:onTapShowMenu()
end
function ReaderMenu:onSetDimensions(dimen)
-- @TODO update gesture listenning range according to new screen
-- orientation 15.12 2012 (houqp)
-- update listening according to new screen dimen
if Device:isTouchDevice() then
self:initGesListener()
end
end
function ReaderMenu:onCloseDocument()

@ -8,32 +8,7 @@ ReaderPaging = InputContainer:new{
}
function ReaderPaging:init()
if Device:isTouchDevice() then
self.ges_events = {
TapForward = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = Screen:getWidth()/4,
y = Screen:getHeight()/4,
w = 3*Screen:getWidth()/4,
h = 5*Screen:getHeight()/8,
}
}
},
TapBackward = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = 0,
y = Screen:getHeight()/4,
w = Screen:getWidth()/4,
h = 5*Screen:getHeight()/8,
}
}
}
}
else
if Device:hasKeyboard() then
self.key_events = {
GotoNextPage = {
{Input.group.PgFwd}, doc = "go to next page",
@ -67,6 +42,34 @@ function ReaderPaging:init()
self.number_of_pages = self.ui.document.info.number_of_pages
end
-- This method will be called in onSetDimensions handler
function ReaderPaging:initGesListener()
self.ges_events = {
TapForward = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = Screen:getWidth()/4,
y = Screen:getHeight()/4,
w = 3*Screen:getWidth()/4,
h = 5*Screen:getHeight()/8,
}
}
},
TapBackward = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = 0,
y = Screen:getHeight()/4,
w = Screen:getWidth()/4,
h = 5*Screen:getHeight()/8,
}
}
}
}
end
function ReaderPaging:onReadSettings(config)
self:gotoPage(config:readSetting("last_page") or 1)
local soe = config:readSetting("show_overlap_enable")
@ -90,24 +93,6 @@ function ReaderPaging:onTapBackward()
return true
end
-- wrapper for bounds checking
function ReaderPaging:gotoPage(number)
if number == self.current_page then
return true
end
if number > self.number_of_pages
or number < 1 then
DEBUG("wrong page number: "..number.."!")
return false
end
DEBUG("going to page number", number)
-- this is an event to allow other controllers to be aware of this change
self.ui:handleEvent(Event:new("PageUpdate", number))
return true
end
function ReaderPaging:onZoomModeUpdate(new_mode)
-- we need to remember zoom mode to handle page turn event
self.zoom_mode = new_mode
@ -232,3 +217,30 @@ function ReaderPaging:onRedrawCurrentPage()
self.ui:handleEvent(Event:new("PageUpdate", self.current_page))
return true
end
function ReaderPaging:onSetDimensions()
-- update listening according to new screen dimen
if Device:isTouchDevice() then
self:initGesListener()
end
end
-- wrapper for bounds checking
function ReaderPaging:gotoPage(number)
if number == self.current_page then
return true
end
if number > self.number_of_pages
or number < 1 then
DEBUG("wrong page number: "..number.."!")
return false
end
DEBUG("going to page number", number)
-- this is an event to allow other controllers to be aware of this change
self.ui:handleEvent(Event:new("PageUpdate", number))
return true
end

@ -14,32 +14,7 @@ ReaderRolling = InputContainer:new{
}
function ReaderRolling:init()
if Device:isTouchDevice() then
self.ges_events = {
TapForward = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = Screen:getWidth()/4,
y = Screen:getHeight()/4,
w = 3*Screen:getWidth()/4,
h = 5*Screen:getHeight()/8,
}
}
},
TapBackward = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = 0,
y = Screen:getHeight()/4,
w = Screen:getWidth()/4,
h = 5*Screen:getHeight()/8,
}
}
}
}
else
if Device:hasKeyboard() then
self.key_events = {
GotoNextView = {
{ Input.group.PgFwd },
@ -89,6 +64,34 @@ function ReaderRolling:init()
self.old_page = self.ui.document.info.number_of_pages
end
-- This method will be called in onSetDimensions handler
function ReaderRolling:initGesListener()
self.ges_events = {
TapForward = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = Screen:getWidth()/4,
y = Screen:getHeight()/4,
w = 3*Screen:getWidth()/4,
h = 5*Screen:getHeight()/8,
}
}
},
TapBackward = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = 0,
y = Screen:getHeight()/4,
w = Screen:getWidth()/4,
h = 5*Screen:getHeight()/8,
}
}
}
}
end
function ReaderRolling:onReadSettings(config)
local soe = config:readSetting("show_overlap_enable")
if not soe then
@ -223,6 +226,13 @@ function ReaderRolling:onRedrawCurrentView()
return true
end
function ReaderRolling:onSetDimensions()
-- update listening according to new screen dimen
if Device:isTouchDevice() then
self:initGesListener()
end
end
--[[
PosUpdate event is used to signal other widgets that pos has been changed.
--]]

@ -1,4 +1,5 @@
ReaderView = WidgetContainer:new{
_name = "ReaderView",
document = nil,
state = {

@ -1,46 +1,4 @@
ReaderZooming = InputContainer:new{
key_events = {
ZoomIn = {
{ "Shift", Input.group.PgFwd },
doc = "zoom in",
event = "Zoom", args = "in"
},
ZoomOut = {
{ "Shift", Input.group.PgBack },
doc = "zoom out",
event = "Zoom", args = "out"
},
ZoomToFitPage = {
{ "A" },
doc = "zoom to fit page",
event = "SetZoomMode", args = "page"
},
ZoomToFitContent = {
{ "Shift", "A" },
doc = "zoom to fit content",
event = "SetZoomMode", args = "content"
},
ZoomToFitPageWidth = {
{ "S" },
doc = "zoom to fit page width",
event = "SetZoomMode", args = "pagewidth"
},
ZoomToFitContentWidth = {
{ "Shift", "S" },
doc = "zoom to fit content width",
event = "SetZoomMode", args = "contentwidth"
},
ZoomToFitPageHeight = {
{ "D" },
doc = "zoom to fit page height",
event = "SetZoomMode", args = "pageheight"
},
ZoomToFitContentHeight = {
{ "Shift", "D" },
doc = "zoom to fit content height",
event = "SetZoomMode", args = "contentheight"
},
},
zoom = 1.0,
-- default to nil so we can trigger ZoomModeUpdate events on start up
zoom_mode = nil,
@ -50,6 +8,50 @@ ReaderZooming = InputContainer:new{
}
function ReaderZooming:init()
if Device:hasKeyboard() then
self.key_events = {
ZoomIn = {
{ "Shift", Input.group.PgFwd },
doc = "zoom in",
event = "Zoom", args = "in"
},
ZoomOut = {
{ "Shift", Input.group.PgBack },
doc = "zoom out",
event = "Zoom", args = "out"
},
ZoomToFitPage = {
{ "A" },
doc = "zoom to fit page",
event = "SetZoomMode", args = "page"
},
ZoomToFitContent = {
{ "Shift", "A" },
doc = "zoom to fit content",
event = "SetZoomMode", args = "content"
},
ZoomToFitPageWidth = {
{ "S" },
doc = "zoom to fit page width",
event = "SetZoomMode", args = "pagewidth"
},
ZoomToFitContentWidth = {
{ "Shift", "S" },
doc = "zoom to fit content width",
event = "SetZoomMode", args = "contentwidth"
},
ZoomToFitPageHeight = {
{ "D" },
doc = "zoom to fit page height",
event = "SetZoomMode", args = "pageheight"
},
ZoomToFitContentHeight = {
{ "Shift", "D" },
doc = "zoom to fit content height",
event = "SetZoomMode", args = "contentheight"
},
}
end
self.ui.menu:registerToMainMenu(self)
end

@ -40,18 +40,42 @@ Codes for rotation modes:
Screen = {
cur_rotation_mode = 0,
-- these two variabls are used to help switching from framework to reader
width = 0,
height = 0,
pitch = 0,
native_rotation_mode = nil,
kpv_rotation_mode = nil,
cur_rotation_mode = 0,
bb = nil,
saved_bb = nil,
fb = einkfb.open("/dev/fb0")
fb = einkfb.open("/dev/fb0"),
}
function Screen:init()
_, self.height = self.fb:getSize()
-- for unknown strange reason, pitch*2 is less than screen width in KPW
-- so we need to calculate width by pitch here
self.width = self.fb:getPitch()*2
self.pitch = self:getPitch()
self.bb = Blitbuffer.new(self.width, self.height, self.pitch)
self.native_rotation_mode = self.fb:getOrientation()
self.cur_rotation_mode = self.native_rotation_mode
end
function Screen:refresh(refesh_type)
if self.native_rotation_mode == self.cur_rotation_mode then
self.fb.bb:blitFrom(self.bb, 0, 0, 0, 0, self.width, self.height)
elseif self.native_rotation_mode == 0 and self.cur_rotation_mode == 1 then
self.fb.bb:blitFromRotate(self.bb, 270)
end
self.fb:refresh(refesh_type)
end
-- @orien: 1 for clockwise rotate, -1 for anti-clockwise
-- Remember to reread screen resolution after this function call
-- WARNING: this method is deprecated!!! use setRotationMode() or
-- setViewMode() instead.
function Screen:screenRotate(orien)
if orien == "clockwise" then
orien = -1
@ -70,22 +94,19 @@ function Screen:screenRotate(orien)
end
function Screen:getSize()
local w, h = self.fb:getSize()
return Geom:new{w = w, h = h}
return Geom:new{w = self.width, h = self.height}
end
function Screen:getWidth()
local w, _ = self.fb:getSize()
return w
return self.width
end
function Screen:getHeight()
local _, h = self.fb:getSize()
return h
return self.height
end
function Screen:getPitch()
return self.fb:getPitch()
return self.ptich
end
function Screen:updateRotationMode()
@ -94,7 +115,46 @@ function Screen:updateRotationMode()
end
function Screen:setRotationMode(mode)
self.fb:setOrientation(Screen.native_rotation_mode)
-- mode 0 and mode 2 has the same width and height, so do mode 1 and 3
if (self.cur_rotation_mode % 2) ~= (mode % 2) then
self.width, self.height = self.height, self.width
end
self.cur_rotation_mode = mode
self.bb:free()
self.pitch = self.width/2
self.bb = Blitbuffer.new(self.width, self.height, self.pitch)
end
function Screen:setViewMode(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 ~= 1 then
self:setRotationMode(1)
end
end
end
--[[
@brief change gesture's x and y coordinates according to screen view mode
@param ges gesture that you want to adjust
@return adjusted gesture.
--]]
function Screen:adjustGesCoordinate(ges)
-- we do nothing is screen is not rotated
if self.native_rotation_mode == self.cur_rotation_mode then
return ges
end
if self.native_rotation_mode == 0 and self.cur_rotation_mode == 1 then
ges.pos.x, ges.pos.y = (self.width - ges.pos.y), (ges.pos.x)
end
return ges
end
function Screen:saveCurrentBB()

@ -5,9 +5,9 @@ require "ui/widget"
require "ui/screen"
require "settings" -- for DEBUG(), TODO: put DEBUG() somewhere else
-- initialize output module, this must be initialized before Input
Screen:init()
-- initialize the input handling
Input:init()
@ -164,7 +164,7 @@ function UIManager:run()
local dirty = false
for _, widget in ipairs(self._window_stack) do
if self.repaint_all or self._dirty[widget.widget] then
widget.widget:paintTo(Screen.fb.bb, widget.x, widget.y)
widget.widget:paintTo(Screen.bb, widget.x, widget.y)
if self._dirty[widget.widget] == "full" then
self.refresh_type = 0
end
@ -178,7 +178,7 @@ function UIManager:run()
if dirty then
-- refresh FB
Screen.fb:refresh(self.refresh_type) -- TODO: refresh explicitly only repainted area
Screen:refresh(self.refresh_type) -- TODO: refresh explicitly only repainted area
-- reset refresh_type
self.refresh_type = 1
end
@ -204,7 +204,7 @@ function UIManager:run()
-- delegate input_event to handler
if input_event then
DEBUG(input_event)
DEBUG("in ui.lua:", input_event)
if input_event == "IntoSS" then
Device:intoScreenSaver()
elseif input_event == "OutOfSS" then

Loading…
Cancel
Save