Changeset 1449
- Timestamp:
- Nov 30, 2006, 11:41:52 PM (16 years ago)
- Location:
- libcaca/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
libcaca/trunk/caca/driver_cocoa.m
r1421 r1449 1 1 /* 2 2 * libcaca Colour ASCII-Art library 3 * Copyright (c) 2006 Olivier Gutknecht <olg@no-distance.net> 4 * 2006 Sam Hocevar <sam@zoy.org> 3 * Copyright (c) 2006 Colin Delacroix <colin@zoy.org> 5 4 * All Rights Reserved 6 5 * … … 22 21 #if defined USE_COCOA 23 22 24 #include <stdio.h> 25 #include <stdlib.h> 26 27 #import <Carbon/Carbon.h> 28 #include <Cocoa/Cocoa.h> 23 #import <Cocoa/Cocoa.h> 29 24 30 25 #include "caca.h" … … 33 28 #include "cucul_internals.h" 34 29 30 //#define COCOA_DEBUG 31 32 // many ways to draw the chars : 33 // - NSString and drawInRect:withAttributes: or drawWithRect:options:attributes: 34 // - NSAttributedString and drawInRect: or drawWithRect:options: 35 // - NSTextLayout and co. 36 // - Quartz 2D 37 // - ATSUI (more accessible from carbon) 38 // 2 firsts are high level cocoa, 3rd is low-level cocoa, other are untested 39 // also see http://www.cocoabuilder.com/archive/message/cocoa/2004/11/18/121928 40 // update: actually high-level is faster, so keep it like that 41 //#define USE_LOWLEVEL_COCOA 1 42 43 // build a complete color table cache for the view 44 #define PRECACHE_WHOLE_COLOR_TABLE 1 45 46 #define USE_RGB12_FGBG 1 47 48 //#define USE_GLOBAL_AUTORELEASE_POOL 1 49 50 #ifdef COCOA_DEBUG 51 #define debug_log NSLog 52 #else 53 #define debug_log(...) 54 #endif 55 56 #define NCOLORS 0x1000 57 58 static BOOL s_quit = NO; 59 static BOOL s_quitting = NO; 60 35 61 @interface CacaView : NSView 36 62 { 37 NSFont* _font; 38 NSRect _r; 39 int xx; 40 int h, w; 41 uint32_t *_attrs; 42 uint32_t *_chars; 43 CFMutableDictionaryRef _cache; 44 } 63 //NSFont* _font; 64 NSRect _font_rect; 65 unsigned int _h, _w; 66 uint32_t* _attrs; 67 uint32_t* _chars; 68 NSRect* _bkg_rects; 69 NSColor** _bkg_colors; 70 #ifdef PRECACHE_WHOLE_COLOR_TABLE 71 NSColor* _colorCache[NCOLORS]; 72 #else 73 NSMutableDictionary* _colorCache; 74 #endif 75 NSMutableDictionary* _attrDict; 76 NSMutableDictionary* _attrDictUnderline; // lame optim 77 #ifdef USE_LOWLEVEL_COCOA 78 NSTextStorage* _textStorage; 79 NSLayoutManager* _layoutManager; 80 NSTextContainer* _textContainer; 81 #endif 82 } 83 45 84 - (void)setFont:(NSFont *)aFont; 46 85 - (void)updateBuffersFromCaca:(caca_display_t *)dp; 47 48 86 @end 49 87 88 @interface NSColor(Caca) 89 + (NSColor *)colorFromRgb12:(uint16_t) ui_rgb12; 90 @end 91 50 92 @implementation CacaView 51 52 - (void)keyDown:(NSEvent *)theEvent53 {54 NSLog(@"key %@", theEvent);55 }56 57 - (void)mouseMoved:(NSEvent *)theEvent58 {59 NSLog(@"mouse %@", theEvent);60 }61 62 - (void)setupNewSize63 {64 int fw = _r.size.width;65 int fh = _r.size.height;66 w = [self bounds].size.width /fw;67 h = [self bounds].size.height / fh;68 // NSLog(@"W %f %f %f %d %f", [self bounds].size.width , _r.size.width, [self bounds].size.width / _r.size.width, w, [self bounds].size.width-(w*fw));69 // NSLog(@"H %f %f %f %d %f", [self bounds].size.height , _r.size.height, [self bounds].size.height / _r.size.height, h, [self bounds].size.height-(h*fh));70 }71 72 93 - (id)initWithFrame:(NSRect)frameRect 73 94 { 74 if((self = [super initWithFrame:frameRect]) != nil) { 75 [[self window] makeFirstResponder:self]; 76 } 95 self = [super initWithFrame:frameRect]; 96 if(!self) 97 return nil; 98 99 [[self window] makeFirstResponder:self]; 100 101 #ifdef PRECACHE_WHOLE_COLOR_TABLE 102 unsigned int i; 103 for(i = 0; i < NCOLORS; i++) 104 _colorCache[i] = [[NSColor colorFromRgb12:i] retain]; 105 #else 106 _colorCache = [[NSMutableDictionary alloc] initWithCapacity:NCOLORS]; 107 #endif 108 _attrDict = [[NSMutableDictionary alloc] initWithCapacity:3]; 109 _attrDictUnderline = [[NSMutableDictionary alloc] initWithCapacity:3]; 110 [_attrDictUnderline setObject:[NSNumber numberWithInt:NSUnderlineStyleSingle] 111 forKey:NSUnderlineStyleAttributeName]; 112 #ifdef USE_LOWLEVEL_COCOA 113 _textStorage = [[NSTextStorage alloc] init]; 114 _layoutManager = [[NSLayoutManager alloc] init]; 115 _textContainer = [[NSTextContainer alloc] init]; 116 [_textContainer setLineFragmentPadding:0.0]; 117 [_layoutManager addTextContainer:_textContainer]; 118 [_textStorage addLayoutManager:_layoutManager]; 119 #endif 120 77 121 return self; 78 122 } 79 123 80 - (NSFont *)font 81 { 82 return _font; 83 } 84 85 - (void)setFont:(NSFont *)aFont 86 { 87 [_font release]; 88 _font = [aFont retain]; 89 _r = [_font boundingRectForFont]; 90 _r = NSMakeRect(0, 0, ceilf(_r.size.width), ceilf(_r.size.height)); 91 [self setupNewSize]; 92 [aFont set]; 93 } 94 95 - (void)updateBuffersFromCaca:(caca_display_t *)dp 96 { 97 NSLog(@"update buffers"); 124 - (void)dealloc 125 { 126 //[_font release]; 127 #ifdef PRECACHE_WHOLE_COLOR_TABLE 128 unsigned short i; 129 for(i = 0; i < NCOLORS; i++) 130 [_colorCache[i] release]; 131 #else 132 [_colorCache release]; 133 #endif 134 [_attrDict release]; 135 [_attrDictUnderline release]; 136 #ifdef USE_LOWLEVEL_COCOA 137 [_textStorage release]; 138 [_layoutManager release]; 139 [_textContainer release]; 140 #endif 98 141 if(_attrs) 99 142 free(_attrs); 100 101 _attrs = malloc(dp->cv->width * dp->cv->height * sizeof(uint32_t) * 2); 102 _chars = _attrs + dp->cv->width * dp->cv->height; 103 memcpy(_attrs, dp->cv->attrs, dp->cv->width * dp->cv->height * sizeof(uint32_t)); 104 memcpy(_chars, dp->cv->chars, dp->cv->width * dp->cv->height * sizeof(uint32_t)); 105 106 w = dp->cv->width; 107 h = dp->cv->height; 108 109 [self setNeedsDisplay:TRUE]; 143 if(_bkg_rects) 144 free(_bkg_rects); 145 if(_bkg_colors) 146 free(_bkg_colors); 147 148 [super dealloc]; 149 } 150 151 // to accelerate the window drawing speed 152 - (BOOL)isOpaque 153 { 154 return YES; 155 } 156 157 - (BOOL)isFlipped 158 { 159 return YES; 160 } 161 162 - (void)setupNewSize 163 { 164 float fw = _font_rect.size.width; 165 float fh = _font_rect.size.height; 166 _w = ceilf([self bounds].size.width / fw); 167 _h = ceilf([self bounds].size.height / fh); 168 debug_log(@"fw=%f selfw=%f %u %f", fw, [self bounds].size.width, 169 _w, [self bounds].size.width-(_w*fw)); 170 debug_log(@"fh=%f selfh=%f %u %f", fh, [self bounds].size.height, 171 _h, [self bounds].size.height-(_h*fh)); 172 } 173 174 - (void)keyDown:(NSEvent *)theEvent 175 { 176 NSLog(@"key %@", theEvent); 177 } 178 179 - (void)mouseMoved:(NSEvent *)theEvent 180 { 181 NSLog(@"mouse %@", theEvent); 182 } 183 184 - (void)setFont:(NSFont *)aFont 185 { 186 //[_font release]; 187 //_font = [aFont retain]; 188 _font_rect = [aFont boundingRectForFont]; 189 _font_rect = NSMakeRect(0, 0, ceilf(_font_rect.size.width), ceilf(_font_rect.size.height)); 190 [self setupNewSize]; 191 [_attrDict setObject:aFont forKey:NSFontAttributeName]; 192 [_attrDictUnderline setObject:aFont forKey:NSFontAttributeName]; 193 [aFont set]; 194 } 195 196 - (void)resizeIfNeeded:(caca_display_t *)dp 197 { 198 if( _w != dp->cv->width || _h != dp->cv->height 199 || !_attrs || !_bkg_rects || !_bkg_colors) 200 { 201 debug_log(@"%s resize to %ux%u", _cmd, _w, _h); 202 203 _w = dp->cv->width; 204 _h = dp->cv->height; 205 206 if(_attrs) 207 free(_attrs); 208 _attrs = malloc(_w * _h * sizeof(uint32_t) * 2); 209 210 if(_bkg_rects) 211 free(_bkg_rects); 212 _bkg_rects = malloc(_w * _h * sizeof(NSRect)); 213 214 if(_bkg_colors) 215 free(_bkg_colors); 216 _bkg_colors = malloc(_w * _h * sizeof(NSColor*)); 217 218 [[self window] setContentSize: NSMakeSize(dp->cv->width * _font_rect.size.width, 219 dp->cv->height * _font_rect.size.height)]; 220 } 221 } 222 223 - (void)updateBuffersFromCaca:(caca_display_t *)dp 224 { 225 [self resizeIfNeeded:dp]; 226 227 if(_attrs) 228 { 229 _chars = _attrs + _w * _h; 230 memcpy(_attrs, dp->cv->attrs, _w * _h * sizeof(uint32_t)); 231 memcpy(_chars, dp->cv->chars, _w * _h * sizeof(uint32_t)); 232 233 [self setNeedsDisplay:TRUE]; 234 } 110 235 } 111 236 … … 113 238 { 114 239 //if([self inLiveResize]) [self setupNewSize]; 115 int x, y; 116 int fw = _r.size.width; 117 int fh = _r.size.height; 118 uint32_t *attrs = _attrs; 119 uint32_t *chars = _chars; 120 NSGraphicsContext* viewContext = [NSGraphicsContext currentContext]; 121 if(!attrs || !chars) 240 241 if(!_attrs || !_chars) 122 242 { 123 243 [[NSColor blueColor] set]; … … 125 245 return; 126 246 } 247 248 unsigned int x, y; 249 float fw = _font_rect.size.width; 250 float fh = _font_rect.size.height; 251 uint32_t* attrs; 252 uint32_t* chars = _chars; 253 254 /* first take care of the background */ 127 255 [[NSColor blackColor] set]; 128 256 NSRectFill(rect); 129 257 130 for(y = 0; y < h; y++) 131 { 132 for(x = 0; x < w; x++) 258 unsigned int arrayLength = 0; 259 for(y = 0; y < _h; y++) 260 { 261 unsigned int yoff = y * fh; 262 for(x = 0; x < _w; x++) 133 263 { 134 unichar c = *chars++; 135 uint8_t argb[8]; 136 _cucul_attr_to_argb4(*attrs++, argb); 137 138 /* FIXME: factorise this colour stuff */ 139 NSRect r = NSMakeRect(x * fw, y * fh, fw, fh); 140 [[NSColor colorWithDeviceRed: (float)argb[1] / 255.0 141 green: (float)argb[2] / 255.0 142 blue: (float)argb[3] / 255.0 143 alpha: 1.0] setFill]; 144 [[NSColor colorWithDeviceRed: (float)argb[5] / 255.0 145 green: (float)argb[6] / 255.0 146 blue: (float)argb[7] / 255.0 147 alpha: 1.0] setStroke]; 148 NSRectFill(r); 149 // NSLog(@"%d %d %C %d %d %@ %@ %@", x, y, c, fg, bg, NSStringFromRect(r), _colormap[fg], _colormap[bg]); 150 // [[NSString stringWithCharacters:&c length:1] drawInRect:r withAttributes:[NSDictionary dictionaryWithObject:_colormap[fg] forKey:NSForegroundColorAttributeName]]; 151 [[NSColor colorWithDeviceRed: (float)argb[5] / 255.0 152 green: (float)argb[6] / 255.0 153 blue: (float)argb[7] / 255.0 154 alpha: 1.0] setFill]; 155 [[NSColor colorWithDeviceRed: (float)argb[5] / 255.0 156 green: (float)argb[6] / 255.0 157 blue: (float)argb[7] / 255.0 158 alpha: 1.0] setStroke]; 159 [[NSString stringWithCharacters:&c length:1] drawInRect:r withAttributes:nil]; 160 // [[NSString stringWithCharacters:&c length:1] drawInRect:r withAttributes:[NSDictionary dictionaryWithObjectsAndKeys: 161 // _colormap[fg], NSForegroundColorAttributeName, _colormap[bg], NSBackgroundColorAttributeName, nil]]; 162 } 163 } 164 [NSGraphicsContext setCurrentContext:viewContext]; 165 } 264 NSRect r = NSMakeRect(x * fw, yoff, fw, fh); 265 if(NSIntersectsRect(r, rect)) 266 { 267 attrs = _attrs + x + y * _w; 268 NSColor* color = nil; 269 #if USE_RGB12_FGBG 270 uint16_t bg = _cucul_attr_to_rgb12bg(*attrs); 271 if(bg) 272 { 273 #ifdef PRECACHE_WHOLE_COLOR_TABLE 274 color = _colorCache[bg]; 275 #else 276 NSNumber* numberBg = [NSNumber numberWithInt:bg]; 277 color = [_colorCache objectForKey:numberBg]; 278 if(!color) 279 { 280 color = [NSColor colorFromRgb12:bg]; 281 if(color) 282 [_colorCache setObject:color forKey:numberBg]; 283 } 284 #endif 285 } 286 #else 287 uint8_t argb[8]; 288 _cucul_attr_to_argb4(*attrs, argb); 289 color = [NSColor colorWithCalibratedRed:((float)argb[1]) / 15.0 290 green:((float)argb[2]) / 15.0 291 blue:((float)argb[3]) / 15.0 292 alpha:1.0]; 293 #endif 294 if(color) 295 { 296 _bkg_colors[arrayLength] = color; 297 _bkg_rects[arrayLength++] = r; 298 } 299 } 300 } 301 } 302 NSRectFillListWithColors(_bkg_rects, _bkg_colors, arrayLength); 303 304 /* Then print the foreground characters */ 305 for(y = 0; y < _h; y++) 306 { 307 unsigned int yoff = y * fh; 308 for(x = 0; x < _w; x++, chars++) 309 { 310 attrs = _attrs + x + y * _w; 311 312 /* Skip spaces */ 313 if(*chars <= 0x00000020) 314 continue; 315 316 if(*chars == CUCUL_MAGIC_FULLWIDTH) 317 continue; 318 319 /* Plain ASCII, no problem. */ 320 // TODO: test me with wide chars 321 //if(*chars > 0x00000020 && *chars < 0x00000080) 322 { 323 NSRect r = NSMakeRect(x * fw + 1, yoff, fw - 1, fh); 324 if(NSIntersectsRect(r, rect)) 325 { 326 NSColor* color = nil; 327 #if USE_RGB12_FGBG 328 uint16_t fg = _cucul_attr_to_rgb12fg(*attrs); 329 #ifdef PRECACHE_WHOLE_COLOR_TABLE 330 color = _colorCache[fg]; 331 #else // PRECACHE_WHOLE_COLOR_TABLE 332 NSNumber* numberFg = [NSNumber numberWithInt:fg]; 333 color = [_colorCache objectForKey:numberFg]; 334 if(!color) 335 { 336 color = [NSColor colorFromRgb12:fg]; 337 if(color) 338 [_colorCache setObject:color forKey:numberFg]; 339 } 340 #endif // PRECACHE_WHOLE_COLOR_TABLE 341 #else // USE_RGB12_FGBG 342 uint8_t argb[8]; 343 _cucul_attr_to_argb4(*attrs, argb); 344 debug_log(@"x,y=[%d,%d] r,g,b back=[%u %u %u] front=[%u %u %u]", 345 x, y, argb[1], argb[2], argb[3], argb[5], argb[6], argb[7]); 346 color = [NSColor colorWithCalibratedRed:((float)argb[5]) / 15.0 347 green:((float)argb[6]) / 15.0 348 blue:((float)argb[7]) / 15.0 349 alpha:1.0]; 350 #endif // USE_RGB12_FGBG 351 352 if(color) 353 { 354 NSMutableDictionary* attrDict = (*attrs & CUCUL_UNDERLINE) ? 355 _attrDictUnderline : _attrDict; 356 [attrDict setObject:color forKey:NSForegroundColorAttributeName]; 357 358 unichar ch = *chars; 359 NSString* str = [[NSString alloc] initWithCharacters:&ch length:1]; 360 361 #ifdef USE_LOWLEVEL_COCOA 362 [[_textStorage mutableString] setString:str]; 363 [_textStorage setAttributes:attrDict range:NSMakeRange(0, 1)]; 364 [_layoutManager drawGlyphsForGlyphRange:NSMakeRange(0, 1) atPoint:r.origin]; 365 #else 366 [str drawInRect:r withAttributes:attrDict]; 367 #endif 368 [str release]; 369 } 370 } 371 continue; 372 } 373 } 374 } 375 } 376 166 377 @end 167 378 … … 169 380 { 170 381 NSWindow* window; 171 idview;172 NSFont* font; 382 CacaView* view; 383 #ifdef USE_GLOBAL_AUTORELEASE_POOL 173 384 NSAutoreleasePool* pool; 385 #endif 174 386 }; 175 387 176 177 //-------------------------------------------------------------------------------------------- 178 static OSStatus 179 AppEventHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon) 180 { 181 OSStatus result = eventNotHandledErr; 182 183 switch(GetEventClass(inEvent)) 184 { 185 case kEventClassCommand: 388 //============================================================================ 389 // NSApplication(Caca) 390 //============================================================================ 391 392 @implementation NSApplication(Caca) 393 - (void)setRunning 394 { 395 _running = 1; 396 } 397 @end 398 399 //============================================================================ 400 // NSColor(Caca) 401 //============================================================================ 402 403 @implementation NSColor(Caca) 404 + (NSColor *)colorFromRgb12:(uint16_t)ui_rgb12 405 { 406 float red = ((float)((ui_rgb12 & 0x0f00) >> 3)) / 15.0, 407 green = ((float)((ui_rgb12 & 0x00f0) >> 2)) / 15.0, 408 blue = ((float)( ui_rgb12 & 0x000f) ) / 15.0; 409 return [NSColor colorWithDeviceRed:red green:green 410 blue:blue alpha:1.0]; 411 } 412 @end 413 414 //============================================================================ 415 // CacaWindowDelegate 416 //============================================================================ 417 418 @interface CacaWindowDelegate : NSObject 419 @end 420 421 @implementation CacaWindowDelegate 422 - (BOOL)windowShouldClose:(id)sender 423 { 424 debug_log(@"%s", _cmd); 425 [NSApp terminate:self]; 426 return NO; 427 } 428 @end 429 430 //============================================================================ 431 // CacaAppDelegate 432 //============================================================================ 433 434 @interface CacaAppDelegate : NSObject 435 @end 436 437 @implementation CacaAppDelegate : NSObject 438 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender 439 { 440 s_quit = YES; 441 return NSTerminateCancel; 442 } 443 @end 444 445 /* setAppleMenu disappeared from the headers in 10.4 */ 446 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 447 @interface NSApplication(NSAppleMenu) 448 - (void)setAppleMenu:(NSMenu *)menu; 449 @end 450 #endif 451 452 //============================================================================ 453 // utility methods 454 //============================================================================ 455 456 static NSString* get_application_name() 457 { 458 NSString* appName = [[NSBundle mainBundle] objectForInfoDictionaryKey: 459 @"CFBundleName"]; 460 if(![appName length]) 461 appName = [[NSProcessInfo processInfo] processName]; 462 463 return appName; 464 } 465 466 static void create_application_menus() 467 { 468 /* Create the main menu bar */ 469 [NSApp setMainMenu:[[NSMenu alloc] init]]; 470 471 /* Create the application menu */ 472 NSString* appName = get_application_name(); 473 NSMenu* appleMenu = [[NSMenu alloc] initWithTitle:@""]; 474 475 /* Add menu items */ 476 NSString* title = [@"About " stringByAppendingString:appName]; 477 [appleMenu addItemWithTitle:title 478 action:@selector(orderFrontStandardAboutPanel:) 479 keyEquivalent:@""]; 480 [appleMenu addItem:[NSMenuItem separatorItem]]; 481 482 title = [@"Hide " stringByAppendingString:appName]; 483 [appleMenu addItemWithTitle:title action:@selector(hide:) 484 keyEquivalent:@"h"]; 485 486 id<NSMenuItem> menuItem = [appleMenu addItemWithTitle:@"Hide Others" 487 action:@selector(hideOtherApplications:) 488 keyEquivalent:@"h"]; 489 [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; 490 491 [appleMenu addItemWithTitle:@"Show All" 492 action:@selector(unhideAllApplications:) 493 keyEquivalent:@""]; 494 [appleMenu addItem:[NSMenuItem separatorItem]]; 495 496 title = [@"Quit " stringByAppendingString:appName]; 497 [appleMenu addItemWithTitle:title action:@selector(terminate:) 498 keyEquivalent:@"q"]; 499 500 /* Put menu into the menubar */ 501 menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; 502 [menuItem setSubmenu:appleMenu]; 503 [[NSApp mainMenu] addItem:menuItem]; 504 [menuItem release]; 505 506 /* Tell the application object that this is now the application menu */ 507 [NSApp setAppleMenu:appleMenu]; 508 [appleMenu release]; 509 510 /* Create the window menu */ 511 NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; 512 513 /* "Minimize" item */ 514 menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" 515 action:@selector(performMiniaturize:) 516 keyEquivalent:@"m"]; 517 [windowMenu addItem:menuItem]; 518 [menuItem release]; 519 520 /* Put menu into the menubar */ 521 menuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; 522 [menuItem setSubmenu:windowMenu]; 523 [[NSApp mainMenu] addItem:menuItem]; 524 [menuItem release]; 525 526 /* Tell the application object that this is now the window menu */ 527 [NSApp setWindowsMenu:windowMenu]; 528 [windowMenu release]; 529 } 530 531 static void register_cocoa_app(caca_display_t *dp) 532 { 533 ProcessSerialNumber psn; 534 if(!GetCurrentProcess(&psn)) 535 { 536 TransformProcessType(&psn, kProcessTransformToForegroundApplication); 537 SetFrontProcess(&psn); 538 } 539 540 if(NSApp == nil) 541 { 542 [NSApplication sharedApplication]; 543 544 if(![NSApp mainMenu]) 545 create_application_menus(); 546 547 [NSApp finishLaunching]; 548 } 549 550 if ([NSApp delegate] == nil) 551 [NSApp setDelegate:[[CacaAppDelegate alloc] init]]; 552 553 [NSApp setRunning]; 554 } 555 556 static __inline__ void convert_NSRect(NSRect *r) 557 { 558 float mb_height = 38.0; // [[NSApp mainMenu] menuBarHeight] is 0 - wtf ? 559 /*debug_log(@"%@ %f %f %d %d %d", [NSApp mainMenu], 560 [[NSApp mainMenu] menuBarHeight], mb_height, 561 (int)CGDisplayPixelsHigh(kCGDirectMainDisplay), 562 (int)r->origin.y, (int)r->size.height);*/ 563 r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - mb_height 564 - r->origin.y - r->size.height; 565 } 566 567 static void create_first_window(caca_display_t *dp) 568 { 569 NSFont* font = [NSFont fontWithName:@"Monaco" size:10]; 570 NSRect fontRect = [font boundingRectForFont]; 571 fontRect = NSMakeRect(0, 0, ceilf(fontRect.size.width), ceilf(fontRect.size.height)); 572 NSRect windowRect = NSMakeRect(20, 20, dp->cv->width * fontRect.size.width, 573 dp->cv->height * fontRect.size.height); 574 convert_NSRect(&windowRect); 575 576 CacaView* view = [[CacaView alloc] initWithFrame:windowRect]; 577 NSWindow* win = [[NSWindow alloc] initWithContentRect:windowRect 578 styleMask: NSTitledWindowMask 579 //| NSResizableWindowMask 580 | NSClosableWindowMask 581 | NSWindowMiniaturizeButton 582 backing:NSBackingStoreBuffered 583 defer:NO]; 584 585 NSString* appName = get_application_name(); 586 if(appName) 587 [win setTitle: appName]; 588 [win setDelegate:[CacaWindowDelegate new]]; 589 [win setContentView:view]; 590 [view setFont:font]; 591 [win makeKeyAndOrderFront:nil]; 592 593 dp->drv.p->window = win; 594 dp->drv.p->view = view; 595 } 596 597 static unsigned int get_caca_keycode(NSEvent* event) 598 { 599 unsigned int caca_keycode = 0; 600 /* 601 unsigned short mac_keycode = [event keyCode]; 602 debug_log(@"keycode %u (%x)", mac_keycode, mac_keycode); 603 switch(mac_keycode) 604 { 605 } 606 */ 607 if(/*!caca_keycode &&*/ ([event modifierFlags] & NSControlKeyMask)) 608 { 609 NSString *chars = [event charactersIgnoringModifiers]; 610 unichar ch = [chars characterAtIndex: 0]; 611 // CACA_KEY_CTRL_A -> CACA_KEY_CTRL_Z 612 if(ch >= 'a' && ch <= 'z') 613 caca_keycode = CACA_KEY_CTRL_A + ch - 'a'; 614 } 615 616 if(!caca_keycode) 617 { 618 NSString *chars = [event characters]; 619 unichar ch = 0; 620 if([chars length]) 621 ch = [chars characterAtIndex: 0]; 622 switch(ch) 186 623 { 187 HICommandExtended cmd; 188 verify_noerr(GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd)); 189 190 switch(GetEventKind(inEvent)) 191 { 192 case kEventCommandProcess: 193 switch(cmd.commandID) 194 { 195 default: 196 break; 197 } 198 break; 199 } 624 case NSUpArrowFunctionKey: 625 caca_keycode = CACA_KEY_UP; 626 break; 627 case NSDownArrowFunctionKey: 628 caca_keycode = CACA_KEY_DOWN; 629 break; 630 case NSLeftArrowFunctionKey: 631 caca_keycode = CACA_KEY_LEFT; 632 break; 633 case NSRightArrowFunctionKey: 634 caca_keycode = CACA_KEY_RIGHT; 635 break; 636 case 27: 637 caca_keycode = CACA_KEY_ESCAPE; 638 break; 639 case NSDeleteCharacter: 640 caca_keycode = CACA_KEY_DELETE; 641 break; 642 case NSBackspaceCharacter: 643 caca_keycode = CACA_KEY_BACKSPACE; 644 break; 645 case NSTabCharacter: 646 caca_keycode = CACA_KEY_TAB; 647 break; 648 case NSNewlineCharacter: 649 case NSCarriageReturnCharacter: 650 caca_keycode = CACA_KEY_RETURN; 651 break; 652 case NSPageUpFunctionKey: 653 caca_keycode = CACA_KEY_PAGEUP; 654 break; 655 case NSPageDownFunctionKey: 656 caca_keycode = CACA_KEY_PAGEDOWN; 657 break; 658 case NSF1FunctionKey: 659 caca_keycode = CACA_KEY_F1; 660 break; 661 case NSF2FunctionKey: 662 caca_keycode = CACA_KEY_F2; 663 break; 664 case NSF3FunctionKey: 665 caca_keycode = CACA_KEY_F3; 666 break; 667 case NSF4FunctionKey: 668 caca_keycode = CACA_KEY_F4; 669 break; 670 case NSF5FunctionKey: 671 caca_keycode = CACA_KEY_F5; 672 break; 673 case NSF6FunctionKey: 674 caca_keycode = CACA_KEY_F6; 675 break; 676 case NSF7FunctionKey: 677 caca_keycode = CACA_KEY_F7; 678 break; 679 case NSF8FunctionKey: 680 caca_keycode = CACA_KEY_F8; 681 break; 682 case NSF9FunctionKey: 683 caca_keycode = CACA_KEY_F9; 684 break; 685 case NSF10FunctionKey: 686 caca_keycode = CACA_KEY_F10; 687 break; 688 case NSF11FunctionKey: 689 caca_keycode = CACA_KEY_F11; 690 break; 691 case NSF12FunctionKey: 692 caca_keycode = CACA_KEY_F12; 693 break; 694 case NSF13FunctionKey: 695 caca_keycode = CACA_KEY_F13; 696 break; 697 case NSF14FunctionKey: 698 caca_keycode = CACA_KEY_F14; 699 break; 700 case NSF15FunctionKey: 701 caca_keycode = CACA_KEY_F15; 702 break; 703 case NSPauseFunctionKey: 704 caca_keycode = CACA_KEY_PAUSE; 705 break; 706 case NSInsertFunctionKey: 707 debug_log(@"insert key"); 708 caca_keycode = CACA_KEY_INSERT; 709 break; 710 case NSHomeFunctionKey: 711 caca_keycode = CACA_KEY_HOME; 712 break; 713 case NSEndFunctionKey: 714 caca_keycode = CACA_KEY_END; 715 break; 716 } 717 } 718 719 return caca_keycode; 720 } 721 722 static BOOL handle_key_event(struct caca_event *ev, NSEvent* event) 723 { 724 if(!ev || !event) 725 return NO; 726 727 BOOL eventHandled = NO; 728 729 if([event modifierFlags] & NSCommandKeyMask) 730 { 731 // let the system handle the Apple-commands for now 732 return NO; 733 } 734 735 switch ([event type]) { 736 case NSKeyDown: 737 /* test [event isARepeat] ? */ 738 ev->type = CACA_EVENT_KEY_PRESS; 739 break; 740 case NSKeyUp: 741 ev->type = CACA_EVENT_KEY_RELEASE; 742 break; 743 default: 744 ; 745 } 746 747 unsigned int caca_keycode = get_caca_keycode(event); 748 if(caca_keycode) 749 { 750 ev->data.key.ch = caca_keycode; 751 eventHandled = YES; 752 } 753 else 754 { 755 NSString *chars = [event characters]; 756 unichar mac_keycode = 0; 757 if([chars length]) 758 mac_keycode = [chars characterAtIndex: 0]; 759 if(mac_keycode) 760 { 761 ev->data.key.ch = mac_keycode; 762 ev->data.key.utf32 = (uint32_t)mac_keycode; 763 ev->data.key.utf8[0] = mac_keycode & 0x00ff; // FIXME: endianness 764 ev->data.key.utf8[1] = mac_keycode & 0xff00; 765 766 eventHandled = YES; 767 } 768 } 769 770 return eventHandled; 771 } 772 773 // TODO: handle CACA_EVENT_RESIZE 774 static BOOL handle_mouse_event(caca_display_t *dp, struct caca_event *ev, 775 NSEvent* event) 776 { 777 if(!ev || !event) 778 return NO; 779 780 switch ([event type]) { 781 case NSLeftMouseDown: 782 ev->type = CACA_EVENT_MOUSE_PRESS; 783 ev->data.mouse.button = 1; 784 break; 785 case NSLeftMouseUp: 786 ev->type = CACA_EVENT_MOUSE_RELEASE; 787 ev->data.mouse.button = 1; 788 break; 789 case NSRightMouseDown: 790 ev->type = CACA_EVENT_MOUSE_PRESS; 791 ev->data.mouse.button = 2; 792 break; 793 case NSRightMouseUp: 794 ev->type = CACA_EVENT_MOUSE_RELEASE; 795 ev->data.mouse.button = 2; 796 break; 797 case NSMouseMoved: 798 { 799 NSPoint mouseLoc = [NSEvent mouseLocation]; 800 unsigned int mouse_x = round(mouseLoc.x); 801 unsigned int mouse_y = round(mouseLoc.y); 802 if(dp->mouse.x == mouse_x && dp->mouse.y == mouse_y) 803 break; 804 805 dp->mouse.x = mouse_x; 806 dp->mouse.y = mouse_y; 807 808 ev->type = CACA_EVENT_MOUSE_MOTION; 809 ev->data.mouse.x = dp->mouse.x; 810 ev->data.mouse.y = dp->mouse.y; 200 811 break; 201 812 } 202 203 813 default: 204 break; 205 } 206 207 return result; 208 } 209 210 211 static OSStatus 212 WindowEventHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon) 213 { 214 OSStatus err = eventNotHandledErr; 215 216 switch(GetEventClass(inEvent)) 217 { 218 case kEventClassCommand: 219 { 220 HICommandExtended cmd; 221 verify_noerr(GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd)); 222 223 switch(GetEventKind(inEvent)) 224 { 225 case kEventCommandProcess: 226 switch(cmd.commandID) 227 { 228 // Add your own command-handling cases here 229 default: 230 break; 231 } 232 break; 233 } 234 break; 235 } 236 237 default: 238 break; 239 } 240 241 return err; 242 } 814 ; 815 } 816 817 return YES; 818 } 819 820 //============================================================================ 821 // caca driver methods 822 //============================================================================ 823 243 824 static int cocoa_init_graphics(caca_display_t *dp) 244 825 { 245 int i; 826 debug_log(@"%s dp->cv: %ux%u", __PRETTY_FUNCTION__, 827 dp->cv->width, dp->cv->height); 828 829 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 246 830 247 831 dp->drv.p = malloc(sizeof(struct driver_private)); … … 249 833 return -1; 250 834 251 Handle aHand = GetNewMBar(128); 252 SetMenuBar(aHand); 253 MenuHandle menu = GetMenuHandle(128); 254 CreateStandardWindowMenu(0, &menu); 255 InsertMenu(menu, 0); 256 257 DrawMenuBar(); 258 DisposeHandle(aHand); 259 260 NSAutoreleasePool* p = [[NSAutoreleasePool alloc] init]; 261 // [NSApplication sharedApplication]; 262 NSApplicationLoad(); 263 264 NSLog(@"Start"); 265 266 NSFont* f = [NSFont fontWithName:@"Monaco" size:10]; 267 NSRect r = [f boundingRectForFont]; 268 269 NSRect windowRect = NSMakeRect(0, 0, dp->cv->width * r.size.width, 270 dp->cv->height * r.size.height); 271 CacaView* v = [[[CacaView alloc] initWithFrame:windowRect] autorelease]; 272 273 // [NSApp setMainMenu:[[[NSMenu alloc] initWithTitle:@"Caca"] autorelease]]; 274 //[NSApp setAppleMenu:[[[NSMenu alloc] initWithTitle:@"ca"] autorelease]]; 275 //[NSApp setDelegate:v]; 276 277 NSWindow* w = [[NSWindow alloc] 278 initWithContentRect:windowRect 279 styleMask:NSTitledWindowMask 280 |NSResizableWindowMask 281 |NSClosableWindowMask 282 |NSWindowMiniaturizeButton 283 backing:NSBackingStoreBuffered 284 defer:NO]; 285 [w setContentView:v]; 286 [v setFont:f]; 287 [v setupNewSize]; 288 [w setFrameTopLeftPoint:NSMakePoint(650, 650)]; 289 [w makeKeyAndOrderFront:w]; 290 [w setLevel:NSFloatingWindowLevel]; 291 [w orderFrontRegardless]; 292 293 dp->drv.p->window = w; 294 dp->drv.p->view = v; 295 dp->drv.p->font = f; 296 dp->drv.p->pool = p; 297 298 // NSLog(@"update4 %d %d", w, h); 299 // _cucul_set_size(dp->cv, windowRect.size.width, windowRect.size.height); 300 OSStatus err; 301 static const EventTypeSpec kAppEvents[] = 302 { 303 { kEventClassCommand, kEventCommandProcess } 304 }; 305 InstallApplicationEventHandler(NewEventHandlerUPP(AppEventHandler), 306 GetEventTypeCount(kAppEvents), kAppEvents, 307 0, NULL); 308 NSLog(@"a"); 309 /* Should not be run here, should it? */ 310 RunApplicationEventLoop(); 311 NSLog(@"ab"); 835 unsigned int width = dp->cv->width, height = dp->cv->height; 836 _cucul_set_canvas_size(dp->cv, width ? width : 80, height ? height : 32); 837 838 // first create a full cocoa app if the host has no bundle 839 if(![[NSBundle mainBundle] bundleIdentifier]) 840 register_cocoa_app(dp); 841 create_first_window(dp); 842 843 #ifdef USE_GLOBAL_AUTORELEASE_POOL 844 dp->drv.p->pool = pool; 845 #else 846 [pool release]; 847 #endif 848 312 849 return 0; 313 850 } 314 851 852 static int cocoa_end_graphics(caca_display_t *dp) 853 { 854 debug_log(@"%s dp->cv: %ux%u", __PRETTY_FUNCTION__, 855 dp->cv->width, dp->cv->height); 856 857 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 858 [dp->drv.p->window close]; 859 CacaWindowDelegate* delegate = [dp->drv.p->window delegate]; 860 [dp->drv.p->window setDelegate:nil]; 861 [delegate release]; 862 // don't release the window yourself 863 //[dp->drv.p->window release]; 864 #ifdef USE_GLOBAL_AUTORELEASE_POOL 865 [dp->drv.p->pool release]; 866 #endif 867 free(dp->drv.p); 868 debug_log(@"%s end", __PRETTY_FUNCTION__); 869 [pool release]; 870 871 return 0; 872 } 315 873 316 874 static void cocoa_display(caca_display_t *dp) 317 875 { 318 //NSLog(@"display1");876 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 319 877 [dp->drv.p->view updateBuffersFromCaca:dp]; 320 #if 1 321 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate date]]; 322 #else 323 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[[NSCalendarDate date] 324 dateByAddingYears:0 months:(int)0 days:(int)0 hours:(int)0 minutes:(int)0 seconds:(int)5]]; 325 #endif 326 //NSLog(@"display2"); 878 [pool release]; 879 } 880 881 static int cocoa_get_event(caca_display_t *dp, struct caca_event *ev) 882 { 883 if(s_quit) 884 { 885 if(s_quitting) 886 { 887 // host app isn't handling the quit event properly, aborting 888 debug_log(@"duplicate quit event, aborting."); 889 abort(); 890 } 891 debug_log(@"posting quit event."); 892 ev->type = CACA_EVENT_QUIT; 893 s_quitting = YES; 894 return 1; 895 } 896 897 BOOL eventHandled = NO, forceRedispatch = NO; 898 ev->type = CACA_EVENT_NONE; 899 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 900 901 if([NSApp isRunning]) 902 { 903 NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask 904 untilDate:[NSDate distantPast] 905 inMode:NSDefaultRunLoopMode 906 dequeue:YES]; 907 if(event) 908 { 909 switch([event type]) 910 { 911 case NSKeyDown: 912 case NSKeyUp: 913 eventHandled = handle_key_event(ev, event); 914 break; 915 916 case NSFlagsChanged: 917 break; 918 919 case NSLeftMouseDown: 920 case NSLeftMouseUp: 921 case NSRightMouseDown: 922 case NSRightMouseUp: 923 case NSMouseMoved: 924 if([NSApp isActive]) 925 { 926 eventHandled = handle_mouse_event(dp, ev, event); 927 forceRedispatch = YES; 928 } 929 else 930 { 931 [NSApp sendEvent:event]; 932 eventHandled = YES; 933 } 934 break; 935 936 default: 937 ; 938 } 939 940 if(!eventHandled || forceRedispatch) 941 [NSApp sendEvent:event]; 942 } 943 } 944 [pool release]; 945 946 if(eventHandled) 947 return 1; 948 949 return 0; 327 950 } 328 951 329 952 static void cocoa_handle_resize(caca_display_t *dp) 330 953 { 954 debug_log(@"%s", __PRETTY_FUNCTION__); 331 955 dp->resize.w = dp->cv->width; 332 956 dp->resize.h = dp->cv->height; 333 957 } 334 958 335 static int cocoa_ get_event(caca_display_t *dp, struct caca_event *ev)336 { 337 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode338 beforeDate:[NSDate date]];339 ev->type = CACA_EVENT_NONE;959 static int cocoa_set_display_title(caca_display_t *dp, char const *title) 960 { 961 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 962 [dp->drv.p->window setTitle:[NSString stringWithUTF8String:title]]; 963 [pool release]; 340 964 return 0; 341 965 } 342 966 343 static int cocoa_set_display_title(caca_display_t *dp, char const *title)344 {345 [dp->drv.p->window setTitle:[NSString stringWithUTF8String:title]];346 return 0;347 }348 349 967 static unsigned int cocoa_get_display_width(caca_display_t *dp) 350 968 { … … 359 977 static void cocoa_set_mouse(caca_display_t *dp, int flag) 360 978 { 979 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 361 980 if(flag) 362 981 [[NSCursor arrowCursor] set]; … … 364 983 [[NSCursor disappearingItemCursor] set]; 365 984 } 366 } 367 368 static int cocoa_end_graphics(caca_display_t *dp) 369 { 370 [dp->drv.p->window close]; 371 [dp->drv.p->window release]; 372 [dp->drv.p->pool release]; 373 [dp->drv.p->font release]; 374 free(dp->drv.p); 375 return 0; 985 [pool release]; 376 986 } 377 987 … … 398 1008 399 1009 #endif /* USE_COCOA */ 400 -
libcaca/trunk/configure.ac
r1439 r1449 17 17 AC_PROG_CXXCPP 18 18 _AM_DEPENDENCIES([OBJC]) 19 OBJC="${C XX}"19 OBJC="${CC}" 20 20 AC_SUBST(OBJC) 21 21 AC_SUBST(OBJCFLAGS) … … 200 200 if test "${enable_cocoa}" != "no"; then 201 201 ac_cv_my_have_cocoa="no" 202 AC_LANG_PUSH(C++)203 savedCPPFLAGS="${CPPFLAGS}"204 CPPFLAGS="${CPPFLAGS} -ObjC"205 202 AC_CHECK_HEADERS(Cocoa/Cocoa.h, 206 203 [ac_cv_my_have_cocoa="yes"]) 207 204 if test "${ac_cv_my_have_cocoa}" = "yes"; then 205 case x${target} in 206 xpowerpc*darwin*) 207 # 10.3 needed to link with X11 208 MACOSX_SDK=/Developer/SDKs/MacOSX10.3.9.sdk 209 GCC_VERSION=3.3 210 ARCH="-arch ppc" 211 MACOSX_SDK_CFLAGS="-nostdinc -isystem ${MACOSX_SDK}/usr/include/gcc/darwin/${GCC_VERSION} -isystem ${MACOSX_SDK}/usr/include" 212 MACOSX_SDK_CXXFLAGS="-nostdinc++ -I${MACOSX_SDK}/usr/include/gcc/darwin/${GCC_VERSION}/c++ -I${MACOSX_SDK}/usr/include/gcc/darwin/${GCC_VERSION}/c++/ppc-darwin -I${MACOSX_SDK}/usr/include/gcc/darwin/${GCC_VERSION}/c++/backward" 213 MACOSX_SDK_LDFLAGS="-L${MACOSX_SDK}/usr/lib/gcc/darwin -L${MACOSX_SDK}/usr/lib/gcc/darwin/${GCC_VERSION} -L${MACOSX_SDK}/usr/lib" 214 ;; 215 x*86*darwin*) 216 MACOSX_SDK=/Developer/SDKs/MacOSX10.4u.sdk 217 GCC_VERSION=4.0 218 ARCH="-arch i386" 219 MACOSX_SDK_CFLAGS="-isysroot ${MACOSX_SDK}" 220 MACOSX_SDK_CXXFLAGS="${MACOSX_SDK_CFLAGS}" 221 ;; 222 esac 223 CC=gcc-${GCC_VERSION} 224 CXX=g++-${GCC_VERSION} 225 MACOSX_SDK_FRAMEWORKS="-F${MACOSX_SDK}/System/Library/Frameworks" 226 CPPFLAGS="${CPPFLAGS} ${ARCH} ${MACOSX_SDK_FRAMEWORKS}" 227 CFLAGS="${CFLAGS} ${MACOSX_SDK_CFLAGS}" 228 CXXFLAGS="${CXXFLAGS} ${MACOSX_SDK_CXXFLAGS}" 229 OBJCFLAGS="${OBJCFLAGS} ${MACOSX_SDK_CFLAGS}" 230 LDFLAGS="${ARCH} ${MACOSX_SDK_LDFLAGS} ${LDFLAGS}" 208 231 AC_DEFINE(USE_COCOA, 1, Define to 1 to activate the Cocoa backend driver) 209 CACA_LIBS="${CACA_LIBS} -Wl,- framework,Carbon,-framework,Cocoa"232 CACA_LIBS="${CACA_LIBS} -Wl,-syslibroot,${MACOSX_SDK},-framework,Cocoa" 210 233 CACA_DRIVERS="${CACA_DRIVERS} cocoa" 211 234 elif test "${enable_cocoa}" = "yes"; then 212 235 AC_MSG_ERROR([cannot find Cocoa development files]) 213 236 fi 214 CPPFLAGS="${savedCPPFLAGS}"215 AC_LANG_POP(C++)216 237 fi 217 238 AM_CONDITIONAL(USE_COCOA, test "${ac_cv_my_have_cocoa}" = "yes") … … 287 308 # Code qui fait des warnings == code de porc == deux baffes dans ta gueule 288 309 # [Jylam] Removed -Wshadow in order to avoid ncurses/gl conflict 289 # (Comme quoi on est pas les seuls porcs)310 # (Comme quoi on n'est pas les seuls porcs) 290 311 CFLAGS="${CFLAGS} -Wall -Wpointer-arith -Wcast-align -Wcast-qual -Wstrict-prototypes -Wshadow -Waggregate-return -Wmissing-prototypes -Wnested-externs -Wsign-compare" 291 312
Note: See TracChangeset
for help on using the changeset viewer.