src/video/cocoa/SDL_cocoamouse.m
author Ryan C. Gordon <icculus@icculus.org>
Tue, 02 Jul 2019 12:29:36 -0400
changeset 12923 73091a9e72f7
parent 12883 72ab279ffcaa
child 12929 d6c5eb7a0afb
permissions -rw-r--r--
cocoa: Don't report trackpad mouse events as synthesized touches.

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