简体   繁体   中英

Change heaviness of NSWindow drop shadow?

I have an NSWindow that has a drop shadow, but it is way to dark. The shadow spreads too far and is too heavy for me. It's the default shadow for the NSWindow and I haven't edited it at all.

What I want to know is if there is a way to shorten the blur radius or lower the heaviness of the drop shadow so it appears a bit more subtle.

Thanks!

There's no public API, but you can do It by swizzling some methods on NSThemeFrame (this is the view class responsible for the window's frame, border, etc).

Here's an example ( a subclass of NSWindow ):

#import <objc/runtime.h>

@interface SOWindow : NSWindow
@end

@interface SOWindowThemeFrameOverrides : NSView
@end

@implementation SOWindow

+ (void)load
{
    NSArray *methodsToOverride = @[@"_shadowOffset", @"_shadowFlags", @"_shadowType"];
    for (NSString *selector in methodsToOverride) {
        Method m = class_getInstanceMethod(NSClassFromString(@"NSThemeFrame"), NSSelectorFromString(selector));
        Method m2 = class_getInstanceMethod([SOWindowThemeFrameOverrides class], NSSelectorFromString(selector));
        class_addMethod(NSClassFromString(@"NSThemeFrame"), NSSelectorFromString([NSString stringWithFormat:@"_original%@", selector]), method_getImplementation(m), method_getTypeEncoding(m));
        method_exchangeImplementations(m, m2);
    }
}

@end

@implementation SOWindowThemeFrameOverrides

- (NSSize)_shadowOffset
{
    if ([self.window isKindOfClass:[SOWindow class]]) {
        return NSMakeSize(0, 8);
    } else {
        return [self _original_shadowOffset];
    }
}

- (NSUInteger)_shadowFlags
{
    if ([self.window isKindOfClass:[SOWindow class]]) {
        return 0;
    } else {
        return [self _original_shadowFlags];
    }
}

- (NSInteger)_shadowType
{
    if ([self.window isKindOfClass:[SOWindow class]]) {
        return 4;
    } else {
        return [self _original_shadowType];
    }
}

#pragma mark Placeholder methods

- (NSSize)_original_shadowOffset
{
    // implementation will be filled in at runtime
    return NSZeroSize;
}

- (NSUInteger)_original_shadowFlags
{
    // implementation will be filled in at runtime
    return 0;
}

- (NSInteger)_original_shadowType
{
    // implementation will be filled in at runtime
    return 0;
}

@end

When the SOWindow class is loaded by the runtime, the + load method is invoked. The method switches NSThemeFrame's implementation of the 3 shadow methods by their implementation in SOWindowThemeFrameOverrides , also adding the original methods to the class with the _original prefix.

When the swizzled methods are called, we check to see if the window is a SOWindow , if It is we use the custom shadow, if It's not we forward the call to the original implementations.

This is what I get by returning 4 from _shadowType :

带有微妙阴影的SOWindow

Please note that this is a huge hack and would probably be rejected if you tried to submit It to the AppStore.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM