slouken@1931
|
1 |
/*
|
slouken@5535
|
2 |
Simple DirectMedia Layer
|
slouken@9619
|
3 |
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
slouken@1931
|
4 |
|
slouken@5535
|
5 |
This software is provided 'as-is', without any express or implied
|
slouken@5535
|
6 |
warranty. In no event will the authors be held liable for any damages
|
slouken@5535
|
7 |
arising from the use of this software.
|
slouken@1931
|
8 |
|
slouken@5535
|
9 |
Permission is granted to anyone to use this software for any purpose,
|
slouken@5535
|
10 |
including commercial applications, and to alter it and redistribute it
|
slouken@5535
|
11 |
freely, subject to the following restrictions:
|
slouken@1931
|
12 |
|
slouken@5535
|
13 |
1. The origin of this software must not be misrepresented; you must not
|
slouken@5535
|
14 |
claim that you wrote the original software. If you use this software
|
slouken@5535
|
15 |
in a product, an acknowledgment in the product documentation would be
|
slouken@5535
|
16 |
appreciated but is not required.
|
slouken@5535
|
17 |
2. Altered source versions must be plainly marked as such, and must not be
|
slouken@5535
|
18 |
misrepresented as being the original software.
|
slouken@5535
|
19 |
3. This notice may not be removed or altered from any source distribution.
|
slouken@1931
|
20 |
*/
|
icculus@8093
|
21 |
#include "../../SDL_internal.h"
|
slouken@1931
|
22 |
|
slouken@6044
|
23 |
#if SDL_VIDEO_DRIVER_COCOA
|
slouken@6044
|
24 |
|
slouken@6676
|
25 |
#include "SDL_assert.h"
|
slouken@3517
|
26 |
#include "SDL_events.h"
|
jorgen@7114
|
27 |
#include "SDL_cocoamouse.h"
|
jorgen@7593
|
28 |
#include "SDL_cocoamousetap.h"
|
slouken@1931
|
29 |
|
slouken@1931
|
30 |
#include "../../events/SDL_mouse_c.h"
|
slouken@1931
|
31 |
|
jorgen@8260
|
32 |
/* #define DEBUG_COCOAMOUSE */
|
jorgen@8260
|
33 |
|
jorgen@8260
|
34 |
#ifdef DEBUG_COCOAMOUSE
|
jorgen@8260
|
35 |
#define DLog(fmt, ...) printf("%s: " fmt "\n", __func__, ##__VA_ARGS__)
|
jorgen@8260
|
36 |
#else
|
jorgen@8260
|
37 |
#define DLog(...) do { } while (0)
|
jorgen@8260
|
38 |
#endif
|
jorgen@8260
|
39 |
|
jorgen@7158
|
40 |
@implementation NSCursor (InvisibleCursor)
|
jorgen@7158
|
41 |
+ (NSCursor *)invisibleCursor
|
jorgen@7158
|
42 |
{
|
jorgen@7158
|
43 |
static NSCursor *invisibleCursor = NULL;
|
jorgen@7158
|
44 |
if (!invisibleCursor) {
|
jorgen@7158
|
45 |
/* RAW 16x16 transparent GIF */
|
jorgen@7158
|
46 |
static unsigned char cursorBytes[] = {
|
jorgen@7158
|
47 |
0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x10, 0x00, 0x10, 0x00, 0x80,
|
jorgen@7158
|
48 |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xF9, 0x04,
|
jorgen@7158
|
49 |
0x01, 0x00, 0x00, 0x01, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x10,
|
jorgen@7158
|
50 |
0x00, 0x10, 0x00, 0x00, 0x02, 0x0E, 0x8C, 0x8F, 0xA9, 0xCB, 0xED,
|
jorgen@7158
|
51 |
0x0F, 0xA3, 0x9C, 0xB4, 0xDA, 0x8B, 0xB3, 0x3E, 0x05, 0x00, 0x3B
|
jorgen@7158
|
52 |
};
|
jorgen@7158
|
53 |
|
jorgen@7158
|
54 |
NSData *cursorData = [NSData dataWithBytesNoCopy:&cursorBytes[0]
|
jorgen@7158
|
55 |
length:sizeof(cursorBytes)
|
jorgen@7158
|
56 |
freeWhenDone:NO];
|
jorgen@7158
|
57 |
NSImage *cursorImage = [[[NSImage alloc] initWithData:cursorData] autorelease];
|
jorgen@7158
|
58 |
invisibleCursor = [[NSCursor alloc] initWithImage:cursorImage
|
jorgen@7158
|
59 |
hotSpot:NSZeroPoint];
|
jorgen@7158
|
60 |
}
|
jorgen@7158
|
61 |
|
jorgen@7158
|
62 |
return invisibleCursor;
|
jorgen@7158
|
63 |
}
|
jorgen@7158
|
64 |
@end
|
jorgen@7158
|
65 |
|
slouken@5376
|
66 |
|
slouken@5376
|
67 |
static SDL_Cursor *
|
slouken@5376
|
68 |
Cocoa_CreateDefaultCursor()
|
slouken@9087
|
69 |
{ @autoreleasepool
|
slouken@5376
|
70 |
{
|
slouken@6848
|
71 |
NSCursor *nscursor;
|
slouken@6848
|
72 |
SDL_Cursor *cursor = NULL;
|
slouken@5376
|
73 |
|
slouken@6848
|
74 |
nscursor = [NSCursor arrowCursor];
|
slouken@5376
|
75 |
|
slouken@6848
|
76 |
if (nscursor) {
|
slouken@6848
|
77 |
cursor = SDL_calloc(1, sizeof(*cursor));
|
slouken@6848
|
78 |
if (cursor) {
|
slouken@6848
|
79 |
cursor->driverdata = nscursor;
|
slouken@6848
|
80 |
[nscursor retain];
|
slouken@5376
|
81 |
}
|
slouken@5376
|
82 |
}
|
slouken@6848
|
83 |
|
slouken@6848
|
84 |
return cursor;
|
slouken@9087
|
85 |
}}
|
slouken@5376
|
86 |
|
slouken@5376
|
87 |
static SDL_Cursor *
|
slouken@5376
|
88 |
Cocoa_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
|
slouken@9087
|
89 |
{ @autoreleasepool
|
slouken@5376
|
90 |
{
|
slouken@6848
|
91 |
NSImage *nsimage;
|
slouken@6848
|
92 |
NSCursor *nscursor = NULL;
|
slouken@6848
|
93 |
SDL_Cursor *cursor = NULL;
|
slouken@5376
|
94 |
|
slouken@6848
|
95 |
nsimage = Cocoa_CreateImage(surface);
|
slouken@6848
|
96 |
if (nsimage) {
|
slouken@6848
|
97 |
nscursor = [[NSCursor alloc] initWithImage: nsimage hotSpot: NSMakePoint(hot_x, hot_y)];
|
slouken@6848
|
98 |
}
|
slouken@5376
|
99 |
|
slouken@6848
|
100 |
if (nscursor) {
|
slouken@6848
|
101 |
cursor = SDL_calloc(1, sizeof(*cursor));
|
slouken@6848
|
102 |
if (cursor) {
|
slouken@6848
|
103 |
cursor->driverdata = nscursor;
|
jorgen@7593
|
104 |
} else {
|
jorgen@7593
|
105 |
[nscursor release];
|
slouken@5376
|
106 |
}
|
slouken@5376
|
107 |
}
|
slouken@6848
|
108 |
|
slouken@6848
|
109 |
return cursor;
|
slouken@9087
|
110 |
}}
|
slouken@5376
|
111 |
|
slouken@6676
|
112 |
static SDL_Cursor *
|
slouken@6676
|
113 |
Cocoa_CreateSystemCursor(SDL_SystemCursor id)
|
slouken@9087
|
114 |
{ @autoreleasepool
|
slouken@6676
|
115 |
{
|
slouken@6848
|
116 |
NSCursor *nscursor = NULL;
|
slouken@6848
|
117 |
SDL_Cursor *cursor = NULL;
|
slouken@6676
|
118 |
|
slouken@8986
|
119 |
switch(id) {
|
slouken@6848
|
120 |
case SDL_SYSTEM_CURSOR_ARROW:
|
slouken@6848
|
121 |
nscursor = [NSCursor arrowCursor];
|
slouken@6848
|
122 |
break;
|
slouken@6848
|
123 |
case SDL_SYSTEM_CURSOR_IBEAM:
|
slouken@6848
|
124 |
nscursor = [NSCursor IBeamCursor];
|
slouken@6848
|
125 |
break;
|
slouken@6848
|
126 |
case SDL_SYSTEM_CURSOR_WAIT:
|
slouken@6848
|
127 |
nscursor = [NSCursor arrowCursor];
|
slouken@6848
|
128 |
break;
|
slouken@6848
|
129 |
case SDL_SYSTEM_CURSOR_CROSSHAIR:
|
slouken@6848
|
130 |
nscursor = [NSCursor crosshairCursor];
|
slouken@6848
|
131 |
break;
|
slouken@6848
|
132 |
case SDL_SYSTEM_CURSOR_WAITARROW:
|
slouken@6848
|
133 |
nscursor = [NSCursor arrowCursor];
|
slouken@6848
|
134 |
break;
|
slouken@6848
|
135 |
case SDL_SYSTEM_CURSOR_SIZENWSE:
|
slouken@6848
|
136 |
case SDL_SYSTEM_CURSOR_SIZENESW:
|
slouken@6848
|
137 |
nscursor = [NSCursor closedHandCursor];
|
slouken@6848
|
138 |
break;
|
slouken@6848
|
139 |
case SDL_SYSTEM_CURSOR_SIZEWE:
|
slouken@6848
|
140 |
nscursor = [NSCursor resizeLeftRightCursor];
|
slouken@6848
|
141 |
break;
|
slouken@6848
|
142 |
case SDL_SYSTEM_CURSOR_SIZENS:
|
slouken@6848
|
143 |
nscursor = [NSCursor resizeUpDownCursor];
|
slouken@6848
|
144 |
break;
|
slouken@6848
|
145 |
case SDL_SYSTEM_CURSOR_SIZEALL:
|
slouken@6848
|
146 |
nscursor = [NSCursor closedHandCursor];
|
slouken@6848
|
147 |
break;
|
slouken@6848
|
148 |
case SDL_SYSTEM_CURSOR_NO:
|
slouken@6848
|
149 |
nscursor = [NSCursor operationNotAllowedCursor];
|
slouken@6848
|
150 |
break;
|
slouken@6848
|
151 |
case SDL_SYSTEM_CURSOR_HAND:
|
slouken@6848
|
152 |
nscursor = [NSCursor pointingHandCursor];
|
slouken@6848
|
153 |
break;
|
slouken@6848
|
154 |
default:
|
slouken@6848
|
155 |
SDL_assert(!"Unknown system cursor");
|
slouken@6848
|
156 |
return NULL;
|
slouken@6848
|
157 |
}
|
slouken@6848
|
158 |
|
slouken@6848
|
159 |
if (nscursor) {
|
slouken@6848
|
160 |
cursor = SDL_calloc(1, sizeof(*cursor));
|
slouken@6848
|
161 |
if (cursor) {
|
slouken@7191
|
162 |
/* We'll free it later, so retain it here */
|
slouken@6848
|
163 |
[nscursor retain];
|
slouken@6848
|
164 |
cursor->driverdata = nscursor;
|
alexey@6832
|
165 |
}
|
slouken@6848
|
166 |
}
|
alexey@6832
|
167 |
|
slouken@6848
|
168 |
return cursor;
|
slouken@9087
|
169 |
}}
|
slouken@6676
|
170 |
|
slouken@5376
|
171 |
static void
|
slouken@5376
|
172 |
Cocoa_FreeCursor(SDL_Cursor * cursor)
|
slouken@9087
|
173 |
{ @autoreleasepool
|
slouken@5376
|
174 |
{
|
slouken@6848
|
175 |
NSCursor *nscursor = (NSCursor *)cursor->driverdata;
|
slouken@5376
|
176 |
|
slouken@6848
|
177 |
[nscursor release];
|
slouken@6848
|
178 |
SDL_free(cursor);
|
slouken@9087
|
179 |
}}
|
slouken@5376
|
180 |
|
slouken@5376
|
181 |
static int
|
slouken@5376
|
182 |
Cocoa_ShowCursor(SDL_Cursor * cursor)
|
slouken@9087
|
183 |
{ @autoreleasepool
|
slouken@5376
|
184 |
{
|
jorgen@7158
|
185 |
SDL_VideoDevice *device = SDL_GetVideoDevice();
|
jorgen@7158
|
186 |
SDL_Window *window = (device ? device->windows : NULL);
|
jorgen@7158
|
187 |
for (; window != NULL; window = window->next) {
|
jorgen@7158
|
188 |
SDL_WindowData *driverdata = (SDL_WindowData *)window->driverdata;
|
jorgen@7158
|
189 |
if (driverdata) {
|
jorgen@7158
|
190 |
[driverdata->nswindow performSelectorOnMainThread:@selector(invalidateCursorRectsForView:)
|
jorgen@7158
|
191 |
withObject:[driverdata->nswindow contentView]
|
jorgen@7158
|
192 |
waitUntilDone:NO];
|
jorgen@7158
|
193 |
}
|
slouken@5376
|
194 |
}
|
slouken@5376
|
195 |
return 0;
|
slouken@9087
|
196 |
}}
|
slouken@5376
|
197 |
|
icculus@9692
|
198 |
static SDL_Window *
|
icculus@9692
|
199 |
SDL_FindWindowAtPoint(const int x, const int y)
|
icculus@9692
|
200 |
{
|
icculus@9692
|
201 |
const SDL_Point pt = { x, y };
|
icculus@9692
|
202 |
SDL_Window *i;
|
icculus@9692
|
203 |
for (i = SDL_GetVideoDevice()->windows; i; i = i->next) {
|
icculus@9692
|
204 |
const SDL_Rect r = { i->x, i->y, i->w, i->h };
|
icculus@9692
|
205 |
if (SDL_PointInRect(&pt, &r)) {
|
icculus@9692
|
206 |
return i;
|
icculus@9692
|
207 |
}
|
icculus@9692
|
208 |
}
|
icculus@9692
|
209 |
|
icculus@9692
|
210 |
return NULL;
|
icculus@9692
|
211 |
}
|
icculus@9692
|
212 |
|
slouken@5376
|
213 |
static void
|
slouken@8815
|
214 |
Cocoa_WarpMouseGlobal(int x, int y)
|
slouken@8815
|
215 |
{
|
slouken@8815
|
216 |
SDL_Mouse *mouse = SDL_GetMouse();
|
slouken@9086
|
217 |
if (mouse->focus) {
|
slouken@9086
|
218 |
SDL_WindowData *data = (SDL_WindowData *) mouse->focus->driverdata;
|
slouken@9086
|
219 |
if ([data->listener isMoving]) {
|
slouken@9086
|
220 |
DLog("Postponing warp, window being moved.");
|
slouken@9086
|
221 |
[data->listener setPendingMoveX:x Y:y];
|
slouken@9086
|
222 |
return;
|
slouken@9086
|
223 |
}
|
slouken@9086
|
224 |
}
|
icculus@9692
|
225 |
const CGPoint point = CGPointMake((float)x, (float)y);
|
slouken@8815
|
226 |
|
slouken@8815
|
227 |
Cocoa_HandleMouseWarp(point.x, point.y);
|
slouken@8815
|
228 |
|
slouken@8815
|
229 |
/* According to the docs, this was deprecated in 10.6, but it's still
|
slouken@8815
|
230 |
* around. The substitute requires a CGEventSource, but I'm not entirely
|
slouken@8815
|
231 |
* sure how we'd procure the right one for this event.
|
slouken@8815
|
232 |
*/
|
slouken@8815
|
233 |
CGSetLocalEventsSuppressionInterval(0.0);
|
slouken@8815
|
234 |
CGWarpMouseCursorPosition(point);
|
slouken@8815
|
235 |
CGSetLocalEventsSuppressionInterval(0.25);
|
slouken@8815
|
236 |
|
icculus@9692
|
237 |
/* CGWarpMouseCursorPosition doesn't generate a window event, unlike our
|
icculus@9692
|
238 |
* other implementations' APIs. Send what's appropriate.
|
icculus@9692
|
239 |
*/
|
icculus@9692
|
240 |
if (!mouse->relative_mode) {
|
icculus@9692
|
241 |
SDL_Window *win = SDL_FindWindowAtPoint(x, y);
|
icculus@9692
|
242 |
SDL_SetMouseFocus(win);
|
icculus@9692
|
243 |
if (win) {
|
icculus@9692
|
244 |
SDL_assert(win == mouse->focus);
|
icculus@9692
|
245 |
SDL_SendMouseMotion(win, mouse->mouseID, 0, x - win->x, y - win->y);
|
icculus@9692
|
246 |
}
|
slouken@8815
|
247 |
}
|
slouken@8815
|
248 |
}
|
slouken@8815
|
249 |
|
slouken@9086
|
250 |
static void
|
slouken@9086
|
251 |
Cocoa_WarpMouse(SDL_Window * window, int x, int y)
|
slouken@9086
|
252 |
{
|
slouken@9086
|
253 |
Cocoa_WarpMouseGlobal(x + window->x, y + window->y);
|
slouken@9086
|
254 |
}
|
slouken@9086
|
255 |
|
slouken@5406
|
256 |
static int
|
slouken@5406
|
257 |
Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
slouken@5406
|
258 |
{
|
jorgen@8262
|
259 |
/* We will re-apply the relative mode when the window gets focus, if it
|
jorgen@8262
|
260 |
* doesn't have focus right now.
|
jorgen@8262
|
261 |
*/
|
jorgen@8262
|
262 |
SDL_Window *window = SDL_GetMouseFocus();
|
jorgen@8262
|
263 |
if (!window) {
|
jorgen@8262
|
264 |
return 0;
|
jorgen@8262
|
265 |
}
|
jorgen@8262
|
266 |
|
jorgen@8262
|
267 |
/* We will re-apply the relative mode when the window finishes being moved,
|
jorgen@8262
|
268 |
* if it is being moved right now.
|
jorgen@8262
|
269 |
*/
|
jorgen@8262
|
270 |
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
jorgen@8262
|
271 |
if ([data->listener isMoving]) {
|
jorgen@8263
|
272 |
return 0;
|
jorgen@8262
|
273 |
}
|
jorgen@8262
|
274 |
|
slouken@5406
|
275 |
CGError result;
|
slouken@5406
|
276 |
if (enabled) {
|
jorgen@8260
|
277 |
DLog("Turning on.");
|
slouken@5406
|
278 |
result = CGAssociateMouseAndMouseCursorPosition(NO);
|
slouken@5406
|
279 |
} else {
|
jorgen@8260
|
280 |
DLog("Turning off.");
|
slouken@5406
|
281 |
result = CGAssociateMouseAndMouseCursorPosition(YES);
|
slouken@5406
|
282 |
}
|
slouken@5406
|
283 |
if (result != kCGErrorSuccess) {
|
icculus@7037
|
284 |
return SDL_SetError("CGAssociateMouseAndMouseCursorPosition() failed");
|
slouken@5406
|
285 |
}
|
slouken@8800
|
286 |
|
slouken@8800
|
287 |
/* The hide/unhide calls are redundant most of the time, but they fix
|
slouken@8800
|
288 |
* https://bugzilla.libsdl.org/show_bug.cgi?id=2550
|
slouken@8800
|
289 |
*/
|
slouken@8800
|
290 |
if (enabled) {
|
slouken@8800
|
291 |
[NSCursor hide];
|
slouken@8800
|
292 |
} else {
|
slouken@8800
|
293 |
[NSCursor unhide];
|
slouken@8800
|
294 |
}
|
slouken@5406
|
295 |
return 0;
|
slouken@5406
|
296 |
}
|
slouken@5406
|
297 |
|
icculus@8928
|
298 |
static int
|
icculus@8928
|
299 |
Cocoa_CaptureMouse(SDL_Window *window)
|
icculus@8928
|
300 |
{
|
icculus@8928
|
301 |
/* our Cocoa event code already tracks the mouse outside the window,
|
icculus@8928
|
302 |
so all we have to do here is say "okay" and do what we always do. */
|
icculus@8928
|
303 |
return 0;
|
icculus@8928
|
304 |
}
|
icculus@8928
|
305 |
|
icculus@8951
|
306 |
static Uint32
|
icculus@8952
|
307 |
Cocoa_GetGlobalMouseState(int *x, int *y)
|
icculus@8951
|
308 |
{
|
icculus@8951
|
309 |
const NSUInteger cocoaButtons = [NSEvent pressedMouseButtons];
|
icculus@8951
|
310 |
const NSPoint cocoaLocation = [NSEvent mouseLocation];
|
icculus@8951
|
311 |
Uint32 retval = 0;
|
icculus@8951
|
312 |
|
icculus@8951
|
313 |
for (NSScreen *screen in [NSScreen screens]) {
|
icculus@8951
|
314 |
NSRect frame = [screen frame];
|
icculus@8951
|
315 |
if (NSPointInRect(cocoaLocation, frame)) {
|
icculus@8951
|
316 |
*x = (int) cocoaLocation.x;
|
icculus@8951
|
317 |
*y = (int) ((frame.origin.y + frame.size.height) - cocoaLocation.y);
|
icculus@8951
|
318 |
break;
|
icculus@8951
|
319 |
}
|
icculus@8951
|
320 |
}
|
icculus@8951
|
321 |
|
icculus@8951
|
322 |
retval |= (cocoaButtons & (1 << 0)) ? SDL_BUTTON_LMASK : 0;
|
icculus@8951
|
323 |
retval |= (cocoaButtons & (1 << 1)) ? SDL_BUTTON_RMASK : 0;
|
icculus@8951
|
324 |
retval |= (cocoaButtons & (1 << 2)) ? SDL_BUTTON_MMASK : 0;
|
icculus@8951
|
325 |
retval |= (cocoaButtons & (1 << 3)) ? SDL_BUTTON_X1MASK : 0;
|
icculus@8951
|
326 |
retval |= (cocoaButtons & (1 << 4)) ? SDL_BUTTON_X2MASK : 0;
|
icculus@8951
|
327 |
|
icculus@8951
|
328 |
return retval;
|
icculus@8951
|
329 |
}
|
icculus@8951
|
330 |
|
slouken@1931
|
331 |
void
|
slouken@1931
|
332 |
Cocoa_InitMouse(_THIS)
|
slouken@1931
|
333 |
{
|
slouken@5376
|
334 |
SDL_Mouse *mouse = SDL_GetMouse();
|
slouken@5376
|
335 |
|
jorgen@7114
|
336 |
mouse->driverdata = SDL_calloc(1, sizeof(SDL_MouseData));
|
jorgen@7114
|
337 |
|
slouken@5376
|
338 |
mouse->CreateCursor = Cocoa_CreateCursor;
|
slouken@6676
|
339 |
mouse->CreateSystemCursor = Cocoa_CreateSystemCursor;
|
slouken@5376
|
340 |
mouse->ShowCursor = Cocoa_ShowCursor;
|
slouken@5406
|
341 |
mouse->FreeCursor = Cocoa_FreeCursor;
|
slouken@5376
|
342 |
mouse->WarpMouse = Cocoa_WarpMouse;
|
slouken@8815
|
343 |
mouse->WarpMouseGlobal = Cocoa_WarpMouseGlobal;
|
slouken@5406
|
344 |
mouse->SetRelativeMouseMode = Cocoa_SetRelativeMouseMode;
|
icculus@8928
|
345 |
mouse->CaptureMouse = Cocoa_CaptureMouse;
|
icculus@8952
|
346 |
mouse->GetGlobalMouseState = Cocoa_GetGlobalMouseState;
|
slouken@5376
|
347 |
|
slouken@5405
|
348 |
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
|
jorgen@7593
|
349 |
|
jorgen@7593
|
350 |
Cocoa_InitMouseEventTap(mouse->driverdata);
|
jorgen@8261
|
351 |
|
jorgen@8261
|
352 |
SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
|
jorgen@8261
|
353 |
const NSPoint location = [NSEvent mouseLocation];
|
jorgen@8261
|
354 |
driverdata->lastMoveX = location.x;
|
jorgen@8261
|
355 |
driverdata->lastMoveY = location.y;
|
slouken@1931
|
356 |
}
|
slouken@1931
|
357 |
|
slouken@3517
|
358 |
void
|
slouken@3517
|
359 |
Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
slouken@3517
|
360 |
{
|
slouken@8986
|
361 |
switch ([event type]) {
|
jorgen@8260
|
362 |
case NSMouseMoved:
|
jorgen@8260
|
363 |
case NSLeftMouseDragged:
|
jorgen@8260
|
364 |
case NSRightMouseDragged:
|
jorgen@8260
|
365 |
case NSOtherMouseDragged:
|
jorgen@8260
|
366 |
break;
|
jorgen@8260
|
367 |
|
jorgen@8260
|
368 |
default:
|
jorgen@8260
|
369 |
/* Ignore any other events. */
|
jorgen@8260
|
370 |
return;
|
jorgen@8260
|
371 |
}
|
jorgen@7114
|
372 |
|
jorgen@8261
|
373 |
SDL_Mouse *mouse = SDL_GetMouse();
|
icculus@8862
|
374 |
SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
|
icculus@8862
|
375 |
if (!driverdata) {
|
icculus@8862
|
376 |
return; /* can happen when returning from fullscreen Space on shutdown */
|
icculus@8862
|
377 |
}
|
jorgen@8261
|
378 |
|
jorgen@8261
|
379 |
const SDL_bool seenWarp = driverdata->seenWarp;
|
jorgen@8261
|
380 |
driverdata->seenWarp = NO;
|
jorgen@8261
|
381 |
|
jorgen@8261
|
382 |
const NSPoint location = [NSEvent mouseLocation];
|
jorgen@8261
|
383 |
const CGFloat lastMoveX = driverdata->lastMoveX;
|
jorgen@8261
|
384 |
const CGFloat lastMoveY = driverdata->lastMoveY;
|
jorgen@8261
|
385 |
driverdata->lastMoveX = location.x;
|
jorgen@8261
|
386 |
driverdata->lastMoveY = location.y;
|
jorgen@8261
|
387 |
DLog("Last seen mouse: (%g, %g)", location.x, location.y);
|
jorgen@8261
|
388 |
|
jorgen@8261
|
389 |
/* Non-relative movement is handled in -[Cocoa_WindowListener mouseMoved:] */
|
jorgen@8261
|
390 |
if (!mouse->relative_mode) {
|
jorgen@8261
|
391 |
return;
|
jorgen@8261
|
392 |
}
|
jorgen@8261
|
393 |
|
jorgen@8260
|
394 |
/* Ignore events that aren't inside the client area (i.e. title bar.) */
|
jorgen@8260
|
395 |
if ([event window]) {
|
jorgen@8260
|
396 |
NSRect windowRect = [[[event window] contentView] frame];
|
jorgen@8260
|
397 |
if (!NSPointInRect([event locationInWindow], windowRect)) {
|
jorgen@8260
|
398 |
return;
|
jorgen@8260
|
399 |
}
|
slouken@5406
|
400 |
}
|
jorgen@8260
|
401 |
|
jorgen@8261
|
402 |
float deltaX = [event deltaX];
|
jorgen@8261
|
403 |
float deltaY = [event deltaY];
|
jorgen@8260
|
404 |
|
slouken@8986
|
405 |
if (seenWarp) {
|
jorgen@8261
|
406 |
deltaX += (lastMoveX - driverdata->lastWarpX);
|
jorgen@8261
|
407 |
deltaY += ((CGDisplayPixelsHigh(kCGDirectMainDisplay) - lastMoveY) - driverdata->lastWarpY);
|
jorgen@8261
|
408 |
|
jorgen@8261
|
409 |
DLog("Motion was (%g, %g), offset to (%g, %g)", [event deltaX], [event deltaY], deltaX, deltaY);
|
jorgen@8260
|
410 |
}
|
jorgen@8260
|
411 |
|
jorgen@8261
|
412 |
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, (int)deltaX, (int)deltaY);
|
slouken@3517
|
413 |
}
|
slouken@3517
|
414 |
|
slouken@1931
|
415 |
void
|
gzjjgod@5057
|
416 |
Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
|
gzjjgod@5057
|
417 |
{
|
slouken@6950
|
418 |
SDL_Mouse *mouse = SDL_GetMouse();
|
slouken@6950
|
419 |
|
slouken@8232
|
420 |
float x = -[event deltaX];
|
gzjjgod@5057
|
421 |
float y = [event deltaY];
|
urkle@9257
|
422 |
SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL;
|
urkle@9257
|
423 |
|
urkle@9257
|
424 |
if ([event respondsToSelector:@selector(isDirectionInvertedFromDevice)]) {
|
urkle@9257
|
425 |
if ([event isDirectionInvertedFromDevice] == YES) {
|
urkle@9257
|
426 |
direction = SDL_MOUSEWHEEL_FLIPPED;
|
urkle@9257
|
427 |
}
|
urkle@9257
|
428 |
}
|
gzjjgod@5057
|
429 |
|
gzjjgod@5057
|
430 |
if (x > 0) {
|
gzjjgod@5057
|
431 |
x += 0.9f;
|
gzjjgod@5057
|
432 |
} else if (x < 0) {
|
gzjjgod@5057
|
433 |
x -= 0.9f;
|
gzjjgod@5057
|
434 |
}
|
gzjjgod@5057
|
435 |
if (y > 0) {
|
gzjjgod@5057
|
436 |
y += 0.9f;
|
gzjjgod@5057
|
437 |
} else if (y < 0) {
|
gzjjgod@5057
|
438 |
y -= 0.9f;
|
gzjjgod@5057
|
439 |
}
|
urkle@9257
|
440 |
SDL_SendMouseWheel(window, mouse->mouseID, (int)x, (int)y, direction);
|
gzjjgod@5057
|
441 |
}
|
gzjjgod@5057
|
442 |
|
slouken@5058
|
443 |
void
|
jorgen@8261
|
444 |
Cocoa_HandleMouseWarp(CGFloat x, CGFloat y)
|
jorgen@8261
|
445 |
{
|
jorgen@8261
|
446 |
/* This makes Cocoa_HandleMouseEvent ignore the delta caused by the warp,
|
jorgen@8261
|
447 |
* since it gets included in the next movement event.
|
jorgen@8261
|
448 |
*/
|
jorgen@8261
|
449 |
SDL_MouseData *driverdata = (SDL_MouseData*)SDL_GetMouse()->driverdata;
|
jorgen@8261
|
450 |
driverdata->lastWarpX = x;
|
jorgen@8261
|
451 |
driverdata->lastWarpY = y;
|
jorgen@8261
|
452 |
driverdata->seenWarp = SDL_TRUE;
|
jorgen@8261
|
453 |
|
jorgen@8261
|
454 |
DLog("(%g, %g)", x, y);
|
jorgen@8261
|
455 |
}
|
jorgen@8261
|
456 |
|
jorgen@8261
|
457 |
void
|
slouken@5058
|
458 |
Cocoa_QuitMouse(_THIS)
|
slouken@5058
|
459 |
{
|
jorgen@7114
|
460 |
SDL_Mouse *mouse = SDL_GetMouse();
|
jorgen@7114
|
461 |
if (mouse) {
|
jorgen@7593
|
462 |
if (mouse->driverdata) {
|
jorgen@7593
|
463 |
Cocoa_QuitMouseEventTap(((SDL_MouseData*)mouse->driverdata));
|
jorgen@7593
|
464 |
}
|
jorgen@7593
|
465 |
|
jorgen@7114
|
466 |
SDL_free(mouse->driverdata);
|
jorgen@7114
|
467 |
}
|
slouken@5058
|
468 |
}
|
slouken@5058
|
469 |
|
slouken@6044
|
470 |
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
slouken@6044
|
471 |
|
slouken@1931
|
472 |
/* vi: set ts=4 sw=4 expandtab: */
|