mirror of https://github.com/encounter/SDL.git
Mac: Redo cursor warp handling.
This fixes bugs related to getting unnaturally large xrel/yrel for SDL_MOUSEMOTION after warps and enabling / disabling relative mode. Bug: https://bugzilla.libsdl.org/show_bug.cgi?id=1836
This commit is contained in:
parent
52a63e823f
commit
4850d25988
|
@ -28,11 +28,18 @@
|
|||
extern void Cocoa_InitMouse(_THIS);
|
||||
extern void Cocoa_HandleMouseEvent(_THIS, NSEvent * event);
|
||||
extern void Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent * event);
|
||||
extern void Cocoa_HandleMouseWarp(CGFloat x, CGFloat y);
|
||||
extern void Cocoa_QuitMouse(_THIS);
|
||||
|
||||
typedef struct {
|
||||
int deltaXOffset;
|
||||
int deltaYOffset;
|
||||
/* Wether we've seen a cursor warp since the last move event. */
|
||||
SDL_bool seenWarp;
|
||||
/* What location our last cursor warp was to. */
|
||||
CGFloat lastWarpX;
|
||||
CGFloat lastWarpY;
|
||||
/* What location we last saw the cursor move to. */
|
||||
CGFloat lastMoveX;
|
||||
CGFloat lastMoveY;
|
||||
void *tapdata;
|
||||
} SDL_MouseData;
|
||||
|
||||
|
|
|
@ -223,16 +223,7 @@ Cocoa_WarpMouse(SDL_Window * window, int x, int y)
|
|||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
CGPoint point = CGPointMake(x + (float)window->x, y + (float)window->y);
|
||||
|
||||
{
|
||||
/* This makes Cocoa_HandleMouseEvent ignore this delta in the next
|
||||
* movement event.
|
||||
*/
|
||||
SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
|
||||
NSPoint location = [NSEvent mouseLocation];
|
||||
driverdata->deltaXOffset = location.x - point.x;
|
||||
driverdata->deltaYOffset = point.y - location.y;
|
||||
DLog("Warp to (%g, %g), offsetting next movement event by (%i, %i)", point.x, point.y, driverdata->deltaXOffset, driverdata->deltaYOffset);
|
||||
}
|
||||
Cocoa_HandleMouseWarp(point.x, point.y);
|
||||
|
||||
/* According to the docs, this was deprecated in 10.6, but it's still
|
||||
* around. The substitute requires a CGEventSource, but I'm not entirely
|
||||
|
@ -285,18 +276,16 @@ Cocoa_InitMouse(_THIS)
|
|||
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
|
||||
|
||||
Cocoa_InitMouseEventTap(mouse->driverdata);
|
||||
|
||||
SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
|
||||
const NSPoint location = [NSEvent mouseLocation];
|
||||
driverdata->lastMoveX = location.x;
|
||||
driverdata->lastMoveY = location.y;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
/* Non-relative movement is handled in -[Cocoa_WindowListener mouseMoved:] */
|
||||
if (!mouse->relative_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch ([event type])
|
||||
{
|
||||
case NSMouseMoved:
|
||||
|
@ -310,6 +299,24 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
|||
return;
|
||||
}
|
||||
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
|
||||
const SDL_bool seenWarp = driverdata->seenWarp;
|
||||
driverdata->seenWarp = NO;
|
||||
|
||||
const NSPoint location = [NSEvent mouseLocation];
|
||||
const CGFloat lastMoveX = driverdata->lastMoveX;
|
||||
const CGFloat lastMoveY = driverdata->lastMoveY;
|
||||
driverdata->lastMoveX = location.x;
|
||||
driverdata->lastMoveY = location.y;
|
||||
DLog("Last seen mouse: (%g, %g)", location.x, location.y);
|
||||
|
||||
/* Non-relative movement is handled in -[Cocoa_WindowListener mouseMoved:] */
|
||||
if (!mouse->relative_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore events that aren't inside the client area (i.e. title bar.) */
|
||||
if ([event window]) {
|
||||
NSRect windowRect = [[[event window] contentView] frame];
|
||||
|
@ -318,16 +325,18 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
|
||||
float x = [event deltaX] + driverdata->deltaXOffset;
|
||||
float y = [event deltaY] + driverdata->deltaYOffset;
|
||||
driverdata->deltaXOffset = driverdata->deltaYOffset = 0;
|
||||
float deltaX = [event deltaX];
|
||||
float deltaY = [event deltaY];
|
||||
|
||||
if (driverdata->deltaYOffset > 0 || driverdata->deltaXOffset > 0) {
|
||||
DLog("Relative move was (%g, %g), offset to (%g, %g)", [event deltaX], [event deltaY], x, y);
|
||||
if (seenWarp)
|
||||
{
|
||||
deltaX += (lastMoveX - driverdata->lastWarpX);
|
||||
deltaY += ((CGDisplayPixelsHigh(kCGDirectMainDisplay) - lastMoveY) - driverdata->lastWarpY);
|
||||
|
||||
DLog("Motion was (%g, %g), offset to (%g, %g)", [event deltaX], [event deltaY], deltaX, deltaY);
|
||||
}
|
||||
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, (int)x, (int)y);
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, (int)deltaX, (int)deltaY);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -351,6 +360,20 @@ Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
|
|||
SDL_SendMouseWheel(window, mouse->mouseID, (int)x, (int)y);
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_HandleMouseWarp(CGFloat x, CGFloat y)
|
||||
{
|
||||
/* This makes Cocoa_HandleMouseEvent ignore the delta caused by the warp,
|
||||
* since it gets included in the next movement event.
|
||||
*/
|
||||
SDL_MouseData *driverdata = (SDL_MouseData*)SDL_GetMouse()->driverdata;
|
||||
driverdata->lastWarpX = x;
|
||||
driverdata->lastWarpY = y;
|
||||
driverdata->seenWarp = SDL_TRUE;
|
||||
|
||||
DLog("(%g, %g)", x, y);
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_QuitMouse(_THIS)
|
||||
{
|
||||
|
|
|
@ -39,6 +39,15 @@
|
|||
#include "SDL_cocoamouse.h"
|
||||
#include "SDL_cocoaopengl.h"
|
||||
|
||||
/* #define DEBUG_COCOAWINDOW */
|
||||
|
||||
#ifdef DEBUG_COCOAWINDOW
|
||||
#define DLog(fmt, ...) printf("%s: " fmt "\n", __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DLog(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
@interface SDLWindow : NSWindow
|
||||
/* These are needed for borderless/fullscreen windows */
|
||||
- (BOOL)canBecomeKeyWindow;
|
||||
|
@ -735,6 +744,8 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
CGSetLocalEventsSuppressionInterval(0.0);
|
||||
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
|
||||
CGSetLocalEventsSuppressionInterval(0.25);
|
||||
|
||||
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1411,6 +1422,10 @@ Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
|
|||
SDL_GetMouseState(&x, &y);
|
||||
cgpoint.x = window->x + x;
|
||||
cgpoint.y = window->y + y;
|
||||
|
||||
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
|
||||
|
||||
DLog("Returning cursor to (%g, %g)", cgpoint.x, cgpoint.y);
|
||||
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue