system.macos.m 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. #import <brl.mod/systemdefault.mod/system.h>
  2. #include <AppKit/AppKit.h>
  3. #include <Carbon/Carbon.h>
  4. static unsigned char key_table[]={
  5. //0...
  6. KEY_A, KEY_S, KEY_D, KEY_F, KEY_H, KEY_G, KEY_Z, KEY_X,
  7. KEY_C, KEY_V, 0, KEY_B, KEY_Q, KEY_W, KEY_E, KEY_R,
  8. KEY_Y, KEY_T, KEY_1, KEY_2, KEY_3, KEY_4, KEY_6, KEY_5,
  9. KEY_EQUALS, KEY_9, KEY_7, KEY_MINUS, KEY_8, KEY_0, KEY_CLOSEBRACKET,KEY_O,
  10. //32...
  11. KEY_U, KEY_OPENBRACKET,KEY_I, KEY_P, KEY_ENTER, KEY_L, KEY_J, KEY_QUOTES,
  12. KEY_K, KEY_SEMICOLON,KEY_BACKSLASH,KEY_COMMA,KEY_SLASH,KEY_N, KEY_M, KEY_PERIOD,
  13. KEY_TAB, KEY_SPACE, KEY_TILDE, KEY_BACKSPACE,0, KEY_ESC, 0, 0,
  14. 0, 0, 0, 0, 0, 0, 0, 0,
  15. //64...
  16. 0, KEY_NUMDECIMAL,0, KEY_NUMMULTIPLY,0, KEY_NUMADD, 0, 0,
  17. 0, 0, 0, KEY_NUMDIVIDE,KEY_ENTER,0, KEY_NUMSUBTRACT,0,
  18. //80...
  19. 0, 0, KEY_NUM0, KEY_NUM1, KEY_NUM2, KEY_NUM3, KEY_NUM4, KEY_NUM5,
  20. KEY_NUM6, KEY_NUM7, 0, KEY_NUM8, KEY_NUM9, 0, 0, 0,
  21. //96...
  22. KEY_F5, KEY_F6, KEY_F7, KEY_F3, KEY_F8, KEY_F9, 0, KEY_F11,
  23. 0, 0, 0, 0, 0, KEY_F10, 0, KEY_F12,
  24. 0, 0, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE, KEY_F4, KEY_END,
  25. KEY_F2, KEY_PAGEDOWN,KEY_F1, KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0,
  26. //128...
  27. };
  28. void bbSystemPoll();
  29. void bbFlushAutoreleasePool();
  30. static int mods,deltaMods;
  31. static NSDate *distantPast,*distantFuture;
  32. static int mouseVisible=1;
  33. static int displayCaptured=0;
  34. static NSView *mouseView;
  35. static BBObject *mouseSource;
  36. static NSTrackingRectTag mouseTrackTag;
  37. static NSEvent *anullEvent;
  38. static NSView *capturedView;
  39. static int appWaiting;
  40. static NSWindow *keyWin;
  41. #define LSHIFTMASK 0x2
  42. #define RSHIFTMASK 0x4
  43. #define LCTRLMASK 0x1
  44. #define RCTRLMASK 0x2000
  45. #define LSYSMASK 0x8
  46. #define RSYSMASK 0x10
  47. #define LALTMASK 0x20
  48. #define RALTMASK 0x40
  49. typedef struct AsyncOp{
  50. BBAsyncOp asyncOp;
  51. int asyncInfo;
  52. size_t asyncRet;
  53. BBSyncOp syncOp;
  54. BBObject *syncInfo;
  55. }AsyncOp;
  56. static BBSystemAppDelegate *appDelegate;
  57. static NSString *tmpNSString( BBString *str ){
  58. return [NSString stringWithCharacters:str->buf length:str->length];
  59. }
  60. static BBString *stringFromNSString( NSString *nsstr ){
  61. return bbStringFromUTF8String( [nsstr UTF8String] );
  62. }
  63. static NSString *appTitle(){
  64. return tmpNSString( bbAppTitle );
  65. }
  66. int bbSystemTranslateKey( int key ){
  67. return (key>=0 && key<128) ? key_table[key] : 0;
  68. }
  69. int bbSystemTranslateChar( int chr ){
  70. switch(chr){
  71. case 127:return 8;
  72. case 63272:return 127;
  73. }
  74. return chr;
  75. }
  76. int bbSystemTranslateMods( int mods ){
  77. int n=0;
  78. if( mods & NSShiftKeyMask ) n|=MODIFIER_SHIFT;
  79. if( mods & NSControlKeyMask ) n|=MODIFIER_CONTROL;
  80. if( mods & NSAlternateKeyMask ) n|=MODIFIER_OPTION;
  81. if( mods & NSCommandKeyMask ) n|=MODIFIER_SYSTEM;
  82. return n;
  83. }
  84. static void updateMouseVisibility(){
  85. static int cursorVisible=1;
  86. int visible=mouseVisible;
  87. if( !visible && !displayCaptured ){
  88. NSArray *windows=(NSArray*)[NSApp windows];
  89. int count=[windows count],i;
  90. visible=1;
  91. for( i=0;i<count;++i ){
  92. NSRect rect;
  93. NSPoint point;
  94. NSView *view;
  95. NSWindow *window;
  96. window=[windows objectAtIndex:i];
  97. view=[window contentView];
  98. if( !view ) continue;
  99. rect=[view bounds];
  100. point=[window mouseLocationOutsideOfEventStream];
  101. point=[view convertPoint:point fromView:nil];
  102. if( ![view isFlipped] ) point.y=rect.size.height-point.y;
  103. if( point.x<0 || point.y<0 || point.x>=rect.size.width || point.y>=rect.size.height ) continue;
  104. visible=0;
  105. break;
  106. }
  107. }
  108. if( visible ){
  109. if( !CGCursorIsVisible() ){
  110. CGDisplayShowCursor( kCGDirectMainDisplay );
  111. }
  112. }else{
  113. if( CGCursorIsVisible() ){
  114. CGDisplayHideCursor( kCGDirectMainDisplay );
  115. }
  116. }
  117. }
  118. static int mouseViewPos( NSView *view,int *x,int *y ){
  119. NSRect rect;
  120. NSPoint point;
  121. NSWindow *window;
  122. if( displayCaptured || !view ){
  123. point = [NSEvent mouseLocation];
  124. *x=point.x;
  125. *y=point.y;
  126. return 1;
  127. }
  128. window=[view window];
  129. point=[window mouseLocationOutsideOfEventStream];
  130. rect=[view bounds];
  131. point=[view convertPoint:point fromView:nil];
  132. if( ![view isFlipped] ) point.y=rect.size.height-point.y;
  133. *x=point.x;
  134. *y=point.y;
  135. return point.x>=0 && point.y>=0 && point.x<rect.size.width && point.y<rect.size.height;
  136. }
  137. static void setMouseView( NSView *view,int x,int y,BBObject *source ){
  138. if( view==mouseView ) return;
  139. if( mouseView ){
  140. int x,y;
  141. mouseViewPos( mouseView,&x,&y );
  142. bbSystemEmitEvent( BBEVENT_MOUSELEAVE,mouseSource,0,0,x,y,&bbNullObject );
  143. if( mouseSource ){
  144. BBRELEASE( mouseSource );
  145. }
  146. [mouseView removeTrackingRect:mouseTrackTag];
  147. [mouseView release];
  148. }
  149. mouseView=[view retain];
  150. if( mouseView ){
  151. mouseSource=source;
  152. if( mouseSource ){
  153. BBRETAIN( mouseSource );
  154. }
  155. bbSystemEmitEvent( BBEVENT_MOUSEENTER,mouseSource,0,0,x,y,&bbNullObject );
  156. mouseTrackTag=[mouseView addTrackingRect:[mouseView bounds] owner:appDelegate userData:0 assumeInside:YES];
  157. }
  158. }
  159. static NSEvent *appDefEvent( int subtype, NSInteger data1, NSInteger data2 ){
  160. return [NSEvent
  161. otherEventWithType:NSApplicationDefined
  162. location:NSMakePoint(0,0)
  163. modifierFlags:0
  164. timestamp:0
  165. windowNumber:0
  166. context:0
  167. subtype:subtype
  168. data1:data1
  169. data2:data2];
  170. }
  171. @implementation BBSystemAppDelegate
  172. -(void)applicationWillTerminate:(NSNotification*)notification{
  173. exit(0);
  174. }
  175. -(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender{
  176. bbSystemEmitEvent( BBEVENT_APPTERMINATE,&bbNullObject,0,0,0,0,&bbNullObject );
  177. return NSTerminateCancel;
  178. }
  179. -(void)applicationDidBecomeActive:(NSNotification *)aNotification{
  180. bbSystemEmitEvent( BBEVENT_APPRESUME,&bbNullObject,0,0,0,0,&bbNullObject );
  181. }
  182. -(void)applicationDidResignActive:(NSNotification *)aNotification{
  183. bbSystemEmitEvent( BBEVENT_APPSUSPEND,&bbNullObject,0,0,0,0,&bbNullObject );
  184. }
  185. -(BOOL)application:(NSApplication*)app openFile:(NSString*)path{
  186. BBString *t=bbStringFromCString( [path cString] );
  187. bbSystemEmitEvent( BBEVENT_APPOPENFILE,&bbNullObject,0,0,0,0,(BBObject*)t );
  188. return YES;
  189. }
  190. -(void)mouseEntered:(NSEvent*)event{
  191. //Never gets here hopefully!
  192. }
  193. -(void)mouseExited:(NSEvent*)event{
  194. setMouseView( 0,0,0,0 );
  195. }
  196. -(void)asyncOpThread:(NSEvent*)event{
  197. AsyncOp *p=(AsyncOp*)[event data1];
  198. p->asyncRet=p->asyncOp( p->asyncInfo );
  199. [NSApp postEvent:event atStart:NO];
  200. }
  201. @end
  202. static void updateDisplayCaptured(){
  203. displayCaptured=CGDisplayIsCaptured( kCGDirectMainDisplay );
  204. }
  205. static void updateEvents( NSDate *until ){
  206. NSEvent *event;
  207. updateDisplayCaptured();
  208. updateMouseVisibility();
  209. while( event=[NSApp nextEventMatchingMask:NSAnyEventMask untilDate:until inMode:NSDefaultRunLoopMode dequeue:YES] ){
  210. if( [event type]==NSApplicationDefined ){
  211. if( [event subtype]==BB_RESERVEDEVENTSUBTYPE1 ){
  212. AsyncOp *p=(AsyncOp*)[event data1];
  213. p->syncOp( p->syncInfo,p->asyncRet );
  214. if( p->asyncOp ){
  215. BBRELEASE( p->syncInfo );
  216. }
  217. free( p );
  218. continue;
  219. }
  220. }
  221. if( displayCaptured ){
  222. bbSystemEmitOSEvent( event,0,&bbNullObject );
  223. }else{
  224. [NSApp sendEvent:event];
  225. }
  226. until=distantPast;
  227. }
  228. bbFlushAutoreleasePool();
  229. }
  230. static void checkDisplay(){
  231. updateDisplayCaptured();
  232. if( displayCaptured ) bbExThrowCString( "GUI unavailable in fullscreen mode" );
  233. }
  234. static void beginPanel(){
  235. checkDisplay();
  236. keyWin=[NSApp keyWindow];
  237. if( !keyWin ) [NSApp activateIgnoringOtherApps:YES];
  238. }
  239. static void endPanel(){
  240. if( keyWin ) [keyWin makeKeyWindow];
  241. }
  242. static NSWindow *appMainWindow(){
  243. int i;
  244. if( ![[NSApp windows] count] ) return 0;
  245. for( i=0;i<10;++i ){
  246. NSWindow *window=[NSApp mainWindow];
  247. if( window ) return window;
  248. bbSystemPoll();
  249. }
  250. return 0;
  251. }
  252. void bbSystemPoll(){
  253. updateEvents( distantPast );
  254. }
  255. void bbSystemWait(){
  256. appWaiting=1;
  257. updateEvents( distantFuture );
  258. appWaiting=0;
  259. }
  260. void bbSystemIntr(){
  261. if( !appWaiting ) return;
  262. appWaiting=0;
  263. [NSApp postEvent:anullEvent atStart:NO];
  264. }
  265. void bbSystemViewClosed( NSView *view ){
  266. if( view!=mouseView ) return;
  267. [mouseView removeTrackingRect:mouseTrackTag];
  268. mouseView=0;
  269. }
  270. void bbSystemEmitOSEvent( NSEvent *event,NSView *view,BBObject *source ){
  271. int inView;
  272. NSEventType type;
  273. NSString *characters;
  274. int ev=0,data=0,x=0,y=0,oldMods=mods,mask;
  275. float f;
  276. mods=[event modifierFlags];
  277. type=[event type];
  278. switch( type ){
  279. case NSKeyDown:
  280. if( data=bbSystemTranslateKey( [event keyCode] ) ){
  281. ev=[event isARepeat] ? BBEVENT_KEYREPEAT : BBEVENT_KEYDOWN;
  282. bbSystemEmitEvent( ev,source,data,bbSystemTranslateMods(mods),0,0,&bbNullObject );
  283. }
  284. characters=[event characters];
  285. if( [characters length]!=1 ) return;
  286. data=[characters characterAtIndex:0];
  287. if( data>=0xf700 && data<=0xf8ff ) return;
  288. ev=BBEVENT_KEYCHAR;
  289. data=bbSystemTranslateChar( data );
  290. break;
  291. case NSKeyUp:
  292. data=bbSystemTranslateKey( [event keyCode] );
  293. if( !data ) return;
  294. ev=BBEVENT_KEYUP;
  295. break;
  296. case NSFlagsChanged:
  297. deltaMods=mods^oldMods;
  298. if( deltaMods & (mask=LSHIFTMASK) ) data=KEY_LSHIFT;
  299. else if( deltaMods & (mask=RSHIFTMASK) ) data=KEY_RSHIFT;
  300. else if( deltaMods & (mask=LCTRLMASK) ) data=KEY_LCONTROL;
  301. else if( deltaMods & (mask=RCTRLMASK) ) data=KEY_RCONTROL;
  302. else if( deltaMods & (mask=LALTMASK) ) data=KEY_LALT;
  303. else if( deltaMods & (mask=RALTMASK) ) data=KEY_RALT;
  304. else if( deltaMods & (mask=LSYSMASK) ) data=KEY_LSYS;
  305. else if( deltaMods & (mask=RSYSMASK) ) data=KEY_RSYS;
  306. if( !data ) return;
  307. ev=(mods & mask) ? BBEVENT_KEYDOWN : BBEVENT_KEYUP;
  308. break;
  309. case NSLeftMouseDown:
  310. case NSRightMouseDown:
  311. case NSOtherMouseDown:
  312. inView=mouseViewPos( view,&x,&y );
  313. if( !inView ) return;
  314. setMouseView( view,x,y,source );
  315. capturedView=mouseView;
  316. ev=BBEVENT_MOUSEDOWN;
  317. data=(type==NSLeftMouseDown) ? 1 : (type==NSRightMouseDown ? 2 : 3);
  318. break;
  319. case NSLeftMouseUp:
  320. case NSRightMouseUp:
  321. case NSOtherMouseUp:
  322. inView=mouseViewPos( view,&x,&y );
  323. if( !inView && !capturedView ) return;
  324. capturedView=0;
  325. ev=BBEVENT_MOUSEUP;
  326. data=(type==NSLeftMouseUp) ? 1 : (type==NSRightMouseUp ? 2 : 3);
  327. break;
  328. case NSMouseMoved:
  329. case NSLeftMouseDragged:
  330. case NSRightMouseDragged:
  331. case NSOtherMouseDragged:
  332. inView=mouseViewPos( view,&x,&y );
  333. setMouseView( inView ? view : 0,x,y,source );
  334. if( !inView && !capturedView ) return;
  335. ev=BBEVENT_MOUSEMOVE;
  336. data=(type==NSLeftMouseDragged) ? 1 : (type==NSRightMouseDragged ? 2 : (type==NSOtherMouseDragged ? 3 : 0));
  337. break;
  338. case NSScrollWheel:
  339. inView=mouseViewPos( view,&x,&y );
  340. if( !inView && view!=capturedView ) return;
  341. ev=BBEVENT_MOUSEWHEEL;
  342. f=[event deltaY];
  343. data=f>0 ? ceil(f) : floor(f);
  344. break;
  345. default:
  346. return;
  347. }
  348. bbSystemEmitEvent( ev,source,data,bbSystemTranslateMods(mods),x,y,&bbNullObject );
  349. }
  350. void bbSystemMoveMouse( int x,int y ){
  351. NSEvent *event;
  352. CGPoint cgPoint={x,y};
  353. CGSetLocalEventsSuppressionInterval(0.0);
  354. if( !CGDisplayIsCaptured(kCGDirectMainDisplay) ){
  355. NSPoint nsPoint={x,y};
  356. NSWindow *window=appMainWindow();
  357. if( !window ) return;
  358. nsPoint.y=[[window contentView] bounds].size.height-1-nsPoint.y;
  359. nsPoint=[window convertBaseToScreen:nsPoint];
  360. cgPoint.x=nsPoint.x;
  361. cgPoint.y=CGDisplayPixelsHigh(kCGDirectMainDisplay)-nsPoint.y;
  362. }
  363. CGDisplayMoveCursorToPoint( kCGDirectMainDisplay,cgPoint );
  364. bbSystemEmitEvent( BBEVENT_MOUSEMOVE,&bbNullObject,0,bbSystemTranslateMods(mods),x,y,&bbNullObject );
  365. }
  366. void bbSystemSetMouseVisible( int visible ){
  367. mouseVisible=visible;
  368. updateDisplayCaptured();
  369. updateMouseVisibility();
  370. }
  371. void bbSystemStartup(){
  372. anullEvent=[appDefEvent( -1,0,0 ) retain];
  373. distantPast=[[NSDate distantPast] retain];
  374. distantFuture=[[NSDate distantFuture] retain];
  375. appDelegate=[[BBSystemAppDelegate alloc] init];
  376. [NSApp setDelegate:appDelegate];
  377. }
  378. typedef int (*AlertPanel)(
  379. NSString *title,
  380. NSString *msg,
  381. NSString *defaultButton,
  382. NSString *alternateButton,
  383. NSString *otherButton );
  384. void bbSystemNotify( BBString *text,int serious ){
  385. AlertPanel panel=serious ? (void*)NSRunCriticalAlertPanel : (void*)NSRunAlertPanel;
  386. beginPanel();
  387. panel(
  388. appTitle(),
  389. tmpNSString(text),
  390. @"OK",0,0 );
  391. endPanel();
  392. }
  393. int bbSystemConfirm( BBString *text,int serious ){
  394. int n;
  395. AlertPanel panel=serious ? (void*)NSRunCriticalAlertPanel : (void*)NSRunAlertPanel;
  396. beginPanel();
  397. n=panel(
  398. appTitle(),
  399. tmpNSString(text),
  400. @"OK",@"Cancel",0 );
  401. endPanel();
  402. switch( n ){
  403. case NSAlertDefaultReturn:return 1;
  404. }
  405. return 0;
  406. }
  407. int bbSystemProceed( BBString *text,int serious ){
  408. int n;
  409. AlertPanel panel=serious ? (void*)NSRunCriticalAlertPanel : (void*)NSRunAlertPanel;
  410. beginPanel();
  411. n=panel(
  412. appTitle(),
  413. tmpNSString(text),
  414. @"Yes",@"No",@"Cancel" );
  415. endPanel();
  416. switch( n ){
  417. case NSAlertDefaultReturn:return 1;
  418. case NSAlertAlternateReturn:return 0;
  419. }
  420. return -1;
  421. }
  422. BBString *bbSystemRequestFile( BBString *title,BBString *exts,int save,BBString *file,BBString *dir ){
  423. NSString *nsdir=0;
  424. NSString *nsfile=0;
  425. NSString *nstitle=0;
  426. NSMutableArray *nsexts=0;
  427. BBString *str=&bbEmptyString;
  428. if( dir->length ){
  429. char tmp[PATH_MAX];
  430. char *p=bbStringToUTF8String( dir );
  431. realpath( p,tmp );
  432. bbMemFree(p);
  433. nsdir=[NSString stringWithUTF8String:tmp];
  434. }
  435. if( file->length ){
  436. nsfile=tmpNSString(file);
  437. }
  438. if( title->length ){
  439. nstitle=tmpNSString(title);
  440. }
  441. if( exts->length ){
  442. char *p=bbStringToUTF8String(exts),*t;
  443. nsexts=[NSMutableArray arrayWithCapacity:10];
  444. while( t=strchr(p,',') ){
  445. *t=0;
  446. [nsexts addObject:[NSString stringWithUTF8String:p]];
  447. p=t+1;
  448. }
  449. if( *p ) [nsexts addObject:[NSString stringWithUTF8String:p]];
  450. bbMemFree(p);
  451. }
  452. beginPanel();
  453. if( save ){
  454. NSSavePanel *panel=[NSSavePanel savePanel];
  455. if( nstitle ) [panel setTitle:nstitle];
  456. if( nsexts ){
  457. [panel setAllowedFileTypes:nsexts];
  458. [panel setAllowsOtherFileTypes:YES];
  459. }
  460. if( [panel runModalForDirectory:nsdir file:nsfile]==NSFileHandlingPanelOKButton ){
  461. str=stringFromNSString([panel filename]);
  462. }
  463. }else{
  464. NSOpenPanel *panel=[NSOpenPanel openPanel];
  465. if( nstitle ) [panel setTitle:nstitle];
  466. if( [panel runModalForDirectory:nsdir file:nsfile types:nsexts]==NSFileHandlingPanelOKButton ){
  467. str=stringFromNSString([panel filename]);
  468. }
  469. }
  470. endPanel();
  471. return str;
  472. }
  473. BBString *bbSystemRequestDir( BBString *title,BBString *dir ){
  474. NSString *nsdir=0;
  475. NSString *nstitle=0;
  476. NSOpenPanel *panel;
  477. BBString *str=&bbEmptyString;
  478. if( dir->length ){
  479. char tmp[PATH_MAX];
  480. char *p=bbStringToUTF8String(dir);
  481. realpath( p,tmp );
  482. bbMemFree(p);
  483. nsdir=[NSString stringWithUTF8String:tmp];
  484. }
  485. if( title->length ){
  486. nstitle=tmpNSString(title);
  487. }
  488. panel=[NSOpenPanel openPanel];
  489. [panel setCanChooseFiles:NO];
  490. [panel setCanChooseDirectories:YES];
  491. [panel setCanCreateDirectories:YES];
  492. if( title ) [panel setTitle:nstitle];
  493. beginPanel();
  494. if( [panel runModalForDirectory:nsdir file:0 types:0]==NSFileHandlingPanelOKButton ){
  495. str=stringFromNSString([panel filename]);
  496. }
  497. endPanel();
  498. return str;
  499. }
  500. int bbOpenURL( BBString *bburl ){
  501. NSURL *url;
  502. NSString *loc;
  503. int res=0;
  504. checkDisplay();
  505. loc=tmpNSString(bburl);
  506. url=[NSURL URLWithString:[loc stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
  507. if( url ) res=[[NSWorkspace sharedWorkspace] openURL:url];
  508. return res;
  509. }
  510. void bbSystemPostSyncOp( BBSyncOp syncOp,BBObject *syncInfo,size_t asyncRet ){
  511. AsyncOp *p=(AsyncOp*)malloc( sizeof(AsyncOp) );
  512. NSEvent *event=appDefEvent( BB_RESERVEDEVENTSUBTYPE1,(NSInteger)p,0 );
  513. p->asyncOp=0;
  514. p->asyncRet=asyncRet;
  515. p->syncOp=syncOp;
  516. p->syncInfo=syncInfo;
  517. [NSApp postEvent:event atStart:NO];
  518. }
  519. void bbSystemStartAsyncOp( BBAsyncOp asyncOp,int asyncInfo,BBSyncOp syncOp,BBObject *syncInfo ){
  520. AsyncOp *p=(AsyncOp*)malloc( sizeof( AsyncOp ) );
  521. NSEvent *event=appDefEvent( BB_RESERVEDEVENTSUBTYPE1,(NSInteger)p,0 );
  522. BBRETAIN( syncInfo );
  523. p->asyncOp=asyncOp;
  524. p->asyncInfo=asyncInfo;
  525. p->syncOp=syncOp;
  526. p->syncInfo=syncInfo;
  527. [NSThread detachNewThreadSelector:@selector(asyncOpThread:) toTarget:appDelegate withObject:event];
  528. }
  529. static NSScreen *DesktopScreen(){
  530. NSArray *screens;
  531. if( screens=[NSScreen screens] ){
  532. if( [screens count] ) return [screens objectAtIndex:0];
  533. }
  534. return 0;
  535. }
  536. int bbSystemDesktopWidth(){
  537. NSScreen *screen=DesktopScreen();
  538. if( screen ) return [screen frame].size.width;
  539. return 640;
  540. }
  541. int bbSystemDesktopHeight(){
  542. NSScreen *screen=DesktopScreen();
  543. if( screen ) return [screen frame].size.height;
  544. return 480;
  545. }
  546. int bbSystemDesktopDepth(){
  547. NSScreen *screen=DesktopScreen();
  548. if( screen ) return NSBitsPerPixelFromDepth( [screen depth] );
  549. return 32;
  550. }
  551. int bbSystemDesktopHertz(){
  552. return 60;
  553. }