diff --git a/code/apps/sys-everest.lua b/code/apps/sys-everest.lua index 6cf42f6..11a4134 100644 --- a/code/apps/sys-everest.lua +++ b/code/apps/sys-everest.lua @@ -399,9 +399,10 @@ everestProvider(function (pkg, pid, sendSig) else title = base .. ":" .. title end - local m = 0 - if renderingAllowed() then m = 1 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 @@ -478,11 +479,11 @@ everestProvider(function (pkg, pid, sendSig) return w, (h - 1) end, getDepth = function () - if neo.dead then return false end + if neo.dead then return 1 end local m = monitors[surf[1]] - if not m then return false end + if not m then return 1 end local cb, rb = m[1]() - if not cb then return false end + if not cb then return 1 end if rb then monitorResetBF(m) end @@ -637,8 +638,8 @@ while not shuttingDown do for k, v in ipairs(monitors) do if v[2] == s[2] then lIM = k - local x, y = math.floor(s[3]), math.floor(s[4]) - local ix, iy = s[3] - x, s[4] - y + local x, y = math.ceil(s[3]), math.ceil(s[4]) + local ix, iy = s[3] - math.floor(x), s[4] - math.floor(y) local sid, lx, ly = surfaceAt(k, x, y) if sid then local os = surfaces[1] @@ -660,7 +661,7 @@ while not shuttingDown do for k, v in ipairs(monitors) do if v[2] == s[2] then if k == focus[1] then - local x, y = (math.floor(s[3]) - focus[2]) + 1, (math.floor(s[4]) - focus[3]) + 1 + 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]) diff --git a/code/apps/sys-glacier.lua b/code/apps/sys-glacier.lua index 7591ccc..bf1a63b 100644 --- a/code/apps/sys-glacier.lua +++ b/code/apps/sys-glacier.lua @@ -177,11 +177,11 @@ donkonitSPProvider(function (pkg, pid, sendSig) end, -- NOTE: REPLICATED IN GB getSetting = function (name) - if type(name) ~= "string" then error("Setting name must be string") end + neo.ensureType(name, "string") return settings[name] end, delSetting = function (name) - if type(name) ~= "string" then error("Setting name must be string") end + neo.ensureType(name, "string") local val = nil if name == "password" or name == "pub.clipboard" then val = "" end settings[name] = val @@ -189,8 +189,8 @@ donkonitSPProvider(function (pkg, pid, sendSig) pcall(saveSettings) end, setSetting = function (name, val) - if type(name) ~= "string" then error("Setting name must be string") end - if type(val) ~= "string" then error("Setting value must be string") end + neo.ensureType(name, "string") + neo.ensureType(val, "string") settings[name] = val -- NOTE: Either a monitor is under application control, -- or it's not under any control. @@ -203,11 +203,11 @@ donkonitSPProvider(function (pkg, pid, sendSig) targsSD[pid] = sendSig end, registerSavingThrow = function (st) - if type(st) ~= "function" then error("Saving throw function must be a function") end + neo.ensureType(st, "function") targsST[pid] = st end, shutdown = function (reboot) - if type(reboot) ~= "boolean" then error("Shutdown parameter must be a boolean (reboot)") end + neo.ensureType(reboot, "boolean") if shuttingDown then return end shuttingDown = true shutdownMode = reboot @@ -263,7 +263,7 @@ donkonitRDProvider(function (pkg, pid, sendSig) return c end, claim = function (address) - if type(address) ~= "string" then error("Address must be string.") end + neo.ensureType(address, "string") for k, v in ipairs(monitorPool) do if v.address == address then local gpu = getGPU(v) @@ -379,11 +379,11 @@ glacierDCProvider(function (pkg, pid, sendSig) forceRescan = rescanDevs, -- NOTE: "pub." prefixed version of functions in sys.manage getSetting = function (name) - if type(name) ~= "string" then error("Setting name must be string") end + neo.ensureType(name, "string") return settings["pub." .. name] end, delSetting = function (name) - if type(name) ~= "string" then error("Setting name must be string") end + neo.ensureType(name, "string") local val = nil if name == "clipboard" then val = "" end settings["pub." .. name] = val @@ -391,8 +391,8 @@ glacierDCProvider(function (pkg, pid, sendSig) pcall(saveSettings) end, setSetting = function (name, val) - if type(name) ~= "string" then error("Setting name must be string") end - if type(val) ~= "string" then error("Setting value must be string") end + neo.ensureType(name, "string") + neo.ensureType(val, "string") settings["pub." .. name] = val sRattle("pub." .. name, val) pcall(saveSettings) diff --git a/code/apps/sys-icecap.lua b/code/apps/sys-icecap.lua index a5f6ed4..386521e 100644 --- a/code/apps/sys-icecap.lua +++ b/code/apps/sys-icecap.lua @@ -78,6 +78,29 @@ nexus = { end } +local function matchesSvc(xd, pkg, perm) + -- This is to ensure the prefix naming scheme is FOLLOWED! + -- sys- : System, part of KittenOS NEO and thus tries to present a "unified fragmented interface" in 'neo' + -- app- : Application - these can have ad-hoc relationships. It is EXPECTED these have a GUI + -- svc- : Service - Same as Application but with no expectation of desktop usability + -- Libraries "have no rights" as they are essentially loadable blobs of Lua code. + -- They have access via the calling program, and have a subset of the NEO Kernel API + local pfx = nil + if pkg:sub(1, 4) == "app-" then pfx = "app" end + if pkg:sub(1, 4) == "svc-" then pfx = "svc" end + if pfx then + -- Apps can register with their own name, w/ details + local permAct = perm + local paP = permAct:match("/[a-z0-9/%.]*$") + if paP then + permAct = permAct:sub(1, #permAct - #paP) + end + if permAct == xd .. pfx .. "." .. pkg:sub(5) then + return "allow" + end + end +end + donkonitDFProvider(function (pkg, pid, sendSig) local prefixNS = "data/" .. pkg local prefixWS = "data/" .. pkg .. "/" @@ -101,6 +124,21 @@ donkonitDFProvider(function (pkg, pid, sendSig) end) return tag end, + lockPerm = function (perm) + -- Are we allowed to? + if not matchesSvc("x.", pkg, perm) then + return false, "You don't own this permission." + end + local set = "perm|*|" .. perm + if settings.getSetting(set) then + -- Silently ignored, to stop apps trying to sense this & be annoying. + -- The user is allowed to choose. + -- You are only allowed to suggest. + return true + end + settings.setSetting(set, "ask") + return true + end, -- Paths must begin with / implicitly list = function (path) if type(path) ~= "string" then error("Expected path to be string") end @@ -187,7 +225,7 @@ rootAccess.securityPolicy = function (pid, proc, perm, req) -- Push to ICECAP thread to avoid deadlock b/c wrong event-pull context neo.scheduleTimer(0) table.insert(todo, function () - local ok, err = pcall(secpol, nexus, settings, proc.pkg, pid, perm, req) + local ok, err = pcall(secpol, nexus, settings, proc.pkg, pid, perm, req, matchesSvc) if not ok then neo.emergency("Used fallback policy because of run-err: " .. err) req(def) diff --git a/code/data/app-claw/local.lua b/code/data/app-claw/local.lua index 7e633b7..ea86ec3 100644 --- a/code/data/app-claw/local.lua +++ b/code/data/app-claw/local.lua @@ -19,6 +19,7 @@ return { "libs/fmttext.lua", "libs/neoux.lua", "libs/braille.lua", + "libs/bmp.lua", "libs/sys-filewrap.lua" }, }, @@ -108,18 +109,29 @@ return { } }, ["app-klogo"] = { - desc = "KittenOS NEO Logo", - v = 0, + desc = "KittenOS NEO Logo shower", + v = 2, + deps = { + "neo", + "app-klogo-logo" + }, + dirs = { + "apps" + }, + files = { + "apps/app-klogo.lua", + }, + }, + ["app-klogo-logo"] = { + desc = "KittenOS NEO Logo (data)", + v = 2, deps = { - "neo" }, dirs = { - "apps", "data", "data/app-klogo" }, files = { - "apps/app-klogo.lua", "data/app-klogo/logo.bmp" }, }, diff --git a/code/init.lua b/code/init.lua index e297644..578402c 100644 --- a/code/init.lua +++ b/code/init.lua @@ -543,6 +543,7 @@ function start(pkg, ...) end local env = baseProcEnv() env.neo.pid = pid + env.neo.pkg = pkg env.neo.executeAsync = startFromUser env.neo.execute = function (...) return osExecuteCore(function () end, ...) diff --git a/code/libs/braille.lua b/code/libs/braille.lua index 3cf8527..e5fb302 100644 --- a/code/libs/braille.lua +++ b/code/libs/braille.lua @@ -20,28 +20,34 @@ -- 25 -- 67 local function dotDist(ra, ga, ba, rb, gb, bb) - local dR, dG, dB = math.abs(ra - rb), math.abs(ga - gb), math.abs(ba - bb) - return (dR * 0.299) + (dG * 0.587) + (dB * 0.114) + local dR, dG, dB = math.abs(ra - rb)^2, math.abs(ga - gb)^2, math.abs(ba - bb)^2 + return (dR * 0.2126) + (dG * 0.7152) + (dB * 0.0722) end -local function dotGet(p, ra, ga, ba, rb, gb, bb, rc, gc, bc, pos, col) +local function ditherResult(pos, pos2, luma) + local res = false + if luma >= 217 then + res = true + elseif luma >= 158 then + res = not pos2 + elseif luma >= 96 then + res = pos + elseif luma >= 32 then + res = pos2 + end + return res +end +local function dotGet(p, ra, ga, ba, rb, gb, bb, rc, gc, bc, pos, pos2, col) if not col then -- Use our own magic - local res = false local luma = (ra * 0.299) + (ga * 0.587) + (ba * 0.114) - if luma > 96 and luma < 160 then - res = pos - elseif luma >= 160 then - res = true - end - return (res and p) or 0 + return (ditherResult(pos, pos2, luma) and p) or 0 end local distA = dotDist(ra, ga, ba, rb, gb, bb) local distB = dotDist(ra, ga, ba, rc, gc, bc) local distAB = dotDist(rb, gb, bb, rc, gc, bc) local distC = dotDist(ra, ga, ba, (rb + rc) / 2, (gb + gc) / 2, (bb + bc) / 2) - -- If A and B are close, - if (distAB < 32) and (distC < (math.min(distA, distB) * 4)) then - return (pos and p) or 0 + if (distC / 2) < math.min(distA, distB) then + return (ditherResult(pos, pos2, (distA / math.max(distA, distB, 0.1)) * 255) and p) or 0 end return ((distB < distA) and p) or 0 end @@ -62,9 +68,7 @@ local function colourize(mark, ...) for i = 1, #t do local luma = (t[i][1] * 0.299) + (t[i][2] * 0.587) + (t[i][3] * 0.114) if luma > nLuma then - bCR = t[i][1] - bCG = t[i][2] - bCB = t[i][3] + bCR, bCG, bCB = table.unpack(t[i]) nLuma = luma end end @@ -95,12 +99,10 @@ end -- NOTE: xo/yo are 0-based! local function calcLine(x, y, w, span, get, colour) local str = "" - local bgR = 0 - local bgG = 0 - local bgB = 0 - local fgR = 255 - local fgG = 255 - local fgB = 255 + -- *g* : actual colour com. + -- *g : RGB mirror of colour + local bgR, bgG, bgB = 0, 0, 0 + local fgR, fgG, fgB = 255, 255, 255 local bg = 0 local fg = 0xFFFFFF local ca = 0 @@ -152,14 +154,14 @@ local function calcLine(x, y, w, span, get, colour) fgR, fgG, fgB = ofgR, ofgG, ofgB end end - i = i + dotGet(1, dot0R, dot0G, dot0B, bgR, bgG, bgB, fgR, fgG, fgB, true, colour) - i = i + dotGet(2, dot1R, dot1G, dot1B, bgR, bgG, bgB, fgR, fgG, fgB, false, colour) - i = i + dotGet(4, dot2R, dot2G, dot2B, bgR, bgG, bgB, fgR, fgG, fgB, true, colour) - i = i + dotGet(8, dot3R, dot3G, dot3B, bgR, bgG, bgB, fgR, fgG, fgB, false, colour) - i = i + dotGet(16, dot4R, dot4G, dot4B, bgR, bgG, bgB, fgR, fgG, fgB, true, colour) - i = i + dotGet(32, dot5R, dot5G, dot5B, bgR, bgG, bgB, fgR, fgG, fgB, false, colour) - i = i + dotGet(64, dot6R, dot6G, dot6B, bgR, bgG, bgB, fgR, fgG, fgB, false, colour) - i = i + dotGet(128, dot7R, dot7G, dot7B, bgR, bgG, bgB, fgR, fgG, fgB, true, colour) + i = i + dotGet(1, dot0R, dot0G, dot0B, bgR, bgG, bgB, fgR, fgG, fgB, true, false, colour) + i = i + dotGet(2, dot1R, dot1G, dot1B, bgR, bgG, bgB, fgR, fgG, fgB, false, false, colour) + i = i + dotGet(4, dot2R, dot2G, dot2B, bgR, bgG, bgB, fgR, fgG, fgB, true, false, colour) + i = i + dotGet(8, dot3R, dot3G, dot3B, bgR, bgG, bgB, fgR, fgG, fgB, false, false, colour) + i = i + dotGet(16, dot4R, dot4G, dot4B, bgR, bgG, bgB, fgR, fgG, fgB, true, true, colour) + i = i + dotGet(32, dot5R, dot5G, dot5B, bgR, bgG, bgB, fgR, fgG, fgB, false, false, colour) + i = i + dotGet(64, dot6R, dot6G, dot6B, bgR, bgG, bgB, fgR, fgG, fgB, false, false, colour) + i = i + dotGet(128, dot7R, dot7G, dot7B, bgR, bgG, bgB, fgR, fgG, fgB, true, true, colour) str = str .. unicode.char(i) ca = ca + 1 end @@ -167,6 +169,7 @@ local function calcLine(x, y, w, span, get, colour) span(x, y, str, bg, fg) end end + heldRef = { calcLine = calcLine, new = function (x, y, w, h, cbs, colour) @@ -185,7 +188,8 @@ heldRef = { scroll = cbs.scroll and cTransform(cbs.scroll), line = function (window, x, y, iy, bg, fg, selected) local colour = colour - if window.getDepth() <= 1 then + local depth = window.getDepth() + if depth <= 1 then colour = nil end calcLine(x, y, control.w, window.span, function (xb, yb) diff --git a/code/libs/sys-secpolicy.lua b/code/libs/sys-secpolicy.lua index 05d6bfb..83f93e0 100644 --- a/code/libs/sys-secpolicy.lua +++ b/code/libs/sys-secpolicy.lua @@ -25,26 +25,15 @@ local actualPolicy = function (pkg, pid, perm) if perm == "s.h.component_added" or perm == "s.h.component_removed" then return "allow" end - -- This is to ensure the prefix naming scheme is FOLLOWED! - -- sys- : System, part of KittenOS NEO and thus tries to present a "unified fragmented interface" in 'neo' - -- app- : Application - these can have ad-hoc relationships. It is EXPECTED these have a GUI - -- svc- : Service - Same as Application but with no expectation of desktop usability - -- Libraries "have no rights" as they are essentially loadable blobs of Lua code. - -- They have access via the calling program, and have a subset of the NEO Kernel API - local pfx = nil - if pkg:sub(1, 4) == "app-" then pfx = "app" end - if pkg:sub(1, 4) == "svc-" then pfx = "svc" end - if pfx then - -- Apps can register with their own name - if perm == "r." .. pfx .. "." .. pkg:sub(5) then - return "allow" - end + if matchesSvc("r.", pkg, perm) then + return "allow" end -- Userlevel has no other registration rights if perm:sub(1, 2) == "r." then return "deny" end - -- app/svc stuff is world-accessible + -- app/svc stuff is world-accessible, + -- but note perm|*| overrides this if perm:sub(1, 6) == "x.app." then return "allow" end @@ -55,10 +44,14 @@ local actualPolicy = function (pkg, pid, perm) return "ask" end -return function (nexus, settings, pkg, pid, perm, rsp) - local res = actualPolicy(pkg, pid, perm) - if res == "ask" and settings then - res = settings.getSetting("perm|" .. pkg .. "|" .. perm) or "ask" +return function (nexus, settings, pkg, pid, perm, rsp, matchesSvc) + local res = "ask" + if settings then + res = settings.getSetting("perm|" .. pkg .. "|" .. perm) or + settings.getSetting("perm|*|" .. perm) or "ask" + end + if res == "ask" then + res = actualPolicy(pkg, pid, perm, matchesSvc) end if res == "ask" and nexus then local totalW = 3 + 6 + 2 + 8 diff --git a/repository/data/app-claw/local.lua b/repository/data/app-claw/local.lua index 5a36f2d..72ba050 100644 --- a/repository/data/app-claw/local.lua +++ b/repository/data/app-claw/local.lua @@ -34,6 +34,7 @@ return { "docs/kn-perms", "docs/us-perms", "docs/us-nxapp", + "docs/us-setti", "docs/ul-seria", "docs/ul-event", "docs/ul-fmttx", diff --git a/repository/docs/kn-refer b/repository/docs/kn-refer index ae41719..33052f0 100644 --- a/repository/docs/kn-refer +++ b/repository/docs/kn-refer @@ -242,6 +242,10 @@ The additional things available to pid: A field that specifies the process ID of this process. Harmless, but not entirely useful. + pkg: A field that specifies the + package name of this process. + Useful if you're worried about + your app getting renamed. dead: Actually a field, that isn't set at first, but is set later to indicate deadness. Useful if your diff --git a/repository/docs/ul-neoux b/repository/docs/ul-neoux index 85bc970..79e80be 100644 --- a/repository/docs/ul-neoux +++ b/repository/docs/ul-neoux @@ -31,19 +31,58 @@ The most reliable reference on the note that "xI"/"yI" is within-char position from 0 to 1. - TODO, TODO, TODO, TODO, TODO, TODO +Main functions: - neoux.fileDialog = function (forWrite, callback) - neoux.create = function (w, h, title, callback) - neoux.pad = require("fmttext").pad - neoux.fmtText = function (...) - neoux.tcwindow = function (w, h, controls, closing, bg, fg, selIndex) - neoux.tcrawview = function (x, y, lines) - neoux.tchdivider = function (x, y, w) - neoux.tcvdivider = function (x, y, h) - neoux.tcbutton = function (x, y, text, callback) - neoux.tcfield = function (x, y, w, textprop) - neoux.startDialog = function (fmt, title, wait) + fileDialog(mode[, callback]): + Creates a file dialog, returning a + file wrapper (see ul-fwrap) on + success, or nil on failure. + If a callback is given, then nil is + always returned immediately, and + the callback is called when the + dialog has shown. + mode is the mode used for the file, + so see ul-fwrap for values. + + neoux.create = TODO + function (w, h, title, callback) + callback(window, evt, ...) + + pad: See ul-fmttx, but loaded on + demand and unloaded after use. + + fmtText: See ul-fmttx, but loaded on + demand and unloaded after use. + + neoux.tcwindow = TODO + function (w, h, controls, closing, + bg, fg, selIndex) + + startDialog(fmt, title, wait): + Shows a text dialog. + fmt is some un-safeTextFormat'd + text for the dialog. + title can be nil, or more un-STF'd + text for the dialog title. + wait can be nil/false to not wait, + and otherwise. + +UI framework controls (TODO): + + neoux.tcrawview = + function (x, y, lines) + table of lines not STF'd + neoux.tchdivider = + function (x, y, w) + neoux.tcvdivider = + function (x, y, h) + neoux.tcbutton = + function (x, y, text, callback) + callback(window) + neoux.tcfield = + function (x, y, w, textprop) + textprop(newval) -> nil + textprop() -> val -- This is released into the public domain. diff --git a/repository/docs/us-nxapp b/repository/docs/us-nxapp index 0a84684..a022ff8 100644 --- a/repository/docs/us-nxapp +++ b/repository/docs/us-nxapp @@ -26,7 +26,11 @@ A good example of this is app-flash, labelling window never needs to be regenerated after it's switched to, so the only regeneration is for the - main window) + main window.) + +A full application of this technique + would regenerate the window whenever + anything occurs of interest. -- This is released into the public domain. diff --git a/repository/docs/us-perms b/repository/docs/us-perms index 38350e2..86c0f2f 100644 --- a/repository/docs/us-perms +++ b/repository/docs/us-perms @@ -1,4 +1,62 @@ -Hello World. +This is a list of the different + additional permissions in KittenOS + NEO as distributed, and their + purposes. + +Installable service documentation is + provided with the respective -doc + packages, and goes under the rs-* + namespace. + +For programs with the prefixes "svc-" + or "app-", they can register their + services using "r.svc.mysvcname" + (for the program "svc-mysvcname"), + or "r.app.myappname" (for the + program "app-myappname") - this + MAY have any postfix matching the + pattern "/[a-z0-9/%.]*$", or none + at all. + +For how this registration works, + and how to access the resulting + service, please see the kn-perms + document. + +APIs registered in this manner are + accessible to all programs by + default. However, local security + policy may be altered by the user, + and part of x.neo.pub.base's API is + to allow locking any of your public + APIs. (The user can override this + mechanism if they so wish, and this + will cause a silent failure of the + lockPerm function.) + A mechanism may also be introduced + in later versions of KittenOS NEO to + easily allow changing your svc/app's + own API to a "ask"-style security + model, but this will not be the + default, and may still be overridden + by a user with access to the + Advanced Settings control panel. + +As for the system APIs... + +-- x.neo.pub.base @ sys-icecap -- + +-- x.neo.pub.session @ -- + +This API is + +-- x.neo.pub.window @ -- + +-- x.neo.pub.session @ -- + +-- x.neo.sys.manage @ sys-glacier -- +-- x.neo.sys.screens @ sys-glacier -- +-- x.neo.pub.globals @ sys-glacier -- -- This is released into the public domain. diff --git a/repository/docs/us-setti b/repository/docs/us-setti new file mode 100644 index 0000000..c19973b --- /dev/null +++ b/repository/docs/us-setti @@ -0,0 +1,94 @@ +This is a list of the settings, and + setting formats, in KittenOS NEO. + +As "*" is used as a part of some of + the settings, <> is used to enclose + a component of a varied name. + +-- System-wide permissions -- + +pub.: Public settings, + readable and writable by anything + with x.neo.pub.globals access. + +pub.clipboard: The text in the user's + clipboard. Can include newlines. + Hardcoded to be non-nil. + +perm|*|: Security policy + override entry, global. Allows an + application to set the defaults for + its own APIs, or for the user to + override that or any other default. + If there is a setting here, it must + be respected unless the user makes a + direct choice to alter it. + sys-secpolicy defines this as having + priority only second to... + +perm||: Security + policy override entry for a specific + application. Solely for use by the + user to make specific choices about + the applications on the system. + The existence or lack of this entry + must be respected, unless the user + makes a direct choice to alter it. + +-- screen management settings -- + +scr.w.: Width, as a string, + for a given monitor by address. + +scr.h.: Height, as a string, + for a given monitor by address. + +scr.d.: Depth, as a string, + for a given monitor by address. + +scr.t.: Touch invert, given + as "yes" for true and anything else + for false (including non-existence), + for a given monitor by address. + +-- sys-init specific settings -- + +password: The user's password. + Hardcoded to be non-nil. + An empty password is considered to + be "not a password". + +sys-init.nologin: If set to "yes", + the login screen is skipped, even if + a password is present. + +sys-init.shell: The user's shell. + Not hardcoded to be non-nil, since + this can be broken in many ways, + but is hardcoded with "sys-everest" + as a default, which will replace nil + the next time sys-glacier starts up. + +run.sys- + This is stage 1 of startup, which + starts things beginning with "sys-". + This is required so that security + policy changeover happens smoothly. + A value equal to "yes" causes the + service to be automatically started + up as the system boots. + As sys-glacier is needed to read the + list of processes to start, it is + always started regardless, and must + not have an entry here. + +run.: Programs which + do not begin with "sys-" start up + during stage 2. As usual, any entry + with the value of "yes" is started. + +-- This is released into + the public domain. +-- No warranty is provided, + implied or otherwise. +