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_InitMouse(_THIS);
|
||||||
extern void Cocoa_HandleMouseEvent(_THIS, NSEvent * event);
|
extern void Cocoa_HandleMouseEvent(_THIS, NSEvent * event);
|
||||||
extern void Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent * event);
|
extern void Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent * event);
|
||||||
|
extern void Cocoa_HandleMouseWarp(CGFloat x, CGFloat y);
|
||||||
extern void Cocoa_QuitMouse(_THIS);
|
extern void Cocoa_QuitMouse(_THIS);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int deltaXOffset;
|
/* Wether we've seen a cursor warp since the last move event. */
|
||||||
int deltaYOffset;
|
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;
|
void *tapdata;
|
||||||
} SDL_MouseData;
|
} SDL_MouseData;
|
||||||
|
|
||||||
|
|
|
@ -223,16 +223,7 @@ Cocoa_WarpMouse(SDL_Window * window, int x, int y)
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
CGPoint point = CGPointMake(x + (float)window->x, y + (float)window->y);
|
CGPoint point = CGPointMake(x + (float)window->x, y + (float)window->y);
|
||||||
|
|
||||||
{
|
Cocoa_HandleMouseWarp(point.x, point.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* According to the docs, this was deprecated in 10.6, but it's still
|
/* 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
|
* around. The substitute requires a CGEventSource, but I'm not entirely
|
||||||
|
@ -285,18 +276,16 @@ Cocoa_InitMouse(_THIS)
|
||||||
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
|
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
|
||||||
|
|
||||||
Cocoa_InitMouseEventTap(mouse->driverdata);
|
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
|
void
|
||||||
Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
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])
|
switch ([event type])
|
||||||
{
|
{
|
||||||
case NSMouseMoved:
|
case NSMouseMoved:
|
||||||
|
@ -310,6 +299,24 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
||||||
return;
|
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.) */
|
/* Ignore events that aren't inside the client area (i.e. title bar.) */
|
||||||
if ([event window]) {
|
if ([event window]) {
|
||||||
NSRect windowRect = [[[event window] contentView] frame];
|
NSRect windowRect = [[[event window] contentView] frame];
|
||||||
|
@ -318,16 +325,18 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
|
float deltaX = [event deltaX];
|
||||||
float x = [event deltaX] + driverdata->deltaXOffset;
|
float deltaY = [event deltaY];
|
||||||
float y = [event deltaY] + driverdata->deltaYOffset;
|
|
||||||
driverdata->deltaXOffset = driverdata->deltaYOffset = 0;
|
|
||||||
|
|
||||||
if (driverdata->deltaYOffset > 0 || driverdata->deltaXOffset > 0) {
|
if (seenWarp)
|
||||||
DLog("Relative move was (%g, %g), offset to (%g, %g)", [event deltaX], [event deltaY], x, y);
|
{
|
||||||
|
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
|
void
|
||||||
|
@ -351,6 +360,20 @@ Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
|
||||||
SDL_SendMouseWheel(window, mouse->mouseID, (int)x, (int)y);
|
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
|
void
|
||||||
Cocoa_QuitMouse(_THIS)
|
Cocoa_QuitMouse(_THIS)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,15 @@
|
||||||
#include "SDL_cocoamouse.h"
|
#include "SDL_cocoamouse.h"
|
||||||
#include "SDL_cocoaopengl.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
|
@interface SDLWindow : NSWindow
|
||||||
/* These are needed for borderless/fullscreen windows */
|
/* These are needed for borderless/fullscreen windows */
|
||||||
- (BOOL)canBecomeKeyWindow;
|
- (BOOL)canBecomeKeyWindow;
|
||||||
|
@ -735,6 +744,8 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
||||||
CGSetLocalEventsSuppressionInterval(0.0);
|
CGSetLocalEventsSuppressionInterval(0.0);
|
||||||
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
|
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
|
||||||
CGSetLocalEventsSuppressionInterval(0.25);
|
CGSetLocalEventsSuppressionInterval(0.25);
|
||||||
|
|
||||||
|
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1411,6 +1422,10 @@ Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
|
||||||
SDL_GetMouseState(&x, &y);
|
SDL_GetMouseState(&x, &y);
|
||||||
cgpoint.x = window->x + x;
|
cgpoint.x = window->x + x;
|
||||||
cgpoint.y = window->y + y;
|
cgpoint.y = window->y + y;
|
||||||
|
|
||||||
|
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
|
||||||
|
|
||||||
|
DLog("Returning cursor to (%g, %g)", cgpoint.x, cgpoint.y);
|
||||||
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
|
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue