Skip to content

Instantly share code, notes, and snippets.

@watsuprico
Created February 23, 2020 23:48
Show Gist options
  • Save watsuprico/a3ac9f9b1b5afefdc1a2c0c9d2491421 to your computer and use it in GitHub Desktop.
Save watsuprico/a3ac9f9b1b5afefdc1a2c0c9d2491421 to your computer and use it in GitHub Desktop.
--[[
Windowed (API/Program)
For ComputerCraft
Free for use. :^) (But please do keep this here)
If you make any modifications that make this program better please tell me and send a copy. If your mod is good I'll add it to the newest update ;^)
v1.0 (7/5/16)-(REDO 7/7/16)-(7/11/16)
v2.0 (Complete redo, 4/4/17 (For RitoOS 2.0.12))
]]--
--[[
Windows[ID].posX = int // Where the top X of the window is
Windows[ID].posY = int // Where the top Y of the window is
Windows[ID].width = int // The width of the window
Windows[ID].height = int // The height of the window
Windows[ID].borderless = bool // The the window have a border?
Windows[ID].canResize = bool // Can the window be resized?
Windows[ID].visible = bool // Is the window minimized to the task bar? (If Windowed.disallowHiding is true, then this can't be true if Windows[ID].visibleInTaskbar is true)
Windows[ID].visibleInTaskbar = bool // Is the window visible in the taskbar?
Windows[ID].windowBorder // This is the term object of the window border
Windows[ID].controlWindow // This is what the program outputs to
Windows[ID].secureKey = {} // This is used to verify the identity of windows
Window[ID].adminKey = {} // This is to check if the window has administrator privilege
]]
local masterNative = term.native()
local masterCurrent = term.current()
local oTermCurrent = term.current
local oTermColor = term.isColor
--[[|| Setup for sandboxing ||]]
local nativeShutdown = os.shutdown -- We use this to shutdown later, (We have to change os.shutdown to just close the window that called it... same for rebooting)
local nativeReboot = os.reboot
local nativeRedirect = term.redirect
local nativeCurrent = term.current
local nativePullEventRaw = os.pullEventRaw -- Security
-- I want power events to just close the Windows, but I don't know the ID yet.
os.shutdown = nil
os.reboot = nil
--[[|| Table definitions ||]]--
local Windows = {}
local WindowedS = {["version"]="1.0"} -- This table holds all our settings, keys, term objects, etc
WindowedS.keys = {} -- Key mappings
WindowedS.default = {}
WindowedS.adminKeys = {} -- We check if the Window is administrator level by comparing a table that is different for every window.
WindowedS.windowKeys = {} -- We have to check the key to something the window can't access
Windowed = {} -- For the API part
local color = {}
color.taskbar = {}
color.windows = {}
local taskbar = {}
taskbar.buttons = {}
taskbar.menu = {}
-- [[|| Strings ||]]--
taskbar.buttons.menuTitle = "M" -- What the left taskbar button is labeled as (Like "Start" in Windows)
taskbar.menu.shutdownText = "Shutdown" -- This is how the buttons for the different actions appear in the taskbar menu
taskbar.menu.restartText = "Restart"
taskbar.menu.shellText = "Shell"
taskbar.menu.exitText = "Exit" -- This SHOULD exit the program. I would add a catch so if the program exits whatever called it will logout the user.
--[[|| Locations / Sizes ||]]--
WindowedS.posX, WindowedS.posY = 1,1
WindowedS.widthOffset, WindowedS.heightOffset = 0,0
WindowedS.width, WindowedS.height = masterNative.getSize() -- Notice! Updated on term_resize (use the offsets)
WindowedS.width, WindowedS.height = WindowedS.width+WindowedS.widthOffset, WindowedS.height+WindowedS.heightOffset
--Default window settings
WindowedS.default.width, WindowedS.default.height = 30,13
WindowedS.default.posX, WindowedS.default.posY = 2,2
--Taskbar
taskbar.posX, taskbar.posY = WindowedS.posX, WindowedS.posY -- The location of the taskbar. I recommend not changing this. See onTop to change the location of the taskbar.
taskbar.widthOffset, taskbar.heightOffset = 0, 0 -- The offsets used when generating the width / height of the taskbar. I also have not tested the height offset, but I know most things do not use it.
taskbar.width, taskbar.height = WindowedS.width+taskbar.widthOffset, 1+taskbar.heightOffset -- Height should not be changed! It has unknown effects | Width is updated when the taskbar is drawn, use the off set instead
taskbar.onTop = false -- Where the taskbar is located. TRUE = top, FALSE = bottom. The positions update around this.
--Taskbar widths
taskbar.buttons.menuWidth = string.len(taskbar.buttons.menuTitle)+3 -- Used below
taskbar.buttons.windowsWidth = (taskbar.width-(taskbar.buttons.menuWidth+10))/1 -- This defines how much space is allocated per window in the taskbar.
taskbar.menu.posX, taskbar.menu.width = 1, 10 -- Width will need to be the longest string + 2
taskbar.menu.posY, taskbar.menu.height = 1,6
if not taskbar.onTop then taskbar.menu.posY = (taskbar.posY+WindowedS.height-1)-taskbar.menu.height end
--Taskbar menu items locations
taskbar.menu.shutdownY = 2 -- The location of 'Shutdown' on the menu (1. this is only used when checking where you click; 2. you have to manually change the menu layout )^: ) (Also, pretend this is based of the top left *1,1*) (Based of the taskbar.menu.posY)
taskbar.menu.restartY = 3
taskbar.menu.shellY = 4
taskbar.menu.exitY = 5
--[[|| Key shortcut mapping ||]]--
-- Key map: computercraft.info/wiki/images/8/81/CC-Keyboard-Charcodes.png
WindowedS.keys.super = 184 -- RAlt | Press and hold to use the below keyboard shortcuts
WindowedS.keys.fullScreen = 200 -- Up | Press to enter full screen on the active window
WindowedS.keys.normalScreen = 208 -- Down | Press to exit full screen on the active window
WindowedS.keys.close = 211 -- Del | Press to close the active window
WindowedS.keys.closeAll = 207 --End | Press to close every window
WindowedS.keys.menu = 50 -- M | Press to open the menu (Can't navigate with keyboard shortcuts yet!)
WindowedS.keys.switchWindow = 16 -- Q | Like ALT+TAB in Windows, switch to a different window
WindowedS.keys.runShell = 31 -- S | Open a shell prompt
WindowedS.keys.compatibilityMode = 46 -- C | Enter compatibility mode on the active window (Fullscreen + no title bar)
WindowedS.keys.exitLoop = 18 -- E | Exit the event listener loop (close the program)
WindowedS.keys.moveWindow = 157 -- Right CTRL | Hold this and the super key to use the arrow keys to move the active window
WindowedS.shellLocation = "/rom/programs/shell" -- When you use the key board shortcut or the shell button in the taskbar menu
WindowedS.useBackgroundImage = false -- I would keep this disabled. (Enabled will force the background to redraw every time a window is moved, created, or removed. (It'll flicker like hell.))
WindowedS.backgroundImage = "zlog" -- If a background is enabled then this is the image loaded
WindowedS.backgroundColor = colors.lightBlue
WindowedS.displayClock = true -- Show the clock in the far right
WindowedS.eventUpdates = 0 -- 0 | Update nothing . 1 | Update active window . 2 | Update all
WindowedS.allowCompatibilityMode = true -- Allow windows to enter compatibility mode ((Fullscreen + no title bar))
WindowedS.showWindowID = true -- Show the ID of the window in the window title
--Security
WindowedS.bypassKeyCheck = true -- If enabled then any window can modify other window's properties
WindowedS.randomness = 0xFFFF -- The max a key a be (math.random(0, <this setting>)) Doesn't have to be HEX.
WindowedS.keyLength = 100 -- The normal key length that every window uses
WindowedS.adminKeyLength = 150 -- The administrator key length for windows that have administrator privilege
-- [[|| Functions ||]]--
taskbar.menu.shutdown = nativeShutdown -- Called when the user clicks "Shutdown" in the menu
taskbar.menu.restart = nativeReboot -- Like above just for restart
--[[|| Colors ||]]--
--Taskbar colors
color.taskbar.menuButtonBackground = colors.gray -- Used in the menu too
color.taskbar.menuButtonText = colors.white
color.taskbar.background = colors.lightGray
color.taskbar.text = colors.white
color.taskbar.textActive = colors.white -- Used on the active window
color.taskbar.backgroundActive = colors.gray
--Top bar (title bar) of Windows
color.windows.titleBarText = colors.white
color.windows.titleBarTextActive = colors.white -- When the window is currently active
color.windows.titleBarBackground = colors.lightGray
color.windows.titleBarBackgroundActive = colors.gray -- When the window is currently active
--Window backgrounds
color.windows.borderBackgroundColor = colors.lightGray
color.windows.borderBackgroundColorActive = colors.gray -- When the window is currently active
--Window buttons
color.windows.closeButtonText = colors.white
color.windows.closeButtonTextActive = colors.white -- When you click the close button
color.windows.closeButtonBackground = colors.red
color.windows.closeButtonBackgroundActive = colors.orange -- When you click the close button
color.windows.minimizeText = colors.white -- The background is the title-bar background. (Also used for maximize button)
color.windows.resizeTab = colors.green
color.windows.resizeTabActive = colors.orange -- When you click and are resizing a window
if not term.isColor() then -- No color on non-advance computers
color.windows.closeButtonBackground = colors.black -- I have this here, but you can't click it on non-advance computers anyways :^\
color.windows.closeButtonBackgroundActive = colors.gray
color.windows.resizeTab = colors.gray
color.windows.resizeTabActive = colors.black
WindowedS.backgroundColor = colors.white -- We can't have this being a color on non-advance computers
end
--[[|| Term Objects ||]]--
WindowedS.term = window.create(masterNative,WindowedS.posX,WindowedS.posY,WindowedS.width,WindowedS.height,true) -- We dump the taskbar, windows, etc in here.
if taskbar.onTop then
WindowedS.windowArea = window.create(WindowedS.term,WindowedS.posX,taskbar.posY+1,WindowedS.width,WindowedS.height-taskbar.height,true) -- All the windows are located in this term object
WindowedS.taskbarArea = window.create(WindowedS.term,taskbar.posX,taskbar.posY,taskbar.width,taskbar.height,true) -- The taskbar is located in this term object
else WindowedS.windowArea = window.create(WindowedS.term,WindowedS.posX,1,WindowedS.width,WindowedS.height-taskbar.height,true) WindowedS.taskbarArea = window.create(WindowedS.term,taskbar.posX,taskbar.posY+WindowedS.height-1,taskbar.width,taskbar.height,true) end
WindowedS.taskbarMenuArea = window.create(WindowedS.windowArea,taskbar.menu.posX,taskbar.menu.posY,taskbar.menu.width,taskbar.menu.height,false) -- The taskbar menu
WindowedS.windowTrap = window.create(WindowedS.term, -1,-1,1,1,false) -- Dump output here if anything else. Output shouldn't go here unless something is messed up.
-- I want nothing to escape a window's control area
term.native = function()
return WindowedS.windowTrap
end
-- Simple declares
taskbar.menuOpened = false
WindowedS.windowArea.setCursorBlink(false)
WindowedS.taskbarArea.setCursorBlink(false)
WindowedS.taskbarMenuArea.setCursorBlink(false)
-- Message box
local function drawAlertBox(title, message1, message2, message3, allowButton, denyButton, highLevel, textBox)
WindowedS.drawingBox = true
local X,Y = masterNative.getSize()
local X,Y = X,Y -- calibrate
local posX = math.floor(X/5)-3
local posY = math.floor(Y/3)
local sizeX = math.floor(X/1.5)+6
local sizeY = math.floor(Y/2)
if title == nil or message1 == nil then return false end
local message2 = message2 or ""
local message3 = message3 or ""
local textBoxText = "" local hidenText = true local hideButton = "Show" local text = ""
local buttonAllowX, buttonAllowY = math.floor((sizeX/2)-(string.len(allowButton)+3)+1), math.floor(sizeY-1)
local buttonDenyX, buttonDenyY = math.floor((sizeX/2)+1)+1, math.floor(sizeY-1)
if highLevel then
BoxBG = window.create(masterNative,1,1,X,Y,true)
BoxBG.setBackgroundColor(colors.lightBlue)
BoxBG.clear()
Box = window.create(masterNative,posX,posY,sizeX,sizeY,true)
WindowedS.term.setVisible(false)
else
Box = window.create(masterNative,posX,posY,sizeX,sizeY,true)
end
local oldtopbarBG, oldBG = colors.black, colors.gray
local function drawBox(Box, topbarBG, BG, textBoxText, hidenText, hideButton, selection)
topbarBG = topbarBG or oldtopbarBG
BG = BG or oldBG
--Title bar
Box.setTextColor(colors.white) Box.setBackgroundColor(BG) Box.clear() Box.setBackgroundColor(topbarBG) Box.setCursorPos(1,1) Box.clearLine()
Box.setCursorPos(math.floor((sizeX/2)-(string.len(title)/2)+1),1)
Box.write(title .. "\n")
Box.setBackgroundColor(BG)
-- Message
Box.setCursorPos(1,3) if (string.len(message1)<sizeX) then Box.setCursorPos(math.floor((sizeX/2)-(string.len(message1)/2)+1),3) end
Box.write(message1)
Box.setCursorPos(1,4) if (string.len(message2)<sizeX) then Box.setCursorPos(math.floor((sizeX/2)-(string.len(message2)/2)+1),4) end
Box.write(message2)
Box.setCursorPos(1,5)
if not textBox then if (string.len(message3)<sizeX) then Box.setCursorPos(math.floor((sizeX/2)-(string.len(message3)/2)+1),5) end Box.write(message3) else
Box.setCursorPos(2,5) Box.setBackgroundColor(colors.blue) local f=2 while f < sizeX do Box.write(" ") f=f+1 end Box.setCursorPos(2,5)
local text = ""
if string.len(textBoxText) < sizeX-2 and string.len(textBoxText) ~= 0 then text = string.sub(textBoxText, 0, string.len(textBoxText))
else text = string.sub(textBoxText, math.abs(sizeX-2)*-1, string.len(textBoxText)) Box.setTextColor(colors.lightGray) end
if hidenText then text=text:gsub(".","*") end
Box.write(text) Box.setTextColor(colors.white)
Box.setCursorPos(math.floor((sizeX/2)-(string.len(hideButton)/2)), 6) if hidenText then Box.setBackgroundColor(colors.red) else Box.setBackgroundColor(colors.green) end
Box.write(" "..hideButton.." ")
end
--Buttons
if allowButton ~= nil and allowButton ~= "" then
Box.setCursorPos(buttonAllowX,buttonAllowY) Box.setBackgroundColor(colors.green)
if selection == "left" then Box.write(">"..allowButton.."<") else Box.write(" "..allowButton.." ") end
end
if denyButton ~= nil and denyButton ~= "" then
Box.setCursorPos(buttonDenyX,buttonDenyY) Box.setBackgroundColor(colors.red)
if selection == "right" then Box.write(">"..denyButton.."<") else Box.write(" "..denyButton.." ") end
end
Box.setBackgroundColor(BG)
oldtopbarBG = topbarBG
oldBG = BG
end
drawBox(Box, colors.black, colors.gray, textBoxText, hidenText, hideButton, "left")
local selection = "left"
while true do
local e, button = os.pullEventRaw()
if e == "key" and button == 203 then
selection = "left"
drawBox(Box, nil, nil, textBoxText, hidenText, hideButton, selection)
elseif e == "key" and button == 205 then
selection = "right"
drawBox(Box, nil, nil, textBoxText, hidenText, hideButton, selection)
elseif e == "key" and textBox and button == keys.backspace then
if string.len(textBoxText) >= 1 then textBoxText = string.sub(textBoxText,1,string.len(textBoxText)-1) end
drawBox(Box, nil, nil, textBoxText, hidenText, hideButton, selection)
elseif e == "key" and textBox and button == keys.delete then
textBoxText = ""
drawBox(Box, nil, nil, textBoxText, hidenText, hideButton, selection)
elseif e == "key" and button == keys.enter then
if background then BoxBG.setVisible(false) else Box.setVisible(false) end Box = nil BoxBG = nil drawBox = nil WindowedS.term.setVisible(true) WindowedS.term.redraw()
break
elseif e == "char" and textBox then
textBoxText = textBoxText..button
drawBox(Box, nil, nil, textBoxText, hidenText, hideButton, selection)
end -- What event?
end -- Main while
local a
if selection == "left" then a = true else a = false end
WindowedS.drawingBox = false
if textBox then return a, textBoxText else return a end
end
--End
-- Taskbar
local function makeString(len)
local string=""
for a=0, len do
string=string.." "
end
return string
end
local function drawTaskbar()
taskbar.width, taskbar.height = WindowedS.width+taskbar.widthOffset, 1+taskbar.heightOffset
if not taskbar.onTop then WindowedS.taskbarArea.reposition(taskbar.posX,taskbar.posY+WindowedS.height-1,taskbar.width,taskbar.height)
else WindowedS.taskbarArea.reposition(taskbar.posX,taskbar.posY,taskbar.width,taskbar.height) end
WindowedS.taskbarArea.setBackgroundColor(color.taskbar.background) WindowedS.taskbarArea.setTextColor(color.taskbar.text) WindowedS.taskbarArea.clear()
WindowedS.taskbarArea.setCursorPos(1,1) WindowedS.taskbarArea.setBackgroundColor(color.taskbar.menuButtonBackground) WindowedS.taskbarArea.setTextColor(color.taskbar.menuButtonText)
WindowedS.taskbarArea.write(" "..taskbar.buttons.menuTitle.." ")
WindowedS.taskbarArea.setBackgroundColor(color.taskbar.background) WindowedS.taskbarArea.setTextColor(color.taskbar.text) WindowedS.taskbarArea.write("|")
local x=string.len(" "..taskbar.buttons.menuTitle.." |")
local a=0 for _ in pairs(Windows) do if Windows[_] ~= nil then a=a+1 end end
local correct=0 if WindowedS.displayClock then correct=string.len("| "..textutils.formatTime(os.time(), false).." ") end
taskbar.buttons.windowsWidth = math.floor((taskbar.width-(string.len(" "..taskbar.buttons.menuTitle.." |")+correct))/a)
for ID in pairs(Windows) do if Windows[ID] ~= nil then if Windows[ID].visibleInTaskbar or not Windows[ID].visible then
if Windows[ID].priorityLevel == 0 and Windows[ID].visible then WindowedS.taskbarArea.setTextColor(color.taskbar.textActive) WindowedS.taskbarArea.setBackgroundColor(color.taskbar.backgroundActive)
else WindowedS.taskbarArea.setBackgroundColor(color.taskbar.background) WindowedS.taskbarArea.setTextColor(color.taskbar.text) end
local title = Windows[ID].title or "Program"
if Windows[ID].compatibilityMode then title = "{C} "..title end
local x=x or 0
if string.len(title)+2 > taskbar.buttons.windowsWidth then
WindowedS.taskbarArea.write(string.sub(title,1,taskbar.buttons.windowsWidth-2).."..")
Windows[ID].taskbarStartX = x x=x+string.len(string.sub(title,1,taskbar.buttons.windowsWidth-2).."..") Windows[ID].taskbarEndX=x
else
WindowedS.taskbarArea.write(" "..title.." ")
Windows[ID].taskbarStartX = x
x=x+string.len(" "..title.." ")
Windows[ID].taskbarEndX = x
end
end end end
WindowedS.taskbarArea.setBackgroundColor(color.taskbar.background) WindowedS.taskbarArea.setTextColor(color.taskbar.text)
if WindowedS.displayClock then WindowedS.taskbarArea.setCursorPos(taskbar.width-9,1) WindowedS.taskbarArea.write("| "..textutils.formatTime(os.time(), false).."") end
WindowedS.taskbarArea.redraw()
end
local function drawTaskbarMenu()
if taskbar.menuOpened then
-- Draw the menu
WindowedS.taskbarMenuArea.setCursorPos(1,1) WindowedS.taskbarMenuArea.setBackgroundColor(color.taskbar.menuButtonBackground) WindowedS.taskbarMenuArea.setTextColor(color.taskbar.menuButtonText)
WindowedS.taskbarMenuArea.clear()
WindowedS.taskbarMenuArea.setCursorPos(1,taskbar.menu.shutdownY) WindowedS.taskbarMenuArea.write(" "..taskbar.menu.shutdownText.." ")
WindowedS.taskbarMenuArea.setCursorPos(1,taskbar.menu.restartY) WindowedS.taskbarMenuArea.write(" "..taskbar.menu.restartText.." ")
WindowedS.taskbarMenuArea.setCursorPos(1,taskbar.menu.shellY) WindowedS.taskbarMenuArea.write(" "..taskbar.menu.shellText.." ")
WindowedS.taskbarMenuArea.setCursorPos(1,taskbar.menu.exitY) WindowedS.taskbarMenuArea.write(" "..taskbar.menu.exitText.." ")
WindowedS.taskbarMenuArea.setVisible(true)
WindowedS.taskbarMenuArea.redraw()
else
WindowedS.taskbarMenuArea.setVisible(false)
WindowedS.taskbarMenuArea.redraw()
end
end
-- End taskbar
-- Window area (play pound)
local function drawWindowArea()
if taskbar.onTop then
WindowedS.windowArea.reposition(WindowedS.posX,taskbar.posY+1,WindowedS.width,WindowedS.height-taskbar.height)
else
WindowedS.windowArea.reposition(WindowedS.posX,(taskbar.posY+WindowedS.height)-(WindowedS.height),WindowedS.width,WindowedS.height-taskbar.height)
end
if WindowedS.useBackgroundImage then
local prv = term.current()
term.redirect(WindowedS.windowArea)
local ok = pcall(function() paintutils.drawImage(paintutils.loadImage(WindowedS.backgroundImage), 1, 1) end)
term.redirect(prv)
if not ok then
WindowedS.windowArea.setBackgroundColor(WindowedS.backgroundColor)
WindowedS.windowArea.clear()
end
else
WindowedS.windowArea.setBackgroundColor(WindowedS.backgroundColor)
WindowedS.windowArea.clear()
end
WindowedS.windowArea.redraw()
end
-- End window area
-- Window functions
local function windowsOpened()
local a=0
for _ in pairs(Windows) do if Windows[_] ~= nil then a=a+1 end end
return a
end
local function findFreeWindowID()
local a=0
for _ in pairs(Windows) do if _ > a then a=_ end end -- Finds the highest ID in use
for b=0, a do if Windows[b] == nil then return b end end -- If there's an ID not in use between the highest and 0, return it
return a+1 -- Return the highest+1
end
local function getFocused()
local a=0
for k in pairs(Windows) do if Windows[k] ~= nil then if Windows[k].priorityLevel == 0 then return k end a=k end end
return nil
end
local function priorityLevel(pl) for k in pairs(Windows) do if Windows[k] ~= nil then if Windows[k].priorityLevel == pl then return k end end end end
local function makeAdminKey(ID)
WindowedS.adminKey[ID] = {}
for k=0, WindowedS.adminKeyLength do WindowedS.adminKey[k] = math.random(0, WindowedS.radnomness) end
end
local function redrawWindow(ID) -- Redraws the border, topbar, and etc
if Windows[ID] == nil then return end
if not Windows[ID].controlWindow then return end
if Windows[ID].compatibilityMode then
Windows[ID].windowBorder.reposition(1,1,WindowedS.width,WindowedS.height-1)
Windows[ID].controlWindow.reposition(1,1,WindowedS.width,WindowedS.height-1)
Windows[ID].controlWindow.redraw()
elseif not Windows[ID].borderless and Windows[ID].windowBorder ~= nil then
if Windows[ID].fullScreen then
Windows[ID].windowBorder.reposition(Windows[ID].posX,Windows[ID].posY,WindowedS.width,WindowedS.height-1)
Windows[ID].controlWindow.reposition(1,2,WindowedS.width,WindowedS.height-2)
else
Windows[ID].windowBorder.reposition(Windows[ID].posX,Windows[ID].posY,Windows[ID].width,Windows[ID].height)
Windows[ID].controlWindow.reposition(2,2,Windows[ID].width-2,Windows[ID].height-2)
end
Windows[ID].windowBorder.setBackgroundColor(color.windows.borderBackgroundColor) local borderColor = color.windows.borderBackgroundColor
if getFocused() == ID and not taskbar.menuOpened then Windows[ID].windowBorder.setBackgroundColor(color.windows.borderBackgroundColorActive) borderColor = color.windows.borderBackgroundColorActive end
Windows[ID].windowBorder.clear()
Windows[ID].windowBorder.setBackgroundColor(color.windows.titleBarBackground) Windows[ID].windowBorder.setTextColor(color.windows.titleBarText)
if getFocused() == ID and not taskbar.menuOpened then Windows[ID].windowBorder.setBackgroundColor(color.windows.titleBarBackgroundActive) Windows[ID].windowBorder.setTextColor(color.windows.titleBarTextActive) end
Windows[ID].windowBorder.setCursorPos(1,1)
Windows[ID].windowBorder.clearLine()
local title = Windows[ID].title or ""
if WindowedS.showWindowID then title = title .. " {"..ID.."}" end
local len = string.len(title)
local width = Windows[ID].windowBorder.getSize()
if len > width-3 then
Windows[ID].windowBorder.write(string.sub(title,1,width-5).."..")
else Windows[ID].windowBorder.write(title) end
Windows[ID].windowBorder.setCursorPos(width,1)
Windows[ID].windowBorder.setBackgroundColor(color.windows.titleBarBackground) Windows[ID].windowBorder.setTextColor(color.windows.titleBarText)
if getFocused() == ID and not taskbar.menuOpened then Windows[ID].windowBorder.setBackgroundColor(color.windows.titleBarBackgroundActive) Windows[ID].windowBorder.setTextColor(color.windows.titleBarTextActive) end
Windows[ID].windowBorder.setCursorPos(width-2,1)
if term.isColor() then
Windows[ID].windowBorder.setTextColor(color.windows.minimizeText) Windows[ID].windowBorder.write("-") if Windows[ID].fullScreen then Windows[ID].windowBorder.write("v") else Windows[ID].windowBorder.write("^") end
Windows[ID].windowBorder.setBackgroundColor(color.windows.closeButtonBackground) Windows[ID].windowBorder.setTextColor(color.windows.closeButtonText) Windows[ID].windowBorder.write("x")
if Windows[ID].canResize == true then
Windows[ID].windowBorder.setCursorPos(width, Windows[ID].height)
Windows[ID].windowBorder.setBackgroundColor(color.windows.resizeTab)
if Windows[ID].resizing then Windows[ID].windowBorder.setBackgroundColor(color.windows.resizeTabActive) end Windows[ID].windowBorder.setTextColor(borderColor)
Windows[ID].windowBorder.write(" ")
end
end
if Windows[ID].visible then Windows[ID].windowBorder.setVisible(true) else Windows[ID].windowBorder.setVisible(false) end
Windows[ID].windowBorder.redraw()
Windows[ID].controlWindow.setVisible(true)
Windows[ID].controlWindow.redraw()
else
if Windows[ID].fullScreen then
Windows[ID].windowBorder.reposition(1,1,WindowedS.width,WindowedS.height-1)
Windows[ID].controlWindow.reposition(1,1,WindowedS.width,WindowedS.height-1)
else
Windows[ID].windowBorder.reposition(Windows[ID].posX,Windows[ID].posY,Windows[ID].width,Windows[ID].height)
Windows[ID].controlWindow.reposition(1,1,Windows[ID].width,Windows[ID].height)
end
if Windows[ID].visible then Windows[ID].windowBorder.setVisible(true) else Windows[ID].windowBorder.setVisible(false) end
Windows[ID].windowBorder.redraw()
Windows[ID].controlWindow.setVisible(true)
Windows[ID].controlWindow.redraw()
end
end
local function redrawWindows()
local b=0
for ID in pairs(Windows) do if Windows[ID] ~= nil then if Windows[ID].priorityLevel > b then b=Windows[ID].priorityLevel end end end
for a=0, b do redrawWindow(priorityLevel(b-a)) end
end
local function redrawAll()
WindowedS.width, WindowedS.height = masterNative.getSize()
WindowedS.width, WindowedS.height = WindowedS.width+WindowedS.widthOffset, WindowedS.height+WindowedS.heightOffset
taskbar.posX, taskbar.posY = WindowedS.posX, WindowedS.posY
drawWindowArea()
redrawWindows()
--WindowedS.windowArea.redraw()
drawTaskbar()
drawTaskbarMenu()
end
local function drawAllWindows()
redrawWindows()
end
local function setFocus(ID)
if Windows[ID]~=nil then if Windows[ID].priorityLevel==0 then return end end
local oID=getFocused()
for k in pairs(Windows) do if Windows[k] ~= nil then if k == ID then Windows[k].priorityLevel = 0 else Windows[k].priorityLevel = Windows[k].priorityLevel+1 end end end
redrawWindow(oID)
redrawWindow(ID)
end
local function create(posX, posY, width, height, title, canResize, borderless, visibleInTaskbar, visible)
local ID = findFreeWindowID()
Windows[ID] = {}
WindowedS.windowKeys[ID] = {}
WindowedS.windowKeys[ID].key = {}
WindowedS.adminKeys[ID] = {}
WindowedS.adminKeys[ID].key = {}
Windows[ID].secureKey = {}
math.randomseed(os.clock()/2) for _=0, WindowedS.keyLength do WindowedS.windowKeys[ID].key[_] = math.random(0, WindowedS.randomness) Windows[ID].secureKey[_] = WindowedS.windowKeys[ID].key[_] end
math.randomseed(os.clock()*2) for _=0, WindowedS.keyLength do WindowedS.adminKeys[ID].key[_] = math.random(0, WindowedS.randomness) end
Windows[ID].posX = posX or WindowedS.default.posX
Windows[ID].posY = posY or WindowedS.default.posY
Windows[ID].width = width or WindowedS.default.width
Windows[ID].height = height or WindowedS.default.height
Windows[ID].title = title or ""
Windows[ID].canResize = canResize or true
Windows[ID].borderless = borderless or false
Windows[ID].visibleInTaskbar = visibleInTaskbar or true
Windows[ID].visible = visible or true
Windows[ID].fullScreen = false
Windows[ID].compatibilityMode = false
setFocus(ID)
if Windows[ID].borderless then
Windows[ID].windowBorder = window.create(WindowedS.windowArea, Windows[ID].posX,Windows[ID].posY,Windows[ID].width,Windows[ID].height,true) -- So if they want to disable borderless mode.
Windows[ID].controlWindow = window.create(Windows[ID].windowBorder, 1,1,Windows[ID].width,Windows[ID].height,true)
else
Windows[ID].windowBorder = window.create(WindowedS.windowArea, Windows[ID].posX,Windows[ID].posY,Windows[ID].width,Windows[ID].height,true)
Windows[ID].controlWindow = window.create(Windows[ID].windowBorder, 2,2,Windows[ID].width-2,Windows[ID].height-2,true)
end
drawTaskbar()
redrawWindow(ID)
return ID
end
local function remove(ID)
if Windows[ID] == nil then return end
for k in pairs(Windows) do
if Windows[k] ~= nil then
if k ~= ID then
Windows[k].priorityLevel = Windows[k].priorityLevel-1
end
end
end
term.setCursorBlink(false)
Windows[ID]=nil
WindowedS.adminKeys[ID] = nil
redrawAll()
end
local function removeAll()
local b=0
for ID in pairs(Windows) do if Windows[ID] ~= nil then if Windows[ID].priorityLevel > b then b=Windows[ID].priorityLevel end end end
for a=0, b do
ID = priorityLevel(b-a)
if Windows[ID] ~= nil then
term.setCursorBlink(false)
Windows[ID]=nil
WindowedS.adminKeys[ID] = nil
sleep(0.1)
end
end
redrawAll()
end
-- End window functions
redrawAll()
-- Window management
local function pushEvent(ID, Event, ...)
if Windows[ID] == nil then return end -- Nil protection
if Windows[ID].event == nil or Windows[ID].event == Event or Windows[ID].event == "terminate" then
term.redirect(Windows[ID].controlWindow)
local ok, result = coroutine.resume(Windows[ID].coroutine, Event, ...)
if ok then if Windows[ID] == nil then return end Windows[ID].event = result else printError(result) end
if Windows[ID].coroutine == "dead" then remove(ID) end
end
end
local function runNew(env, program, ...)
local args = { ... }
local ID=create()
Windows[ID].title=fs.getName(program)
local WindowEnvSetup={}
WindowEnvSetup.Windowed=Windowed -- Inject our API
WindowEnvSetup.Windowed.ID=ID
WindowEnvSetup.Windowed.version=WindowedS.version
WindowEnvSetup.Windowed.properties=Windows[ID]
WindowEnvSetup.Windowed.redrawAll=redrawAll
WindowEnvSetup.term=term
WindowEnvSetup.term.native=function() return Windows[ID].controlWindow end
WindowEnvSetup.os=os
WindowEnvSetup.os.shutdown=function() remove(ID) redrawAll() end
WindowEnvSetup.os.reboot=function() remove(ID) redrawAll() end
--setmetatable(WindowEnvSetup, {__index=_ENV}) -- This will inject everything
Windows[ID].coroutine=coroutine.create(function() os.run(WindowEnvSetup, program, table.unpack(args)) Windows[ID].title=Windows[ID].title.." [closed]" redrawAll() sleep(1) remove(ID) redrawAll() end)
Windows[ID].event = nil
redrawAll()
pushEvent(ID)
return ID
end
function Windowed.getFocused()
return getFocused()
end
function Windowed.title(ID)
return Windows[ID].title
end
function Windowed.getWindowProperties(ID, key)
if Windows[ID] == nil then return false, "Invalid window ID" end
if not WindowedS.bypassKeyCheck then if key ~= nil and type(key) == "table" then for k,v in pairs(key) do if WindowedS.adminKey[ID].key[k] ~= key[k] then return false, "Invalid key" end end else return false, "No key" end end
return Windows[ID]
end
function Windowed.setWindowProperties(ID, key, properties)
if Windows[ID] == nil then return false, "Invalid window ID" end
if not WindowedS.bypassKeyCheck then if key ~= nil and type(key) == "table" then for k,v in pairs(key) do if WindowedS.adminKey[ID].key[k] ~= key[k] then return false, "Invalid key" end end else return false, "No key" end end
if type(properties) ~= "table" then return false, "Properties need to be in a table." end
Windows[ID] = properties
end
function Windowed.requestAdmin(ID, windowKey)
if Windows[ID] == nil then return false, "Invalid window ID" end
if Windows[ID].adminKey ~= nil then return false, "You already have the key" end
if not WindowedS.bypassKeyCheck then if windowKey ~= nil and type(windowKey) == "table" then for k,v in pairs(windowKey) do if WindowedS.windowKeys[ID].key[k] ~= key[k] then return false, "Invalid key" end end else return false, "No key table" end end
if drawAlertBox("Administrator privilege",Windows[ID].title.." is requesting", "administrator privilege. Allow?","(They can modify windows with this)","Allow","Deny",true,false) then
Windows[ID].adminKey = {}
for k in pairs(WindowedS.adminKeys) do Windows[ID].adminKey[k] = WindowedS.adminKeys[ID].key[k] end
return true
else
return false, "User denied."
end
end
function Windowed.new(posX, posY, width, height, title, resizable, borderless, visible, visibleInTaskbar, env, path, ...)
local prv = term.current()
local ID = runNew(env, path, ...)
Windows[ID].posX = posX or Windows[ID].posX
Windows[ID].posY = posY or Windows[ID].posY
Windows[ID].width = width or Windows[ID].width
Windows[ID].height = height or Windows[ID].height
Windows[ID].title = title or Windows[ID].title
Windows[ID].borderless = borderless or Windows[ID].borderless
Windows[ID].visible, Windows[ID].visibleInTaskbar = visible, visibleInTaskbar or Windows[ID].visible, Windows[ID].visibleInTaskbar
term.redirect(prv)
redrawAll()
return ID
end
function Windowed.getCount()
return windowsOpened()
end
runNew({}, "/rom/programs/shell")
--create()
-- Run processes
local cor = coroutine.running()
local exitLoop = true
local superKey = false
while exitLoop do -- I'm not going to indent this
-- Get the event
local tEventData = { os.pullEventRaw() }
local sEvent = tEventData[1]
if sEvent == "term_resize" then
redrawAll()
for ID in pairs(Windows) do
if Windows[ID] ~= nil then
pushEvent(ID, "term_resize" )
end
end
elseif sEvent == "key" or sEvent == "char" or sEvent == "key_up" then
local key, held = tEventData[2], tEventData[3]
if sEvent == "key" and key == WindowedS.keys.super and held and not WindowedS.drawingBox then
local a=0
local oldTitle = ""
local ID = getFocused()
if Windows[getFocused()] ~= nil then oldTitle = Windows[ID].title Windows[ID].title = "{K} " .. oldTitle redrawWindow(ID) drawTaskbar() end
local taskbarFix = taskbar.height
if not taskbar.onTop then taskbarFix = 0 end
while true do
local event, key, held = os.pullEventRaw()
superKey = true
key = key or "0"
if event ~= "key" and event ~= "key_up" and event ~= "char" then break
elseif event == "key" and key == WindowedS.keys.super then
elseif event == "key_up" and key == WindowedS.keys.super then break
elseif Windows[ID] ~= nil and event == "key" and key == WindowedS.keys.fullScreen then
if not Windows[ID].fullScreen then Windows[ID].oWidth = Windows[ID].width Windows[ID].oHeight = Windows[ID].height Windows[ID].oPosX = Windows[ID].posX Windows[ID].oPosY = Windows[ID].posY
Windows[ID].width = WindowedS.width Windows[ID].height = WindowedS.height-1 Windows[ID].posX = 1 Windows[ID].posY = 1+taskbarFix Windows[ID].fullScreen = true redrawWindow(ID) end pushEvent(ID, "term_resize")
elseif Windows[ID] ~= nil and event == "key" and key == WindowedS.keys.normalScreen then
if Windows[ID].fullScreen then Windows[ID].width = Windows[ID].oWidth Windows[ID].height = Windows[ID].oHeight Windows[ID].posX = Windows[ID].oPosX Windows[ID].posY = Windows[ID].oPosY
Windows[ID].fullScreen = false redrawAll() end pushEvent(ID, "term_resize")
elseif Windows[ID] ~= nil and event == "key" and key == WindowedS.keys.close then
remove(ID)
redrawAll()
elseif Windows[ID] ~= nil and event == "key" and key == WindowedS.keys.closeAll then
removeAll()
elseif event == "key" and key == WindowedS.keys.menu then
-- Open the menu
if taskbar.menuOpened then taskbar.menuOpened = false else taskbar.menuOpened = true end drawTaskbarMenu()
redrawAll()
elseif Windows[ID] ~= nil and event == "key" and key == WindowedS.keys.switchWindow then
local a=0
for k in pairs(Windows) do if Windows[k] ~= nil then if Windows[k].priorityLevel > a then a=Windows[k].priorityLevel end end end
setFocus(priorityLevel(a))
Windows[ID].title = oldTitle
redrawWindow(ID)
ID = getFocused()
if Windows[ID] ~= nil then oldTitle = Windows[ID].title Windows[ID].title = "{K} " .. oldTitle redrawWindow(ID) drawTaskbar() end
drawTaskbar()
redrawWindow(ID)
elseif event == "key" and key == WindowedS.keys.runShell then
if Windows[ID] ~= nil then Windows[ID].title = oldTitle end
runNew({},WindowedS.shellLocation)
setFocus(ID)
elseif Windows[ID] ~= nil and event == "key" and key == WindowedS.keys.compatibilityMode and WindowedS.allowCompatibilityMode then
if Windows[ID] ~= nil then Windows[ID].title = oldTitle end
if Windows[ID].compatibilityMode then Windows[ID].compatibilityMode = false
else Windows[ID].compatibilityMode = true end
redrawAll()
pushEvent(ID, "term_resize")
elseif event == "key" and key == WindowedS.keys.moveWindow and Windows[ID] ~= nil then
local oTitle = Windows[ID].title
Windows[ID].title = "{M} "..oldTitle
redrawAll()
local breakThis = false
while true do
local event, key, held = os.pullEventRaw()
if event == "key_up" and key == WindowedS.keys.moveWindow then break
elseif event == "key_up" and key == WindowedS.super then breakThis = true break
elseif event == "key" and key == 205 then -- right
if Windows[ID].posX+Windows[ID].width+1 < WindowedS.width+2 then Windows[ID].posX = Windows[ID].posX+1 end
elseif event == "key" and key == 203 then -- Left
if Windows[ID].posX-1 > WindowedS.posX-1 then Windows[ID].posX = Windows[ID].posX-1 end
elseif event == "key" and key == 200 then -- Up
if Windows[ID].posY-1 > WindowedS.posY-1 then Windows[ID].posY = Windows[ID].posY-1 end
elseif event == "key" and key == 208 then -- Down
if Windows[ID].posY+Windows[ID].height+1 < WindowedS.height+1 then Windows[ID].posY = Windows[ID].posY+1 end
end
drawWindowArea()
drawAllWindows()
end
if breakThis then os.queueEvent("key_up", WindoedS.keys.super) end
Windows[ID].title = oTitle
redrawAll()
elseif event == "key" and held and key == WindowedS.keys.exitLoop then exitLoop = false break end
redrawWindow(ID)
end
superKey = false
if Windows[ID] ~= nil then Windows[ID].title = oldTitle redrawAll() end
elseif Windows[getFocused()] ~= nil then
pushEvent(getFocused(), table.unpack(tEventData))
end
elseif sEvent == "paste" or sEvent == "terminate" then
if Windows[getFocused()] ~= nil then pushEvent( getFocused(), table.unpack( tEventData ) ) end
elseif Windows[getFocused()] ~= nil and sEvent == "mouse_click" or sEvent == "mouse_up" or sEvent == "mouse_scroll" or sEvent == "mouse_drag" then
local button, x, y = tEventData[2], tEventData[3], tEventData[4]
local a=0
for k in pairs(Windows) do if Windows[k] ~= nil then if Windows[k].priorityLevel > a then a=Windows[k].priorityLevel end end end
local taskbarFix = taskbar.height if not taskbar.onTop then taskbarFix = 0 end
local taskbarY = taskbar.posY if not taskbar.onTop then taskbarY = taskbar.posY+WindowedS.height-1 end
-- Get which one was clicked
if sEvent == "mouse_click" then
local b=0 while b<a+1 do
local ID = priorityLevel(b)
if Windows[ID] ~= nil then
if taskbar.menuOpened and x >= taskbar.menu.posX and x < taskbar.menu.posX+taskbar.menu.width and y >= taskbar.menu.posY and y < taskbar.menu.posY+taskbar.menu.height then
break -- Clicked the menu
elseif Windows[ID].compatibilityMode or Windows[ID].fullScreen and y ~= taskbarY then
taskbar.menuOpened = false setFocus(ID) break
elseif Windows[ID].visible and x >= Windows[ID].posX and x < Windows[ID].posX+Windows[ID].width and y >= Windows[ID].posY+taskbarFix and y < Windows[ID].posY+Windows[ID].height+taskbarFix then
taskbar.menuOpened = false setFocus(ID) break
else taskbar.menuOpened = false end
end
b=b+1
end end
local ID = getFocused()
local border = true
if Windows[ID] ~= nil and not taskbar.menuOpened then
if Windows[ID].compatibilityMode or Windows[ID].borderless then border = false end
local farRight = Windows[ID].posX+Windows[ID].width-3
if not Windows[ID].visibleInTaskbar then farRight = Windows[ID].posX+Windows[ID].width-2 end
if not Windows[ID].borderless and sEvent == "mouse_up" and button == 1 and dragging then
dragging = false
draggingResize = false
Windows[ID].resizing = false
redrawWindow(ID)
elseif sEvent == "mouse_drag" and not Windows[ID].compatibilityMode and not Windows[ID].borderless and dragging and not draggingResize then
pcall(function() local moveX, moveY = x-Windows[ID].xCorrect, y-taskbarFix
maxX, maxY = WindowedS.windowArea.getSize()
if moveX+Windows[ID].width >= maxX+2 or moveX <= 0 then moveX = Windows[ID].posX end
if moveY == taskbar.posY and taskbar.onTop then moveY = Windows[ID].posY elseif moveY >= WindowedS.height and not taskbar.onTop then moveY = Windows[ID].posY end
if moveX ~= oMoveX or moveY ~= oMoveY then -- Something moved
Windows[ID].posX = moveX
Windows[ID].posY = moveY
if Windows[ID].fullScreen then Windows[ID].xCorrect = 0 Windows[ID].posX = x Windows[ID].width = Windows[ID].oWidth Windows[ID].height = Windows[ID].oHeight end
drawWindowArea()
drawAllWindows()
if Windows[ID].fullScreen then pushEvent(ID, "term_resize") Windows[ID].fullScreen = false end
end
local oMoveX, oMoveY = moveX, moveY end)
elseif sEvent == "mouse_drag" and not Windows[ID].fullScreen and border and draggingResize then
pcall(function() local resizeX, resizeY = x-Windows[ID].posX, y-Windows[ID].posY-taskbarFix
maxX, maxY = WindowedS.windowArea.getSize()
if resizeX >= maxX+2 or resizeX <= 4 then resizeX = Windows[ID].width-1 end if resizeY >= maxY+2-taskbarFix or resizeY <=2 then resizeY = Windows[ID].height-1 end
if resizeY <= 2 and taskbar.onTop then resizeY = Windows[ID].height-1 -- I have no idea how this will ever be called...
elseif resizeY >= WindowedS.height-1 and not taskbar.onTop then resizeY = Windows[ID].height-1 end
if resizeX ~= oResizeX or resizeY ~= oResizeY then -- Something resized
Windows[ID].fullScreen = false
Windows[ID].width = resizeX+1
Windows[ID].height = resizeY+1
drawWindowArea()
drawAllWindows()
pushEvent(ID, "term_resize")
end
local oResizeX, oResizeY = resizeX, resizeY end)
elseif border and not dragging and Windows[ID].visible and sEvent == "mouse_click" and button == 1 and x >= Windows[ID].posX and x < farRight and y == Windows[ID].posY+taskbarFix then
-- Clicked the title bar, probably going to drag it around
Windows[ID].xCorrect = x-Windows[ID].posX -- How far the mouse click was from the far left of the title bar
dragging=true
elseif border and not Windows[ID].fullScreen and not dragging and Windows[ID].canResize and Windows[ID].visible and sEvent == "mouse_click" and button == 1 and x == Windows[ID].posX+Windows[ID].width-1 and y == Windows[ID].posY+Windows[ID].height+taskbarFix-1 then
-- Resizing
dragging = true -- So I don't have to add "and not draggingResize" to every if line
draggingResize = true
Windows[ID].resizing = true
redrawWindow(ID)
elseif border and not dragging and Windows[ID].visible and sEvent == "mouse_up" and button == 1 and Windows[ID].visibleInTaskbar and x == Windows[ID].width+Windows[ID].posX-3 and y == Windows[ID].posY+taskbarFix then
-- Minimize
Windows[ID].visible = false
redrawWindow(ID)
redrawAll()
redrawWindows()
elseif border and not dragging and Windows[ID].visible and sEvent == "mouse_up" and button == 1 and x == Windows[ID].width+Windows[ID].posX-2 and y == Windows[ID].posY+taskbarFix then
-- Fullscreen
if not Windows[ID].fullScreen then
Windows[ID].oWidth = Windows[ID].width
Windows[ID].oHeight = Windows[ID].height
Windows[ID].oPosX = Windows[ID].posX
Windows[ID].oPosY = Windows[ID].posY
Windows[ID].width = WindowedS.width
Windows[ID].height = WindowedS.height-1
Windows[ID].posX = 1
Windows[ID].posY = 1+taskbarFix
Windows[ID].fullScreen = true
redrawWindow(ID)
pushEvent(ID, "term_resize")
elseif Windows[ID].fullScreen then
Windows[ID].width = Windows[ID].oWidth
Windows[ID].height = Windows[ID].oHeight
Windows[ID].posX = Windows[ID].oPosX
Windows[ID].posY = Windows[ID].oPosY
Windows[ID].fullScreen = false
redrawAll()
pushEvent(ID, "term_resize")
end
elseif border and not dragging and Windows[ID].visible and sEvent == "mouse_up" and button == 1 and x == Windows[ID].posX+Windows[ID].width-1 and y == Windows[ID].posY+taskbarFix then
-- Close
remove(ID)
redrawAll()
elseif border and not Windows[ID].fullScreen and not dragging and Windows[ID].visible and x >= Windows[ID].posX+1 and x < Windows[ID].width+Windows[ID].posX-1 and y > Windows[ID].posY+taskbarFix and y < Windows[ID].posY+Windows[ID].height-1+taskbarFix then
-- Clicked the control area
pushEvent(ID, sEvent, button, x-(Windows[ID].posX), (y)-(Windows[ID].posY+taskbarFix))
elseif not border and not Windows[ID].compatibilityMode and x >= Windows[ID].posX and x < Windows[ID].width+Windows[ID].posX and y >= Windows[ID].posY+taskbarFix and y < Windows[ID].height+Windows[ID].posY+taskbarFix then
-- Clicked inside the borderless control area
pushEvent(ID, sEvent, button, x-Windows[ID].posX, (y)-Windows[ID].posY-taskbarFix)
elseif Windows[ID].fullScreen and not dragging and Windows[ID].visible and x >= Windows[ID].posX and x < Windows[ID].width+Windows[ID].posX and y > Windows[ID].posY+taskbarFix and y < Windows[ID].posY+Windows[ID].height-1+taskbarFix then
-- Clicked a control area in full screen mode
pushEvent(ID, sEvent, button, x-Windows[ID].posX+1, (y)-Windows[ID].posY-taskbarFix)
elseif Windows[ID].compatibilityMode and not dragging and Windows[ID].visible and y ~= taskbarY then
-- Clicked a window in compatibility mode
pushEvent(ID, sEvent, button, x, y-taskbarFix)
elseif x >= taskbar.posX and x < taskbar.posX+taskbar.width and y == taskbarY then
-- Somewhere on the taskbar was clicked.
if x >= taskbar.posX and x < taskbar.posX+taskbar.buttons.menuWidth and sEvent == "mouse_up" then
-- Menu button clicked
if taskbar.menuOpened then taskbar.menuOpened = false else taskbar.menuOpened = true end redrawAll()
elseif x > taskbar.buttons.menuWidth and x < taskbar.posX+(taskbar.width-10) then
-- Clicked a window
for kID in pairs(Windows) do if Windows[kID] ~= nil then if x > taskbar.posX+Windows[kID].taskbarStartX-1 and x < taskbar.posX+Windows[kID].taskbarEndX then -- Clicked this window.
Windows[kID].visible = true setFocus(kID) redrawAll()
end end end
else menuOpened = false end
elseif sEvent == "mouse_up" and taskbar.menuOpened and x >= taskbar.menu.posX and x < taskbar.menu.posX+taskbar.menu.width-1 and y >= taskbar.menu.posY and y < taskbar.menu.posY+taskbar.menu.height then
-- Menu clicked
local taskbarFixer = 0
if not taskbar.onTop then taskbarFixer = -1 end
if y == taskbar.menu.shutdownY+taskbar.menu.posY+taskbarFixer then
taskbar.menu.shutdown()
taskbar.menuOpened = false
elseif y == taskbar.menu.restartY+taskbar.menu.posY+taskbarFixer then
taskbar.menu.restart()
taskbar.menuOpened = false
elseif y == taskbar.menu.shellY+taskbar.menu.posY+taskbarFixer then
runNew({},WindowedS.shellLocation)
taskbar.menuOpened = false
redrawAll()
elseif y == taskbar.menu.exitY+taskbar.menu.posY+taskbarFixer then
exitLoop = false
redrawAll()
end
end
elseif x >= taskbar.posX and x < taskbar.posX+taskbar.width and y == taskbarY then
-- Somewhere on the taskbar was clicked.
if x >= taskbar.posX and x < taskbar.posX+taskbar.buttons.menuWidth and sEvent == "mouse_up" then
-- Menu button clicked
if taskbar.menuOpened then taskbar.menuOpened = false else taskbar.menuOpened = true end redrawAll()
elseif x > taskbar.buttons.menuWidth and x < taskbar.posX+(taskbar.width-10) then
taskbar.menuOpened = false
-- Clicked a window
for kID in pairs(Windows) do if Windows[kID] ~= nil then if x > taskbar.posX+Windows[kID].taskbarStartX-1 and x < taskbar.posX+Windows[kID].taskbarEndX then -- Clicked this window.
Windows[kID].visible = true setFocus(kID) redrawAll()
end end end
else taskbar.menuOpened = false end
elseif sEvent == "mouse_up" and taskbar.menuOpened and x >= taskbar.menu.posX and x < taskbar.menu.posX+taskbar.menu.width-1 and y >= taskbar.menu.posY and y < taskbar.menu.posY+taskbar.menu.height then
-- Menu clicked
local taskbarFixer = 0
if not taskbar.onTop then taskbarFixer = -1 end
if y == taskbar.menu.shutdownY+taskbar.menu.posY+taskbarFixer then
taskbar.menu.shutdown()
taskbar.menuOpened = false
elseif y == taskbar.menu.restartY+taskbar.menu.posY+taskbarFixer then
taskbar.menu.restart()
taskbar.menuOpened = false
elseif y == taskbar.menu.shellY+taskbar.menu.posY+taskbarFixer then
runNew({},WindowedS.shellLocation)
taskbar.menuOpened = false
redrawAll()
elseif y == taskbar.menu.exitY+taskbar.menu.posY+taskbarFixer then
exitLoop = false
redrawAll()
end
end
elseif Windows[getFocused()] ~= nil then
-- Other event (go to all programs)
pcall(function() for ID in pairs(Windows) do
if Windows[ID] ~= nil then
pushEvent(ID, table.unpack( tEventData ) )
end
end end)
--redrawAll()
end
if WindowedS.eventUpdates == 1 then redrawWindow(getFocused()) elseif WindowedS.eventUpdates == 2 then redrawAll() end
end
term.native = function()
return masterNative
end
term.current = oTermCurrent
os.reboot = nativeReboot
os.shutdown = nativeShutdown
term.redirect(masterCurrent)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment