Make sys-everest a bit smaller by eliminating abstraction.

This commit is contained in:
20kdc 2018-06-12 01:35:15 +01:00
parent 3ba0792dfe
commit 050941a513
1 changed files with 207 additions and 224 deletions

View File

@ -46,7 +46,7 @@ local monitors = {}
-- This is where we stuff processes until monitors show up
monitors[0] = {nil, nil, 160, 50}
-- {monitor, x, y, w, h, callback}
-- {monitor, x, y, w, h, callback, title}
-- callback events are:
-- key ka kc down
-- line y
@ -61,10 +61,12 @@ local shuttingDown = false
-- Also used for settings.
local savingThrow = neo.requestAccess("x.neo.sys.manage")
local draggingWindowX, draggingWindowY
local function suggestAppsStop()
for k, v in ipairs(surfaces) do
for i = 1, 4 do
v[6]("close")
v[6](v[8], "close")
end
end
end
@ -81,8 +83,8 @@ local function dying()
-- If a process evades the deathtrap then it clearly has reason to stay alive regardless of Everest status.
-- Also note, should savingThrow fail, neo.dead is now a thing.
for _, v in ipairs(surfaces) do
pcall(v[6], "line", 1)
pcall(v[6], "line", 2)
pcall(v[6], v[8], "line", 1)
pcall(v[6], v[8], "line", 2)
end
surfaces = {}
end
@ -147,155 +149,6 @@ local function doBackgroundLine(m, mg, bdx, bdy, bdl)
end
end
local function updateRegion(monitorId, x, y, w, h, surfaceSpanCache)
if not renderingAllowed() then return end
local m = monitors[monitorId]
local mg, rb = m[1]()
if not mg then return end
if rb then
monitorResetBF(m)
end
-- The input region is the one that makes SENSE.
-- Considering WC handling, that's not an option.
-- WCHAX: start
if x > 1 then
x = x - 1
w = w + 1
end
-- this, in combination with 'forcefully blank out last column of window during render',
-- cleans up littering
w = w + 1
-- WCHAX: end
for span = 1, h do
local backgroundMarkStart = nil
for sx = 1, w do
local t, tx, ty = surfaceAt(monitorId, sx + x - 1, span + y - 1)
if t then
-- Background must occur first due to wide char weirdness
if backgroundMarkStart then
local bdx, bdy, bdl = backgroundMarkStart + x - 1, span + y - 1, sx - backgroundMarkStart
doBackgroundLine(m, mg, bdx, bdy, bdl)
backgroundMarkStart = nil
end
if not surfaceSpanCache[monitorId .. "_" .. t .. "_" .. ty] then
surfaceSpanCache[monitorId .. "_" .. t .. "_" .. ty] = true
surfaces[t][6]("line", ty)
end
elseif not backgroundMarkStart then
backgroundMarkStart = sx
end
end
if backgroundMarkStart then
doBackgroundLine(monitors[monitorId], mg, backgroundMarkStart + x - 1, span + y - 1, (w - backgroundMarkStart) + 1)
end
end
end
local function updateStatus()
statusLine = "Λ-¶: menu (launch 'control' to logout)"
if surfaces[1] then
if #monitors > 1 then
-- 123456789X123456789X123456789X123456789X123456789X
statusLine = "Λ-+: move, Λ-Z: switch, Λ-X: swMonitor, Λ-C: close"
else
statusLine = "Λ-+: move, Λ-Z: switch, Λ-C: close"
end
end
statusLine = unicode.safeTextFormat(statusLine)
for k, v in ipairs(monitors) do
updateRegion(k, 1, 1, v[3], 1, {})
end
end
local function ensureOnscreen(monitor, x, y, w, h)
if monitor <= 0 then monitor = #monitors end
if monitor >= (#monitors + 1) then monitor = 1 end
-- Failing anything else, revert to monitor 0
if #monitors == 0 then monitor = 0 end
x = math.min(math.max(1, x - (w - 1)), monitors[monitor][3])
y = math.max(2 - h, math.min(monitors[monitor][4], y))
return monitor, x, y
end
-- This is the "a state change occurred" function, only for use when needed
local function reconcileAll()
for k, v in ipairs(surfaces) do
-- About to update whole screen anyway so avoid the wait.
v[1], v[2], v[3] = ensureOnscreen(v[1], v[2], v[3], v[4], v[5])
end
local k = 1
while k <= #monitors do
local v = monitors[k]
local mon, rb = v[1]()
if rb then
monitorResetBF(v)
end
if mon then
-- This *can* return null if something went wonky. Let's detect that
v[3], v[4] = mon.getResolution()
if not v[3] then
neo.emergency("everest: monitor went AWOL and nobody told me u.u")
table.remove(monitors, k)
v = nil
end
end
if v then
updateRegion(k, 1, 1, v[3], v[4], {})
k = k + 1
end
end
updateStatus()
end
-- NOTE: If the M, X, Y, W and H are the same, this function ignores you, unless you put , true on the end.
local function moveSurface(surface, m, x, y, w, h, force)
local om, ox, oy, ow, oh = table.unpack(surface, 1, 5)
m = m or om
x = x or ox
y = y or oy
w = w or ow
h = h or oh
surface[1], surface[2], surface[3], surface[4], surface[5] = m, x, y, w, h
local cache = {}
if om == m and ow == w and oh == h then
if ox == x and oy == y and not force then
return
end
-- note: this doesn't always work due to WC support, and due to resize-to-repaint
if renderingAllowed() and not force then
local cb, b = monitors[m][1]()
if b then
monitorResetBF(monitors[m])
end
if cb then
pcall(cb.copy, ox, oy, w, h, x - ox, y - oy)
if surface == surfaces[1] then
local cacheControl = {}
for i = 1, h do
cacheControl[om .. "_1_" .. i] = true
end
updateRegion(om, ox, oy, ow, oh, cacheControl)
return
end
end
end
end
updateRegion(om, ox, oy, ow, oh, cache)
updateRegion(m, x, y, w, h, cache)
end
-- Returns offset from where we expected to be to where we are.
local function ofsSurface(focus, dx, dy)
local exX, exY = focus[2] + dx, focus[3] + dy
local m, x, y = ensureOnscreen(focus[1], exX, exY, focus[4], focus[5])
moveSurface(focus, nil, x, y)
return focus[2] - exX, focus[3] - exY
end
local function ofsMSurface(focus, dm)
local m, x, y = ensureOnscreen(focus[1] + dm, focus[2], focus[3], focus[4], focus[5])
moveSurface(focus, m, x, y)
end
local function handleSpan(target, x, y, text, bg, fg)
if not renderingAllowed() then return end
local m = monitors[target[1]]
@ -353,6 +206,178 @@ local function handleSpan(target, x, y, text, bg, fg)
submitSegment()
end
local function updateRegion(monitorId, x, y, w, h, surfaceSpanCache)
if not renderingAllowed() then return end
local m = monitors[monitorId]
local mg, rb = m[1]()
if not mg then return end
if rb then
monitorResetBF(m)
end
-- The input region is the one that makes SENSE.
-- Considering WC handling, that's not an option.
-- WCHAX: start
if x > 1 then
x = x - 1
w = w + 1
end
-- this, in combination with 'forcefully blank out last column of window during render',
-- cleans up littering
w = w + 1
-- WCHAX: end
for span = 1, h do
local backgroundMarkStart = nil
for sx = 1, w do
local t, tx, ty = surfaceAt(monitorId, sx + x - 1, span + y - 1)
if t then
-- Background must occur first due to wide char weirdness
if backgroundMarkStart then
local bdx, bdy, bdl = backgroundMarkStart + x - 1, span + y - 1, sx - backgroundMarkStart
doBackgroundLine(m, mg, bdx, bdy, bdl)
backgroundMarkStart = nil
end
if not surfaceSpanCache[monitorId .. "_" .. t .. "_" .. ty] then
surfaceSpanCache[monitorId .. "_" .. t .. "_" .. ty] = true
if ty == 1 then
local lw = surfaces[t][4]
local bg = 0x0080FF
local fg = 0x000000
local tx = "-"
if t == 1 then
bg = 0x000000
fg = 0x0080FF
tx = "+"
end
local vtitle = surfaces[t][7]
local vto = unicode.len(vtitle)
if vto < lw then
vtitle = vtitle .. (tx):rep(lw - vto)
else
vtitle = unicode.sub(vtitle, 1, lw)
end
handleSpan(surfaces[t], 1, 1, vtitle, bg, fg)
else
surfaces[t][6](surfaces[t][8], "line", ty - 1)
end
end
elseif not backgroundMarkStart then
backgroundMarkStart = sx
end
end
if backgroundMarkStart then
doBackgroundLine(monitors[monitorId], mg, backgroundMarkStart + x - 1, span + y - 1, (w - backgroundMarkStart) + 1)
end
end
end
local function updateStatus()
statusLine = "Λ-¶: menu (launch 'control' to logout)"
if surfaces[1] then
if #monitors > 1 then
-- 123456789X123456789X123456789X123456789X123456789X
statusLine = "Λ-+: move, Λ-Z: switch, Λ-X: swMonitor, Λ-C: close"
else
statusLine = "Λ-+: move, Λ-Z: switch, Λ-C: close"
end
end
statusLine = unicode.safeTextFormat(statusLine)
for k, v in ipairs(monitors) do
updateRegion(k, 1, 1, v[3], 1, {})
end
end
local function ensureOnscreen(monitor, x, y, w, h)
if monitor <= 0 then monitor = #monitors end
if monitor >= (#monitors + 1) then monitor = 1 end
-- Failing anything else, revert to monitor 0
if #monitors == 0 then monitor = 0 end
x = math.min(math.max(x, 1), monitors[monitor][3] - (w - 1))
y = math.max(2 - h, math.min(monitors[monitor][4], y))
return monitor, x, y
end
-- This is the "a state change occurred" function, only for use when needed
local function reconcileAll()
for k, v in ipairs(surfaces) do
-- About to update whole screen anyway so avoid the wait.
v[1], v[2], v[3] = ensureOnscreen(v[1], v[2], v[3], v[4], v[5])
end
local k = 1
while k <= #monitors do
local v = monitors[k]
local mon, rb = v[1]()
if rb then
monitorResetBF(v)
end
if mon then
-- This *can* return null if something went wonky. Let's detect that
v[3], v[4] = mon.getResolution()
if not v[3] then
neo.emergency("everest: monitor went AWOL and nobody told me u.u")
table.remove(monitors, k)
v = nil
end
end
if v then
updateRegion(k, 1, 1, v[3], v[4], {})
k = k + 1
end
end
updateStatus()
end
-- NOTE: If the M, X, Y, W and H are the same, this function ignores you, unless you put , true on the end.
local function moveSurface(surface, m, x, y, w, h, force)
local om, ox, oy, ow, oh = table.unpack(surface, 1, 5)
m = m or om
x = x or ox
y = y or oy
w = w or ow
h = h or oh
surface[1], surface[2], surface[3], surface[4], surface[5] = m, x, y, w, h
local cache = {}
if om == m and ow == w and oh == h then
if ox == x and oy == y and not force then
return
end
-- note: this doesn't always work due to WC support, and due to resize-to-repaint
if renderingAllowed() and not force then
local cb, b = monitors[m][1]()
if b then
monitorResetBF(monitors[m])
end
if cb then
local monH = monitors[m][4]
local cutTop = math.max(0, 1 - math.min(oy, y))
local cutBottom = math.max(0, (math.max(oy + oh, y + h) - 1) - monH)
pcall(cb.copy, ox, oy + cutTop, w, h - (cutTop + cutBottom), x - ox, y - oy)
if surface == surfaces[1] then
local cacheControl = {}
for i = 1 + cutTop, h - cutBottom do
cacheControl[om .. "_1_" .. i] = true
end
updateRegion(om, ox, oy, ow, oh, cacheControl)
return
end
end
end
end
updateRegion(om, ox, oy, ow, oh, cache)
updateRegion(m, x, y, w, h, cache)
end
-- Returns offset from where we expected to be to where we are.
local function ofsSurface(focus, dx, dy)
local exX, exY = focus[2] + dx, focus[3] + dy
local m, x, y = ensureOnscreen(focus[1], exX, exY, focus[4], focus[5])
moveSurface(focus, nil, x, y)
return focus[2] - exX, focus[3] - exY
end
local function ofsMSurface(focus, dm)
local m, x, y = ensureOnscreen(focus[1] + dm, focus[2], focus[3], focus[4], focus[5])
moveSurface(focus, m, x, y)
end
local basePalT2 = {
-- on T2 we provide 'system colours' by default
0x000000, 0x0080FF, 0x000040, 0xFFFFFF,
@ -416,11 +441,11 @@ local function changeFocus(oldSurface, optcache)
if ns1 ~= oldSurface then
if oldSurface then
setSurfacePalette(oldSurface, nil)
oldSurface[6]("focus", false)
oldSurface[6](oldSurface[8], "focus", false)
end
if ns1 then
setSurfacePalette(ns1, nil)
ns1[6]("focus", true)
ns1[6](ns1[8], "focus", true)
end
updateStatus()
if oldSurface then
@ -459,70 +484,11 @@ everestProvider(function (pkg, pid, sendSig)
else
title = base .. ":" .. title
end
local surf = {math.min(#monitors, math.max(1, lIM)), 1, 2, w, h}
if h >= monitors[surf[1]][4] then
surf[3] = 1
end
local focusState = false
local llid = lid
lid = lid + 1
local specialDragHandler
surf[6] = function (ev, a, b, c, d, e)
-- Must forward surface events
if ev == "focus" then
focusState = a
end
if ev == "touch" then
specialDragHandler = nil
if math.floor(b) == 1 then
if e == 1 then
sendSig(llid, "close")
return
end
specialDragHandler = function (x, y)
local ofsX, ofsY = math.floor(x) - math.floor(a), math.floor(y) - math.floor(b)
if (ofsX == 0) and (ofsY == 0) then return end
ofsSurface(surf, ofsX, ofsY)
end
return
end
b = b - 1
end
if ev == "drag" then
if specialDragHandler then
specialDragHandler(a, b)
return
end
b = b - 1
end
if ev == "scroll" or ev == "drop" then
specialDragHandler = nil
b = b - 1
end
if ev == "line" then
if a == 1 then
local lw = surf[4]
local bg = 0x0080FF
local fg = 0x000000
local tx = "-"
if focusState then
bg = 0x000000
fg = 0x0080FF
tx = "+"
end
local vtitle = title
local vto = unicode.len(vtitle)
if vto < lw then
vtitle = vtitle .. (tx):rep(lw - vto)
else
vtitle = unicode.sub(vtitle, 1, lw)
end
handleSpan(surf, 1, 1, vtitle, bg, fg)
return
end
a = a - 1
end
sendSig(llid, ev, a, b, c, d, e)
local surf = {math.min(#monitors, math.max(1, lIM)), 1, 2, w, h, sendSig, title, llid}
if h >= monitors[surf[1]][4] then
surf[3] = 1
end
local osrf = surfaces[1]
table.insert(surfaces, 1, surf)
@ -557,7 +523,7 @@ everestProvider(function (pkg, pid, sendSig)
handleSpan(surf, x, y + 1, text, bg, fg)
end,
recommendPalette = function (pal)
if not focusState then return 0 end
if surfaces[1] ~= surf then return 0 end
return setSurfacePalette(surf, pal)
end,
close = function ()
@ -679,7 +645,7 @@ local function key(ku, ka, kc, down)
error("User-authorized Everest crash.")
else
if focus then
focus[6]("close")
focus[6](focus[8], "close")
end
end
end
@ -696,7 +662,7 @@ local function key(ku, ka, kc, down)
if kc ~= 56 then
lIM = focus[1]
end
focus[6]("key", ka, kc, down)
focus[6](focus[8], "key", ka, kc, down)
end
end
@ -729,7 +695,7 @@ while not shuttingDown do
end
if s[1] == "h.clipboard" then
if surfaces[1] then
surfaces[1][6]("clipboard", s[3])
surfaces[1][6](surfaces[1][8], "clipboard", s[3])
end
end
-- next on my list: high-res coordinates
@ -745,7 +711,16 @@ while not shuttingDown do
local ns = table.remove(surfaces, sid)
table.insert(surfaces, 1, ns)
changeFocus(os)
ns[6]("touch", lx, ly, ix, iy, s[5])
draggingWindowX, draggingWindowY = nil
if ly == 1 then
if s[5] == 1 then
ns[6](ns[8], "close")
else
draggingWindowX, draggingWindowY = lx, ly
end
else
ns[6](ns[8], "touch", lx, ly - 1, ix, iy, s[5])
end
else
if s[5] == 1 then startLauncher() end
end
@ -762,8 +737,16 @@ while not shuttingDown do
if k == focus[1] then
local x, y = (math.ceil(s[3]) - focus[2]) + 1, (math.ceil(s[4]) - focus[3]) + 1
local ix, iy = s[3] - math.floor(s[3]), s[4] - math.floor(s[4])
-- Ok, so let's see...
focus[6](s[1]:sub(3), x, y, ix, iy, s[5])
if s[1] == "h.drag" and draggingWindowX then
local ofsX, ofsY = x - draggingWindowX, y - draggingWindowY
if ofsX ~= 0 or ofsY ~= 0 then
ofsSurface(focus, ofsX, ofsY)
end
else
draggingWindowX, draggingWindowY = nil
-- Ok, so let's see...
focus[6](focus[8], s[1]:sub(3), x, y - 1, ix, iy, s[5])
end
end
break
end