summary refs log tree commit diff stats
path: root/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m
diff options
context:
space:<
connections {
  from_room: "Daedalus Extension"
  to_room: "Main Area"
  door { name: "Gallery Extension" }
}
connections {
  from_room: "Main Area"
  to_room: "Back Room"
  door { name: "Back Door" }
}
connections {
  from_room: "Back Room"
  to_room: "Ending"
  door { name: "Ending Door" }
}
es or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26// Only compile this code on Mac. These files should not be included on your iOS project. 27// But in case they are included, it won't be compiled. 28#import <Availability.h> 29#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED 30#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) 31 32#import "CCEventDispatcher.h" 33#import "../../ccConfig.h" 34 35static CCEventDispatcher *sharedDispatcher = nil; 36 37enum { 38 // mouse 39 kCCImplementsMouseDown = 1 << 0, 40 kCCImplementsMouseMoved = 1 << 1, 41 kCCImplementsMouseDragged = 1 << 2, 42 kCCImplementsMouseUp = 1 << 3, 43 kCCImplementsRightMouseDown = 1 << 4, 44 kCCImplementsRightMouseDragged = 1 << 5, 45 kCCImplementsRightMouseUp = 1 << 6, 46 kCCImplementsOtherMouseDown = 1 << 7, 47 kCCImplementsOtherMouseDragged = 1 << 8, 48 kCCImplementsOtherMouseUp = 1 << 9, 49 kCCImplementsScrollWheel = 1 << 10, 50 kCCImplementsMouseEntered = 1 << 11, 51 kCCImplementsMouseExited = 1 << 12, 52 53 kCCImplementsTouchesBegan = 1 << 13, 54 kCCImplementsTouchesMoved = 1 << 14, 55 kCCImplementsTouchesEnded = 1 << 15, 56 kCCImplementsTouchesCancelled = 1 << 16, 57 58 // keyboard 59 kCCImplementsKeyUp = 1 << 0, 60 kCCImplementsKeyDown = 1 << 1, 61 kCCImplementsFlagsChanged = 1 << 2, 62}; 63 64 65typedef struct _listEntry 66{ 67 struct _listEntry *prev, *next; 68 id delegate; 69 NSInteger priority; 70 NSUInteger flags; 71} tListEntry; 72 73 74#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD 75 76#define QUEUE_EVENT_MAX 128 77struct _eventQueue { 78 SEL selector; 79 NSEvent *event; 80}; 81 82static struct _eventQueue eventQueue[QUEUE_EVENT_MAX]; 83static int eventQueueCount; 84 85#endif // CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD 86 87 88@implementation CCEventDispatcher 89 90@synthesize dispatchEvents=dispatchEvents_; 91 92 93+(CCEventDispatcher*) sharedDispatcher 94{ 95 @synchronized(self) { 96 if (sharedDispatcher == nil) 97 sharedDispatcher = [[self alloc] init]; // assignment not done here 98 } 99 return sharedDispatcher; 100} 101 102+(id) allocWithZone:(NSZone *)zone 103{ 104 @synchronized(self) { 105 NSAssert(sharedDispatcher == nil, @"Attempted to allocate a second instance of a singleton."); 106 return [super allocWithZone:zone]; 107 } 108 return nil; // on subsequent allocation attempts return nil 109} 110 111-(id) init 112{ 113 if( (self = [super init]) ) 114 { 115 // events enabled by default 116 dispatchEvents_ = YES; 117 118 // delegates 119 keyboardDelegates_ = NULL; 120 mouseDelegates_ = NULL; 121 touchDelegates_ = NULL; 122 123#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD 124 eventQueueCount = 0; 125#endif 126 } 127 128 return self; 129} 130 131- (void) dealloc 132{ 133 [super dealloc]; 134} 135 136#pragma mark CCEventDispatcher - add / remove delegates 137 138-(void) addDelegate:(id)delegate priority:(NSInteger)priority flags:(NSUInteger)flags list:(tListEntry**)list 139{ 140 tListEntry *listElement = malloc( sizeof(*listElement) ); 141 142 listElement->delegate = [delegate retain]; 143 listElement->priority = priority; 144 listElement->flags = flags; 145 listElement->next = listElement->prev = NULL; 146 147 // empty list ? 148 if( ! *list ) { 149 DL_APPEND( *list, listElement ); 150 151 } else { 152 BOOL added = NO; 153 154 for( tListEntry *elem = *list; elem ; elem = elem->next ) { 155 if( priority < elem->priority ) { 156 157 if( elem == *list ) 158 DL_PREPEND(*list, listElement); 159 else { 160 listElement->next = elem; 161 listElement->prev = elem->prev; 162 163 elem->prev->next = listElement; 164 elem->prev = listElement; 165 } 166 167 added = YES; 168 break; 169 } 170 } 171 172 // Not added? priority has the higher value. Append it. 173 if( !added ) 174 DL_APPEND(*list, listElement); 175 } 176} 177 178-(void) removeDelegate:(id)delegate fromList:(tListEntry**)list 179{ 180 tListEntry *entry, *tmp; 181 182 // updates with priority < 0 183 DL_FOREACH_SAFE( *list, entry, tmp ) { 184 if( entry->delegate == delegate ) { 185 DL_DELETE( *list, entry ); 186 [delegate release]; 187 free(entry); 188 break; 189 } 190 } 191} 192 193-(void) removeAllDelegatesFromList:(tListEntry**)list 194{ 195 tListEntry *entry, *tmp; 196 197 DL_FOREACH_SAFE( *list, entry, tmp ) { 198 DL_DELETE( *list, entry ); 199 free(entry); 200 } 201} 202 203 204-(void) addMouseDelegate:(id<CCMouseEventDelegate>) delegate priority:(NSInteger)priority 205{ 206 NSUInteger flags = 0; 207 208 flags |= ( [delegate respondsToSelector:@selector(ccMouseDown:)] ? kCCImplementsMouseDown : 0 ); 209 flags |= ( [delegate respondsToSelector:@selector(ccMouseDragged:)] ? kCCImplementsMouseDragged : 0 ); 210 flags |= ( [delegate respondsToSelector:@selector(ccMouseMoved:)] ? kCCImplementsMouseMoved : 0 ); 211 flags |= ( [delegate respondsToSelector:@selector(ccMouseUp:)] ? kCCImplementsMouseUp : 0 ); 212 213 flags |= ( [delegate respondsToSelector:@selector(ccRightMouseDown:)] ? kCCImplementsRightMouseDown : 0 ); 214 flags |= ( [delegate respondsToSelector:@selector(ccRightMouseDragged:)] ? kCCImplementsRightMouseDragged : 0 ); 215 flags |= ( [delegate respondsToSelector:@selector(ccRightMouseUp:)] ? kCCImplementsRightMouseUp : 0 ); 216 217 flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseDown:)] ? kCCImplementsOtherMouseDown : 0 ); 218 flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseDragged:)] ? kCCImplementsOtherMouseDragged : 0 ); 219 flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseUp:)] ? kCCImplementsOtherMouseUp : 0 ); 220 221 flags |= ( [delegate respondsToSelector:@selector(ccMouseEntered:)] ? kCCImplementsMouseEntered : 0 ); 222 flags |= ( [delegate respondsToSelector:@selector(ccMouseExited:)] ? kCCImplementsMouseExited : 0 ); 223 224 flags |= ( [delegate respondsToSelector:@selector(ccScrollWheel:)] ? kCCImplementsScrollWheel : 0 ); 225 226 [self addDelegate:delegate priority:priority flags:flags list:&mouseDelegates_]; 227} 228 229-(void) removeMouseDelegate:(id) delegate 230{ 231 [self removeDelegate:delegate fromList:&mouseDelegates_]; 232} 233 234-(void) removeAllMouseDelegates 235{ 236 [self removeAllDelegatesFromList:&mouseDelegates_]; 237} 238 239-(void) addKeyboardDelegate:(id<CCKeyboardEventDelegate>) delegate priority:(NSInteger)priority 240{ 241 NSUInteger flags = 0; 242 243 flags |= ( [delegate respondsToSelector:@selector(ccKeyUp:)] ? kCCImplementsKeyUp : 0 ); 244 flags |= ( [delegate respondsToSelector:@selector(ccKeyDown:)] ? kCCImplementsKeyDown : 0 ); 245 flags |= ( [delegate respondsToSelector:@selector(ccFlagsChanged:)] ? kCCImplementsFlagsChanged : 0 ); 246 247 [self addDelegate:delegate priority:priority flags:flags list:&keyboardDelegates_]; 248} 249 250-(void) removeKeyboardDelegate:(id) delegate 251{ 252 [self removeDelegate:delegate fromList:&keyboardDelegates_]; 253} 254 255-(void) removeAllKeyboardDelegates 256{ 257 [self removeAllDelegatesFromList:&keyboardDelegates_]; 258} 259 260-(void) addTouchDelegate:(id<CCTouchEventDelegate>) delegate priority:(NSInteger)priority 261{ 262 NSUInteger flags = 0; 263 264 flags |= ( [delegate respondsToSelector:@selector(ccTouchesBeganWithEvent:)] ? kCCImplementsTouchesBegan : 0 ); 265 flags |= ( [delegate respondsToSelector:@selector(ccTouchesMovedWithEvent:)] ? kCCImplementsTouchesMoved : 0 ); 266 flags |= ( [delegate respondsToSelector:@selector(ccTouchesEndedWithEvent:)] ? kCCImplementsTouchesEnded : 0 ); 267 flags |= ( [delegate respondsToSelector:@selector(ccTouchesCancelledWithEvent:)] ? kCCImplementsTouchesCancelled : 0 ); 268 269 [self addDelegate:delegate priority:priority flags:flags list:&touchDelegates_]; 270} 271 272-(void) removeTouchDelegate:(id) delegate 273{ 274 [self removeDelegate:delegate fromList:&touchDelegates_]; 275} 276 277-(void) removeAllTouchDelegates 278{ 279 [self removeAllDelegatesFromList:&touchDelegates_]; 280} 281 282 283#pragma mark CCEventDispatcher - Mouse events 284// 285// Mouse events 286// 287 288// 289// Left 290// 291- (void)mouseDown:(NSEvent *)event 292{ 293 if( dispatchEvents_ ) { 294 tListEntry *entry, *tmp; 295 296 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 297 if ( entry->flags & kCCImplementsMouseDown ) { 298 void *swallows = [entry->delegate performSelector:@selector(ccMouseDown:) withObject:event]; 299 if( swallows ) 300 break; 301 } 302 } 303 } 304} 305 306- (void)mouseMoved:(NSEvent *)event 307{ 308 if( dispatchEvents_ ) { 309 tListEntry *entry, *tmp; 310 311 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 312 if ( entry->flags & kCCImplementsMouseMoved ) { 313 void *swallows = [entry->delegate performSelector:@selector(ccMouseMoved:) withObject:event]; 314 if( swallows ) 315 break; 316 } 317 } 318 } 319} 320 321- (void)mouseDragged:(NSEvent *)event 322{ 323 if( dispatchEvents_ ) { 324 tListEntry *entry, *tmp; 325 326 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 327 if ( entry->flags & kCCImplementsMouseDragged ) { 328 void *swallows = [entry->delegate performSelector:@selector(ccMouseDragged:) withObject:event]; 329 if( swallows ) 330 break; 331 } 332 } 333 } 334} 335 336- (void)mouseUp:(NSEvent *)event 337{ 338 if( dispatchEvents_ ) { 339 tListEntry *entry, *tmp; 340 341 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 342 if ( entry->flags & kCCImplementsMouseUp ) { 343 void *swallows = [entry->delegate performSelector:@selector(ccMouseUp:) withObject:event]; 344 if( swallows ) 345 break; 346 } 347 } 348 } 349} 350 351// 352// Mouse Right 353// 354- (void)rightMouseDown:(NSEvent *)event 355{ 356 if( dispatchEvents_ ) { 357 tListEntry *entry, *tmp; 358 359 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 360 if ( entry->flags & kCCImplementsRightMouseDown ) { 361 void *swallows = [entry->delegate performSelector:@selector(ccRightMouseDown:) withObject:event]; 362 if( swallows ) 363 break; 364 } 365 } 366 } 367} 368 369- (void)rightMouseDragged:(NSEvent *)event 370{ 371 if( dispatchEvents_ ) { 372 tListEntry *entry, *tmp; 373 374 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 375 if ( entry->flags & kCCImplementsRightMouseDragged ) { 376 void *swallows = [entry->delegate performSelector:@selector(ccRightMouseDragged:) withObject:event]; 377 if( swallows ) 378 break; 379 } 380 } 381 } 382} 383 384- (void)rightMouseUp:(NSEvent *)event 385{ 386 if( dispatchEvents_ ) { 387 tListEntry *entry, *tmp; 388 389 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 390 if ( entry->flags & kCCImplementsRightMouseUp ) { 391 void *swallows = [entry->delegate performSelector:@selector(ccRightMouseUp:) withObject:event]; 392 if( swallows ) 393 break; 394 } 395 } 396 } 397} 398 399// 400// Mouse Other 401// 402- (void)otherMouseDown:(NSEvent *)event 403{ 404 if( dispatchEvents_ ) { 405 tListEntry *entry, *tmp; 406 407 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 408 if ( entry->flags & kCCImplementsOtherMouseDown ) { 409 void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseDown:) withObject:event]; 410 if( swallows ) 411 break; 412 } 413 } 414 } 415} 416 417- (void)otherMouseDragged:(NSEvent *)event 418{ 419 if( dispatchEvents_ ) { 420 tListEntry *entry, *tmp; 421 422 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 423 if ( entry->flags & kCCImplementsOtherMouseDragged ) { 424 void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseDragged:) withObject:event]; 425 if( swallows ) 426 break; 427 } 428 } 429 } 430} 431 432- (void)otherMouseUp:(NSEvent *)event 433{ 434 if( dispatchEvents_ ) { 435 tListEntry *entry, *tmp; 436 437 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 438 if ( entry->flags & kCCImplementsOtherMouseUp ) { 439 void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseUp:) withObject:event]; 440 if( swallows ) 441 break; 442 } 443 } 444 } 445} 446 447// 448// Scroll Wheel 449// 450- (void)scrollWheel:(NSEvent *)event 451{ 452 if( dispatchEvents_ ) { 453 tListEntry *entry, *tmp; 454 455 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 456 if ( entry->flags & kCCImplementsScrollWheel ) { 457 void *swallows = [entry->delegate performSelector:@selector(ccScrollWheel:) withObject:event]; 458 if( swallows ) 459 break; 460 } 461 } 462 } 463} 464 465// 466// Mouse enter / exit 467- (void)mouseExited:(NSEvent *)event 468{ 469 if( dispatchEvents_ ) { 470 tListEntry *entry, *tmp; 471 472 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 473 if ( entry->flags & kCCImplementsMouseEntered ) { 474 void *swallows = [entry->delegate performSelector:@selector(ccMouseEntered:) withObject:event]; 475 if( swallows ) 476 break; 477 } 478 } 479 } 480} 481 482- (void)mouseEntered:(NSEvent *)event 483{ 484 if( dispatchEvents_ ) { 485 tListEntry *entry, *tmp; 486 487 DL_FOREACH_SAFE( mouseDelegates_, entry, tmp ) { 488 if ( entry->flags & kCCImplementsMouseExited) { 489 void *swallows = [entry->delegate performSelector:@selector(ccMouseExited:) withObject:event]; 490 if( swallows ) 491 break; 492 } 493 } 494 } 495} 496 497 498#pragma mark CCEventDispatcher - Keyboard events 499 500// Keyboard events 501- (void)keyDown:(NSEvent *)event 502{ 503 if( dispatchEvents_ ) { 504 tListEntry *entry, *tmp; 505 506 DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) { 507 if ( entry->flags & kCCImplementsKeyDown ) { 508 void *swallows = [entry->delegate performSelector:@selector(ccKeyDown:) withObject:event]; 509 if( swallows ) 510 break; 511 } 512 } 513 } 514} 515 516- (void)keyUp:(NSEvent *)event 517{ 518 if( dispatchEvents_ ) { 519 tListEntry *entry, *tmp; 520 521 DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) { 522 if ( entry->flags & kCCImplementsKeyUp ) { 523 void *swallows = [entry->delegate performSelector:@selector(ccKeyUp:) withObject:event]; 524 if( swallows ) 525 break; 526 } 527 } 528 } 529} 530 531- (void)flagsChanged:(NSEvent *)event 532{ 533 if( dispatchEvents_ ) { 534 tListEntry *entry, *tmp; 535 536 DL_FOREACH_SAFE( keyboardDelegates_, entry, tmp ) { 537 if ( entry->flags & kCCImplementsFlagsChanged ) { 538 void *swallows = [entry->delegate performSelector:@selector(ccFlagsChanged:) withObject:event]; 539 if( swallows ) 540 break; 541 } 542 } 543 } 544} 545 546 547#pragma mark CCEventDispatcher - Touch events 548 549- (void)touchesBeganWithEvent:(NSEvent *)event 550{ 551 if( dispatchEvents_ ) { 552 tListEntry *entry, *tmp; 553 554 DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) { 555 if ( entry->flags & kCCImplementsTouchesBegan) { 556 void *swallows = [entry->delegate performSelector:@selector(ccTouchesBeganWithEvent:) withObject:event]; 557 if( swallows ) 558 break; 559 } 560 } 561 } 562} 563 564- (void)touchesMovedWithEvent:(NSEvent *)event 565{ 566 if( dispatchEvents_ ) { 567 tListEntry *entry, *tmp; 568 569 DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) { 570 if ( entry->flags & kCCImplementsTouchesMoved) { 571 void *swallows = [entry->delegate performSelector:@selector(ccTouchesMovedWithEvent:) withObject:event]; 572 if( swallows ) 573 break; 574 } 575 } 576 } 577} 578 579- (void)touchesEndedWithEvent:(NSEvent *)event 580{ 581 if( dispatchEvents_ ) { 582 tListEntry *entry, *tmp; 583 584 DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) { 585 if ( entry->flags & kCCImplementsTouchesEnded) { 586 void *swallows = [entry->delegate performSelector:@selector(ccTouchesEndedWithEvent:) withObject:event]; 587 if( swallows ) 588 break; 589 } 590 } 591 } 592} 593 594- (void)touchesCancelledWithEvent:(NSEvent *)event 595{ 596 if( dispatchEvents_ ) { 597 tListEntry *entry, *tmp; 598 599 DL_FOREACH_SAFE( touchDelegates_, entry, tmp ) { 600 if ( entry->flags & kCCImplementsTouchesCancelled) { 601 void *swallows = [entry->delegate performSelector:@selector(ccTouchesCancelledWithEvent:) withObject:event]; 602 if( swallows ) 603 break; 604 } 605 } 606 } 607} 608 609 610#pragma mark CCEventDispatcher - queue events 611 612#if CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD 613-(void) queueEvent:(NSEvent*)event selector:(SEL)selector 614{ 615 NSAssert( eventQueueCount < QUEUE_EVENT_MAX, @"CCEventDispatcher: recompile. Increment QUEUE_EVENT_MAX value"); 616 617 @synchronized (self) { 618 eventQueue[eventQueueCount].selector = selector; 619 eventQueue[eventQueueCount].event = [event copy]; 620 621 eventQueueCount++; 622 } 623} 624 625-(void) dispatchQueuedEvents 626{ 627 @synchronized (self) { 628 for( int i=0; i < eventQueueCount; i++ ) { 629 SEL sel = eventQueue[i].selector; 630 NSEvent *event = eventQueue[i].event; 631 632 [self performSelector:sel withObject:event]; 633 634 [event release]; 635 } 636 637 eventQueueCount = 0; 638 } 639} 640#endif // CC_DIRECTOR_MAC_USE_DISPLAY_LINK_THREAD 641 642 643@end 644 645#endif // __MAC_OS_X_VERSION_MAX_ALLOWED