Using Core Image Filters On/Under a NSWindow

So just to kick off I thought I'd drop a little Cocoa code to apply a Core Image filter to, or underneath, a window. This is similar to what Apple themselves use in Mac OS X v10.5 "Leopard" to create a blur under menus, etc. Firstly, you'll need to define some things:
typedef void * CGSConnection;
extern OSStatus CGSNewConnection(const void **attributes, CGSConnection * id);
Then you'll need to use the following code to create a filter and apply it to a window. For this example, I use a blur placed beneath a window's contents (similar to menus, or Glass in Vista):
-(void)enableBlurForWindow:(NSWindow *)window
{
 CGSConnection thisConnection;
 uint32_t compositingFilter;
 int compositingType = 1; // Under the window

 /* Make a new connection to CoreGraphics */
 CGSNewConnection(NULL, &thisConnection);

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

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

5 comments:

  1. Hey Steve,

    Is there any way to dynamically change the values of a given window in Leopard to apply the transparency and blur that you've outlined in this post? I'd really like to change Safari's windows so that I can have them semi-transparent, but blur the background in order to make the transparency useful, but not distracting.

    Any help would be awesome!

    ReplyDelete
  2. @Deathsushi Yeah, it should be possible, it all works on the window ID that the OS keeps -> you'd need to find a way of making the Safari window chrome semitransparent and then just add the blur.

    ReplyDelete
  3. Thanks Steve,

    So, if I understand correctly, I would need to:

    1. Determine the ID for the window
    2. Apply transparency to that window
    3. Add blur to that window

    How would I go about doing this? Is it just a matter of writing a script? Can you give me some tips or advice in the direction I should start looking into? If I can get something working, I'll post it here.

    It would be very nice and useful to be able to have transparency and blur on for my Terminal (already done using Deeper), Safari, and Mail.app

    ReplyDelete
  4. Look at the CGWindowListCopyWindowInfo method, it will return a CFArrayRef of windows (you can choose if they're visible windows or onscreen windows etc when you call the method). From there you can get the window number and the window owner PID or owner name. From there it should be pretty straightforward, however I was trying to do something similar and am having problems attaching filters to windows that don't belong to my application.

    ReplyDelete
  5. It doesn't work anymore on Mavericks

    ReplyDelete