diff --git a/AfloatX.xcodeproj/project.pbxproj b/AfloatX.xcodeproj/project.pbxproj index 4f90bcf..c30a97b 100644 --- a/AfloatX.xcodeproj/project.pbxproj +++ b/AfloatX.xcodeproj/project.pbxproj @@ -307,7 +307,7 @@ CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1.3.1; + CURRENT_PROJECT_VERSION = 1.3.4; DEPLOYMENT_LOCATION = YES; DEVELOPMENT_TEAM = 6LAE5ASX7M; DSTROOT = /; @@ -318,7 +318,7 @@ INSTALL_PATH = "/Library/Application Support/MacEnhance/Plugins"; MACH_O_TYPE = mh_dylib; MACOSX_DEPLOYMENT_TARGET = 10.12; - MARKETING_VERSION = 1.3.1; + MARKETING_VERSION = 1.3.4; PRODUCT_BUNDLE_IDENTIFIER = com.github.jslegendre.AfloatX; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = bundle; @@ -331,7 +331,7 @@ CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1.3.1; + CURRENT_PROJECT_VERSION = 1.3.4; DEPLOYMENT_LOCATION = YES; DEVELOPMENT_TEAM = 6LAE5ASX7M; DSTROOT = /; @@ -342,7 +342,7 @@ INSTALL_PATH = "/Library/Application Support/MacEnhance/Plugins"; MACH_O_TYPE = mh_dylib; MACOSX_DEPLOYMENT_TARGET = 10.12; - MARKETING_VERSION = 1.3.1; + MARKETING_VERSION = 1.3.4; PRODUCT_BUNDLE_IDENTIFIER = com.github.jslegendre.AfloatX; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = bundle; diff --git a/AfloatX/AfloatX.h b/AfloatX/AfloatX.h index cd6ca78..6cabdac 100644 --- a/AfloatX/AfloatX.h +++ b/AfloatX/AfloatX.h @@ -11,6 +11,3 @@ @interface AfloatX : NSObject + (instancetype)sharedInstance; @end - -@interface AXAppDelegate : NSObject -@end diff --git a/AfloatX/AfloatX.m b/AfloatX/AfloatX.m index 182acc0..9577fe1 100644 --- a/AfloatX/AfloatX.m +++ b/AfloatX/AfloatX.m @@ -15,6 +15,8 @@ #import #import +static dispatch_once_t injectMenuOnceToken; + WindowTransparencyController *transparencyController; NSMenu *AfloatXMenu; NSMenuItem *AfloatXItem; @@ -30,7 +32,6 @@ NSMenu *windowOutlineSubmenu; NSArray *afloatXItems; CIFilter* colorInvertFilter; -BOOL menuInjected; @interface AfloatX() @@ -165,9 +166,7 @@ + (void)load { colorInvertFilter = [CIFilter filterWithName:@"CIColorInvert"]; [colorInvertFilter setDefaults]; - - menuInjected = NO; - + transparencyController = [WindowTransparencyController sharedInstance]; AfloatXMenu = [NSMenu new]; @@ -212,57 +211,71 @@ + (void)load { transparencyItem, nil]; [AfloatXSubmenu setItemArray:afloatXItems]; - - // If the application has a custom dock menu, we will add ourselves to that - if([[NSApp delegate] respondsToSelector:@selector(applicationDockMenu:)]) { - AfloatXMenu = [[NSApp delegate] applicationDockMenu:NSApp]; - [AfloatXMenu addItem:[NSMenuItem separatorItem]]; - menuInjected = YES; + + // Are we in an Electron app? + if(objc_lookUpClass("AtomApplicationDelegate")) { + dispatch_once(&injectMenuOnceToken, ^{ /* Use up token */ }); + [AfloatXMenu addItem:AfloatXItem]; } - - [AfloatXMenu addItem:AfloatXItem]; - _ZKSwizzle([AXAppDelegate class], [[NSApp delegate] class]); } @end +/* + AtomApplicationDelegate is the application delegate class + for all Electron apps. In order for AfloatX to work we must + explicitly swizzle this class because the application delegate + class gets subclassed/swizzled to this one after injection. +*/ +ZKSwizzleInterface(AXAppDelegate, AtomApplicationDelegate, NSObject) @implementation AXAppDelegate - (NSMenu *)applicationDockMenu:(NSApplication *)sender { - if (menuInjected) { + NSMenu *originalMenu = ZKOrig(NSMenu*, sender); + if(originalMenu) { [AfloatXMenu removeItem:AfloatXItem]; - AfloatXMenu = ZKOrig(NSMenu*, sender); + AfloatXMenu = originalMenu; // Only add a separator if last item isn't already a separator if (!AfloatXMenu.itemArray.lastObject.isSeparatorItem) [AfloatXMenu addItem:[NSMenuItem separatorItem]]; [AfloatXMenu addItem:AfloatXItem]; } + return AfloatXMenu; } @end ZKSwizzleInterface(AXApplication, NSApplication, NSResponder) @implementation AXApplication -- (CFArrayRef)_flattenMenu:(NSMenu *)arg1 flatList:(NSArray *)arg2 { +- (CFArrayRef)_flattenMenu:(NSMenu *)dockMenu flatList:(NSArray *)flatList { + + // Add AfloatX to the dock menu + dispatch_once(&injectMenuOnceToken, ^{ + if (!dockMenu.itemArray.lastObject.isSeparatorItem) + [dockMenu addItem:[NSMenuItem separatorItem]]; + + [dockMenu addItem:AfloatXItem]; + }); + // Make any necessary changes to our menu before it is 'flattened' NSWindow *window = [AXWindowUtils windowToModify]; if(!window) { AfloatXItem.enabled = NO; - return ZKOrig(CFArrayRef, arg1, arg2); + return ZKOrig(CFArrayRef, dockMenu, flatList); } - + AfloatXItem.enabled = YES; if([[AfloatX sharedInstance] isWindowTransient:window]) { [transientItem setState:NSControlStateValueOn]; } else { [transientItem setState:NSControlStateValueOff]; } - + if([[AfloatX sharedInstance] isWindowSticky:window]) { [stickyItem setState:NSControlStateValueOn]; } else { [stickyItem setState:NSControlStateValueOff]; } - + CGWindowLevel windowLevel = [AXWindowUtils getCGWindowLevelForWindow:window]; if(windowLevel != kCGNormalWindowLevel) { if(windowLevel == kCGBackstopMenuLevel) { @@ -276,13 +289,13 @@ - (CFArrayRef)_flattenMenu:(NSMenu *)arg1 flatList:(NSArray *)arg2 { [dropItem setState:NSControlStateValueOff]; [floatItem setState:NSControlStateValueOff]; } - + if([AXWindowUtils window:window hasLowTag:CGSTagTransparent]) { [clickPassthroughItem setState:NSControlStateValueOn]; } else { [clickPassthroughItem setState:NSControlStateValueOff]; } - + /* Create a new WindowOutliningController per window */ if (!objc_getAssociatedObject(window, "outlineController")) { WindowOutliningController *outlineController = [WindowOutliningController new]; @@ -292,13 +305,13 @@ - (CFArrayRef)_flattenMenu:(NSMenu *)arg1 flatList:(NSArray *)arg2 { WindowOutliningController *outlineController = objc_getAssociatedObject(window, "outlineController"); windowOutlineSubmenu.itemArray = [outlineController colorItems]; } - + if ([objc_getAssociatedObject(window, "isColorInverted") boolValue]) { [invertColorItem setState:NSControlStateValueOn]; } else { [invertColorItem setState:NSControlStateValueOff]; } - - return ZKOrig(CFArrayRef, arg1, arg2); + + return ZKOrig(CFArrayRef, dockMenu, flatList); } @end