|
3 | 3 | // found in the LICENSE file. |
4 | 4 |
|
5 | 5 | #import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterApplication.h" |
6 | | -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterApplication_Internal.h" |
7 | 6 |
|
8 | | -#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterAppDelegate.h" |
9 | | -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterAppDelegate_Internal.h" |
10 | | -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h" |
11 | | -#include "flutter/shell/platform/embedder/embedder.h" |
12 | | - |
13 | | -// An NSApplication subclass that implements overrides necessary for some |
14 | | -// Flutter features, like application lifecycle handling. |
15 | 7 | @implementation FlutterApplication |
16 | | - |
17 | | -// Initialize NSApplication using the custom subclass. Check whether NSApp was |
18 | | -// already initialized using another class, because that would break some |
19 | | -// things. Warn about the mismatch only once, and only in debug builds. |
20 | | -+ (NSApplication*)sharedApplication { |
21 | | - NSApplication* app = [super sharedApplication]; |
22 | | - |
23 | | - // +sharedApplication initializes the global NSApp, so if we're delivering |
24 | | - // something other than a FlutterApplication, warn the developer once. |
25 | | -#ifndef FLUTTER_RELEASE |
26 | | - static dispatch_once_t onceToken = 0; |
27 | | - dispatch_once(&onceToken, ^{ |
28 | | - if (![app respondsToSelector:@selector(terminateApplication:)]) { |
29 | | - NSLog(@"NSApp should be of type %s, not %s.\n" |
30 | | - "System requests for the application to terminate will not be sent to " |
31 | | - "the Flutter framework, so the framework will be unable to cancel " |
32 | | - "those requests.\n" |
33 | | - "Modify the application's NSPrincipleClass to be %s in the " |
34 | | - "Info.plist to fix this.", |
35 | | - [[self className] UTF8String], [[NSApp className] UTF8String], |
36 | | - [[self className] UTF8String]); |
37 | | - } |
38 | | - }); |
39 | | -#endif // !FLUTTER_RELEASE |
40 | | - return app; |
41 | | -} |
42 | | - |
43 | | -// |terminate| is the entry point for orderly "quit" operations in Cocoa. This |
44 | | -// includes the application menu's Quit menu item and keyboard equivalent, the |
45 | | -// application's dock icon menu's Quit menu item, "quit" (not "force quit") in |
46 | | -// the Activity Monitor, and quits triggered by user logout and system restart |
47 | | -// and shutdown. |
48 | | -// |
49 | | -// We override the normal |terminate| implementation. Our implementation, which |
50 | | -// is specific to the asynchronous nature of Flutter, works by asking the |
51 | | -// application delegate to terminate using its |requestApplicationTermination| |
52 | | -// method instead of going through |applicationShouldTerminate|. |
53 | | -// |
54 | | -// The standard |applicationShouldTerminate| is not used because returning |
55 | | -// NSTerminateLater from that function moves the run loop into a modal dialog |
56 | | -// mode (NSModalPanelRunLoopMode), which stops the main run loop from processing |
57 | | -// messages like, for instance, the response to the method channel call, and |
58 | | -// code paths leading to it must be redirected to |requestApplicationTermination|. |
59 | | -// |
60 | | -// |requestApplicationTermination| differs from the standard |
61 | | -// |applicationShouldTerminate| in that no special event loop is run in the case |
62 | | -// that immediate termination is not possible (e.g., if dialog boxes allowing |
63 | | -// the user to cancel have to be shown, or data needs to be saved). Instead, |
64 | | -// requestApplicationTermination sends a method channel call to the framework asking |
65 | | -// it if it is OK to terminate. When that method channel call returns with a |
66 | | -// result, the application either terminates or continues running. |
67 | | -- (void)terminate:(id)sender { |
68 | | - FlutterAppDelegate* delegate = [self delegate]; |
69 | | - if (!delegate || ![delegate respondsToSelector:@selector(terminationHandler)] || |
70 | | - [delegate terminationHandler] == nil) { |
71 | | - // If there's no termination handler, then just terminate. |
72 | | - [super terminate:sender]; |
73 | | - } |
74 | | - FlutterEngineTerminationHandler* terminationHandler = |
75 | | - [static_cast<FlutterAppDelegate*>([self delegate]) terminationHandler]; |
76 | | - [terminationHandler requestApplicationTermination:sender |
77 | | - exitType:kFlutterAppExitTypeCancelable |
78 | | - result:nil]; |
79 | | - // Return, don't exit. The application delegate is responsible for exiting on |
80 | | - // its own by calling |terminateApplication|. |
81 | | -} |
82 | | - |
83 | | -// Starts the regular Cocoa application termination flow, so that plugins will |
84 | | -// get the appropriate notifications after the application has already decided |
85 | | -// to quit. This is called after the application has decided that |
86 | | -// it's OK to terminate. |
87 | | -- (void)terminateApplication:(id)sender { |
88 | | - [super terminate:sender]; |
89 | | -} |
90 | 8 | @end |
0 commit comments