early-access version 2281

This commit is contained in:
pineappleEA
2021-12-07 02:20:09 +01:00
parent c2ae6d480a
commit c4fa174d53
591 changed files with 36978 additions and 18653 deletions

View File

@@ -162,7 +162,7 @@ GetDisplayModePixelFormat(CGDisplayModeRef vidmode)
}
static SDL_bool
GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CFArrayRef modelist, CVDisplayLinkRef link, SDL_DisplayMode *mode)
GetDisplayMode(_THIS, CGDisplayModeRef vidmode, SDL_bool vidmodeCurrent, CFArrayRef modelist, CVDisplayLinkRef link, SDL_DisplayMode *mode)
{
SDL_DisplayModeData *data;
bool usableForGUI = CGDisplayModeIsUsableForDesktopGUI(vidmode);
@@ -178,7 +178,9 @@ GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CFArrayRef modelist, CVDisplayLi
return SDL_FALSE;
}
if (!HasValidDisplayModeFlags(vidmode)) {
/* Don't fail the current mode based on flags because this could prevent Cocoa_InitModes from
* succeeding if the current mode lacks certain flags (esp kDisplayModeSafeFlag). */
if (!vidmodeCurrent && !HasValidDisplayModeFlags(vidmode)) {
return SDL_FALSE;
}
@@ -375,7 +377,7 @@ Cocoa_InitModes(_THIS)
SDL_zero(display);
/* this returns a stddup'ed string */
display.name = (char *)Cocoa_GetDisplayName(displays[i]);
if (!GetDisplayMode(_this, moderef, NULL, link, &mode)) {
if (!GetDisplayMode(_this, moderef, SDL_TRUE, NULL, link, &mode)) {
CVDisplayLinkRelease(link);
CGDisplayModeRelease(moderef);
SDL_free(display.name);
@@ -499,7 +501,7 @@ Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
* sure there are no duplicates so it's safe to always add the desktop mode
* even in cases where it is in the CopyAllDisplayModes list.
*/
if (desktopmoderef && GetDisplayMode(_this, desktopmoderef, NULL, link, &desktopmode)) {
if (desktopmoderef && GetDisplayMode(_this, desktopmoderef, SDL_TRUE, NULL, link, &desktopmode)) {
if (!SDL_AddDisplayMode(display, &desktopmode)) {
CFRelease(((SDL_DisplayModeData*)desktopmode.driverdata)->modes);
SDL_free(desktopmode.driverdata);
@@ -546,7 +548,7 @@ Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
CGDisplayModeRef moderef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
SDL_DisplayMode mode;
if (GetDisplayMode(_this, moderef, modes, link, &mode)) {
if (GetDisplayMode(_this, moderef, SDL_FALSE, modes, link, &mode)) {
if (!SDL_AddDisplayMode(display, &mode)) {
CFRelease(((SDL_DisplayModeData*)mode.driverdata)->modes);
SDL_free(mode.driverdata);

View File

@@ -102,6 +102,8 @@ Cocoa_CreateDevice(int devindex)
device->SetWindowFullscreen = Cocoa_SetWindowFullscreen;
device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
device->GetWindowICCProfile = Cocoa_GetWindowICCProfile;
device->SetWindowMouseRect = Cocoa_SetWindowMouseRect;
device->SetWindowMouseGrab = Cocoa_SetWindowMouseGrab;
device->SetWindowKeyboardGrab = Cocoa_SetWindowKeyboardGrab;
device->DestroyWindow = Cocoa_DestroyWindow;

View File

@@ -48,7 +48,7 @@ typedef enum
BOOL inFullscreenTransition;
PendingWindowOperation pendingWindowOperation;
BOOL isMoving;
int focusClickPending;
NSInteger focusClickPending;
int pendingWindowWarpX, pendingWindowWarpY;
BOOL isDragAreaRunning;
}
@@ -64,8 +64,8 @@ typedef enum
-(BOOL) isMoving;
-(BOOL) isMovingOrFocusClickPending;
-(void) setFocusClickPending:(int) button;
-(void) clearFocusClickPending:(int) button;
-(void) setFocusClickPending:(NSInteger) button;
-(void) clearFocusClickPending:(NSInteger) button;
-(void) setPendingMoveX:(int)x Y:(int)y;
-(void) windowDidFinishMoving;
-(void) onMovingOrFocusClickPendingStateCleared;
@@ -80,6 +80,7 @@ typedef enum
-(void) windowDidBecomeKey:(NSNotification *) aNotification;
-(void) windowDidResignKey:(NSNotification *) aNotification;
-(void) windowDidChangeBackingProperties:(NSNotification *) aNotification;
-(void) windowDidChangeScreenProfile:(NSNotification *) aNotification;
-(void) windowWillEnterFullScreen:(NSNotification *) aNotification;
-(void) windowDidEnterFullScreen:(NSNotification *) aNotification;
-(void) windowWillExitFullScreen:(NSNotification *) aNotification;
@@ -151,7 +152,9 @@ extern void Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resiza
extern void Cocoa_SetWindowAlwaysOnTop(_THIS, SDL_Window * window, SDL_bool on_top);
extern void Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
extern int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
extern void* Cocoa_GetWindowICCProfile(_THIS, SDL_Window * window, size_t * size);
extern int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
extern void Cocoa_SetWindowMouseRect(_THIS, SDL_Window * window);
extern void Cocoa_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
extern void Cocoa_DestroyWindow(_THIS, SDL_Window * window);
extern SDL_bool Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info);

View File

@@ -55,9 +55,21 @@
#ifndef MAC_OS_X_VERSION_10_12
#define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask
#endif
#ifndef NSAppKitVersionNumber10_14
#define NSAppKitVersionNumber10_14 1671
#ifndef NSAppKitVersionNumber10_13_2
#define NSAppKitVersionNumber10_13_2 1561.2
#endif
#ifndef NSAppKitVersionNumber10_14
#define NSAppKitVersionNumber10_14 1671
#endif
@interface NSWindow (SDL)
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000 /* Added in the 10.10 SDK */
@property (readonly) NSRect contentLayoutRect;
#endif
/* This is available as of 10.13.2, but isn't in public headers */
@property (nonatomic) NSRect mouseConfinementRect;
@end
@interface SDLWindow : NSWindow <NSDraggingDestination>
/* These are needed for borderless/fullscreen windows */
@@ -322,6 +334,119 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
return SDL_TRUE;
}
static SDL_bool
ShouldAdjustCoordinatesForGrab(SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (!data || [data->listener isMovingOrFocusClickPending]) {
return SDL_FALSE;
}
if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
return SDL_FALSE;
}
if ((window->flags & SDL_WINDOW_MOUSE_GRABBED) || (window->mouse_rect.w > 0 && window->mouse_rect.h > 0)) {
return SDL_TRUE;
}
return SDL_FALSE;
}
static SDL_bool
AdjustCoordinatesForGrab(SDL_Window * window, int x, int y, CGPoint *adjusted)
{
if (window->mouse_rect.w > 0 && window->mouse_rect.h > 0) {
SDL_Rect window_rect;
SDL_Rect mouse_rect;
window_rect.x = 0;
window_rect.y = 0;
window_rect.w = window->w;
window_rect.h = window->h;
if (SDL_IntersectRect(&window->mouse_rect, &window_rect, &mouse_rect)) {
int left = window->x + mouse_rect.x;
int right = left + mouse_rect.w - 1;
int top = window->y + mouse_rect.y;
int bottom = top + mouse_rect.h - 1;
if (x < left || x > right || y < top || y > bottom) {
adjusted->x = SDL_clamp(x, left, right);
adjusted->y = SDL_clamp(y, top, bottom);
return SDL_TRUE;
}
return SDL_FALSE;
}
}
if ((window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0) {
int left = window->x;
int right = left + window->w - 1;
int top = window->y;
int bottom = top + window->h - 1;
if (x < left || x > right || y < top || y > bottom) {
adjusted->x = SDL_clamp(x, left, right);
adjusted->y = SDL_clamp(y, top, bottom);
return SDL_TRUE;
}
}
return SDL_FALSE;
}
static void
Cocoa_UpdateClipCursor(SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_13_2) {
NSWindow *nswindow = data->nswindow;
SDL_Rect mouse_rect;
SDL_zero(mouse_rect);
if (ShouldAdjustCoordinatesForGrab(window)) {
SDL_Rect window_rect;
window_rect.x = 0;
window_rect.y = 0;
window_rect.w = window->w;
window_rect.h = window->h;
if (window->mouse_rect.w > 0 && window->mouse_rect.h > 0) {
SDL_IntersectRect(&window->mouse_rect, &window_rect, &mouse_rect);
}
if ((window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0 &&
SDL_RectEmpty(&mouse_rect)) {
SDL_memcpy(&mouse_rect, &window_rect, sizeof(mouse_rect));
}
}
if (SDL_RectEmpty(&mouse_rect)) {
nswindow.mouseConfinementRect = NSZeroRect;
} else {
NSRect rect;
rect.origin.x = mouse_rect.x;
rect.origin.y = [nswindow contentLayoutRect].size.height - mouse_rect.y - mouse_rect.h;
rect.size.width = mouse_rect.w;
rect.size.height = mouse_rect.h;
nswindow.mouseConfinementRect = rect;
}
} else {
/* Move the cursor to the nearest point in the window */
if (ShouldAdjustCoordinatesForGrab(window)) {
int x, y;
CGPoint cgpoint;
SDL_GetGlobalMouseState(&x, &y);
if (AdjustCoordinatesForGrab(window, x, y, &cgpoint)) {
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
}
}
}
}
@implementation Cocoa_WindowListener
@@ -352,6 +477,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
[center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:window];
[center addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:window];
[center addObserver:self selector:@selector(windowDidChangeBackingProperties:) name:NSWindowDidChangeBackingPropertiesNotification object:window];
[center addObserver:self selector:@selector(windowDidChangeScreenProfile:) name:NSWindowDidChangeScreenProfileNotification object:window];
[center addObserver:self selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:window];
[center addObserver:self selector:@selector(windowDidEnterFullScreen:) name:NSWindowDidEnterFullScreenNotification object:window];
[center addObserver:self selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:window];
@@ -483,6 +609,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
[center removeObserver:self name:NSWindowDidBecomeKeyNotification object:window];
[center removeObserver:self name:NSWindowDidResignKeyNotification object:window];
[center removeObserver:self name:NSWindowDidChangeBackingPropertiesNotification object:window];
[center removeObserver:self name:NSWindowDidChangeScreenProfileNotification object:window];
[center removeObserver:self name:NSWindowWillEnterFullScreenNotification object:window];
[center removeObserver:self name:NSWindowDidEnterFullScreenNotification object:window];
[center removeObserver:self name:NSWindowWillExitFullScreenNotification object:window];
@@ -513,12 +640,12 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
return isMoving || (focusClickPending != 0);
}
-(void) setFocusClickPending:(int) button
-(void) setFocusClickPending:(NSInteger) button
{
focusClickPending |= (1 << button);
}
-(void) clearFocusClickPending:(int) button
-(void) clearFocusClickPending:(NSInteger) button
{
if ((focusClickPending & (1 << button)) != 0) {
focusClickPending &= ~(1 << button);
@@ -567,6 +694,8 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
}
mouse->SetRelativeMouseMode(SDL_TRUE);
} else {
Cocoa_UpdateClipCursor(_data->window);
}
}
}
@@ -665,6 +794,10 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
- (void)windowDidMiniaturize:(NSNotification *)aNotification
{
if (focusClickPending) {
focusClickPending = 0;
[self onMovingOrFocusClickPendingStateCleared];
}
SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
}
@@ -750,6 +883,11 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
}
}
- (void)windowDidChangeScreenProfile:(NSNotification *)aNotification
{
SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_ICCPROF_CHANGED, 0, 0);
}
- (void)windowWillEnterFullScreen:(NSNotification *)aNotification
{
SDL_Window *window = _data->window;
@@ -1012,16 +1150,43 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
return NO; /* not a special area, carry on. */
}
static int
Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * window, const Uint8 state, const Uint8 button)
{
const SDL_MouseID mouseID = mouse->mouseID;
const int clicks = (int) [theEvent clickCount];
SDL_Window *focus = SDL_GetKeyboardFocus();
int rc;
// macOS will send non-left clicks to background windows without raising them, so we need to
// temporarily adjust the mouse position when this happens, as `mouse` will be tracking
// the position in the currently-focused window. We don't (currently) send a mousemove
// event for the background window, this just makes sure the button is reported at the
// correct position in its own event.
if ( focus && ([theEvent window] == ((SDL_WindowData *) focus->driverdata)->nswindow) ) {
rc = SDL_SendMouseButtonClicks(window, mouseID, state, button, clicks);
} else {
const int orig_x = mouse->x;
const int orig_y = mouse->y;
const NSPoint point = [theEvent locationInWindow];
mouse->x = (int) point.x;
mouse->y = (int) (window->h - point.y);
rc = SDL_SendMouseButtonClicks(window, mouseID, state, button, clicks);
mouse->x = orig_x;
mouse->y = orig_y;
}
return rc;
}
- (void)mouseDown:(NSEvent *)theEvent
{
const SDL_Mouse *mouse = SDL_GetMouse();
SDL_Mouse *mouse = SDL_GetMouse();
if (!mouse) {
return;
}
const SDL_MouseID mouseID = mouse->mouseID;
int button;
int clicks;
/* Ignore events that aren't inside the client area (i.e. title bar.) */
if ([theEvent window]) {
@@ -1058,9 +1223,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
break;
}
clicks = (int) [theEvent clickCount];
SDL_SendMouseButtonClicks(_data->window, mouseID, SDL_PRESSED, button, clicks);
Cocoa_SendMouseButtonClicks(mouse, theEvent, _data->window, SDL_PRESSED, button);
}
- (void)rightMouseDown:(NSEvent *)theEvent
@@ -1075,14 +1238,12 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
- (void)mouseUp:(NSEvent *)theEvent
{
const SDL_Mouse *mouse = SDL_GetMouse();
SDL_Mouse *mouse = SDL_GetMouse();
if (!mouse) {
return;
}
const SDL_MouseID mouseID = mouse->mouseID;
int button;
int clicks;
if ([self processHitTest:theEvent]) {
SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
@@ -1109,9 +1270,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
break;
}
clicks = (int) [theEvent clickCount];
SDL_SendMouseButtonClicks(_data->window, mouseID, SDL_RELEASED, button, clicks);
Cocoa_SendMouseButtonClicks(mouse, theEvent, _data->window, SDL_RELEASED, button);
}
- (void)rightMouseUp:(NSEvent *)theEvent
@@ -1149,27 +1308,15 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
x = (int)point.x;
y = (int)(window->h - point.y);
if (window->flags & SDL_WINDOW_MOUSE_GRABBED) {
if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
if (x < 0) {
x = 0;
} else if (x >= window->w) {
x = window->w - 1;
}
if (y < 0) {
y = 0;
} else if (y >= window->h) {
y = window->h - 1;
}
CGPoint cgpoint;
cgpoint.x = window->x + x;
cgpoint.y = window->y + y;
if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_13_2) {
/* Mouse grab is taken care of by the confinement rect */
} else {
CGPoint cgpoint;
if (ShouldAdjustCoordinatesForGrab(window) &&
AdjustCoordinatesForGrab(window, window->x + x, window->y + y, &cgpoint)) {
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
CGAssociateMouseAndMouseCursorPosition(YES);
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
}
}
@@ -1200,7 +1347,18 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
{
/* probably a MacBook trackpad; make this look like a synthesized event.
This is backwards from reality, but better matches user expectations. */
const BOOL istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
BOOL istrackpad = NO;
@try {
istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
}
@catch (NSException *e) {
/* if NSEvent type doesn't have subtype, such as NSEventTypeBeginGesture on
* macOS 10.5 to 10.10, then NSInternalInconsistencyException is thrown.
* This still prints a message to terminal so catching it's not an ideal solution.
*
* *** Assertion failure in -[NSEvent subtype]
*/
}
NSSet *touches = [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
const SDL_TouchID touchID = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[[touches anyObject] device];
@@ -1251,7 +1409,18 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
/* probably a MacBook trackpad; make this look like a synthesized event.
This is backwards from reality, but better matches user expectations. */
const BOOL istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
BOOL istrackpad = NO;
@try {
istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
}
@catch (NSException *e) {
/* if NSEvent type doesn't have subtype, such as NSEventTypeBeginGesture on
* macOS 10.5 to 10.10, then NSInternalInconsistencyException is thrown.
* This still prints a message to terminal so catching it's not an ideal solution.
*
* *** Assertion failure in -[NSEvent subtype]
*/
}
for (NSTouch *touch in touches) {
const SDL_TouchID touchId = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[touch device];
@@ -1981,6 +2150,42 @@ Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
return 0;
}
void*
Cocoa_GetWindowICCProfile(_THIS, SDL_Window * window, size_t * size)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
NSWindow *nswindow = data->nswindow;
NSScreen *screen = [nswindow screen];
NSData* iccProfileData = nil;
void* retIccProfileData = NULL;
if (screen == nil) {
SDL_SetError("Could not get screen of window.");
return NULL;
}
if ([screen colorSpace] == nil) {
SDL_SetError("Could not get colorspace information of screen.");
return NULL;
}
iccProfileData = [[screen colorSpace] ICCProfileData];
if (iccProfileData == nil) {
SDL_SetError("Could not get ICC profile data.");
return NULL;
}
retIccProfileData = SDL_malloc([iccProfileData length]);
if (!retIccProfileData) {
SDL_OutOfMemory();
return NULL;
}
[iccProfileData getBytes:retIccProfileData length:[iccProfileData length]];
*size = [iccProfileData length];
return retIccProfileData;
}
int
Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
{
@@ -2005,27 +2210,20 @@ Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
return 0;
}
void
Cocoa_SetWindowMouseRect(_THIS, SDL_Window * window)
{
Cocoa_UpdateClipCursor(window);
}
void
Cocoa_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
/* Move the cursor to the nearest point in the window */
if (grabbed && data && ![data->listener isMovingOrFocusClickPending]) {
int x, y;
CGPoint cgpoint;
Cocoa_UpdateClipCursor(window);
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);
}
if ( data && (window->flags & SDL_WINDOW_FULLSCREEN) ) {
if (data && (window->flags & SDL_WINDOW_FULLSCREEN)) {
if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_INPUT_FOCUS)
&& ![data->listener isInFullscreenSpace]) {
/* OpenGL is rendering to the window, so make it visible! */