summary refs log tree commit diff stats
path: root/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cocos2d/Platforms/Mac/CCEventDispatcher.m')
-rwxr-xr-xlibs/cocos2d/Platforms/Mac/CCEventDispatcher.m645
1 files changed, 645 insertions, 0 deletions
diff --git a/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m b/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m new file mode 100755 index 0000000..1d1740e --- /dev/null +++ b/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m
@@ -0,0 +1,645 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies 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