Mark Sibly 9 anni fa
parent
commit
80abb862d9

+ 24 - 0
modules/hoedown/hoedown.monkey2

@@ -110,3 +110,27 @@ Function hoedown_document_render( doc:hoedown_document Ptr,ob:hoedown_buffer Ptr
 Function hoedown_document_render_inline( doc:hoedown_document Ptr,ob:hoedown_buffer Ptr,data:Utf8String,size:Int )
 
 Function hoedown_document_free( doc:hoedown_document Ptr )
+
+Public
+
+Function MarkdownToHtml:String( markdown:String )
+
+	Local ob:=hoedown_buffer_new( 4096 )
+	
+	Local r:=hoedown_html_renderer_new( HOEDOWN_HTML_NONE,10 )
+	
+	Local doc:=hoedown_document_new( r,HOEDOWN_EXT_TABLES|HOEDOWN_EXT_FENCED_CODE,10 )
+		
+	hoedown_document_render( doc,ob,markdown,markdown.Utf8Length )
+	
+	Local html:=String.FromCString( hoedown_buffer_cstr( ob ) )
+	
+	hoedown_document_free( doc )
+	
+	hoedown_html_renderer_free( r )
+	
+	hoedown_buffer_free( ob )
+	
+	Return html
+
+End

+ 95 - 50
modules/mojo/app/app.monkey2

@@ -42,6 +42,8 @@ Class AppInstance
 		App=Self
 	
 		SDL_Init( SDL_INIT_EVERYTHING )
+		
+		_sdlThread=SDL_ThreadID()
 
 #If __TARGET__<>"emscripten"
 
@@ -54,8 +56,6 @@ Class AppInstance
 		SDL_GL_SetAttribute( SDL_GL_SHARE_WITH_CURRENT_CONTEXT,1 )
 		
 #Endif
-		_keyMatrix=SDL_GetKeyboardState( Varptr _numKeys )
-		
 		_defaultFont=Font.Open( DefaultFontName,16 )
 		
 		_defaultMonoFont=Font.Open( DefaultMonoFontName,16 )
@@ -166,13 +166,11 @@ Class AppInstance
 		Return New Vec2i( 1280,960 )
 
 #Else
-	
 		Local dm:SDL_DisplayMode
 		
 		If SDL_GetDesktopDisplayMode( 0,Varptr dm ) Return New Vec2i
 		
 		Return New Vec2i( dm.w,dm.h )
-		
 #Endif
 
 	End
@@ -187,43 +185,31 @@ Class AppInstance
 		Return Window.VisibleWindows()[0]
 	End
 	
-	#rem monkeydoc Gets state of a key.
+	#rem monkeydoc Approximate frames per second rendering rate.
 	#end
-	Method KeyDown:Bool( key:Key )
-	
-		Local n:=Int( key )
-		If n>=0 And n<_numKeys Return _keyMatrix[n]
-		Return False
-	End
-	
-	#rem monkeydoc Mouse location relative to the active window.
-	
-	@see [[ActiveWindow]], [[MouseX]], [[MouseY]]
-	
-	#end	
-	Property MouseLocation:Vec2i()
+	Property FPS:Float()
 
-		Return _mouseLocation
+		Return _fps
 	End
 	
-	#rem monkeydoc X coordinate of mouse location.
+	#rem monkeydoc Number of milliseconds app has been running.
 	
-	@see [[MouseLocation]]
+	This property uses the high precision system timer if possible.
 	
 	#end
-	Property MouseX:Int()
+	Property Millisecs:Int()
 	
-		Return _mouseLocation.x
+		Return SDL_GetTicks()
 	End
 	
-	#rem monkeydoc Y coordinate of mouse location.
-
-	@see [[MouseLocation]]
+	#rem monkeydoc Mouse location relative to the active window.
 	
-	#end
-	Property MouseY:Int()
+	@see [[ActiveWindow]], [[MouseX]], [[MouseY]]
 	
-		Return _mouseLocation.y
+	#end	
+	Property MouseLocation:Vec2i()
+
+		Return _mouseLocation
 	End
 	
 	#rem monkeydoc Terminate the app.
@@ -245,7 +231,7 @@ Class AppInstance
 	Method MainLoop()
 	
 		If Not _requestRender 
-		
+
 			SDL_WaitEvent( Null )
 			
 		Endif
@@ -255,6 +241,8 @@ Class AppInstance
 		If Not _requestRender Return
 		
 		_requestRender=False
+		
+		UpdateFPS()
 			
 		For Local window:=Eachin Window.VisibleWindows()
 			window.Render()
@@ -264,7 +252,7 @@ Class AppInstance
 	
 	Function EmscriptenMainLoop()
 	
-		App._requestRender=True
+'		App._requestRender=True
 		
 		App.MainLoop()
 	End
@@ -274,6 +262,7 @@ Class AppInstance
 	Method Run()
 	
 		SDL_AddEventWatch( _EventFilter,Null )
+'		SDL_SetEventFilter( _EventFilter,Null )
 		
 		RequestRender()
 		
@@ -293,6 +282,7 @@ Class AppInstance
 
 	Private
 	
+	Field _sdlThread:SDL_threadID
 	Field _glWindow:SDL_Window Ptr
 	Field _glContext:SDL_GLContext
 
@@ -304,8 +294,9 @@ Class AppInstance
 	Field _hoverView:View
 	Field _mouseView:View
 	
-	Field _numKeys:Int
-	Field _keyMatrix:UByte Ptr
+	Field _fps:Float
+	Field _fpsFrames:Int
+	Field _fpsMillis:Int
 	
 	Field _window:Window
 	Field _key:Key
@@ -320,13 +311,28 @@ Class AppInstance
 	
 	Global _nextCallbackId:Int
 	Global _asyncCallbacks:=New IntMap<Void()>
+	Global _disabledCallbacks:=New IntMap<Bool>
+	
+	Method UpdateFPS()
+	
+		_fpsFrames+=1
+			
+		Local elapsed:=App.Millisecs-_fpsMillis
+		
+		If elapsed>=250
+			_fps=Round( _fpsFrames/(elapsed/1000.0) )
+			_fpsMillis+=elapsed
+			_fpsFrames=0
+		Endif
+
+	End
 	
 	Method UpdateEvents()
 	
 		Local event:SDL_Event
 
 		_polling=True
-			
+		
 		While SDL_PollEvent( Varptr event )
 		
 			DispatchEvent( Varptr event )
@@ -350,7 +356,7 @@ Class AppInstance
 	
 		Local view:=KeyView
 		If view And Not view.ReallyEnabled view=Null
-	
+		
 		Local event:=New KeyEvent( type,view,_key,_scanCode,_modifiers,_keyText )
 		
 		KeyEventFilter( event )
@@ -379,15 +385,24 @@ Class AppInstance
 	
 	Method SendWindowEvent( type:EventType,window:Window )
 	
-		Local shape:Recti
+		Local event:=New WindowEvent( type,window )
 		
+		window.SendWindowEvent( event )
+	End
+	
+	Method ValidateWindowShape( window:Window )
+
 		Local x:Int,y:Int,w:Int,h:Int
 		SDL_GetWindowPosition( window.NativeWindow,Varptr x,Varptr y )
 		SDL_GetWindowSize( window.NativeWindow,Varptr w,Varptr h )
 		
-		Local event:=New WindowEvent( type,window,New Recti( x,y,x+w,y+h ) )
+		Local frame:=window.Frame
 		
-		window.SendWindowEvent( event )
+		window.Frame=New Recti( x,y,x+w,y+h )
+		
+		If x<>frame.X Or y<>frame.Y SendWindowEvent( EventType.WindowMoved,window )
+		
+		If w<>frame.Width Or h<>frame.Height SendWindowEvent( EventType.WindowResized,window )
 	End
 	
 	Method DispatchEvent( event:SDL_Event Ptr )
@@ -526,12 +541,19 @@ Class AppInstance
 			
 			Case SDL_WINDOWEVENT_MOVED
 			
-				SendWindowEvent( EventType.WindowMoved,window )
+'				ValidateWindowShape( window )
 
-'			Case SDL_WINDOWEVENT_RESIZED,
-			Case SDL_WINDOWEVENT_SIZE_CHANGED
+			Case SDL_WINDOWEVENT_RESIZED
+			
+'				ValidateWindowShape( window )
+				
+			Case SDL_WINDOWEVENT_FOCUS_GAINED
+			
+				SendWindowEvent( EventType.WindowGainedFocus,window )
+			
+			Case SDL_WINDOWEVENT_FOCUS_LOST
 			
-				SendWindowEvent( EventType.WindowResized,window )
+				SendWindowEvent( EventType.WindowLostFocus,window )
 				
 			Case SDL_WINDOWEVENT_LEAVE
 			
@@ -550,11 +572,11 @@ Class AppInstance
 			Local id:=code & $3fffffff
 			
 			If code & $40000000
-				Local func:=_asyncCallbacks[id]
-				If code & $80000000 _asyncCallbacks.Remove( id )
-				func()
+				Local func:=_asyncCallbacks[ id ]				'null if removed
+				If code & $80000000 RemoveAsyncCallback( id )
+				If Not _disabledCallbacks[id] func()
 			Else If code & $80000000
-				_asyncCallbacks.Remove( id )
+				RemoveAsyncCallback( id )
 			Endif
 
 		End
@@ -568,8 +590,13 @@ Class AppInstance
 	
 	Method EventFilter:Int( userData:Void Ptr,event:SDL_Event Ptr )
 	
-'		If _polling Return 1
-	
+		#rem
+		If SDL_ThreadID()<>_sdlThread 
+			Print "Yikes! EventFilter running in non-main thread..."
+			Return 1
+		Endif
+		#end
+			
 		Select event[0].type
 		Case SDL_WINDOWEVENT
 
@@ -577,10 +604,16 @@ Class AppInstance
 			Local window:=Window.WindowForID( wevent->windowID )
 			
 			Select wevent->event
+			
+			Case SDL_WINDOWEVENT_MOVED
+			
+				ValidateWindowShape( window )
+				
+				Return 0
 					
 			Case SDL_WINDOWEVENT_RESIZED
 			
-				SendWindowEvent( EventType.WindowResized,window )
+				ValidateWindowShape( window )
 				
 				If _requestRender
 				
@@ -608,5 +641,17 @@ Class AppInstance
 		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
-

+ 12 - 8
modules/mojo/app/event.monkey2

@@ -17,6 +17,8 @@ Namespace mojo.app
 | WindowClose		| Window close clicked event.
 | WindowMoved		| Window moved event.
 | WindowResized		| Window resized event.
+| WindowGainedFocus	| Window gained input focus.
+| WindowLostFocus	| Window lost input focus.
 
 #end
 Enum EventType
@@ -35,6 +37,8 @@ Enum EventType
 	WindowClose,
 	WindowMoved,
 	WindowResized,
+	WindowGainedFocus,
+	WindowLostFocus,
 	
 	Eaten=$80000000
 End
@@ -186,19 +190,19 @@ Class WindowEvent Extends Event
 
 	#rem monkeydoc @hidden
 	#end
-	Method New( type:EventType,view:View,rect:Recti )
-		Super.New( type,view )
-		_rect=rect
+	Method New( type:EventType,window:Window )
+		Super.New( type,window )
+		_window=window
 	End
-	
-	#rem monkeydoc The window rect for [[EventType.WindowMoved]] and [[EventType.WindowResized]] events.
+
+	#rem monkeydoc The window the event was sent to.
 	#end
-	Property Rect:Recti()
-		Return _rect
+	Property Window:Window()
+		Return _window
 	End
 	
 	Private
 	
-	Field _rect:Recti
+	Field _window:Window
 	
 End

+ 0 - 199
modules/mojo/app/keycodes.monkey2

@@ -1,199 +0,0 @@
-
-Namespace mojo.app
-
-'These are actually SDL 'scan codes', ie: what's written on US keyboard keys...
-'
-#rem monkeydoc Key codes.
-
-| Key
-|:---
-| A
-| B
-| C
-| D
-| E
-| F
-| G
-| H
-| I
-| J 
-| K
-| L
-| M
-| N
-| O
-| P
-| Q
-| R
-| S
-| T
-| U
-| V
-| W
-| X
-| Y
-| Z
-| Key0
-| Key1
-| Key2
-| Key3
-| Key4
-| Key5
-| Key6
-| Key7
-| Key8
-| Key9
-| Enter
-| Escape
-| Backspace
-| Tab
-| Space
-| Minus
-| Equals
-| LeftBracket
-| RightBracket
-| Backslash
-| Semicolon
-| Apostrophe
-| Grave
-| Comma
-| Period
-| Slash
-| CapsLock
-| F1
-| F2
-| F3
-| F4
-| F5
-| F6
-| F7
-| F8
-| F9
-| F10
-| F11
-| F12
-| PrintScreem
-| ScrollLock
-| Pause
-| Insert
-| Home
-| PageUp
-| KeyDelete
-| KeyEnd
-| PageDown
-| Right
-| Left
-| Down
-| Up
-| LeftControl
-| LeftShift
-| LeftAlt
-| LeftGui
-| RightControl
-| RightShift
-| RightAlt
-| RightGui
-
-#end
-Enum Key
-
-	None=0
-
-	A=4,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
-	
-	Key1=30,Key2,Key3,Key4,Key5,Key6,Key7,Key8,Key9,Key0
-	
-	Enter=40,Escape,Backspace,Tab,Space
-	
-	Minus=45,Equals,LeftBracket,RightBracket,Blackslash
-	
-	Semicolon=51,Apostrophe,Grave,Comma,Period,Slash
-	
-	CapsLock=57
-	
-	F1=58,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12
-	
-	PrintScreen=70,ScrollLock,Pause,Insert
-	
-	Home=74,PageUp,KeyDelete,KeyEnd,PageDown,Right,Left,Down,Up
-
-	LeftControl=224,LeftShift,LeftAlt,LeftGui
-	
-	RightControl=228,RightShift,RightAlt,RightGui
-
-End
-
-#rem monkeydoc @hidden
-#end
-Enum ScanCode
-End
-
-#rem monkeydoc Modifiers.
-
-| Modifier 		| Description 
-|:--------------|:-----------
-| LeftShift		| Left shift key.
-| RightShift	| Right shift key.
-| LeftControl	| Left control key.
-| RightControl	| Right control key.
-| LeftAlt		| Left alt key.
-| RightAlt		| Right alt key.
-| LeftGui		| Left gui key.
-| RightGui		| Right gui key.
-| NumLock		| Num lock key.
-| CapsLock		| Caps lock key.
-| Shift			| LeftShit | RightShift mask.
-| Control		| LeftControl | RightControl mask.
-| Alt			| LeftAlt | RightAlt mask.
-| Gui			| LeftGui | RightGui mask.
-
-#end
-Enum Modifier
-
-	None=			$0000
-	LeftShift=		$0001
-	RightShift=		$0002
-	LeftControl=	$0040
-	RightControl=	$0080
-	LeftAlt=		$0100
-	RightAlt=		$0200
-	LeftGui=		$0400
-	RightGui=		$0800
-	NumLock=		$1000
-	CapsLock=		$2000
-	
-	Shift=			LeftShift|RightShift
-	Control=		LeftControl|RightControl
-	Alt=			LeftAlt|RightAlt
-	Gui=			LeftGui|RightGui
-End
-
-#rem monkeydoc Mouse buttons.
-
-| MouseButton	| Description
-|:--------------|------------
-| Left			| Left mouse button.
-| Middle		| Middle mouse button.
-| Right			| Right mouse button.
-
-#end
-Enum MouseButton
-	None=0
-	Left=1
-	Middle=2
-	Right=3
-	X1=4
-	X2=5
-End
-
-#rem monkeydoc Gets the name of a key.
-#end
-Function KeyName:String( key:Key )
-	Local ikey:=Int( key )
-
-	If ikey>=Int( Key.A ) And ikey<=Int( Key.Z ) Return String.FromChar( ikey-Int( Key.A )+65 )
-
-	If ikey>=Int( Key.F1 ) And ikey<=Int( Key.F12 ) Return "F"+( ikey-Int( Key.F1 )+1 )
-	
-	Return "?"
-End

+ 0 - 512
modules/mojo/app/native/process.cpp

@@ -1,512 +0,0 @@
-
-#include "process.h"
-
-#ifndef EMSCRIPTEN
-
-#include <thread>
-#include <atomic>
-#include <mutex>
-#include <condition_variable>
-
-#include <SDL.h>
-
-bbInt g_mojo_app_AppInstance_AddAsyncCallback(bbFunction<void()> l_func);
-
-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>
-
-#else
-
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#endif
-
-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 );
-		}
-	}
-	
-#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;
-	
-	Rep( HANDLE proc,HANDLE in,HANDLE out,HANDLE err ):proc( proc ),in( in ),out( out ),err( err ),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 );
-
-	STARTUPINFOA si={sizeof(si)};
-	si.dwFlags=STARTF_USESTDHANDLES;//|STARTF_USESHOWWINDOW;
-	si.hStdInput=in[0];
-	si.hStdOutput=out[1];
-	si.hStdError=err[1];
-//	si.wShowWindow=SW_HIDE;
-
-	PROCESS_INFORMATION pi={0};
-    
-	DWORD flags=CREATE_NEW_PROCESS_GROUP;
-    
-	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] );
-    
-#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=g_mojo_app_AppInstance_AddAsyncCallback( finished );
-    
-    std::thread( [=](){
-    
-		#if _WIN32
-		
-	    	WaitForSingleObject( rep->proc,INFINITE );
-	    	
-	    	GetExitCodeProcess( rep->proc,(DWORD*)&rep->exit );
-	    		
-	    	CloseHandle( rep->proc );
-	    	
-		#else
-		
-			int status;
-			waitpid( rep->proc,&status,0 );
-			
-			if( WIFEXITED( status ) ){
-				rep->exit=WEXITSTATUS( status );
-			}else{
-				rep->exit=-1;
-			}
-			
-		#endif
-    		
-	    	postEvent( callback|INVOKE|REMOVE );
-    		
-    		rep->release();
-
-	} ).detach();
-	
-	
-	//Create stdoutReady thread
-	rep->retain();
-	
-	int callback2=g_mojo_app_AppInstance_AddAsyncCallback( 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;
-			
-			postEvent( callback2|INVOKE );
-			
-			rep->stdoutSema.wait();
-			
-			if( rep->stdoutAvail ) break;
-		}
-		
-		rep->stdoutAvail=0;
-		
-		postEvent( callback2|INVOKE|REMOVE );
-		
-		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
-	GenerateConsoleCtrlEvent( CTRL_BREAK_EVENT,GetProcessId( _rep->proc ) );
-#else
-	killpg( _rep->proc,SIGTSTP );
-#endif
-}
-
-void bbProcess::terminate(){
-
-	if( !_rep ) return;
-
-#if _WIN32
-	TerminateProcessGroup( _rep->proc,-1 );
-#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/app/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/app/process.monkey2

@@ -1,38 +0,0 @@
-
-Namespace mojo.app
-
-#Import "native/process.h"
-#Import "native/process.cpp"
-
-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

+ 7 - 0
modules/mojo/app/view.monkey2

@@ -220,6 +220,13 @@ Class View
 		Return _bounds
 	End
 	
+	#rem monkeydoc Mouse location relative to the view.
+	#end
+	Property MouseLocation:Vec2i()
+
+		Return TransformPointFromView( App.MouseLocation,Null )
+	End
+	
 	#rem monkeydoc View clip rect.
 	
 	The clip rect represents the part of the content rect NOT obscured by an parent views.

+ 25 - 32
modules/mojo/app/window.monkey2

@@ -25,18 +25,6 @@ End
 
 Class Window Extends View
 
-	#rem monkeydoc @hidden
-	#end
-	Field WindowClose:Void()
-	
-	#rem monkeydoc @hidden
-	#end
-	Field WindowMoved:Void()
-	
-	#rem monkeydoc @hidden
-	#end
-	Field WindowResized:Void()
-	
 	Method New()
 		Init( "Window",New Recti( 0,0,640,480 ),WindowFlags.Center )
 	End
@@ -80,7 +68,10 @@ Class Window Extends View
 #If __TARGET__="emscripten"
 		Local w:Int,h:Int,fs:Int
 		emscripten_get_canvas_size( Varptr w,Varptr h,Varptr fs )
-		If w<>Frame.Width Or h<>Frame.Height Frame=New Recti( 0,0,w,h )
+		If w<>Frame.Width Or h<>Frame.Height
+			Frame=New Recti( 0,0,w,h )
+		Endif
+		
 #Endif
 
 		'ugly...fixme.
@@ -88,10 +79,12 @@ Class Window Extends View
 			_minSize=MinSize
 			_maxSize=MaxSize
 			_frame=Frame
+#If __TARGET__<>"emscripten"
 			SDL_SetWindowMinimumSize( _sdlWindow,_minSize.x,_minSize.y )
 			SDL_SetWindowMinimumSize( _sdlWindow,_maxSize.x,_maxSize.y )
 			SDL_SetWindowPosition( _sdlWindow,_frame.X,_frame.Y )
 			SDL_SetWindowSize( _sdlWindow,_frame.Width,_frame.Height )
+#Endif
 		Endif
 		
 		Measure()
@@ -113,8 +106,6 @@ Class Window Extends View
 		
 		_canvas.Resize( viewport.Size )
 		
-'		_canvas.BeginRender()
-		
 		_canvas.RenderColor=Color.White
 		_canvas.RenderMatrix=New AffineMat3f
 		_canvas.RenderBounds=viewport
@@ -135,8 +126,6 @@ Class Window Extends View
 
 		_canvas.Flush()
 		
-'		_canvas.EndRender()
-		
 		SDL_GL_SwapWindow( _sdlWindow )
 	End
 	
@@ -213,15 +202,19 @@ Class Window Extends View
 	
 		Select event.Type
 		Case EventType.WindowClose
-			WindowClose()
+		
+			App.Terminate()
+			
 		Case EventType.WindowMoved
-			Frame=event.Rect
-			WindowMoved()
+		
 		Case EventType.WindowResized
-			Frame=event.Rect
-'			Frame=New Recti( 0,0,event.Rect.Size )
+		
 			App.RequestRender()
-			WindowResized()
+			
+		Case EventType.WindowGainedFocus
+		
+		Case EventType.WindowLostFocus
+		
 		End
 		
 	End
@@ -266,6 +259,14 @@ Class Window Extends View
 		If Not (flags & WindowFlags.Hidden) _visibleWindows.Push( Self )
 		_windowsByID[SDL_GetWindowID( _sdlWindow )]=Self
 		
+		'Create GLContext and canvas
+		
+		_sdlGLContext=SDL_GL_CreateContext( _sdlWindow )
+		
+		SDL_GL_MakeCurrent( _sdlWindow,_sdlGLContext )
+		
+		_canvas=New Canvas( rect.Width,rect.Height )
+		
 		Local tx:Int,ty:Int,tw:Int,th:Int
 		SDL_GetWindowMinimumSize( _sdlWindow,Varptr tw,Varptr th )
 		_minSize=New Vec2i( tw,th )
@@ -281,14 +282,6 @@ Class Window Extends View
 		MaxSize=_maxSize
 		Frame=_frame
 		
-		WindowClose=App.Terminate
-		
-		'Create GLContext and canvas
-		
-		_sdlGLContext=SDL_GL_CreateContext( _sdlWindow )
-		
-		SDL_GL_MakeCurrent( _sdlWindow,_sdlGLContext )
-		
-		_canvas=New Canvas( rect.Width,rect.Height )
+		Update()
 	End
 End

+ 0 - 1
modules/mojo/bananas/mojotest/mojotest.monkey2

@@ -78,7 +78,6 @@ Class MojoTest Extends Window
 		canvas.DrawRect( Width-1,0,1,Height )
 		canvas.DrawRect( 0,Height-1,Width,1 )
 		canvas.DrawRect( 0,0,1,Height-1 )
-	
 
 		canvas.Color=Color.Blue
 		canvas.DrawText( Seconds(),0,0 )

+ 82 - 23
modules/mojo/bananas/spacechimps/spacechimps.monkey2

@@ -11,65 +11,101 @@ Using mojo..
 
 Class MyWindow Extends Window
 
+	Field timer:Timer
 	Field image:Image
-	
-	Field pos:Vec2f
-	Field vel:Vec2f
+	Field pos:=New Vec2f
+	Field vel:=New Vec2f
 	Field rot:Float
 
 	Method New( title:String,width:Int,height:Int )
 	
 		'Call super class constructor - this just passes the arguments 'up' to the Window class constructor.
 		'
-		Super.New( title,width,height )
-
+		Super.New( title,width,height,WindowFlags.Resizable )
 		
 		'Black 'coz we're in space!
 		'
 		ClearColor=Color.Black
 		
-		
 		'Load and setup our image...
 		'
 		'Note: Scaling image here is faster than scaling in DrawImage.
 		'
 		image=Image.Load( "asset::spaceship.png" )
-		
 		image.Handle=New Vec2f( .5,.5 )
-		
 		image.Scale=New Vec2f( .125,.125 )
 		
-		
 		'Set initial image pos
 		'
 		pos=New Vec2f( width/2,height/2 )
+		
+		'Start update timer
+		'
+'		timer=New Timer( 60,OnUpdate )
+
+		'Vwait always recommended...
+		'	
+		SwapInterval=1
+	End
 	
+	Method OnKeyEvent( event:KeyEvent ) Override
+		Select event.Type
+		Case EventType.KeyDown
+			Select event.Key
+			Case Key.S
+				SwapInterval=1-SwapInterval
+'#If __TARGET__<>"emscripten"
+			Case Key.T
+				If timer
+					timer.Cancel()
+					timer=Null
+					App.RequestRender()
+				Else
+					timer=New Timer( 60,OnUpdate )
+				Endif
+'#Endif
+			End
+		End
 	End
 
-	Method OnRender( canvas:Canvas ) Override
+	Method OnWindowEvent( event:WindowEvent ) Override
+	
+		Select event.Type
+		Case EventType.WindowMoved
+		Case EventType.WindowResized
+			App.RequestRender()
+		Case EventType.WindowGainedFocus
+			If timer timer.Suspended=False
+		Case EventType.WindowLostFocus
+			If timer timer.Suspended=True
+		Default
+			Super.OnWindowEvent( event )
+		End
+	End
+	
+	Method OnUpdate()
 	
-		'This is necessary for 'continuous' rendering.
-		'
-		'Without it, OnRender will only be called when necessary, eg: when the window is resized.
-		'
 		App.RequestRender()
 		
-		
-		'Gamey stuff below
+		'rotate
 		'
-		If App.KeyDown( Key.Left )
+		If Keyboard.KeyDown( Key.Left )
 			rot+=.1
-		Else If App.KeyDown( Key.Right )
+		Else If Keyboard.KeyDown( Key.Right )
 			rot-=.1
 		Endif
 		
 		'wrap rot to [-Pi,Pi)
+		'
 		rot=(rot+Pi*3) Mod TwoPi-Pi
 
 		'calc forward vector..
+		'
 		Local dir:=New Vec2f( Cos( rot ),-Sin( rot ) )
-		
-		If App.KeyDown( Key.Up )
+
+		'thrust
+		'
+		If Keyboard.KeyDown( Key.Up )
 			vel+=(dir * 5 - vel) *.025	'arcadey thruster
 '			vel+=dir * .03				'realistic...
 		Else
@@ -77,19 +113,42 @@ Class MyWindow Extends Window
 		End
 		
 		'add velocity to position
+		'
 		pos+=vel
 		
 		'wrap pos to [0,size)
+		'
 		pos.x=(pos.x+Width) Mod Width
 		pos.y=(pos.y+Height) Mod Height
-
-		canvas.DrawText( "Arrow keys to fly",Width/2,8,.5,0 )
+		
+	End
+	
+	Field ms:=0
+	
+	Method OnRender( canvas:Canvas ) Override
+	
+		Local e:=App.Millisecs-ms	'ideally, e should be 16,17,17,16,17,17 ie: 16.6666...
+'		If e<>16 And e<>17 Print "elapsed="+e	'show glitches
+		ms+=e
+		
+		If Not timer OnUpdate()
+		
+		'Title text
+		'	
+		canvas.DrawText( "FPS="+App.FPS,Width/2,8,.5,0 )
+		canvas.DrawText( "Arrow keys to fly",Width/2,24,.5,0 )
+		canvas.DrawText( "Swap interval="+SwapInterval +" ('S' to toggle)",Width/2,40,.5,0 )
+'#If __TARGET__="emscripten"
+'		canvas.Color=Color.Grey
+'#Endif
+		canvas.DrawText( "Timer sync="+(timer ? "true" Else "false")+" ('T' to toggle)",Width/2,56,.5,0 )
+		canvas.Color=Color.White
 		
 		'Draw image
 		'
 		Local r:=rot-Pi/2
 		canvas.DrawImage( image,pos,r )
-		
+
 		'Draw wrap around(s)
 		'
 		If pos.x-image.Radius<0 canvas.DrawImage( image,pos.x+Width,pos.y,r )

+ 14 - 32
modules/mojo/bananas/viewlayout/viewlayout.monkey2

@@ -29,45 +29,19 @@ Class MyWindow Extends Window
 		'Set initial layout (this is the default for Windows).
 		'
 		Layout="fill"
-		
 
 		'Window clear color - for "letterbox" and "float" layouts, this is effectively the border color.
 		'
 		ClearColor=Color.Black
 		
-		
 		'Set minimum view size
 		'
 		MinSize=New Vec2i( 200,140 )
-
 		
 		'Set view background color.
 		'
 		Style.BackgroundColor=Color.DarkGrey
 		
-		
-		'One way to detect window resizing (you can also override OnWindowEvent).
-		'
-		'Note: you don't have to use a lambda here, a method or function will also work fine.
-		'
-		WindowResized=Lambda()
-		
-			Print "Window Resized to:"+Frame.Width+","+Frame.Height
-			
-		End
-		
-		
-		'One way to detect window close click (you can also override OnWindowEvent).
-		'
-		'Note: WindowClose is connected to App.Terminate by default, so this doesn't do a lot.
-		'
-		WindowClose=Lambda()
-		
-			Print "WindowClose - outta here!"
-			
-			App.Terminate()
-		End
-	
 	End
 
 	Method OnRender( canvas:Canvas ) Override
@@ -78,13 +52,9 @@ Class MyWindow Extends Window
 		'
 		App.RequestRender()
 		
-		
-		'Get mouse location in 'view' coordinates.
-		'
-		'Note: this is only necessary if Layout is not "fill". If Layout="fill" (the default), you can just use App.MouseLocation directly.
+		'Gets mouse location in 'view' coordinates.
 		'
-		Local mouse:=TransformPointFromView( App.MouseLocation,Null )
-
+		Local mouse:=Mouse.Location
 
 		'Render!
 		'		
@@ -143,6 +113,18 @@ Class MyWindow Extends Window
 	Method OnMouseEvent( event:MouseEvent ) Override
 	End
 	
+	Method OnWindowEvent( event:WindowEvent ) Override
+		Select event.Type
+		Case EventType.WindowClose
+			Print "Close"
+			App.Terminate()
+		Case EventType.WindowMoved
+			Print "Window moved to:"+Frame.Origin.ToString()
+		Case EventType.WindowResized
+			Print "Window resized to:"+Frame.Size.ToString()
+		End
+	End
+	
 	Method CycleLayout()
 		Select Layout
 		Case "fill"

+ 7 - 0
modules/mojo/graphics/texture.monkey2

@@ -36,6 +36,13 @@ Class Texture
 			flags=TextureFlags.Filter|TextureFlags.Mipmap|TextureFlags.ClampST|TextureFlags.Managed
 		Endif
 		
+#If __TARGET__="emscripten"
+		If flags & TextureFlags.Mipmap
+			Local tw:=Log2( pixmap.Width ),th:=Log2( pixmap.Height )
+			If tw<>Round( tw ) Or th<>Round( th ) flags&=~TextureFlags.Mipmap
+		Endif
+#Endif
+		
 		_rect=New Recti( 0,0,pixmap.Width,pixmap.Height )
 		_format=pixmap.Format
 		_flags=flags

+ 2 - 0
modules/mojo/input/keyboard.monkey2

@@ -5,6 +5,8 @@ Global Keyboard:=New KeyboardDevice
 
 Class KeyboardDevice Extends InputDevice
 
+	#rem monkeydoc @hidden
+	#end
 	Method Reset()
 		Init()
 		For Local i:=0 Until _numKeys

+ 2 - 0
modules/mojo/input/mouse.monkey2

@@ -23,6 +23,8 @@ End
 
 Class MouseDevice Extends InputDevice
 
+	#rem monkeydoc @hidden
+	#end
 	Method Reset()
 		Init()
 		For Local i:=0 Until 6

+ 11 - 2
modules/mojo/mojo.monkey2

@@ -7,12 +7,10 @@ Namespace mojo
 
 #Import "app/app"
 #Import "app/event"
-#Import "app/keycodes"
 #Import "app/skin"
 #Import "app/style"
 #Import "app/view"
 #Import "app/window"
-#Import "app/process"
 #Import "app/requesters"
 
 #Import "graphics/canvas"
@@ -27,12 +25,23 @@ Namespace mojo
 #Import "graphics/texture"
 #Import "graphics/vertex"
 
+#Import "input/device"
+#Import "input/keyboard"
+#Import "input/mouse"
+#Import "input/joystick"
+#Import "input/keycodes"
+
+#Import "process/process"
+#Import "timer/timer"
+
 Using emscripten..
 Using std..
 Using sdl2..
 Using gles20..
 Using mojo..
 
+Private
+
 Function Main()
 End
 

+ 2 - 2
modules/mojo/timer/timer.monkey2

@@ -10,9 +10,9 @@ Class Timer="bbTimer"
 
 	#rem monkeydoc Creates a new timer.
 	#end
-	Method New( fps:Int,fired:Void() )
+	Method New( ticksPerSecond:Int,fired:Void() )
 
-	#rem monkeydoc Suspended state.
+	#rem monkeydoc @hidden Suspended state.
 	#end
 	Property Suspended:Bool()="suspended"
 	Setter( suspended:Bool )="setSuspended"

+ 2 - 1
modules/monkey/native/bbmonkey.cpp

@@ -29,9 +29,10 @@ namespace{
 	#endif	
 		}
 		
-		bbAssert( false,err );
+//		bbAssert( false,err );
 		
 		printf( "Caught signal:%s\n",err );
+		exit( 0 );
 		
 #if __APPLE__
 

+ 1 - 5
modules/std/geom/mat3.monkey2

@@ -3,7 +3,7 @@ Namespace std.geom
 
 Alias Mat3f:Mat3<Float>
 
-Class Mat3<T>
+Struct Mat3<T>
 
 	Field i:Vec3<T>
 	Field j:Vec3<T>
@@ -13,10 +13,6 @@ Class Mat3<T>
 		i.x=1;j.y=1;k.z=1
 	End
 	
-	Method New( m:Mat3 )
-		i=m.i;j=m.j;k=m.k
-	End
-	
 	Method New( i:Vec3<T>,j:Vec3<T>,k:Vec3<T> )
 		Self.i=i;Self.j=j;Self.k=k
 	End

+ 1 - 1
modules/std/misc/chartype.monkey2

@@ -1,5 +1,5 @@
 
-Namespace std.chartype
+Namespace std.stringio
 
 #rem monkeydoc Checks if a character is whitespace.
 

+ 0 - 28
modules/std/misc/markdown.monkey2

@@ -1,28 +0,0 @@
-
-Namespace std.markdown
-
-#Import "<hoedown.monkey2>"
-
-Using hoedown
-
-Function MarkdownToHtml:String( markdown:String )
-
-	Local ob:=hoedown_buffer_new( 4096 )
-	
-	Local r:=hoedown_html_renderer_new( HOEDOWN_HTML_NONE,10 )
-	
-	Local doc:=hoedown_document_new( r,HOEDOWN_EXT_TABLES|HOEDOWN_EXT_FENCED_CODE,10 )
-		
-	hoedown_document_render( doc,ob,markdown,markdown.Utf8Length )
-	
-	Local html:=String.FromCString( hoedown_buffer_cstr( ob ) )
-	
-	hoedown_document_free( doc )
-	
-	hoedown_html_renderer_free( r )
-	
-	hoedown_buffer_free( ob )
-	
-	Return html
-
-End

+ 0 - 1
modules/std/std.monkey2

@@ -36,7 +36,6 @@ Namespace std
 #Import "misc/filesystem"
 #Import "misc/stringio"
 #Import "misc/json"
-#Import "misc/markdown"
 #Import "misc/time"
 
 #Import "fiber/fiber"