Flutter macOS Embedder
FlutterAppLifecycleDelegate.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
7 
8 #include <AppKit/AppKit.h>
9 #include <AppKit/NSApplication.h>
10 #include <Foundation/Foundation.h>
11 #include <objc/message.h>
12 
13 #include "flutter/fml/logging.h"
14 #include "flutter/fml/paths.h"
15 
16 @implementation FlutterAppLifecycleRegistrar {
17  NSMutableArray* _notificationUnsubscribers;
18 }
19 
20 - (void)addObserverFor:(NSString*)name selector:(SEL)selector {
21  [[NSNotificationCenter defaultCenter] addObserver:self selector:selector name:name object:nil];
22  __block NSObject* blockSelf = self;
23  dispatch_block_t unsubscribe = ^{
24  [[NSNotificationCenter defaultCenter] removeObserver:blockSelf name:name object:nil];
25  };
26  [_notificationUnsubscribers addObject:[unsubscribe copy]];
27 }
28 
29 - (instancetype)init {
30  if (self = [super init]) {
31  _notificationUnsubscribers = [[NSMutableArray alloc] init];
32 
33 // Using a macro to avoid errors where the notification doesn't match the
34 // selector.
35 #ifdef OBSERVE_NOTIFICATION
36 #error OBSERVE_NOTIFICATION ALREADY DEFINED!
37 #else
38 #define OBSERVE_NOTIFICATION(SELECTOR) \
39  [self addObserverFor:NSApplication##SELECTOR##Notification selector:@selector(handle##SELECTOR:)]
40 #endif
41 
42  OBSERVE_NOTIFICATION(WillFinishLaunching);
43  OBSERVE_NOTIFICATION(DidFinishLaunching);
44  OBSERVE_NOTIFICATION(WillBecomeActive);
45  OBSERVE_NOTIFICATION(DidBecomeActive);
46  OBSERVE_NOTIFICATION(WillResignActive);
47  OBSERVE_NOTIFICATION(DidResignActive);
48  OBSERVE_NOTIFICATION(WillTerminate);
49  OBSERVE_NOTIFICATION(WillHide);
50  OBSERVE_NOTIFICATION(DidHide);
51  OBSERVE_NOTIFICATION(WillUnhide);
52  OBSERVE_NOTIFICATION(DidUnhide);
53  OBSERVE_NOTIFICATION(DidChangeScreenParameters);
54  OBSERVE_NOTIFICATION(DidChangeOcclusionState);
55 
56 #undef OBSERVE_NOTIFICATION
57 
58  _delegates = [NSPointerArray weakObjectsPointerArray];
59  }
60  return self;
61 }
62 
63 - (void)dealloc {
64  for (dispatch_block_t unsubscribe in _notificationUnsubscribers) {
65  unsubscribe();
66  }
67  [_notificationUnsubscribers removeAllObjects];
68  _delegates = nil;
69  _notificationUnsubscribers = nil;
70 }
71 
72 static BOOL IsPowerOfTwo(NSUInteger x) {
73  return x != 0 && (x & (x - 1)) == 0;
74 }
75 
76 - (void)addDelegate:(NSObject<FlutterAppLifecycleDelegate>*)delegate {
77  [_delegates addPointer:(__bridge void*)delegate];
78  if (IsPowerOfTwo([_delegates count])) {
79  [_delegates compact];
80  }
81 }
82 
83 - (void)removeDelegate:(NSObject<FlutterAppLifecycleDelegate>*)delegate {
84  NSUInteger index = [[_delegates allObjects] indexOfObject:delegate];
85  if (index != NSNotFound) {
86  [_delegates removePointerAtIndex:index];
87  }
88 }
89 
90 // This isn't done via performSelector because that can cause leaks due to the
91 // selector not being known. Using a macro to avoid mismatch errors between the
92 // notification and the selector.
93 #ifdef DISTRIBUTE_NOTIFICATION
94 #error DISTRIBUTE_NOTIFICATION ALREADY DEFINED!
95 #else
96 #define DISTRIBUTE_NOTIFICATION(SELECTOR) \
97  -(void)handle##SELECTOR : (NSNotification*)notification { \
98  for (NSObject<FlutterAppLifecycleDelegate> * delegate in _delegates) { \
99  if ([delegate respondsToSelector:@selector(handle##SELECTOR:)]) { \
100  [delegate handle##SELECTOR:notification]; \
101  } \
102  } \
103  }
104 #endif
105 
106 DISTRIBUTE_NOTIFICATION(WillFinishLaunching)
107 DISTRIBUTE_NOTIFICATION(DidFinishLaunching)
108 DISTRIBUTE_NOTIFICATION(WillBecomeActive)
109 DISTRIBUTE_NOTIFICATION(DidBecomeActive)
110 DISTRIBUTE_NOTIFICATION(WillResignActive)
111 DISTRIBUTE_NOTIFICATION(DidResignActive)
112 DISTRIBUTE_NOTIFICATION(WillTerminate)
113 DISTRIBUTE_NOTIFICATION(WillHide)
114 DISTRIBUTE_NOTIFICATION(WillUnhide)
116 DISTRIBUTE_NOTIFICATION(DidUnhide)
117 DISTRIBUTE_NOTIFICATION(DidChangeScreenParameters)
118 DISTRIBUTE_NOTIFICATION(DidChangeOcclusionState)
119 
120 #undef DISTRIBUTE_NOTIFICATION
121 
122 @end
FlutterAppLifecycleRegistrar
Definition: FlutterAppLifecycleDelegate.h:126
DISTRIBUTE_NOTIFICATION
#define DISTRIBUTE_NOTIFICATION(SELECTOR)
Definition: FlutterAppLifecycleDelegate.mm:96
FlutterAppLifecycleDelegate-p
Definition: FlutterAppLifecycleDelegate.h:21
FlutterAppLifecycleDelegate_Internal.h
OBSERVE_NOTIFICATION
#define OBSERVE_NOTIFICATION(SELECTOR)
FlutterAppLifecycleDelegate.h