Trigger for whenever user switches application?

Couldn't find this in the tips, via google or as a feature request, so here goes:

  • I have a script I want to run whenever the user switches to a new application.

  • Feature could be just like the conditional activation group, just that it is an "unconditional activation group" with a way to do something only once per context switch.

it doesn't matter which or how that change was triggered ( ⌘Tab, ⇧⌘Tab, btt did dit, open -a in iTerm etc etc)

The script when run is querying for which app is open, then asks a floating html5 window to open the corresponding .html for this particular app. This html has various functionality like text, icon, font and graphical resources for drag and drop, search fields, as well as a dynamically updated list of shortcuts for this app: keyboard bindings, mouse button bindings (btt), mouse gestures, named triggers, home assistant smart-home remote triggers and available actions.

I'm sorry if it's possible to accomplish this with btt already somehow, but I can't get the setup up and running other than polling every so many seconds, which isn't really the best way forward :slight_smile: thanks for a great app.

I would be interested as well actually. Maybe this is possible with a widget with a very long refresh rate but with "always run when becoming visible". Did you try that?

Found this on stackoverflow:

// Get the process ID of the frontmost application.
NSRunningApplication* app = [[NSWorkspace sharedWorkspace]
                              frontmostApplication];
pid_t pid = [app processIdentifier];

// See if we have accessibility permissions, and if not, prompt the user to
// visit System Preferences.
NSDictionary *options = @{(id)kAXTrustedCheckOptionPrompt: @YES};
Boolean appHasPermission = AXIsProcessTrustedWithOptions(
                             (__bridge CFDictionaryRef)options);
if (!appHasPermission) {
   return; // we don't have accessibility permissions

// Get the accessibility element corresponding to the frontmost application.
AXUIElementRef appElem = AXUIElementCreateApplication(pid);
if (!appElem) {
  return;
}

// Get the accessibility element corresponding to the frontmost window
// of the frontmost application.
AXUIElementRef window = NULL;
if (AXUIElementCopyAttributeValue(appElem, 
      kAXFocusedWindowAttribute, (CFTypeRef*)&window) != kAXErrorSuccess) {
  CFRelease(appElem);
  return;
}

// Finally, get the title of the frontmost window.
CFStringRef title = NULL;
AXError result = AXUIElementCopyAttributeValue(window, kAXTitleAttribute,
                   (CFTypeRef*)&title);

// At this point, we don't need window and appElem anymore.
CFRelease(window);
CFRelease(appElem);

if (result != kAXErrorSuccess) {
  // Failed to get the window title.
  return;
}

// Success! Now, do something with the title, e.g. copy it somewhere.

// Once we're done with the title, release it.
CFRelease(title);

Alternatively, it may be simpler to use the CGWindow API, as alluded to in this StackOverflow answer.

I already have this integrated in BTT but currently not exposed as trigger. I'll add a way to do that soon.

Currently the closest you could come would be to create a conditional activation group for every app you need this for, then use the "Conditional Activation Group Activated" trigger in the "Other" section.

However I think I'll be able to add the requested feature in a few days, so maybe worth waiting.

1 Like

What can I do and how do I use the "other" section?

What do you want to achieve? :slight_smile:

With "other" section I refer to this: