同様に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
メソッドを使用して、一番右のワークスペースの閉じるボタンの位置を決定します。
これは非常に単純な方法ですが、何が起こるかの主要部分です。
ワークスペースがミッション コントロール内にある場所の四角形を計算しました。計算内容を表す画像は次のとおりです。
次に、この rect から 145 (ワークスペース アイコンの幅) を引いて、表示された [閉じる] ボタンをクリックします。
この部分は、すべてのワークスペース (1 を除く) が閉じられるまでループします。
FWI: 多くのメソッドに分割されている理由は、特定のメソッドにループバックし、スレッドをブロックすることなく遅延後にメソッドを実行できるようにするためです。
やった複雑なクローズオーバー!
ワークスペースの追加ははるかに簡単です。
これは 1 つの方法 ( openWorkspaces:(NSInteger)numberToOpen
) であり、ミッション コントロールを開き、マウスを所定の位置に移動し、すべてのワークスペースが追加されるまで何度もクリックします。とてもシンプルです。