Merge commit '6c536afdb7bdc9cece4152c7e1f9a18306976b46' into main
commit
48f2d2f832
|
@ -824,7 +824,10 @@ prepare_audioqueue(_THIS)
|
|||
const AudioStreamBasicDescription *strdesc = &this->hidden->strdesc;
|
||||
const int iscapture = this->iscapture;
|
||||
OSStatus result;
|
||||
int i;
|
||||
int i, numAudioBuffers = 2;
|
||||
AudioChannelLayout layout;
|
||||
double MINIMUM_AUDIO_BUFFER_TIME_MS;
|
||||
const double msecs = (this->spec.samples / ((double) this->spec.freq)) * 1000.0;;
|
||||
|
||||
SDL_assert(CFRunLoopGetCurrent() != NULL);
|
||||
|
||||
|
@ -856,7 +859,6 @@ prepare_audioqueue(_THIS)
|
|||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Set the channel layout for the audio queue */
|
||||
AudioChannelLayout layout;
|
||||
SDL_zero(layout);
|
||||
switch (this->spec.channels) {
|
||||
case 1:
|
||||
|
@ -901,15 +903,13 @@ prepare_audioqueue(_THIS)
|
|||
}
|
||||
|
||||
/* Make sure we can feed the device a minimum amount of time */
|
||||
double MINIMUM_AUDIO_BUFFER_TIME_MS = 15.0;
|
||||
MINIMUM_AUDIO_BUFFER_TIME_MS = 15.0;
|
||||
#if defined(__IPHONEOS__)
|
||||
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
|
||||
/* Older iOS hardware, use 40 ms as a minimum time */
|
||||
MINIMUM_AUDIO_BUFFER_TIME_MS = 40.0;
|
||||
}
|
||||
#endif
|
||||
const double msecs = (this->spec.samples / ((double) this->spec.freq)) * 1000.0;
|
||||
int numAudioBuffers = 2;
|
||||
if (msecs < MINIMUM_AUDIO_BUFFER_TIME_MS) { /* use more buffers if we have a VERY small sample set. */
|
||||
numAudioBuffers = ((int)SDL_ceil(MINIMUM_AUDIO_BUFFER_TIME_MS / msecs) * 2);
|
||||
}
|
||||
|
@ -946,6 +946,7 @@ static int
|
|||
audioqueue_thread(void *arg)
|
||||
{
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) arg;
|
||||
int rc;
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
const AudioObjectPropertyAddress default_device_address = {
|
||||
|
@ -960,7 +961,7 @@ audioqueue_thread(void *arg)
|
|||
}
|
||||
#endif
|
||||
|
||||
const int rc = prepare_audioqueue(this);
|
||||
rc = prepare_audioqueue(this);
|
||||
if (!rc) {
|
||||
this->hidden->thread_error = SDL_strdup(SDL_GetError());
|
||||
SDL_SemPost(this->hidden->ready_semaphore);
|
||||
|
@ -977,6 +978,7 @@ audioqueue_thread(void *arg)
|
|||
|
||||
#if MACOSX_COREAUDIO
|
||||
if ((this->handle == NULL) && SDL_AtomicGet(&this->hidden->device_change_flag)) {
|
||||
const AudioDeviceID prev_devid = this->hidden->deviceID;
|
||||
SDL_AtomicSet(&this->hidden->device_change_flag, 0);
|
||||
|
||||
#if DEBUG_COREAUDIO
|
||||
|
@ -986,7 +988,6 @@ audioqueue_thread(void *arg)
|
|||
/* if any of this fails, there's not much to do but wait to see if the user gives up
|
||||
and quits (flagging the audioqueue for shutdown), or toggles to some other system
|
||||
output device (in which case we'll try again). */
|
||||
const AudioDeviceID prev_devid = this->hidden->deviceID;
|
||||
if (prepare_device(this) && (prev_devid != this->hidden->deviceID)) {
|
||||
AudioQueueStop(this->hidden->audioQueue, 1);
|
||||
if (assign_device_to_audioqueue(this)) {
|
||||
|
|
|
@ -36,18 +36,22 @@ FILE* SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode)
|
|||
{ @autoreleasepool
|
||||
{
|
||||
FILE* fp = NULL;
|
||||
NSFileManager* file_manager;
|
||||
NSString* resource_path;
|
||||
NSString* ns_string_file_component;
|
||||
NSString* full_path_with_file_to_try;
|
||||
|
||||
/* If the file mode is writable, skip all the bundle stuff because generally the bundle is read-only. */
|
||||
if(strcmp("r", mode) && strcmp("rb", mode)) {
|
||||
return fopen(file, mode);
|
||||
}
|
||||
|
||||
NSFileManager* file_manager = [NSFileManager defaultManager];
|
||||
NSString* resource_path = [[NSBundle mainBundle] resourcePath];
|
||||
file_manager = [NSFileManager defaultManager];
|
||||
resource_path = [[NSBundle mainBundle] resourcePath];
|
||||
|
||||
NSString* ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)];
|
||||
ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)];
|
||||
|
||||
NSString* full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
|
||||
full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
|
||||
if([file_manager fileExistsAtPath:full_path_with_file_to_try]) {
|
||||
fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
|
||||
} else {
|
||||
|
|
|
@ -71,6 +71,10 @@ char *
|
|||
SDL_GetPrefPath(const char *org, const char *app)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
char *retval = NULL;
|
||||
static SDL_bool shown = SDL_FALSE;
|
||||
NSArray *array;
|
||||
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
|
@ -79,9 +83,8 @@ SDL_GetPrefPath(const char *org, const char *app)
|
|||
org = "";
|
||||
}
|
||||
|
||||
char *retval = NULL;
|
||||
#if !TARGET_OS_TV
|
||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
#else
|
||||
/* tvOS does not have persistent local storage!
|
||||
* The only place on-device where we can store data is
|
||||
|
@ -91,15 +94,13 @@ SDL_GetPrefPath(const char *org, const char *app)
|
|||
* between sessions. If you want your app's save data to
|
||||
* actually stick around, you'll need to use iCloud storage.
|
||||
*/
|
||||
|
||||
static SDL_bool shown = SDL_FALSE;
|
||||
if (!shown)
|
||||
{
|
||||
shown = SDL_TRUE;
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "tvOS does not have persistent local storage! Use iCloud storage if you want your data to persist between sessions.\n");
|
||||
}
|
||||
|
||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
#endif /* !TARGET_OS_TV */
|
||||
|
||||
if ([array count] > 0) { /* we only want the first item in the list. */
|
||||
|
|
|
@ -156,11 +156,12 @@ static hid_device *new_hid_device(void)
|
|||
|
||||
static void free_hid_device(hid_device *dev)
|
||||
{
|
||||
struct input_report *rpt;
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
/* Delete any input reports still left over. */
|
||||
struct input_report *rpt = dev->input_reports;
|
||||
rpt = dev->input_reports;
|
||||
while (rpt) {
|
||||
struct input_report *next = rpt->next;
|
||||
free(rpt->data);
|
||||
|
@ -260,14 +261,12 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t
|
|||
buf[0] = 0;
|
||||
|
||||
if (str && CFGetTypeID(str) == CFStringGetTypeID()) {
|
||||
len --;
|
||||
|
||||
CFIndex str_len = CFStringGetLength(str);
|
||||
CFIndex used_buf_len, chars_copied;
|
||||
CFRange range;
|
||||
CFIndex str_len = CFStringGetLength(str);
|
||||
len --;
|
||||
range.location = 0;
|
||||
range.length = (str_len > len)? len: str_len;
|
||||
CFIndex used_buf_len;
|
||||
CFIndex chars_copied;
|
||||
chars_copied = CFStringGetBytes(str,
|
||||
range,
|
||||
kCFStringEncodingUTF32LE,
|
||||
|
@ -299,14 +298,12 @@ static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, cha
|
|||
buf[0] = 0;
|
||||
|
||||
if (str && CFGetTypeID(str) == CFStringGetTypeID()) {
|
||||
len--;
|
||||
|
||||
CFIndex str_len = CFStringGetLength(str);
|
||||
CFIndex used_buf_len, chars_copied;
|
||||
CFRange range;
|
||||
CFIndex str_len = CFStringGetLength(str);
|
||||
len--;
|
||||
range.location = 0;
|
||||
range.length = (str_len > len)? len: str_len;
|
||||
CFIndex used_buf_len;
|
||||
CFIndex chars_copied;
|
||||
chars_copied = CFStringGetBytes(str,
|
||||
range,
|
||||
kCFStringEncodingUTF8,
|
||||
|
@ -517,6 +514,8 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
|||
struct hid_device_info *root = NULL; // return object
|
||||
struct hid_device_info *cur_dev = NULL;
|
||||
CFIndex num_devices;
|
||||
CFSetRef device_set;
|
||||
IOHIDDeviceRef *device_array;
|
||||
int i;
|
||||
|
||||
/* Set up the HID Manager if it hasn't been done */
|
||||
|
@ -527,7 +526,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
|||
process_pending_events();
|
||||
|
||||
/* Get a list of the Devices */
|
||||
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
|
||||
device_set = IOHIDManagerCopyDevices(hid_mgr);
|
||||
if (!device_set)
|
||||
return NULL;
|
||||
|
||||
|
@ -537,7 +536,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
|||
CFRelease(device_set);
|
||||
return NULL;
|
||||
}
|
||||
IOHIDDeviceRef *device_array = (IOHIDDeviceRef*)calloc(num_devices, sizeof(IOHIDDeviceRef));
|
||||
device_array = (IOHIDDeviceRef*)calloc(num_devices, sizeof(IOHIDDeviceRef));
|
||||
CFSetGetValues(device_set, (const void **) device_array);
|
||||
|
||||
/* Iterate over each device, making an entry for it. */
|
||||
|
@ -733,13 +732,14 @@ static void perform_signal_callback(void *context)
|
|||
static void *read_thread(void *param)
|
||||
{
|
||||
hid_device *dev = (hid_device *)param;
|
||||
CFRunLoopSourceContext ctx;
|
||||
SInt32 code;
|
||||
|
||||
/* Move the device's run loop to this thread. */
|
||||
IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);
|
||||
|
||||
/* Create the RunLoopSource which is used to signal the
|
||||
event loop to stop when hid_close() is called. */
|
||||
CFRunLoopSourceContext ctx;
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.version = 0;
|
||||
ctx.info = dev;
|
||||
|
@ -756,7 +756,6 @@ static void *read_thread(void *param)
|
|||
|
||||
/* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input
|
||||
reports into the hid_report_callback(). */
|
||||
SInt32 code;
|
||||
while (!dev->shutdown_thread && !dev->disconnected) {
|
||||
code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE);
|
||||
/* Return if the device has been disconnected */
|
||||
|
@ -796,9 +795,11 @@ static void *read_thread(void *param)
|
|||
|
||||
hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
hid_device *dev = NULL;
|
||||
CFIndex num_devices;
|
||||
CFSetRef device_set;
|
||||
IOHIDDeviceRef *device_array;
|
||||
|
||||
dev = new_hid_device();
|
||||
|
||||
|
@ -809,10 +810,10 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
/* give the IOHIDManager a chance to update itself */
|
||||
process_pending_events();
|
||||
|
||||
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
|
||||
device_set = IOHIDManagerCopyDevices(hid_mgr);
|
||||
|
||||
num_devices = CFSetGetCount(device_set);
|
||||
IOHIDDeviceRef *device_array = (IOHIDDeviceRef *)calloc(num_devices, sizeof(IOHIDDeviceRef));
|
||||
device_array = (IOHIDDeviceRef *)calloc(num_devices, sizeof(IOHIDDeviceRef));
|
||||
CFSetGetValues(device_set, (const void **) device_array);
|
||||
for (i = 0; i < num_devices; i++) {
|
||||
char cbuf[BUF_LEN];
|
||||
|
@ -824,6 +825,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeNone);
|
||||
if (ret == kIOReturnSuccess) {
|
||||
char str[32];
|
||||
struct hid_device_list_node *node;
|
||||
|
||||
free(device_array);
|
||||
CFRelease(device_set);
|
||||
|
@ -845,7 +847,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
os_dev, dev->input_report_buf, dev->max_input_report_len,
|
||||
&hid_report_callback, dev);
|
||||
|
||||
struct hid_device_list_node *node = (struct hid_device_list_node *)calloc(1, sizeof(struct hid_device_list_node));
|
||||
node = (struct hid_device_list_node *)calloc(1, sizeof(struct hid_device_list_node));
|
||||
node->dev = dev;
|
||||
node->next = device_list;
|
||||
device_list = node;
|
||||
|
@ -1083,13 +1085,13 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
|
|||
{
|
||||
CFIndex len = length;
|
||||
IOReturn res;
|
||||
int skipped_report_id = 0, report_number;
|
||||
|
||||
/* Return if the device has been unplugged. */
|
||||
if (dev->disconnected)
|
||||
return -1;
|
||||
|
||||
int skipped_report_id = 0;
|
||||
int report_number = data[0];
|
||||
report_number = data[0];
|
||||
if (report_number == 0x0) {
|
||||
/* Offset the return buffer by 1, so that the report ID
|
||||
will remain in byte 0. */
|
||||
|
|
|
@ -985,7 +985,7 @@ DARWIN_JoystickUpdate(SDL_Joystick *joystick)
|
|||
recDevice *device = joystick->hwdata;
|
||||
recElement *element;
|
||||
SInt32 value, range;
|
||||
int i;
|
||||
int i, goodRead = SDL_FALSE;
|
||||
|
||||
if (!device) {
|
||||
return;
|
||||
|
@ -1001,7 +1001,6 @@ DARWIN_JoystickUpdate(SDL_Joystick *joystick)
|
|||
element = device->firstAxis;
|
||||
i = 0;
|
||||
|
||||
int goodRead = SDL_FALSE;
|
||||
while (element) {
|
||||
goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value);
|
||||
if (goodRead) {
|
||||
|
|
|
@ -180,16 +180,16 @@ IsControllerXbox(GCController *controller)
|
|||
static BOOL
|
||||
IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
|
||||
{
|
||||
if ((@available(macOS 11.3, *)) && !GCController.shouldMonitorBackgroundEvents) {
|
||||
GCController.shouldMonitorBackgroundEvents = YES;
|
||||
}
|
||||
|
||||
Uint16 *guid16 = (Uint16 *)device->guid.data;
|
||||
Uint16 vendor = 0;
|
||||
Uint16 product = 0;
|
||||
Uint8 subtype = 0;
|
||||
|
||||
const char *name = NULL;
|
||||
|
||||
if ((@available(macOS 11.3, *)) && !GCController.shouldMonitorBackgroundEvents) {
|
||||
GCController.shouldMonitorBackgroundEvents = YES;
|
||||
}
|
||||
|
||||
/* Explicitly retain the controller because SDL_JoystickDeviceItem is a
|
||||
* struct, and ARC doesn't work with structs. */
|
||||
device->controller = (__bridge GCController *) CFBridgingRetain(controller);
|
||||
|
@ -213,6 +213,7 @@ IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controlle
|
|||
BOOL is_MFi = (!is_xbox && !is_ps4 && !is_ps5);
|
||||
#endif
|
||||
int nbuttons = 0;
|
||||
BOOL has_direct_menu;
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
if ((is_xbox && HIDAPI_IsDeviceTypePresent(SDL_CONTROLLER_TYPE_XBOXONE)) ||
|
||||
|
@ -251,7 +252,7 @@ IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controlle
|
|||
device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_GUIDE);
|
||||
++nbuttons;
|
||||
}
|
||||
BOOL has_direct_menu = [gamepad respondsToSelector:@selector(buttonMenu)] && gamepad.buttonMenu;
|
||||
has_direct_menu = [gamepad respondsToSelector:@selector(buttonMenu)] && gamepad.buttonMenu;
|
||||
#if TARGET_OS_TV
|
||||
/* On tvOS MFi controller menu button brings you to the home screen */
|
||||
if (is_MFi) {
|
||||
|
@ -575,6 +576,7 @@ IOS_JoystickInit(void)
|
|||
#endif
|
||||
|
||||
@autoreleasepool {
|
||||
NSNotificationCenter *center;
|
||||
#ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
|
||||
if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) {
|
||||
/* Default behavior, accelerometer as joystick */
|
||||
|
@ -599,7 +601,7 @@ IOS_JoystickInit(void)
|
|||
SDL_AppleTVRemoteRotationHintChanged, NULL);
|
||||
#endif /* TARGET_OS_TV */
|
||||
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
connectObserver = [center addObserverForName:GCControllerDidConnectNotification
|
||||
object:nil
|
||||
|
@ -907,9 +909,8 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
|||
|
||||
#ifdef ENABLE_PHYSICAL_INPUT_PROFILE
|
||||
if (joystick->hwdata->has_dualshock_touchpad) {
|
||||
buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton].isPressed;
|
||||
|
||||
GCControllerDirectionPad *dpad;
|
||||
buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton].isPressed;
|
||||
|
||||
dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadOne];
|
||||
if (dpad.xAxis.value || dpad.yAxis.value) {
|
||||
|
@ -1129,6 +1130,7 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
|||
@autoreleasepool {
|
||||
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
|
||||
NSError *error = nil;
|
||||
CHHapticDynamicParameter *param;
|
||||
|
||||
if (self.engine == nil) {
|
||||
return SDL_SetError("Haptics engine was stopped");
|
||||
|
@ -1143,8 +1145,8 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
|||
}
|
||||
|
||||
if (self.player == nil) {
|
||||
CHHapticEventParameter *param = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticIntensity value:1.0f];
|
||||
CHHapticEvent *event = [[CHHapticEvent alloc] initWithEventType:CHHapticEventTypeHapticContinuous parameters:[NSArray arrayWithObjects:param, nil] relativeTime:0 duration:GCHapticDurationInfinite];
|
||||
CHHapticEventParameter *event_param = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticIntensity value:1.0f];
|
||||
CHHapticEvent *event = [[CHHapticEvent alloc] initWithEventType:CHHapticEventTypeHapticContinuous parameters:[NSArray arrayWithObjects:event_param, nil] relativeTime:0 duration:GCHapticDurationInfinite];
|
||||
CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithEvents:[NSArray arrayWithObject:event] parameters:[[NSArray alloc] init] error:&error];
|
||||
if (error != nil) {
|
||||
return SDL_SetError("Couldn't create haptic pattern: %s", [error.localizedDescription UTF8String]);
|
||||
|
@ -1157,7 +1159,7 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
|||
self.active = false;
|
||||
}
|
||||
|
||||
CHHapticDynamicParameter *param = [[CHHapticDynamicParameter alloc] initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl value:intensity relativeTime:0];
|
||||
param = [[CHHapticDynamicParameter alloc] initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl value:intensity relativeTime:0];
|
||||
[self.player sendParameters:[NSArray arrayWithObject:param] atTime:0 error:&error];
|
||||
if (error != nil) {
|
||||
return SDL_SetError("Couldn't update haptic player: %s", [error.localizedDescription UTF8String]);
|
||||
|
@ -1176,8 +1178,10 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
|||
-(id) initWithController:(GCController*)controller locality:(GCHapticsLocality)locality API_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0))
|
||||
{
|
||||
@autoreleasepool {
|
||||
self = [super init];
|
||||
NSError *error;
|
||||
__weak __typeof(self) weakSelf;
|
||||
self = [super init];
|
||||
weakSelf = self;
|
||||
|
||||
self.engine = [controller.haptics createEngineWithLocality:locality];
|
||||
if (self.engine == nil) {
|
||||
|
@ -1191,7 +1195,6 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
|
|||
return nil;
|
||||
}
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
self.engine.stoppedHandler = ^(CHHapticEngineStoppedReason stoppedReason) {
|
||||
SDL_RumbleMotor *_this = weakSelf;
|
||||
if (_this == nil) {
|
||||
|
|
|
@ -240,16 +240,24 @@ static id<MTLRenderPipelineState>
|
|||
MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
|
||||
NSString *blendlabel, SDL_BlendMode blendmode)
|
||||
{
|
||||
MTLRenderPipelineDescriptor *mtlpipedesc;
|
||||
MTLVertexDescriptor *vertdesc;
|
||||
MTLRenderPipelineColorAttachmentDescriptor *rtdesc;
|
||||
NSError *err = nil;
|
||||
id<MTLRenderPipelineState> state;
|
||||
METAL_PipelineState pipeline;
|
||||
METAL_PipelineState *states;
|
||||
|
||||
id<MTLFunction> mtlvertfn = [data.mtllibrary newFunctionWithName:GetVertexFunctionName(cache->vertexFunction)];
|
||||
id<MTLFunction> mtlfragfn = [data.mtllibrary newFunctionWithName:GetFragmentFunctionName(cache->fragmentFunction)];
|
||||
SDL_assert(mtlvertfn != nil);
|
||||
SDL_assert(mtlfragfn != nil);
|
||||
|
||||
MTLRenderPipelineDescriptor *mtlpipedesc = [[MTLRenderPipelineDescriptor alloc] init];
|
||||
mtlpipedesc = [[MTLRenderPipelineDescriptor alloc] init];
|
||||
mtlpipedesc.vertexFunction = mtlvertfn;
|
||||
mtlpipedesc.fragmentFunction = mtlfragfn;
|
||||
|
||||
MTLVertexDescriptor *vertdesc = [MTLVertexDescriptor vertexDescriptor];
|
||||
vertdesc = [MTLVertexDescriptor vertexDescriptor];
|
||||
|
||||
switch (cache->vertexFunction) {
|
||||
case SDL_METAL_VERTEX_SOLID:
|
||||
|
@ -287,7 +295,7 @@ MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
|
|||
|
||||
mtlpipedesc.vertexDescriptor = vertdesc;
|
||||
|
||||
MTLRenderPipelineColorAttachmentDescriptor *rtdesc = mtlpipedesc.colorAttachments[0];
|
||||
rtdesc = mtlpipedesc.colorAttachments[0];
|
||||
rtdesc.pixelFormat = cache->renderTargetFormat;
|
||||
|
||||
if (blendmode != SDL_BLENDMODE_NONE) {
|
||||
|
@ -304,15 +312,13 @@ MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
|
|||
|
||||
mtlpipedesc.label = [@(cache->label) stringByAppendingString:blendlabel];
|
||||
|
||||
NSError *err = nil;
|
||||
id<MTLRenderPipelineState> state = [data.mtldevice newRenderPipelineStateWithDescriptor:mtlpipedesc error:&err];
|
||||
state = [data.mtldevice newRenderPipelineStateWithDescriptor:mtlpipedesc error:&err];
|
||||
SDL_assert(err == nil);
|
||||
|
||||
METAL_PipelineState pipeline;
|
||||
pipeline.blendMode = blendmode;
|
||||
pipeline.pipe = (void *)CFBridgingRetain(state);
|
||||
|
||||
METAL_PipelineState *states = SDL_realloc(cache->states, (cache->count + 1) * sizeof(pipeline));
|
||||
states = SDL_realloc(cache->states, (cache->count + 1) * sizeof(pipeline));
|
||||
|
||||
if (states) {
|
||||
states[cache->count++] = pipeline;
|
||||
|
@ -542,6 +548,10 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
{ @autoreleasepool {
|
||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||
MTLPixelFormat pixfmt;
|
||||
MTLTextureDescriptor *mtltexdesc;
|
||||
id<MTLTexture> mtltexture, mtltexture_uv;
|
||||
BOOL yuv, nv12;
|
||||
METAL_TextureData *texturedata;
|
||||
|
||||
switch (texture->format) {
|
||||
case SDL_PIXELFORMAT_ABGR8888:
|
||||
|
@ -560,7 +570,7 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
return SDL_SetError("Texture format %s not supported by Metal", SDL_GetPixelFormatName(texture->format));
|
||||
}
|
||||
|
||||
MTLTextureDescriptor *mtltexdesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixfmt
|
||||
mtltexdesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixfmt
|
||||
width:(NSUInteger)texture->w height:(NSUInteger)texture->h mipmapped:NO];
|
||||
|
||||
/* Not available in iOS 8. */
|
||||
|
@ -572,15 +582,15 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
}
|
||||
}
|
||||
|
||||
id<MTLTexture> mtltexture = [data.mtldevice newTextureWithDescriptor:mtltexdesc];
|
||||
mtltexture = [data.mtldevice newTextureWithDescriptor:mtltexdesc];
|
||||
if (mtltexture == nil) {
|
||||
return SDL_SetError("Texture allocation failed");
|
||||
}
|
||||
|
||||
id<MTLTexture> mtltexture_uv = nil;
|
||||
mtltexture_uv = nil;
|
||||
#if SDL_HAVE_YUV
|
||||
BOOL yuv = (texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12);
|
||||
BOOL nv12 = (texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21);
|
||||
yuv = (texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12);
|
||||
nv12 = (texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21);
|
||||
|
||||
if (yuv) {
|
||||
mtltexdesc.pixelFormat = MTLPixelFormatR8Unorm;
|
||||
|
@ -601,7 +611,7 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
}
|
||||
}
|
||||
#endif /* SDL_HAVE_YUV */
|
||||
METAL_TextureData *texturedata = [[METAL_TextureData alloc] init];
|
||||
texturedata = [[METAL_TextureData alloc] init];
|
||||
if (texture->scaleMode == SDL_ScaleModeNearest) {
|
||||
texturedata.mtlsampler = data.mtlsamplernearest;
|
||||
} else {
|
||||
|
@ -672,6 +682,8 @@ METAL_UpdateTextureInternal(SDL_Renderer * renderer, METAL_TextureData *textured
|
|||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||
SDL_Rect stagingrect = {0, 0, rect.w, rect.h};
|
||||
MTLTextureDescriptor *desc;
|
||||
id<MTLTexture> stagingtex;
|
||||
id<MTLBlitCommandEncoder> blitcmd;
|
||||
|
||||
/* If the texture is managed or shared and this is the first upload, we can
|
||||
* use replaceRegion to upload to it directly. Otherwise we upload the data
|
||||
|
@ -693,7 +705,7 @@ METAL_UpdateTextureInternal(SDL_Renderer * renderer, METAL_TextureData *textured
|
|||
/* TODO: We could have a pool of textures or a MTLHeap we allocate from,
|
||||
* and release a staging texture back to the pool in the command buffer's
|
||||
* completion handler. */
|
||||
id<MTLTexture> stagingtex = [data.mtldevice newTextureWithDescriptor:desc];
|
||||
stagingtex = [data.mtldevice newTextureWithDescriptor:desc];
|
||||
if (stagingtex == nil) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
@ -709,7 +721,7 @@ METAL_UpdateTextureInternal(SDL_Renderer * renderer, METAL_TextureData *textured
|
|||
data.mtlcmdbuffer = [data.mtlcmdqueue commandBuffer];
|
||||
}
|
||||
|
||||
id<MTLBlitCommandEncoder> blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
|
||||
blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
|
||||
|
||||
[blitcmd copyFromTexture:stagingtex
|
||||
sourceSlice:0
|
||||
|
@ -877,6 +889,7 @@ METAL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
{ @autoreleasepool {
|
||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||
METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->driverdata;
|
||||
id<MTLBlitCommandEncoder> blitcmd;
|
||||
SDL_Rect rect = texturedata.lockedrect;
|
||||
int pitch = SDL_BYTESPERPIXEL(texture->format) * rect.w;
|
||||
SDL_Rect UVrect = {rect.x / 2, rect.y / 2, (rect.w + 1) / 2, (rect.h + 1) / 2};
|
||||
|
@ -894,7 +907,7 @@ METAL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
data.mtlcmdbuffer = [data.mtlcmdqueue commandBuffer];
|
||||
}
|
||||
|
||||
id<MTLBlitCommandEncoder> blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
|
||||
blitcmd = [data.mtlcmdbuffer blitCommandEncoder];
|
||||
|
||||
[blitcmd copyFromBuffer:texturedata.lockedbuffer
|
||||
sourceOffset:0
|
||||
|
@ -1068,11 +1081,13 @@ METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
|
|||
cmd->data.draw.b,
|
||||
cmd->data.draw.a
|
||||
};
|
||||
size_t vertlen;
|
||||
float *verts;
|
||||
|
||||
SDL_assert(count >= 2); /* should have been checked at the higher level. */
|
||||
|
||||
const size_t vertlen = (2 * sizeof (float) + sizeof (SDL_Color)) * count;
|
||||
float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
|
||||
vertlen = (2 * sizeof (float) + sizeof (SDL_Color)) * count;
|
||||
verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
|
||||
if (!verts) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1095,15 +1110,17 @@ METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
|
|||
points -= 2; /* update the last line. */
|
||||
verts -= 2 + 1;
|
||||
|
||||
const float xstart = points[0].x;
|
||||
const float ystart = points[0].y;
|
||||
const float xend = points[1].x;
|
||||
const float yend = points[1].y;
|
||||
{
|
||||
const float xstart = points[0].x;
|
||||
const float ystart = points[0].y;
|
||||
const float xend = points[1].x;
|
||||
const float yend = points[1].y;
|
||||
|
||||
if (ystart == yend) { /* horizontal line */
|
||||
verts[0] += (xend > xstart) ? 1.0f : -1.0f;
|
||||
} else if (xstart == xend) { /* vertical line */
|
||||
verts[1] += (yend > ystart) ? 1.0f : -1.0f;
|
||||
if (ystart == yend) { /* horizontal line */
|
||||
verts[0] += (xend > xstart) ? 1.0f : -1.0f;
|
||||
} else if (xstart == xend) { /* vertical line */
|
||||
verts[1] += (yend > ystart) ? 1.0f : -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1127,6 +1144,7 @@ METAL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture
|
|||
|
||||
for (int i = 0; i < count; i++) {
|
||||
int j;
|
||||
float *xy_;
|
||||
if (size_indices == 4) {
|
||||
j = ((const Uint32 *)indices)[i];
|
||||
} else if (size_indices == 2) {
|
||||
|
@ -1137,7 +1155,7 @@ METAL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture
|
|||
j = i;
|
||||
}
|
||||
|
||||
float *xy_ = (float *)((char*)xy + j * xy_stride);
|
||||
xy_ = (float *)((char*)xy + j * xy_stride);
|
||||
|
||||
*(verts++) = xy_[0] * scale_x;
|
||||
*(verts++) = xy_[1] * scale_y;
|
||||
|
@ -1282,11 +1300,10 @@ static int
|
|||
METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
|
||||
{ @autoreleasepool {
|
||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||
id<MTLBuffer> mtlbufvertex = nil;
|
||||
METAL_DrawStateCache statecache;
|
||||
SDL_zero(statecache);
|
||||
|
||||
id<MTLBuffer> mtlbufvertex = nil;
|
||||
|
||||
statecache.pipeline = nil;
|
||||
statecache.vertex_buffer = nil;
|
||||
statecache.constants_offset = CONSTANTS_OFFSET_INVALID;
|
||||
|
@ -1363,15 +1380,17 @@ METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
|||
statecache.cliprect_dirty = SDL_TRUE;
|
||||
statecache.viewport_dirty = SDL_TRUE;
|
||||
|
||||
const Uint8 r = cmd->data.color.r;
|
||||
const Uint8 g = cmd->data.color.g;
|
||||
const Uint8 b = cmd->data.color.b;
|
||||
const Uint8 a = cmd->data.color.a;
|
||||
MTLClearColor color = MTLClearColorMake(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
|
||||
{
|
||||
const Uint8 r = cmd->data.color.r;
|
||||
const Uint8 g = cmd->data.color.g;
|
||||
const Uint8 b = cmd->data.color.b;
|
||||
const Uint8 a = cmd->data.color.a;
|
||||
MTLClearColor color = MTLClearColorMake(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
|
||||
|
||||
// get new command encoder, set up with an initial clear operation.
|
||||
// (this might fail, and future draw operations will notice.)
|
||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, mtlbufvertex);
|
||||
// get new command encoder, set up with an initial clear operation.
|
||||
// (this might fail, and future draw operations will notice.)
|
||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, mtlbufvertex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1424,12 +1443,17 @@ METAL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
|||
Uint32 pixel_format, void * pixels, int pitch)
|
||||
{ @autoreleasepool {
|
||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||
id<MTLTexture> mtltexture;
|
||||
MTLRegion mtlregion;
|
||||
int temp_pitch, status;
|
||||
Uint32 temp_format;
|
||||
void *temp_pixels;
|
||||
if (!METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil)) {
|
||||
return SDL_SetError("Failed to activate render command encoder (is your window in the background?");
|
||||
}
|
||||
|
||||
[data.mtlcmdencoder endEncoding];
|
||||
id<MTLTexture> mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
|
||||
mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
|
||||
|
||||
#ifdef __MACOSX__
|
||||
/* on macOS with managed-storage textures, we need to tell the driver to
|
||||
|
@ -1450,19 +1474,19 @@ METAL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
|||
data.mtlcmdencoder = nil;
|
||||
data.mtlcmdbuffer = nil;
|
||||
|
||||
MTLRegion mtlregion = MTLRegionMake2D(rect->x, rect->y, rect->w, rect->h);
|
||||
mtlregion = MTLRegionMake2D(rect->x, rect->y, rect->w, rect->h);
|
||||
|
||||
// we only do BGRA8 or RGBA8 at the moment, so 4 will do.
|
||||
const int temp_pitch = rect->w * 4;
|
||||
void *temp_pixels = SDL_malloc(temp_pitch * rect->h);
|
||||
temp_pitch = rect->w * 4;
|
||||
temp_pixels = SDL_malloc(temp_pitch * rect->h);
|
||||
if (!temp_pixels) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
[mtltexture getBytes:temp_pixels bytesPerRow:temp_pitch fromRegion:mtlregion mipmapLevel:0];
|
||||
|
||||
const Uint32 temp_format = (mtltexture.pixelFormat == MTLPixelFormatBGRA8Unorm) ? SDL_PIXELFORMAT_ARGB8888 : SDL_PIXELFORMAT_ABGR8888;
|
||||
const int status = SDL_ConvertPixels(rect->w, rect->h, temp_format, temp_pixels, temp_pitch, pixel_format, pixels, pitch);
|
||||
temp_format = (mtltexture.pixelFormat == MTLPixelFormatBGRA8Unorm) ? SDL_PIXELFORMAT_ARGB8888 : SDL_PIXELFORMAT_ABGR8888;
|
||||
status = SDL_ConvertPixels(rect->w, rect->h, temp_format, temp_pixels, temp_pitch, pixel_format, pixels, pitch);
|
||||
SDL_free(temp_pixels);
|
||||
return status;
|
||||
}}
|
||||
|
@ -1542,8 +1566,9 @@ METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
|
|||
// note that data.mtlcmdencoder can be nil if METAL_ActivateRenderCommandEncoder fails.
|
||||
// Before SDL 2.0.18, it might have returned a non-nil encoding that might not have been
|
||||
// usable for presentation. Check your return values!
|
||||
METAL_RenderData *data;
|
||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
|
||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||
data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||
return (__bridge void*)data.mtlcmdencoder;
|
||||
}}
|
||||
|
||||
|
@ -1603,8 +1628,58 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
|||
SDL_MetalView view = NULL;
|
||||
CAMetalLayer *layer = nil;
|
||||
SDL_SysWMinfo syswm;
|
||||
Uint32 window_flags;
|
||||
SDL_bool changed_window = SDL_FALSE;
|
||||
NSError *err = nil;
|
||||
dispatch_data_t mtllibdata;
|
||||
char *constantdata;
|
||||
int maxtexsize, quadcount = UINT16_MAX / 4;
|
||||
UInt16 *indexdata;
|
||||
Uint32 window_flags;
|
||||
size_t indicessize = sizeof(UInt16) * quadcount * 6;
|
||||
MTLSamplerDescriptor *samplerdesc;
|
||||
id<MTLCommandQueue> mtlcmdqueue;
|
||||
id<MTLLibrary> mtllibrary;
|
||||
id<MTLSamplerState> mtlsamplernearest, mtlsamplerlinear;
|
||||
id<MTLBuffer> mtlbufconstantstaging, mtlbufquadindicesstaging, mtlbufconstants, mtlbufquadindices;
|
||||
id<MTLCommandBuffer> cmdbuffer;
|
||||
id<MTLBlitCommandEncoder> blitcmd;
|
||||
|
||||
/* Note: matrices are column major. */
|
||||
float identitytransform[16] = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
|
||||
float halfpixeltransform[16] = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.0f, 1.0f,
|
||||
};
|
||||
|
||||
/* Metal pads float3s to 16 bytes. */
|
||||
float decodetransformJPEG[4*4] = {
|
||||
0.0, -0.501960814, -0.501960814, 0.0, /* offset */
|
||||
1.0000, 0.0000, 1.4020, 0.0, /* Rcoeff */
|
||||
1.0000, -0.3441, -0.7141, 0.0, /* Gcoeff */
|
||||
1.0000, 1.7720, 0.0000, 0.0, /* Bcoeff */
|
||||
};
|
||||
|
||||
float decodetransformBT601[4*4] = {
|
||||
-0.0627451017, -0.501960814, -0.501960814, 0.0, /* offset */
|
||||
1.1644, 0.0000, 1.5960, 0.0, /* Rcoeff */
|
||||
1.1644, -0.3918, -0.8130, 0.0, /* Gcoeff */
|
||||
1.1644, 2.0172, 0.0000, 0.0, /* Bcoeff */
|
||||
};
|
||||
|
||||
float decodetransformBT709[4*4] = {
|
||||
0.0, -0.501960814, -0.501960814, 0.0, /* offset */
|
||||
1.0000, 0.0000, 1.4020, 0.0, /* Rcoeff */
|
||||
1.0000, -0.3441, -0.7141, 0.0, /* Gcoeff */
|
||||
1.0000, 1.7720, 0.0000, 0.0, /* Bcoeff */
|
||||
};
|
||||
|
||||
SDL_VERSION(&syswm.version);
|
||||
if (!SDL_GetWindowWMInfo(window, &syswm)) {
|
||||
|
@ -1691,17 +1766,15 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
|||
|
||||
data.mtldevice = layer.device;
|
||||
data.mtllayer = layer;
|
||||
id<MTLCommandQueue> mtlcmdqueue = [data.mtldevice newCommandQueue];
|
||||
mtlcmdqueue = [data.mtldevice newCommandQueue];
|
||||
data.mtlcmdqueue = mtlcmdqueue;
|
||||
data.mtlcmdqueue.label = @"SDL Metal Renderer";
|
||||
data.mtlpassdesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
|
||||
NSError *err = nil;
|
||||
|
||||
// The compiled .metallib is embedded in a static array in a header file
|
||||
// but the original shader source code is in SDL_shaders_metal.metal.
|
||||
dispatch_data_t mtllibdata = dispatch_data_create(sdl_metallib, sdl_metallib_len, dispatch_get_global_queue(0, 0), ^{});
|
||||
id<MTLLibrary> mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err];
|
||||
mtllibdata = dispatch_data_create(sdl_metallib, sdl_metallib_len, dispatch_get_global_queue(0, 0), ^{});
|
||||
mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err];
|
||||
data.mtllibrary = mtllibrary;
|
||||
SDL_assert(err == nil);
|
||||
data.mtllibrary.label = @"SDL Metal renderer shader library";
|
||||
|
@ -1711,74 +1784,35 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
|||
data.allpipelines = NULL;
|
||||
ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm);
|
||||
|
||||
MTLSamplerDescriptor *samplerdesc = [[MTLSamplerDescriptor alloc] init];
|
||||
samplerdesc = [[MTLSamplerDescriptor alloc] init];
|
||||
|
||||
samplerdesc.minFilter = MTLSamplerMinMagFilterNearest;
|
||||
samplerdesc.magFilter = MTLSamplerMinMagFilterNearest;
|
||||
id<MTLSamplerState> mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
||||
mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
||||
data.mtlsamplernearest = mtlsamplernearest;
|
||||
|
||||
samplerdesc.minFilter = MTLSamplerMinMagFilterLinear;
|
||||
samplerdesc.magFilter = MTLSamplerMinMagFilterLinear;
|
||||
id<MTLSamplerState> mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
||||
mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
||||
data.mtlsamplerlinear = mtlsamplerlinear;
|
||||
|
||||
/* Note: matrices are column major. */
|
||||
float identitytransform[16] = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared];
|
||||
|
||||
float halfpixeltransform[16] = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.0f, 1.0f,
|
||||
};
|
||||
|
||||
/* Metal pads float3s to 16 bytes. */
|
||||
float decodetransformJPEG[4*4] = {
|
||||
0.0, -0.501960814, -0.501960814, 0.0, /* offset */
|
||||
1.0000, 0.0000, 1.4020, 0.0, /* Rcoeff */
|
||||
1.0000, -0.3441, -0.7141, 0.0, /* Gcoeff */
|
||||
1.0000, 1.7720, 0.0000, 0.0, /* Bcoeff */
|
||||
};
|
||||
|
||||
float decodetransformBT601[4*4] = {
|
||||
-0.0627451017, -0.501960814, -0.501960814, 0.0, /* offset */
|
||||
1.1644, 0.0000, 1.5960, 0.0, /* Rcoeff */
|
||||
1.1644, -0.3918, -0.8130, 0.0, /* Gcoeff */
|
||||
1.1644, 2.0172, 0.0000, 0.0, /* Bcoeff */
|
||||
};
|
||||
|
||||
float decodetransformBT709[4*4] = {
|
||||
0.0, -0.501960814, -0.501960814, 0.0, /* offset */
|
||||
1.0000, 0.0000, 1.4020, 0.0, /* Rcoeff */
|
||||
1.0000, -0.3441, -0.7141, 0.0, /* Gcoeff */
|
||||
1.0000, 1.7720, 0.0000, 0.0, /* Bcoeff */
|
||||
};
|
||||
|
||||
id<MTLBuffer> mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared];
|
||||
|
||||
char *constantdata = [mtlbufconstantstaging contents];
|
||||
constantdata = [mtlbufconstantstaging contents];
|
||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_IDENTITY, identitytransform, sizeof(identitytransform));
|
||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_HALF_PIXEL_TRANSFORM, halfpixeltransform, sizeof(halfpixeltransform));
|
||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_JPEG, decodetransformJPEG, sizeof(decodetransformJPEG));
|
||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT601, decodetransformBT601, sizeof(decodetransformBT601));
|
||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT709, decodetransformBT709, sizeof(decodetransformBT709));
|
||||
|
||||
int quadcount = UINT16_MAX / 4;
|
||||
size_t indicessize = sizeof(UInt16) * quadcount * 6;
|
||||
id<MTLBuffer> mtlbufquadindicesstaging = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModeShared];
|
||||
mtlbufquadindicesstaging = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModeShared];
|
||||
|
||||
/* Quads in the following vertex order (matches the FillRects vertices):
|
||||
* 1---3
|
||||
* | \ |
|
||||
* 0---2
|
||||
*/
|
||||
UInt16 *indexdata = [mtlbufquadindicesstaging contents];
|
||||
indexdata = [mtlbufquadindicesstaging contents];
|
||||
for (int i = 0; i < quadcount; i++) {
|
||||
indexdata[i * 6 + 0] = i * 4 + 0;
|
||||
indexdata[i * 6 + 1] = i * 4 + 1;
|
||||
|
@ -1789,16 +1823,16 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
|||
indexdata[i * 6 + 5] = i * 4 + 3;
|
||||
}
|
||||
|
||||
id<MTLBuffer> mtlbufconstants = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModePrivate];
|
||||
mtlbufconstants = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModePrivate];
|
||||
data.mtlbufconstants = mtlbufconstants;
|
||||
data.mtlbufconstants.label = @"SDL constant data";
|
||||
|
||||
id<MTLBuffer> mtlbufquadindices = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModePrivate];
|
||||
mtlbufquadindices = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModePrivate];
|
||||
data.mtlbufquadindices = mtlbufquadindices;
|
||||
data.mtlbufquadindices.label = @"SDL quad index buffer";
|
||||
|
||||
id<MTLCommandBuffer> cmdbuffer = [data.mtlcmdqueue commandBuffer];
|
||||
id<MTLBlitCommandEncoder> blitcmd = [cmdbuffer blitCommandEncoder];
|
||||
cmdbuffer = [data.mtlcmdqueue commandBuffer];
|
||||
blitcmd = [cmdbuffer blitCommandEncoder];
|
||||
|
||||
[blitcmd copyFromBuffer:mtlbufconstantstaging sourceOffset:0 toBuffer:mtlbufconstants destinationOffset:0 size:CONSTANTS_LENGTH];
|
||||
[blitcmd copyFromBuffer:mtlbufquadindicesstaging sourceOffset:0 toBuffer:mtlbufquadindices destinationOffset:0 size:indicessize];
|
||||
|
@ -1853,7 +1887,7 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
|||
}
|
||||
|
||||
/* https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf */
|
||||
int maxtexsize = 4096;
|
||||
maxtexsize = 4096;
|
||||
#if defined(__MACOSX__) || TARGET_OS_MACCATALYST
|
||||
maxtexsize = 16384;
|
||||
#elif defined(__TVOS__)
|
||||
|
|
|
@ -87,8 +87,7 @@ SDL_TicksInit(void)
|
|||
has_monotonic_time = SDL_TRUE;
|
||||
} else
|
||||
#elif defined(__APPLE__)
|
||||
kern_return_t ret = mach_timebase_info(&mach_base_info);
|
||||
if (ret == 0) {
|
||||
if (0 == mach_timebase_info(&mach_base_info)) {
|
||||
has_monotonic_time = SDL_TRUE;
|
||||
start_mach = mach_absolute_time();
|
||||
} else
|
||||
|
|
|
@ -229,6 +229,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
|
|||
|
||||
- (void)focusSomeWindow:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_VideoDevice *device;
|
||||
/* HACK: Ignore the first call. The application gets a
|
||||
* applicationDidBecomeActive: a little bit after the first window is
|
||||
* created, and if we don't ignore it, a window that has been created with
|
||||
|
@ -246,7 +247,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
|
|||
return;
|
||||
}
|
||||
|
||||
SDL_VideoDevice *device = SDL_GetVideoDevice();
|
||||
device = SDL_GetVideoDevice();
|
||||
if (device && device->windows) {
|
||||
SDL_Window *window = device->windows;
|
||||
int i;
|
||||
|
|
|
@ -390,6 +390,7 @@ UpdateKeymap(SDL_VideoData *data, SDL_bool send_event)
|
|||
int i;
|
||||
SDL_Scancode scancode;
|
||||
SDL_Keycode keymap[SDL_NUM_SCANCODES];
|
||||
CFDataRef uchrDataRef;
|
||||
|
||||
/* See if the keymap needs to be updated */
|
||||
key_layout = TISCopyCurrentKeyboardLayoutInputSource();
|
||||
|
@ -401,7 +402,7 @@ UpdateKeymap(SDL_VideoData *data, SDL_bool send_event)
|
|||
SDL_GetDefaultKeymap(keymap);
|
||||
|
||||
/* Try Unicode data first */
|
||||
CFDataRef uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
|
||||
uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
|
||||
if (uchrDataRef) {
|
||||
chr_data = CFDataGetBytePtr(uchrDataRef);
|
||||
} else {
|
||||
|
@ -472,6 +473,7 @@ void
|
|||
Cocoa_StartTextInput(_THIS)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSView *parentView;
|
||||
SDL_VideoData *data = (__bridge SDL_VideoData *) _this->driverdata;
|
||||
SDL_Window *window = SDL_GetKeyboardFocus();
|
||||
NSWindow *nswindow = nil;
|
||||
|
@ -479,7 +481,7 @@ Cocoa_StartTextInput(_THIS)
|
|||
nswindow = ((__bridge SDL_WindowData*)window->driverdata).nswindow;
|
||||
}
|
||||
|
||||
NSView *parentView = [nswindow contentView];
|
||||
parentView = [nswindow contentView];
|
||||
|
||||
/* We only keep one field editor per process, since only the front most
|
||||
* window can receive text input events, so it make no sense to keep more
|
||||
|
@ -527,13 +529,14 @@ Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect)
|
|||
void
|
||||
Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
|
||||
{
|
||||
unsigned short scancode;
|
||||
SDL_Scancode code;
|
||||
SDL_VideoData *data = _this ? ((__bridge SDL_VideoData *) _this->driverdata) : nil;
|
||||
if (!data) {
|
||||
return; /* can happen when returning from fullscreen Space on shutdown */
|
||||
}
|
||||
|
||||
unsigned short scancode = [event keyCode];
|
||||
SDL_Scancode code;
|
||||
scancode = [event keyCode];
|
||||
#if 0
|
||||
const char *text;
|
||||
#endif
|
||||
|
|
|
@ -92,9 +92,14 @@
|
|||
static void
|
||||
Cocoa_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid, int *returnValue)
|
||||
{
|
||||
NSAlert* alert;
|
||||
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
||||
SDLMessageBoxPresenter* presenter;
|
||||
NSInteger clicked;
|
||||
int i;
|
||||
Cocoa_RegisterApp();
|
||||
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
alert = [[NSAlert alloc] init];
|
||||
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_ERROR) {
|
||||
[alert setAlertStyle:NSAlertStyleCritical];
|
||||
|
@ -107,8 +112,6 @@ Cocoa_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid
|
|||
[alert setMessageText:[NSString stringWithUTF8String:messageboxdata->title]];
|
||||
[alert setInformativeText:[NSString stringWithUTF8String:messageboxdata->message]];
|
||||
|
||||
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
||||
int i;
|
||||
for (i = 0; i < messageboxdata->numbuttons; ++i) {
|
||||
const SDL_MessageBoxButtonData *sdlButton;
|
||||
NSButton *button;
|
||||
|
@ -129,11 +132,11 @@ Cocoa_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid
|
|||
}
|
||||
}
|
||||
|
||||
SDLMessageBoxPresenter* presenter = [[SDLMessageBoxPresenter alloc] initWithParentWindow:messageboxdata->window];
|
||||
presenter = [[SDLMessageBoxPresenter alloc] initWithParentWindow:messageboxdata->window];
|
||||
|
||||
[presenter showAlert:alert];
|
||||
|
||||
NSInteger clicked = presenter->clicked;
|
||||
clicked = presenter->clicked;
|
||||
if (clicked >= NSAlertFirstButtonReturn) {
|
||||
clicked -= NSAlertFirstButtonReturn;
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
|
||||
|
|
|
@ -185,6 +185,9 @@ GetDisplayMode(_THIS, CGDisplayModeRef vidmode, SDL_bool vidmodeCurrent, CFArray
|
|||
int i;
|
||||
|
||||
for (i = 0; i < modescount; i++) {
|
||||
int otherW, otherH, otherpixelW, otherpixelH, otherrefresh;
|
||||
Uint32 otherformat;
|
||||
bool otherGUI;
|
||||
CGDisplayModeRef othermode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modelist, i);
|
||||
uint32_t otherioflags = CGDisplayModeGetIOFlags(othermode);
|
||||
|
||||
|
@ -196,13 +199,13 @@ GetDisplayMode(_THIS, CGDisplayModeRef vidmode, SDL_bool vidmodeCurrent, CFArray
|
|||
continue;
|
||||
}
|
||||
|
||||
int otherW = (int) CGDisplayModeGetWidth(othermode);
|
||||
int otherH = (int) CGDisplayModeGetHeight(othermode);
|
||||
int otherpixelW = (int) CGDisplayModeGetPixelWidth(othermode);
|
||||
int otherpixelH = (int) CGDisplayModeGetPixelHeight(othermode);
|
||||
int otherrefresh = GetDisplayModeRefreshRate(othermode, link);
|
||||
Uint32 otherformat = GetDisplayModePixelFormat(othermode);
|
||||
bool otherGUI = CGDisplayModeIsUsableForDesktopGUI(othermode);
|
||||
otherW = (int) CGDisplayModeGetWidth(othermode);
|
||||
otherH = (int) CGDisplayModeGetHeight(othermode);
|
||||
otherpixelW = (int) CGDisplayModeGetPixelWidth(othermode);
|
||||
otherpixelH = (int) CGDisplayModeGetPixelHeight(othermode);
|
||||
otherrefresh = GetDisplayModeRefreshRate(othermode, link);
|
||||
otherformat = GetDisplayModePixelFormat(othermode);
|
||||
otherGUI = CGDisplayModeIsUsableForDesktopGUI(othermode);
|
||||
|
||||
/* Ignore this mode if it's low-dpi (@1x) and we have a high-dpi
|
||||
* mode in the list with the same size in points.
|
||||
|
@ -417,11 +420,13 @@ Cocoa_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
|
|||
return -1;
|
||||
}
|
||||
|
||||
const NSRect frame = [screen visibleFrame];
|
||||
rect->x = (int)frame.origin.x;
|
||||
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
|
||||
rect->w = (int)frame.size.width;
|
||||
rect->h = (int)frame.size.height;
|
||||
{
|
||||
const NSRect frame = [screen visibleFrame];
|
||||
rect->x = (int)frame.origin.x;
|
||||
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
|
||||
rect->w = (int)frame.size.width;
|
||||
rect->h = (int)frame.size.height;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -487,20 +492,21 @@ Cocoa_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdp
|
|||
}
|
||||
}
|
||||
|
||||
const CGSize displaySize = CGDisplayScreenSize(data->display);
|
||||
const int pixelWidth = displayNativeSize.width;
|
||||
const int pixelHeight = displayNativeSize.height;
|
||||
{
|
||||
const CGSize displaySize = CGDisplayScreenSize(data->display);
|
||||
const int pixelWidth = displayNativeSize.width;
|
||||
const int pixelHeight = displayNativeSize.height;
|
||||
|
||||
if (ddpi) {
|
||||
*ddpi = (SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH));
|
||||
if (ddpi) {
|
||||
*ddpi = (SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH));
|
||||
}
|
||||
if (hdpi) {
|
||||
*hdpi = (pixelWidth * MM_IN_INCH / displaySize.width);
|
||||
}
|
||||
if (vdpi) {
|
||||
*vdpi = (pixelHeight * MM_IN_INCH / displaySize.height);
|
||||
}
|
||||
}
|
||||
if (hdpi) {
|
||||
*hdpi = (pixelWidth * MM_IN_INCH / displaySize.width);
|
||||
}
|
||||
if (vdpi) {
|
||||
*vdpi = (pixelHeight * MM_IN_INCH / displaySize.height);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}}
|
||||
|
||||
|
|
|
@ -112,35 +112,37 @@ static NSCursor *
|
|||
LoadHiddenSystemCursor(NSString *cursorName, SEL fallback)
|
||||
{
|
||||
NSString *cursorPath = [@"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/Resources/cursors" stringByAppendingPathComponent:cursorName];
|
||||
NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[cursorPath stringByAppendingPathComponent:@"info.plist"]];
|
||||
/* we can't do animation atm. :/ */
|
||||
const int frames = [[info valueForKey:@"frames"] integerValue];
|
||||
NSCursor *cursor;
|
||||
NSImage *image = [[NSImage alloc] initWithContentsOfFile:[cursorPath stringByAppendingPathComponent:@"cursor.pdf"]];
|
||||
if ((image == nil) || (image.valid == NO)) {
|
||||
return [NSCursor performSelector:fallback];
|
||||
}
|
||||
|
||||
NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[cursorPath stringByAppendingPathComponent:@"info.plist"]];
|
||||
|
||||
/* we can't do animation atm. :/ */
|
||||
const int frames = [[info valueForKey:@"frames"] integerValue];
|
||||
if (frames > 1) {
|
||||
#ifdef MAC_OS_VERSION_12_0 /* same value as deprecated symbol. */
|
||||
const NSCompositingOperation operation = NSCompositingOperationCopy;
|
||||
#else
|
||||
const NSCompositingOperation operation = NSCompositeCopy;
|
||||
#endif
|
||||
const NSSize cropped_size = NSMakeSize(image.size.width, (int) (image.size.height / frames));
|
||||
NSImage *cropped = [[NSImage alloc] initWithSize:cropped_size];
|
||||
if (cropped == nil) {
|
||||
return [NSCursor performSelector:fallback];
|
||||
}
|
||||
|
||||
#ifdef MAC_OS_VERSION_12_0 /* same value as deprecated symbol. */
|
||||
const NSCompositingOperation operation = NSCompositingOperationCopy;
|
||||
#else
|
||||
const NSCompositingOperation operation = NSCompositeCopy;
|
||||
#endif
|
||||
[cropped lockFocus];
|
||||
const NSRect cropped_rect = NSMakeRect(0, 0, cropped_size.width, cropped_size.height);
|
||||
[image drawInRect:cropped_rect fromRect:cropped_rect operation:operation fraction:1];
|
||||
{
|
||||
const NSRect cropped_rect = NSMakeRect(0, 0, cropped_size.width, cropped_size.height);
|
||||
[image drawInRect:cropped_rect fromRect:cropped_rect operation:operation fraction:1];
|
||||
}
|
||||
[cropped unlockFocus];
|
||||
image = cropped;
|
||||
}
|
||||
|
||||
NSCursor *cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint([[info valueForKey:@"hotx"] doubleValue], [[info valueForKey:@"hoty"] doubleValue])];
|
||||
cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint([[info valueForKey:@"hotx"] doubleValue], [[info valueForKey:@"hoty"] doubleValue])];
|
||||
return cursor;
|
||||
}
|
||||
|
||||
|
@ -247,6 +249,7 @@ SDL_FindWindowAtPoint(const int x, const int y)
|
|||
static int
|
||||
Cocoa_WarpMouseGlobal(int x, int y)
|
||||
{
|
||||
CGPoint point;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (mouse->focus) {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) mouse->focus->driverdata;
|
||||
|
@ -256,7 +259,7 @@ Cocoa_WarpMouseGlobal(int x, int y)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
const CGPoint point = CGPointMake((float)x, (float)y);
|
||||
point = CGPointMake((float)x, (float)y);
|
||||
|
||||
Cocoa_HandleMouseWarp(point.x, point.y);
|
||||
|
||||
|
@ -295,6 +298,8 @@ static int
|
|||
Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
CGError result;
|
||||
SDL_Window *window;
|
||||
SDL_WindowData *data;
|
||||
if (enabled) {
|
||||
DLog("Turning on.");
|
||||
result = CGAssociateMouseAndMouseCursorPosition(NO);
|
||||
|
@ -309,7 +314,7 @@ Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
|||
/* We will re-apply the non-relative mode when the window gets focus, if it
|
||||
* doesn't have focus right now.
|
||||
*/
|
||||
SDL_Window *window = SDL_GetKeyboardFocus();
|
||||
window = SDL_GetKeyboardFocus();
|
||||
if (!window) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -317,7 +322,7 @@ Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
|||
/* We will re-apply the non-relative mode when the window finishes being moved,
|
||||
* if it is being moved right now.
|
||||
*/
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
if ([data.listener isMovingOrFocusClickPending]) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -363,6 +368,7 @@ Cocoa_GetGlobalMouseState(int *x, int *y)
|
|||
int
|
||||
Cocoa_InitMouse(_THIS)
|
||||
{
|
||||
NSPoint location;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_MouseData *driverdata = (SDL_MouseData*) SDL_calloc(1, sizeof(SDL_MouseData));
|
||||
if (driverdata == NULL) {
|
||||
|
@ -382,7 +388,7 @@ Cocoa_InitMouse(_THIS)
|
|||
|
||||
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
|
||||
|
||||
const NSPoint location = [NSEvent mouseLocation];
|
||||
location = [NSEvent mouseLocation];
|
||||
driverdata->lastMoveX = location.x;
|
||||
driverdata->lastMoveY = location.y;
|
||||
return 0;
|
||||
|
@ -419,6 +425,13 @@ Cocoa_HandleTitleButtonEvent(_THIS, NSEvent *event)
|
|||
void
|
||||
Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
||||
{
|
||||
SDL_Mouse *mouse;
|
||||
SDL_MouseData *driverdata;
|
||||
SDL_MouseID mouseID;
|
||||
NSPoint location;
|
||||
CGFloat lastMoveX, lastMoveY;
|
||||
float deltaX, deltaY;
|
||||
SDL_bool seenWarp;
|
||||
switch ([event type]) {
|
||||
case NSEventTypeMouseMoved:
|
||||
case NSEventTypeLeftMouseDragged:
|
||||
|
@ -446,19 +459,19 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
|||
return;
|
||||
}
|
||||
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
|
||||
mouse = SDL_GetMouse();
|
||||
driverdata = (SDL_MouseData*)mouse->driverdata;
|
||||
if (!driverdata) {
|
||||
return; /* can happen when returning from fullscreen Space on shutdown */
|
||||
}
|
||||
|
||||
SDL_MouseID mouseID = mouse ? mouse->mouseID : 0;
|
||||
const SDL_bool seenWarp = driverdata->seenWarp;
|
||||
mouseID = mouse ? mouse->mouseID : 0;
|
||||
seenWarp = driverdata->seenWarp;
|
||||
driverdata->seenWarp = NO;
|
||||
|
||||
const NSPoint location = [NSEvent mouseLocation];
|
||||
const CGFloat lastMoveX = driverdata->lastMoveX;
|
||||
const CGFloat lastMoveY = driverdata->lastMoveY;
|
||||
location = [NSEvent mouseLocation];
|
||||
lastMoveX = driverdata->lastMoveX;
|
||||
lastMoveY = driverdata->lastMoveY;
|
||||
driverdata->lastMoveX = location.x;
|
||||
driverdata->lastMoveY = location.y;
|
||||
DLog("Last seen mouse: (%g, %g)", location.x, location.y);
|
||||
|
@ -476,8 +489,8 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
float deltaX = [event deltaX];
|
||||
float deltaY = [event deltaY];
|
||||
deltaX = [event deltaX];
|
||||
deltaY = [event deltaY];
|
||||
|
||||
if (seenWarp) {
|
||||
deltaX += (lastMoveX - driverdata->lastWarpX);
|
||||
|
@ -492,15 +505,18 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
|
|||
void
|
||||
Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
|
||||
{
|
||||
SDL_MouseID mouseID;
|
||||
SDL_MouseWheelDirection direction;
|
||||
CGFloat x, y;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (!mouse) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_MouseID mouseID = mouse->mouseID;
|
||||
CGFloat x = -[event deltaX];
|
||||
CGFloat y = [event deltaY];
|
||||
SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL;
|
||||
mouseID = mouse->mouseID;
|
||||
x = -[event deltaX];
|
||||
y = [event deltaY];
|
||||
direction = SDL_MOUSEWHEEL_NORMAL;
|
||||
|
||||
if ([event isDirectionInvertedFromDevice] == YES) {
|
||||
direction = SDL_MOUSEWHEEL_FLIPPED;
|
||||
|
|
|
@ -189,6 +189,7 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
|
|||
const char *glversion;
|
||||
int glversion_major;
|
||||
int glversion_minor;
|
||||
NSOpenGLPixelFormatAttribute profile;
|
||||
|
||||
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
|
||||
#if SDL_VIDEO_OPENGL_EGL
|
||||
|
@ -216,7 +217,7 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
|
|||
|
||||
attr[i++] = NSOpenGLPFAAllowOfflineRenderers;
|
||||
|
||||
NSOpenGLPixelFormatAttribute profile = NSOpenGLProfileVersionLegacy;
|
||||
profile = NSOpenGLProfileVersionLegacy;
|
||||
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_CORE) {
|
||||
profile = NSOpenGLProfileVersion3_2Core;
|
||||
}
|
||||
|
|
|
@ -115,6 +115,7 @@ Cocoa_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
|||
int
|
||||
Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSView* v;
|
||||
/* The current context is lost in here; save it and reset it. */
|
||||
SDL_WindowData *windowdata = (__bridge SDL_WindowData *) window->driverdata;
|
||||
SDL_Window *current_win = SDL_GL_GetCurrentWindow();
|
||||
|
@ -134,7 +135,7 @@ Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window)
|
|||
}
|
||||
|
||||
/* Create the GLES window surface */
|
||||
NSView* v = windowdata.nswindow.contentView;
|
||||
v = windowdata.nswindow.contentView;
|
||||
windowdata.egl_surface = SDL_EGL_CreateSurface(_this, (__bridge NativeWindowType)[v layer]);
|
||||
|
||||
if (windowdata.egl_surface == EGL_NO_SURFACE) {
|
||||
|
|
|
@ -31,25 +31,28 @@ SDL_WindowShaper*
|
|||
Cocoa_CreateShaper(SDL_Window* window)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
SDL_WindowShaper* result;
|
||||
SDL_ShapeData* data;
|
||||
int resized_properly;
|
||||
SDL_WindowData* windata = (__bridge SDL_WindowData*)window->driverdata;
|
||||
[windata.nswindow setOpaque:NO];
|
||||
|
||||
[windata.nswindow setStyleMask:NSWindowStyleMaskBorderless];
|
||||
|
||||
SDL_WindowShaper* result = (SDL_WindowShaper *)SDL_malloc(sizeof(SDL_WindowShaper));
|
||||
result = (SDL_WindowShaper *)SDL_malloc(sizeof(SDL_WindowShaper));
|
||||
result->window = window;
|
||||
result->mode.mode = ShapeModeDefault;
|
||||
result->mode.parameters.binarizationCutoff = 1;
|
||||
result->userx = result->usery = 0;
|
||||
window->shaper = result;
|
||||
|
||||
SDL_ShapeData* data = (SDL_ShapeData *)SDL_malloc(sizeof(SDL_ShapeData));
|
||||
data = (SDL_ShapeData *)SDL_malloc(sizeof(SDL_ShapeData));
|
||||
result->driverdata = data;
|
||||
data->context = [windata.nswindow graphicsContext];
|
||||
data->saved = SDL_FALSE;
|
||||
data->shape = NULL;
|
||||
|
||||
int resized_properly = Cocoa_ResizeWindowShape(window);
|
||||
resized_properly = Cocoa_ResizeWindowShape(window);
|
||||
SDL_assert(resized_properly == 0);
|
||||
return result;
|
||||
}}
|
||||
|
|
|
@ -123,13 +123,14 @@
|
|||
|
||||
- (void)sendEvent:(NSEvent *)event
|
||||
{
|
||||
id delegate;
|
||||
[super sendEvent:event];
|
||||
|
||||
if ([event type] != NSEventTypeLeftMouseUp) {
|
||||
return;
|
||||
}
|
||||
|
||||
id delegate = [self delegate];
|
||||
delegate = [self delegate];
|
||||
if (![delegate isKindOfClass:[Cocoa_WindowListener class]]) {
|
||||
return;
|
||||
}
|
||||
|
@ -163,24 +164,29 @@
|
|||
NSArray *types = [NSArray arrayWithObject:NSFilenamesPboardType];
|
||||
NSString *desiredType = [pasteboard availableTypeFromArray:types];
|
||||
SDL_Window *sdlwindow = [self findSDLWindow];
|
||||
NSData *data;
|
||||
NSArray *array;
|
||||
NSPoint point;
|
||||
SDL_Mouse *mouse;
|
||||
int x, y;
|
||||
|
||||
if (desiredType == nil) {
|
||||
return NO; /* can't accept anything that's being dropped here. */
|
||||
}
|
||||
|
||||
NSData *data = [pasteboard dataForType:desiredType];
|
||||
data = [pasteboard dataForType:desiredType];
|
||||
if (data == nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
SDL_assert([desiredType isEqualToString:NSFilenamesPboardType]);
|
||||
NSArray *array = [pasteboard propertyListForType:@"NSFilenamesPboardType"];
|
||||
array = [pasteboard propertyListForType:@"NSFilenamesPboardType"];
|
||||
|
||||
/* Code addon to update the mouse location */
|
||||
NSPoint point = [sender draggingLocation];
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
int x = (int)point.x;
|
||||
int y = (int)(sdlwindow->h - point.y);
|
||||
point = [sender draggingLocation];
|
||||
mouse = SDL_GetMouse();
|
||||
x = (int)point.x;
|
||||
y = (int)(sdlwindow->h - point.y);
|
||||
if (x >= 0 && x < sdlwindow->w && y >= 0 && y < sdlwindow->h) {
|
||||
SDL_SendMouseMotion(sdlwindow, mouse->mouseID, 0, x, y);
|
||||
}
|
||||
|
@ -254,6 +260,8 @@ static void ConvertNSRect(NSScreen *screen, BOOL fullscreen, NSRect *r)
|
|||
static void
|
||||
ScheduleContextUpdates(SDL_WindowData *data)
|
||||
{
|
||||
NSOpenGLContext *currentContext;
|
||||
NSMutableArray *contexts;
|
||||
if (!data || !data.nscontexts) {
|
||||
return;
|
||||
}
|
||||
|
@ -264,8 +272,8 @@ ScheduleContextUpdates(SDL_WindowData *data)
|
|||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
NSOpenGLContext *currentContext = [NSOpenGLContext currentContext];
|
||||
NSMutableArray *contexts = data.nscontexts;
|
||||
currentContext = [NSOpenGLContext currentContext];
|
||||
contexts = data.nscontexts;
|
||||
@synchronized (contexts) {
|
||||
for (SDLOpenGLContext *context in contexts) {
|
||||
if (context == currentContext) {
|
||||
|
@ -763,15 +771,19 @@ Cocoa_UpdateClipCursor(SDL_Window * window)
|
|||
|
||||
- (void)windowDidResize:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_Window *window;
|
||||
NSWindow *nswindow;
|
||||
NSRect rect;
|
||||
int x, y, w, h;
|
||||
BOOL zoomed;
|
||||
if (inFullscreenTransition) {
|
||||
/* We'll take care of this at the end of the transition */
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Window *window = _data.window;
|
||||
NSWindow *nswindow = _data.nswindow;
|
||||
int x, y, w, h;
|
||||
NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
|
||||
window = _data.window;
|
||||
nswindow = _data.nswindow;
|
||||
rect = [nswindow contentRectForFrameRect:[nswindow frame]];
|
||||
ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
|
||||
x = (int)rect.origin.x;
|
||||
y = (int)rect.origin.y;
|
||||
|
@ -789,7 +801,7 @@ Cocoa_UpdateClipCursor(SDL_Window * window)
|
|||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
|
||||
|
||||
const BOOL zoomed = [nswindow isZoomed];
|
||||
zoomed = [nswindow isZoomed];
|
||||
if (!zoomed) {
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
|
||||
} else if (zoomed) {
|
||||
|
@ -844,10 +856,11 @@ Cocoa_UpdateClipCursor(SDL_Window * window)
|
|||
if ((isFullscreenSpace) && ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)) {
|
||||
[NSMenu setMenuBarVisible:NO];
|
||||
}
|
||||
|
||||
const unsigned int newflags = [NSEvent modifierFlags] & NSEventModifierFlagCapsLock;
|
||||
_data.videodata.modifierFlags = (_data.videodata.modifierFlags & ~NSEventModifierFlagCapsLock) | newflags;
|
||||
SDL_ToggleModState(KMOD_CAPS, newflags != 0);
|
||||
{
|
||||
const unsigned int newflags = [NSEvent modifierFlags] & NSEventModifierFlagCapsLock;
|
||||
_data.videodata.modifierFlags = (_data.videodata.modifierFlags & ~NSEventModifierFlagCapsLock) | newflags;
|
||||
SDL_ToggleModState(KMOD_CAPS, newflags != 0);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)windowDidResignKey:(NSNotification *)aNotification
|
||||
|
@ -1187,12 +1200,12 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
|||
- (void)mouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
int button;
|
||||
|
||||
if (!mouse) {
|
||||
return;
|
||||
}
|
||||
|
||||
int button;
|
||||
|
||||
/* Ignore events that aren't inside the client area (i.e. title bar.) */
|
||||
if ([theEvent window]) {
|
||||
NSRect windowRect = [[[theEvent window] contentView] frame];
|
||||
|
@ -1244,12 +1257,12 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
|||
- (void)mouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
int button;
|
||||
|
||||
if (!mouse) {
|
||||
return;
|
||||
}
|
||||
|
||||
int button;
|
||||
|
||||
if ([self processHitTest:theEvent]) {
|
||||
SDL_SendWindowEvent(_data.window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
|
||||
return; /* stopped dragging, drop event. */
|
||||
|
@ -1291,14 +1304,17 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
|||
- (void)mouseMoved:(NSEvent *)theEvent
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_MouseID mouseID;
|
||||
NSPoint point;
|
||||
int x, y;
|
||||
SDL_Window *window;
|
||||
|
||||
if (!mouse) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SDL_MouseID mouseID = mouse->mouseID;
|
||||
SDL_Window *window = _data.window;
|
||||
NSPoint point;
|
||||
int x, y;
|
||||
mouseID = mouse->mouseID;
|
||||
window = _data.window;
|
||||
|
||||
if ([self processHitTest:theEvent]) {
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
|
||||
|
@ -1350,6 +1366,10 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
|||
|
||||
- (void)touchesBeganWithEvent:(NSEvent *) theEvent
|
||||
{
|
||||
NSSet *touches;
|
||||
SDL_TouchID touchID;
|
||||
int existingTouchCount;
|
||||
|
||||
/* probably a MacBook trackpad; make this look like a synthesized event.
|
||||
This is backwards from reality, but better matches user expectations. */
|
||||
BOOL istrackpad = NO;
|
||||
|
@ -1365,9 +1385,9 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
|||
*/
|
||||
}
|
||||
|
||||
NSSet *touches = [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
|
||||
const SDL_TouchID touchID = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[[touches anyObject] device];
|
||||
int existingTouchCount = 0;
|
||||
touches = [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
|
||||
touchID = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[[touches anyObject] device];
|
||||
existingTouchCount = 0;
|
||||
|
||||
for (NSTouch* touch in touches) {
|
||||
if ([touch phase] != NSTouchPhaseBegan) {
|
||||
|
@ -1411,6 +1431,8 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
|||
- (void)handleTouches:(NSTouchPhase) phase withEvent:(NSEvent *) theEvent
|
||||
{
|
||||
NSSet *touches = [theEvent touchesMatchingPhase:phase inView:nil];
|
||||
SDL_FingerID fingerId;
|
||||
float x, y;
|
||||
|
||||
/* probably a MacBook trackpad; make this look like a synthesized event.
|
||||
This is backwards from reality, but better matches user expectations. */
|
||||
|
@ -1457,9 +1479,9 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
|||
return;
|
||||
}
|
||||
|
||||
const SDL_FingerID fingerId = (SDL_FingerID)(intptr_t)[touch identity];
|
||||
float x = [touch normalizedPosition].x;
|
||||
float y = [touch normalizedPosition].y;
|
||||
fingerId = (SDL_FingerID)(intptr_t)[touch identity];
|
||||
x = [touch normalizedPosition].x;
|
||||
y = [touch normalizedPosition].y;
|
||||
/* Make the origin the upper left instead of the lower left */
|
||||
y = 1.0f - y;
|
||||
|
||||
|
@ -1554,8 +1576,9 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
|
|||
|
||||
- (void)resetCursorRects
|
||||
{
|
||||
SDL_Mouse *mouse;
|
||||
[super resetCursorRects];
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
mouse = SDL_GetMouse();
|
||||
|
||||
if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) {
|
||||
[self addCursorRect:[self bounds]
|
||||
|
@ -1680,6 +1703,9 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
|
|||
SDL_Rect bounds;
|
||||
NSUInteger style;
|
||||
NSArray *screens = [NSScreen screens];
|
||||
NSScreen *screen = nil;
|
||||
SDLView *contentView;
|
||||
BOOL highdpi;
|
||||
|
||||
Cocoa_GetDisplayBounds(_this, display, &bounds);
|
||||
rect.origin.x = window->x;
|
||||
|
@ -1691,7 +1717,6 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
|
|||
style = GetWindowStyle(window);
|
||||
|
||||
/* Figure out which screen to place this window */
|
||||
NSScreen *screen = nil;
|
||||
for (NSScreen *candidate in screens) {
|
||||
NSRect screenRect = [candidate frame];
|
||||
if (rect.origin.x >= screenRect.origin.x &&
|
||||
|
@ -1732,7 +1757,7 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
|
|||
|
||||
/* Create a default view for this window */
|
||||
rect = [nswindow contentRectForFrameRect:[nswindow frame]];
|
||||
SDLView *contentView = [[SDLView alloc] initWithFrame:rect];
|
||||
contentView = [[SDLView alloc] initWithFrame:rect];
|
||||
[contentView setSDLWindow:window];
|
||||
|
||||
/* We still support OpenGL as long as Apple offers it, deprecated or not, so disable deprecation warnings about it. */
|
||||
|
@ -1742,7 +1767,7 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
|
|||
#endif
|
||||
/* Note: as of the macOS 10.15 SDK, this defaults to YES instead of NO when
|
||||
* the NSHighResolutionCapable boolean is set in Info.plist. */
|
||||
BOOL highdpi = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
||||
highdpi = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
||||
[contentView setWantsBestResolutionOpenGLSurface:highdpi];
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
|
@ -1789,6 +1814,8 @@ Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
|
|||
{
|
||||
NSView* nsview = nil;
|
||||
NSWindow *nswindow = nil;
|
||||
NSString *title;
|
||||
BOOL highdpi;
|
||||
|
||||
if ([(__bridge id)data isKindOfClass:[NSWindow class]]) {
|
||||
nswindow = (__bridge NSWindow*)data;
|
||||
|
@ -1800,8 +1827,6 @@ Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
|
|||
SDL_assert(false);
|
||||
}
|
||||
|
||||
NSString *title;
|
||||
|
||||
/* Query the title from the existing window */
|
||||
title = [nswindow title];
|
||||
if (title) {
|
||||
|
@ -1815,7 +1840,7 @@ Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
|
|||
#endif
|
||||
/* Note: as of the macOS 10.15 SDK, this defaults to YES instead of NO when
|
||||
* the NSHighResolutionCapable boolean is set in Info.plist. */
|
||||
BOOL highdpi = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
||||
highdpi = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
||||
[nsview setWantsBestResolutionOpenGLSurface:highdpi];
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
|
@ -2083,6 +2108,7 @@ Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
|
|||
|
||||
[nswindow setStyleMask:NSWindowStyleMaskBorderless];
|
||||
} else {
|
||||
NSRect frameRect;
|
||||
rect.origin.x = window->windowed.x;
|
||||
rect.origin.y = window->windowed.y;
|
||||
rect.size.width = window->windowed.w;
|
||||
|
@ -2098,7 +2124,7 @@ Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
|
|||
[nswindow setStyleMask:GetWindowWindowedStyle(window)];
|
||||
|
||||
/* Hack to restore window decorations on Mac OS X 10.10 */
|
||||
NSRect frameRect = [nswindow frame];
|
||||
frameRect = [nswindow frame];
|
||||
[nswindow setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO];
|
||||
[nswindow setFrame:frameRect display:NO];
|
||||
}
|
||||
|
@ -2204,6 +2230,9 @@ int
|
|||
Cocoa_GetWindowDisplayIndex(_THIS, SDL_Window * window)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSRect displayframe;
|
||||
SDL_Point display_center;
|
||||
SDL_Rect sdl_display_rect;
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
|
||||
/* Not recognized via CHECK_WINDOW_MAGIC */
|
||||
|
@ -2216,9 +2245,7 @@ Cocoa_GetWindowDisplayIndex(_THIS, SDL_Window * window)
|
|||
instead of checking in which display the window is placed, we should check which SDL display matches the display described
|
||||
via displayframe.
|
||||
*/
|
||||
NSRect displayframe = data.nswindow.screen.frame;
|
||||
SDL_Point display_center;
|
||||
SDL_Rect sdl_display_rect;
|
||||
displayframe = data.nswindow.screen.frame;
|
||||
|
||||
display_center.x = displayframe.origin.x + displayframe.size.width / 2;
|
||||
display_center.y = displayframe.origin.y + displayframe.size.height / 2;
|
||||
|
@ -2292,6 +2319,7 @@ Cocoa_DestroyWindow(_THIS, SDL_Window * window)
|
|||
SDL_WindowData *data = (SDL_WindowData *) CFBridgingRelease(window->driverdata);
|
||||
|
||||
if (data) {
|
||||
NSArray *contexts;
|
||||
if ([data.listener isInFullscreenSpace]) {
|
||||
[NSMenu setMenuBarVisible:YES];
|
||||
}
|
||||
|
@ -2303,7 +2331,7 @@ Cocoa_DestroyWindow(_THIS, SDL_Window * window)
|
|||
[data.nswindow close];
|
||||
}
|
||||
|
||||
NSArray *contexts = [data.nscontexts copy];
|
||||
contexts = [data.nscontexts copy];
|
||||
for (SDLOpenGLContext *context in contexts) {
|
||||
/* Calling setWindow:NULL causes the context to remove itself from the context list. */
|
||||
[context setWindow:NULL];
|
||||
|
|
Loading…
Reference in New Issue