lwouis / alt-tab-macos

Windows alt-tab on macOS
https://alt-tab-macos.netlify.app
GNU General Public License v3.0
10.59k stars 322 forks source link

Starting with macOS 12.2, AltTab only grabs windows in active spaces #1324

Open skyzyx opened 2 years ago

skyzyx commented 2 years ago

Describe the bug

I updated to macOS 12.2 Beta (21D5039d) this morning, and since then, AltTab only grabs the front-most full-screen app window from each of my displays — ignoring the full-screen windows that are not front-most.

I know that the full-screen support is buggy because this app has to use private APIs, etc., but I wanted to bring this situation to the attention of the developers as a known issue.

Usually when AltTab is missing windows, I can quit and re-launch the app to get it to pick up the current state of my environment. However, even this action no longer works as of this morning's macOS beta update.

Screenshots / video

http://s3.ryanparman.com.s3.amazonaws.com/alttab-bug-1.mp4

dnivi3 commented 2 years ago

Seeing the same on macOS 12.2 (21D49), the production version of macOS 12.2.

kaatt commented 2 years ago

likely related to https://github.com/kasper/phoenix/issues/289 and https://github.com/ianyh/Amethyst/issues/1192

dnivi3 commented 2 years ago

Looks like Amethyst has fixed this in https://github.com/ianyh/Amethyst/pull/1184

lwouis commented 2 years ago

@dnivi3 the code change you linked to is this:

image

Changing the order remove -> add to add -> remove. AltTab already does add -> remove:

image

dnivi3 commented 2 years ago

@lwouis yeah, I realised my layman non-technical understanding of this isn't helpful. Is there any I can help or contribute towards this getting fixed?

lwouis commented 2 years ago

@dnivi3 i'm afraid only code contributions would help. Please see https://github.com/lwouis/alt-tab-macos/issues/1179

lwouis commented 2 years ago

Related: #1351

stevetodd commented 2 years ago

Just to add the datapoint, the issue persists in the newly released macOS 12.3.

radaczynski commented 2 years ago

This behaviour is repeatable. I have 3 desktops. When restarting alt-tab, windows from the active one get detected correctly, the switcher works just as expected, while on the other desktops only the active window is shown in the switcher. Restarting the apps/reopening the windows causes them to be shown in the switcher. Macos 12.3.1 here.

kaatt commented 2 years ago

Allowing screen recording permissions to the app should fix this.

radaczynski commented 2 years ago

@kaatt - were you refering to my comment? It does not fix this issue - AltTab had the permission to record screen all the time. Windows from the current desktop are detected just fine after restart of AltTab, but on other desktops only one window is detected (+ all the windows that are created after AltTab is launched).

lwouis commented 2 years ago

It seems that we could simply replace the call to CGSAddWindowsToSpaces with a call to CGSMoveWindowsToManagedSpace.

Can anyone confirm this would work?

lwouis commented 2 years ago

I experimented with replacing CGSAddWindowsToSpaces with CGSMoveWindowsToManagedSpace. It's not a 1-to-1 replacement. It doesn't move fullscreen windows. It successfully moves regular windows, and moves them back, but it doesn't do anything for fullscreen windows, thus AltTab doesn't see them.

dnivi3 commented 2 years ago

@lwouis glad to hear it solves for regular windows, but shame with fullscreen ones. Selfishly, this solves for my use cases. Is there a branch I can build from to test this?

lwouis commented 2 years ago

Is there a branch I can build from to test this?

i'm sorry, there isn't

lwouis commented 2 years ago

Interesting data point: https://github.com/lwouis/alt-tab-macos/issues/1088#issuecomment-1054595185

i wonder if HS works on macOS 12.3+. If it can still work it means they have a robust trick to deal with windows in other Spaces

dnivi3 commented 2 years ago

Interesting data point: #1088 (comment)

i wonder if HS works on macOS 12.3+. If it can still work it means they have a robust trick to deal with windows in other Spaces

@lwouis I can confirm that HyperSwitch works just fine on macOS Monterey 12.4 (21F79) and is grabbing any and all windows, including in other spaces. This is with the caveat that the window previews sometime just return blank, but that is a problem that HS has had for a long time.

lwouis commented 2 years ago

Today I wanted to decompile the Skylight framework on 12.4. I went in my 12.4 VM, and got surprised that I couldn't find it at /System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight:

image

Furthermore, I thought "how can AltTab work if Skylight is missing?". I tried to run AltTab, and it seems to work fine.

But as I was testing AltTab, I noticed that the Spaces at the top of the screen, in Mission Control, look different from my main machine which is still on macOS 10.15:

10.15 12.4
image image

Anyone knows what's going on here? Why is Skylight not at the usual path, and did Apple change the UI for Mission Control?

decodism commented 2 years ago

@lwouis

Why is Skylight not at the usual path

From the Big Sur release notes:

New in macOS Big Sur 11.0.1, the system ships with a built-in dynamic linker cache of all system-provided libraries. As part of this change, copies of dynamic libraries are no longer present on the filesystem. Code that attempts to check for dynamic library presence by looking for a file at a path or enumerating a directory will fail. Instead, check for library presence by attempting to dlopen() the path, which will correctly check for the library in the cache.

Hopper has a function to read from the DYLD shared cache.

did Apple change the UI for Mission Control

Not to my knowledge. On your screenshot, it looks like the transparency was disabled.

lwouis commented 2 years ago

Hopper has a function to read from the DYLD shared cache.

I googled that, and it's a pretty new feature in Hopper apparently. My version didn't support it for instance. I'm constantly amazed at how fast things get deprecated these days. Constant march forward :/

On your screenshot, it looks like the transparency was disabled

But also, the Spaces "thumbnails" at the top are squarish now instead of rectangles. And they don't show the windows in each Space. Is that just on that VM, or it's like this now?

decodism commented 2 years ago

My version didn't support it for instance

It seems that there are third party tools to extract from the cache.

the Spaces "thumbnails" at the top are squarish now instead of rectangles

It looks like they are the same aspect ratio as your screenshot.

they don't show the windows in each Space

It's your VM.

lwouis commented 2 years ago

@decodism you seem to be knowledgeable with decompiling. Could you please help me? I would like to investigate what happened to CGSAddWindowsToSpaces on macOS 12.2+, and why it stopped working.

macOS 10.15

On macOS 10.15, I see this proc, and it seems to lead to a mach message, to WindowServer I imagine? So there is not much implementation, it's just messaging. Maybe I'm not reading it correctly though?

image image image

macOS 12.4

On macOS 12.4, I used the new Hopper feature for DYLD shared cache. But that only shows me strings which match, not procs. I don't know how to dig further with these things.

image image image

I have investigated a lot of alternative APIs to replace CGSAddWindowsToSpaces. Nothing seems to cut it and be a good replacement. I don't think any other big projects in the community which relied on it has found a successful replacement yet.

I was hoping maybe that if I could look into the internal of CGSAddWindowsToSpaces, I could bypass calling it, and instead maybe call a sub-function, or maybe even directly send raw mach messages to the WindowServer to emulate the old behavior. We already use this approach to focus windows.

Any help would be amazing here, and I'm quite out of my expertise zone, and I feel sad thinking that AltTab is broken for users of macOS 12.2+

kaatt commented 2 years ago

@lwouis CGS functions are in SkyLight; they’ve been renamed from CGS to SLS* (the CGS variants still work)

CGSConnectionRef contains a mach port; SLS functions communicate with some service (likely WindowServer) over the mach port, sending raw payloads. Payload kind is determined by DWORD at msg_hdr[0x14] (likely msgh_id).

WindowServer is itself implemented in SkyLight: WindowServer binary merely executes SLXServer entrypoint, which checks flags and re-spawns WindowServer as a daemon (in classic Unix style; no launchd involvement).

SLXServer seems to be a massive loop, it’s a switch statement with 383 cases.

Also, Objective-See has some RE work on WindowServer/SLS: https://objective-see.com/blog/blog_0x2C.html

You'll not be able to send raw mach messages to WindowServer because of entitlements - Apple has Skylight entitlements too only issued to official binaries.

I'm opening /System/Library/dyld/dyld_shared_cache_arm64e → Skylight in Hopper

Screen Shot 2022-05-29 at 4 16 48 PM

and see transaction methods:

Screen Shot 2022-05-29 at 4 17 19 PM

Transaction methods may work but I've incorrect/partial headers for them:

#import <AppKit/AppKit.h>
typedef NSObject SLSTransaction;
typedef int SLSConnectionID;
typedef size_t SLSSpaceID;

int SLSMainConnectionID(void);

// SLSTransactionCreate returns <SLSTransaction [0x600002300ac0] cid: 493239, data: 0x109664000, size: 0, capacity: 16384, valid>
SLSTransaction* SLSTransactionCreate(SLSConnectionID cid);
int SLSTransactionCommit(SLSTransaction* txID, int unknown);

int SLSTransactionAddWindowToSpace(SLSTransaction* txID, CGWindowID window, SLSSpaceID space);
int SLSTransactionRemoveWindowFromSpace(SLSTransaction* txID, CGWindowID window, SLSSpaceID space);
int SLSTransactionRemoveWindowFromSpaces(SLSTransaction* txID, CGWindowID window, CFArrayRef spaces);
int SLSTransactionMoveWindowsToManagedSpace(SLSTransaction* txID, CFArrayRef windows, SLSSpaceID space);
int SLSTransactionAddWindowToSpaceAndRemoveFromSpaces(SLSTransaction* txID, CGWindowID window_id, SLSSpaceID add_space_id, CFArrayRef remove_space_ids);
koekeishiya commented 2 years ago

SLS functions are the user-facing API of the WindowServer; they are essentially helper functions. The actual implementation is also in the SkyLight framework, with an X prefix, which is what the server ends up executing upon receiving a mach_msg of said type.

Screenshot 2022-05-29 at 15 56 51

I've tested some of the transaction related functions mentioned above before, and they work fine, but not sure if they can get around the issue that the non-transactional-version have in 12.2 and newer.

kaatt commented 2 years ago

What headers/call incantation did you try for the transaction functions? I can test out on 12.3+

koekeishiya commented 2 years ago
extern CFTypeRef SLSTransactionCreate(int cid);
extern CGError SLSTransactionCommit(CFTypeRef transaction, int unknown); // passed 0 as unknown
extern CGError SLSTransactionMoveWindowsToManagedSpace(CFTypeRef transaction, CFArrayRef window_list, uint64_t sid);
extern CGError SLSTransactionAddWindowToSpace(CFTypeRef transaction, uint32_t wid, uint64_t sid);
extern CGError SLSTransactionRemoveWindowFromSpace(CFTypeRef transaction, uint32_t wid, uint64_t sid);
lwouis commented 2 years ago

@kaatt I didn't get the path from the search matches in Hopper, to getting the list of methods here:

image

How did the search in Hopper reveal to you the existence of SLSTransactionAddWindowToSpace for instance?

@koekeishiya

On macOS 10.15, in the __XAddWindowsToSpaces function you mentioned, it seems to call a function called _PKGSpacesAddWindowsWithConnection internally to do the work:

image

This one has the PKG prefix instead of CGS/SLS. Have you investigated around that? Maybe that PKG function is still preserved on 12.2+ as it's more internal? Maybe there is generally interesting features within the PKG functions family?

And also, how do you investigate on macOS 12.2+? There is no __XAddWindowsToSpaces there, so it seems they make big changes to the SLS internals.

kaatt commented 2 years ago

How did the search in Hopper reveal to you the existence of SLSTransactionAddWindowToSpace for instance?

I was probably searching for SLSTransaction. I also looked into /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/System/Library/PrivateFrameworks/SkyLight.framework/SkyLight.tbd

@koekeishiya your headers look similar to mine. Doesn't look like any SLSTransaction methods are working for me on 12.4. Even tried SLSTransactionMoveWindowsToManagedSpace since SLSMoveWindowsToManagedSpace is working:

typedef CFTypeRef SLSTransaction;

SLSTransaction* SLSTransactionCreate(SLSConnectionID cid);
int SLSTransactionCommit(SLSTransaction* txID, int unknown);
int SLSTransactionMoveWindowsToManagedSpace(SLSTransaction* txID, CFArrayRef window_list, SLSSpaceID sid);

tx = SLSTransactionCreate(connection)
SLSTransactionMoveWindowsToManagedSpace(tx, [fromSpace], toSpace)
SLSTransactionCommit(tx, 0)
lwouis commented 2 years ago

This one has the PKG prefix instead of CGS/SLS. Have you investigated around that? Maybe that PKG function is still preserved on 12.2+ as it's more internal? Maybe there is generally interesting features within the PKG functions family?

I found this string inside SkyLight.framework: SkyLight/Server/Packages/PKGSpace.c. So it seems they created packages inside SkyLight, and PKG may just be the way they are separating those packages. Here PKGSpace may be where they deal with Spaces.

Furthermore, inside the PKG call I mentioned above, they call ___WSWorkspacesAddWindowsWithConnection_block_invoke which is probably WS = WindowServer

decodism commented 2 years ago

@lwouis

you seem to be knowledgeable with decompiling

Sorry but I am not.

Cnly commented 2 years ago

I'm on macOS 12.4 (21F79) with alt-tab-macos 6.4.0. Prior to a few days ago everything worked fine and if not, relaunching the app would've fixed it. Then all of a sudden I ran into this problem and relaunching the app didn't fix things anymore. It seems to have started after I logged out and in again a few days ago. Today I tried rebooting and everything's working again.

fieryorc commented 2 years ago

AltTab is no longer showing windows correctly in spaces other than the one where alt-tab is started in. I have 3 spaces, and when i start alt tab, it shows the windows in current space correctly, but when I switch to another space, it either shows 1 window or no window. I have multiple windows open. Most of my windows are chrome and chrome apps. This is a blocker for me as I can use it anymore.

kashanico commented 2 years ago

Having a similar issue with dual monitors. Sometimes does not detect open windows and I have to restart AltTab to get it to recognize all open windows. Happens everytime I boot it up.

lwouis commented 2 years ago

@kashanico you're probably seeing https://github.com/lwouis/alt-tab-macos/issues/447#issuecomment-1153229652 (last bullet point, and the general ticket), if it's not the issue in this thread here.

probablykasper commented 1 year ago

The way Contexts works is that when you switch to a space, it'll scan all the windows in there. That would at least be a nice improvement, since right now it seems you have to open individual windows to get them scanned

lwouis commented 1 year ago

@probablykasper I've added logic like this for the next release. It will get all windows of a Space when you switch to that Space. It's not a full solution, but it's a nice mitigation of the issue.

probablykasper commented 1 year ago

That's great !!

radaczynski commented 1 year ago

well, from what I can tell, this has fixed the issue for me. Thanks a lot!

dnivi3 commented 1 year ago

@lwouis I just wanted to thank you so much for adding this logic to AltTab! I can finally uninstall HyperSwitch and start using AltTab again!