Skip to content

Commit

Permalink
Made project El Capitan compatible
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreasVerhoeven committed Oct 4, 2015
1 parent 2ba4a5b commit e92ae53
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 14 deletions.
6 changes: 5 additions & 1 deletion AveNoAnimationsInMailPlugin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
objects = {

/* Begin PBXBuildFile section */
495BBFFB1BC16D1800FC37B9 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 495BBFFA1BC16D1800FC37B9 /* QuartzCore.framework */; };
B2662CE4181909FE00783601 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B2662CE3181909FE00783601 /* Cocoa.framework */; };
B2662CEE181909FE00783601 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B2662CEC181909FE00783601 /* InfoPlist.strings */; };
B2662CF718190A6600783601 /* AveHookBootstrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = B2662CF618190A6600783601 /* AveHookBootstrapper.m */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
495BBFFA1BC16D1800FC37B9 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
B2662CE0181909FD00783601 /* AveNoAnimationsInMailPlugin.mailbundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AveNoAnimationsInMailPlugin.mailbundle; sourceTree = BUILT_PRODUCTS_DIR; };
B2662CE3181909FE00783601 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
B2662CE6181909FE00783601 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
Expand All @@ -30,6 +32,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
495BBFFB1BC16D1800FC37B9 /* QuartzCore.framework in Frameworks */,
B2662CE4181909FE00783601 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -57,6 +60,7 @@
B2662CE2181909FE00783601 /* Frameworks */ = {
isa = PBXGroup;
children = (
495BBFFA1BC16D1800FC37B9 /* QuartzCore.framework */,
B2662CE3181909FE00783601 /* Cocoa.framework */,
B2662CE5181909FE00783601 /* Other Frameworks */,
);
Expand Down Expand Up @@ -164,7 +168,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [ \"${CONFIGURATION}\" = \"Release\" ]; then\n cp -r $BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME $PROJECT_DIR/Output/\n zip -r -X $PROJECT_DIR/Output/$(basename \"$FULL_PRODUCT_NAME\").zip $PROJECT_DIR/Output/$FULL_PRODUCT_NAME\n cd $PROJECT_DIR/Output/\n /bin/sh $PROJECT_DIR/Output/repackage.sh\nfi";
shellScript = "if [ \"${CONFIGURATION}\" = \"Release\" ]; then\n cp -r \"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME\" \"$PROJECT_DIR/Output/\"\n zip -r -X \"$PROJECT_DIR/Output/$(basename \"$FULL_PRODUCT_NAME\").zip\" \"$PROJECT_DIR/Output/$FULL_PRODUCT_NAME\"\n cd \"$PROJECT_DIR/Output/\"\n /bin/sh \"$PROJECT_DIR/Output/repackage.sh\"\nfi";
};
/* End PBXShellScriptBuildPhase section */

Expand Down
215 changes: 209 additions & 6 deletions AveNoAnimationsInMailPlugin/AveHookBootstrapper.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,195 @@
//

#import "AveHookBootstrapper.h"
#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>

@implementation AveHookBootstrapper

#pragma mark shouldDoPopOutAnimation
static BOOL elCapitanOverrideTransactionDurationToZero = NO;

+(BOOL)isElCapitan
{
static BOOL isElCapitan = NO;

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSProcessInfo* processInfo = [NSProcessInfo processInfo];
if([processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)])
{
NSOperatingSystemVersion version = {0};
version.majorVersion = 10;
version.minorVersion = 11; // el cap
isElCapitan = [processInfo isOperatingSystemAtLeastVersion:version];
}
});

return isElCapitan;
}

static IMP AveReplaceMethod(Class class, BOOL isMetaClass, SEL sel, id block) {

NSString* printableMethodDescription = [NSString stringWithFormat:@"%@[%@ %@]", isMetaClass ? @"+" : @"-", NSStringFromClass(class), NSStringFromSelector(sel)];

// get original method
Method method = class_getInstanceMethod(class, sel);
if(method == nil)
{
NSLog(@"Ave: Method not found %@", printableMethodDescription);
}

NSLog(@"Ave: %@ -> %s", printableMethodDescription, method_getTypeEncoding(method));

IMP newIMP = imp_implementationWithBlock(block);

if(class_addMethod(class, sel, newIMP, method_getTypeEncoding(method)))
{
NSLog(@"Ave: Added %@", printableMethodDescription);
return method_getImplementation(method);
}
else
{
NSLog(@"Ave: Replaced %@", printableMethodDescription);
return method_setImplementation(method, newIMP);
}
}

static IMP AveReplaceInstanceMethod(Class class, SEL sel, id block) {
return AveReplaceMethod(class, NO, sel, block);
}

static IMP AveReplaceClassMethod(Class class, SEL sel, id block) {
Class metaClass = object_getClass(class);
return AveReplaceMethod(metaClass, YES, sel, block);
}

#pragma mark - El Capitan

+(void)aveElCapitanSwizzleCATransactionSetAnimationDuration
{
Class class = [CATransaction class];
SEL sel = @selector(setAnimationDuration:);
__block IMP originalImplementation = AveReplaceClassMethod(class, sel, ^(id obj, NSTimeInterval duration){

if([NSThread isMainThread] && elCapitanOverrideTransactionDurationToZero)
duration = 0.01;

if(originalImplementation != NULL)
{
((void(*)(id, SEL, NSTimeInterval))originalImplementation)(obj, sel, duration);
}
});
}

+(void)aveElCapitanSwizzleNSAnimationContextSetDuration
{
Class class = [NSAnimationContext class];
SEL sel = @selector(setDuration:);
__block IMP originalImplementation = AveReplaceInstanceMethod(class, sel, ^(id obj, NSTimeInterval duration){

if([NSThread isMainThread] && elCapitanOverrideTransactionDurationToZero)
duration = 0.0;

if(originalImplementation != NULL)
{
((void(*)(id, SEL, NSTimeInterval))originalImplementation)(obj, sel, duration);
}
});
}

+(void)aveElCapitanSwizzleComposeWindowControllerPerformSendAnimation
{
Class class = NSClassFromString(@"ComposeWindowController");
SEL sel = @selector(_performSendAnimation);
__block IMP originalImplementation = AveReplaceInstanceMethod(class, sel, ^(id obj){
elCapitanOverrideTransactionDurationToZero = YES;
if(originalImplementation != NULL)
{
((void(*)(id, SEL))originalImplementation)(obj, sel);
}

elCapitanOverrideTransactionDurationToZero = NO;
});
}

+(void)aveElCapitanSwizzlePopoutAnimationController_animateFrom_to_withCompletion
{
Class class = NSClassFromString(@"PopoutAnimationController");
SEL sel = @selector(animateFrom:to:withCompletion:);
__block IMP originalImplementation = AveReplaceInstanceMethod(class, sel, ^(id obj, id from, id to, id completion){
elCapitanOverrideTransactionDurationToZero = YES;
if(originalImplementation != NULL)
{
((void(*)(id, SEL, id, id, id))originalImplementation)(obj, sel, from, to, completion);
}

elCapitanOverrideTransactionDurationToZero = NO;
});
}

+(void)aveElCapitanswizzlePopoutAnimationController_internalTransitionAnimationWithDestination_fadeOut
{
Class class = NSClassFromString(@"PopoutAnimationController");
SEL sel = @selector(_internalTransitionAnimationWithDestination:fadeOut:);
/*__block IMP originalImplementation = */AveReplaceInstanceMethod(class, sel, ^id(id obj, CGRect rc, BOOL fadeOut){

return nil;
/*
if(originalImplementation != NULL)
{
CAAnimationGroup* animationGroup = ((CAAnimationGroup*(*)(id, SEL, CGRect, BOOL))originalImplementation)(obj, sel, rc, fadeOut);
return animationGroup;
}
*/
});
}

+(void)aveElCapitanSwizzleWindowTransformAnimation__animationDurationForAnimationType
{
Class class = NSClassFromString(@"WindowTransformAnimation");
SEL sel = @selector(_animationDurationForAnimationType:);
AveReplaceInstanceMethod(class, sel, ^NSTimeInterval(id obj, NSInteger type){
return 0.0;
});
}

+(void)aveElCapitanSwizzleFullScreenWindowController_animateModalWindowClose
{
Class class = NSClassFromString(@"FullScreenWindowController");
SEL sel = @selector(_animateModalWindowClose:);
__block IMP originalImplementation = AveReplaceInstanceMethod(class, sel, ^(id obj, id sender){
elCapitanOverrideTransactionDurationToZero = YES;
if(originalImplementation != NULL)
{
((void(*)(id, SEL, id))originalImplementation)(obj, sel, sender);
}

elCapitanOverrideTransactionDurationToZero = NO;
});
}


// ensure the selectors exist
-(CAAnimationGroup*)_internalTransitionAnimationWithDestination:(CGRect)rc fadeOut:(BOOL)fadeOut
{
return nil;
}
-(void)animateFrom:(id)from to:(id)to withCompletion:(id)completion
{
}

-(NSTimeInterval)_animationDurationForAnimationType:(NSInteger)type
{
return 0.0;
}

-(void)_animateModalWindowClose:(id)sender
{
}

#pragma mark - Mavericks and Yosemite

#pragma mark shouldDoPopOutAnimation
// use the same names as the method we swizzle, so the selectors exist
-(BOOL)shouldDoPopOutAnimation
{
Expand All @@ -25,7 +208,7 @@ +(void)aveSwizzlePopoutAnimation
Class class = NSClassFromString(@"DocumentEditor");
Method orig = class_getInstanceMethod(class, @selector(shouldDoPopOutAnimation));
Method repl = class_getInstanceMethod(self, @selector(shouldDoPopOutAnimation));
NSLog(@"Ave: Swizzle shouldDoPopOutAnimation: %p -> %p", orig, repl);
NSLog(@"Ave: Swizzle %@ shouldDoPopOutAnimation: %p -> %p", class, orig, repl);
method_exchangeImplementations(orig, repl);
}

Expand Down Expand Up @@ -58,8 +241,14 @@ +(void)swizzlePerformSendAnimation
// -[DocumentEditor _sendAnimationCompleted]
Class class = NSClassFromString(@"DocumentEditor");
Method orig = class_getInstanceMethod(class, @selector(_performSendAnimation));
if(nil == orig || nil == class)
{
class = NSClassFromString(@"ComposeWindowController");
orig = class_getInstanceMethod(class, @selector(_performSendAnimation));
}

Method repl = class_getInstanceMethod(self, @selector(_performSendAnimation));
NSLog(@"Ave: Swizzle _performSendAnimation: %p -> %p", orig, repl);
NSLog(@"Ave: Swizzle %@ _performSendAnimation: %p -> %p", class, orig, repl);
method_exchangeImplementations(orig, repl);
}

Expand Down Expand Up @@ -87,9 +276,23 @@ +(void)aveSwizzleWindowTransformAnimation
+(void)load
{
NSLog(@"Ave: Loaded, time to start swizzling");
[self aveSwizzlePopoutAnimation];
[self swizzlePerformSendAnimation];
[self aveSwizzleWindowTransformAnimation];
if([self isElCapitan])
{
[self aveElCapitanSwizzleCATransactionSetAnimationDuration];
[self aveElCapitanSwizzleNSAnimationContextSetDuration];
[self aveElCapitanSwizzleComposeWindowControllerPerformSendAnimation];
[self aveElCapitanSwizzlePopoutAnimationController_animateFrom_to_withCompletion];
[self aveElCapitanswizzlePopoutAnimationController_internalTransitionAnimationWithDestination_fadeOut];
[self aveElCapitanSwizzleWindowTransformAnimation__animationDurationForAnimationType];
[self aveElCapitanSwizzleFullScreenWindowController_animateModalWindowClose];
}
else
{
[self aveSwizzlePopoutAnimation];
[self swizzlePerformSendAnimation];
[self aveSwizzleWindowTransformAnimation];
}

}

#pragma mark MVMailBundle class methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.1.2</string>
<string>1.2</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2014 AveApps. All rights reserved.</string>
<string>Copyright © 2015 AveApps. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string>AveHookBootstrapper</string>
<key>SupportedPluginCompatibilityUUIDs</key>
Expand Down
Binary file modified Output/AveNoAnimationsInMailPlugin.mailbundle.zip
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>15B17c</string>
<string>15A282b</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
Expand All @@ -25,7 +25,7 @@
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1.1.2</string>
<string>1.2</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
Expand All @@ -41,7 +41,7 @@
<key>DTXcodeBuild</key>
<string>7A220</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2014 AveApps. All rights reserved.</string>
<string>Copyright © 2015 AveApps. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string>AveHookBootstrapper</string>
<key>SupportedPluginCompatibilityUUIDs</key>
Expand Down
Binary file not shown.
Binary file modified Output/DisableMailAnimationsForOSX.pkg
Binary file not shown.
4 changes: 2 additions & 2 deletions Output/repackage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ cat /tmp/Package.unpkg/avenoanimationsinmailplugin.pkg/Payload | gzip -d | cpio

# copying files
echo "Copying files"
cp -r $CWD/AveNoAnimationsInMailPlugin.mailbundle /tmp/Package-inner.pkg/
cp -r "$CWD/AveNoAnimationsInMailPlugin.mailbundle" /tmp/Package-inner.pkg/

rm /tmp/Package.unpkg/avenoanimationsinmailplugin.pkg/Payload
rm /tmp/Package.unpkg/avenoanimationsinmailplugin.pkg/Bom
Expand All @@ -36,7 +36,7 @@ echo "$NUMFILES files, $NUMKBYTES kb"
sed -i '' -e 's/installKBytes="[-0-9]*"/installKBytes="'$NUMKBYTES'"/' /tmp/Package.unpkg/avenoanimationsinmailplugin.pkg/PackageInfo
sed -i '' -e 's/numberOfFiles="[-0-9]*"/numberOfFiles="'$NUMFILES'"/' /tmp/Package.unpkg/avenoanimationsinmailplugin.pkg/PackageInfo

pkgutil --flatten /tmp/Package.unpkg/ $CWD/DisableMailAnimationsForOSX.pkg
pkgutil --flatten /tmp/Package.unpkg/ "$CWD/DisableMailAnimationsForOSX.pkg"

rm -r /tmp/Package.unpkg 2> /dev/null
rm -r /tmp/Package-inner.pkg 2> /dev/null
Expand Down

0 comments on commit e92ae53

Please sign in to comment.