1 #import "ITCoreImageWindowEffect.h"
2 #import "ITTransientStatusWindow.h"
3 #import "ITCoreGraphicsHacks.h"
4 #import "ITCoreImageView.h"
6 @interface ITCoreImageWindowEffect (Private)
7 - (void)performAppearFromProgress:(float)progress effectTime:(float)time;
10 - (void)performVanishFromProgress:(float)progress effectTime:(float)time;
17 static BOOL _running = NO;
19 @implementation ITCoreImageWindowEffect
21 + (NSString *)effectName
26 + (NSDictionary *)supportedPositions
28 return [NSDictionary dictionaryWithObjectsAndKeys:
29 [NSDictionary dictionaryWithObjectsAndKeys:
30 [NSNumber numberWithBool:YES], @"Left",
31 [NSNumber numberWithBool:YES], @"Center",
32 [NSNumber numberWithBool:YES], @"Right", nil] , @"Top" ,
33 [NSDictionary dictionaryWithObjectsAndKeys:
34 [NSNumber numberWithBool:YES], @"Left",
35 [NSNumber numberWithBool:YES], @"Center",
36 [NSNumber numberWithBool:YES], @"Right", nil] , @"Middle" ,
37 [NSDictionary dictionaryWithObjectsAndKeys:
38 [NSNumber numberWithBool:YES], @"Left",
39 [NSNumber numberWithBool:YES], @"Center",
40 [NSNumber numberWithBool:YES], @"Right", nil] , @"Bottom" , nil];
43 + (unsigned int)listOrder
48 /*************************************************************************/
50 #pragma mark APPEAR METHODS
51 /*************************************************************************/
57 [self setWindowVisibility:ITWindowAppearingState];
58 [self performAppearFromProgress:0.0 effectTime:_effectTime];
61 - (void)performAppearFromProgress:(float)progress effectTime:(float)time
63 [_window setEffectProgress:progress];
64 _effectSpeed = (1.0 / (EFFECT_FPS * time));
66 if ( progress == 0.0 ) {
67 [_window setAlphaValue:0.0];
70 [_window orderFront:self];
72 _effectTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / EFFECT_FPS)
74 selector:@selector(appearStep)
82 float interFade = 0.0;
83 [_window setEffectProgress:([_window effectProgress] + _effectSpeed)];
84 [_window setEffectProgress:( ([_window effectProgress] < 1.0) ? [_window effectProgress] : 1.0)];
85 interFade = (( sin(([_window effectProgress] * pi) - (pi / 2)) + 1 ) / 2);
86 [_window setAlphaValue:interFade];
88 if ( [_window effectProgress] >= 1.0 ) {
95 [_effectTimer invalidate];
98 [self setWindowVisibility:ITWindowVisibleState];
102 if ( __shouldReleaseWhenIdle ) {
109 [self setWindowVisibility:ITWindowVanishingState];
111 [_effectTimer invalidate];
114 [self performVanishFromProgress:[_window effectProgress] effectTime:(_effectTime / 3.5)];
118 /*************************************************************************/
120 #pragma mark VANISH METHODS
121 /*************************************************************************/
123 - (void)performVanish
127 [self setWindowVisibility:ITWindowVanishingState];
128 [self performVanishFromProgress:1.0 effectTime:_effectTime];
131 - (void)performVanishFromProgress:(float)progress effectTime:(float)time
133 [_window setEffectProgress:progress];
134 _effectSpeed = (1.0 / (EFFECT_FPS * time));
135 if ( progress == 1.0 ) {
136 [_window setAlphaValue:1.0];
139 [_window orderFront:self];
141 _effectTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / EFFECT_FPS)
143 selector:@selector(vanishStep)
151 float interFade = 1.0;
152 [_window setEffectProgress:([_window effectProgress] - _effectSpeed)];
153 [_window setEffectProgress:( ([_window effectProgress] > 0.0) ? [_window effectProgress] : 0.0)];
154 interFade = (( sin(([_window effectProgress] * pi) - (pi / 2)) + 1 ) / 2);
155 [_window setAlphaValue:interFade];
157 if ( [_window effectProgress] <= 0.0 ) {
164 [_effectTimer invalidate];
166 [_window orderOut:self];
167 [_window setAlphaValue:1.0];
169 [self setWindowVisibility:ITWindowHiddenState];
173 if ( __shouldReleaseWhenIdle ) {
180 [self setWindowVisibility:ITWindowVanishingState];
182 [_effectTimer invalidate];
185 [self performAppearFromProgress:[_window effectProgress] effectTime:(_effectTime / 3.5)];
188 /*************************************************************************/
190 #pragma mark CORE IMAGE METHODS
191 /*************************************************************************/
195 NSRect rippleRect = [_window frame];
196 NSRect screenRect = [[_window screen] frame];
199 //Short-circuit to avoid layering effects and crashing
206 rippleRect.origin.y = - (NSMaxY(rippleRect) - screenRect.size.height);
208 _effectWindow = [[NSWindow alloc] initWithContentRect:_ripple ? NSInsetRect([_window frame], -200, -200) : [_window frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
209 [_effectWindow setBackgroundColor:[NSColor clearColor]];
210 [_effectWindow setAlphaValue:1.0];
211 [_effectWindow setOpaque:NO];
212 [_effectWindow setHasShadow:NO];
213 [_effectWindow setContentView:[[ITCoreImageView alloc] initWithFrame:[_window frame]]];
214 [_effectWindow setLevel:[_window level]];
216 [_effectWindow orderFrontRegardless];
217 [_window orderWindow:NSWindowAbove relativeTo:[_effectWindow windowNumber]];
220 _effectFilter = [[CIFilter filterWithName:@"CIShapedWaterRipple"] retain];
221 [_effectFilter setDefaults];
222 [_effectFilter setValue:[NSNumber numberWithFloat:50.0] forKey:@"inputCornerRadius"];
223 [_effectFilter setValue:[CIVector vectorWithX:rippleRect.origin.x Y:rippleRect.origin.y] forKey:@"inputPoint0"];
224 [_effectFilter setValue:[CIVector vectorWithX:(rippleRect.origin.x + rippleRect.size.width) Y:(rippleRect.origin.y + rippleRect.size.height)] forKey:@"inputPoint1"];
225 [_effectFilter setValue:[NSNumber numberWithFloat:0.0] forKey:@"inputPhase"];
227 _effectFilter = [[CIFilter filterWithName:@"CIZoomBlur"] retain];
228 [_effectFilter setDefaults];
229 [_effectFilter setValue:[CIVector vectorWithX:(rippleRect.origin.x + rippleRect.size.width / 2) Y:(rippleRect.origin.y + rippleRect.size.height / 2)] forKey:@"inputCenter"];
232 _windowFilter = [[CICGSFilter filterWithFilter:_effectFilter connectionID:[NSApp contextID]] retain];
233 [_windowFilter addToWindow:(CGSWindowID)[_effectWindow windowNumber] flags:1];
235 [NSThread detachNewThreadSelector:@selector(runFilterAnimation:) toTarget:self withObject:self];
238 - (void)runFilterAnimation:(id)sender
240 NSAutoreleasePool *pool;
241 CICGSFilter *oldFilter;
242 CFAbsoluteTime startTime, time;
243 CGSWindowID windowNumber = (CGSWindowID)[_effectWindow windowNumber];
245 pool = [[NSAutoreleasePool alloc] init];
247 startTime = CFAbsoluteTimeGetCurrent();
248 time = CFAbsoluteTimeGetCurrent();
250 while (time < (startTime + 2.5) && (time >= startTime)) {
251 oldFilter = _windowFilter;
253 [_effectFilter setValue:[NSNumber numberWithFloat:160*(time - startTime)] forKey:@"inputPhase"];
255 [_effectFilter setValue:[NSNumber numberWithFloat:5 * (time - startTime)] forKey:@"inputAmount"];
257 _windowFilter = [[CICGSFilter filterWithFilter:_effectFilter connectionID:[NSApp contextID]] retain];
258 [_windowFilter addToWindow:windowNumber flags:1];
259 [oldFilter removeFromWindow:windowNumber];
261 time = CFAbsoluteTimeGetCurrent();
264 [_windowFilter removeFromWindow:windowNumber];
265 [_windowFilter release];
266 [_effectFilter release];
267 [_effectWindow orderOut:self];
268 [[_effectWindow contentView] release];
269 [_effectWindow release];