Second Revision (from Archive)
[~jspiros/WindowBlur.git] / WindowBlurSIMBL.m
1 //
2 //  WindowBlurSIMBL.m
3 //  WindowBlur
4 //
5 //  Created by Joseph Spiros on 5/12/09.
6 //  Copyright 2009 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "WindowBlurSIMBL.h"
10 #import "CGSInternal.h"
11 #import <objc/objc-class.h>
12
13 void MethodSwizzle(Class aClass, SEL orig_sel, SEL alt_sel)
14 {
15     Method orig_method = nil, alt_method = nil;
16         
17     // First, look for the methods
18     orig_method = class_getInstanceMethod(aClass, orig_sel);
19     alt_method = class_getInstanceMethod(aClass, alt_sel);
20         
21     // If both are found, swizzle them
22     if ((orig_method != nil) && (alt_method != nil))
23         {
24         char *temp1;
25         IMP temp2;
26                 
27         temp1 = orig_method->method_types;
28         orig_method->method_types = alt_method->method_types;
29         alt_method->method_types = temp1;
30                 
31         temp2 = orig_method->method_imp;
32         orig_method->method_imp = alt_method->method_imp;
33         alt_method->method_imp = temp2;
34         }
35 }
36
37 static NSMutableDictionary *instanceIDToIvars = nil;
38 static BOOL needToSwizzleDealloc = YES;
39
40 @implementation WindowBlurWindowHack
41
42 - (id)PRE__instanceID
43 {
44     return [NSValue valueWithPointer:self];
45 }
46
47 - (NSMutableDictionary *)PRE__ivars
48 {
49     NSMutableDictionary *ivars;
50     
51     if (needToSwizzleDealloc)
52     {
53         MethodSwizzle([NSWindow class], 
54                       @selector(dealloc), 
55                       @selector(PRE__deallocSwizzler));
56         needToSwizzleDealloc = NO;
57     }
58         
59     if (instanceIDToIvars == nil)
60     {
61         instanceIDToIvars = [[NSMutableDictionary alloc] init];
62     }
63     
64     ivars = [instanceIDToIvars objectForKey:[self PRE__instanceID]];
65     if (ivars == nil)
66     {
67         ivars = [NSMutableDictionary dictionary];
68         [instanceIDToIvars setObject:ivars forKey:[self PRE__instanceID]];
69     }
70     
71     return ivars;
72 }
73
74 - (void)PRE__deallocSwizzler
75 {
76     [instanceIDToIvars removeObjectForKey:[self PRE__instanceID]];
77     if ([instanceIDToIvars count] == 0)
78     {
79         [instanceIDToIvars release];
80         instanceIDToIvars = nil;
81     }
82     
83     [self PRE__deallocSwizzler];
84 }
85
86 - (void)display {
87         #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
88         if (floor(NSAppKitVersionNumber) > 824) {
89                 NSString *filterName;
90                 if (!(filterName = [[NSUserDefaults standardUserDefaults] stringForKey:@"WindowBlurSIMBL-FilterName"])) {
91                         filterName = @"CIGaussianBlur";
92                 }
93                 NSDictionary *filterValues;
94                 if (!(filterValues = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"WindowBlurSIMBL-FilterValues"])) {
95                         filterValues = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:2.0] forKey:@"inputRadius"];
96                 }
97                 NSMutableDictionary *optionsDict = [NSMutableDictionary dictionaryWithDictionary:filterValues];
98                 if (![optionsDict objectForKey:@"inputCenter"]) {
99                         [optionsDict setObject:[CIVector vectorWithX:0.0 Y:0.0] forKey:@"inputCenter"];
100                 }
101                 CGSConnectionID con = CGSMainConnectionID();
102                 if (con) {
103                         NSNumber *filterNumber;
104                         int filter;
105                         if (filterNumber = [[self PRE__ivars] objectForKey:@"filter"]) {
106                                 filter = [filterNumber intValue];
107                                 CGSRemoveWindowFilter(con, [self windowNumber], filter);
108                         }
109                         if (noErr == CGSNewCIFilterByName(con, (CFStringRef)filterName, &filter)) {
110                                 CGSSetCIFilterValuesFromDictionary(con, filter, (CFDictionaryRef)optionsDict);
111                                 CGSAddWindowFilter(con, [self windowNumber], filter, kCGWindowFilterUnderlay);
112                                 [[self PRE__ivars] setObject:[NSNumber numberWithInt:filter] forKey:@"filter"];
113                         }
114                 }                       
115         }
116         #endif
117         [super display];
118 }
119
120 @end
121
122 @implementation WindowBlurSIMBL
123
124 + (void)load {
125         [WindowBlurWindowHack poseAsClass:[NSWindow class]];
126 }
127
128 @end