-
Notifications
You must be signed in to change notification settings - Fork 1
/
FMNAXModule.m
186 lines (164 loc) · 5.91 KB
/
FMNAXModule.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//
// FMNAXModule.m
// FMN
//
// Created by Nathaniel Gray on 8/16/06.
// Copyright 2006 __MyCompanyName__. All rights reserved.
//
#import "FMNAXModule.h"
#import "AXApplication.h"
#define MAX_WORKSPACE 16
@implementation FMNAXModule
- (void) setExclusions:(NSArray *)ex
{
if (mExclusions != nil) {
[mExclusions release];
}
mExclusions = [ex retain];
}
- (id) initWithBundle:(NSBundle *)bundle
{
self = [super init];
if (!self)
return nil;
// This should be in the prefs pane, but for now put it in the info.plist
NSArray *exclusions =
[bundle objectForInfoDictionaryKey:@"ExcludedAppBundleIDs"];
if (exclusions == nil) {
NSLog(@"No excluded apps found");
} else if (![exclusions isKindOfClass:[NSArray class]]) {
NSLog(@"Ignoring ExcludedAppBundleIDs. Not an NSArray! (class = %@)",
[exclusions class]);
} else {
NSLog(@"Excluding apps:\n%@", exclusions);
mExclusions = [exclusions retain];
}
mOrigin = [[AXOrigin alloc] init];
// Yes, this hideous script is the best I could do...
mCountWSScript = [[NSAppleScript alloc] initWithSource:@"\n\
tell application \"System Events\"\n\
if spaces enabled of spaces preferences of expose preferences is true then\n\
return (spaces rows of spaces preferences of expose preferences) * (spaces columns of spaces preferences of expose preferences)\n\
else\n\
return 1\n\
end if\n\
end tell"];
NSDictionary *err;
if (![mCountWSScript compileAndReturnError:&err]) {
NSLog(@"Couldn't compile script to count workspaces. Using default count.");
[mCountWSScript release];
mCountWSScript = nil;
}
return self;
}
- (void) dealloc
{
if (mExclusions != nil)
[mExclusions release];
[mOrigin release];
[super dealloc];
}
typedef int CGSConnection;
extern OSStatus CGSGetWorkspace(const CGSConnection cid, int *workspace);
extern OSStatus CGSSetWorkspace(const CGSConnection cid, int workspace);
extern CGSConnection _CGSDefaultConnection(void);
- (int) countWorkspaces
{
if (mCountWSScript) {
NSDictionary *err;
NSAppleEventDescriptor *rval;
rval = [mCountWSScript executeAndReturnError:&err];
if (nil == rval) {
NSLog(@"Error executing our workspace counting script.");
} else {
int nws = [rval int32Value];
if (nws > MAX_WORKSPACE){
NSLog(@"Bogus return value from ws counting script: %i", nws);
} else {
return nws;
}
}
}
return MAX_WORKSPACE;
}
- (NSArray *) getRestorables
{
NSMutableArray* orientations = [NSMutableArray arrayWithCapacity : 100];
int workspace = 0;
CGSConnection cid = _CGSDefaultConnection();
CGSGetWorkspace(cid,&workspace);
NSDate *ws_startDate = [NSDate date];
NSPoint origin = [mOrigin getOrigin];
// Get the list of launched applications
NSArray* launchedApplications = [[NSWorkspace sharedWorkspace] launchedApplications];
NSEnumerator* enumerator = [launchedApplications objectEnumerator];
// Make an AXApplication for each one
NSMutableArray *axApps =
[NSMutableArray arrayWithCapacity:[launchedApplications count]];
ProcessSerialNumber psn;
NSDictionary* appInfo;
while (appInfo = [enumerator nextObject])
{
NSDate *startDate = [NSDate date];
NSNumber* tmp;
tmp = [appInfo objectForKey:@"NSApplicationProcessSerialNumberLow"];
psn.lowLongOfPSN = [tmp longValue];
tmp = [appInfo objectForKey:@"NSApplicationProcessSerialNumberHigh"];
psn.highLongOfPSN = [tmp longValue];
NSString *name = [appInfo objectForKey:@"NSApplicationName"];
NSString *bundleID = [appInfo objectForKey:@"NSApplicationBundleIdentifier"];
if (mExclusions != nil && [mExclusions containsObject:bundleID]) {
NSLog (@"Skipping excluded app: \"%@\" (%@)", name, bundleID);
continue;
}
@try
{
AXApplication* app = [AXApplication configWithPSN:psn
appName:name
origin:origin];
[axApps addObject:app];
}
@catch (NSException* ex)
{
NSLog(@"%@: %@ (after %f seconds)", name, [ex reason],
-[startDate timeIntervalSinceNow]);
}
}
int i;
for(i=1; i<=[self countWorkspaces]; ++i)
{
int ws_ret = CGSSetWorkspace(cid,i);
int wsWinCount = 0;
NSLog (@"Setting workspace: %d (ret=%d)", i, ws_ret);
AXApplication *app;
enumerator = [axApps objectEnumerator];
while (app = [enumerator nextObject]) {
NSDate *startDate = [NSDate date];
@try
{
NSArray *appOrientations = [app getCurrentWindowOrientations];
int nWins = [appOrientations count];
wsWinCount += nWins;
if (nWins > 0) {
[orientations addObjectsFromArray : appOrientations];
NSLog(@"%@: Got %d windows in %.2f seconds", [app name],
nWins, -[startDate timeIntervalSinceNow]);
}
}
@catch (NSException* ex)
{
NSLog(@"%@: %@ (after %f seconds)", [app name], [ex reason],
-[startDate timeIntervalSinceNow]);
}
}
}
NSLog(@"AX: Got %d windows in %f seconds",
[orientations count], -[ws_startDate timeIntervalSinceNow]);
CGSSetWorkspace(cid,workspace);
return orientations;
}
- (void) restoreFinished
{
[mOrigin resetOrigin];
}
@end