LevelOS.self.window.events = "all" local w,h = lOS.wAll.getSize() local timeObj = {x=w-13,w=8} local function round(n) return math.floor(n + 0.5) end local oclickmenu = lUtils.clickmenu lUtils.oclickmenu = oclickmenu local opopup = lUtils.popup local oinputbox = lUtils.inputbox local events = {} local doLog = false local subprocesses = {} local theOverlayFunction local oshutdown = os.shutdown local oreboot = os.reboot local function shutdownscreen(reboot) local bgcolor = colors.cyan local txtcolor = colors.white local txtcolor2 = colors.gray local txtcolor3 = colors.lightGray local button1 = colors.lightBlue -- fill local button2 = colors.cyan -- border local button3 = colors.white -- text lOS.focusWin = lOS.wins[0] local nEvents = lOS.noEvents lOS.noEvents = true local img = lUtils.asset.load("LevelOS/assets/loading.limg") local iw,ih = #img[1][1][1],#img[1] local frame = 1 local action = 1 local programs = {} local objs = {} local sel local function genPrograms() programs = {} for i,process in ipairs(lOS.processes) do if (process.env and process.env.LevelOS and type(process.env.LevelOS.close) == "function") or process.winMode ~= "background" then table.insert(programs,process) -- ha potato end end end local function drawObj(obj) term.setTextColor(obj.border) term.setBackgroundColor(obj.color) lUtils.border(obj.x1, obj.y1, obj.x2, obj.y2, "fill") term.setCursorPos(obj.x1+1,obj.y1+1) term.setTextColor(button3) term.write(obj.txt) end local function overlayFunc() term.setCursorBlink(false) term.setBackgroundColor(bgcolor) term.clear() local w,h = term.getSize() lUtils.renderImg(img[frame],nil,math.ceil(h/2)-2) term.setCursorPos(1,math.ceil(h/2)+2) term.setTextColor(txtcolor) if reboot then lUtils.centerText("Restarting") else lUtils.centerText("Shutting down") end end LevelOS.overlay = overlayFunc local oTime = os.epoch("utc") lOS.save() local render local e local closewin while true do local tID = os.startTimer(0.1) while true do e = {os.pullEventRaw()} LevelOS.overlay = overlayFunc if os.epoch("utc") > oTime+250 and action == 1 then action = 2 genPrograms() if #programs == 0 then if reboot then oreboot() else oshutdown() end else closewin = window.create(lOS.wAll,2,2,51-2,19-2,false) function render() objs = {} local list = {} for i,p in ipairs(lOS.processes) do if p.winMode ~= "background" or (p.env and p.env.LevelOS and type(p.env.LevelOS.close) == "function") then table.insert(list,p) end end local cTerm = term.current() local tW,tH = lOS.wAll.getSize() local cW,cH = 51,#list*3+10 local big = false local spacing = 3 local offset = 0 if tH >= 30 and tW >= 100 then big = true cW = 74 offset = 5 end if tH >= 30 then spacing = 4 cH = #list*4+10+offset end closewin.reposition(math.floor(tW/2-cW/2)+1,math.floor(tH/2-cH/2)+1,cW,cH) term.redirect(closewin) term.setBackgroundColor(bgcolor) term.setTextColor(txtcolor) term.clear() local w,h = term.getSize() term.setCursorPos(1,1) local word = " apps" if #list == 1 then word = " app" end local act = "shutting down" if reboot then act = "restarting" end if big then bigfont.bigPrint("Closing "..#list..word.." and") bigfont.bigPrint(act) else print("Closing "..#list..word.." and "..act) term.setTextColor(txtcolor2) -- gray end print("To go back and save your work, click Cancel and finish what you need to.") for i,p in ipairs(list) do local path = p.path if fs.isDir(path) and fs.exists(fs.combine(path,"main.lua")) then path = fs.combine(path,"main.lua") end lOS.explorer.drawIcon(path,1,i*spacing+1+offset,true,true) term.setTextColor(txtcolor) term.setCursorPos(7,i*spacing+3+offset) print(p.title or lOS.explorer.getName(p.path)) if p.env and p.env.LevelOS and type(p.env.LevelOS.close) == "function" then term.setCursorPos(7,i*spacing+4+offset) term.setTextColor(txtcolor3) -- light gray if reboot then print("This app is preventing you from restarting.") else print("This app is preventing shutdown.") end end end local txt = " Shut down anyway " if reboot then txt = " Restart anyway " end local obj1 = {x1=1, y1=#list*spacing+8+offset, x2=#txt+2, y2=#list*spacing+10+offset, id="shutdown", color=button1, border=button2, txt=txt} if sel == 1 then obj1.color = button2 obj1.border = button1 end table.insert(objs,obj1) drawObj(obj1) local txt2 = " Cancel " local obj2 = {x1=#txt+3, y1=#list*spacing+8+offset, x2=#txt+2+#txt2+2, y2=#list*spacing+10+offset, id="cancel", color=button1, border=button2, txt=txt2} if sel == 2 then obj2.color = button2 obj2.border = button1 end table.insert(objs,obj2) drawObj(obj2) term.redirect(cTerm) end local ok,err = pcall(render) if not ok then lOS.bsod(err) os.sleep(10) end function overlayFunc() term.setCursorBlink(false) term.setBackgroundColor(bgcolor) term.clear() closewin.setVisible(true) closewin.setVisible(false) end LevelOS.overlay = overlayFunc end elseif os.epoch("utc") > oTime+2250 and action == 2 then action = 3 for i=#lOS.processes,3,-1 do local process = lOS.processes[i] if (process.env and process.env.LevelOS and type(process.env.LevelOS.close) == "function") or process.winMode ~= "background" then os.queueEvent("process_close",i,tostring(lOS.processes[i])) end end genPrograms() render() elseif action == 3 then local ocount = #programs genPrograms() if #programs == 0 then if reboot then oreboot() else oshutdown() end end if ocount ~= #programs then render() end end if e[1] == "key" and e[2] == keys.t and lUtils.isHolding(keys.leftCtrl) then term.setBackgroundColor(colors.black) LevelOS.overlay = theOverlayFunction lOS.noEvents = nil return elseif e[1] == "mouse_click" or e[1] == "mouse_up" then local wx,wy = closewin.getPosition() for i,o in ipairs(objs) do if lUtils.isInside(e[3]-(wx-1),e[4]-(wy-1),o) then if e[1] == "mouse_click" then sel = i render() elseif e[1] == "mouse_up" and sel == i then if o.id == "cancel" then LevelOS.overlay = theOverlayFunction lOS.noEvents = nil LevelOS.events = oEvents return elseif o.id == "shutdown" then if reboot then oreboot() else oshutdown() end end end end end if e[1] == "mouse_up" and sel then sel = nil render() end elseif e[1] == "timer" and e[2] == tID then break end end frame = frame%#img+1 end end function os.shutdown() table.insert(subprocesses,coroutine.create(shutdownscreen)) coroutine.resume(subprocesses[#subprocesses]) end function os.reboot() table.insert(subprocesses,coroutine.create(shutdownscreen)) coroutine.resume(subprocesses[#subprocesses],true) end local tbIcoAssets = lUtils.asset.load("LevelOS/assets/Compact_Icons.limg") local tbIco = { ["LevelOS/explorer.lua"] = { tbIcoAssets[1], {"\143","4","7"}, }, ["LevelOS/LevelCloud.lua"] = { tbIcoAssets[2], }, ["LevelOS/Pigeon.lua"] = { tbIcoAssets[3], {"\29","b","7"}, }, ["Program_Files/Shapescape"] = { tbIcoAssets[4], {"\7","e","7"}, }, ["rom/programs/shell.lua"] = { tbIcoAssets[5], }, ["rom/programs/lua.lua"] = { tbIcoAssets[6], }, ["LevelOS/notepad.lua"] = { tbIcoAssets[7], {"\143","0","7"}, }, ["*"] = { tbIcoAssets[8], }, ["LevelOS/paint.lua"] = { tbIcoAssets[9], {"\1","1","7"}, }, } local pHistory = {} local function logEvents() while true do local e = {os.pullEventRaw()} if doLog and (e[1]:find("window") or e[1]:find("process")) then table.insert(events,e) end for p=#subprocesses,1,-1 do coroutine.resume(subprocesses[p],unpack(e)) if coroutine.status(subprocesses[p]) == "dead" then table.remove(subprocesses,p) end end end end local function runOverlay(func,grayOut,system) local levOS if system then levOS = lOS.sysUI.env.LevelOS else levOS = lOS.wins[lOS.cWin].env.LevelOS end local oterm = term.current() local w,h = lOS.wAll.getSize() local win = window.create(oterm,1,1,w,h,false) local cor = coroutine.create(func) lOS.noEvents = true if grayOut then os.sleep(0) end for y=1,h do win.setCursorPos(1,y) win.blit(lOS.wAll.getLine(y)) end local oldOverlay = levOS.overlay function levOS.overlay() for y=1,h do term.setCursorPos(1,y) term.blit(win.getLine(y)) term.setCursorPos(1,1) term.setBackgroundColor(colors.white) term.setTextColor(colors.red) end oldOverlay() end term.redirect(win) local pEvent if system or lOS.wins[lOS.cWin].events == "all" then pEvent = os.pullEventRaw else pEvent = levOS.pullEvent end coroutine.resume(cor) while true do local e = {pEvent()} term.redirect(win) coroutine.resume(cor,unpack(e)) term.redirect(oterm) if coroutine.status(cor) == "dead" then lOS.noEvents = false break end end term.redirect(oterm) levOS.overlay = oldOverlay end function runLevelOSclose(process) if process.env and process.env.LevelOS and type(process.env.LevelOS.close) == "function" then local func = process.env.LevelOS.close local oEnv = getfenv(func) local nEnv = {} for k,v in pairs(oEnv) do nEnv[k] = v end setmetatable(nEnv,getmetatable(oEnv)) local cor = process[1] nEnv.abort = function() process[1] = cor process.env.LevelOS.close = func os.sleep(0) end setfenv(func,nEnv) process[1] = coroutine.create(func) process.env.LevelOS.close = nil end end function lUtils.clickmenu(...) if not lOS.cWin or not lOS.wins[lOS.cWin] or not lOS.wins[lOS.cWin].win then return oclickmenu(...) end local output local x,y = lOS.wins[lOS.cWin].win.getPosition() if term.current() ~= lOS.wins[lOS.cWin].win then local x1,y1 = term.current().getPosition() x = x+x1-1 y = y+y1-1 end local input = table.pack(...) input[1],input[2] = input[1]+(x-1),input[2]+(y-1) os.sleep(0) runOverlay(function() output = table.pack(oclickmenu(table.unpack(input,1,input.n))) end) return table.unpack(output,1,output.n) end function lOS.contextmenu(x,y,width,options,colorScheme,dividers) -- no bad change whole thing i need to put render function in LevelOS.overlay n shit lOS.noEvents = 2 local oterm = term.current() --[[local tx,ty = lOS.wins[lOS.cWin].win.getPosition() if term.current() ~= lOS.wins[lOS.cWin].win then local tx1,ty1 = term.current().getPosition() tx = tx+tx1-1 ty = ty+ty1-1 end]] local tx,ty = lUtils.getWindowPos(oterm) term.redirect(lOS.wAll) local menu = lUtils.contextmenu(x+tx-1,y+ty-1,width,options,colorScheme,dividers) lOS.debugMenu = menu term.redirect(oterm) levOS = lOS.wins[lOS.cWin].env.LevelOS local oldOverlay = levOS.overlay function levOS.overlay() menu.render() oldOverlay() end local clicked while menu.status ~= "dead" do local e = {levOS.pullEvent()} term.redirect(lOS.wAll) clicked = menu.update(unpack(e)) term.redirect(oterm) end lOS.noEvents = false levOS.overlay = oldOverlay os.sleep(0) return clicked end local function animation(v,x,y,w,h,gx,gy,gw,gh,dur) local dur = dur or 8 if lOS.settings.animations == false then dur = 0 end local minWin local oterm = term.current() if v.winMode == "windowed" then local wx,wy = v.win.getPosition() local ww,wh = v.win.getSize() minWin = window.create(term.current(),wx-1,wy-1,ww+2,wh+2,false) term.redirect(minWin) term.setBackgroundColor(colors.gray) term.setCursorPos(1,1) term.clearLine() term.setCursorPos(1,wh+2) term.clearLine() for t=1,wh do term.setCursorPos(1,t+1) term.write(" ") term.blit(v.win.getLine(t)) term.write(" ") end term.redirect(oterm) else minWin = v.win end local width,height = term.getSize() --lOS.noEvents = true local oldOverlay = LevelOS.overlay local lilwin function LevelOS.overlay() if lilwin then lilwin.render(lilwin.x,lilwin.y) end oldOverlay() end for t=1,dur do local nx,ny = round(x+(gx-(x))*(t/dur)),round(y+(gy-(y))*(t/dur)) local nw,nh = round(w+(gw-(w))*(t/dur)),round(h+(gh-(h))*(t/dur)) lilwin = lUtils.littlewin(minWin,nw,nh) lilwin.x,lilwin.y = nx,ny os.sleep(0.05) end LevelOS.overlay = oldOverlay --lOS.noEvents = false end local imgcache = {} local nimgcache = {} local function UI() local function startMenu() local width,height = lOS.wAll.getSize() height = height-lOS.tbSize while true do local opt = {{"Task Manager"},{"Settings","Search","Execute"},"Shut Down Options >"} if fs.exists("LevelOS/Global_Login.lua") then if not lOS.userID then table.insert(opt[1],1,"Log in") else table.insert(opt[1],1,"Log out") end end a = {oclickmenu(2,height,21,opt,nil,{Settings=true})} if a[1] == false then break else if a[3] == "Task Manager" then if not fs.exists("LevelOS/Task_Manager.lua") then local f = hpost("https://old.leveloper.cc/sGet.php","path="..textutils.urlEncode("LevelOS/Task_Manager.lua").."&code="..textutils.urlEncode("lSlb8kZq")).readAll() fwrite("LevelOS/Task_Manager.lua",f) end lOS.execute("LevelOS/Task_Manager.lua") break elseif a[3] == "Log in" then lOS.execute("LevelOS/Global_Login.lua") break elseif a[3] == "Log out" then lUtils.logout() break elseif a[3] == "Execute" then -- code b = {lUtils.inputbox("Execute","Enter the path of the program you want to run:",27,10,{" OK ","Cancel"})} if b[1] ~= nil and b[1] ~= "" and b[3] == 1 then local path = string.sub(b[1],string.find(b[1],"%S+")) -- virusscan if fs.exists(path) == false then lUtils.popup("Error!","File does not exist.",21,8,{"OK"}) else --lOS.oWins[#lOS.oWins+1] = {window.create(oldterm,1,2,w,h-3),coroutine.create(function() if shell.run(b[1]) == false then curterm = term.current() term.redirect(oldterm) lUtils.popup(fs.getName(path),fs.getName(path).." has stopped working.",25,9,{"OK"}) term.redirect(curterm) end end),fullscreen=false,minimized=false,filepath=path,icon={string.sub(fs.getName(path),1,3),string.sub(fs.getName(path),4,6)},ran=false} --_G.cWin = #lOS.oWins lOS.execute(b[1]) end end break elseif a[3] == "Search" then -- run search break elseif a[3] == "Settings" then lUtils.openWin("Settings","LevelOS/settings.lua",2,2,49,17,true) break elseif a[3] == "Shut Down Options >" then b = {oclickmenu(22,height,20,{{"Shut Down","Reboot"}})} if b[1] == true then if b[3] == "Shut Down" or b[3] == "Reboot" then --[[lOS.focusWin = lOS.wins[0] local te = lOS.focusWin.win local te2 = lOS.focusWin.owin allcolors = {} for t=0,15,1 do allcolors[#allcolors+1] = {te.getPaletteColor(2^t)} end for t=1,0,-0.1 do for c=0,15,1 do te.setPaletteColor(2^c,allcolors[c+1][1]*t,allcolors[c+1][2]*t,allcolors[c+1][3]*t) te2.setPaletteColor(2^c,allcolors[c+1][1]*t,allcolors[c+1][2]*t,allcolors[c+1][3]*t) end os.sleep(0.05) end lOS.save()]] if b[3] == "Shut Down" then table.insert(subprocesses,coroutine.create(shutdownscreen)) coroutine.resume(subprocesses[#subprocesses]) break --os.shutdown() elseif b[3] == "Reboot" then table.insert(subprocesses,coroutine.create(shutdownscreen)) coroutine.resume(subprocesses[#subprocesses],true) break end end else break end else break end end end lOS.noEvents = false end local tbApps = {} local tbPos = {} _G.lOS.sysDebug = {tbApps=tbApps,tbPos=tbPos} local icoSel local previewWin local function drawTaskbar() local w,h = term.getSize() timeObj.x = w-13 term.setBackgroundColor(colors.gray) term.setCursorPos(1,h) term.clearLine() if icoSel ~= 0 then term.setTextColor(colors.white) else term.setTextColor(colors.lightGray) end tbApps = {} tbPos = {} lOS.sysDebug.tbApps,lOS.sysDebug.tbPos = tbApps,tbPos local appLookup = {} for i,p in ipairs(lOS.processes) do if p.win and p.winMode ~= "widget" and p.winMode ~= "background" then if not appLookup[p.path] then local newLookup = {p} table.insert(tbApps,newLookup) appLookup[p.path] = newLookup else table.insert(appLookup[p.path],p) end end end if not lOS.settings then lOS.settings = {} end if lOS.settings.timeOffset == nil then lOS.settings.timeOffset = 0 end if lOS.settings.rTime == nil then lOS.settings.rTime = false end local t = os.date("*t",os.epoch("utc")/1000+lOS.settings.timeOffset*3600) local function tz(n) return string.rep("0",2-string.len(n))..n end local dateTxt = t.day.."-"..t.month.."-"..(t.year-2000) local lTime if lOS.settings.rTime then lTime = tz(t.hour)..":"..tz(t.min) else local nTime = (os.time()+lOS.settings.timeOffset)%24 local nHour = math.floor(nTime) local nMinute = math.floor((nTime - nHour) * 60) lTime = tz(nHour)..":"..tz(nMinute) end if lOS.tbSize > 1 then term.setCursorPos(1,h-1) term.clearLine() term.setCursorPos(1,h-1) term.write("\144") term.setCursorPos(1,h) term.write("\141") for i,w in ipairs(tbApps) do local top for t=1,#w do if w[t] == lOS.focusWin then top = t break end end local bg,txt if top then bg = colors.lightGray else bg = colors.gray end if icoSel == i then txt = colors.lightGray else txt = colors.white end --[[for y=h-(lOS.tbSize-1),h do term.setBackgroundColor(bg) term.setTextColor(colors.gray) term.setCursorPos(i*4-1,y) term.write("\149") term.setBackgroundColor(colors.gray) term.setTextColor(bg) term.setCursorPos(i*4+3,y) term.write("\149") end]] if lOS.settings.taskbarIcons == false then term.setBackgroundColor(bg) term.setTextColor(txt) term.setCursorPos(i*4,h-1) local title = lUtils.getFileName(program) title = title:sub(1,1):upper()..title:sub(2) local t1,t2 = title:sub(1,3),title:sub(4,6) t1 = t1..string.rep(" ",3-#t1) t2 = t2..string.rep(" ",3-#t2) term.write(t1) term.setCursorPos(i*4,h) term.write(t2) else term.setBackgroundColor(bg) local ico local dPath = w[1].path if fs.getName(dPath) == "main.lua" then dPath = fs.getDir(dPath) end if imgcache[dPath] then ico = {imgcache[dPath]} elseif not nimgcache[dPath] and fs.isDir(dPath) and (fs.exists(fs.combine(dPath,"taskbar.limg")) or fs.exists(fs.combine(dPath,"taskbar.bimg"))) then local img if fs.exists(fs.combine(dPath,"taskbar.limg")) then img = lUtils.asset.load(fs.combine(dPath,"taskbar.limg")) else img = lUtils.asset.load(fs.combine(dPath,"taskbar.bimg")) end img = img[1] local iw = #img[1][1] local ih = #img if iw <= 3 and ih <= 2 then if not imgcache[dPath] then imgcache[dPath] = img end ico = {img} else nimgcache[dPath] = true ico = tbIco["*"] end elseif tbIco[dPath] then ico = tbIco[dPath] else ico = tbIco["*"] end if not ico.inactive then ico.inactive = lUtils.instantiate(ico[1]) for l,line in ipairs(ico.inactive) do line[2] = line[2]:gsub("0","8") line[3] = line[3]:gsub("0","8") end end if icoSel == i then ico = ico.inactive else ico = ico[1] end -- sync pls lUtils.renderImg(ico,i*4,h-1) end tbPos[w] = { x1=i*4, y1=h-1, x2=i*4+2, y2=h } for t=1,#w do tbPos[w[t]] = tbPos[w] end end term.setTextColor(colors.white) if icoSel == -1 then term.setBackgroundColor(colors.lightGray) term.setCursorPos(timeObj.x,h) term.write(string.rep(" ",8)) else term.setBackgroundColor(colors.gray) end term.setCursorPos((timeObj.x+(timeObj.w-1))-(#dateTxt-1),h) term.write(dateTxt) else term.setCursorPos(1,h) term.write("L") for i,w in ipairs(tbApps) do local top for t=1,#w do if w[t] == lOS.focusWin then top = t break end end local bg,txt if top then bg = colors.lightGray else bg = colors.gray end if icoSel == i then txt = colors.lightGray else txt = colors.white end --[[for y=h-(lOS.tbSize-1),h do term.setBackgroundColor(bg) term.setTextColor(colors.gray) term.setCursorPos(i*4-1,y) term.write("\149") term.setBackgroundColor(colors.gray) term.setTextColor(bg) term.setCursorPos(i*4+3,y) term.write("\149") end]] term.setBackgroundColor(bg) term.setTextColor(txt) term.setCursorPos(i*4,h) local t1 = w[1].title:sub(1,3) t1 = t1..string.rep(" ",3-#t1) term.setCursorPos(i*4,h) term.write(t1) tbPos[w] = { x1=i*4, y1=h, x2=i*4+2, y2=h } -- x1, y1, x2, y2 for t=1,#w do tbPos[w[t]] = tbPos[w] end end end term.setTextColor(colors.white) if icoSel == -1 then term.setBackgroundColor(colors.lightGray) term.setCursorPos(timeObj.x,h-(lOS.tbSize-1)) term.write(string.rep(" ",8)) else term.setBackgroundColor(colors.gray) end term.setCursorPos(timeObj.x+2,h-(lOS.tbSize-1)) term.write(lTime) -- notifications button term.setCursorPos(timeObj.x+timeObj.w+1,h-(lOS.tbSize-1)) local fg = colors.white local bg if icoSel == -2 then bg = colors.lightGray else bg = colors.gray end fg,bg = lUtils.toBlit(fg),lUtils.toBlit(bg) --[[if #lOS.notifications > 0 then term.blit("\151\131\148",bg..bg..fg,fg..fg..bg) term.setCursorPos(timeObj.x+timeObj.w+1,h-(lOS.tbSize-2)) term.blit("\130\135\129",fg..fg..fg,bg..bg..bg)]] if #lOS.notifications == 0 then fg = lUtils.toBlit(colors.lightGray) --[[term.blit("\151\140\148",bg..fg..fg,fg..bg..bg) term.setCursorPos(timeObj.x+timeObj.w+1,h-(lOS.tbSize-2)) term.blit("\130\134\129",fg..fg..fg,bg..bg..bg)]] end if lOS.tbSize > 1 then term.blit("\151\131\148",bg..bg..fg,fg..fg..bg) term.setCursorPos(timeObj.x+timeObj.w+1,h-(lOS.tbSize-2)) term.blit("\130\135\129",fg..fg..fg,bg..bg..bg) else term.write("msg") end -- draw uh mminimize button on task bar term.setBackgroundColor(colors.gray) term.setTextColor(colors.lightGray) for y=h-(lOS.tbSize-1),h do term.setCursorPos(w,y) term.write("\149") end end local function genTabMenu() local tabMenu = {} local w,h = lOS.wAll.getSize() local maxW,maxH = w-(math.floor(w/8))-math.floor(math.floor(w/8)),h-(math.floor(h/8))-math.floor(math.floor(h/8)) local minX,minY = math.floor(w/8),math.floor(h/8) while minY+(maxH-1) >= h-lOS.tbSize do maxH = maxH-1 end local maxRows = 4 local rowH = math.floor((maxH-1)/maxRows-2) local minRowH = 5 if h <= 21 then minRowH = 4 end while rowH < minRowH do maxRows = maxRows-1 rowH = math.floor((maxH-1)/maxRows-2) end --#pHistory tabMenu[1] = {w=3} tabMenu.a = {} for i=1,#pHistory do local p = pHistory[i] if p.winMode ~= "background" then local wW,wH = p.win.getSize() local pH = rowH local pW = round(wW/(wH/rowH)) local lilWin = lUtils.littlewin(p.win,pW,pH) lilWin.proc = p lilWin.w,lilWin.h = pW,pH if tabMenu[#tabMenu].w+pW+1 <= maxW then table.insert(tabMenu[#tabMenu],lilWin) tabMenu[#tabMenu].w = tabMenu[#tabMenu].w+pW+1 else table.insert(tabMenu,{lilWin,w=2+pW}) end lilWin.row = #tabMenu table.insert(tabMenu.a,lilWin) end end local rows = math.min(#tabMenu,maxRows) tabMenu.h = 1+rows*(rowH+2) tabMenu.w = 0 local cenX,cenY = math.ceil(w/2),math.ceil(h/2) tabMenu.y = cenY-(math.floor(tabMenu.h/2)) for i,row in ipairs(tabMenu) do tabMenu.w = math.max(row.w,tabMenu.w) local cX = cenX-math.floor(row.w/2) row.x = cX row.y = tabMenu.y+2+(i-1)*(rowH+2) cX = cX+2 for p,win in ipairs(row) do win.x = cX win.y = row.y cX = cX+win.w+1 end end tabMenu.x = cenX-(math.floor(tabMenu.w/2)) function tabMenu.render(fromRow) local fromRow = fromRow or 1 term.setBackgroundColor(colors.gray) lOS.boxClear(tabMenu.x,tabMenu.y,tabMenu.x+(tabMenu.w-1),tabMenu.y+(tabMenu.h-1)) local rows = math.min(#tabMenu,maxRows) local toRow = math.min(fromRow+(maxRows-1),rows) local offset = (fromRow-1)*(rowH+2) local count = 1 for r=1,fromRow-1 do count = count+#tabMenu[r] end local startedTimer for r=fromRow,toRow do local row = tabMenu[r] for p,win in ipairs(row) do if tabMenu.clickSel and tabMenu.clickSel == win then if not win.small then win.small = lUtils.littlewin(win.proc.win,win.w-2,win.h-2) end win.small.render(win.x+1,win.y+1-offset,true) term.setBackgroundColor(colors.gray) term.setTextColor(colors.white) lUtils.border(win.x,win.y,win.x+(win.w-1),win.y+(win.h-1),nil,1) else win.render(win.x,win.y-offset,true) end term.setBackgroundColor(colors.gray) local of = 0 term.setCursorPos(win.x,win.y-1) if win.proc.icon then term.blit(win.proc.icon[1],(win.proc.icon[2] or lUtils.toBlit(term.getBackgroundColor())),(win.proc.icon[3] or lUtils.toBlit(term.getBackgroundColor()))) term.write(" ") of = 2 end term.setTextColor(colors.white) local t = win.proc.title if #t >= win.w-1-of then t = t:sub(1,win.w-3-of)..".." end term.write(t) term.setCursorPos(win.x+win.w-2,win.y-1) local c = "7" if win.closeSel then c = "e" end term.blit("\149×","70",c..c) if tabMenu.sel and tabMenu.sel == count then lUtils.border(win.x-1,win.y-2,win.x+win.w,win.y+win.h,nil,2) end count = count+1 if win.nX then if win.x < win.nX then win.x = win.x+1 elseif win.x > win.nX then win.x = win.x-1 else win.nX = nil end if not startedTimer then startedTimer = os.startTimer(0.05) end end end end end return tabMenu end --[[local function drawTabMenu() term.setBackgroundColor(colors.gray) --lOS.boxClear(math.floor(w/8),math.floor(h/8),w-(math.floor(w/8)-1),h-(math.floor(h/8)-1)) end]] lOS.tbSize = 2 -- check config if disabled, usually local function lMenu() function theOverlayFunction() if previewWin then for i,win in ipairs(previewWin) do local bg = colors.lightGray local tcol if previewWin.sel and previewWin.sel == win then tcol = colors.white else tcol = colors.gray end if tbApps[icoSel][i] == lOS.focusWin then bg = colors.gray if previewWin.sel and previewWin.sel == win then tcol = colors.lightGray else tcol = colors.white end end win.render(win.x,win.y,true) term.setTextColor(bg) lUtils.border(win.x,win.y-1,win.x+(win.w-1),win.y+(win.h-1),"transparent") term.setTextColor(tcol) term.setBackgroundColor(bg) term.setCursorPos(win.x,win.y-1) local txt = tbApps[icoSel][i].title:sub(1,win.w-2) term.write(" "..txt..string.rep(" ",win.w-1-#txt)) local w,h = lOS.wAll.getSize() if win.y+(win.h-1) > h-(lOS.tbSize) then win.y = win.y-1 os.startTimer(0.05) end end end if lOS.tbSize and lOS.tbSize > 0 then local ok, err = pcall(drawTaskbar) if not ok then term.setCursorPos(1,1) term.setBackgroundColor(colors.white) term.setTextColor(colors.red) term.write(err) end end -- DEBUG --[[term.setBackgroundColor(colors.white) term.setTextColor(colors.red) term.setCursorPos(1,1) print(textutils.serialize(events))]] end LevelOS.overlay = theOverlayFunction while true do local w,h = lOS.wAll.getSize() doLog = false local hurry = false if #events > 0 then e = events[1] --[[doLog = true os.sleep(2)]] table.remove(events,1) hurry = true else e = {os.pullEventRaw()} end --[[ MANAGE NOTIFICATIONS ]] if #lOS.notifications > 0 then --[[timer = timer+0.1 if timer >= 2 then table.remove(lOS.notifications,1) timer = 0 end]] end --[[ END OF MANAGE NOTIFICATIONS ]] if #lOS.wins >= 1 then local topwin = lOS.focusWin if topwin ~= pHistory[1] and topwin ~= lOS.wins[0] then for t=1,#pHistory do if pHistory[t] == topwin then table.remove(pHistory,t) break end end table.insert(pHistory,1,topwin) end end for t=#pHistory,1,-1 do if coroutine.status(pHistory[t][1]) == "dead" or pHistory[t].winMode == "background" then table.remove(pHistory,t) end end if e[1] == "window_open" then if tostring(lOS.processes[e[2]]) ~= e[3] then for t=1,#lOS.processes do if tostring(lOS.processes[t]) == e[3] then e[2] = t break end end end elseif e[1]:find("window_") then local wins = lOS.wins if e[1] == "window_focus" then wins = lOS.processes end if tostring(wins[e[2]]) ~= e[3] then for t=1,#wins do if tostring(wins[t]) == e[3] then e[2] = t break end end end end doLog = true if e[1]:find("mouse") and type(e[3]) == "number" and e[4] >= h-(lOS.tbSize-1) then local foundwidget = false if e[1] ~= "mouse_scroll" and e[1] ~= "mouse_move" then for t=#lOS.wins,1,-1 do if lOS.wins[t].winMode == "widget" then if not lOS.sysUIlog then lOS.sysUIlog = {} end table.insert(lOS.sysUIlog,"Closed win "..t.." due to event "..table.concat(e,",")..".") os.queueEvent("window_close",t,tostring(lOS.wins[t]),"some mouse shit") foundwidget = true end end end if foundwidget then -- nothing elseif e[3] <= 2 then if e[1] == "mouse_click" then icoSel = 0 elseif e[1] == "mouse_up" then local oterm = term.current() local win = window.create(term.current(),1,1,w,h,false) local cor = coroutine.create(startMenu) lOS.noEvents = true os.sleep(0) for y=1,h do win.setCursorPos(1,y) win.blit(lOS.wAll.getLine(y)) end local oldOverlay = LevelOS.overlay function LevelOS.overlay() for y=1,h do term.setCursorPos(1,y) term.blit(win.getLine(y)) term.setCursorPos(1,1) term.setBackgroundColor(colors.white) term.setTextColor(colors.red) end oldOverlay() end term.redirect(win) coroutine.resume(cor) while true do local e = {os.pullEventRaw()} term.redirect(win) coroutine.resume(cor,unpack(e)) term.redirect(oterm) if lOS.noEvents == false then break end end term.redirect(oterm) LevelOS.overlay = oldOverlay end -- elseif widget area elseif e[3] >= timeObj.x and e[4] <= h and e[4] >= h-1 then if e[3] <= timeObj.x+(timeObj.w-1) then if e[1] == "mouse_click" then icoSel = -1 elseif e[1] == "mouse_up" then lOS.execute("LevelOS/Clock.lua") end elseif e[3] <= w-2 then if e[1] == "mouse_click" then icoSel = -2 elseif e[1] == "mouse_up" then --lOS.execute("LevelOS/Clock.lua") end else for t=#lOS.wins,1,-1 do if lOS.wins[t].winMode == "widget" then if not lOS.sysUIlog then lOS.sysUIlog = {} end table.insert(lOS.sysUIlog,"Closed win "..t.." due to event "..table.concat(e,",")..".") os.queueEvent("window_close",t,tostring(lOS.wins[t]),"some timeobj thing idk") else os.queueEvent("window_minimize",t,tostring(lOS.wins[t]),true) end end end else for i,v in ipairs(tbApps) do if not tbPos[v] then _G.lOS.sysDebug.error = "tbPos["..tostring(v).." (tbApps["..i.."])] not found." _G.lOS.curApps = {} _G.lOS.curPos = {} for a,b in ipairs(tbApps) do _G.lOS.curApps[a] = {b,tostring(b)} end for c,d in pairs(tbPos) do _G.lOS.curPos[c] = d end lOS.sysDebug.str = tostring(v).." vs "..tostring(tbApps[i]) lOS.sysDebug.theProblem = {v,tbApps[i],tostring(v),tostring(tbApps[i])} _G.lOS.theError = lOS.sysDebug.error error(lOS.sysDebug.error,0) end if lUtils.isInside(e[3],e[4],tbPos[v]) then if e[1] == "mouse_click" or e[1] == "mouse_drag" or e[1] == "mouse_hover" or (previewWin and e[1] == "mouse_move" and type(e[3]) == "number") then icoSel = i if ((e[2] == 1 and #v > 1) or e[1] ~= "mouse_click") then local cX local pW = {} _G.debugPreviewWin = pW for p,app in ipairs(v) do local w,h = app.win.getSize() local nH = 7 local nW = round(w/(h/nH)) local x,y y = tbPos[v].y1-nH if not cX then x = (tbPos[v].x1+1)-(math.floor(nW/2)) if x < 2 then x = 2 elseif x+(nW-1) > ({lOS.wAll.getSize()})[1] then x = ({lOS.wAll.getSize()})[1]-(nW-1) end else x = cX end cX = x+nW pW[p] = lUtils.littlewin(app.win, nW, nH) local offset = 0 if not previewWin then offset = 4 end pW[p].x,pW[p].y = x,y+offset pW[p].w,pW[p].h = nW,nH end previewWin = pW end elseif e[1] == "mouse_up" and icoSel == i and e[2] == 2 then previewWin = nil local opt = {} local dis = {} local h = 1 if v[1].path then local t if fs.getName(v[1].path) == "main.lua" then t = lUtils.getFileName(fs.getDir(v[1].path)) else t = lUtils.getFileName(v[1].path) end t = t:sub(1,1):upper()..t:sub(2) table.insert(opt," \4 "..t) h = h+2 -- (un)pin to/from taskbar table.insert(opt," \25 Pin to taskbar") dis[opt[#opt]] = true h = h+2 end if #v == 1 then table.insert(opt," × Close") else table.insert(opt," × Close all") end h = h+2 local tW,tH = lOS.wAll.getSize() local w,h = 21,7 local x,y = tbPos[v].x1-9,tH-(lOS.tbSize)-(h-1) if x < 2 then x = 2 elseif x+(w-1) > tW then x = tW end local function rWin() term.setBackgroundColor(colors.gray) term.setTextColor(colors.lightGray) lUtils.border(x,y,x+(w-1),y+(h-1),"fill") for t=1,#opt do if dis[opt[t]] then term.setTextColor(colors.lightGray) else term.setTextColor(colors.white) end term.setCursorPos(x+1,y+(t*2)-1) term.write(opt[t]..string.rep(" ",(w-2)-#opt[t])) if t < #opt then term.setCursorPos(x+1,y+(t*2)) term.write(" ",w-2) end end end y = y+3 local oOverlay = LevelOS.overlay function LevelOS.overlay() rWin() oOverlay() end for t=1,3 do os.sleep(0.05) y = y-1 end os.sleep(0) function LevelOS.overlay() term.setBackgroundColor(colors.gray) term.setTextColor(colors.lightGray) lUtils.border(x,y,x+(w-1),y+(h-1)) end local a runOverlay(function() a = {lUtils.oclickmenu(x,y,w,opt,nil,dis,{bg=colors.gray,fg=colors.gray,txt=colors.white})} end,false,true) if a[1] then if a[3] == opt[1] and v[1].path then lOS.execute(v[1].path) elseif (a[3] == opt[1] and not v[1].path) or (v[1].path and a[3] == opt[3]) then for t=#lOS.wins,1,-1 do if (lOS.wins[t] == v[1] and not v[1].path) or (v[1].path and v[1].path == lOS.wins[t].path) then if not lOS.sysUIlog then lOS.sysUIlog = {} end table.insert(lOS.sysUIlog,"Closed win "..t.." through taskbar menu.") os.queueEvent("window_close",t,tostring(lOS.wins[t])) end end for t=1,#v do if v[t].minimized then for p=1,#lOS.processes do if lOS.processes[p] == v[t] then table.remove(lOS.processes,p) break end end for p=1,#pHistory do if pHistory[p] == v[t] then table.remove(pHistory,p) break end end end end elseif v[1].path and a[3] == opt[2] then -- nothing end end LevelOS.overlay = oOverlay elseif e[1] == "mouse_up" and icoSel == i and e[2] == 1 then if #v == 1 then previewWin = nil local v = v[1] if v == lOS.focusWin then --[[local dur = 5 local x,y = v.win.getPosition() local w,h = v.win.getSize() local gx,gy = tbPos[v].x1,tbPos[v].y1 local gw,gh = 3,2 for t=#lOS.wins,1,-1 do if lOS.wins[t] == lOS.focusWin then table.remove(lOS.wins,t) lOS.focusWin = lOS.wins[t-1] break end end animation(v,x,y,w,h,gx,gy,gw,gh,dur) v.minimized = true]] local id for k1,v1 in pairs(lOS.wins) do if v1 == v then id = k1 break end end os.queueEvent("window_minimize",id,tostring(v)) --[[elseif not potato then lOS.sysDebug.v = v]] else local id for k1,v1 in pairs(lOS.processes) do if v1 == v then id = k1 break end end os.queueEvent("window_focus",id,tostring(v)) end else -- choose from previews lOS.noEvents = true local pW = previewWin while true do local e = {os.pullEventRaw()} if e[1] == "mouse_up" or e[1] == "mouse_drag" or e[1] == "mouse_click" then local terminate = true for i,win in ipairs(pW) do local lWin = tbApps[icoSel][i] local focusWin for t=1,#lOS.wins do if lOS.wins[t] == lWin then focusWin = t break end end local fID for t=#lOS.wins,0,-1 do if lOS.wins[t] == lOS.focusWin then fID = t end end if e[3] >= win.x and e[4] >= win.y and e[3] <= win.x+(win.w-1) and e[4] <= win.y+(win.h-1) then terminate = false if e[2] == 2 and e[1] == "mouse_up" then local dis = {} if not (lWin.snap or lWin.minimized) then dis["= Restore"] = true end if lWin.snap and lWin.snap.x and lWin.snap.y then dis["+ Maximize"] = true end if lWin.minimized then dis["- Minimize"] = true end lOS.cWin = 0 local a local oOverlay = LevelOS.overlay LevelOS.overlay = nil runOverlay(function() a = {lUtils.oclickmenu(e[3],e[4],19,{"= Restore",{"- Minimize","+ Maximize"},"× Close Ctrl+W"},nil,dis)} end,false,true) LevelOS.overlay = oOverlay if a[1] then if a[3] == "= Restore" then if lWin.minimized then local dur = 5 local x,y = tbPos[lWin].x1,tbPos[lWin].y1 local w,h = 3,2 local gx,gy = lWin.win.getPosition() local gw,gh = lWin.win.getSize() animation(lWin,x,y,w,h,gx,gy,gw,gh,dur) lWin.minimized = nil table.insert(lOS.wins,lWin) lOS.focusWin = lWin elseif lWin.snap then --os.queueEvent("timer",9999999) os.queueEvent("window_reposition",focusWin,tostring(lWin),lWin.snap.oPos[1],lWin.snap.oPos[2],unpack(lWin.snap.oSize)) lWin.snap = nil end elseif a[3] == "- Minimize" then --os.queueEvent("timer",9999999) os.queueEvent("window_minimize",focusWin,tostring(lWin)) elseif a[3] == "+ Maximize" then os.queueEvent("timer",9999999) local totalW,totalH = lOS.wAll.getSize() lWin.snap = {x=true,y=true,oPos={lWin.win.getPosition()},oSize={lWin.win.getSize()}} os.queueEvent("window_reposition",focusWin,tostring(lWin),1,2,totalW,totalH-1) elseif a[3] == "× Close Ctrl+W" then if lWin.env and lWin.env.LevelOS and type(lWin.env.LevelOS.close) == "function" then if lWin.minimized then local dur = 5 local x,y = tbPos[lWin].x1,tbPos[lWin].y1 local w,h = 3,2 local gx,gy = lWin.win.getPosition() local gw,gh = lWin.win.getSize() animation(lWin,x,y,w,h,gx,gy,gw,gh,dur) lWin.minimized = nil table.insert(lOS.wins,lWin) lOS.focusWin = lWin end --lWin[1] = coroutine.create(lWin.env.LevelOS.close) --lWin.env.LevelOS.close = nil runLevelOSclose(lWin) else if focusWin then --os.queueEvent("timer",9999999) --[[if not lOS.sysUIlog then lOS.sysUIlog = {} end table.insert(lOS.sysUIlog,"Closed win "..focusWin.." through taskbar submenu.")]] os.queueEvent("window_close",focusWin,tostring(lWin)) else for t=1,#lOS.processes do if lOS.processes[t] == lWin then table.remove(lOS.processes,t) break end end for t=1,#pHistory do if pHistory[t] == lWin then table.remove(pHistory,t) break end end end end end end previewWin = nil lOS.noEvents = false break elseif e[2] == 1 and e[1] == "mouse_up" then -- switch if not (focusWin and focusWin == fID) then local v = lWin if v.minimized then local dur = 5 local x,y = tbPos[v].x1,tbPos[v].y1 local w,h = 3,2 local gx,gy = v.win.getPosition() local gw,gh = v.win.getSize() animation(v,x,y,w,h,gx,gy,gw,gh,dur) v.minimized = nil else for i=1,#lOS.wins do if lOS.wins[i] == v then table.remove(lOS.wins,i) break end end end table.insert(lOS.wins,v) lOS.focusWin = v end previewWin = nil lOS.noEvents = false break else pW.sel = win end end end if terminate or not previewWin then icoSel = nil previewWin = nil lOS.noEvents = false break end end if e[1] == "mouse_up" and previewWin then previewWin.sel = nil end end end end break end end end elseif e[1] == "window_open" then local v = lOS.processes[e[2]] if v and tostring(v) == e[3] then local dur = 2 local gx,gy = v.win.getPosition() local gw,gh = v.win.getSize() local x,y = gx+4,gy+2 local w,h = gw-8,gh-4 local tW,tH = lOS.wAll.getSize() if (v.winMode == "widget" or v.winMode == "borderless") then dur = 4 if gy > 2 and gy+(gh-1) == tH-lOS.tbSize then x,y = gx,tH-lOS.tbSize w,h = gw,gh elseif gx+(gw-1) == tW then x,y = tW,gy w,h = gw,gh end end animation(v,x,y,w,h,gx,gy,gw,gh,dur) table.insert(lOS.wins,v) if e[4] ~= false then lOS.focusWin = v end end elseif e[1] == "window_focus" and lOS.processes[e[2]] and tostring(lOS.processes[e[2]]) == e[3] then local v = lOS.processes[e[2]] if v.minimized then local dur = 5 local x,y = tbPos[v].x1,tbPos[v].y1 local w,h = 3,2 local gx,gy = v.win.getPosition() local gw,gh = v.win.getSize() animation(v,x,y,w,h,gx,gy,gw,gh,dur) v.minimized = nil else for i=1,#lOS.wins do if lOS.wins[i] == v then table.remove(lOS.wins,i) break end end end table.insert(lOS.wins,v) lOS.focusWin = v elseif e[1] == "window_minimize" and lOS.wins[e[2]] and tostring(lOS.wins[e[2]]) == e[3] then local v = lOS.wins[e[2]] local dur = 5 if hurry or #events > 0 or e[4] then dur = 3 end local x,y = v.win.getPosition() local w,h = v.win.getSize() local gx,gy = tbPos[v].x1,tbPos[v].y1 local gw,gh = 3,2 table.remove(lOS.wins,e[2]) if lOS.focusWin == v then lOS.focusWin = lOS.wins[e[2]-1] end animation(v,x,y,w,h,gx,gy,gw,gh,dur) v.minimized = true elseif e[1] == "window_reposition" and lOS.wins[e[2]] and tostring(lOS.wins[e[2]]) == e[3] then local win = lOS.wins[e[2]] local x,y = win.win.getPosition() local w,h = win.win.getSize() local _,focusWin,pointer,gx,gy,gw,gh = unpack(e) local dur = 2 table.remove(lOS.wins,e[2]) animation(win,x,y,w,h,gx,gy,gw,gh,dur) table.insert(lOS.wins,win) win.win.reposition(gx,gy,gw,gh) os.queueEvent("term_resize") elseif (e[1] == "window_close" and tostring(lOS.wins[e[2]]) == e[3]) or (e[1] == "process_close" and tostring(lOS.processes[e[2]]) == e[3]) --[[or (e[1] == "key_up" and lUtils.isHolding(keys.leftCtrl) and e[2] == keys.w and #lOS.wins > 0 and lOS.focusWin and lOS.focusWin ~= lOS.wins[0] and not lOS.focusWin.noShortcuts)]] then local focusWin if e[1] == "window_close" then focusWin = e[2] elseif e[1] == "process_close" then for i,lwin in pairs(lOS.wins) do if lOS.wins[i] == lOS.processes[e[2]] then focusWin = i e[1] = "window_close" e[2] = focusWin break end end else for t=#lOS.wins,1,-1 do if lOS.wins[t] == lOS.focusWin then focusWin = t break end end end local win if focusWin then win = lOS.wins[focusWin] elseif e[1] == "process_close" then win = lOS.processes[e[2]] end if win.env and win.env.LevelOS and type(win.env.LevelOS.close) == "function" then --[[win[1] = coroutine.create(win.env.LevelOS.close) win.env.LevelOS.close = nil]] runLevelOSclose(win) elseif e[1] == "process_close" then table.remove(lOS.processes,e[2]) elseif e[1] == "window_close" then win.closing = true local x,y = win.win.getPosition() local w,h = win.win.getSize() local gx,gy = x+4,y+2 local gw,gh = w-8,h-4 local tW,tH = lOS.wAll.getSize() local dur = 2 if (win.winMode == "widget" or win.winMode == "borderless") then dur = 4 if y > 2 and y+(h-1) == tH-lOS.tbSize then gx,gy = x,tH-lOS.tbSize gw,gh = w,h elseif x+(w-1) == tW then gx,gy = tW,y gw,gh = w,h end end if lOS.wins[focusWin].winMode ~= "background" then local proc = lOS.processes for i=1,#proc do if lOS.wins[focusWin] == proc[i] then table.remove(proc,i) end end end table.remove(lOS.wins,focusWin) if lOS.focusWin == win then lOS.focusWin = lOS.wins[focusWin-1] -- good end animation(win,x,y,w,h,gx,gy,gw,gh,dur) for t=1,#pHistory do if pHistory[t] == win then table.remove(pHistory,t) break end end end elseif e[1] == "key" then if e[2] == keys.f5 and #lOS.wins > 0 then if lOS.focusWin.winMode == "fullscreen" and lOS.focusWin.fullscreen then local proc = lOS.focusWin proc.winMode = "windowed" proc.win.reposition(proc.fullscreen.pos[1],proc.fullscreen.pos[2],proc.fullscreen.size[1],proc.fullscreen.size[2],lOS.wAll) proc.win.setVisible(false) proc.fullscreen = nil else local proc = lOS.focusWin proc.winMode = "fullscreen" end elseif e[2] == keys.tab and lUtils.isHolding(keys.leftCtrl) and #pHistory > 0 then if lOS.focusWin.winMode == "fullscreen" then local win = lOS.focusWin for t=#lOS.wins,1,-1 do if lOS.wins[t] == lOS.focusWin then table.remove(lOS.wins,t) break end end win.minimized = true end local oOverlay = LevelOS.overlay local tabMenu = genTabMenu() lOS.sysDebug.tabMenu = tabMenu tabMenu.sel = math.min(#pHistory,2) function LevelOS.overlay() oOverlay() tabMenu.render() end lOS.noEvents = true while true do if tabMenu.sel and not tabMenu.a[tabMenu.sel] then if #tabMenu.a < 1 then LevelOS.overlay = oOverlay break else while tabMenu.sel > #tabMenu.a do tabMenu.sel = tabMenu.sel-1 end end end local e = {os.pullEventRaw()} lOS.noEvents = true if (e[1] == "key_up" and e[2] == keys.leftCtrl) or e[1] == "tabMenu_close" then LevelOS.overlay = oOverlay if tabMenu.sel then local proc = tabMenu.a[tabMenu.sel].proc if proc.minimized then for t=1,#lOS.processes do if lOS.processes[t] == proc then local dur = 5 local x,y = tbPos[proc].x1,tbPos[proc].y1 local w,h = 3,2 local gx,gy = proc.win.getPosition() local gw,gh = proc.win.getSize() animation(proc,x,y,w,h,gx,gy,gw,gh,dur) proc.minimized = nil table.insert(lOS.wins,proc) lOS.focusWin = proc break end end else for t=1,#lOS.wins do if lOS.wins[t] == proc then table.remove(lOS.wins,t) break end end table.insert(lOS.wins,proc) lOS.focusWin = proc end end break elseif e[1] == "key" and e[2] == keys.tab or e[2] == keys.right then tabMenu.sel = tabMenu.sel+1 if tabMenu.sel > #tabMenu.a then tabMenu.sel = 1 end elseif e[1] == "key" and e[2] == keys.left then tabMenu.sel = tabMenu.sel-1 if tabMenu.sel < 1 then tabMenu.sel = #tabMenu.a end elseif e[1]:find("mouse") and e[2] == 1 and type(e[3]) == "number" then if e[3] >= tabMenu.x and e[4] >= tabMenu.y and e[3] <= tabMenu.x+(tabMenu.w-1) and e[4] <= tabMenu.y+(tabMenu.h-1) then tabMenu.closing = nil for i,win in ipairs(tabMenu.a) do if e[3] >= win.x and e[4] >= win.y and e[3] <= win.x+(win.w-1) and e[4] <= win.y+(win.h-1) then if e[1] == "mouse_click" or e[1] == "mouse_drag" then tabMenu.clickSel = win elseif e[1] == "mouse_up" then tabMenu.sel = i os.queueEvent("tabMenu_close") end elseif e[3] == win.x+(win.w-1) and e[4] == win.y-1 then if e[1] == "mouse_click" then win.closeSel = true elseif e[1] == "mouse_up" and win.closeSel then local lWin = win.proc local focusWin for t=1,#lOS.wins do if lOS.wins[t] == lWin then focusWin = t end end if lWin.env and lWin.env.LevelOS and type(lWin.env.LevelOS.close) == "function" then if lWin.minimized then local dur = 5 local x,y = tbPos[lWin].x1,tbPos[lWin].y1 local w,h = 3,2 local gx,gy = lWin.win.getPosition() local gw,gh = lWin.win.getSize() animation(lWin,x,y,w,h,gx,gy,gw,gh,dur) lWin.minimized = nil table.insert(lOS.wins,lWin) lOS.focusWin = lWin end --[[lWin[1] = coroutine.create(lWin.env.LevelOS.close) lWin.env.LevelOS.close = nil]] runLevelOSclose(lWin) else if focusWin then --os.queueEvent("timer",9999999) --os.queueEvent("window_close",focusWin,tostring(lWin)) local win = lWin local x,y = win.win.getPosition() local w,h = win.win.getSize() local gx,gy = x+4,y+2 local gw,gh = w-8,h-4 local tW,tH = lOS.wAll.getSize() local dur = 2 if (win.winMode == "widget" or win.winMode == "borderless") and y > 2 and y+(h-1) == tH-lOS.tbSize then dur = 4 gx,gy = x,tH-lOS.tbSize gw,gh = w,h end if lOS.wins[focusWin].winMode ~= "background" then local proc = lOS.processes for i=1,#proc do if lOS.wins[focusWin] == proc[i] then table.remove(proc,i) end end end table.remove(lOS.wins,focusWin) animation(win,x,y,w,h,gx,gy,gw,gh,dur) for t=1,#pHistory do if pHistory[t] == win then table.remove(pHistory,t) break end end else for t=1,#lOS.processes do if lOS.processes[t] == lWin then table.remove(lOS.processes,t) break end end for t=1,#pHistory do if pHistory[t] == lWin then table.remove(pHistory,t) break end end end end --[[LevelOS.overlay = oOverlay break]] table.remove(tabMenu.a,i) local row = tabMenu[win.row] for t=1,#row do if win == row[t] then table.remove(row,t) break end end if #row > 0 then row.w = 3 for i,win in ipairs(row) do row.w = row.w+win.w+1 end local w,h = lOS.wAll.getSize() local cenX,cenY = math.ceil(w/2),math.ceil(h/2) local cX = cenX-math.floor(row.w/2) --row.x = cX cX = cX+2 for p,win in ipairs(row) do win.nX = cX cX = cX+win.w+1 end else local sel = tabMenu.sel tabMenu = genTabMenu() tabMenu.sel = sel end break end else win.closeSel = nil end end else if e[1] == "mouse_click" then tabMenu.closing = true elseif e[1] == "mouse_up" and tabMenu.closing then LevelOS.overlay = oOverlay break end end if e[1] == "mouse_up" then tabMenu.clickSel = nil end end end lOS.noEvents = false end end if e[1] == "mouse_up" then previewWin = nil icoSel = nil end end end local function internet() while true do lOS.checkinternet() os.sleep(30) end end local function fade() local native = {} local col = colors.black if lOS.isCyan then col = colors.cyan end for c=0,15,1 do native[2^c] = {--[[lOS.wins[0].win.getPaletteColor(2^c)]]term.nativePaletteColor(col)} end for p,process in pairs(lOS.processes) do for c=0,15,1 do process.win.setPaletteColor(2^c,unpack(native[2^c])) if process.owin then process.owin.setPaletteColor(2^c,unpack(native[2^c])) end end end local prog = 1 local dur = 5 local function col(c,d) local n = native[c] local cur = {lOS.wins[0].win.getPaletteColor(c)} local rgb = {} for t=1,3 do local st = (d[t]-n[t])/dur --rgb[t] = cur[t]+st rgb[t] = n[t]+st*prog end return rgb[1],rgb[2],rgb[3] end for t=1,dur do prog = t for p,process in pairs(lOS.processes) do for c=0,15,1 do if t < dur then process.win.setPaletteColor(2^c,col(2^c,{term.nativePaletteColor(2^c)})) if process.owin then process.owin.setPaletteColor(2^c,col(2^c,{term.nativePaletteColor(2^c)})) end else process.win.setPaletteColor(2^c,term.nativePaletteColor(2^c)) if process.owin then process.owin.setPaletteColor(2^c,term.nativePaletteColor(2^c)) end end end end os.sleep(0.05) end end parallel.waitForAny(logEvents,lMenu,function() if lOS.isCyan then fade() end lOS.fadeComplete = true while true do pcall(internet) end end) end local ok,err = pcall(UI) if not ok then lOS.systemUIerror = err lOS.bsod(err) else lOS.systemUIerror = "Unknown error: "..tostring(err) end lOS.noEvents = false