• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 The zlib/libpng License
3
4 Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
5
6 This software is provided 'as-is', without any express or implied warranty. In no event will
7 the authors be held liable for any damages arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose, including commercial
10 applications, and to alter it and redistribute it freely, subject to the following
11 restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not claim that
14 you wrote the original software. If you use this software in a product,
15 an acknowledgment in the product documentation would be appreciated but is
16 not required.
17
18 2. Altered source versions must be plainly marked as such, and must not be
19 misrepresented as being the original software.
20
21 3. This notice may not be removed or altered from any source distribution.
22 */
23#include "mac/CocoaMouse.h"
24#include "mac/CocoaInputManager.h"
25#include "mac/CocoaHelpers.h"
26#include "OISException.h"
27#include "OISEvents.h"
28
29using namespace OIS;
30
31//-------------------------------------------------------------------//
32CocoaMouse::CocoaMouse( InputManager* creator, bool buffered )
33	: Mouse(creator->inputSystemName(), buffered, 0, creator)
34{
35    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
36
37	CocoaInputManager *man = static_cast<CocoaInputManager*>(mCreator);
38    mResponder = [[CocoaMouseView alloc] initWithFrame:[[man->_getWindow() contentView] frame]];
39    if(!mResponder)
40        OIS_EXCEPT( E_General, "CocoaMouseView::CocoaMouseView >> Error creating event responder" );
41
42    [[man->_getWindow() contentView] addSubview:mResponder];
43    [mResponder setOISMouseObj:this];
44
45	static_cast<CocoaInputManager*>(mCreator)->_setMouseUsed(true);
46
47    [pool drain];
48}
49
50CocoaMouse::~CocoaMouse()
51{
52	// Restore Mouse
53//	CGAssociateMouseAndMouseCursorPosition(true);
54	CGDisplayShowCursor(kCGDirectMainDisplay);
55
56    if (mResponder)
57    {
58        [mResponder release];
59        mResponder = nil;
60    }
61
62	static_cast<CocoaInputManager*>(mCreator)->_setMouseUsed(false);
63}
64
65void CocoaMouse::_initialize()
66{
67	mState.clear();
68	CGAssociateMouseAndMouseCursorPosition(false);
69}
70
71void CocoaMouse::setBuffered( bool buffered )
72{
73	mBuffered = buffered;
74}
75
76void CocoaMouse::capture()
77{
78    [mResponder capture];
79}
80
81@implementation CocoaMouseView
82
83- (id)initWithFrame:(NSRect)frame
84{
85    self = [super initWithFrame:frame];
86    if (self) {
87        mTempState.clear();
88        mMouseWarped = false;
89        mNeedsToRegainFocus = false;
90
91        // Hide OS Mouse
92        CGDisplayHideCursor(kCGDirectMainDisplay);
93
94        NSRect clipRect = NSMakeRect(0.0f, 0.0f, 0.0f, 0.0f);
95        clipRect = [[[self window] contentView] frame];
96
97        CGPoint warpPoint;
98		warpPoint.x = (((frame.origin.x + frame.size.width) - frame.origin.x) / 2) + frame.origin.x;
99		warpPoint.y = (((frame.origin.y + frame.size.height) - frame.origin.y) / 2) - frame.origin.y;
100//        warpPoint = CGPointMake(clipRect.size.height, clipRect.size.width);
101        CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, warpPoint);
102
103        // Use NSTrackingArea to track mouse move events
104        NSTrackingAreaOptions trackingOptions =
105            NSTrackingMouseMoved | NSTrackingEnabledDuringMouseDrag |
106            NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp;
107
108        NSDictionary *trackerData = [NSDictionary dictionaryWithObjectsAndKeys:
109                                     [NSNumber numberWithInt:0], @"OISMouseTrackingKey", nil];
110        NSTrackingArea *trackingArea = [[NSTrackingArea alloc]
111                                        initWithRect:[self frame]// in our case track the entire view
112                                        options:trackingOptions
113                                        owner:self
114                                        userInfo:trackerData];
115        [self addTrackingArea:trackingArea];
116        [[self window] setAcceptsMouseMovedEvents:YES];
117        [trackingArea release];
118    }
119    return self;
120}
121
122- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
123{
124    return YES;
125}
126
127- (void)setOISMouseObj:(CocoaMouse *)obj
128{
129    oisMouseObj = obj;
130}
131
132- (void)capture
133{
134	MouseState *state = oisMouseObj->getMouseStatePtr();
135    state->X.rel = 0;
136    state->Y.rel = 0;
137    state->Z.rel = 0;
138
139	if(mTempState.X.rel || mTempState.Y.rel || mTempState.Z.rel)
140	{
141//		NSLog(@"%i %i %i", mTempState.X.rel, mTempState.Y.rel, mTempState.Z.rel);
142
143		// Set new relative motion values
144		state->X.rel = mTempState.X.rel;
145		state->Y.rel = mTempState.Y.rel;
146		state->Z.rel = mTempState.Z.rel;
147
148		// Update absolute position
149		state->X.abs += mTempState.X.rel;
150		state->Y.abs += mTempState.Y.rel;
151
152		if(state->X.abs > state->width)
153			state->X.abs = state->width;
154		else if(state->X.abs < 0)
155			state->X.abs = 0;
156
157		if(state->Y.abs > state->height)
158			state->Y.abs = state->height;
159		else if(state->Y.abs < 0)
160			state->Y.abs = 0;
161
162		state->Z.abs += mTempState.Z.rel;
163
164		//Fire off event
165        if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
166			oisMouseObj->getEventCallback()->mouseMoved(MouseEvent(oisMouseObj, *state));
167	}
168
169	mTempState.clear();
170}
171
172#pragma mark Left Mouse Event overrides
173- (void)mouseDown:(NSEvent *)theEvent
174{
175    int mouseButton = MB_Left;
176    NSEventType type = [theEvent type];
177    MouseState *state = oisMouseObj->getMouseStatePtr();
178
179    if(mNeedsToRegainFocus)
180        return;
181
182    if((type == NSLeftMouseDown) && ([theEvent modifierFlags] & NSAlternateKeyMask))
183    {
184        mouseButton = MB_Middle;
185    }
186    else if((type == NSLeftMouseDown) && ([theEvent modifierFlags] & NSControlKeyMask))
187    {
188        mouseButton = MB_Right;
189    }
190    else if(type == NSLeftMouseDown)
191    {
192        mouseButton = MB_Left;
193    }
194    state->buttons |= 1 << mouseButton;
195    if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
196        oisMouseObj->getEventCallback()->mousePressed( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
197}
198
199- (void)mouseUp:(NSEvent *)theEvent {
200    int mouseButton = MB_Left;
201    NSEventType type = [theEvent type];
202    MouseState *state = oisMouseObj->getMouseStatePtr();
203
204    if((type == NSLeftMouseUp) && ([theEvent modifierFlags] & NSAlternateKeyMask))
205    {
206        mouseButton = MB_Middle;
207    }
208    else if((type == NSLeftMouseUp) && ([theEvent modifierFlags] & NSControlKeyMask))
209    {
210        mouseButton = MB_Right;
211    }
212    else if(type == NSLeftMouseUp)
213    {
214        mouseButton = MB_Left;
215    }
216    state->buttons &= ~(1 << mouseButton);
217
218    if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
219        oisMouseObj->getEventCallback()->mouseReleased( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
220}
221
222
223- (void)mouseDragged:(NSEvent *)theEvent
224{
225    CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]);
226    if(mNeedsToRegainFocus)
227        return;
228
229    // Relative positioning
230    if(!mMouseWarped)
231    {
232        mTempState.X.rel += delta.x;
233        mTempState.Y.rel += delta.y;
234    }
235
236    mMouseWarped = false;
237}
238
239#pragma mark Right Mouse Event overrides
240- (void)rightMouseDown:(NSEvent *)theEvent
241{
242    int mouseButton = MB_Right;
243    NSEventType type = [theEvent type];
244    MouseState *state = oisMouseObj->getMouseStatePtr();
245
246    if(mNeedsToRegainFocus)
247        return;
248
249    if(type == NSRightMouseDown)
250    {
251        state->buttons |= 1 << mouseButton;
252    }
253
254    if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
255        oisMouseObj->getEventCallback()->mousePressed( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
256}
257
258- (void)rightMouseUp:(NSEvent *)theEvent {
259    int mouseButton = MB_Right;
260    NSEventType type = [theEvent type];
261    MouseState *state = oisMouseObj->getMouseStatePtr();
262
263    if(type == NSRightMouseUp)
264    {
265        state->buttons &= ~(1 << mouseButton);
266    }
267
268    if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
269        oisMouseObj->getEventCallback()->mouseReleased( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
270}
271
272- (void)rightMouseDragged:(NSEvent *)theEvent
273{
274    CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]);
275    if(mNeedsToRegainFocus)
276        return;
277
278    // Relative positioning
279    if(!mMouseWarped)
280    {
281        mTempState.X.rel += delta.x;
282        mTempState.Y.rel += delta.y;
283    }
284
285    mMouseWarped = false;
286}
287
288#pragma mark Other Mouse Event overrides
289- (void)otherMouseDown:(NSEvent *)theEvent
290{
291    int mouseButton = MB_Middle;
292    NSEventType type = [theEvent type];
293    MouseState *state = oisMouseObj->getMouseStatePtr();
294
295    if(mNeedsToRegainFocus)
296        return;
297
298    if(type == NSOtherMouseDown)
299    {
300        state->buttons |= 1 << mouseButton;
301    }
302
303    if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
304        oisMouseObj->getEventCallback()->mousePressed( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
305}
306
307- (void)otherMouseUp:(NSEvent *)theEvent {
308    int mouseButton = MB_Middle;
309    NSEventType type = [theEvent type];
310    MouseState *state = oisMouseObj->getMouseStatePtr();
311
312    if(type == NSOtherMouseUp)
313    {
314        state->buttons &= ~(1 << mouseButton);
315    }
316
317    if ( oisMouseObj->buffered() && oisMouseObj->getEventCallback() )
318        oisMouseObj->getEventCallback()->mouseReleased( MouseEvent( oisMouseObj, *state ), (MouseButtonID)mouseButton );
319}
320
321- (void)otherMouseDragged:(NSEvent *)theEvent
322{
323    CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]);
324    if(mNeedsToRegainFocus)
325        return;
326
327    // Relative positioning
328    if(!mMouseWarped)
329    {
330        mTempState.X.rel += delta.x;
331        mTempState.Y.rel += delta.y;
332    }
333
334    mMouseWarped = false;
335}
336
337- (void)scrollWheel:(NSEvent *)theEvent
338{
339    if([theEvent deltaY] != 0.0)
340        mTempState.Z.rel += ([theEvent deltaY] * 60);
341}
342
343- (void)mouseMoved:(NSEvent *)theEvent
344{
345    CGPoint delta = CGPointMake([theEvent deltaX], [theEvent deltaY]);
346    if(mNeedsToRegainFocus)
347        return;
348
349    // Relative positioning
350    if(!mMouseWarped)
351    {
352        mTempState.X.rel += delta.x;
353        mTempState.Y.rel += delta.y;
354    }
355
356    mMouseWarped = false;
357}
358
359- (void)mouseEntered:(NSEvent *)theEvent
360{
361	CGDisplayHideCursor(kCGDirectMainDisplay);
362	CGAssociateMouseAndMouseCursorPosition(false);
363    if(!mMouseWarped)
364    {
365        NSPoint pos = [[self window] mouseLocationOutsideOfEventStream];
366        NSRect frame = [[[self window] contentView] frame];
367
368        // Clear the previous mouse state
369        MouseState *state = oisMouseObj->getMouseStatePtr();
370        state->clear();
371
372        // Cocoa's coordinate system has the origin in the bottom left so we need to transform the height
373        mTempState.X.rel = pos.x;
374        mTempState.Y.rel = frame.size.height - pos.y;
375    }
376}
377
378- (void)mouseExited:(NSEvent *)theEvent
379{
380	CGDisplayShowCursor(kCGDirectMainDisplay);
381	CGAssociateMouseAndMouseCursorPosition(true);
382}
383
384@end
385