与Willeke 类似,经过几个小时的代码,我能够完成此任务。这是我的代码,然后我将解释它对以后遇到此代码的人的作用。
In .h
My code is in AppDelegate (it is a menubar app).
@interface AppDelegate : NSObject <NSApplicationDelegate>
{
...
// Workspace mutations vars
NSInteger workspacesToRemove; // Used in removing workspaces (as
loop)
}
// Define constants for sizes
#define kWORKSPACE_WIDTH 145
#define kWORKSPACE_HEIGHT 90
#define kWORKSPACE_SPACING 30
In .m
- (void)removeAllWorkspaces
{
NSDictionary *spacesPlist = [NSDictionary dictionaryWithContentsOfFile:[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Preferences/com.apple.spaces.plist"]];
NSDictionary *spacesDisplayConfig = [spacesPlist objectForKey:[[spacesPlist allKeys] objectAtIndex:0]];
NSArray *spaceProperties = [spacesDisplayConfig objectForKey:@"Space Properties"];
NSInteger numberOfWorkspaces = [spaceProperties count];
NSLog(@"Number of workspaces: %ld", (long)numberOfWorkspaces);
// Set counter
workspacesToRemove = numberOfWorkspaces;
[self openMissionControl];
}
#pragma mark Open/Close step methods
- (void)openMissionControl
{
CGEventSourceRef src =
CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef cntd = CGEventCreateKeyboardEvent(src, 0x3B, YES);
CGEventRef cntu = CGEventCreateKeyboardEvent(src, 0x3B, NO);
CGEventRef upd = CGEventCreateKeyboardEvent(src, 0x7E, YES);
CGEventRef upu = CGEventCreateKeyboardEvent(src, 0x7E, NO);
/*
*/
CGEventSetFlags(upd, kCGEventFlagMaskControl);
CGEventSetFlags(upu, kCGEventFlagMaskControl);
CGEventTapLocation loc = kCGHIDEventTap; // kCGSessionEventTap also works
CGEventPost(loc, cntd);
CGEventPost(loc, upd);
CGEventPost(loc, upu);
CGEventPost(loc, cntu);
CFRelease(cntd);
CFRelease(cntu);
CFRelease(upd);
CFRelease(upu);
[self performSelector:@selector(moveMouseToUpdateMissionControl) withObject:nil afterDelay:1];
}
- (void)moveMouseToUpdateMissionControl
{
CGEventPost(kCGHIDEventTap, CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, CGPointMake([[NSScreen mainScreen] frame].size.width - 10, 10), kCGMouseButtonLeft));
[self performSelector:@selector(moveMouseToCloseRightmostWorkspace) withObject:nil afterDelay:1];
}
- (void)moveMouseToCloseRightmostWorkspace
{
NSRect workspaceRect = [self rectForWorkspaces];
NSInteger closeX = (workspaceRect.origin.x + workspaceRect.size.width) - kWORKSPACE_WIDTH;
CGPoint closePoint = CGPointMake(closeX, workspaceRect.origin.y);
// Move mouse to point
CGEventRef mouseMove = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, closePoint, kCGMouseButtonLeft);
CGEventPost(kCGHIDEventTap, mouseMove);
CFRelease(mouseMove);
// Click
[self performSelector:@selector(clickMouseAtPoint:) withObject:[NSValue valueWithPoint:closePoint] afterDelay:2]; // Must be equal or greater 1.5
}
- (void)clickMouseAtPoint:(NSValue *)pointValue
{
CGPoint clickPoint = [pointValue pointValue];
// Click
CGEventPost(kCGHIDEventTap, CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, clickPoint, kCGMouseButtonLeft));
CGEventPost(kCGHIDEventTap, CGEventCreateMouseEvent(NULL, kCGEventLeftMouseUp, clickPoint, kCGMouseButtonLeft));
workspacesToRemove--;
NSLog(@"%ld", (long)workspacesToRemove);
if (workspacesToRemove > 1) {
[self performSelector:@selector(moveMouseToCloseRightmostWorkspace) withObject:nil afterDelay:2];
} else {
[self performSelector:@selector(closeMissionControl) withObject:nil afterDelay:1];
}
}
- (void)closeMissionControl
{
CGEventSourceRef src =
CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef cntd = CGEventCreateKeyboardEvent(src, 0x3B, YES);
CGEventRef cntu = CGEventCreateKeyboardEvent(src, 0x3B, NO);
CGEventRef upd = CGEventCreateKeyboardEvent(src, 0x7E, YES);
CGEventRef upu = CGEventCreateKeyboardEvent(src, 0x7E, NO);
CGEventSetFlags(upd, kCGEventFlagMaskControl);
CGEventSetFlags(upu, kCGEventFlagMaskControl);
CGEventTapLocation loc = kCGHIDEventTap; // kCGSessionEventTap also works
CGEventPost(loc, cntd);
CGEventPost(loc, upd);
CGEventPost(loc, upu);
CGEventPost(loc, cntu);
CFRelease(cntd);
CFRelease(cntu);
CFRelease(upd);
CFRelease(upu);
}
#pragma mark
#pragma mark Adding Workspaces
- (void)openWorkspaces:(NSInteger)numberToOpen
{
// Open Mission control
CGEventSourceRef src =
CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef cntd = CGEventCreateKeyboardEvent(src, 0x3B, YES);
CGEventRef cntu = CGEventCreateKeyboardEvent(src, 0x3B, NO);
CGEventRef upd = CGEventCreateKeyboardEvent(src, 0x7E, YES);
CGEventRef upu = CGEventCreateKeyboardEvent(src, 0x7E, NO);
/*
*/
CGEventSetFlags(upd, kCGEventFlagMaskControl);
CGEventSetFlags(upu, kCGEventFlagMaskControl);
CGEventTapLocation loc = kCGHIDEventTap; // kCGSessionEventTap also works
CGEventPost(loc, cntd);
CGEventPost(loc, upd);
CGEventPost(loc, upu);
CGEventPost(loc, cntu);
[NSThread sleepForTimeInterval:2];
// Move mouse to point
CGEventRef mouseMove = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, CGPointMake([[NSScreen mainScreen] frame].size.width - 10, 10), kCGMouseButtonLeft);
CGEventPost(kCGHIDEventTap, mouseMove);
CFRelease(mouseMove);
for (NSInteger i = 0; i < numberToOpen; i++) {
// Add as many times as needed
CGEventPost(kCGHIDEventTap, CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, CGPointMake([[NSScreen mainScreen] frame].size.width - 10, 10), kCGMouseButtonLeft));
CGEventPost(kCGHIDEventTap, CGEventCreateMouseEvent(NULL, kCGEventLeftMouseUp, CGPointMake([[NSScreen mainScreen] frame].size.width - 10, 10), kCGMouseButtonLeft));
[NSThread sleepForTimeInterval:1];
}
CGEventPost(loc, cntd);
CGEventPost(loc, upd);
CGEventPost(loc, upu);
CGEventPost(loc, cntu);
CFRelease(cntd);
CFRelease(cntu);
CFRelease(upd);
CFRelease(upu);
}
- (NSRect)rectForWorkspaces
{
NSDictionary *spacesPlist = [NSDictionary dictionaryWithContentsOfFile:[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Preferences/com.apple.spaces.plist"]];
NSDictionary *spacesDisplayConfig = [spacesPlist objectForKey:[[spacesPlist allKeys] objectAtIndex:0]];
NSArray *spaceProperties = [spacesDisplayConfig objectForKey:@"Space Properties"];
NSInteger numberOfWorkspaces = [spaceProperties count];
NSInteger totalSpacing = (numberOfWorkspaces - 1) * kWORKSPACE_SPACING;
NSInteger totalLengthOfWorkspaces = numberOfWorkspaces * kWORKSPACE_WIDTH;
NSInteger totalRectWidth = totalSpacing + totalLengthOfWorkspaces;
NSRect workspaceRect = NSMakeRect(0, 0, totalRectWidth, kWORKSPACE_HEIGHT);
// Calculate center x or screen
NSInteger screenCenter = [[NSScreen mainScreen] frame].size.width / 2;
workspaceRect.origin.x = screenCenter - (workspaceRect.size.width / 2);
workspaceRect.origin.y = kWORKSPACE_SPACING;
return workspaceRect;
}
现在让我们逐步了解代码
对于删除工作区,第一种方法removeAllWorkspaces 是起点。
此代码从com.apple.spaces.plist 文件中获取打开的工作区数量,然后设置变量workspacesToRemove。这个变量对于循环很重要,因为当有方法链(我称之为方法链)时很难执行for-loop。
接下来,我通过CGEvents 调用一个方法来打开任务控制。然后我将鼠标移动到屏幕的上角,以确保工作区图标正确居中。
接下来,代码使用rectForWorkspaces 方法确定最右侧工作区的关闭按钮的位置。
这是一个非常简单的方法,但它是发生的主要部分。
它计算了工作区在任务控制中的位置的矩形。这是一个表示它计算的图像:
然后我将这个矩形减去 145(工作区图标宽度),然后在它弹出时单击关闭按钮。
这部分循环直到所有工作区(除了 1)都关闭。
FWI:它被分成许多方法的原因是我可以循环回一个特定的方法并在延迟后执行这些方法而不会阻塞线程。
耶复杂的结束了!
添加工作区要容易得多。
这只是一种方法(openWorkspaces:(NSInteger)numberToOpen),它打开任务控制,将鼠标移动到某个位置,然后单击多次,直到添加所有工作空间。很简单。