Skip to content

Commit edc6ec0

Browse files
committed
Deprecate Space#moveWindows in macOS 13.6+, 14.5+ and 15.0+ (#354)
1 parent 1249142 commit edc6ec0

5 files changed

Lines changed: 28 additions & 39 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Release: dd.mm.yyyy
1010

1111
- **Breaking:** Phoenix now requires macOS Big Sur (11) or higher (required by Xcode 16).
1212
- **Breaking:** Function `App#launch(...)` is now asynchronous and the function does not return the app. Pass a callback function as the third argument to receive the app after launching.
13+
- **Breaking:** Moving windows between spaces is not anymore supported if you have macOS 13.6+, 14.5+ or 15.0+ ([#354](https://github.com/kasper/phoenix/issues/354)).
1314
- Upgrade Sparkle to 2.7.1.
1415
- Xcode 16 is now required for building.
1516

@@ -19,6 +20,10 @@ Release: dd.mm.yyyy
1920

2021
- Change: Function `launch(...)` is now asynchronous and the function does not return the app. Pass a callback function as the third argument to receive the app after launching.
2122

23+
### Space
24+
25+
- Deprecation: Function `Space#moveWindows` is not anymore supported if you have macOS 13.6+, 14.5+ or 15.0+. Apple has restricted the access for 3rd party apps to call the relevant APIs ([#354](https://github.com/kasper/phoenix/issues/354)).
26+
2227
4.0.1
2328
-----
2429

Phoenix/NSProcessInfo+PHExtension.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
+ (BOOL)isOperatingSystemAtLeastBigSur;
1212
+ (BOOL)isOperatingSystemAtLeastMonterey;
13+
+ (BOOL)isOperatingSystemAtLeastVentura136;
1314
+ (BOOL)isOperatingSystemAtLeastSonoma145;
15+
+ (BOOL)isOperatingSystemAtLeastSequoia;
1416

1517
@end

Phoenix/NSProcessInfo+PHExtension.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,19 @@ + (BOOL)isOperatingSystemAtLeastMonterey {
1818
return [[self processInfo] isOperatingSystemAtLeastVersion:monterey];
1919
}
2020

21+
+ (BOOL)isOperatingSystemAtLeastVentura136 {
22+
NSOperatingSystemVersion ventura136 = {.majorVersion = 13, .minorVersion = 6, .patchVersion = 0};
23+
return [[self processInfo] isOperatingSystemAtLeastVersion:ventura136];
24+
}
25+
2126
+ (BOOL)isOperatingSystemAtLeastSonoma145 {
2227
NSOperatingSystemVersion sonoma145 = {.majorVersion = 14, .minorVersion = 5, .patchVersion = 0};
2328
return [[self processInfo] isOperatingSystemAtLeastVersion:sonoma145];
2429
}
2530

31+
+ (BOOL)isOperatingSystemAtLeastSequoia {
32+
NSOperatingSystemVersion sequoia = {.majorVersion = 15, .minorVersion = 0, .patchVersion = 0};
33+
return [[self processInfo] isOperatingSystemAtLeastVersion:sequoia];
34+
}
35+
2636
@end

Phoenix/PHSpace.m

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
typedef NSUInteger CGSConnectionID;
1616
typedef NSUInteger CGSSpaceID;
1717
typedef NSUInteger CGSWorkspaceID;
18-
typedef NSUInteger CGSMoveWindowCompatID;
1918

2019
typedef enum {
2120
kCGSSpaceIncludesCurrent = 1 << 0,
@@ -38,10 +37,6 @@ @implementation PHSpace
3837
static NSString *const CGSSpaceIDKey = @"ManagedSpaceID";
3938
static NSString *const CGSSpacesKey = @"Spaces";
4039

41-
// An arbitrary ID we can use with CGSSpaceSetCompatID
42-
static const CGSMoveWindowCompatID PHMoveWindowsCompatId = 4000;
43-
static const CGSMoveWindowCompatID PHMoveWindowsResetCompatId = 0;
44-
4540
// XXX: Undocumented private API to get the CGSConnectionID for the default connection for this process
4641
CGSConnectionID CGSMainConnectionID(void);
4742

@@ -70,15 +65,6 @@ @implementation PHSpace
7065
// only works prior to macOS 14.5
7166
void CGSMoveWindowsToManagedSpace(CGSConnectionID connection, CFArrayRef windowIds, CGSSpaceID spaceId);
7267

73-
// XXX: Undocumented private API to set a space’s (legacy) compatId
74-
CGError CGSSpaceSetCompatID(CGSConnectionID connection, CGSSpaceID spaceId, CGSMoveWindowCompatID compatId);
75-
76-
// XXX: Undocumented private API to move the given windows (CGWindowIDs) to the given space by its (legacy) compatId
77-
CGError CGSSetWindowListWorkspace(CGSConnectionID connection,
78-
CGWindowID windowIds[],
79-
NSUInteger windowCount,
80-
CGSMoveWindowCompatID compatId);
81-
8268
#pragma mark - Initialising
8369

8470
- (instancetype)initWithIdentifier:(NSUInteger)identifier {
@@ -238,34 +224,16 @@ - (void)removeWindows:(NSArray<PHWindow *> *)windows {
238224
(__bridge CFArrayRef) @[@(self.identifier)]);
239225
}
240226

241-
/* Fixes https://github.com/kasper/phoenix/issues/348, referencing:
242-
* - https://github.com/koekeishiya/yabai/issues/2240#issuecomment-2116326165
243-
* - https://github.com/ianyh/Amethyst/issues/1643#issuecomment-2132519682
244-
*/
245-
- (void)moveWindowsWithCompatId:(NSArray<PHWindow *> *)windows {
246-
NSArray<NSNumber *> *windowIds = [self identifiersForWindows:windows];
247-
NSUInteger windowCount = [windowIds count];
248-
NSMutableData *windowIdSequence = [[NSMutableData alloc] initWithCapacity:windowCount * sizeof(CGWindowID)];
249-
for (NSNumber *windowId in windowIds) {
250-
CGWindowID value = windowId.unsignedIntValue;
251-
[windowIdSequence appendBytes:&value length:sizeof(CGWindowID)];
252-
}
253-
254-
CGSConnectionID connection = CGSMainConnectionID();
255-
CGSSpaceSetCompatID(connection, self.identifier, PHMoveWindowsCompatId);
256-
CGSSetWindowListWorkspace(connection, (CGWindowID *)[windowIdSequence bytes], windowCount, PHMoveWindowsCompatId);
257-
CGSSpaceSetCompatID(connection, self.identifier, PHMoveWindowsResetCompatId);
258-
}
259-
260227
- (void)moveWindows:(NSArray<PHWindow *> *)windows {
261-
if (![NSProcessInfo isOperatingSystemAtLeastSonoma145]) {
262-
CGSMoveWindowsToManagedSpace(
263-
CGSMainConnectionID(), (__bridge CFArrayRef)[self identifiersForWindows:windows], self.identifier);
228+
// Moving windows is not anymore supported in macOS 13.6+, 14.5+ and 15.0+
229+
if ([NSProcessInfo isOperatingSystemAtLeastVentura136] || [NSProcessInfo isOperatingSystemAtLeastSonoma145] ||
230+
[NSProcessInfo isOperatingSystemAtLeastSequoia]) {
231+
NSLog(@"Deprecated: Function Space#moveWindows(...) is deprecated and will be removed in later versions.");
264232
return;
265233
}
266234

267-
// CGSMoveWindowsToManagedSpace is broken in macOS 14.5+, so use the legacy Compat ID API instead
268-
[self moveWindowsWithCompatId:windows];
235+
CGSMoveWindowsToManagedSpace(
236+
CGSMainConnectionID(), (__bridge CFArrayRef)[self identifiersForWindows:windows], self.identifier);
269237
}
270238

271239
@end

docs/docs/api/space.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Use the Space to control spaces. *These features are only supported on El Capita
66
You can switch to a space by focusing on a window in that space. By default, macOS also supports the keyboard shortcut <kbd>Control</kbd> + <kbd>←/→</kbd> to navigate between spaces.
77
:::
88

9+
:::warning Moving Windows Between Spaces
10+
Moving windows between spaces is not anymore supported if you have macOS 13.6+, 14.5+ or 15.0+. Apple has restricted the access for 3rd party apps to call the relevant APIs.
11+
:::
12+
913
## Interface
1014

1115
```javascript
@@ -41,7 +45,7 @@ end
4145

4246
### 3.0.0+
4347

44-
- `moveWindows(Array<Window> windows)` moves the given windows to the space (macOS 10.13+)
48+
- `moveWindows(Array<Window> windows)` moves the given windows to the space (macOS 10.13+, <13.6, <14.5, <15.0)
4549

4650
### Optionals
4751

0 commit comments

Comments
 (0)