3057 posts
Location
United States of America
Posted 05 November 2015 - 12:17 AM
I have this program, not nearly finished, that's going to be a coroutine manager.
the program
local tUserEvents = {
mouse_click = true,
mouse_drag = true,
mouse_up = true,
key = true,
char = true,
key_up = true,
monitor_touch = true,
mouse_scroll = true,
paste = true,
}
local tApps, sCurrent = {}
function getRunningApp()
for i, app in ipairs( tApps ) do
if coroutine.status( app.co ) == "running" then
return app.name
end
end
end
function listRunningApps()
return table.protect( tApps )
end
function launchApp( appPath, ... )
local app = {}
app.window = term.current()
app.name = fs.getName( appPath )
local func = loadfile( appPath )
app.co = coroutine.create( func )
_, app.filter = coroutine.resume( app.co, ... )
tApps[ #tApps + 1 ] = app
end
function setCurrent( appName )
for i, app in ipairs( tApps ) do
if app.name == appName then
sCurrent = appName
return true
end
end
return false
end
function runApps()
local event = {}
while #tApps > 0 do
for i, app in ipairs( tApps ) do
if (app.name == sCurrent or not tUserEvents[ event[ 1 ] ]) and (app.filter == event[ 1 ] or not app.filter) then
term.redirect( app.window )
_, app.filter = coroutine.resume( app.co, unpack(event) )
end
if coroutine.status( app.co ) == "dead" then
table.remove( tApps, i )
end
end
event = {os.pullEvent()}
end
end
…however, it doesn't exactly work as planned when a program uses term.redirect itself. The program in question works perfectly fine when not being run by this manager, but rendering is very screwed up when it is - given that it has an internal window. For now, I am using the default window API in this program, changing it would not help as any program that does use it will continue to have incorrect behavior.
8543 posts
Posted 05 November 2015 - 01:03 AM
You need to redirect to the window you want the app to run in prior to resuming it for the first time. I'd assume that the program with the messed up rendering creates the window prior to its first yield, so at that point, term.current() won't be pointing at where you'd really like it to be without an initial redirect.
Either that or you're not showing us all of the relevant code.
3057 posts
Location
United States of America
Posted 05 November 2015 - 01:30 AM
I'm running the app in the default term at the moment. ( notice the line app.window = term.current() ). The program is, therefor, redirected to the current window when launched - because the apps window becomes whatever term.current() was at the time of launch.
I've created a demonstration program that should show the problem I ran into:
test
local maxx, maxy = term.getSize()
local w = window.create( term.current(), 1, 4, maxx, maxy - 3 )
term.redirect( w )
term.setBackgroundColor( colors.white )
term.clear()
sleep( 1 )
term.clear()
runitall
os.loadAPI( "appManager" ) --#this is the API I posted in the OP
appManager.launchApp( "test" ) --#this is the test program above
appManager.runApps()
Running the program test directly will cover an area of the screen in white, wait a second, then end.
Running the runitall program will cover an area of the screen in white, wait a second, cover the remaining part in white, then end.
Edited on 05 November 2015 - 12:31 AM
7083 posts
Location
Tasmania (AU)
Posted 05 November 2015 - 03:35 AM
After resuming each coroutine, you should be immediately performing "app.window = term.current()" again.
2679 posts
Location
You will never find me, muhahahahahaha
Posted 05 November 2015 - 05:44 AM
Also, the getRunning function isn't very helpful if you call it from outside because it will return suspended for all the coroutines. Also, to make it faster, you could add a var running and before a routine is resumed, set it to the number of the routine. I hope this will increase performance.
3057 posts
Location
United States of America
Posted 05 November 2015 - 01:50 PM
Thanks BB, that fixed it!
Creator, that function is meant to be called within a running coroutine - it's part of my security.
Edited on 05 November 2015 - 12:52 PM
2679 posts
Location
You will never find me, muhahahahahaha
Posted 05 November 2015 - 02:16 PM
Ok. What security?
3057 posts
Location
United States of America
Posted 05 November 2015 - 03:29 PM
Certain programs will have write access for fs, others will not. It's not released yet, you'll just have to wait and see :)/>
(Although, I probably will go with your suggestion of using a variable)
3057 posts
Location
United States of America
Posted 09 November 2015 - 05:18 AM
So… I broke this again somehow. Same problem as before with windows in programs. Went so far as to actually open minecraft and test it on the actual mod instead of an emulator. Still broken.
Relevant Code:
Spoiler
Github Repo
1. Make the directory "SecureOS"
2. Get these files from the repo
SecureOS/startup
SecureOS/desktop
SecureOS/appManager
SecureOS/simpleButton
3. Run SecureOS/desktop –this will show you what *should* happen
4. Run SecureOS/startup –this will show you what is *broken*
7083 posts
Location
Tasmania (AU)
Posted 09 November 2015 - 07:00 AM
Just at a glance, I'm seeing two copies of most of your function definitions within "startup". Beats me whether they're exactly the same or not, but obviously only the second ones will apply.
Also note that this:
appManager = table.protect( appManager )
… will not replace _G.appManager, but rather will define a new global variable within your script's environment.
Edit:
On actually
running your code, I can't see what symptoms you're referring to - it's the same whether I run "desktop" directly or via "startup". You may need to elaborate on your problem.
Edited on 09 November 2015 - 11:55 AM
3057 posts
Location
United States of America
Posted 09 November 2015 - 07:47 PM
I fixed the double definition thing on github. I have no idea when that happened.
As for it working exactly the same, did you actually click on anything? The bug doesn't happen immediately, rather, it occurs after a button is clicked.
7083 posts
Location
Tasmania (AU)
Posted 09 November 2015 - 11:14 PM
Yes, though I didn't see anything too obvious.
Looking at the appManager code though, I see my answer is the same as before: You need to perform "app.window = term.current()" immediately after resuming each coroutine. Including after
line 36.
8543 posts
Posted 10 November 2015 - 01:01 AM
You may be better off creating one central function that resumes coroutines (passing to it all relevant information about the coroutine and the current event), and only ever resume them from that function. The initial resume to "launch" the program is then just passing the newly created coroutine an empty event in the master resume function. That way, you can ensure consistent behavior with your coroutines and only have to change things in one place.
3057 posts
Location
United States of America
Posted 10 November 2015 - 02:33 AM
I added the line you specified after line 36, which fixed the problem I was having. Odd that you didn't encounter the bug I did.
Anyway, thanks for all the help.