Skip to content

Commit

Permalink
Fix macOS client/server failing to start from terminal
Browse files Browse the repository at this point in the history
The macOS client and server were completely unusable when run from a
terminal. They blocked forever in `[NSApp run];` which was called by
Sys_InitProtocolHandler(). `applicationDidFinishLaunching` was never
called to exit the NSApp run loop.

Use SDL's SDL_DROPFILE event to receive URLs to handle on macOS instead.
This also handles URLs while the game is running (connect to new server)
instead of nothing happening when clicking a link while the game is
running.
  • Loading branch information
zturtleman committed Jun 11, 2023
1 parent 8b6333f commit e452b7a
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 64 deletions.
26 changes: 26 additions & 0 deletions code/sdl/sdl_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,28 @@ static void IN_ProcessEvents( void )
}
break;

#if defined(PROTOCOL_HANDLER) && defined(__APPLE__)
case SDL_DROPFILE:
{
char *filename = e.drop.file;

// Handle macOS open URL event. URL protocol scheme must be set in Info.plist.
if( !Q_strncmp( filename, PROTOCOL_HANDLER ":", strlen( PROTOCOL_HANDLER ":" ) ) )
{
char *protocolCommand = Sys_ParseProtocolUri( filename );

if( protocolCommand )
{
Cbuf_ExecuteText( EXEC_APPEND, va( "%s\n", protocolCommand ) );
free( protocolCommand );
}
}

SDL_free( filename );
}
break;
#endif

default:
break;
}
Expand Down Expand Up @@ -1250,6 +1272,10 @@ void IN_Init( void *windowData )
in_joystick = Cvar_Get( "in_joystick", "0", CVAR_ARCHIVE|CVAR_LATCH );
in_joystickThreshold = Cvar_Get( "joy_threshold", "0.15", CVAR_ARCHIVE );

#if defined(PROTOCOL_HANDLER) && defined(__APPLE__)
SDL_EventState( SDL_DROPFILE, SDL_ENABLE );
#endif

SDL_StartTextInput( );

mouseAvailable = ( in_mouse->value != 0 );
Expand Down
1 change: 0 additions & 1 deletion code/sys/sys_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,5 @@ int Sys_PID( void );
qboolean Sys_PIDIsRunning( int pid );

#ifdef PROTOCOL_HANDLER
char *Sys_InitProtocolHandler( void );
char *Sys_ParseProtocolUri( const char *uri );
#endif
23 changes: 3 additions & 20 deletions code/sys/sys_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -643,20 +643,6 @@ void Sys_ParseArgs( int argc, char **argv )
}

#ifdef PROTOCOL_HANDLER
/*
=================
Sys_InitProtocolHandler
See sys_osx.m for macOS implementation.
=================
*/
#ifndef __APPLE__
char *Sys_InitProtocolHandler( void )
{
return NULL;
}
#endif

/*
=================
Sys_ParseProtocolUri
Expand Down Expand Up @@ -716,9 +702,9 @@ char *Sys_ParseProtocolUri( const char *uri )
}
}

bufsize = strlen( "+connect " ) + i + 1;
bufsize = strlen( "connect " ) + i + 1;
out = malloc( bufsize );
strcpy( out, "+connect " );
strcpy( out, "connect " );
strncat( out, uri, i );
return out;
}
Expand Down Expand Up @@ -815,10 +801,6 @@ int main( int argc, char **argv )

Sys_PlatformInit( );

#ifdef PROTOCOL_HANDLER
protocolCommand = Sys_InitProtocolHandler( );
#endif

// Set the initial time base
Sys_Milliseconds( );

Expand Down Expand Up @@ -865,6 +847,7 @@ int main( int argc, char **argv )
#ifdef PROTOCOL_HANDLER
if ( protocolCommand != NULL )
{
Q_strcat( commandLine, sizeof( commandLine ), "+" );
Q_strcat( commandLine, sizeof( commandLine ), protocolCommand );
free( protocolCommand );
}
Expand Down
43 changes: 0 additions & 43 deletions code/sys/sys_osx.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>

#ifdef PROTOCOL_HANDLER
char *protocolCommand = NULL;
#endif

/*
==============
Sys_Dialog
Expand Down Expand Up @@ -119,42 +115,3 @@ dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *t
Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd));
return cwd;
}

#ifdef PROTOCOL_HANDLER

@interface AppDelegate : NSObject <NSApplicationDelegate>
@end

@implementation AppDelegate

- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
NSString *input = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
protocolCommand = Sys_ParseProtocolUri( input.UTF8String );
}

- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
[NSApp stop:nil];
}

@end

char *Sys_InitProtocolHandler( void )
{
[NSApplication sharedApplication];

AppDelegate *appDelegate = [AppDelegate new];
NSAppleEventManager *sharedAppleEventManager = [NSAppleEventManager new];
[sharedAppleEventManager setEventHandler:appDelegate
andSelector:@selector(handleAppleEvent:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];

[NSApp setDelegate:appDelegate];
[NSApp run];

return protocolCommand;
}

#endif

0 comments on commit e452b7a

Please sign in to comment.