Alt-tab-macos: Bear.app not appearing

Created on 29 Sep 2020  Â·  13Comments  Â·  Source: lwouis/alt-tab-macos

Describe the bug

https://bear.app/ is not appearing in AltTab

Using current latest AltTab 6.7.1 and Bear 1.7.16 (8574); I'm using the free version.

cmd-tab does not show it

When I focus bear and use cmd-~ (switch in-app) it shows its single window.

So currently the only way to locate it is to either use the Dock or Spotlight.

Interesting fact: when I bring up the preferences of Bear, the pref window appears in AltTab. Once I close it, the main app also appears! And seems to stay…

bug

Most helpful comment

Hello, I'm one of Bear's developers.

I'll focus on the launch for the moment. I can confirm we don't always show the main window on applicationDidFinishLaunching because we have to wait for the CoreData and CloudKit stacks to become available and this might not be the case for large data.

Unfortunately, I don't know and alternative solution because we don't want to show an empty state interface on launch. I can tell you we use NSWindow's makeKeyAndOrderFront when we are ready, maybe there's an alternative event you can listen to in this particular scenario? Otherwise, if there's a way to trigger the "new window created" event from code, I can try that route.

All 13 comments

I can reproduce the issue... sometimes. Sometimes it just shows in AltTab.

I did a deep investigation. It seems that when asked for its windows through the accessibility API, Bear.app responds with 0 window. Here is the logic to ask for an app's windows:

  • Detect a new app is launched
  • Observe isFinishedLaunching to wait for the app to be ready
  • Subscribe to accessibility API events from that app, such as "new window created"
  • At this point, ask the app for its windows. here Bear.app responds with 0 window
  • Now since we have subscribed to the events, any new window will trigger an event, and we will add it to AltTab. The previous step is for window that are created right when the app starts and we haven't had time to subscribe to events yet.

I don't know what to do. It's the first app to behave that way. I wonder how they manage to create a window without triggering the accessibility "new window created" event. I tried to delay step 4 above, by 2s, and I get the window when I do this. So it seems they:

  • Don't send the event for new window created
  • Don't list the window if you ask quickly after launch
  • List the window if you ask after a delay (even though they send no event, while we are subscribe to events)

Could you please open a support ticket with them, and reference my investigation? I would like to know their opinion on this. It seems like a defect on their side.

It's the first app to behave that way

Of course! 😄 Thank you your time!

Could you please open a support ticket with them, and reference my investigation?

Roger! They don't seem to have a public tracker or similar, so I submitted the form at https://bear.app/contact/

Hello, I'm one of Bear's developers.

I'll focus on the launch for the moment. I can confirm we don't always show the main window on applicationDidFinishLaunching because we have to wait for the CoreData and CloudKit stacks to become available and this might not be the case for large data.

Unfortunately, I don't know and alternative solution because we don't want to show an empty state interface on launch. I can tell you we use NSWindow's makeKeyAndOrderFront when we are ready, maybe there's an alternative event you can listen to in this particular scenario? Otherwise, if there's a way to trigger the "new window created" event from code, I can try that route.

Hi @trix180! Thank you for the quick feedback! I'll try to explain the situation, as I understand it.

AltTab at the technical level, is an accessibility app. It uses macOS Accessibility APIs - the AX family of APIs. On launch, AltTab finds apps such as Bear, and subscribe to their AX events using AXObserverAddNotification. Once the subscription returns a .success code, AltTab will get a callback anytime Bear sends an EX notification, such as kAXWindowCreatedNotification. These notifications are automatically sent if you use standard APIs to build your app, as the doc of the notification I just listed say:

A window was created. Carbon automatically sends this notification when window is created, as long as the window is implemented using Carbon window mechanisms.

Note however that before AltTab subscribes to Bear, Bear could potentially already open a window, which AltTab would not get a callback for, since it's not subscribed yet. This is why, after subscribing successfully, AltTab manually asks Bear for all its open windows, using another AX API, which is not subscription based, but a direct getter: AXUIElementCopyAttributeValue on kAXWindowsAttribute.

Now as I explained previously, Bear spawns a window which is neither triggering an event post-subscription, nor being listed in the getter call. I have never seen this happen before. I would imagine it could happen if your way of instantiating or showing the window is unusual, or done on the wrong thread, or maybe your app is unresponsive at a particular time? AltTab retries failing calls, both for the subscription and the getter, so it eventually succeeds, so it may not be the problem here.

I'm not sure what to tell you beyond that. I would suggest you google similar issue with windows not being listed in a AXUIElementCopyAttributeValue call from another app. Maybe review your threading, init sequence, etc. You can also git clone this project, run it, and put a debug point exactly here after it's launched. Then launch Bear, and see how the getter call returns 0 window.

Let me know if I can help more. I don't have access to your codebase unfortunately, so I can only give pointers and guess.

Hi, sorry for the late response, and thanks a lot for pointers.

To help me sort this mystery out I created a brand new macOS app project in XCode and after some testing... I'm still a little puzzled. Apparently unchecking the Is Initial Controller option on the window controller and call programmatically makeKeyAndOrderFront works if it's called at the end of applicationDidFinishLaunching, but also tried some silly threading to simulate Bear's delay

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    self.aqueue = [NSOperationQueue new];

    [self.aqueue addOperationWithBlock:^{

        sleep(4);

        [[NSOperationQueue mainQueue] addOperationWithBlock:^{

            NSStoryboard* board = [NSStoryboard storyboardWithName:@"Main" bundle:nil];
            NSWindowController* wc = (NSWindowController*)[board instantiateControllerWithIdentifier:@"Window Controller"];
            [wc.window makeKeyAndOrderFront:nil];
        }];
    }];
}

Apparently, the code above is causing the wrongful detection of the app window at the suggested breakpoint. I'm testing this on Big Sur, so I'm not 100% sure this is what's happening on Catalina or will happen on macOS 11 final release but, if confirmed, I don't know what to do with this because we don't have control over the delay in real life (and we don't want to show an empty window). I'm totally unsure this is a problem with AltTab or the API.

Regards.

P.S.
Congratulations on the AltTab project

Hey @trix180, thanks for looking deeper into this! Could you please share this test app you shared the main method of? I would like to start it locally and see what kind of AX events it produces for other apps like AltTab. The above code is not enough because there are thousands of settings in XCode that could interact here like the checkbox you mentionned. So could you please share a release .app (you need to zip it to drop it here) of this test app?

Hi! Sure, here it is.

alttab-test.zip

@trix180 I recorded a complete analysis video/showcase for you here. Could you please have a look?

Follow-up: I looked again into the fail-safe of "why is the window not added when focused". The answer is that Bear doesn't generate a kAXFocusedWindowChangedNotification event either. It generates the kAXApplicationActivatedNotification, but no window event basically. Something is wrong with the main window in Bear.

This is when I focus the main window:

"Accessibility event" "AXApplicationActivated" "Bear"

This is when I bring up Bear's preferences window, which works correctly, unlike the main window:

"Accessibility event" "AXFocusedUIElementChanged" "nil"
"Accessibility event" "AXFocusedWindowChanged" "Preferences"
"Accessibility event" "AXMainWindowChanged" "Preferences"
"Accessibility event" "AXWindowCreated" "Preferences"
"Adding window" 37173 "Preferences" "net.shinyfrog.bear"

Look into the differences between the main window and the preference window, in terms of how it's instantiated, what class it uses, etc.

Thanks for the video, now the even chain is more clear to me. I'm following the check Bear's code with the altTab open route without any success at the moment, but I can tell the following

  • Bear's main window is instantiated in a standard Storyboard like the one used in the TestApp and, as far as I know, those happen on the main thread
  • Bear's main window is a subclass of NSWindow but removing the subclass doesn't solve the problem
  • makeKeyAndOrderFront on the main window is called on the main thread after a delay caused by core data initialization
  • AppKit's standard run loop is used
  • Somehow if I launch Bear from XCode often I get the window in altTab. This doesn't seem to be the case if I launch the same app bundle from Finder
    IMG_1382
  • If I put a breakpoint before makeKeyAndOrderFront in XCode the main window never shows in altTab

The last 2 points make me think something odd in the OS is happening. Especially the last point makes me wonder if some timing is applied at the OS level if a window from another app is front before the launched app is showing a window. I'm not sure how this theory applies when the app is launched from Finder but you mentioned some not-real windows triggering events after Bear's start in the video and this might be a cause (???). Either way, this alternate behavior is not really encouraging for finding a solution to the problem but I'll try to dedicate some spare time to work on it.

For the moment thanks a lot for the info, I'll get back with other questions or (hopefully) a solution.

It seems to be timing related. Maybe try running the makeKeyAndOrderFront on the main queue with a delay?

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    // makeKeyAndOrderFront
});

I'm imagining that somehow the app is not ready to publish its events when makeKeyAndOrderFront is called. Maybe if you give it artificially some time, not by pausing the main thread, which doesn't change anything here, but by scheduling the call for later, it may let the app be ready when the call happens? It's speculations of course but it's an easy test that may reveal more.

If I put a breakpoint before makeKeyAndOrderFront in XCode the main window never shows in altTab

I assume you mean "If I put a breaking, the main window never shows up after I continue the breakpoint" right? If so, it's really perplexing. Have you tried asking Apple support for help? I'm not a pro developer on Apple ecosystem, so I don't know how useful that would be, but maybe?

I assume you mean "If I put a breaking, the main window never shows up after I continue the breakpoint" right?

Yes, exactly. It was just a silly test which kinda confirmed my window+timing theory.

Have you tried asking Apple support for help?

No, and I can give it try eventually, but I think there's a chance this is a compiling/building problem. I recently updated Big Sur and compiled Bear using the new XCode 12.1. With the build I got from it, Bear's main window shows in altTab all the times running from XCode or launched in Finder (without code changes).

I have not tested on Catalina yet, but I'm sending you the build by mail so you can eventually confirm it's working as expected.

using the new XCode 12.1. With the build I got from it, Bear's main window shows in altTab all the times running from XCode or launched in Finder (without code changes).

Unfortunately, when I run this build on my machine (with Catalina), it's still not showing the main window in AltTab. I tried to launch it 5 times, and never got the main window listed.

It still seem like a data-race inside Bear since sometimes it shows, sometimes it doesn't, depending on some internal timing. Maybe the timing is impacted by the WindowServer, which means it would vary based on which other apps/windows are opened. Maybe they updated stuff in Big Sur that impacts it. It's hard to tell.

Did you try the code snippet I shared above? Maybe that would unveil something

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gingerr picture gingerr  Â·  6Comments

gingerbeardman picture gingerbeardman  Â·  5Comments

net picture net  Â·  3Comments

mfn picture mfn  Â·  4Comments

anukul picture anukul  Â·  3Comments