mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-13 09:18:05 -04:00
make reliable screen and keyboard selection for boot and terminals
closes #1933
This commit is contained in:
parent
1fdd30ae72
commit
d46eed8a4a
@ -430,7 +430,7 @@ local function find()
|
|||||||
setStatus("Find: " .. findText)
|
setStatus("Find: " .. findText)
|
||||||
|
|
||||||
local _, address, char, code = term.pull("key_down")
|
local _, address, char, code = term.pull("key_down")
|
||||||
if address == term.keyboard().address then
|
if address == term.keyboard() then
|
||||||
local handler, name = getKeyBindHandler(code)
|
local handler, name = getKeyBindHandler(code)
|
||||||
highlight(cbx, cby, unicode.wlen(findText), false)
|
highlight(cbx, cby, unicode.wlen(findText), false)
|
||||||
if name == "newline" then
|
if name == "newline" then
|
||||||
@ -557,7 +557,7 @@ getKeyBindHandler = function(code)
|
|||||||
elseif value == "shift" then shift = true
|
elseif value == "shift" then shift = true
|
||||||
else key = value end
|
else key = value end
|
||||||
end
|
end
|
||||||
local keyboardAddress = term.keyboard().address
|
local keyboardAddress = term.keyboard()
|
||||||
if (not alt or keyboard.isAltDown(keyboardAddress)) and
|
if (not alt or keyboard.isAltDown(keyboardAddress)) and
|
||||||
(not control or keyboard.isControlDown(keyboardAddress)) and
|
(not control or keyboard.isControlDown(keyboardAddress)) and
|
||||||
(not shift or keyboard.isShiftDown(keyboardAddress)) and
|
(not shift or keyboard.isShiftDown(keyboardAddress)) and
|
||||||
@ -656,7 +656,7 @@ end
|
|||||||
|
|
||||||
while running do
|
while running do
|
||||||
local event, address, arg1, arg2, arg3 = term.pull()
|
local event, address, arg1, arg2, arg3 = term.pull()
|
||||||
if address == term.keyboard().address or address == term.screen().address then
|
if address == term.keyboard() or address == term.screen() then
|
||||||
local blink = true
|
local blink = true
|
||||||
if event == "key_down" then
|
if event == "key_down" then
|
||||||
onKeyDown(arg1, arg2)
|
onKeyDown(arg1, arg2)
|
||||||
|
@ -101,6 +101,7 @@ function component.setPrimary(componentType, address)
|
|||||||
if wasAvailable or wasAdding then
|
if wasAvailable or wasAdding then
|
||||||
adding[componentType] = {
|
adding[componentType] = {
|
||||||
address=address,
|
address=address,
|
||||||
|
proxy = primary,
|
||||||
timer=event.timer(0.1, function()
|
timer=event.timer(0.1, function()
|
||||||
adding[componentType] = nil
|
adding[componentType] = nil
|
||||||
primaries[componentType] = primary
|
primaries[componentType] = primary
|
||||||
@ -116,14 +117,55 @@ end
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
for address in component.list('screen', true) do
|
|
||||||
if #component.invoke(address,'getKeyboards') > 0 then
|
|
||||||
component.setPrimary('screen',address)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function onComponentAdded(_, address, componentType)
|
local function onComponentAdded(_, address, componentType)
|
||||||
if not (primaries[componentType] or adding[componentType]) then
|
local prev = primaries[componentType] or (adding[componentType] and adding[componentType].proxy)
|
||||||
|
|
||||||
|
if prev then
|
||||||
|
-- special handlers -- some components are just better at being primary
|
||||||
|
if componentType == "screen" then
|
||||||
|
--the primary has no keyboards but we do
|
||||||
|
if #prev.getKeyboards() == 0 then
|
||||||
|
local first_kb = component.invoke(address, 'getKeyboards')[1]
|
||||||
|
if first_kb then
|
||||||
|
-- just in case our kb failed to achieve primary
|
||||||
|
-- possible if existing primary keyboard became primary first without a screen
|
||||||
|
-- then prev (a screen) was added without a keyboard
|
||||||
|
-- and then we attached this screen+kb pair, and our kb fired first - failing to achieve primary
|
||||||
|
-- also, our kb may fire right after this, which is fine
|
||||||
|
component.setPrimary("keyboard", first_kb)
|
||||||
|
prev = nil -- nil meaning we should take this new one over the previous
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif componentType == "keyboard" then
|
||||||
|
-- to reduce signal noise, if this kb is also the prev, we do not need to reset primary
|
||||||
|
if address ~= prev.address then
|
||||||
|
--keyboards never replace primary keyboards unless the are the only keyboard on the primary screen
|
||||||
|
local current_screen = primaries.screen or (adding.screen and adding.screen.proxy)
|
||||||
|
--if there is not yet a screen, do not use this keyboard, it's not any better
|
||||||
|
if current_screen then
|
||||||
|
-- the next phase is complicated
|
||||||
|
-- there is already a screen and there is already a keyboard
|
||||||
|
-- this keyboard is only better if this is a keyboard of the primary screen AND the current keyboard is not
|
||||||
|
-- i don't think we can trust kb order (1st vs 2nd), 2nd could fire first
|
||||||
|
-- but if there are two kbs on a screen, we can give preferred treatment to the first
|
||||||
|
-- thus, assume 2nd is not attached for the purposes of primary kb
|
||||||
|
-- and THUS, whichever (if either) is the 1st kb of the current screen
|
||||||
|
-- this is only possible if
|
||||||
|
-- 1. the only kb on the system (current) has no screen
|
||||||
|
-- 2. a screen is added without a kb
|
||||||
|
-- 3. this kb is added later manually
|
||||||
|
|
||||||
|
-- prev is true when addr is not equal to the primary keyboard of the current screen -- meaning
|
||||||
|
-- when addr is different, and thus it is not the primary keyboard, then we ignore this
|
||||||
|
-- keyboard, and keep the previous
|
||||||
|
-- prev is false means we should take this new keyboard
|
||||||
|
prev = address ~= current_screen.getKeyboards()[1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not prev then
|
||||||
component.setPrimary(componentType, address)
|
component.setPrimary(componentType, address)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -132,9 +174,31 @@ local function onComponentRemoved(_, address, componentType)
|
|||||||
if primaries[componentType] and primaries[componentType].address == address or
|
if primaries[componentType] and primaries[componentType].address == address or
|
||||||
adding[componentType] and adding[componentType].address == address
|
adding[componentType] and adding[componentType].address == address
|
||||||
then
|
then
|
||||||
component.setPrimary(componentType, component.list(componentType, true)())
|
local next = component.list(componentType, true)()
|
||||||
|
component.setPrimary(componentType, next)
|
||||||
|
|
||||||
|
if componentType == "screen" and next then
|
||||||
|
-- setPrimary already set the proxy (if successful)
|
||||||
|
local proxy = (primaries.screen or (adding.screen and adding.screen.proxy))
|
||||||
|
if proxy then
|
||||||
|
-- if a screen is removed, and the primary keyboard is actually attached to another, non-primary, screen
|
||||||
|
-- then the `next` screen, if it has a keyboard, should TAKE priority
|
||||||
|
local next_kb = proxy.getKeyboards()[1] -- costly, don't call this method often
|
||||||
|
local old_kb = primaries.keyboard or adding.keyboard
|
||||||
|
-- if the next screen doesn't have a kb, this operation is without purpose, leave things as they are
|
||||||
|
-- if there was no previous kb, use the new one
|
||||||
|
if next_kb and (not old_kb or old_kb.address ~= next_kb) then
|
||||||
|
component.setPrimary("keyboard", next_kb)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
event.listen("component_added", onComponentAdded)
|
event.listen("component_added", onComponentAdded)
|
||||||
event.listen("component_removed", onComponentRemoved)
|
event.listen("component_removed", onComponentRemoved)
|
||||||
|
|
||||||
|
if _G.boot_screen then
|
||||||
|
component.setPrimary("screen", _G.boot_screen)
|
||||||
|
end
|
||||||
|
_G.boot_screen = nil
|
||||||
|
@ -7,30 +7,59 @@ local process = require("process")
|
|||||||
-- this should be the init level process
|
-- this should be the init level process
|
||||||
process.info().data.window = term.internal.open()
|
process.info().data.window = term.internal.open()
|
||||||
|
|
||||||
event.listen("gpu_bound", function(ename, gpu, screen)
|
event.listen("gpu_bound", function(ename, gpu)
|
||||||
gpu=component.proxy(gpu)
|
gpu=component.proxy(gpu)
|
||||||
screen=component.proxy(screen)
|
term.bind(gpu)
|
||||||
term.bind(gpu, screen)
|
|
||||||
computer.pushSignal("term_available")
|
computer.pushSignal("term_available")
|
||||||
end)
|
end)
|
||||||
|
|
||||||
event.listen("component_unavailable", function(_,type)
|
local function components_changed(ename, address, type)
|
||||||
if type == "screen" or type == "gpu" then
|
local window = term.internal.window()
|
||||||
if term.isAvailable() then
|
if not window then
|
||||||
local window = term.internal.window()
|
return
|
||||||
if window[type] and not component.proxy(window[type].address) then
|
|
||||||
window[type] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not term.isAvailable() then
|
|
||||||
computer.pushSignal("term_unavailable")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end)
|
|
||||||
|
if ename == "component_available" or ename == "component_unavailable" then
|
||||||
|
type = address
|
||||||
|
end
|
||||||
|
|
||||||
|
if ename == "component_removed" or ename == "component_unavailable" then
|
||||||
|
-- address can be type, when ename is *_unavailable, but *_removed works here and that's all we need
|
||||||
|
if type == "gpu" and window.gpu.address == address then
|
||||||
|
window.gpu = nil
|
||||||
|
window.keyboard = nil
|
||||||
|
elseif type == "keyboard" then
|
||||||
|
-- we could check if this was our keyboard
|
||||||
|
-- i.e. if address == window.keyboard
|
||||||
|
-- but it is also simple for the terminal to
|
||||||
|
-- recheck what kb to use
|
||||||
|
window.keyboard = nil
|
||||||
|
end
|
||||||
|
elseif (ename == "component_added" or ename == "component_available") and type == "keyboard" then
|
||||||
|
-- we need to clear the current terminals cached keyboard (if any) when
|
||||||
|
-- a new keyboard becomes available. This is in case the new keyboard was
|
||||||
|
-- attached to the terminal's window. The terminal library has the code to
|
||||||
|
-- determine what the best keyboard to use is, but here we'll just set the
|
||||||
|
-- cache to nil to force term library to reload it. An alternative to this
|
||||||
|
-- method would be to make sure the terminal library doesn't cache the
|
||||||
|
-- wrong keybaord to begin with but, users may actually expect that any
|
||||||
|
-- primary keyboard is a valid keyboard (weird, in my opinion)
|
||||||
|
window.keyboard = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if (type == "screen" or type == "gpu") and not term.isAvailable() then
|
||||||
|
computer.pushSignal("term_unavailable")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
event.listen("component_removed", components_changed)
|
||||||
|
event.listen("component_added", components_changed)
|
||||||
|
event.listen("component_available", components_changed)
|
||||||
|
event.listen("component_unavailable", components_changed)
|
||||||
|
|
||||||
event.listen("screen_resized", function(_,addr,w,h)
|
event.listen("screen_resized", function(_,addr,w,h)
|
||||||
local window = term.internal.window()
|
local window = term.internal.window()
|
||||||
if term.isAvailable(window) and window.screen.address == addr and window.fullscreen then
|
if term.isAvailable(window) and term.screen(window) == addr and window.fullscreen then
|
||||||
window.w,window.h = w,h
|
window.w,window.h = w,h
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
@ -32,9 +32,12 @@ do
|
|||||||
for address in component.list('screen', true) do
|
for address in component.list('screen', true) do
|
||||||
if #component.invoke(address, 'getKeyboards') > 0 then
|
if #component.invoke(address, 'getKeyboards') > 0 then
|
||||||
screen = address
|
screen = address
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
_G.boot_screen = screen
|
||||||
|
|
||||||
-- Report boot progress if possible.
|
-- Report boot progress if possible.
|
||||||
local gpu = component.list("gpu", true)()
|
local gpu = component.list("gpu", true)()
|
||||||
local w, h
|
local w, h
|
||||||
@ -150,17 +153,9 @@ do
|
|||||||
|
|
||||||
status("Initializing components...")
|
status("Initializing components...")
|
||||||
|
|
||||||
local primaries = {}
|
|
||||||
for c, t in component.list() do
|
for c, t in component.list() do
|
||||||
local s = component.slot(c)
|
|
||||||
if not primaries[t] or (s >= 0 and s < primaries[t].slot) then
|
|
||||||
primaries[t] = {address=c, slot=s}
|
|
||||||
end
|
|
||||||
computer.pushSignal("component_added", c, t)
|
computer.pushSignal("component_added", c, t)
|
||||||
end
|
end
|
||||||
for t, c in pairs(primaries) do
|
|
||||||
component.setPrimary(t, c.address)
|
|
||||||
end
|
|
||||||
os.sleep(0.5) -- Allow signal processing by libraries.
|
os.sleep(0.5) -- Allow signal processing by libraries.
|
||||||
computer.pushSignal("init") -- so libs know components are initialized.
|
computer.pushSignal("init") -- so libs know components are initialized.
|
||||||
|
|
||||||
|
@ -42,14 +42,7 @@ setmetatable(keyboard.keys,
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function getKeyboardAddress(address)
|
local function getKeyboardAddress(address)
|
||||||
if address then
|
return address or require("term").keyboard()
|
||||||
return address
|
|
||||||
else
|
|
||||||
local primary = component.isAvailable("keyboard") and component.getPrimary("keyboard")
|
|
||||||
if primary then
|
|
||||||
return primary.address
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getPressedCodes(address)
|
local function getPressedCodes(address)
|
||||||
|
@ -2,6 +2,7 @@ local unicode = require("unicode")
|
|||||||
local event = require("event")
|
local event = require("event")
|
||||||
local process = require("process")
|
local process = require("process")
|
||||||
local kb = require("keyboard")
|
local kb = require("keyboard")
|
||||||
|
local component = require("component")
|
||||||
local keys = kb.keys
|
local keys = kb.keys
|
||||||
|
|
||||||
local term = {}
|
local term = {}
|
||||||
@ -51,7 +52,7 @@ end
|
|||||||
|
|
||||||
function term.isAvailable(w)
|
function term.isAvailable(w)
|
||||||
w = w or W()
|
w = w or W()
|
||||||
return w and not not (w.gpu and w.screen)
|
return w and not not (w.gpu and w.gpu.getScreen())
|
||||||
end
|
end
|
||||||
|
|
||||||
function term.internal.pull(input, c, off, t, ...)
|
function term.internal.pull(input, c, off, t, ...)
|
||||||
@ -74,6 +75,11 @@ function term.internal.pull(input, c, off, t, ...)
|
|||||||
c=c or {{gpu.getBackground()},{gpu.getForeground()},gpu.get(x,y)}
|
c=c or {{gpu.getBackground()},{gpu.getForeground()},gpu.get(x,y)}
|
||||||
local c11,c12 = unpack(c[1])
|
local c11,c12 = unpack(c[1])
|
||||||
local c21,c22 = unpack(c[2])
|
local c21,c22 = unpack(c[2])
|
||||||
|
-- c can fail if gpu does not have a screen
|
||||||
|
-- if can happen during a type of race condition when a screen is removed
|
||||||
|
if not c11 then
|
||||||
|
return nil, "interrupted"
|
||||||
|
end
|
||||||
if not off then
|
if not off then
|
||||||
sf(c11,c12)
|
sf(c11,c12)
|
||||||
sb(c21,c22)
|
sb(c21,c22)
|
||||||
@ -227,54 +233,64 @@ function term.readKeyboard(ops)
|
|||||||
local draw=io.stdin.tty and term.drawText or term.internal.nop
|
local draw=io.stdin.tty and term.drawText or term.internal.nop
|
||||||
local input={w=w,promptx=w.x,prompty=w.y,index=0,data="",mask=pwchar}
|
local input={w=w,promptx=w.x,prompty=w.y,index=0,data="",mask=pwchar}
|
||||||
input.blink = ops.blink
|
input.blink = ops.blink
|
||||||
if input.blink == nil then input.blink = w.blink end
|
if input.blink == nil then
|
||||||
if ops.nowrap then
|
input.blink = w.blink
|
||||||
term.internal.build_horizontal_reader(input)
|
|
||||||
else
|
|
||||||
term.internal.build_vertical_reader(input)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- two wrap types currently supported, vertical and hortizontal
|
||||||
|
if ops.nowrap then term.internal.build_horizontal_reader(input)
|
||||||
|
else term.internal.build_vertical_reader(input)
|
||||||
|
end
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local killed, name, address, char, code = term.internal.pull(input)
|
local killed, name, address, char, code = term.internal.pull(input)
|
||||||
|
-- we have to keep checking what kb is active in case it is switching during use
|
||||||
|
-- we could have multiple screens, each with keyboards active
|
||||||
|
local main_kb = term.keyboard(w)
|
||||||
|
local main_sc = term.screen(w)
|
||||||
local c = nil
|
local c = nil
|
||||||
local backup_cache = hints.cache
|
local backup_cache = hints.cache
|
||||||
if name =="interrupted" then draw("^C\n",true) return ""
|
if name == "interrupted" or name == "term_unavailable" then
|
||||||
elseif name=="touch" or name=="drag" then term.internal.onTouch(input,char,code)
|
draw("^C\n",true)
|
||||||
elseif name=="clipboard" then c=char hints.cache = nil
|
return ""
|
||||||
elseif name=="key_down" then
|
elseif address == main_kb or address == main_sc then
|
||||||
hints.cache = nil
|
if name == "touch" or name == "drag" then
|
||||||
local ctrl = kb.isControlDown(address)
|
term.internal.onTouch(input,char,code)
|
||||||
if ctrl and code == keys.d then return
|
elseif name == "clipboard" then
|
||||||
elseif char==9 then hints.cache = backup_cache term.internal.tab(input,hints)
|
c = char
|
||||||
elseif char==13 and filter(input) then
|
hints.cache = nil
|
||||||
input:move(math.huge)
|
elseif name == "key_down" then
|
||||||
if db ~= false then draw("\n") end
|
hints.cache = nil
|
||||||
term.internal.read_history(history,input)
|
local ctrl = kb.isControlDown(address)
|
||||||
return input.data.."\n"
|
if ctrl and code == keys.d then return --nil
|
||||||
elseif code==keys.back then
|
elseif char == 9 then
|
||||||
input:update(-1)
|
hints.cache = backup_cache
|
||||||
elseif code==keys.left then
|
term.internal.tab(input,hints)
|
||||||
input:move(ctrl and term.internal.ctrl_movement(input, -1) or -1)
|
elseif char == 13 and filter(input) then
|
||||||
elseif code==keys.right then
|
input:move(math.huge)
|
||||||
input:move(ctrl and term.internal.ctrl_movement(input, 1) or 1)
|
if db ~= false then
|
||||||
elseif ctrl and char=="w" then
|
draw("\n")
|
||||||
-- cut word
|
end
|
||||||
elseif code==keys.up then
|
term.internal.read_history(history,input)
|
||||||
term.internal.read_history(history,input,1)
|
return input.data .. "\n"
|
||||||
elseif code==keys.down then
|
elseif code == keys.up then term.internal.read_history(history, input, 1)
|
||||||
term.internal.read_history(history,input,-1)
|
elseif code == keys.down then term.internal.read_history(history, input, -1)
|
||||||
elseif code==keys.home then
|
elseif code == keys.left then input:move(ctrl and term.internal.ctrl_movement(input, -1) or -1)
|
||||||
input:move(-math.huge)
|
elseif code == keys.right then input:move(ctrl and term.internal.ctrl_movement(input, 1) or 1)
|
||||||
elseif code==keys["end"] then
|
elseif code == keys.home then input:move(-math.huge)
|
||||||
input:move(math.huge)
|
elseif code == keys["end"] then input:move( math.huge)
|
||||||
elseif code==keys.delete then
|
elseif code == keys.back then c = -1
|
||||||
input:update(0)
|
elseif code == keys.delete then c = 0
|
||||||
elseif char>=32 then
|
elseif char >= 32 then c = unicode.char(char)
|
||||||
c=unicode.char(char)
|
elseif ctrl and char == "w"then -- TODO: cut word
|
||||||
else
|
else hints.cache = backup_cache -- ignored chars shouldn't clear hint cache
|
||||||
hints.cache = backup_cache
|
end
|
||||||
|
end
|
||||||
|
-- if we obtained something (c) to handle
|
||||||
|
if c then
|
||||||
|
input:update(c)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if c then input:update(c) end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -380,16 +396,56 @@ function term.getCursorBlink()
|
|||||||
return W().blink
|
return W().blink
|
||||||
end
|
end
|
||||||
|
|
||||||
function term.bind(gpu, screen, kb, window)
|
function term.bind(gpu, window)
|
||||||
window = window or W()
|
window = window or W()
|
||||||
window.gpu = gpu or window.gpu
|
window.gpu = gpu or window.gpu
|
||||||
window.screen = screen or window.screen
|
window.keyboard = nil -- without a keyboard bound, always use the screen's main keyboard (1st)
|
||||||
window.keyboard = kb or window.keyboard
|
|
||||||
if window.fullscreen then
|
if window.fullscreen then
|
||||||
term.setViewport(nil,nil,nil,nil,window.x,window.y,window)
|
term.setViewport(nil,nil,nil,nil,window.x,window.y,window)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function term.keyboard(window)
|
||||||
|
window = window or W() or {} -- this method needs to be safe even if there is no terminal window (e.g. no gpu)
|
||||||
|
|
||||||
|
if window.keyboard then
|
||||||
|
return window.keyboard
|
||||||
|
end
|
||||||
|
|
||||||
|
local system_keyboard = component.isAvailable("keyboard") and component.keyboard
|
||||||
|
system_keyboard = system_keyboard and system_keyboard.address or "no_system_keyboard"
|
||||||
|
|
||||||
|
local screen = term.screen(window)
|
||||||
|
|
||||||
|
if not screen then
|
||||||
|
-- no screen, no known keyboard, use system primary keyboard if any
|
||||||
|
return system_keyboard
|
||||||
|
end
|
||||||
|
|
||||||
|
-- if we are using a gpu bound to the primary scren, then use the primary keyboard
|
||||||
|
if component.isAvailable("screen") and component.screen.address == screen then
|
||||||
|
window.keyboard = system_keyboard
|
||||||
|
else
|
||||||
|
-- calling getKeyboards() on the screen is costly (time)
|
||||||
|
-- custom terminals should avoid designs that require
|
||||||
|
-- this on every key hit
|
||||||
|
|
||||||
|
-- this is expensive (slow!)
|
||||||
|
window.keyboard = component.invoke(screen, "getKeyboards")[1] or system_keyboard
|
||||||
|
end
|
||||||
|
|
||||||
|
return window.keyboard
|
||||||
|
end
|
||||||
|
|
||||||
|
function term.screen(window)
|
||||||
|
window = window or W()
|
||||||
|
local gpu = window.gpu
|
||||||
|
if not gpu then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return gpu.getScreen()
|
||||||
|
end
|
||||||
|
|
||||||
function --[[@delayloaded-start@]] term.scroll(number, window)
|
function --[[@delayloaded-start@]] term.scroll(number, window)
|
||||||
-- if zero scroll length is requested, do nothing
|
-- if zero scroll length is requested, do nothing
|
||||||
if number == 0 then return end
|
if number == 0 then return end
|
||||||
@ -552,7 +608,13 @@ function --[[@delayloaded-start@]] term.internal.tab(input,hints)
|
|||||||
hints.cache.i=-1
|
hints.cache.i=-1
|
||||||
end
|
end
|
||||||
local c=hints.cache
|
local c=hints.cache
|
||||||
local change = kb.isShiftDown(term.keyboard().address) and -1 or 1
|
local main_kb = term.keyboard()
|
||||||
|
-- term may not have a keyboard
|
||||||
|
-- in which case, we shouldn't be handling tab events
|
||||||
|
if not main_kb then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local change = kb.isShiftDown(main_kb) and -1 or 1
|
||||||
c.i=(c.i+change)%math.max(#c,1)
|
c.i=(c.i+change)%math.max(#c,1)
|
||||||
local next=c[c.i+1]
|
local next=c[c.i+1]
|
||||||
if next then
|
if next then
|
||||||
@ -568,21 +630,4 @@ function --[[@delayloaded-start@]] term.getGlobalArea(window)
|
|||||||
return dx+1,dy+1,w,h
|
return dx+1,dy+1,w,h
|
||||||
end --[[@delayloaded-end@]]
|
end --[[@delayloaded-end@]]
|
||||||
|
|
||||||
function --[[@delayloaded-start@]] term.screen(window)
|
|
||||||
return (window or W()).screen
|
|
||||||
end --[[@delayloaded-end@]]
|
|
||||||
|
|
||||||
function --[[@delayloaded-start@]] term.keyboard(window)
|
|
||||||
window = window or W()
|
|
||||||
local kba = window.keyboard and window.keyboard.address
|
|
||||||
if kba and kb.pressedCodes[kba] then return window.keyboard end
|
|
||||||
window.keyboard=nil
|
|
||||||
local component = require("component")
|
|
||||||
if not window.screen or not component.proxy(window.screen.address) then window.screen = nil return end
|
|
||||||
local kba = window.screen.getKeyboards()[1]
|
|
||||||
if not kba then return end
|
|
||||||
window.keyboard = component.proxy(kba)
|
|
||||||
return window.keyboard
|
|
||||||
end --[[@delayloaded-end@]]
|
|
||||||
|
|
||||||
return term, local_env
|
return term, local_env
|
||||||
|
Loading…
x
Reference in New Issue
Block a user