src/video/cocoa/SDL_cocoamouse.m
author Ryan C. Gordon <icculus@icculus.org>
Fri, 17 Jul 2015 21:03:58 -0400
changeset 9807 57b448735f48
parent 9692 1982dc994254
child 9998 f67cf37e9cd4
permissions -rw-r--r--
SDL_WarpMouseGlobal() should return non-void.

There are platforms it isn't implemented on (and currently can't be
implemented on!), and there's currently no way for an app to know this.

This shouldn't break ABI on apps that moved to a revision between 2.0.3 and
2.0.4.
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@6848
    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];
alexey@6832
   106
        }
slouken@6848
   107
    }
alexey@6832
   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
icculus@9807
   213
static int
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];
icculus@9807
   222
            return 0;
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
    }
icculus@9807
   248
icculus@9807
   249
    return 0;
slouken@8815
   250
}
slouken@8815
   251
slouken@9086
   252
static void
slouken@9086
   253
Cocoa_WarpMouse(SDL_Window * window, int x, int y)
slouken@9086
   254
{
slouken@9086
   255
    Cocoa_WarpMouseGlobal(x + window->x, y + window->y);
slouken@9086
   256
}
slouken@9086
   257
slouken@5406
   258
static int
slouken@5406
   259
Cocoa_SetRelativeMouseMode(SDL_bool enabled)
slouken@5406
   260
{
jorgen@8262
   261
    /* We will re-apply the relative mode when the window gets focus, if it
jorgen@8262
   262
     * doesn't have focus right now.
jorgen@8262
   263
     */
jorgen@8262
   264
    SDL_Window *window = SDL_GetMouseFocus();
jorgen@8262
   265
    if (!window) {
jorgen@8262
   266
      return 0;
jorgen@8262
   267
    }
jorgen@8262
   268
jorgen@8262
   269
    /* We will re-apply the relative mode when the window finishes being moved,
jorgen@8262
   270
     * if it is being moved right now.
jorgen@8262
   271
     */
jorgen@8262
   272
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
jorgen@8262
   273
    if ([data->listener isMoving]) {
jorgen@8263
   274
        return 0;
jorgen@8262
   275
    }
jorgen@8262
   276
slouken@5406
   277
    CGError result;
slouken@5406
   278
    if (enabled) {
jorgen@8260
   279
        DLog("Turning on.");
slouken@5406
   280
        result = CGAssociateMouseAndMouseCursorPosition(NO);
slouken@5406
   281
    } else {
jorgen@8260
   282
        DLog("Turning off.");
slouken@5406
   283
        result = CGAssociateMouseAndMouseCursorPosition(YES);
slouken@5406
   284
    }
slouken@5406
   285
    if (result != kCGErrorSuccess) {
icculus@7037
   286
        return SDL_SetError("CGAssociateMouseAndMouseCursorPosition() failed");
slouken@5406
   287
    }
slouken@8800
   288
slouken@8800
   289
    /* The hide/unhide calls are redundant most of the time, but they fix
slouken@8800
   290
     * https://bugzilla.libsdl.org/show_bug.cgi?id=2550
slouken@8800
   291
     */
slouken@8800
   292
    if (enabled) {
slouken@8800
   293
        [NSCursor hide];
slouken@8800
   294
    } else {
slouken@8800
   295
        [NSCursor unhide];
slouken@8800
   296
    }
slouken@5406
   297
    return 0;
slouken@5406
   298
}
slouken@5406
   299
icculus@8928
   300
static int
icculus@8928
   301
Cocoa_CaptureMouse(SDL_Window *window)
icculus@8928
   302
{
icculus@8928
   303
    /* our Cocoa event code already tracks the mouse outside the window,
icculus@8928
   304
        so all we have to do here is say "okay" and do what we always do. */
icculus@8928
   305
    return 0;
icculus@8928
   306
}
icculus@8928
   307
icculus@8951
   308
static Uint32
icculus@8952
   309
Cocoa_GetGlobalMouseState(int *x, int *y)
icculus@8951
   310
{
icculus@8951
   311
    const NSUInteger cocoaButtons = [NSEvent pressedMouseButtons];
icculus@8951
   312
    const NSPoint cocoaLocation = [NSEvent mouseLocation];
icculus@8951
   313
    Uint32 retval = 0;
icculus@8951
   314
icculus@8951
   315
    for (NSScreen *screen in [NSScreen screens]) {
icculus@8951
   316
        NSRect frame = [screen frame];
icculus@8951
   317
        if (NSPointInRect(cocoaLocation, frame)) {
icculus@8951
   318
            *x = (int) cocoaLocation.x;
icculus@8951
   319
            *y = (int) ((frame.origin.y + frame.size.height) - cocoaLocation.y);
icculus@8951
   320
            break;
icculus@8951
   321
        }
icculus@8951
   322
    }
icculus@8951
   323
icculus@8951
   324
    retval |= (cocoaButtons & (1 << 0)) ? SDL_BUTTON_LMASK : 0;
icculus@8951
   325
    retval |= (cocoaButtons & (1 << 1)) ? SDL_BUTTON_RMASK : 0;
icculus@8951
   326
    retval |= (cocoaButtons & (1 << 2)) ? SDL_BUTTON_MMASK : 0;
icculus@8951
   327
    retval |= (cocoaButtons & (1 << 3)) ? SDL_BUTTON_X1MASK : 0;
icculus@8951
   328
    retval |= (cocoaButtons & (1 << 4)) ? SDL_BUTTON_X2MASK : 0;
icculus@8951
   329
icculus@8951
   330
    return retval;
icculus@8951
   331
}
icculus@8951
   332
slouken@1931
   333
void
slouken@1931
   334
Cocoa_InitMouse(_THIS)
slouken@1931
   335
{
slouken@5376
   336
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@5376
   337
jorgen@7114
   338
    mouse->driverdata = SDL_calloc(1, sizeof(SDL_MouseData));
jorgen@7114
   339
slouken@5376
   340
    mouse->CreateCursor = Cocoa_CreateCursor;
slouken@6676
   341
    mouse->CreateSystemCursor = Cocoa_CreateSystemCursor;
slouken@5376
   342
    mouse->ShowCursor = Cocoa_ShowCursor;
slouken@5406
   343
    mouse->FreeCursor = Cocoa_FreeCursor;
slouken@5376
   344
    mouse->WarpMouse = Cocoa_WarpMouse;
slouken@8815
   345
    mouse->WarpMouseGlobal = Cocoa_WarpMouseGlobal;
slouken@5406
   346
    mouse->SetRelativeMouseMode = Cocoa_SetRelativeMouseMode;
icculus@8928
   347
    mouse->CaptureMouse = Cocoa_CaptureMouse;
icculus@8952
   348
    mouse->GetGlobalMouseState = Cocoa_GetGlobalMouseState;
slouken@5376
   349
slouken@5405
   350
    SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
jorgen@7593
   351
jorgen@7593
   352
    Cocoa_InitMouseEventTap(mouse->driverdata);
jorgen@8261
   353
jorgen@8261
   354
    SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
jorgen@8261
   355
    const NSPoint location =  [NSEvent mouseLocation];
jorgen@8261
   356
    driverdata->lastMoveX = location.x;
jorgen@8261
   357
    driverdata->lastMoveY = location.y;
slouken@1931
   358
}
slouken@1931
   359
slouken@3517
   360
void
slouken@3517
   361
Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
slouken@3517
   362
{
slouken@8986
   363
    switch ([event type]) {
jorgen@8260
   364
        case NSMouseMoved:
jorgen@8260
   365
        case NSLeftMouseDragged:
jorgen@8260
   366
        case NSRightMouseDragged:
jorgen@8260
   367
        case NSOtherMouseDragged:
jorgen@8260
   368
            break;
jorgen@8260
   369
jorgen@8260
   370
        default:
jorgen@8260
   371
            /* Ignore any other events. */
jorgen@8260
   372
            return;
slouken@5406
   373
    }
jorgen@8260
   374
jorgen@8261
   375
    SDL_Mouse *mouse = SDL_GetMouse();
icculus@8862
   376
    SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
icculus@8862
   377
    if (!driverdata) {
icculus@8862
   378
        return;  /* can happen when returning from fullscreen Space on shutdown */
icculus@8862
   379
    }
jorgen@8261
   380
jorgen@8261
   381
    const SDL_bool seenWarp = driverdata->seenWarp;
jorgen@8261
   382
    driverdata->seenWarp = NO;
jorgen@8261
   383
jorgen@8261
   384
    const NSPoint location =  [NSEvent mouseLocation];
jorgen@8261
   385
    const CGFloat lastMoveX = driverdata->lastMoveX;
jorgen@8261
   386
    const CGFloat lastMoveY = driverdata->lastMoveY;
jorgen@8261
   387
    driverdata->lastMoveX = location.x;
jorgen@8261
   388
    driverdata->lastMoveY = location.y;
jorgen@8261
   389
    DLog("Last seen mouse: (%g, %g)", location.x, location.y);
jorgen@8261
   390
jorgen@8261
   391
    /* Non-relative movement is handled in -[Cocoa_WindowListener mouseMoved:] */
jorgen@8261
   392
    if (!mouse->relative_mode) {
jorgen@8261
   393
        return;
jorgen@8261
   394
    }
jorgen@8261
   395
jorgen@8260
   396
    /* Ignore events that aren't inside the client area (i.e. title bar.) */
jorgen@8260
   397
    if ([event window]) {
jorgen@8260
   398
        NSRect windowRect = [[[event window] contentView] frame];
jorgen@8260
   399
        if (!NSPointInRect([event locationInWindow], windowRect)) {
jorgen@8260
   400
            return;
jorgen@8260
   401
        }
jorgen@8260
   402
    }
jorgen@8260
   403
jorgen@8261
   404
    float deltaX = [event deltaX];
jorgen@8261
   405
    float deltaY = [event deltaY];
jorgen@8260
   406
slouken@8986
   407
    if (seenWarp) {
jorgen@8261
   408
        deltaX += (lastMoveX - driverdata->lastWarpX);
jorgen@8261
   409
        deltaY += ((CGDisplayPixelsHigh(kCGDirectMainDisplay) - lastMoveY) - driverdata->lastWarpY);
jorgen@8261
   410
jorgen@8261
   411
        DLog("Motion was (%g, %g), offset to (%g, %g)", [event deltaX], [event deltaY], deltaX, deltaY);
jorgen@8260
   412
    }
jorgen@8260
   413
jorgen@8261
   414
    SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, (int)deltaX, (int)deltaY);
slouken@3517
   415
}
slouken@3517
   416
slouken@1931
   417
void
gzjjgod@5057
   418
Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
gzjjgod@5057
   419
{
slouken@6950
   420
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@6950
   421
slouken@8232
   422
    float x = -[event deltaX];
gzjjgod@5057
   423
    float y = [event deltaY];
urkle@9257
   424
    SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL;
urkle@9257
   425
urkle@9257
   426
    if ([event respondsToSelector:@selector(isDirectionInvertedFromDevice)]) {
urkle@9257
   427
        if ([event isDirectionInvertedFromDevice] == YES) {
urkle@9257
   428
            direction = SDL_MOUSEWHEEL_FLIPPED;
urkle@9257
   429
        }
urkle@9257
   430
    }
gzjjgod@5057
   431
gzjjgod@5057
   432
    if (x > 0) {
gzjjgod@5057
   433
        x += 0.9f;
gzjjgod@5057
   434
    } else if (x < 0) {
gzjjgod@5057
   435
        x -= 0.9f;
gzjjgod@5057
   436
    }
gzjjgod@5057
   437
    if (y > 0) {
gzjjgod@5057
   438
        y += 0.9f;
gzjjgod@5057
   439
    } else if (y < 0) {
gzjjgod@5057
   440
        y -= 0.9f;
gzjjgod@5057
   441
    }
urkle@9257
   442
    SDL_SendMouseWheel(window, mouse->mouseID, (int)x, (int)y, direction);
gzjjgod@5057
   443
}
gzjjgod@5057
   444
slouken@5058
   445
void
jorgen@8261
   446
Cocoa_HandleMouseWarp(CGFloat x, CGFloat y)
jorgen@8261
   447
{
jorgen@8261
   448
    /* This makes Cocoa_HandleMouseEvent ignore the delta caused by the warp,
jorgen@8261
   449
     * since it gets included in the next movement event.
jorgen@8261
   450
     */
jorgen@8261
   451
    SDL_MouseData *driverdata = (SDL_MouseData*)SDL_GetMouse()->driverdata;
jorgen@8261
   452
    driverdata->lastWarpX = x;
jorgen@8261
   453
    driverdata->lastWarpY = y;
jorgen@8261
   454
    driverdata->seenWarp = SDL_TRUE;
jorgen@8261
   455
jorgen@8261
   456
    DLog("(%g, %g)", x, y);
jorgen@8261
   457
}
jorgen@8261
   458
jorgen@8261
   459
void
slouken@5058
   460
Cocoa_QuitMouse(_THIS)
slouken@5058
   461
{
jorgen@7114
   462
    SDL_Mouse *mouse = SDL_GetMouse();
jorgen@7114
   463
    if (mouse) {
jorgen@7593
   464
        if (mouse->driverdata) {
jorgen@7593
   465
            Cocoa_QuitMouseEventTap(((SDL_MouseData*)mouse->driverdata));
jorgen@7593
   466
        }
jorgen@7593
   467
jorgen@7114
   468
        SDL_free(mouse->driverdata);
jorgen@7114
   469
    }
slouken@5058
   470
}
slouken@5058
   471
slouken@6044
   472
#endif /* SDL_VIDEO_DRIVER_COCOA */
slouken@6044
   473
slouken@1931
   474
/* vi: set ts=4 sw=4 expandtab: */