Skip to content

Commit

Permalink
Too much for one commit 🤷🏻‍♂️
Browse files Browse the repository at this point in the history
Add support for Electron apps
Change menu injection logic to not replace custom dock menus in some apps like Terminal
  • Loading branch information
jslegendre committed Jan 30, 2020
1 parent b7a8de7 commit d9eff11
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 32 deletions.
8 changes: 4 additions & 4 deletions AfloatX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 = /;
Expand All @@ -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;
Expand All @@ -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 = /;
Expand All @@ -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;
Expand Down
3 changes: 0 additions & 3 deletions AfloatX/AfloatX.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,3 @@
@interface AfloatX : NSObject
+ (instancetype)sharedInstance;
@end

@interface AXAppDelegate : NSObject <NSApplicationDelegate>
@end
63 changes: 38 additions & 25 deletions AfloatX/AfloatX.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#import <objc/runtime.h>
#import <objc/message.h>

static dispatch_once_t injectMenuOnceToken;

WindowTransparencyController *transparencyController;
NSMenu *AfloatXMenu;
NSMenuItem *AfloatXItem;
Expand All @@ -30,7 +32,6 @@
NSMenu *windowOutlineSubmenu;
NSArray *afloatXItems;
CIFilter* colorInvertFilter;
BOOL menuInjected;

@interface AfloatX()

Expand Down Expand Up @@ -165,9 +166,7 @@ + (void)load {

colorInvertFilter = [CIFilter filterWithName:@"CIColorInvert"];
[colorInvertFilter setDefaults];

menuInjected = NO;


transparencyController = [WindowTransparencyController sharedInstance];

AfloatXMenu = [NSMenu new];
Expand Down Expand Up @@ -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) {
Expand All @@ -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];
Expand All @@ -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

0 comments on commit d9eff11

Please sign in to comment.