[macOS] Improve file association handling, and allow URL schema handling.
This commit is contained in:
parent
8ec6c075bd
commit
238ac2fdd5
7 changed files with 63 additions and 34 deletions
|
@ -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; }
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
- (void)forceUnbundledWindowActivationHackStep1;
|
||||
- (void)forceUnbundledWindowActivationHackStep2;
|
||||
- (void)forceUnbundledWindowActivationHackStep3;
|
||||
- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
|
||||
@end
|
||||
|
||||
#endif // GODOT_APPLICATION_DELEGATE_H
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue