-
-
Notifications
You must be signed in to change notification settings - Fork 339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AltTab doesn't list windows from other Spaces opened before it was started #431
Comments
Update: actually it seems to affect any window on another space, not just fullscreen window. Seems like a regression |
Ok I found the root cause. It's quite a complex story, and I'm not sure which way to go forwards. Recently, I've improved the multi-threading, and handling of some OS calls. Namely, AX calls (made to get the windows title, type, position, etc) were put on a separate thread, so they can be processed in the background without affecting the UI responsiveness. There are 2 reasons here:
We added this background and retry-loop logic everywhere, including AltTab startup code, which plays some tricks. At startup, AltTab teleports all windows from other Spaces into the current Space, then attempts to get their AX info like titles, then teleports them back to their original Space. This is ugly, uses private APIs, makes the screen flash for a few milliseconds, but is the only way to be able to list these windows in AltTab at startup. Indeed the OS doesn't list windows from other Spaces otherwise, so it's the only way I know of to achieve that. Here is the actual code from startup: // on initial launch, we use private APIs to bring windows from other spaces into the current space, observe them, then remove them from the current space
CGSAddWindowsToSpaces(cgsMainConnectionId, windowsOnlyOnOtherSpaces as NSArray, [Spaces.currentSpaceId])
Applications.observeNewWindows()
CGSRemoveWindowsFromSpaces(cgsMainConnectionId, windowsOnlyOnOtherSpaces as NSArray, [Spaces.currentSpaceId]) The issue is that in 2 ways to go forwards I can imagine:
Writing this out, I think it's clear that solution 2 is crazy, so I want to go with solution 1. I actually want to go further, and completely remove the hacky code above from AltTab. It was a useful hack, and is a valiant effort to list windows from other Spaces at startup, but in the end it can't be done in a clean way since any app may be unresponsive, and we don't want to wait seconds with the app magically showing in the current Space, while we try to get it's AX info. I tried the same scenario with HyperSwitch, and somehow it's able to list the windows. There must be another trick than teleporting them. Here is a dump of the symbols they use as a reference. I'll update this ticket to reflect that goal. |
I was just about to report this. When I switch on my Mac every day, I'll have to switch to the other 2 Desktops (Spaces) to fully populate AltTabs List. |
Re. crazy solution 2, i.e.
I realise it might amount to another rewrite of this logic, but - Couldn't you do this with a (manual) timeout per app/window query instead? For example, if one doesn't respond within 100ms then it is omitted, until the user switches to the Space manually. That would still give better results than option 1, and presumably well-behaved apps generally ought to respond pretty quickly. I know you said they're blocking but perhaps you could also paralellise these queries, so that it's still fast? (Equally, this isn't a very big issue, for me at least, so it seems entirely reasonable not to want to spend that much time on it.) |
That approach would still flash the screen. It is also pretty tricky to do. I think I would rather keep current status quo, and when looking to improve (i.e. fix this ticket), try to find a novel way. If HyperSwitch is doing it, there is a way. I need to revisit the private APIs I haven't tried, and find a new trick to get these windows on other spaces at startup. Please feel free to join the investigation: |
You can get both the window title and position (and screenshot) from a window using private APIs that only require the target window id. You can also retrieve a list of window_ids for all windows regardless of the space they are at. You will however not be able to retrieve an AXUIElementRef unless the window is on the currently active space. I believe you already have used some of these before. Fairly certain I mentioned a few of them in various issues/PRs here as well, but they are easy to spot if you look at the exported symbols in the SkyLight (or CoreGraphics) framework. |
@koekeishiya i'm sorry, my memory failed me I think. I'll find these private APIs then! However, let's say i have title, screenshot, and app icon, i still need to be able to focus the window with the wid only. I tried that 2 days ago and while i can actually have the window be active, the code is not able to switch Space. I then looked for private APIs to switch space, but then remembered why i moved the windows previously: all the private APIs for Space manipulation are not actually moving to different Spaces. Instead they do logical assignement of windows to Spaces which result in graphical glitches. Do you think it's possible to focus a window on another Space only with its wid? I remember spending a few weeks on this last time, playing with the methods from yabai, but in the end i still had to add an AX call to make it work |
The scripting addition that yabai injects into the Dock is capapble of focusing a window using only its window id, by calling a non-exported function. IIRC this function is sending a message to some apple.dock.Server port to implement that. I’m not sure if this is simply a mach call that any process could send, to implement the same feature, or if it is a protected xpc service.
You can combine CGSShowSpaces, CGSHideSpaces and CGSSetCurrentSpaceForManagedDisplay to do a proper space switch (but mission control is out of sync, unless you update the internal datastructures in the Dock like yabai does.)
…Sent from my iPhone
On 19 Jul 2020, at 06:52, lwouis <[email protected]> wrote:
@koekeishiya<https://github.com/koekeishiya> i'm sorry, my memory failed me I think. I'll find these private APIs then! However, let's say i have title, screenshot, and app icon, i still need to be able to focus the window with the wid only. I tried that 2 days ago and while i can actually have the window be active, the code is not able to switch Space. I then looked for private APIs to switch space, but then remembered why i moved the windows previously: all the private APIs for Space manipulation are not actually moving to different Spaces. Instead they do logical assignement of windows to Spaces which result in graphical glitches.
Do you think it's possible to focus a window on another Space only with its wid? I remember spending a few weeks on this last time, playing with the methods from yabai, but in the end i still had to add an AX call<https://github.com/lwouis/alt-tab-macos/blob/c21170d574c4e9bb2de1bc3a1f3873289720ae4f/src/logic/Window.swift#L143> to make it work
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub<#431 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/ABPDZV4HM4YRHXFF7QXPUVDR4J3ZNANCNFSM4O3PKSCA>.
|
Interesting. Maybe i could reuse that somehow. Could you please point me to the area of the codebase where this is happening? I don't remember seeing this in the past. Maybe the scripting addition is in another dedicated repo? |
Wrapper for code that I inject into the Dock: https://github.com/koekeishiya/yabai/blob/master/src/osax/payload.m#L812 |
I found this to be quite interesting so I looked into where this service is defined, and it is ran by TALagent (Transparent Application Lifecycle agent), and this is what the Dock is signalling when it wants to request focus for a window. The binary is located at |
This is a bit too difficult for me to keep investigating as I lack background in low-level languages, and their toolchains and practices. Furthermore, I think there may be a simpler approach. When investigating the decompiled code of HyperSwitch, I see their fullscreen function: Note how it uses Now if I put a window on another Space, and I start HyperSwitch, I can then summon it. At this point I see the window listed. Our theory so far was that they are able to focus it without having access to the Now the question is: how do they get the |
Not sure how relevant this really is at this point, but I did some more digging for fun and figured I would share my findings. I tested and confirmed that it does work as-is (by running it from inside the Dock process, because it already has access to the mach_port_t instances). Unfortunately as far as I know there is no way to get the task (mach_port_t) to some other process without at least running as root. The Dock, however, is NOT running as root, so I assume there may still be some way to be able to achieve this both out of process and without root...
|
That's very interesting. This reminded me of this section of this retro-engineering repo, and this issue opened last year there. There may be way indeed. This system doesn't seem very sound from a security standpoint. You have also explained you found a way to read the keyboard through userland security measures, so that sets the tone for macOS security. That being said, are you not intrigued by how HyperSwitch seemingly is able to access |
Describe the bug
As discussed in this other ticket, fullscreen windows open before AltTab is opened, will not be listed in AltTab.
Steps to reproduce the bug
The text was updated successfully, but these errors were encountered: