Browse Source

Cleaned/rearranged mojo. Remove mojo.process and mojo.timer (now in std).

Mark Sibly 9 years ago
parent
commit
efd10ec5f3

+ 150 - 131
modules/mojo/app/app.monkey2

@@ -1,8 +1,15 @@
 
-#Import "native/async.cpp"
+#Import "native/app.cpp"
+#Import "native/app.h"
 
 Namespace mojo.app
 
+Extern Private
+
+Function AppInit()="bbApp::init"
+
+Public
+
 '#Import "assets/Roboto-Regular.ttf@/mojo"
 '#Import "assets/RobotoMono-Regular.ttf@/mojo"
 
@@ -29,23 +36,10 @@ by prefixing it with 'App.', eg: App.MilliSecs
 #end
 Class AppInstance
 	
-	#rem monkeydoc Idle signal.
-	
-	Invoked when the app becomes idle.
-	
-	This is reset to null after being invoked.
-
+	#rem monkeydoc Invoked when the app becomes idle.
 	#end
 	Field Idle:Void()
 	
-	#rem monkeydoc @hidden
-	#end
-	Field NextIdle:Void()	
-
-	#rem monkeydoc @hidden
-	#end
-	Field ThemeChanged:Void()
-	
 	#rem monkeydoc Invoked when app is activated.
 	#end
 	Field Activated:Void()
@@ -54,11 +48,19 @@ Class AppInstance
 	#end
 	Field Deactivated:Void()
 	
+	#rem monkeydoc @hidden
+	#end
+	Field ThemeChanged:Void()
+	
+	#rem monkeydoc Invoked when a file is dropped on an app window.
+	#end
+	Field FileDropped:Void( path:String )
+	
 	#rem monkeydoc Key event filter.
 	
 	To prevent the event from being sent to a view, a filter can eat the event using [[Event.Eat]].
 	
-	Functions should check if the event has already been 'eaten' by checking the event's [[Event.Eaten]] property before processing the event.
+	Filter functions should check if the event has already been 'eaten' by checking the event's [[Event.Eaten]] property before processing the event.
 	
 	#end
 	Field KeyEventFilter:Void( event:KeyEvent )
@@ -67,7 +69,7 @@ Class AppInstance
 	
 	To prevent the event from being sent to a view, a filter can eat the event using [[Event.Eat]].
 
-	Functions should check if the event has already been 'eaten' by checking the event's [[Event.Eaten]] property before processing the event.
+	Filter functions should check if the event has already been 'eaten' by checking the event's [[Event.Eaten]] property before processing the event.
 	
 	#end	
 	Field MouseEventFilter:Void( event:MouseEvent )
@@ -82,11 +84,9 @@ Class AppInstance
 	
 		_config=config
 
-#if __TARGET__="android"
-		_touchMouse=True
-#endif
+		SDL_Init( SDL_INIT_VIDEO|SDL_INIT_JOYSTICK )
 		
-		SDL_Init( SDL_INIT_EVERYTHING & ~SDL_INIT_AUDIO )
+		AppInit()
 		
 		Keyboard.Init()
 		
@@ -94,15 +94,22 @@ Class AppInstance
 		
 		Audio.Init()
 		
-#if __TARGET__="android"		
+#if __MOBILE_TARGET__
+
+		_touchMouse=True
 
 		SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION,2 )
 	    SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION,0 ) 
     	SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK,SDL_GL_CONTEXT_PROFILE_ES )
     	
 #endif
+
+#If __TARGET__="windows" Or __TARGET__="macos"
+
+		_captureMouse=True
+#Endif
     
-#if __TARGET__="desktop" and __HOSTOS__="windows"
+#if __TARGET__="windows"
 
 		Local gl_major:=Int( GetConfig( "GL_context_major_version",-1 ) )
 		Local gl_minor:=Int( GetConfig( "GL_context_major_version",-1 ) )
@@ -127,7 +134,7 @@ Class AppInstance
 
 #Endif
 
-#if __TARGET__="desktop"
+#if __DESKTOP_TARGET__
 
 		SDL_GL_SetAttribute( SDL_GL_SHARE_WITH_CURRENT_CONTEXT,1 )
 		SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER,1 )
@@ -283,6 +290,21 @@ Class AppInstance
 		Return _activeWindow
 	End
 	
+	#rem monkeydoc Mouse location relative to the active window.
+	
+	@see [[ActiveWindow]], [[MouseX]], [[MouseY]]
+	
+	#end	
+	Property MouseLocation:Vec2i()
+
+		Return _mouseLocation
+	End
+	
+	Property ModalView:View()
+	
+		Return _modalView
+	End
+	
 	#rem monkeydoc Approximate frames per second rendering rate.
 	#end
 	Property FPS:Float()
@@ -292,30 +314,37 @@ Class AppInstance
 	
 	#rem monkeydoc Number of milliseconds app has been running.
 	
-	This property uses the high precision system timer if possible.
+	Deprecated! Just use std.time.Millisecs()
 	
 	#end
 	Property Millisecs:Int()
 	
-		Return SDL_GetTicks()
+		Return std.time.Millisecs()
 	End
 	
-	#rem monkeydoc Mouse location relative to the active window.
-	
-	@see [[ActiveWindow]], [[MouseX]], [[MouseY]]
-	
-	#end	
-	Property MouseLocation:Vec2i()
+#If __TARGET__<>"emscripten"
 
-		Return _mouseLocation
-	End
+	Method Sleep( seconds:Double )
 	
-	Property ModalView:View()
+		Local timeout:=Now()+seconds
+		
+		Repeat
+			Local sleep:=timeout-Now()
+			If sleep>10
+				time.Sleep( sleep )
+				UpdateWindows()
+			Else If sleep>0
+				time.Sleep( sleep )
+			Else
+				Return
+			Endif
+		Forever
 	
-		Return _modalView
 	End
+
+#endif
 	
-	#if __TARGET__="desktop"
+#If __DESKTOP_TARGET__
 	
 	#rem monkeydoc @hidden
 	#end
@@ -329,7 +358,7 @@ Class AppInstance
 		future.Get()
 	End
 	
-	#endif
+#Endif
 	
 	#rem monkeydoc @hidden
 	#end
@@ -467,7 +496,7 @@ Class AppInstance
 	#end
 	Method Run()
 	
-#if __TARGET__="desktop"
+#if __DESKTOP_TARGET__ 
 	
 		SDL_AddEventWatch( _EventFilter,Null )
 
@@ -491,8 +520,9 @@ Class AppInstance
 	Private
 	
 	Field _config:StringMap<String>
-	
-	Field _touchMouse:Bool=False		'mouse is really touch...
+
+	Field _touchMouse:Bool=False		'Whether mouse is really touch
+	Field _captureMouse:Bool=False		'Whether to use SDL_CaptureMouse
 	
 	Field _defaultFont:Font
 	Field _theme:Theme
@@ -561,8 +591,7 @@ Class AppInstance
 		_polling=False
 		
 		Local idle:=Idle
-		Idle=NextIdle
-		NextIdle=Null
+		Idle=Null
 		idle()
 		
 	End
@@ -686,23 +715,28 @@ Class AppInstance
 			
 			If Not _mouseView
 			
-				Local view:=ActiveViewAtMouseLocation()
-
-				If view
+				Local mouseView:=ActiveViewAtMouseLocation()
+				
+				If mouseView
 
 					If _touchMouse
-						_hoverView=view
+					
+						_hoverView=mouseView
+						
 						SendMouseEvent( EventType.MouseEnter,_hoverView )
+					
 					Endif
+				
+					If _captureMouse SDL_CaptureMouse( SDL_TRUE )
 					
-					SDL_CaptureMouse( SDL_TRUE )
-					_mouseView=view
+					_mouseView=mouseView
 					
 					_mouseClicks=mevent->clicks
 					
 					SendMouseEvent( EventType.MouseDown,_mouseView )
 					
 					_mouseClicks=0
+
 				Endif
 				
 			Endif
@@ -719,19 +753,22 @@ Class AppInstance
 			
 			If _mouseView
 
+				If _captureMouse SDL_CaptureMouse( SDL_FALSE )
+
 				SendMouseEvent( EventType.MouseUp,_mouseView )
-				
-				SDL_CaptureMouse( SDL_FALSE )
-				
-				_mouseView=Null
 
 				_mouseButton=Null
 				
+				_mouseView=Null
+				
 				If _touchMouse
+					
 					SendMouseEvent( EventType.MouseLeave,_hoverView )
+				
 					_hoverView=Null
+
 				Endif
-				
+
 			Endif
 			
 		Case SDL_MOUSEMOTION
@@ -743,62 +780,32 @@ Class AppInstance
 				
 			_mouseLocation=New Vec2i( mevent->x,mevent->y )
 			
-			If _mouseView
-			
-				SendMouseEvent( EventType.MouseMove,_mouseView )
-			
-			Else If Not _touchMouse
+			If Not _touchMouse
 			
-				Local view:=ActiveViewAtMouseLocation()
-				
-				If view<>_hoverView
-
+				Local hoverView:=ActiveViewAtMouseLocation()
+				If _mouseView And hoverView<>_mouseView hoverView=Null
+	
+				If hoverView<>_hoverView
+	
 					If _hoverView SendMouseEvent( EventType.MouseLeave,_hoverView )
-					
-					_hoverView=view
-					
+						
+					_hoverView=hoverView
+						
 					If _hoverView SendMouseEvent( EventType.MouseEnter,_hoverView )
-
+				
 				Endif
 				
-				If _hoverView SendMouseEvent( EventType.MouseMove,_hoverView )
-			
 			Endif
 			
-			#rem
-			If Not _touchMouse Or _mouseView
-		
-				Local mevent:=Cast<SDL_MouseMotionEvent Ptr>( event )
-				
-				_window=Window.WindowForID( mevent->windowID )
-				If Not _window Return
-				
-				_mouseLocation=New Vec2i( mevent->x,mevent->y )
-				
-				Local view:=ActiveViewAtMouseLocation()
-				If _mouseView And view<>_mouseView view=Null
-				
-				If view<>_hoverView
-				
-					If _hoverView SendMouseEvent( EventType.MouseLeave,_hoverView )
-					
-					_hoverView=view
-					
-					If _hoverView SendMouseEvent( EventType.MouseEnter,_hoverView )
-				Endif
-				
-				If _mouseView
-	
-					SendMouseEvent( EventType.MouseMove,_mouseView )
-					
-				Else If _hoverView
-	
-					SendMouseEvent( EventType.MouseMove,_hoverView )
-				
-				Endif
+			If _mouseView
+			
+				SendMouseEvent( EventType.MouseMove,_mouseView )
+			
+			Else If _hoverView
+
+				SendMouseEvent( EventType.MouseMove,_hoverView )
 			
 			Endif
-			#end
 
 		Case SDL_MOUSEWHEEL
 		
@@ -858,12 +865,27 @@ Class AppInstance
 '				_activeWindow=Null		'too dangerous for now!
 				_active=False
 			
+				If _mouseView And Not _captureMouse
+					SendMouseEvent( EventType.MouseUp,_mouseView )
+					_mouseView=Null
+				Endif
+
+				If _hoverView
+					SendMouseEvent( EventType.MouseLeave,_hoverView )
+					_hoverView=Null
+				Endif
+			
 				SendWindowEvent( EventType.WindowLostFocus )
 				
 				If active<>_active Deactivated()
 				
 			Case SDL_WINDOWEVENT_LEAVE
 			
+				If _mouseView And Not _captureMouse
+					SendMouseEvent( EventType.MouseUp,_mouseView )
+					_mouseView=Null
+				Endif
+			
 				If _hoverView
 					SendMouseEvent( EventType.MouseLeave,_hoverView )
 					_hoverView=Null
@@ -873,18 +895,11 @@ Class AppInstance
 			
 		Case SDL_USEREVENT
 		
-			Local t:=Cast<SDL_UserEvent Ptr>( event )
+			Local uevent:=Cast<SDL_UserEvent Ptr>( event )
 			
-			Local code:=t[0].code
-			Local id:=code & $3fffffff
+			Local event:=Cast<AsyncEvent Ptr>( uevent->data1 )
 			
-			If code & $40000000
-				Local func:=_asyncCallbacks[ id ]				'null if removed
-				If code & $80000000 RemoveAsyncCallback( id )
-				If Not _disabledCallbacks[id] func()
-			Else If code & $80000000
-				RemoveAsyncCallback( id )
-			Endif
+			event->Dispatch()
 
 		Case SDL_RENDER_TARGETS_RESET
 		
@@ -897,6 +912,30 @@ Class AppInstance
 			Print "SDL_RENDER_DEVICE_RESET"
 		
 			mojo.graphics.glutil.glGraphicsSeq+=1
+#rem
+
+		'Linux weirdness: These may or may not be necessary when I get mouse cpature working again.
+			
+		Case SDL_WINDOWEVENT_MOVED
+			
+			SendWindowEvent( EventType.WindowMoved )
+					
+		Case SDL_WINDOWEVENT_RESIZED
+		
+			SendWindowEvent( EventType.WindowResized )
+				
+			UpdateWindows()
+#end
+
+		Case SDL_DROPFILE
+		
+			Local devent:=Cast<SDL_DropEvent Ptr>( event )
+			
+			Local path:=String.FromCString( devent->file ).Replace( "\","/" )
+			
+			SDL_free( devent->file )
+			
+			FileDropped( path )
 
 		End
 			
@@ -939,24 +978,4 @@ Class AppInstance
 		Return 1
 	End
 	
-	Function AddAsyncCallback:Int( func:Void() )
-		_nextCallbackId+=1
-		Local id:=_nextCallbackId
-		_asyncCallbacks[id]=func
-		Return id
-	End
-	
-	Function RemoveAsyncCallback( id:Int )
-		_disabledCallbacks.Remove( id )
-		_asyncCallbacks.Remove( id )
-	End
-	
-	Function EnableAsyncCallback( id:Int )
-		_disabledCallbacks.Remove( id )
-	End
-	
-	Function DisableAsyncCallback( id:Int )
-		If _asyncCallbacks.Contains( id ) _disabledCallbacks[id]=True
-	End
-	
 End

+ 27 - 0
modules/mojo/app/native/app.cpp

@@ -0,0 +1,27 @@
+
+#include "app.h"
+
+#include "../../../std/async/native/async.h"
+
+#include <SDL.h>
+
+namespace bbApp{
+
+	void postEventFilter( bbAsync::Event *event ){
+
+		SDL_UserEvent uevent;
+		uevent.type=SDL_USEREVENT;
+		uevent.code=0;
+		uevent.data1=event;
+		uevent.data2=0;
+	
+		if( SDL_PeepEvents( (SDL_Event*)&uevent,1,SDL_ADDEVENT,SDL_FIRSTEVENT,SDL_LASTEVENT )!=1 ){
+			printf( "SDL_PeepEvents error!\n" );fflush( stdout );
+		}
+	}
+
+	void init(){
+
+		bbAsync::setPostEventFilter( postEventFilter );
+	}
+}

+ 10 - 0
modules/mojo/app/native/app.h

@@ -0,0 +1,10 @@
+
+#ifndef BB_MOJO_APP_H
+#define BB_MOJO_APP_H
+
+namespace bbApp{
+
+	void init();
+}
+
+#endif

+ 67 - 8
modules/mojo/app/native/async.cpp

@@ -1,8 +1,15 @@
 
 #include "async.h"
 
+#include "../../../std/async/native/async.h"
+
+#include "../../../std/fiber/native/fiber.h"
+
 #include <SDL.h>
 
+#include <thread>
+#include <chrono>
+
 bbInt g_mojo_app_AppInstance_AddAsyncCallback( bbFunction<void()> callback );
 
 namespace{
@@ -11,14 +18,14 @@ namespace{
 	const int REMOVE=0x80000000;
 
 	static void postEvent( int code ){
-			SDL_UserEvent event;
-			event.type=SDL_USEREVENT;
-			event.code=code;
-			event.data1=0;
-			event.data2=0;
-			if( SDL_PeepEvents( (SDL_Event*)&event,1,SDL_ADDEVENT,SDL_FIRSTEVENT,SDL_LASTEVENT )!=1 ){
-				printf(" SDL_PeepEvents error!\n" );fflush( stdout );
-			}
+		SDL_UserEvent event;
+		event.type=SDL_USEREVENT;
+		event.code=code;
+		event.data1=0;
+		event.data2=0;
+		if( SDL_PeepEvents( (SDL_Event*)&event,1,SDL_ADDEVENT,SDL_FIRSTEVENT,SDL_LASTEVENT )!=1 ){
+			printf(" SDL_PeepEvents error!\n" );fflush( stdout );
+		}
 	}
 }
 
@@ -42,3 +49,55 @@ void bbRemoveAsyncCallback( int callback ){
 	
 	postEvent( code );
 }
+
+void bbAppFiberSleep( int millis ){
+
+	int timeout=SDL_GetTicks()+millis;
+
+	struct Resumer : public bbFunction<void()>::Rep{
+		
+		int fiber;
+
+		Resumer():fiber( bbFiber::getCurrentFiber() ){
+		}
+			
+		void invoke(){
+			bbFiber::resumeFiber( fiber );
+		}
+	};
+		
+	bbFunction<void()> resumer( new Resumer );
+		
+	int resume=bbAddAsyncCallback( resumer );
+		
+	std::thread( [=](){
+	
+		int dur=timeout-SDL_GetTicks();
+		
+		if( dur>0 ) SDL_Delay( dur );
+			
+		bbInvokeAsyncCallback( resume,true );
+		
+	} ).detach();
+		
+	bbFiber::suspendCurrentFiber();
+}
+
+void bbAppPostEventFilter( bbAsync::Event *event ){
+
+	SDL_UserEvent uevent;
+	uevent.type=SDL_USEREVENT;
+	uevent.code=0;
+	uevent.data1=event;
+	uevent.data2=0;
+
+	if( SDL_PeepEvents( (SDL_Event*)&uevent,1,SDL_ADDEVENT,SDL_FIRSTEVENT,SDL_LASTEVENT )!=1 ){
+		printf( "SDL_PeepEvents error!\n" );fflush( stdout );
+	}
+}
+
+void bbAppSetPostEventFilter(){
+
+	bbAsync::setPostEventFilter( bbAppPostEventFilter );
+}
+

+ 4 - 0
modules/mojo/app/native/async.h

@@ -14,4 +14,8 @@ void bbInvokeAsyncCallback( int callback,bool remove );
 
 void bbRemoveAsyncCallback( int callback );
 
+void bbAppFiberSleep( int millis );
+
+void bbAppSetPostEventFilter();
+
 #endif

+ 68 - 39
modules/mojo/audio/audio.monkey2

@@ -66,33 +66,6 @@ Class AudioDevice
 	Field _alcContext:ALCcontext Ptr
 	Field _error:String
 	
-	Field _channels:=New Stack<Channel>
-
-	Method FlushTmpChannels()
-	
-		Local put:=0
-		For Local chan:=Eachin _channels
-		
-			If chan.Playing
-				_channels[put]=chan;put+=1
-				Continue
-			Endif
-			
-			chan.Discard()
-		Next
-		_channels.Resize( put )
-	End
-
-	Method AllocTmpChannel:Channel()
-	
-		FlushTmpChannels()
-		
-		Local channel:=New Channel()
-		_channels.Push( channel )
-		
-		Return channel
-	End
-	
 End
 
 #rem monkeydoc The Sound class.
@@ -121,7 +94,7 @@ Class Sound
 	#end
 	Method Play:Channel( loop:Bool=False )
 	
-		Local channel:=Audio.AllocTmpChannel()
+		Local channel:=New Channel( ChannelFlags.AutoDiscard )
 		
 		channel.Play( Self,loop )
 		
@@ -147,13 +120,42 @@ Class Sound
 
 End
 
+#rem monkeydoc ChannelFlags enum.
+
+| Flag			| Description
+|:--------------|:-----------
+| `AutoDiscard`	| Channel will be automatically discarded when it finishes playing, or when it is stopped using [[Channel.Stop]].
+
+#end
+Enum ChannelFlags
+	AutoDiscard=1
+End
+
 Class Channel
 
-	#rem monkeydoc Creates a new audio channel
+	#rem monkeydoc Creates a new audio channel.
+	
+	If `flags` is ChannelFlags.AutoDiscard, then the channel will be automatically discarded when it finishes playing, or when it is
+	stopped using [[Stop]].
+	
 	#end
-	Method New()
-		Audio.FlushTmpChannels()
+	Method New( flags:ChannelFlags=Null )
+	
+		_flags=flags
+	
+		FlushTmpChannels()
+		
 		alGenSources( 1,Varptr _alSource )
+		
+		If _flags & ChannelFlags.AutoDiscard _tmpChannels.Push( Self )
+		
+		_active+=1
+		Print "Active channels="+_active
+	End
+	
+	Property Flags:ChannelFlags()
+	
+		Return _flags
 	End
 	
 	#rem monkeydoc True if channel is playing audio.
@@ -235,6 +237,9 @@ Class Channel
 		
 		alDeleteSources( 1,Varptr _alSource )
 		_alSource=0
+		
+		_active-=1
+		Print "Active channels="+_active
 	End
 
 	#rem monkeydoc Play a sound through the channel.
@@ -314,21 +319,51 @@ Class Channel
 	#end
 	Method Stop()
 		If Not _alSource Return
+
 		alSourceStop( _alSource )
+		
+		If _flags & ChannelFlags.AutoDiscard Discard()
 	End
 
 	Private
 	
+	Field _flags:ChannelFlags
 	Field _alSource:ALuint
 	Field _volume:Float=1
 	Field _rate:Float=1
 	Field _pan:Float=0
 	
-	Field _tmpBuffers:Stack<ALuint>
-	Field _freeBuffers:Stack<ALuint>
+	Global _active:=0
+	
+	Global _tmpChannels:=New Stack<Channel>
+	
+	Method ALState:ALenum()
+		Local state:ALenum
+		alGetSourcei( _alSource,AL_SOURCE_STATE,Varptr state )
+		Return state
+	End
+	
+	Function FlushTmpChannels()
+	
+		Local put:=0
+		For Local chan:=Eachin _tmpChannels
+			If Not chan._alSource Continue
+		
+			If chan.ALState()<>AL_STOPPED
+				_tmpChannels[put]=chan;put+=1
+				Continue
+			Endif
+			
+			chan.Discard()
+		Next
+
+		_tmpChannels.Resize( put )
+	End
 	
 	#if __TARGET__<>"emscripten"
 	
+	Field _tmpBuffers:Stack<ALuint>
+	Field _freeBuffers:Stack<ALuint>
 	Field _future:Future<Int>
 	Field _waiting:Bool
 	Field _queued:Int
@@ -364,10 +399,4 @@ Class Channel
 	
 	#endif
 	
-	Method ALState:ALenum()
-		Local state:ALenum
-		alGetSourcei( _alSource,AL_SOURCE_STATE,Varptr state )
-		Return state
-	End
-	
 End

+ 0 - 2
modules/mojo/mojo.monkey2

@@ -39,8 +39,6 @@ Namespace mojo
 #Import "input/keycodes"
 
 #Import "requesters/requesters"
-#Import "process/process"
-#Import "timer/timer"
 #Import "audio/audio"
 
 Using emscripten..

+ 0 - 505
modules/mojo/process/native/process.cpp

@@ -1,505 +0,0 @@
-
-#include "process.h"
-
-#include "../../app/native/async.h"
-
-#ifndef EMSCRIPTEN
-
-#include <thread>
-#include <atomic>
-#include <mutex>
-#include <condition_variable>
-
-struct semaphore{
-
-	int count=0;
-	std::mutex mutex;
-	std::condition_variable cond_var;
-	
-	void wait(){
-		std::unique_lock<std::mutex> lock( mutex );
-		while( !count ) cond_var.wait( lock );
-		--count;
-	}
-	
-	void signal(){
-		std::unique_lock<std::mutex> lock( mutex );
-		++count;
-		cond_var.notify_one();
-	}
-};
-
-#if _WIN32
-
-#include <windows.h>
-#include <tlhelp32.h>
-
-extern "C" WINBASEAPI WINBOOL WINAPI CancelIoEx( HANDLE hFile,LPOVERLAPPED lpOverlapped );
-
-#else
-
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#endif
-
-namespace{
-
-#if _WIN32
-
-	void terminateChildren( DWORD procid,HANDLE snapshot,int exitCode ){
-	
-		PROCESSENTRY32 procinfo;
-			
-		procinfo.dwSize=sizeof( procinfo );
-		
-		int gotinfo=Process32First( snapshot,&procinfo );
-			
-		while( gotinfo ){
-		
-			if( procinfo.th32ParentProcessID==procid ){
-			
-//				printf("process=%i parent=%i module=%x path=%s\n",procinfo.th32ProcessID,procinfo.th32ParentProcessID,procinfo.th32ModuleID,procinfo.szExeFile);
-
-				terminateChildren( procinfo.th32ProcessID,snapshot,exitCode );
-				 
-				HANDLE child=OpenProcess( PROCESS_ALL_ACCESS,0,procinfo.th32ProcessID );
-				
-				if( child ){
-					int res=TerminateProcess( child,exitCode );
-					CloseHandle( child );
-				}
-			}
-			
-			gotinfo=Process32Next( snapshot,&procinfo );
-		}	
-	}
-	
-	int TerminateProcessGroup( HANDLE prochandle,int exitCode ){
-
-		HANDLE snapshot;
-		
-		int procid=GetProcessId( prochandle );
-		
-		snapshot=CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS,0 );
-		
-		if( snapshot!=INVALID_HANDLE_VALUE ){
-		
-			terminateChildren( GetProcessId( prochandle ),snapshot,exitCode );
-
-			CloseHandle( snapshot );
-		}
-			
-		int res=TerminateProcess( prochandle,exitCode );
-		return res;
-	}
-	
-#endif	
-
-#ifndef _WIN32
-
-	char **makeargv( const char *cmd ){
-	    int n,c;
-	    char *p;
-	    static char *args,**argv;
-	
-	    if( args ) free( args );
-	    if( argv ) free( argv );
-	    args=(char*)malloc( strlen(cmd)+1 );
-	    strcpy( args,cmd );
-	
-	    n=0;
-	    p=args;
-	    while( (c=*p++) ){
-	        if( c==' ' ){
-	            continue;
-	        }else if( c=='\"' ){
-	            while( *p && *p!='\"' ) ++p;
-	        }else{
-	            while( *p && *p!=' ' ) ++p;
-	        }
-	        if( *p ) ++p;
-	        ++n;
-	    }
-	    argv=(char**)malloc( (n+1)*sizeof(char*) );
-	    n=0;
-	    p=args;
-	    while( (c=*p++) ){
-	        if( c==' ' ){
-	            continue;
-	        }else if( c=='\"' ){
-	            argv[n]=p;
-	            while( *p && *p!='\"' ) ++p;
-	        }else{
-	            argv[n]=p-1;
-	            while( *p && *p!=' ' ) ++p;
-	        }
-	        if( *p ) *p++=0;
-	        ++n;
-	    }
-	    argv[n]=0;
-	    return argv;
-	}
-	
-#endif
-
-}
-
-struct bbProcess::Rep{
-
-	std::atomic_int refs;
-	
-	semaphore stdoutSema;
-	char stdoutBuf[4096];
-	char *stdoutGet;
-	int stdoutAvail=0;
-	bool terminated=false;
-	int exit;
-
-#if _WIN32
-
-	HANDLE proc;
-	HANDLE in;
-	HANDLE out;
-	HANDLE err;
-	HANDLE breakEvent;
-	
-	Rep( HANDLE proc,HANDLE in,HANDLE out,HANDLE err,HANDLE breakEvent ):proc( proc ),in( in ),out( out ),err( err ),breakEvent( breakEvent ),exit( -1 ),refs( 1 ){
-	}
-	
-	void close(){
-		CloseHandle( in );
-		CloseHandle( out );
-		CloseHandle( err );
-	}
-
-#else
-
-	int proc;
-	int in;
-	int out;
-	int err;
-
-	Rep( int proc,int in,int out,int err ):proc( proc ),in( in ),out( out ),err( err ),exit( -1 ),refs( 1 ){
-	}
-	
-	void close(){
-		::close( in );
-		::close( out );
-		::close( err );
-	}
-
-#endif
-	
-	void retain(){
-		++refs;
-	}
-	
-	void release(){
-		if( --refs ) return;
-		
-		close();
-		
-		delete this;
-	}
-};
-
-bbProcess::bbProcess():_rep( nullptr ){
-}
-
-bbProcess::~bbProcess(){
-
-	if( _rep ) _rep->release();
-}
-
-bbBool bbProcess::start( bbString cmd ){
-
-	if( _rep ) return false;
-	
-#if _WIN32
-
-	HANDLE in[2],out[2],err[2];
-	SECURITY_ATTRIBUTES sa={sizeof(sa),0,1};
-	CreatePipe( &in[0],&in[1],&sa,0 );
-	CreatePipe( &out[0],&out[1],&sa,0 );
-	CreatePipe( &err[0],&err[1],&sa,0 );
-	HANDLE breakEvent=CreateEvent( &sa,0,0,"MX2_BREAK_EVENT" );
-
-	STARTUPINFOA si={sizeof(si)};
-	si.dwFlags=STARTF_USESTDHANDLES;
-	si.hStdInput=in[0];
-	si.hStdOutput=out[1];
-	si.hStdError=err[1];
-
-	PROCESS_INFORMATION pi={0};
-    
-	DWORD flags=CREATE_NEW_PROCESS_GROUP|CREATE_NO_WINDOW;
-	
-	int res=CreateProcessA( 0,(LPSTR)cmd.c_str(),0,0,TRUE,flags,0,0,&si,&pi );
-
-	CloseHandle( in[0] );
-	CloseHandle( out[1] );
-	CloseHandle( err[1] );
-
-	if( !res ){
-		CloseHandle( in[1] );
-		CloseHandle( out[0] );
-		CloseHandle( err[0] );
-		return false;
-	}
-
-	CloseHandle( pi.hThread );
-	
-	Rep *rep=new Rep( pi.hProcess,in[1],out[0],err[0],breakEvent );
-    
-#else
-  
-	int in[2],out[2],err[2];
-
-	pipe( in );
-	pipe( out );
-	pipe( err );
-
-	char **argv=makeargv( bbCString( cmd ) );
-	
-	bool failed=false;
-
-	int proc=vfork();
-
-	if( !proc ){
-
-#if __linux
-		setsid();
-#else
-		setpgid(0,0);
-#endif
-
-		dup2( in[0],0 );
-		dup2( out[1],1 );
-		dup2( err[1],2 );
-
-		execvp( argv[0],argv );
-		
-		failed=true;
-
-		_exit( 127 );
-	}
-	
-	if( failed ) proc=-1;
-
-	close( in[0] );
-	close( out[1] );
-	close( err[1] );
-
-	if( proc==-1 ){
-		close( in[1] );
-		close( out[0] );
-		close( err[0] );
-		return false;
-	}
-  
-	Rep *rep=new Rep( proc,in[1],out[0],err[0] );
-	
-#endif
-
-	//Create finished thread    
-    rep->retain();
-
-    int callback=bbAddAsyncCallback( finished );
-    
-    std::thread( [=](){
-    
-		#if _WIN32
-		
-	    	WaitForSingleObject( rep->proc,INFINITE );
-	    	
-	    	GetExitCodeProcess( rep->proc,(DWORD*)&rep->exit );
-	    	
-	    	CloseHandle( rep->breakEvent );
-	    		
-	    	CloseHandle( rep->proc );
-	    	
-		#else
-		
-			int status;
-			waitpid( rep->proc,&status,0 );
-			
-			if( WIFEXITED( status ) ){
-				rep->exit=WEXITSTATUS( status );
-			}else{
-				rep->exit=-1;
-			}
-			
-		#endif
-		
-			bbInvokeAsyncCallback( callback,true );
-    		
-    		rep->release();
-
-	} ).detach();
-	
-	
-	//Create stdoutReady thread
-	rep->retain();
-	
-	int callback2=bbAddAsyncCallback( stdoutReady );
-	
-	std::thread( [=](){
-	
-		for(;;){
-		
-#if _WIN32		
-			DWORD n=0;
-			if( !ReadFile( rep->out,rep->stdoutBuf,4096,&n,0 ) ) break;
-			if( n<=0 ) break;
-#else
-			int n=read( rep->out,rep->stdoutBuf,4096 );
-			if( n<=0 ) break;
-#endif
-			rep->stdoutGet=rep->stdoutBuf;
-			
-			rep->stdoutAvail=n;
-
-			bbInvokeAsyncCallback( callback2,false );			
-			
-			rep->stdoutSema.wait();
-			
-			if( rep->stdoutAvail ) break;
-		}
-		
-		rep->stdoutAvail=0;
-		
-		bbInvokeAsyncCallback( callback2,true );
-		
-		rep->release();
-
-	} ).detach();
-	
-	_rep=rep;
-    
-    return true;
-}
-
-int bbProcess::exitCode(){
-
-	if( !_rep ) return -1;
-
-	return _rep->exit;
-}
-
-bbInt bbProcess::stdoutAvail(){
-
-	if( !_rep ) return 0;
-
-	return _rep->stdoutAvail;
-}
-
-bbString bbProcess::readStdout(){
-
-	if( !_rep || !_rep->stdoutAvail ) return "";
-
-	bbString str=bbString::fromCString( _rep->stdoutGet,_rep->stdoutAvail );
-	
-	_rep->stdoutAvail=0;
-	
-	_rep->stdoutSema.signal();
-	
-	return str;
-}
-
-bbInt bbProcess::readStdout( void *buf,int count ){
-
-	if( !_rep || count<=0 || !_rep->stdoutAvail ) return 0;
-
-	if( count>_rep->stdoutAvail ) count=_rep->stdoutAvail;
-	
-	memcpy( buf,_rep->stdoutGet,count );
-	
-	_rep->stdoutGet+=count;
-
-	_rep->stdoutAvail-=count;
-	
-	if( !_rep->stdoutAvail ) _rep->stdoutSema.signal();
-	
-	return count;
-}
-
-void bbProcess::writeStdin( bbString str ){
-
-	if( !_rep ) return;
-
-#if _WIN32	
-	WriteFile( _rep->in,str.c_str(),str.length(),0,0 );
-#else
-	write( _rep->in,str.c_str(),str.length() );
-#endif
-}
-
-void bbProcess::sendBreak(){
-
-	if( !_rep ) return;
-	
-#if _WIN32
-	SetEvent( _rep->breakEvent );
-#else
-	killpg( _rep->proc,SIGTSTP );
-#endif
-}
-
-void bbProcess::terminate(){
-
-	if( !_rep ) return;
-
-#if _WIN32
-
-	TerminateProcessGroup( _rep->proc,-1 );
-	
-	CancelIoEx( _rep->out,0 );
-
-#else
-	killpg( _rep->proc,SIGTERM );
-#endif
-}
-
-#else
-
-//***** Dummy emscripten version *****
-
-struct bbProcess::Rep{
-};
-
-void bbProcess::discard(){
-}
-
-bbBool bbProcess::start( bbString cmd ){
-	return false;
-}
-	
-bbInt bbProcess::exitCode(){
-	return -1;
-}
-	
-bbInt bbProcess::stdoutAvail(){
-	return 0;
-}
-	
-bbString bbProcess::readStdout(){
-	return "";
-}
-
-bbInt bbProcess::readStdout( void *buf,bbInt count ){
-	return 0;
-}
-
-void bbProcess::writeStdin( bbString str ){
-}
-
-void bbProcess::sendBreak(){
-}
-
-void bbProcess::terminate(){
-}
-
-#endif

+ 0 - 40
modules/mojo/process/native/process.h

@@ -1,40 +0,0 @@
-
-#ifndef BB_STD_PROCESS_H
-#define BB_STD_PROCESS_H
-
-#include <bbmonkey.h>
-
-class bbProcess : public bbObject{
-public:
-
-	bbProcess();
-	~bbProcess();
-	
-	void discard();
-	
-	bbFunction<void()> finished;
-	bbFunction<void()> stdoutReady;
-	
-	bbBool start( bbString cmd );
-	
-	bbInt exitCode();
-	
-	bbInt stdoutAvail();
-	
-	bbString readStdout();
-	
-	bbInt readStdout( void *buf,bbInt count );
-	
-	void writeStdin( bbString str );
-	
-	void sendBreak();
-	
-	void terminate();
-	
-private:
-	struct Rep;
-	
-	Rep *_rep;
-};
-
-#endif

+ 0 - 38
modules/mojo/process/process.monkey2

@@ -1,38 +0,0 @@
-
-#Import "native/process.h"
-#Import "native/process.cpp"
-
-Namespace mojo.process
-
-Extern
-
-Class Process="bbProcess"
-
-	Field Finished:Void()="finished"
-	
-	Field StdoutReady:Void()="stdoutReady"
-	
-	Field StderrReady:Void()="stderrReady"
-
-	Property ExitCode:Int()="exitCode"
-	
-	Property StdoutAvail:Int()="stdoutAvail"
-
-	Property StderrAvail:Int()="stderrAvail"
-	
-	Method Start:Bool( cmd:String )="start"
-	
-	Method ReadStdout:String()="readStdout"
-	
-	Method ReadStdout:Int( buf:Void Ptr,count:Int )="readStdout"
-
-	Method ReadStderr:String()="readStderr"
-	
-	Method ReadStderr:Int( buf:Void Ptr,count:Int )="readStderr"
-
-	Method WriteStdin( str:String )="writeStdin"
-	
-	Method SendBreak()="sendBreak"
-	
-	Method Terminate:Void()="terminate"	
-End

+ 1 - 3
modules/mojo/requesters/native/requesters.cpp

@@ -204,9 +204,7 @@ void bbRequesters::OpenUrl( bbString url ){
 
 bbString bbRequesters::RequestFile( bbString title,bbString exts,bbBool save,bbString path ){
 
-//	unsetenv( "WINDOWID" );
-
-	bbString cmd=BB_T("zenity --title=\"")+title+BB_T("\" --file-selection");	// --modal");
+	bbString cmd=BB_T("zenity --title=\"")+title+BB_T("\" --file-selection");
 	
 	if( save ) cmd+=" --save";
 	

+ 0 - 132
modules/mojo/timer/native/timer.cpp

@@ -1,132 +0,0 @@
-
-#include "timer.h"
-
-#include <SDL.h>
-
-bbInt	g_mojo_app_AppInstance_AddAsyncCallback(bbFunction<void()> l_func);
-void	g_mojo_app_AppInstance_RemoveAsyncCallback( bbInt id );
-void	g_mojo_app_AppInstance_EnableAsyncCallback( bbInt id );
-void	g_mojo_app_AppInstance_DisableAsyncCallback( bbInt id );
-
-struct bbTimer::Rep{
-
-	int _freq;
-	int	_interval;
-	int _remainder;
-	int _accumulator;
-
-	bool _suspended;
-	bool _cancelled;
-	bool _reset;
-	
-	int _callback;
-	int _timer;
-};
-
-namespace{
-
-	const int INVOKE=0x40000000;
-	const int REMOVE=0x80000000;
-
-	void postEvent( int code ){
-		SDL_UserEvent event;
-		event.type=SDL_USEREVENT;
-		event.code=code;
-		event.data1=0;
-		event.data2=0;
-		
-		if( SDL_PeepEvents( (SDL_Event*)&event,1,SDL_ADDEVENT,SDL_FIRSTEVENT,SDL_LASTEVENT )!=1 ){
-			printf(" SDL_PeepEvents error!\n" );fflush( stdout );
-		}
-	}
-}
-
-bbTimer::bbTimer( int freq,bbFunction<void()> fired ){
-
-	int p=1000/freq;
-
-	_rep=new Rep;
-
-	_rep->_freq=freq;
-	_rep->_interval=p;
-	_rep->_remainder=1000-p*freq;
-	_rep->_accumulator=0;
-	_rep->_suspended=true;
-	_rep->_cancelled=false;
-	_rep->_reset=false;
-	
-	_rep->_callback=g_mojo_app_AppInstance_AddAsyncCallback( fired );
-	
-	setSuspended( false );
-}
-
-bool bbTimer::suspended(){
-	if( !_rep ) return false;
-	
-	return _rep->_suspended;
-}
-
-void bbTimer::setSuspended( bool suspended ){
-	if( !_rep ) return;
-	
-	if( suspended==_rep->_suspended ) return;
-	
-	if( _rep->_suspended=suspended ){
-	
-		SDL_RemoveTimer( _rep->_timer );
-	
-		g_mojo_app_AppInstance_DisableAsyncCallback( _rep->_callback );
-
-	}else{
-
-		g_mojo_app_AppInstance_EnableAsyncCallback( _rep->_callback );
-	
-		_rep->_timer=SDL_AddTimer( _rep->_interval,sdl_timer_callback,(void*)_rep );
-
-	}
-}
-
-void bbTimer::reset(){
-	if( !_rep ) return;
-	
-	_rep->_reset=true;
-}
-
-void bbTimer::cancel(){
-	if( !_rep ) return;
-
-	g_mojo_app_AppInstance_RemoveAsyncCallback( _rep->_callback );
-
-	_rep->_suspended=true;
-	_rep->_cancelled=true;
-	
-	_rep=nullptr;
-}
-
-unsigned bbTimer::sdl_timer_callback( unsigned interval,void *param ){
-	
-	bbTimer::Rep *rep=(bbTimer::Rep*)param;
-	
-	if( rep->_suspended ){
-		if( rep->_cancelled ) delete rep;
-		return 0;
-	}
-	
-	/*
-	if( rep->_reset ){
-		rep->_reset=false;
-		rep->_accumulator=0;
-		return SDL_GetTicks()+interval;
-	}
-	*/
-	
-	postEvent( rep->_callback|INVOKE );
-	
-	rep->_accumulator+=rep->_remainder;
-	if( rep->_accumulator>=rep->_freq ){
-		rep->_accumulator-=rep->_freq;
-		return rep->_interval+1;
-	}
-	
-	return rep->_interval;
-}

+ 0 - 28
modules/mojo/timer/native/timer.h

@@ -1,28 +0,0 @@
-
-#ifndef BB_TIMER_H
-#define BB_TIMER_H
-
-#include <bbmonkey.h>
-
-class bbTimer : public bbObject{
-public:
-
-	bbTimer( int freq,bbFunction<void()> fired );
-	
-	bool suspended();
-	
-	void setSuspended( bool suspended );
-	
-	void reset();
-	
-	void cancel();
-	
-private:
-	
-	struct Rep;
-	Rep *_rep;
-	
-	static unsigned sdl_timer_callback( unsigned interval,void *param );
-};
-
-#endif

+ 0 - 27
modules/mojo/timer/timer.monkey2

@@ -1,27 +0,0 @@
-
-Namespace mojo.timer
-
-#Import "native/timer.cpp"
-#Import "native/timer.h"
-
-Extern
-
-Class Timer="bbTimer"
-
-	#rem monkeydoc Creates a new timer.
-	#end
-	Method New( ticksPerSecond:Int,fired:Void() )
-
-	#rem monkeydoc @hidden Suspended state.
-	#end
-	Property Suspended:Bool()="suspended"
-	Setter( suspended:Bool )="setSuspended"
-
-	#rem monkeydoc Cancels the timer.
-
-	Once cancelled, a timer can no longer be used.
-	
-	#end
-	Method Cancel()="cancel"
-
-End