first demo of gesture parsing

pull/2/merge
Qingping Hou 12 years ago
parent 36a4ead630
commit 3486ae7e09

@ -146,8 +146,8 @@ for points, it is basically an equality check
function Geom:contains(rect_b)
if self.x <= rect_b.x
and self.y <= rect_b.y
and self.x + self.w <= rect_b.x + rect_b.w
and self.y + self.h <= rect_b.y + rect_b.h
and self.x + self.w >= rect_b.x + rect_b.w
and self.y + self.h >= rect_b.y + rect_b.h
then
return true
end

@ -0,0 +1,115 @@
require "ui/geometry"
-- Synchronization events (SYN.code).
SYN_REPORT = 0
SYN_CONFIG = 1
SYN_MT_REPORT = 2
-- For multi-touch events (ABS.code).
ABS_MT_SLOT = 47
ABS_MT_POSITION_X = 53
ABS_MT_POSITION_Y = 54
ABS_MT_TRACKING_ID = 57
ABS_MT_PRESSURE = 58
GestureRange = {
ges = nil,
range = nil,
}
function GestureRange:new(o)
local o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function GestureRange:match(gs)
if gs.ges ~= self.ges then
return false
end
if self.range:contains(gs.pos) then
DEBUG(self, gs)
return true
end
return false
end
GestureDetector = {
ev_stack = {},
cur_ev = {},
}
--[[
MT_TRACK_ID: 0
MT_X: 310
MT_Y: 174
SYN REPORT
MT_TRACK_ID: -1
SYN REPORT
MT_TRACK_ID: 0
MT_X: 222
MT_Y: 207
SYN REPORT
MT_TRACK_ID: -1
SYN REPORT
--]]
function GestureDetector:feedEvent(ev)
if ev.type == EV_SYN then
if ev.code == SYN_REPORT then
-- end of one event or release touch?
if self.cur_ev.id == -1 then
-- touch release?
return self:guessGesture()
else
table.insert(self.ev_stack, self.cur_ev)
self.cur_ev = {}
--DEBUG(self.ev_stack)
end
end
elseif ev.type == EV_ABS then
if ev.code == ABS_MT_SLOT then
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 GestureDetector:guessGesture()
local is_recognized = false
local result = nil
local last_ev = {pos = Geom:new{}}
for k,ev in ipairs(self.ev_stack) do
--@TODO do real recognization here (houqp)
is_recognized = true
result = {
ges = "tap",
pos = Geom:new{
x = ev.x or last_ev.x,
y = ev.y or last_ev.x,
w = 0,
h = 0,
}
}
last_ev = ev
end
if is_recognized then
self.ev_stack = {}
return result
else
DEBUG("Unknown gesture!!", self.ev_stack)
self.ev_stack = {}
end
end

@ -1,5 +1,6 @@
require "ui/event"
require "ui/device"
require "ui/gesturedetector"
require "settings"
-- constants from <linux/input.h>
@ -7,18 +8,6 @@ EV_SYN = 0
EV_KEY = 1
EV_ABS = 3
-- Synchronization events (SYN.code).
SYN_REPORT = 0
SYN_CONFIG = 1
SYN_MT_REPORT = 2
-- For multi-touch events (ABS.code).
ABS_MT_SLOT = 47
ABS_MT_POSITION_X = 53
ABS_MT_POSITION_Y = 54
ABS_MT_TRACKING_ID = 57
ABS_MT_PRESSURE = 58
-- key press event values (KEY.value)
EVENT_VALUE_KEY_PRESS = 1
EVENT_VALUE_KEY_REPEAT = 2
@ -341,29 +330,35 @@ function Input:waitEvent(timeout_us, timeout_s)
elseif ev.value == EVENT_VALUE_KEY_RELEASE then
return Event:new("KeyRelease", key)
end
elseif ev.type == EV_ABS then
if ev.code == ABS_MT_SLOT then
DEBUG("MT_SLOT:", ev.value)
elseif ev.code == ABS_MT_TRACKING_ID then
DEBUG("MT_TRACK_ID:", ev.value)
elseif ev.code == ABS_MT_POSITION_X then
DEBUG("MT_X:", ev.value)
elseif ev.code == ABS_MT_POSITION_Y then
DEBUG("MT_Y:", ev.value)
else
DEBUG("unknown touch event!", ev)
return Event:new("UnkonwnTouchEvent", ev)
end
elseif ev.type == EV_SYN then
if ev.code == SYN_REPORT then
DEBUG("SYN REPORT")
elseif ev.code == SYN_MT_REPORT then
DEBUG("SYN MT_REPORT")
elseif ev.code == SYN_CONFIG then
DEBUG("SYN CONFIG")
else
DEBUG(ev)
elseif ev.type == EV_ABS or ev.type == EV_SYN then
local touch_ges = GestureDetector:feedEvent(ev)
DEBUG(touch_ges)
if touch_ges then
return Event:new("Gesture", touch_ges)
end
--elseif ev.type == EV_ABS then
--if ev.code == ABS_MT_SLOT then
--DEBUG("MT_SLOT:", ev.value)
--elseif ev.code == ABS_MT_TRACKING_ID then
--DEBUG("MT_TRACK_ID:", ev.value)
--elseif ev.code == ABS_MT_POSITION_X then
--DEBUG("MT_X:", ev.value)
--elseif ev.code == ABS_MT_POSITION_Y then
--DEBUG("MT_Y:", ev.value)
--else
--DEBUG("unknown touch event!", ev)
--return Event:new("UnkonwnTouchEvent", ev)
--end
--elseif ev.type == EV_SYN then
--if ev.code == SYN_REPORT then
--DEBUG("SYN REPORT")
--elseif ev.code == SYN_MT_REPORT then
--DEBUG("SYN MT_REPORT")
--elseif ev.code == SYN_CONFIG then
--DEBUG("SYN CONFIG")
--else
--DEBUG(ev)
--end
else
-- some other kind of event that we do not know yet
return Event:new("GenericInput", ev)

@ -80,6 +80,21 @@ function MenuItem:init()
self.active_key_events = {
Select = { {"Press"}, doc = "chose selected item" },
}
self.ges_events = {
TapSelect = {
GestureRange:new{
ges = "tap",
range = self.dimen,
--range = Geom:new{
--x = self.dimen.x,
--y = self.dimen.y,
--h = self.dimen.h,
--w = self.dimen.w,
--},
},
doc = "Select Menu Item",
},
}
w = sizeUtf8Text(0, self.dimen.w, self.face, self.text, true).x
if w >= self.content_width then
@ -136,6 +151,11 @@ function MenuItem:onShowItemDetail()
return true
end
function MenuItem:onTapSelect()
self.menu:onMenuSelect(self.table)
return true
end
--[[
Widget that displays menu
@ -265,9 +285,11 @@ function Menu:updateItems(select_number)
local item_tmp = MenuItem:new{
text = self.item_table[i].text,
face = self.cface,
dimen = self.item_dimen,
dimen = self.item_dimen:new(),
shortcut = item_shortcut,
shortcut_style = shortcut_style,
table = self.item_table[i],
menu = self,
}
table.insert(self.item_group, item_tmp)
table.insert(self.layout, {item_tmp})

@ -4,6 +4,7 @@ require "ui/graphics"
require "ui/image"
require "ui/event"
require "ui/inputevent"
require "ui/gesturedetector"
require "ui/font"
--[[
@ -60,7 +61,7 @@ function WidgetContainer:getSize()
-- return size of first child widget
return self[1]:getSize()
else
return { w = 0, h = 0 }
return Geom:new{ w = 0, h = 0 }
end
end
@ -513,9 +514,18 @@ it is suggested to reference configurable sequences from another table
and store that table as configuration setting
]]
InputContainer = WidgetContainer:new{
key_events = {}
key_events = {},
ges_events = {},
}
function InputContainer:paintTo(bb, x, y)
self.dimen.x = x
self.dimen.y = y
if self[1] then
return self[1]:paintTo(bb, x, y)
end
end
-- the following handler handles keypresses and checks
-- if they lead to a command.
-- if this is the case, we retransmit another event within
@ -533,3 +543,15 @@ function InputContainer:onKeyPress(key)
end
end
function InputContainer:onGesture(ev)
for name, gsseq in pairs(self.ges_events) do
for _, gs_range in ipairs(gsseq) do
if gs_range:match(ev) then
--DEBUG(gs_range)
local eventname = gsseq.event or name
return self:handleEvent(Event:new(eventname, gsseq.args, ev))
end
end
end
end

Loading…
Cancel
Save