[macOS] Improve file association handling, and allow URL schema handling.

This commit is contained in:
bruvzg 2022-07-07 10:57:22 +03:00
parent 8ec6c075bd
commit 238ac2fdd5
No known key found for this signature in database
GPG key ID: 7960FCF39844EC38
7 changed files with 63 additions and 34 deletions

View file

@ -160,6 +160,7 @@ public:
virtual String get_name() const = 0;
virtual List<String> get_cmdline_args() const { return _cmdline; }
virtual List<String> get_cmdline_platform_args() const { return List<String>(); }
virtual String get_model_name() const;
bool is_layered_allowed() const { return _allow_layered; }

View file

@ -621,11 +621,18 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
/* argument parsing and main creation */
List<String> args;
List<String> main_args;
List<String> platform_args = OS::get_singleton()->get_cmdline_platform_args();
// Add command line arguments.
for (int i = 0; i < argc; i++) {
args.push_back(String::utf8(argv[i]));
}
// Add arguments received from macOS LaunchService (URL schemas, file associations).
for (const String &arg : platform_args) {
args.push_back(arg);
}
List<String>::Element *I = args.front();
while (I) {

View file

@ -40,6 +40,7 @@
- (void)forceUnbundledWindowActivationHackStep1;
- (void)forceUnbundledWindowActivationHackStep2;
- (void)forceUnbundledWindowActivationHackStep3;
- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
@end
#endif // GODOT_APPLICATION_DELEGATE_H

View file

@ -67,6 +67,52 @@
}
}
- (id)init {
self = [super init];
NSAppleEventManager *aem = [NSAppleEventManager sharedAppleEventManager];
[aem setEventHandler:self andSelector:@selector(handleAppleEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
[aem setEventHandler:self andSelector:@selector(handleAppleEvent:withReplyEvent:) forEventClass:kCoreEventClass andEventID:kAEOpenDocuments];
return self;
}
- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
OS_OSX *os = (OS_OSX *)OS::get_singleton();
if (!event || !os) {
return;
}
List<String> args;
if (([event eventClass] == kInternetEventClass) && ([event eventID] == kAEGetURL)) {
// Opening URL scheme.
NSString *url = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
args.push_back(vformat("--uri=\"%s\"", String::utf8([url UTF8String])));
}
if (([event eventClass] == kCoreEventClass) && ([event eventID] == kAEOpenDocuments)) {
// Opening file association.
NSAppleEventDescriptor *files = [event paramDescriptorForKeyword:keyDirectObject];
if (files) {
NSInteger count = [files numberOfItems];
for (NSInteger i = 1; i <= count; i++) {
NSURL *url = [NSURL URLWithString:[[files descriptorAtIndex:i] stringValue]];
args.push_back(String::utf8([url.path UTF8String]));
}
}
}
if (!args.is_empty()) {
if (os->get_main_loop()) {
// Application is already running, open a new instance with the URL/files as command line arguments.
os->create_instance(args);
} else {
// Application is just started, add to the list of command line arguments and continue.
os->set_cmdline_platform_args(args);
}
}
}
- (void)applicationDidResignActive:(NSNotification *)notification {
DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
if (ds) {
@ -99,25 +145,6 @@
}
}
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
// Note: may be called called before main loop init!
OS_OSX *os = (OS_OSX *)OS::get_singleton();
if (os) {
os->set_open_with_filename(String::utf8([filename UTF8String]));
}
#ifdef TOOLS_ENABLED
// Open new instance.
if (os && os->get_main_loop()) {
List<String> args;
args.push_back(os->get_open_with_filename());
String exec = os->get_executable_path();
os->create_process(exec, args);
}
#endif
return YES;
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
if (ds) {

View file

@ -74,14 +74,7 @@ int main(int argc, char **argv) {
// We must override main when testing is enabled.
TEST_MAIN_OVERRIDE
if (os.get_open_with_filename() != "") {
char *argv_c = (char *)malloc(os.get_open_with_filename().utf8().size());
memcpy(argv_c, os.get_open_with_filename().utf8().get_data(), os.get_open_with_filename().utf8().size());
err = Main::setup(argv[0], 1, &argv_c);
free(argv_c);
} else {
err = Main::setup(argv[0], argc - first_arg, &argv[first_arg]);
}
err = Main::setup(argv[0], argc - first_arg, &argv[first_arg]);
if (err == ERR_HELP) { // Returned by --help and --version, so success.
return 0;

View file

@ -57,7 +57,7 @@ class OS_OSX : public OS_Unix {
MainLoop *main_loop = nullptr;
String open_with_filename;
List<String> launch_service_args;
static _FORCE_INLINE_ String get_framework_executable(const String &p_path);
static void pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context);
@ -73,8 +73,8 @@ protected:
virtual void delete_main_loop() override;
public:
String get_open_with_filename() const;
void set_open_with_filename(const String &p_path);
virtual void set_cmdline_platform_args(const List<String> &p_args);
virtual List<String> get_cmdline_platform_args() const override;
virtual String get_name() const override;

View file

@ -121,12 +121,12 @@ void OS_OSX::delete_main_loop() {
main_loop = nullptr;
}
String OS_OSX::get_open_with_filename() const {
return open_with_filename;
void OS_OSX::set_cmdline_platform_args(const List<String> &p_args) {
launch_service_args = p_args;
}
void OS_OSX::set_open_with_filename(const String &p_path) {
open_with_filename = p_path;
List<String> OS_OSX::get_cmdline_platform_args() const {
return launch_service_args;
}
String OS_OSX::get_name() const {