123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664 |
- #import <brl.mod/systemdefault.mod/system.h>
- #include <AppKit/AppKit.h>
- #include <Carbon/Carbon.h>
- static unsigned char key_table[]={
- //0...
- KEY_A, KEY_S, KEY_D, KEY_F, KEY_H, KEY_G, KEY_Z, KEY_X,
- KEY_C, KEY_V, 0, KEY_B, KEY_Q, KEY_W, KEY_E, KEY_R,
- KEY_Y, KEY_T, KEY_1, KEY_2, KEY_3, KEY_4, KEY_6, KEY_5,
- KEY_EQUALS, KEY_9, KEY_7, KEY_MINUS, KEY_8, KEY_0, KEY_CLOSEBRACKET,KEY_O,
- //32...
- KEY_U, KEY_OPENBRACKET,KEY_I, KEY_P, KEY_ENTER, KEY_L, KEY_J, KEY_QUOTES,
- KEY_K, KEY_SEMICOLON,KEY_BACKSLASH,KEY_COMMA,KEY_SLASH,KEY_N, KEY_M, KEY_PERIOD,
- KEY_TAB, KEY_SPACE, KEY_TILDE, KEY_BACKSPACE,0, KEY_ESC, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- //64...
- 0, KEY_NUMDECIMAL,0, KEY_NUMMULTIPLY,0, KEY_NUMADD, 0, 0,
- 0, 0, 0, KEY_NUMDIVIDE,KEY_ENTER,0, KEY_NUMSUBTRACT,0,
- //80...
- 0, 0, KEY_NUM0, KEY_NUM1, KEY_NUM2, KEY_NUM3, KEY_NUM4, KEY_NUM5,
- KEY_NUM6, KEY_NUM7, 0, KEY_NUM8, KEY_NUM9, 0, 0, 0,
- //96...
- KEY_F5, KEY_F6, KEY_F7, KEY_F3, KEY_F8, KEY_F9, 0, KEY_F11,
- 0, 0, 0, 0, 0, KEY_F10, 0, KEY_F12,
- 0, 0, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE, KEY_F4, KEY_END,
- KEY_F2, KEY_PAGEDOWN,KEY_F1, KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0,
- //128...
- };
- void bbSystemPoll();
- void bbFlushAutoreleasePool();
- static int mods,deltaMods;
- static NSDate *distantPast,*distantFuture;
- static int mouseVisible=1;
- static int displayCaptured=0;
- static NSView *mouseView;
- static BBObject *mouseSource;
- static NSTrackingRectTag mouseTrackTag;
- static NSEvent *anullEvent;
- static NSView *capturedView;
- static int appWaiting;
- static NSWindow *keyWin;
- #define LSHIFTMASK 0x2
- #define RSHIFTMASK 0x4
- #define LCTRLMASK 0x1
- #define RCTRLMASK 0x2000
- #define LSYSMASK 0x8
- #define RSYSMASK 0x10
- #define LALTMASK 0x20
- #define RALTMASK 0x40
- typedef struct AsyncOp{
- BBAsyncOp asyncOp;
- int asyncInfo;
- size_t asyncRet;
- BBSyncOp syncOp;
- BBObject *syncInfo;
- }AsyncOp;
- static BBSystemAppDelegate *appDelegate;
- static NSString *tmpNSString( BBString *str ){
- return [NSString stringWithCharacters:str->buf length:str->length];
- }
- static BBString *stringFromNSString( NSString *nsstr ){
- return bbStringFromUTF8String( [nsstr UTF8String] );
- }
- static NSString *appTitle(){
- return tmpNSString( bbAppTitle );
- }
- int bbSystemTranslateKey( int key ){
- return (key>=0 && key<128) ? key_table[key] : 0;
- }
- int bbSystemTranslateChar( int chr ){
- switch(chr){
- case 127:return 8;
- case 63272:return 127;
- }
- return chr;
- }
- int bbSystemTranslateMods( int mods ){
- int n=0;
- if( mods & NSShiftKeyMask ) n|=MODIFIER_SHIFT;
- if( mods & NSControlKeyMask ) n|=MODIFIER_CONTROL;
- if( mods & NSAlternateKeyMask ) n|=MODIFIER_OPTION;
- if( mods & NSCommandKeyMask ) n|=MODIFIER_SYSTEM;
- return n;
- }
- static void updateMouseVisibility(){
- static int cursorVisible=1;
-
- int visible=mouseVisible;
- if( !visible && !displayCaptured ){
-
- NSArray *windows=(NSArray*)[NSApp windows];
- int count=[windows count],i;
-
- visible=1;
- for( i=0;i<count;++i ){
- NSRect rect;
- NSPoint point;
- NSView *view;
- NSWindow *window;
-
- window=[windows objectAtIndex:i];
- view=[window contentView];
- if( !view ) continue;
-
- rect=[view bounds];
- point=[window mouseLocationOutsideOfEventStream];
- point=[view convertPoint:point fromView:nil];
-
- if( ![view isFlipped] ) point.y=rect.size.height-point.y;
-
- if( point.x<0 || point.y<0 || point.x>=rect.size.width || point.y>=rect.size.height ) continue;
-
- visible=0;
- break;
- }
- }
- if( visible ){
- if( !CGCursorIsVisible() ){
- CGDisplayShowCursor( kCGDirectMainDisplay );
- }
- }else{
- if( CGCursorIsVisible() ){
- CGDisplayHideCursor( kCGDirectMainDisplay );
- }
- }
- }
- static int mouseViewPos( NSView *view,int *x,int *y ){
- NSRect rect;
- NSPoint point;
- NSWindow *window;
- if( displayCaptured || !view ){
- point = [NSEvent mouseLocation];
- *x=point.x;
- *y=point.y;
- return 1;
- }
- window=[view window];
- point=[window mouseLocationOutsideOfEventStream];
- rect=[view bounds];
- point=[view convertPoint:point fromView:nil];
- if( ![view isFlipped] ) point.y=rect.size.height-point.y;
- *x=point.x;
- *y=point.y;
- return point.x>=0 && point.y>=0 && point.x<rect.size.width && point.y<rect.size.height;
- }
- static void setMouseView( NSView *view,int x,int y,BBObject *source ){
- if( view==mouseView ) return;
- if( mouseView ){
- int x,y;
- mouseViewPos( mouseView,&x,&y );
- bbSystemEmitEvent( BBEVENT_MOUSELEAVE,mouseSource,0,0,x,y,&bbNullObject );
- if( mouseSource ){
- BBRELEASE( mouseSource );
- }
- [mouseView removeTrackingRect:mouseTrackTag];
- [mouseView release];
- }
- mouseView=[view retain];
- if( mouseView ){
- mouseSource=source;
- if( mouseSource ){
- BBRETAIN( mouseSource );
- }
- bbSystemEmitEvent( BBEVENT_MOUSEENTER,mouseSource,0,0,x,y,&bbNullObject );
- mouseTrackTag=[mouseView addTrackingRect:[mouseView bounds] owner:appDelegate userData:0 assumeInside:YES];
- }
- }
- static NSEvent *appDefEvent( int subtype, NSInteger data1, NSInteger data2 ){
- return [NSEvent
- otherEventWithType:NSApplicationDefined
- location:NSMakePoint(0,0)
- modifierFlags:0
- timestamp:0
- windowNumber:0
- context:0
- subtype:subtype
- data1:data1
- data2:data2];
- }
- @implementation BBSystemAppDelegate
- -(void)applicationWillTerminate:(NSNotification*)notification{
- exit(0);
- }
- -(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender{
- bbSystemEmitEvent( BBEVENT_APPTERMINATE,&bbNullObject,0,0,0,0,&bbNullObject );
- return NSTerminateCancel;
- }
- -(void)applicationDidBecomeActive:(NSNotification *)aNotification{
- bbSystemEmitEvent( BBEVENT_APPRESUME,&bbNullObject,0,0,0,0,&bbNullObject );
- }
- -(void)applicationDidResignActive:(NSNotification *)aNotification{
- bbSystemEmitEvent( BBEVENT_APPSUSPEND,&bbNullObject,0,0,0,0,&bbNullObject );
- }
- -(BOOL)application:(NSApplication*)app openFile:(NSString*)path{
- BBString *t=bbStringFromCString( [path cString] );
- bbSystemEmitEvent( BBEVENT_APPOPENFILE,&bbNullObject,0,0,0,0,(BBObject*)t );
- return YES;
- }
- -(void)mouseEntered:(NSEvent*)event{
- //Never gets here hopefully!
- }
- -(void)mouseExited:(NSEvent*)event{
- setMouseView( 0,0,0,0 );
- }
- -(void)asyncOpThread:(NSEvent*)event{
- AsyncOp *p=(AsyncOp*)[event data1];
- p->asyncRet=p->asyncOp( p->asyncInfo );
- [NSApp postEvent:event atStart:NO];
- }
- @end
- static void updateDisplayCaptured(){
- displayCaptured=CGDisplayIsCaptured( kCGDirectMainDisplay );
- }
- static void updateEvents( NSDate *until ){
- NSEvent *event;
- updateDisplayCaptured();
- updateMouseVisibility();
-
- while( event=[NSApp nextEventMatchingMask:NSAnyEventMask untilDate:until inMode:NSDefaultRunLoopMode dequeue:YES] ){
- if( [event type]==NSApplicationDefined ){
- if( [event subtype]==BB_RESERVEDEVENTSUBTYPE1 ){
- AsyncOp *p=(AsyncOp*)[event data1];
- p->syncOp( p->syncInfo,p->asyncRet );
- if( p->asyncOp ){
- BBRELEASE( p->syncInfo );
- }
- free( p );
- continue;
- }
- }
- if( displayCaptured ){
- bbSystemEmitOSEvent( event,0,&bbNullObject );
- }else{
- [NSApp sendEvent:event];
- }
- until=distantPast;
- }
- bbFlushAutoreleasePool();
- }
- static void checkDisplay(){
- updateDisplayCaptured();
- if( displayCaptured ) bbExThrowCString( "GUI unavailable in fullscreen mode" );
- }
- static void beginPanel(){
- checkDisplay();
- keyWin=[NSApp keyWindow];
- if( !keyWin ) [NSApp activateIgnoringOtherApps:YES];
- }
- static void endPanel(){
- if( keyWin ) [keyWin makeKeyWindow];
- }
- static NSWindow *appMainWindow(){
- int i;
- if( ![[NSApp windows] count] ) return 0;
- for( i=0;i<10;++i ){
- NSWindow *window=[NSApp mainWindow];
- if( window ) return window;
- bbSystemPoll();
- }
- return 0;
- }
- void bbSystemPoll(){
- updateEvents( distantPast );
- }
- void bbSystemWait(){
- appWaiting=1;
- updateEvents( distantFuture );
- appWaiting=0;
- }
- void bbSystemIntr(){
- if( !appWaiting ) return;
- appWaiting=0;
- [NSApp postEvent:anullEvent atStart:NO];
- }
- void bbSystemViewClosed( NSView *view ){
- if( view!=mouseView ) return;
- [mouseView removeTrackingRect:mouseTrackTag];
- mouseView=0;
- }
- void bbSystemEmitOSEvent( NSEvent *event,NSView *view,BBObject *source ){
- int inView;
- NSEventType type;
- NSString *characters;
- int ev=0,data=0,x=0,y=0,oldMods=mods,mask;
- float f;
-
- mods=[event modifierFlags];
- type=[event type];
- switch( type ){
- case NSKeyDown:
- if( data=bbSystemTranslateKey( [event keyCode] ) ){
- ev=[event isARepeat] ? BBEVENT_KEYREPEAT : BBEVENT_KEYDOWN;
- bbSystemEmitEvent( ev,source,data,bbSystemTranslateMods(mods),0,0,&bbNullObject );
- }
- characters=[event characters];
- if( [characters length]!=1 ) return;
- data=[characters characterAtIndex:0];
- if( data>=0xf700 && data<=0xf8ff ) return;
- ev=BBEVENT_KEYCHAR;
- data=bbSystemTranslateChar( data );
- break;
- case NSKeyUp:
- data=bbSystemTranslateKey( [event keyCode] );
- if( !data ) return;
- ev=BBEVENT_KEYUP;
- break;
- case NSFlagsChanged:
- deltaMods=mods^oldMods;
- if( deltaMods & (mask=LSHIFTMASK) ) data=KEY_LSHIFT;
- else if( deltaMods & (mask=RSHIFTMASK) ) data=KEY_RSHIFT;
- else if( deltaMods & (mask=LCTRLMASK) ) data=KEY_LCONTROL;
- else if( deltaMods & (mask=RCTRLMASK) ) data=KEY_RCONTROL;
- else if( deltaMods & (mask=LALTMASK) ) data=KEY_LALT;
- else if( deltaMods & (mask=RALTMASK) ) data=KEY_RALT;
- else if( deltaMods & (mask=LSYSMASK) ) data=KEY_LSYS;
- else if( deltaMods & (mask=RSYSMASK) ) data=KEY_RSYS;
- if( !data ) return;
- ev=(mods & mask) ? BBEVENT_KEYDOWN : BBEVENT_KEYUP;
- break;
- case NSLeftMouseDown:
- case NSRightMouseDown:
- case NSOtherMouseDown:
- inView=mouseViewPos( view,&x,&y );
- if( !inView ) return;
- setMouseView( view,x,y,source );
- capturedView=mouseView;
- ev=BBEVENT_MOUSEDOWN;
- data=(type==NSLeftMouseDown) ? 1 : (type==NSRightMouseDown ? 2 : 3);
- break;
- case NSLeftMouseUp:
- case NSRightMouseUp:
- case NSOtherMouseUp:
- inView=mouseViewPos( view,&x,&y );
- if( !inView && !capturedView ) return;
- capturedView=0;
- ev=BBEVENT_MOUSEUP;
- data=(type==NSLeftMouseUp) ? 1 : (type==NSRightMouseUp ? 2 : 3);
- break;
- case NSMouseMoved:
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- case NSOtherMouseDragged:
- inView=mouseViewPos( view,&x,&y );
- setMouseView( inView ? view : 0,x,y,source );
- if( !inView && !capturedView ) return;
- ev=BBEVENT_MOUSEMOVE;
- data=(type==NSLeftMouseDragged) ? 1 : (type==NSRightMouseDragged ? 2 : (type==NSOtherMouseDragged ? 3 : 0));
- break;
- case NSScrollWheel:
- inView=mouseViewPos( view,&x,&y );
- if( !inView && view!=capturedView ) return;
- ev=BBEVENT_MOUSEWHEEL;
- f=[event deltaY];
- data=f>0 ? ceil(f) : floor(f);
- break;
- default:
- return;
- }
- bbSystemEmitEvent( ev,source,data,bbSystemTranslateMods(mods),x,y,&bbNullObject );
- }
- void bbSystemMoveMouse( int x,int y ){
- NSEvent *event;
- CGPoint cgPoint={x,y};
- CGSetLocalEventsSuppressionInterval(0.0);
- if( !CGDisplayIsCaptured(kCGDirectMainDisplay) ){
- NSPoint nsPoint={x,y};
-
- NSWindow *window=appMainWindow();
-
- if( !window ) return;
- nsPoint.y=[[window contentView] bounds].size.height-1-nsPoint.y;
- nsPoint=[window convertBaseToScreen:nsPoint];
- cgPoint.x=nsPoint.x;
- cgPoint.y=CGDisplayPixelsHigh(kCGDirectMainDisplay)-nsPoint.y;
- }
- CGDisplayMoveCursorToPoint( kCGDirectMainDisplay,cgPoint );
- bbSystemEmitEvent( BBEVENT_MOUSEMOVE,&bbNullObject,0,bbSystemTranslateMods(mods),x,y,&bbNullObject );
- }
- void bbSystemSetMouseVisible( int visible ){
- mouseVisible=visible;
- updateDisplayCaptured();
- updateMouseVisibility();
- }
- void bbSystemStartup(){
- anullEvent=[appDefEvent( -1,0,0 ) retain];
- distantPast=[[NSDate distantPast] retain];
- distantFuture=[[NSDate distantFuture] retain];
- appDelegate=[[BBSystemAppDelegate alloc] init];
- [NSApp setDelegate:appDelegate];
- }
- typedef int (*AlertPanel)(
- NSString *title,
- NSString *msg,
- NSString *defaultButton,
- NSString *alternateButton,
- NSString *otherButton );
- void bbSystemNotify( BBString *text,int serious ){
- AlertPanel panel=serious ? (void*)NSRunCriticalAlertPanel : (void*)NSRunAlertPanel;
-
- beginPanel();
- panel(
- appTitle(),
- tmpNSString(text),
- @"OK",0,0 );
-
- endPanel();
- }
- int bbSystemConfirm( BBString *text,int serious ){
- int n;
- AlertPanel panel=serious ? (void*)NSRunCriticalAlertPanel : (void*)NSRunAlertPanel;
-
- beginPanel();
- n=panel(
- appTitle(),
- tmpNSString(text),
- @"OK",@"Cancel",0 );
- endPanel();
-
- switch( n ){
- case NSAlertDefaultReturn:return 1;
- }
- return 0;
- }
- int bbSystemProceed( BBString *text,int serious ){
- int n;
- AlertPanel panel=serious ? (void*)NSRunCriticalAlertPanel : (void*)NSRunAlertPanel;
-
- beginPanel();
- n=panel(
- appTitle(),
- tmpNSString(text),
- @"Yes",@"No",@"Cancel" );
- endPanel();
-
- switch( n ){
- case NSAlertDefaultReturn:return 1;
- case NSAlertAlternateReturn:return 0;
- }
- return -1;
- }
- BBString *bbSystemRequestFile( BBString *title,BBString *exts,int save,BBString *file,BBString *dir ){
- NSString *nsdir=0;
- NSString *nsfile=0;
- NSString *nstitle=0;
- NSMutableArray *nsexts=0;
- BBString *str=&bbEmptyString;
-
- if( dir->length ){
- char tmp[PATH_MAX];
- char *p=bbStringToUTF8String( dir );
- realpath( p,tmp );
- bbMemFree(p);
- nsdir=[NSString stringWithUTF8String:tmp];
- }
-
- if( file->length ){
- nsfile=tmpNSString(file);
- }
-
- if( title->length ){
- nstitle=tmpNSString(title);
- }
-
- if( exts->length ){
- char *p=bbStringToUTF8String(exts),*t;
- nsexts=[NSMutableArray arrayWithCapacity:10];
- while( t=strchr(p,',') ){
- *t=0;
- [nsexts addObject:[NSString stringWithUTF8String:p]];
- p=t+1;
- }
- if( *p ) [nsexts addObject:[NSString stringWithUTF8String:p]];
- bbMemFree(p);
- }
- beginPanel();
- if( save ){
- NSSavePanel *panel=[NSSavePanel savePanel];
-
- if( nstitle ) [panel setTitle:nstitle];
-
- if( nsexts ){
- [panel setAllowedFileTypes:nsexts];
- [panel setAllowsOtherFileTypes:YES];
- }
-
- if( [panel runModalForDirectory:nsdir file:nsfile]==NSFileHandlingPanelOKButton ){
- str=stringFromNSString([panel filename]);
- }
- }else{
- NSOpenPanel *panel=[NSOpenPanel openPanel];
- if( nstitle ) [panel setTitle:nstitle];
-
- if( [panel runModalForDirectory:nsdir file:nsfile types:nsexts]==NSFileHandlingPanelOKButton ){
- str=stringFromNSString([panel filename]);
- }
- }
- endPanel();
- return str;
- }
- BBString *bbSystemRequestDir( BBString *title,BBString *dir ){
- NSString *nsdir=0;
- NSString *nstitle=0;
- NSOpenPanel *panel;
- BBString *str=&bbEmptyString;
- if( dir->length ){
- char tmp[PATH_MAX];
- char *p=bbStringToUTF8String(dir);
- realpath( p,tmp );
- bbMemFree(p);
- nsdir=[NSString stringWithUTF8String:tmp];
- }
-
- if( title->length ){
- nstitle=tmpNSString(title);
- }
- panel=[NSOpenPanel openPanel];
-
- [panel setCanChooseFiles:NO];
- [panel setCanChooseDirectories:YES];
- [panel setCanCreateDirectories:YES];
-
- if( title ) [panel setTitle:nstitle];
-
- beginPanel();
- if( [panel runModalForDirectory:nsdir file:0 types:0]==NSFileHandlingPanelOKButton ){
- str=stringFromNSString([panel filename]);
- }
- endPanel();
-
- return str;
- }
- int bbOpenURL( BBString *bburl ){
- NSURL *url;
- NSString *loc;
- int res=0;
- checkDisplay();
- loc=tmpNSString(bburl);
- url=[NSURL URLWithString:[loc stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
- if( url ) res=[[NSWorkspace sharedWorkspace] openURL:url];
- return res;
- }
- void bbSystemPostSyncOp( BBSyncOp syncOp,BBObject *syncInfo,size_t asyncRet ){
- AsyncOp *p=(AsyncOp*)malloc( sizeof(AsyncOp) );
- NSEvent *event=appDefEvent( BB_RESERVEDEVENTSUBTYPE1,(NSInteger)p,0 );
- p->asyncOp=0;
- p->asyncRet=asyncRet;
- p->syncOp=syncOp;
- p->syncInfo=syncInfo;
- [NSApp postEvent:event atStart:NO];
- }
- void bbSystemStartAsyncOp( BBAsyncOp asyncOp,int asyncInfo,BBSyncOp syncOp,BBObject *syncInfo ){
- AsyncOp *p=(AsyncOp*)malloc( sizeof( AsyncOp ) );
- NSEvent *event=appDefEvent( BB_RESERVEDEVENTSUBTYPE1,(NSInteger)p,0 );
- BBRETAIN( syncInfo );
- p->asyncOp=asyncOp;
- p->asyncInfo=asyncInfo;
- p->syncOp=syncOp;
- p->syncInfo=syncInfo;
- [NSThread detachNewThreadSelector:@selector(asyncOpThread:) toTarget:appDelegate withObject:event];
- }
- static NSScreen *DesktopScreen(){
- NSArray *screens;
- if( screens=[NSScreen screens] ){
- if( [screens count] ) return [screens objectAtIndex:0];
- }
- return 0;
- }
- int bbSystemDesktopWidth(){
- NSScreen *screen=DesktopScreen();
- if( screen ) return [screen frame].size.width;
- return 640;
- }
- int bbSystemDesktopHeight(){
- NSScreen *screen=DesktopScreen();
- if( screen ) return [screen frame].size.height;
- return 480;
- }
- int bbSystemDesktopDepth(){
- NSScreen *screen=DesktopScreen();
- if( screen ) return NSBitsPerPixelFromDepth( [screen depth] );
- return 32;
- }
- int bbSystemDesktopHertz(){
- return 60;
- }
|