Skip to content

Commit d9eff11

Browse files
committed
Too much for one commit 🤷🏻‍♂️
Add support for Electron apps Change menu injection logic to not replace custom dock menus in some apps like Terminal
1 parent b7a8de7 commit d9eff11

3 files changed

Lines changed: 42 additions & 32 deletions

File tree

AfloatX.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@
307307
CLANG_ENABLE_OBJC_ARC = YES;
308308
CODE_SIGN_STYLE = Automatic;
309309
COMBINE_HIDPI_IMAGES = YES;
310-
CURRENT_PROJECT_VERSION = 1.3.1;
310+
CURRENT_PROJECT_VERSION = 1.3.4;
311311
DEPLOYMENT_LOCATION = YES;
312312
DEVELOPMENT_TEAM = 6LAE5ASX7M;
313313
DSTROOT = /;
@@ -318,7 +318,7 @@
318318
INSTALL_PATH = "/Library/Application Support/MacEnhance/Plugins";
319319
MACH_O_TYPE = mh_dylib;
320320
MACOSX_DEPLOYMENT_TARGET = 10.12;
321-
MARKETING_VERSION = 1.3.1;
321+
MARKETING_VERSION = 1.3.4;
322322
PRODUCT_BUNDLE_IDENTIFIER = com.github.jslegendre.AfloatX;
323323
PRODUCT_NAME = "$(TARGET_NAME)";
324324
WRAPPER_EXTENSION = bundle;
@@ -331,7 +331,7 @@
331331
CLANG_ENABLE_OBJC_ARC = YES;
332332
CODE_SIGN_STYLE = Automatic;
333333
COMBINE_HIDPI_IMAGES = YES;
334-
CURRENT_PROJECT_VERSION = 1.3.1;
334+
CURRENT_PROJECT_VERSION = 1.3.4;
335335
DEPLOYMENT_LOCATION = YES;
336336
DEVELOPMENT_TEAM = 6LAE5ASX7M;
337337
DSTROOT = /;
@@ -342,7 +342,7 @@
342342
INSTALL_PATH = "/Library/Application Support/MacEnhance/Plugins";
343343
MACH_O_TYPE = mh_dylib;
344344
MACOSX_DEPLOYMENT_TARGET = 10.12;
345-
MARKETING_VERSION = 1.3.1;
345+
MARKETING_VERSION = 1.3.4;
346346
PRODUCT_BUNDLE_IDENTIFIER = com.github.jslegendre.AfloatX;
347347
PRODUCT_NAME = "$(TARGET_NAME)";
348348
WRAPPER_EXTENSION = bundle;

AfloatX/AfloatX.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,3 @@
1111
@interface AfloatX : NSObject
1212
+ (instancetype)sharedInstance;
1313
@end
14-
15-
@interface AXAppDelegate : NSObject <NSApplicationDelegate>
16-
@end

AfloatX/AfloatX.m

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#import <objc/runtime.h>
1616
#import <objc/message.h>
1717

18+
static dispatch_once_t injectMenuOnceToken;
19+
1820
WindowTransparencyController *transparencyController;
1921
NSMenu *AfloatXMenu;
2022
NSMenuItem *AfloatXItem;
@@ -30,7 +32,6 @@
3032
NSMenu *windowOutlineSubmenu;
3133
NSArray *afloatXItems;
3234
CIFilter* colorInvertFilter;
33-
BOOL menuInjected;
3435

3536
@interface AfloatX()
3637

@@ -165,9 +166,7 @@ + (void)load {
165166

166167
colorInvertFilter = [CIFilter filterWithName:@"CIColorInvert"];
167168
[colorInvertFilter setDefaults];
168-
169-
menuInjected = NO;
170-
169+
171170
transparencyController = [WindowTransparencyController sharedInstance];
172171

173172
AfloatXMenu = [NSMenu new];
@@ -212,57 +211,71 @@ + (void)load {
212211
transparencyItem,
213212
nil];
214213
[AfloatXSubmenu setItemArray:afloatXItems];
215-
216-
// If the application has a custom dock menu, we will add ourselves to that
217-
if([[NSApp delegate] respondsToSelector:@selector(applicationDockMenu:)]) {
218-
AfloatXMenu = [[NSApp delegate] applicationDockMenu:NSApp];
219-
[AfloatXMenu addItem:[NSMenuItem separatorItem]];
220-
menuInjected = YES;
214+
215+
// Are we in an Electron app?
216+
if(objc_lookUpClass("AtomApplicationDelegate")) {
217+
dispatch_once(&injectMenuOnceToken, ^{ /* Use up token */ });
218+
[AfloatXMenu addItem:AfloatXItem];
221219
}
222-
223-
[AfloatXMenu addItem:AfloatXItem];
224-
_ZKSwizzle([AXAppDelegate class], [[NSApp delegate] class]);
225220
}
226221

227222
@end
228223

224+
/*
225+
AtomApplicationDelegate is the application delegate class
226+
for all Electron apps. In order for AfloatX to work we must
227+
explicitly swizzle this class because the application delegate
228+
class gets subclassed/swizzled to this one after injection.
229+
*/
230+
ZKSwizzleInterface(AXAppDelegate, AtomApplicationDelegate, NSObject)
229231
@implementation AXAppDelegate
230232
- (NSMenu *)applicationDockMenu:(NSApplication *)sender {
231-
if (menuInjected) {
233+
NSMenu *originalMenu = ZKOrig(NSMenu*, sender);
234+
if(originalMenu) {
232235
[AfloatXMenu removeItem:AfloatXItem];
233-
AfloatXMenu = ZKOrig(NSMenu*, sender);
236+
AfloatXMenu = originalMenu;
234237
// Only add a separator if last item isn't already a separator
235238
if (!AfloatXMenu.itemArray.lastObject.isSeparatorItem)
236239
[AfloatXMenu addItem:[NSMenuItem separatorItem]];
237240
[AfloatXMenu addItem:AfloatXItem];
238241
}
242+
239243
return AfloatXMenu;
240244
}
241245
@end
242246

243247
ZKSwizzleInterface(AXApplication, NSApplication, NSResponder)
244248
@implementation AXApplication
245-
- (CFArrayRef)_flattenMenu:(NSMenu *)arg1 flatList:(NSArray *)arg2 {
249+
- (CFArrayRef)_flattenMenu:(NSMenu *)dockMenu flatList:(NSArray *)flatList {
250+
251+
// Add AfloatX to the dock menu
252+
dispatch_once(&injectMenuOnceToken, ^{
253+
if (!dockMenu.itemArray.lastObject.isSeparatorItem)
254+
[dockMenu addItem:[NSMenuItem separatorItem]];
255+
256+
[dockMenu addItem:AfloatXItem];
257+
});
258+
246259
// Make any necessary changes to our menu before it is 'flattened'
247260
NSWindow *window = [AXWindowUtils windowToModify];
248261
if(!window) {
249262
AfloatXItem.enabled = NO;
250-
return ZKOrig(CFArrayRef, arg1, arg2);
263+
return ZKOrig(CFArrayRef, dockMenu, flatList);
251264
}
252-
265+
253266
AfloatXItem.enabled = YES;
254267
if([[AfloatX sharedInstance] isWindowTransient:window]) {
255268
[transientItem setState:NSControlStateValueOn];
256269
} else {
257270
[transientItem setState:NSControlStateValueOff];
258271
}
259-
272+
260273
if([[AfloatX sharedInstance] isWindowSticky:window]) {
261274
[stickyItem setState:NSControlStateValueOn];
262275
} else {
263276
[stickyItem setState:NSControlStateValueOff];
264277
}
265-
278+
266279
CGWindowLevel windowLevel = [AXWindowUtils getCGWindowLevelForWindow:window];
267280
if(windowLevel != kCGNormalWindowLevel) {
268281
if(windowLevel == kCGBackstopMenuLevel) {
@@ -276,13 +289,13 @@ - (CFArrayRef)_flattenMenu:(NSMenu *)arg1 flatList:(NSArray *)arg2 {
276289
[dropItem setState:NSControlStateValueOff];
277290
[floatItem setState:NSControlStateValueOff];
278291
}
279-
292+
280293
if([AXWindowUtils window:window hasLowTag:CGSTagTransparent]) {
281294
[clickPassthroughItem setState:NSControlStateValueOn];
282295
} else {
283296
[clickPassthroughItem setState:NSControlStateValueOff];
284297
}
285-
298+
286299
/* Create a new WindowOutliningController per window */
287300
if (!objc_getAssociatedObject(window, "outlineController")) {
288301
WindowOutliningController *outlineController = [WindowOutliningController new];
@@ -292,13 +305,13 @@ - (CFArrayRef)_flattenMenu:(NSMenu *)arg1 flatList:(NSArray *)arg2 {
292305
WindowOutliningController *outlineController = objc_getAssociatedObject(window, "outlineController");
293306
windowOutlineSubmenu.itemArray = [outlineController colorItems];
294307
}
295-
308+
296309
if ([objc_getAssociatedObject(window, "isColorInverted") boolValue]) {
297310
[invertColorItem setState:NSControlStateValueOn];
298311
} else {
299312
[invertColorItem setState:NSControlStateValueOff];
300313
}
301-
302-
return ZKOrig(CFArrayRef, arg1, arg2);
314+
315+
return ZKOrig(CFArrayRef, dockMenu, flatList);
303316
}
304317
@end

0 commit comments

Comments
 (0)