Activate the Window or Application With a Specific Word in Title

I'm attempting to create a macro that will either activate, or launch, Firefox with a specific profile. I'm using a plugin so that each Firefox instance has the profile name in the title, so the following macro half works to invoke Firefox using the profile only if it hasn't already been launched.

But how can I identify and activate the window/app based on the word in its title? I can't just activate Firefox because it will not necessarily show the right instance, and invoking Firefox again with the same profile results in an error because that profile is already running.

image

Use the Bring a Window to the Front action?

image

Thanks. That should work. BUT, there is something buggy, maybe with Firefox, or maybe because of multiple instances: if I only have one instance of Firefox running, this works fine. If I have more than one, it still works fine UNLESS I am viewing, or have viewed, a different instance. Then, for some reason, it doesn't detect the window title text (until I switch back to the WYRD profile and try again).

Kind of defeats the whole purpose of the macro :slight_smile:

That's what you get for playing with multiple instances of an app on macOS... :sunglasses:

There's probably a way around this, but not for certain-sure...

Run this in Script Debugger and see what you get:

tell application "System Events"
   tell (processes whose name contains "Firefox")
      return {its name, its windows}
   end tell
end tell

Hey, I didn't create Firefox! :slight_smile:

Script debugger shows the windows with the words in the title, so I'm not sure why KM doesn't see them consistently:

{{"firefox", "firefox"}, 
{{window "[FNCLL] Posts | Chris Lott (@fncll@social.coop) | Elk" of application process "firefox"}, 
{window "Library" of application process "firefox", window "[WYRD] Download | Late Night Software" of application process "firefox"}}}

No, but you are creating multiple concurrent instances of it. When you ask KM to "get the window names from Firefox" it doesn't know which Firefox you mean, and will probably use the (most recently) frontmost.

Following on from @ccstone's smart idea, try the following in Script Debugger and let us know what you get:

tell application "System Events"
   tell (processes whose name contains "Firefox")
      return {its name, its id, its windows}
   end tell
end tell

We need to target the correct instance of Firefox, and getting the "process id" of the one which has the window you want could enable that.

1 Like

Try this.

I'm not sure how well it's going to manage multiple instances of Firefox, but hopefully it's on the right track.

--------------------------------------------------------
# Auth: Christopher Stone <scriptmeister@thestoneforge.com>
# dCre: 2023/03/03 11:46
# dMod: 2023/03/03 11:46 
# Appl: Miscellaneous AppleScript, System Events
# Task: Raise a Window of a Partially Named Process by Partial Name.
# Libs: None
# Osax: None
# URLs: https://forum.keyboardmaestro.com/t/activate-the-window-or-application-with-a-specific-word-in-title/31152/
# Tags: @Applescript, @Script, @System_Events, @Raise, @Window, @Partially, @Named, @Process, @KMF, @Chris_Lott
--------------------------------------------------------

set appName to "Firefox"
set windowNameContains to "WYRD"

raiseAppWindowByName(appName, windowNameContains)

--------------------------------------------------------
--ยป HANDLERS
--------------------------------------------------------
on flattenList(theList)
   script util
      property flattenedList : theList
      property interimFlattenedList : missing value
   end script
   repeat while util's flattenedList's lists's length > 0
      set util's interimFlattenedList to {}
      repeat with currItem in util's flattenedList
         tell currItem's contents
            if its class = list then
               set util's interimFlattenedList to util's interimFlattenedList & it
            else
               set end of util's interimFlattenedList to it
            end if
         end tell
      end repeat
      set util's flattenedList to util's interimFlattenedList
   end repeat
   return util's flattenedList as list -- "as list" assures that the return value is dereferenced
end flattenList
--------------------------------------------------------
on raiseAppWindowByName(appName, windowName)
   tell application "System Events"
      tell (application processes whose name is appName)
         set windowList to (windows whose name contains windowName)
         set windowList to my flattenList(windowList)
         repeat with theWindow in windowList
            tell contents of (get theWindow)
               perform action "AXRaise"
            end tell
         end repeat
      end tell
   end tell
end raiseAppWindowByName
--------------------------------------------------------

This results in an invalid object reference, though it does refer to the proper instance of Firefox based on the name of the window it is trying to activate:

window "[WYRD] Activate the Window or Application With a Specific Word in Title - Questions & Suggestions - Keyboard Maestro Discourse" of application process "firefox"

And not sure if this helps, but the AEPrint window of Script Debugger has this:

'obj '{ 'form':'name', 'want':'cwin', 'seld':'utxt'("[WYRD] Activate the Window or Application With a Specific Word in Title - Questions & Suggestions - Keyboard Maestro Discourse"), 'from':'obj '{ 'form':'name', 'want':'pcap', 'seld':'utxt'("firefox"), 'from':[0x0,6a039fd "System Events"] } }

I just meant there is, as far as I know, no other way to use different profiles with Firefox than to run concurrent instances.

The output from your script:

{{"firefox", "firefox"}, {110446926, 111245841}, {{window "[UW] |Home - Radio Paradise" of application process "firefox"}, {window "[WYRD] DuckDuckGo โ€” Privacy, simplified." of application process "firefox"}}}

Thanks!

I'm still not sure if you want to activate just the correct instance of Firefox or a specific window in a specific instance -- if it's the latter you'll need more than just the prefix of the window name.

This should pop the right Firefox -- you could leave the prefix hard-coded or get it from a KM variable:

set theTarget to "[WYRD]"
tell application "System Events"
	tell (processes whose name contains "Firefox")
		set theList to {its id, name of its windows}
	end tell
	repeat with i from 1 to count of item 1 of theList
		repeat with j from 1 to count of item i of item 2 of theList
			if item j of item i of item 2 of theList starts with theTarget then
				set processID to (get item i of item 1 of theList)
				set frontmost of process id processID to true
				return 0
			end if
		end repeat
	end repeat
end tell
return "Not found"

If you want a specific window, set theTarget to the exact name and do the comparison using is rather than starts with, adding a couple of lines to get/target the window:

set theTarget to "[WYRD] A Particular Window Title"
tell application "System Events"
	tell (processes whose name contains "Firefox")
		set theList to {its id, name of its windows}
	end tell
	repeat with i from 1 to count of item 1 of theList
		repeat with j from 1 to count of item i of item 2 of theList
			if item j of item i of item 2 of theList is theTarget then
				set processID to (get item i of item 1 of theList)
				set winName to (get item j of item i of item 2 of theList)
				set frontmost of process id processID to true
				tell window winName of application process id processID to perform action "AXRaise"
				return 0
			end if
		end repeat
	end repeat
end tell
return "Not found"

If you'll remind me of the code necessary to launch a specific profile in Firefox, I'll take another crack at it in the next day or so.