src/video/cocoa/SDL_cocoamouse.m
author Sam Lantinga <slouken@libsdl.org>
Sun, 17 Aug 2014 14:57:52 -0700
changeset 9086 c5e33f9a0d03
parent 8986 1c81316ac642
child 9087 eef2e43f60d1
permissions -rw-r--r--
Fixed bug 2655 - OSX: Window position and global mouse coord spaces are different

Tim McDaniel

On OSX, with revision 8729, the coordinate space for window position and the coordinate space for global mouse position don't match. For a non-fullscreen window, the window position is global relative to the bottom of the menubar. The global mouse position is relative to the top of the screen. This affects Cocoa_WarpMouse and potentially other things as well. Further, the coordinate system for window position is now affected by what screen it is on. For example, if I have two equal size screens oriented side by side such that the tops of the screens are equal in global space, with the menubar on one screen, and a window straddles the two screens, the window's y position makes no sense. The window's y position depends on what screen "most" of the window is on. So if I move the window horizontally just a bit, the y position of my window is now different by the size of the menubar, even though the window was not moved vertically.

I'd like to reiterate that this was a fairly fundamental change (and a breaking change for us). If SDL OSX is to really support multi-display configurations, this is especially problematic.

If the real concern is preventing windows from going under the menubar, then perhaps a solution involving something like overriding [NSWindow constrainFrameRect] would be less problematic than redefining the global window coord space for the main display.
slouken@1931
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 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@5376
    69
{
slouken@6848
    70
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
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
    [pool release];
slouken@6848
    85
slouken@6848
    86
    return cursor;
slouken@5376
    87
}
slouken@5376
    88
slouken@5376
    89
static SDL_Cursor *
slouken@5376
    90
Cocoa_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
slouken@5376
    91
{
slouken@6848
    92
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
    93
    NSImage *nsimage;
slouken@6848
    94
    NSCursor *nscursor = NULL;
slouken@6848
    95
    SDL_Cursor *cursor = NULL;
slouken@5376
    96
slouken@6848
    97
    nsimage = Cocoa_CreateImage(surface);
slouken@6848
    98
    if (nsimage) {
slouken@6848
    99
        nscursor = [[NSCursor alloc] initWithImage: nsimage hotSpot: NSMakePoint(hot_x, hot_y)];
slouken@6848
   100
    }
slouken@6848
   101
slouken@6848
   102
    if (nscursor) {
slouken@6848
   103
        cursor = SDL_calloc(1, sizeof(*cursor));
slouken@6848
   104
        if (cursor) {
slouken@6848
   105
            cursor->driverdata = nscursor;
jorgen@7593
   106
        } else {
jorgen@7593
   107
            [nscursor release];
alexey@6832
   108
        }
slouken@6848
   109
    }
alexey@6832
   110
slouken@6848
   111
    [pool release];
slouken@6848
   112
slouken@6848
   113
    return cursor;
slouken@5376
   114
}
slouken@5376
   115
slouken@6676
   116
static SDL_Cursor *
slouken@6676
   117
Cocoa_CreateSystemCursor(SDL_SystemCursor id)
slouken@6676
   118
{
slouken@6848
   119
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   120
    NSCursor *nscursor = NULL;
slouken@6848
   121
    SDL_Cursor *cursor = NULL;
slouken@6676
   122
slouken@8986
   123
    switch(id) {
slouken@6848
   124
    case SDL_SYSTEM_CURSOR_ARROW:
slouken@6848
   125
        nscursor = [NSCursor arrowCursor];
slouken@6848
   126
        break;
slouken@6848
   127
    case SDL_SYSTEM_CURSOR_IBEAM:
slouken@6848
   128
        nscursor = [NSCursor IBeamCursor];
slouken@6848
   129
        break;
slouken@6848
   130
    case SDL_SYSTEM_CURSOR_WAIT:
slouken@6848
   131
        nscursor = [NSCursor arrowCursor];
slouken@6848
   132
        break;
slouken@6848
   133
    case SDL_SYSTEM_CURSOR_CROSSHAIR:
slouken@6848
   134
        nscursor = [NSCursor crosshairCursor];
slouken@6848
   135
        break;
slouken@6848
   136
    case SDL_SYSTEM_CURSOR_WAITARROW:
slouken@6848
   137
        nscursor = [NSCursor arrowCursor];
slouken@6848
   138
        break;
slouken@6848
   139
    case SDL_SYSTEM_CURSOR_SIZENWSE:
slouken@6848
   140
    case SDL_SYSTEM_CURSOR_SIZENESW:
slouken@6848
   141
        nscursor = [NSCursor closedHandCursor];
slouken@6848
   142
        break;
slouken@6848
   143
    case SDL_SYSTEM_CURSOR_SIZEWE:
slouken@6848
   144
        nscursor = [NSCursor resizeLeftRightCursor];
slouken@6848
   145
        break;
slouken@6848
   146
    case SDL_SYSTEM_CURSOR_SIZENS:
slouken@6848
   147
        nscursor = [NSCursor resizeUpDownCursor];
slouken@6848
   148
        break;
slouken@6848
   149
    case SDL_SYSTEM_CURSOR_SIZEALL:
slouken@6848
   150
        nscursor = [NSCursor closedHandCursor];
slouken@6848
   151
        break;
slouken@6848
   152
    case SDL_SYSTEM_CURSOR_NO:
slouken@6848
   153
        nscursor = [NSCursor operationNotAllowedCursor];
slouken@6848
   154
        break;
slouken@6848
   155
    case SDL_SYSTEM_CURSOR_HAND:
slouken@6848
   156
        nscursor = [NSCursor pointingHandCursor];
slouken@6848
   157
        break;
slouken@6848
   158
    default:
slouken@6848
   159
        SDL_assert(!"Unknown system cursor");
slouken@6848
   160
        return NULL;
slouken@6848
   161
    }
slouken@6848
   162
slouken@6848
   163
    if (nscursor) {
slouken@6848
   164
        cursor = SDL_calloc(1, sizeof(*cursor));
slouken@6848
   165
        if (cursor) {
slouken@7191
   166
            /* We'll free it later, so retain it here */
slouken@6848
   167
            [nscursor retain];
slouken@6848
   168
            cursor->driverdata = nscursor;
alexey@6832
   169
        }
slouken@6848
   170
    }
alexey@6832
   171
slouken@6848
   172
    [pool release];
slouken@6848
   173
slouken@6848
   174
    return cursor;
slouken@6676
   175
}
slouken@6676
   176
slouken@5376
   177
static void
slouken@5376
   178
Cocoa_FreeCursor(SDL_Cursor * cursor)
slouken@5376
   179
{
slouken@6848
   180
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   181
    NSCursor *nscursor = (NSCursor *)cursor->driverdata;
slouken@5376
   182
slouken@6848
   183
    [nscursor release];
slouken@6848
   184
    SDL_free(cursor);
slouken@6848
   185
slouken@6848
   186
    [pool release];
slouken@5376
   187
}
slouken@5376
   188
slouken@5376
   189
static int
slouken@5376
   190
Cocoa_ShowCursor(SDL_Cursor * cursor)
slouken@5376
   191
{
slouken@6848
   192
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@5376
   193
jorgen@7158
   194
    SDL_VideoDevice *device = SDL_GetVideoDevice();
jorgen@7158
   195
    SDL_Window *window = (device ? device->windows : NULL);
jorgen@7158
   196
    for (; window != NULL; window = window->next) {
jorgen@7158
   197
        SDL_WindowData *driverdata = (SDL_WindowData *)window->driverdata;
jorgen@7158
   198
        if (driverdata) {
jorgen@7158
   199
            [driverdata->nswindow performSelectorOnMainThread:@selector(invalidateCursorRectsForView:)
jorgen@7158
   200
                                                   withObject:[driverdata->nswindow contentView]
jorgen@7158
   201
                                                waitUntilDone:NO];
jorgen@7158
   202
        }
slouken@5376
   203
    }
slouken@5376
   204
slouken@6848
   205
    [pool release];
slouken@6848
   206
slouken@5376
   207
    return 0;
slouken@5376
   208
}
slouken@5376
   209
slouken@5376
   210
static void
slouken@8815
   211
Cocoa_WarpMouseGlobal(int x, int y)
slouken@8815
   212
{
slouken@8815
   213
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@9086
   214
    if (mouse->focus) {
slouken@9086
   215
        SDL_WindowData *data = (SDL_WindowData *) mouse->focus->driverdata;
slouken@9086
   216
        if ([data->listener isMoving]) {
slouken@9086
   217
            DLog("Postponing warp, window being moved.");
slouken@9086
   218
            [data->listener setPendingMoveX:x Y:y];
slouken@9086
   219
            return;
slouken@9086
   220
        }
slouken@9086
   221
    }
slouken@8815
   222
    CGPoint point = CGPointMake((float)x, (float)y);
slouken@8815
   223
slouken@8815
   224
    Cocoa_HandleMouseWarp(point.x, point.y);
slouken@8815
   225
slouken@8815
   226
    /* According to the docs, this was deprecated in 10.6, but it's still
slouken@8815
   227
     * around. The substitute requires a CGEventSource, but I'm not entirely
slouken@8815
   228
     * sure how we'd procure the right one for this event.
slouken@8815
   229
     */
slouken@8815
   230
    CGSetLocalEventsSuppressionInterval(0.0);
slouken@8815
   231
    CGWarpMouseCursorPosition(point);
slouken@8815
   232
    CGSetLocalEventsSuppressionInterval(0.25);
slouken@8815
   233
slouken@8815
   234
    if (!mouse->relative_mode && mouse->focus) {
slouken@8815
   235
        /* CGWarpMouseCursorPosition doesn't generate a window event, unlike our
slouken@8815
   236
         * other implementations' APIs.
slouken@8815
   237
         */
slouken@8816
   238
        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x - mouse->focus->x, y - mouse->focus->y);
slouken@8815
   239
    }
slouken@8815
   240
}
slouken@8815
   241
slouken@9086
   242
static void
slouken@9086
   243
Cocoa_WarpMouse(SDL_Window * window, int x, int y)
slouken@9086
   244
{
slouken@9086
   245
    Cocoa_WarpMouseGlobal(x + window->x, y + window->y);
slouken@9086
   246
}
slouken@9086
   247
slouken@5406
   248
static int
slouken@5406
   249
Cocoa_SetRelativeMouseMode(SDL_bool enabled)
slouken@5406
   250
{
jorgen@8262
   251
    /* We will re-apply the relative mode when the window gets focus, if it
jorgen@8262
   252
     * doesn't have focus right now.
jorgen@8262
   253
     */
jorgen@8262
   254
    SDL_Window *window = SDL_GetMouseFocus();
jorgen@8262
   255
    if (!window) {
jorgen@8262
   256
      return 0;
jorgen@8262
   257
    }
jorgen@8262
   258
jorgen@8262
   259
    /* We will re-apply the relative mode when the window finishes being moved,
jorgen@8262
   260
     * if it is being moved right now.
jorgen@8262
   261
     */
jorgen@8262
   262
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
jorgen@8262
   263
    if ([data->listener isMoving]) {
jorgen@8263
   264
        return 0;
jorgen@8262
   265
    }
jorgen@8262
   266
slouken@5406
   267
    CGError result;
slouken@5406
   268
    if (enabled) {
jorgen@8260
   269
        DLog("Turning on.");
slouken@5406
   270
        result = CGAssociateMouseAndMouseCursorPosition(NO);
slouken@5406
   271
    } else {
jorgen@8260
   272
        DLog("Turning off.");
slouken@5406
   273
        result = CGAssociateMouseAndMouseCursorPosition(YES);
slouken@5406
   274
    }
slouken@5406
   275
    if (result != kCGErrorSuccess) {
icculus@7037
   276
        return SDL_SetError("CGAssociateMouseAndMouseCursorPosition() failed");
slouken@5406
   277
    }
slouken@8800
   278
slouken@8800
   279
    /* The hide/unhide calls are redundant most of the time, but they fix
slouken@8800
   280
     * https://bugzilla.libsdl.org/show_bug.cgi?id=2550
slouken@8800
   281
     */
slouken@8800
   282
    if (enabled) {
slouken@8800
   283
        [NSCursor hide];
slouken@8800
   284
    } else {
slouken@8800
   285
        [NSCursor unhide];
slouken@8800
   286
    }
slouken@5406
   287
    return 0;
slouken@5406
   288
}
slouken@5406
   289
icculus@8928
   290
static int
icculus@8928
   291
Cocoa_CaptureMouse(SDL_Window *window)
icculus@8928
   292
{
icculus@8928
   293
    /* our Cocoa event code already tracks the mouse outside the window,
icculus@8928
   294
        so all we have to do here is say "okay" and do what we always do. */
icculus@8928
   295
    return 0;
icculus@8928
   296
}
icculus@8928
   297
icculus@8951
   298
static Uint32
icculus@8952
   299
Cocoa_GetGlobalMouseState(int *x, int *y)
icculus@8951
   300
{
icculus@8951
   301
    const NSUInteger cocoaButtons = [NSEvent pressedMouseButtons];
icculus@8951
   302
    const NSPoint cocoaLocation = [NSEvent mouseLocation];
icculus@8951
   303
    Uint32 retval = 0;
icculus@8951
   304
icculus@8951
   305
    for (NSScreen *screen in [NSScreen screens]) {
icculus@8951
   306
        NSRect frame = [screen frame];
icculus@8951
   307
        if (NSPointInRect(cocoaLocation, frame)) {
icculus@8951
   308
            *x = (int) cocoaLocation.x;
icculus@8951
   309
            *y = (int) ((frame.origin.y + frame.size.height) - cocoaLocation.y);
icculus@8951
   310
            break;
icculus@8951
   311
        }
icculus@8951
   312
    }
icculus@8951
   313
icculus@8951
   314
    retval |= (cocoaButtons & (1 << 0)) ? SDL_BUTTON_LMASK : 0;
icculus@8951
   315
    retval |= (cocoaButtons & (1 << 1)) ? SDL_BUTTON_RMASK : 0;
icculus@8951
   316
    retval |= (cocoaButtons & (1 << 2)) ? SDL_BUTTON_MMASK : 0;
icculus@8951
   317
    retval |= (cocoaButtons & (1 << 3)) ? SDL_BUTTON_X1MASK : 0;
icculus@8951
   318
    retval |= (cocoaButtons & (1 << 4)) ? SDL_BUTTON_X2MASK : 0;
icculus@8951
   319
icculus@8951
   320
    return retval;
icculus@8951
   321
}
icculus@8951
   322
slouken@1931
   323
void
slouken@1931
   324
Cocoa_InitMouse(_THIS)
slouken@1931
   325
{
slouken@5376
   326
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@5376
   327
jorgen@7114
   328
    mouse->driverdata = SDL_calloc(1, sizeof(SDL_MouseData));
jorgen@7114
   329
slouken@5376
   330
    mouse->CreateCursor = Cocoa_CreateCursor;
slouken@6676
   331
    mouse->CreateSystemCursor = Cocoa_CreateSystemCursor;
slouken@5376
   332
    mouse->ShowCursor = Cocoa_ShowCursor;
slouken@5406
   333
    mouse->FreeCursor = Cocoa_FreeCursor;
slouken@5376
   334
    mouse->WarpMouse = Cocoa_WarpMouse;
slouken@8815
   335
    mouse->WarpMouseGlobal = Cocoa_WarpMouseGlobal;
slouken@5406
   336
    mouse->SetRelativeMouseMode = Cocoa_SetRelativeMouseMode;
icculus@8928
   337
    mouse->CaptureMouse = Cocoa_CaptureMouse;
icculus@8952
   338
    mouse->GetGlobalMouseState = Cocoa_GetGlobalMouseState;
slouken@5376
   339
slouken@5405
   340
    SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
jorgen@7593
   341
jorgen@7593
   342
    Cocoa_InitMouseEventTap(mouse->driverdata);
jorgen@8261
   343
jorgen@8261
   344
    SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
jorgen@8261
   345
    const NSPoint location =  [NSEvent mouseLocation];
jorgen@8261
   346
    driverdata->lastMoveX = location.x;
jorgen@8261
   347
    driverdata->lastMoveY = location.y;
slouken@1931
   348
}
slouken@1931
   349
slouken@3517
   350
void
slouken@3517
   351
Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
slouken@3517
   352
{
slouken@8986
   353
    switch ([event type]) {
jorgen@8260
   354
        case NSMouseMoved:
jorgen@8260
   355
        case NSLeftMouseDragged:
jorgen@8260
   356
        case NSRightMouseDragged:
jorgen@8260
   357
        case NSOtherMouseDragged:
jorgen@8260
   358
            break;
jorgen@8260
   359
jorgen@8260
   360
        default:
jorgen@8260
   361
            /* Ignore any other events. */
jorgen@8260
   362
            return;
slouken@5406
   363
    }
jorgen@8260
   364
jorgen@8261
   365
    SDL_Mouse *mouse = SDL_GetMouse();
icculus@8862
   366
    SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
icculus@8862
   367
    if (!driverdata) {
icculus@8862
   368
        return;  /* can happen when returning from fullscreen Space on shutdown */
icculus@8862
   369
    }
jorgen@8261
   370
jorgen@8261
   371
    const SDL_bool seenWarp = driverdata->seenWarp;
jorgen@8261
   372
    driverdata->seenWarp = NO;
jorgen@8261
   373
jorgen@8261
   374
    const NSPoint location =  [NSEvent mouseLocation];
jorgen@8261
   375
    const CGFloat lastMoveX = driverdata->lastMoveX;
jorgen@8261
   376
    const CGFloat lastMoveY = driverdata->lastMoveY;
jorgen@8261
   377
    driverdata->lastMoveX = location.x;
jorgen@8261
   378
    driverdata->lastMoveY = location.y;
jorgen@8261
   379
    DLog("Last seen mouse: (%g, %g)", location.x, location.y);
jorgen@8261
   380
jorgen@8261
   381
    /* Non-relative movement is handled in -[Cocoa_WindowListener mouseMoved:] */
jorgen@8261
   382
    if (!mouse->relative_mode) {
jorgen@8261
   383
        return;
jorgen@8261
   384
    }
jorgen@8261
   385
jorgen@8260
   386
    /* Ignore events that aren't inside the client area (i.e. title bar.) */
jorgen@8260
   387
    if ([event window]) {
jorgen@8260
   388
        NSRect windowRect = [[[event window] contentView] frame];
jorgen@8260
   389
        if (!NSPointInRect([event locationInWindow], windowRect)) {
jorgen@8260
   390
            return;
jorgen@8260
   391
        }
jorgen@8260
   392
    }
jorgen@8260
   393
jorgen@8261
   394
    float deltaX = [event deltaX];
jorgen@8261
   395
    float deltaY = [event deltaY];
jorgen@8260
   396
slouken@8986
   397
    if (seenWarp) {
jorgen@8261
   398
        deltaX += (lastMoveX - driverdata->lastWarpX);
jorgen@8261
   399
        deltaY += ((CGDisplayPixelsHigh(kCGDirectMainDisplay) - lastMoveY) - driverdata->lastWarpY);
jorgen@8261
   400
jorgen@8261
   401
        DLog("Motion was (%g, %g), offset to (%g, %g)", [event deltaX], [event deltaY], deltaX, deltaY);
jorgen@8260
   402
    }
jorgen@8260
   403
jorgen@8261
   404
    SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, (int)deltaX, (int)deltaY);
slouken@3517
   405
}
slouken@3517
   406
slouken@1931
   407
void
gzjjgod@5057
   408
Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
gzjjgod@5057
   409
{
slouken@6950
   410
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@6950
   411
slouken@8232
   412
    float x = -[event deltaX];
gzjjgod@5057
   413
    float y = [event deltaY];
gzjjgod@5057
   414
gzjjgod@5057
   415
    if (x > 0) {
gzjjgod@5057
   416
        x += 0.9f;
gzjjgod@5057
   417
    } else if (x < 0) {
gzjjgod@5057
   418
        x -= 0.9f;
gzjjgod@5057
   419
    }
gzjjgod@5057
   420
    if (y > 0) {
gzjjgod@5057
   421
        y += 0.9f;
gzjjgod@5057
   422
    } else if (y < 0) {
gzjjgod@5057
   423
        y -= 0.9f;
gzjjgod@5057
   424
    }
slouken@6950
   425
    SDL_SendMouseWheel(window, mouse->mouseID, (int)x, (int)y);
gzjjgod@5057
   426
}
gzjjgod@5057
   427
slouken@5058
   428
void
jorgen@8261
   429
Cocoa_HandleMouseWarp(CGFloat x, CGFloat y)
jorgen@8261
   430
{
jorgen@8261
   431
    /* This makes Cocoa_HandleMouseEvent ignore the delta caused by the warp,
jorgen@8261
   432
     * since it gets included in the next movement event.
jorgen@8261
   433
     */
jorgen@8261
   434
    SDL_MouseData *driverdata = (SDL_MouseData*)SDL_GetMouse()->driverdata;
jorgen@8261
   435
    driverdata->lastWarpX = x;
jorgen@8261
   436
    driverdata->lastWarpY = y;
jorgen@8261
   437
    driverdata->seenWarp = SDL_TRUE;
jorgen@8261
   438
jorgen@8261
   439
    DLog("(%g, %g)", x, y);
jorgen@8261
   440
}
jorgen@8261
   441
jorgen@8261
   442
void
slouken@5058
   443
Cocoa_QuitMouse(_THIS)
slouken@5058
   444
{
jorgen@7114
   445
    SDL_Mouse *mouse = SDL_GetMouse();
jorgen@7114
   446
    if (mouse) {
jorgen@7593
   447
        if (mouse->driverdata) {
jorgen@7593
   448
            Cocoa_QuitMouseEventTap(((SDL_MouseData*)mouse->driverdata));
jorgen@7593
   449
        }
jorgen@7593
   450
jorgen@7114
   451
        SDL_free(mouse->driverdata);
jorgen@7114
   452
    }
slouken@5058
   453
}
slouken@5058
   454
slouken@6044
   455
#endif /* SDL_VIDEO_DRIVER_COCOA */
slouken@6044
   456
slouken@1931
   457
/* vi: set ts=4 sw=4 expandtab: */