-
Notifications
You must be signed in to change notification settings - Fork 6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add platform channel
System.exitApplication
and `System.requestAppE…
…xit` support (#39836) Add platform channel `System.exitApplication` and `System.requestAppExit` support
- Loading branch information
1 parent
706fd9c
commit 55b6631
Showing
15 changed files
with
470 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
shell/platform/darwin/macos/framework/Headers/FlutterApplication.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef FLUTTER_FLUTTERAPPLICATION_H_ | ||
#define FLUTTER_FLUTTERAPPLICATION_H_ | ||
|
||
#import <Cocoa/Cocoa.h> | ||
|
||
/** | ||
* A Flutter-specific subclass of NSApplication that overrides |terminate| and | ||
* provides an additional |terminateApplication| method so that Flutter can | ||
* handle requests for termination in an asynchronous fashion. | ||
* | ||
* When a call to |terminate| comes in, either from the OS through a Quit menu | ||
* item, through the Quit item in the dock context menu, or from the application | ||
* itself, a request is sent to the Flutter framework. If that request is | ||
* granted, this subclass will (in |terminateApplication|) call | ||
* |NSApplication|'s version of |terminate| to proceed with terminating the | ||
* application normally by calling |applicationShouldTerminate|, etc. | ||
* | ||
* If the termination request is denied by the framework, then the application | ||
* will continue to execute normally, as if no |terminate| call were made. | ||
* | ||
* The |FlutterAppDelegate| always returns |NSTerminateNow| from | ||
* |applicationShouldTerminate|, since it has already decided by that point that | ||
* it should terminate. | ||
* | ||
* In order for this class to be used in place of |NSApplication|, the | ||
* "NSPrincipalClass" entry in the Info.plist for the application must be set to | ||
* "FlutterApplication". If it is not, then the application will not be given | ||
* the chance to deny a termination request, and calls to requestAppExit on the | ||
* engine (from the framework, typically) will simply exit the application | ||
* without ceremony. | ||
* | ||
* If the |NSApp| global isn't of type |FlutterApplication|, a log message will | ||
* be printed once in debug mode when the application is first accessed through | ||
* the singleton's |sharedApplication|, describing how to fix this. | ||
* | ||
* Flutter applications are *not* required to inherit from this class. | ||
* Developers of custom |NSApplication| subclasses should copy and paste code as | ||
* necessary from FlutterApplication.mm. | ||
*/ | ||
@interface FlutterApplication : NSApplication | ||
@end | ||
|
||
#endif // FLUTTER_FLUTTERAPPLICATION_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
shell/platform/darwin/macos/framework/Source/FlutterAppDelegate_Internal.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef FLUTTER_FLUTTERAPPDELEGATE_INTERNAL_H_ | ||
#define FLUTTER_FLUTTERAPPDELEGATE_INTERNAL_H_ | ||
|
||
#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterAppDelegate.h" | ||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h" | ||
|
||
@interface FlutterAppDelegate () | ||
|
||
/** | ||
* Holds a weak reference to the termination handler owned by the engine. | ||
* Called by the |FlutterApplication| when termination is requested by the OS. | ||
*/ | ||
@property(readwrite, nullable, weak) FlutterEngineTerminationHandler* terminationHandler; | ||
|
||
@end | ||
|
||
#endif // FLUTTER_FLUTTERAPPDELEGATE_INTERNAL_H_ |
90 changes: 90 additions & 0 deletions
90
shell/platform/darwin/macos/framework/Source/FlutterApplication.mm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterApplication.h" | ||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterApplication_Internal.h" | ||
|
||
#include "flutter/shell/platform/embedder/embedder.h" | ||
#import "shell/platform/darwin/macos/framework/Headers/FlutterAppDelegate.h" | ||
#import "shell/platform/darwin/macos/framework/Source/FlutterAppDelegate_Internal.h" | ||
#import "shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h" | ||
|
||
// An NSApplication subclass that implements overrides necessary for some | ||
// Flutter features, like application lifecycle handling. | ||
@implementation FlutterApplication | ||
|
||
// Initialize NSApplication using the custom subclass. Check whether NSApp was | ||
// already initialized using another class, because that would break some | ||
// things. Warn about the mismatch only once, and only in debug builds. | ||
+ (NSApplication*)sharedApplication { | ||
NSApplication* app = [super sharedApplication]; | ||
|
||
// +sharedApplication initializes the global NSApp, so if we're delivering | ||
// something other than a FlutterApplication, warn the developer once. | ||
#ifndef FLUTTER_RELEASE | ||
static dispatch_once_t onceToken = 0; | ||
dispatch_once(&onceToken, ^{ | ||
if (![app respondsToSelector:@selector(terminateApplication:)]) { | ||
NSLog(@"NSApp should be of type %s, not %s.\n" | ||
"System requests for the application to terminate will not be sent to " | ||
"the Flutter framework, so the framework will be unable to cancel " | ||
"those requests.\n" | ||
"Modify the application's NSPrincipleClass to be %s in the " | ||
"Info.plist to fix this.", | ||
[[self className] UTF8String], [[NSApp className] UTF8String], | ||
[[self className] UTF8String]); | ||
} | ||
}); | ||
#endif // !FLUTTER_RELEASE | ||
return app; | ||
} | ||
|
||
// |terminate| is the entry point for orderly "quit" operations in Cocoa. This | ||
// includes the application menu's Quit menu item and keyboard equivalent, the | ||
// application's dock icon menu's Quit menu item, "quit" (not "force quit") in | ||
// the Activity Monitor, and quits triggered by user logout and system restart | ||
// and shutdown. | ||
// | ||
// We override the normal |terminate| implementation. Our implementation, which | ||
// is specific to the asynchronous nature of Flutter, works by asking the | ||
// application delegate to terminate using its |requestApplicationTermination| | ||
// method instead of going through |applicationShouldTerminate|. | ||
// | ||
// The standard |applicationShouldTerminate| is not used because returning | ||
// NSTerminateLater from that function moves the run loop into a modal dialog | ||
// mode (NSModalPanelRunLoopMode), which stops the main run loop from processing | ||
// messages like, for instance, the response to the method channel call, and | ||
// code paths leading to it must be redirected to |requestApplicationTermination|. | ||
// | ||
// |requestApplicationTermination| differs from the standard | ||
// |applicationShouldTerminate| in that no special event loop is run in the case | ||
// that immediate termination is not possible (e.g., if dialog boxes allowing | ||
// the user to cancel have to be shown, or data needs to be saved). Instead, | ||
// requestApplicationTermination sends a method channel call to the framework asking | ||
// it if it is OK to terminate. When that method channel call returns with a | ||
// result, the application either terminates or continues running. | ||
- (void)terminate:(id)sender { | ||
FlutterAppDelegate* delegate = [self delegate]; | ||
if (!delegate || ![delegate respondsToSelector:@selector(terminationHandler)] || | ||
[delegate terminationHandler] == nil) { | ||
// If there's no termination handler, then just terminate. | ||
[super terminate:sender]; | ||
} | ||
FlutterEngineTerminationHandler* terminationHandler = | ||
[static_cast<FlutterAppDelegate*>([self delegate]) terminationHandler]; | ||
[terminationHandler requestApplicationTermination:sender | ||
exitType:kFlutterAppExitTypeCancelable | ||
result:nil]; | ||
// Return, don't exit. The application delegate is responsible for exiting on | ||
// its own by calling |terminateApplication|. | ||
} | ||
|
||
// Starts the regular Cocoa application termination flow, so that plugins will | ||
// get the appropriate notifications after the application has already decided | ||
// to quit. This is called after the application has decided that | ||
// it's OK to terminate. | ||
- (void)terminateApplication:(id)sender { | ||
[super terminate:sender]; | ||
} | ||
@end |
27 changes: 27 additions & 0 deletions
27
shell/platform/darwin/macos/framework/Source/FlutterApplication_Internal.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef FLUTTER_FLUTTERAPPLICATION_INTERNAL_H_ | ||
#define FLUTTER_FLUTTERAPPLICATION_INTERNAL_H_ | ||
|
||
#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterApplication.h" | ||
|
||
/** | ||
* Define |terminateApplication| for internal use. | ||
*/ | ||
@interface FlutterApplication () | ||
|
||
/** | ||
* FlutterApplication's implementation of |terminate| doesn't terminate the | ||
* application: that is left up to the engine, which will call this function if | ||
* it decides that termination request is granted, which will start the regular | ||
* Cocoa flow for terminating the application, calling | ||
* |applicationShouldTerminate|, etc. | ||
* | ||
* @param(sender) The id of the object requesting the termination, or nil. | ||
*/ | ||
- (void)terminateApplication:(id)sender; | ||
@end | ||
|
||
#endif // FLUTTER_FLUTTERAPPLICATION_INTERNAL_H_ |
Oops, something went wrong.