当主窗口透明时应用CIFilter背景过滤器

5
我希望能够在网格和列表模式下复制dock Stacks的背景。背景是半透明黑色,具有模糊效果: 网格模式下dock stack示例http://www.thecustommac.com/wp-content/uploads/2009/09/stack-highlight.jpg 问题是[CALayer backgroundFilters]仅适用于窗口中的内容,过滤器不适用于其他窗口中的内容。这是我的代码:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{
    //make window transparent
    self.window.backgroundColor = [NSColor clearColor];
    [self.window setOpaque:NO];
    [self.window setHasShadow:NO];
    [self.window setStyleMask:NSBorderlessWindowMask];


    //make the content view layer hosting
    CALayer *rootLayer = [CALayer layer];
    [[self.window contentView] setLayer:rootLayer];
    [[self.window contentView] setWantsLayer:YES];


    //blur the background contents - NOT WORKING!
    [rootLayer setBackgroundColor:CGColorCreateGenericGray(0.0, .716)];

    CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
    [blurFilter setDefaults];
    [rootLayer setBackgroundFilters:[NSArray arrayWithObject: blurFilter]];
}

我想不出其他实现这种效果的方法。(我查看了显示服务,看看是否有任何有用的功能,但我没有看到任何。) 有什么想法吗?
4个回答

9

这里提供了一个私有API,以下是Rob Keniger的示例代码:

在10.5版本中,您可以使用私有函数“CGSAddWindowFilter”将任何核心图像滤镜添加到窗口中。

typedef void * CGSConnectionID;

extern OSStatus CGSNewConnection(const void **attr, CGSConnectionID *id);

- (void)enableBlurForWindow:(NSWindow *)window
{

CGSConnectionID _myConnection;
uint32_t __compositingFilter;

int __compositingType = 1; // Apply filter to contents underneath the window, then draw window normally on top

/* Make a new connection to CoreGraphics, alternatively you could use the main connection*/

CGSNewConnection(NULL , &_myConnection);

/* The following creates a new CoreImage filter, then sets its options with a dictionary of values*/

CGSNewCIFilterByName (_myConnection, (CFStringRef)@"CIGaussianBlur", &__compositingFilter);
NSDictionary *optionsDict = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:3.0] forKey:@"inputRadius"];
CGSSetCIFilterValuesFromDictionary(_myConnection, __compositingFilter, (CFDictionaryRef)optionsDict);

/* Now just switch on the filter for the window */

CGSAddWindowFilter(_myConnection, [window windowNumber], __compositingFilter, __compositingType );
}

值得一提的是,这在Yosemite中似乎不再起作用了。 :-( CGSNewCIFilterByName()返回kCGErrorNotImplemented。 - Siobhán

1

你的代码有一些错误,这里是可以正常工作的代码:

typedef void * CGSConnection;
extern OSStatus CGSNewConnection(const void **attributes, CGSConnection * id);

-(void)enableBlurForWindow:(NSWindow *)window {

    CGSConnection thisConnection;
    NSUInteger compositingFilter;
    NSInteger compositingType = 1 << 0;

    // Make a new connection to Core Graphics
    CGSNewConnection(NULL, &thisConnection);

    // Create a Core Image filter and set it up
    CGSNewCIFilterByName(thisConnection, (CFStringRef)@"CIGaussianBlur", &compositingFilter);
    NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:2] forKey:@"inputRadius"];
    CGSSetCIFilterValuesFromDictionary(thisConnection, compositingFilter, (__bridge CFDictionaryRef)options);

    // Apply the filter to the window
    CGSAddWindowFilter(thisConnection, [window windowNumber], compositingFilter, compositingType);
}

然后,使用它:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [_window setOpaque:NO];

    [_window setBackgroundColor: [NSColor colorWithCalibratedHue:0.568 saturation:0.388 brightness:0.941 alpha:0.6]];

    [self enableBlurForWindow:_window];
}

据我所知,这在XCode7.1中已经不再适用了。尽管我已经添加了CoreGraphics.framework和#import "CoreGraphics/CoreGraphics.h",但您的代码仍无法编译,因为它找不到CGSNewCIFilterByNameCGSSetCIFilterValuesFromDictionaryCGSAddWindowFilter。我还将我的项目设置为运行于10.8 OSX,但后来将其更改为10.10 OSX,以查看是否能够编译,但结果仍然失败。 - Volomike

1
过滤器没有被根层使用: 来自文档的描述:
    /* An array of filters that are applied to the background of the layer.
 * The root layer ignores this property. Animatable. */

@property(copy) NSArray *backgroundFilters;

-3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接