Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix NSApplication initialization to prevent some issues on macOS #131

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion os/osx/app.mm
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,25 @@ void setAppMode(AppMode appMode)

void finishLaunching()
{
[m_app finishLaunching];
id runningApp = [NSRunningApplication currentApplication];
// [m_app run] must be called once, if the app didn't finish launching yet.
if (![runningApp isFinishedLaunching]) {
// The run method must be called in GUI mode only, otherwise the
// [AppDelegateOSX applicationDidFinishLaunching] doesn't get called
// and [m_app run] ends up blocking the app.
if ([runningApp activationPolicy] == NSApplicationActivationPolicyRegular) {
// Note that the [m_app run] call doesn't block because we are calling
// [NSApp stop] from [AppDelegateOSX applicationDidFinishLaunching]. We only
// need the application's initialization done inside run to prevent issues
// such as: https://github.com/aseprite/aseprite/issues/4795
[m_app run];
}
else {
// The app is running in CLI mode, then we just call finishLaunching.
[m_app finishLaunching];
}
}

[m_appDelegate resetCliFiles];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we put this line under the scope of the if clause as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just in case, we should test if dropping files to the app icon in the dock works. Probably it should be tested with the final Aseprite.app bundle, not only the bin/aseprite binary. I could give a try next week.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested with the binary with and without this fix, and it doesn't work either way. So it seems that we can only test this with the final bundle?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just kind of tested this by vandalizing a v1.3.12 bundle (replaced the release binary with a compiled one 😬) and it worked...not sure if it will work by creating the bundle, but seems like it.

}

Expand Down
1 change: 1 addition & 0 deletions os/osx/app_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)app;
- (void)applicationWillTerminate:(NSNotification*)notification;
- (void)applicationWillResignActive:(NSNotification*)notification;
- (void)applicationDidFinishLaunching:(NSNotification*)notification;
- (void)applicationDidBecomeActive:(NSNotification*)notification;
- (void)applicationDidHide:(NSNotification*)notification;
- (void)applicationDidUnhide:(NSNotification*)notification;
Expand Down
7 changes: 7 additions & 0 deletions os/osx/app_delegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ - (void)applicationWillResignActive:(NSNotification*)notification
[ViewOSX updateKeyFlags:event];
}

- (void)applicationDidFinishLaunching:(NSNotification*)notification
{
// We do not want that the [NSApplication run] call made from
// AppOSX::Impl::finishLaunching() blocks.
[NSApp stop:nil];
}

- (void)applicationDidBecomeActive:(NSNotification*)notification
{
for (id window : [NSApp windows]) {
Expand Down
17 changes: 9 additions & 8 deletions os/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,16 @@ class System : public RefCount {
// files that were processed from the CLI arguments directly.
virtual void markCliFileAsProcessed(const std::string& cliFile) = 0;

// On macOS it calls [NSApplication finishLaunching] that will
// produce some extra events like [NSApplicationDelegate
// application:openFiles:] which generates os::Event::DropFiles
// events for each file specified in the command line.
// On macOS it calls [NSApplication run], which in turn does two things:
// - It calls [NSApplication finishLaunching], which will produce some extra
// events like [NSApplicationDelegate application:openFiles:] which generates
// os::Event::DropFiles events for each file specified in the command line.
// - It initializes internal state of the NSApplication instance to make it
// behave as expected under some circumstances.
//
// You can ignore those DropFiles events if you've already
// processed through the CLI arguments (app_main(argc, argv)) or
// you can use markCliFileAsProcessed() before calling this
// function.
// About the first point: you can ignore those DropFiles events if you've
// already processed through the CLI arguments (app_main(argc, argv)) or
// you can use markCliFileAsProcessed() before calling this function.
virtual void finishLaunching() = 0;

// We might need to call this function when the app is launched
Expand Down