move multishell functionality to kernel

This commit is contained in:
kepler155c@gmail.com
2018-01-10 16:46:37 -05:00
parent 13ec8ea04f
commit d224f5df25
20 changed files with 467 additions and 409 deletions

View File

@@ -58,33 +58,37 @@ local function nextUID()
return Event.uid - 1
end
function Event.on(event, fn)
function Event.on(events, fn)
events = type(events) == 'table' and events or { events }
local handlers = Event.types[event]
if not handlers then
handlers = { }
Event.types[event] = handlers
end
local handler = {
local handler = setmetatable({
uid = nextUID(),
event = event,
event = events,
fn = fn,
}
handlers[handler.uid] = handler
setmetatable(handler, { __index = Routine })
}, { __index = Routine })
for _,event in pairs(events) do
local handlers = Event.types[event]
if not handlers then
handlers = { }
Event.types[event] = handlers
end
handlers[handler.uid] = handler
end
return handler
end
function Event.off(h)
if h and h.event then
Event.types[h.event][h.uid] = nil
for _,event in pairs(h.event) do
Event.types[event][h.uid] = nil
end
end
end
local function addTimer(interval, recurring, fn)
local timerId = os.startTimer(interval)
local handler
@@ -133,20 +137,18 @@ function Event.waitForEvent(event, timeout)
end
function Event.addRoutine(fn)
local r = {
local r = setmetatable({
co = coroutine.create(fn),
uid = nextUID()
}
setmetatable(r, { __index = Routine })
Event.routines[r.uid] = r
}, { __index = Routine })
Event.routines[r.uid] = r
r:resume()
return r
end
function Event.pullEvents(...)
for _, fn in ipairs({ ... }) do
Event.addRoutine(fn)
end
@@ -162,7 +164,6 @@ function Event.exitPullEvents()
end
local function processHandlers(event)
local handlers = Event.types[event]
if handlers then
for _,h in pairs(handlers) do
@@ -184,7 +185,6 @@ local function tokeys(t)
end
local function processRoutines(...)
local keys = tokeys(Event.routines)
for _,key in ipairs(keys) do
local r = Event.routines[key]
@@ -200,7 +200,6 @@ function Event.processEvent(e)
end
function Event.pullEvent(eventType)
while true do
local e = { os.pullEventRaw() }

View File

@@ -1,7 +1,8 @@
local Util = require('util')
local keys = _G.keys
local os = _G.os
local keyboard = _G.device.keyboard
local keys = _G.keys
local os = _G.os
local modifiers = Util.transpose {
keys.leftCtrl, keys.rightCtrl,
@@ -10,28 +11,31 @@ local modifiers = Util.transpose {
}
local input = {
pressed = { },
state = { },
}
function input:modifierPressed()
return self.pressed[keys.leftCtrl] or
self.pressed[keys.rightCtrl] or
self.pressed[keys.leftAlt] or
self.pressed[keys.rightAlt]
return keyboard.state[keys.leftCtrl] or
keyboard.state[keys.rightCtrl] or
keyboard.state[keys.leftAlt] or
keyboard.state[keys.rightAlt]
end
function input:toCode(ch, code)
local result = { }
if self.pressed[keys.leftCtrl] or self.pressed[keys.rightCtrl] then
if keyboard.state[keys.leftCtrl] or keyboard.state[keys.rightCtrl] or
code == keys.leftCtrl or code == keys.rightCtrl then
table.insert(result, 'control')
end
if self.pressed[keys.leftAlt] or self.pressed[keys.rightAlt] then
if keyboard.state[keys.leftAlt] or keyboard.state[keys.rightAlt] or
code == keys.leftAlt or code == keys.rightAlt then
table.insert(result, 'alt')
end
if self.pressed[keys.leftShift] or self.pressed[keys.rightShift] then
if keyboard.state[keys.leftShift] or keyboard.state[keys.rightShift] or
code == keys.leftShift or code == keys.rightShift then
if code and modifiers[code] then
table.insert(result, 'shift')
elseif #ch == 1 then
@@ -48,7 +52,7 @@ function input:toCode(ch, code)
end
function input:reset()
self.pressed = { }
self.state = { }
self.fired = nil
self.timer = nil
@@ -64,7 +68,7 @@ function input:translate(event, code, p1, p2)
return input:toCode(keys.getName(code), code)
end
else
self.pressed[code] = true
self.state[code] = true
if self:modifierPressed() and not modifiers[code] or code == 57 then
self.fired = true
return input:toCode(keys.getName(code), code)
@@ -81,18 +85,18 @@ function input:translate(event, code, p1, p2)
elseif event == 'key_up' then
if not self.fired then
if self.pressed[code] then
if self.state[code] then
self.fired = true
local ch = input:toCode(keys.getName(code), code)
self.pressed[code] = nil
self.state[code] = nil
return ch
end
end
self.pressed[code] = nil
self.state[code] = nil
elseif event == 'paste' then
self.pressed[keys.leftCtrl] = nil
self.pressed[keys.rightCtrl] = nil
--self.state[keys.leftCtrl] = nil
--self.state[keys.rightCtrl] = nil
self.fired = true
return input:toCode('paste', 255)
@@ -147,4 +151,4 @@ function input:test()
end
end
return input
return input

View File

@@ -68,6 +68,7 @@ local function encodeCommon(val, pretty, tabLevel, tTracking)
str = str .. encodeCommon(v, pretty, tabLevel, tTracking)
end)
else
debug(val)
arrEncoding(val, "{", "}", pairs, function(k,v)
assert(type(k) == "string", "JSON object keys must be strings", 2)
str = str .. encodeCommon(k, pretty, tabLevel, tTracking)
@@ -94,6 +95,13 @@ function json.encodePretty(val)
return encodeCommon(val, true, 0, {})
end
function json.encodeToFile(path, val)
local file = io.open(path, "w")
assert(file, "Unable to open file")
file:write(json.encodePretty(val))
file:close()
end
------------------------------------------------------------------ decoding
local decodeControls = {}

View File

@@ -2,6 +2,8 @@ local Event = require('event')
local Socket = require('socket')
local Util = require('util')
local os = _G.os
local Peripheral = Util.shallowCopy(_G.peripheral)
function Peripheral.getList()
@@ -176,12 +178,12 @@ local function getProxy(pi)
if proxy.type == 'monitor' then
Event.addRoutine(function()
while true do
local event = socket:read()
if not event then
local data = socket:read()
if not data then
break
end
if not Util.empty(event) then
os.queueEvent(table.unpack(event))
if data.fn and data.fn == 'event' then
os.queueEvent(table.unpack(data.data))
end
end
end)

View File

@@ -43,111 +43,6 @@ end
--[[-- Top Level Manager --]]--
local Manager = class()
function Manager:init()
local running = false
-- single thread all input events
local function singleThread(event, fn)
Event.on(event, function(_, ...)
if not running then
running = true
fn(...)
running = false
else
Input:translate(event, ...)
end
end)
end
Event.on('multishell_focus', function()
Input:reset()
end)
singleThread('term_resize', function(side)
if self.currentPage then
-- the parent doesn't have any children set...
-- that's why we have to resize both the parent and the current page
-- kinda makes sense
if self.currentPage.parent.device.side == side then
self.currentPage.parent:resize()
self.currentPage:resize()
self.currentPage:draw()
self.currentPage:sync()
end
end
end)
singleThread('mouse_scroll', function(direction, x, y)
if self.currentPage then
local event = self.currentPage:pointToChild(x, y)
local directions = {
[ -1 ] = 'up',
[ 1 ] = 'down'
}
-- revisit - should send out scroll_up and scroll_down events
-- let the element convert them to up / down
self:inputEvent(event.element,
{ type = 'key', key = directions[direction] })
self.currentPage:sync()
end
end)
-- this should be moved to the device !
singleThread('monitor_touch', function(side, x, y)
if self.currentPage then
if self.currentPage.parent.device.side == side then
self:click('mouse_click', 1, x, y)
end
end
end)
singleThread('mouse_click', function(button, x, y)
Input:translate('mouse_click', button, x, y)
if self.currentPage then
if not self.currentPage.parent.device.side then
local event = self.currentPage:pointToChild(x, y)
if event.element.focus and not event.element.inactive then
self.currentPage:setFocus(event.element)
self.currentPage:sync()
end
end
end
end)
singleThread('mouse_up', function(button, x, y)
local ch = Input:translate('mouse_up', button, x, y)
if ch == 'control-shift-mouse_click' then -- hack
local event = self.currentPage:pointToChild(x, y)
_ENV.multishell.openTab({
path = 'sys/apps/Lua.lua',
args = { event.element },
focused = true })
elseif ch and self.currentPage then
if not self.currentPage.parent.device.side then
self:click(ch, button, x, y)
end
end
end)
singleThread('mouse_drag', function(button, x, y)
local ch = Input:translate('mouse_drag', button, x, y)
if ch and self.currentPage then
local event = self.currentPage:pointToChild(x, y)
event.type = ch
self:inputEvent(event.element, event)
self.currentPage:sync()
end
end)
singleThread('paste', function(text)
Input:translate('paste')
self:emitEvent({ type = 'paste', text = text })
self.currentPage:sync()
end)
local function keyFunction(event, code, held)
local ch = Input:translate(event, code, held)
@@ -159,9 +54,108 @@ function Manager:init()
end
end
singleThread('char', function(code, held) keyFunction('char', code, held) end)
singleThread('key_up', function(code, held) keyFunction('key_up', code, held) end)
singleThread('key', function(code, held) keyFunction('key', code, held) end)
local handlers = {
char = keyFunction,
key_up = keyFunction,
key = keyFunction,
term_resize = function(_, side)
if self.currentPage then
-- the parent doesn't have any children set...
-- that's why we have to resize both the parent and the current page
-- kinda makes sense
if self.currentPage.parent.device.side == side then
self.currentPage.parent:resize()
self.currentPage:resize()
self.currentPage:draw()
self.currentPage:sync()
end
end
end,
mouse_scroll = function(_, direction, x, y)
if self.currentPage then
local event = self.currentPage:pointToChild(x, y)
local directions = {
[ -1 ] = 'up',
[ 1 ] = 'down'
}
-- revisit - should send out scroll_up and scroll_down events
-- let the element convert them to up / down
self:inputEvent(event.element,
{ type = 'key', key = directions[direction] })
self.currentPage:sync()
end
end,
-- this should be moved to the device !
monitor_touch = function(_, side, x, y)
Input:translate('mouse_click', 1, x, y)
local ch = Input:translate('mouse_up', 1, x, y)
if self.currentPage then
if self.currentPage.parent.device.side == side then
self:click(ch, 1, x, y)
end
end
end,
mouse_click = function(_, button, x, y)
Input:translate('mouse_click', button, x, y)
if self.currentPage then
if not self.currentPage.parent.device.side then
local event = self.currentPage:pointToChild(x, y)
if event.element.focus and not event.element.inactive then
self.currentPage:setFocus(event.element)
self.currentPage:sync()
end
end
end
end,
mouse_up = function(_, button, x, y)
local ch = Input:translate('mouse_up', button, x, y)
if ch == 'control-shift-mouse_click' then -- hack
local event = self.currentPage:pointToChild(x, y)
_ENV.multishell.openTab({
path = 'sys/apps/Lua.lua',
args = { event.element },
focused = true })
elseif ch and self.currentPage then
if not self.currentPage.parent.device.side then
self:click(ch, button, x, y)
end
end
end,
mouse_drag = function(_, button, x, y)
local ch = Input:translate('mouse_drag', button, x, y)
if ch and self.currentPage then
local event = self.currentPage:pointToChild(x, y)
event.type = ch
self:inputEvent(event.element, event)
self.currentPage:sync()
end
end,
paste = function(_, text)
Input:translate('paste')
self:emitEvent({ type = 'paste', text = text })
self.currentPage:sync()
end,
}
-- use 1 handler to single thread all events
Event.on({
'char', 'key_up', 'key', 'term_resize',
'mouse_scroll', 'monitor_touch', 'mouse_click',
'mouse_up', 'mouse_drag', 'paste' },
function(event, ...)
handlers[event](event, ...)
end)
end
function Manager:configure(appName, ...)

View File

@@ -460,6 +460,8 @@ function Util.toBytes(n)
if not tonumber(n) then error('Util.toBytes: n must be a number', 2) end
if n >= 1000000 or n <= -1000000 then
return string.format('%sM', math.floor(n/1000000 * 10) / 10)
elseif n >= 10000 or n <= -10000 then
return string.format('%sK', math.floor(n/1000))
elseif n >= 1000 or n <= -1000 then
return string.format('%sK', math.floor(n/1000 * 10) / 10)
end
@@ -549,7 +551,6 @@ end
-- end word wrapping
function Util.wordWrap(str, limit)
local longLines = Util.split(str)
local lines = { }
@@ -560,6 +561,23 @@ function Util.wordWrap(str, limit)
return lines
end
function Util.args(arg)
local tab = { remainder = { } }
local k = 1
while k <= #arg do
local v = arg[k]
if string.sub(v, 1, 1) == '-' then
local jopt = string.sub(v, 2)
tab[ jopt ] = arg[ k + 1 ]
k = k + 1
else
table.insert(tab.remainder, v)
end
k = k + 1
end
return tab
end
-- http://lua-users.org/wiki/AlternativeGetOpt
local function getopt( arg, options )
local tab = {}