Focused window's title changes/d triggering repeatedly

Trying to make the Terminal window automatically full size when running certain programs, and then resize automatically to my preferred window size and position. I had trouble with this previously and am revisiting it again. I thought this should work, and it does, but for some reason the macro is being triggered 20 times or more. I tried adding a semaphore lock, but it doesn't seem to be doing anything (not sure I fully understand them yet).

Macro image

Terminal- full size window for btop, castero.kmmacros (7.6 KB)

[edit] Forgot to mention I tried both The focused window's title changes and The focused window's title changed triggers with the same result, although I have now read the wiki on the difference between them. The uploaded macro has changes but it should be changed.

I suspect I know the reason (there's always a chance that I'm wrong.) If you look closely, the title of a Terminal window includes its size (eg, 80x24). When you resize the window, that part of the title is likely to change (eg, 90x30) and that will re-trigger the macro to resize again, in a loop.

If I'm right, this is a funny error. I smiled.

There are probably ways to fix this. If you show your terminal window in a screenshot, I may be able to give you a decent solution.

Of course you are right! I must be blind to the obvious today, how embarrassing.

Standard Terminal window size/position

Full size Terminal window

[edit] Although, I thought this was exactly the sort of thing semaphore locks were supposed to be good for?

[edit2] Also, it still triggers about 4 times when the window title changes and the size has not been changed (or the size should not have been changed), which seems strange.

[edit 3] The macro triggered 4 times when I launched wordle (no resize) and then twice again when wordle closed after solving (no resize).

Example

[edit 4] Interesting. I tried tracking the window title changes. Launching wordle changes the window title twice, so it's curious that the macro is triggered four times.

Window title changes

[edit 5] Okay, yeah. The changing window size has this weird cascading name change :melting_face:

Cascading...

Semaphores are meant to temporarily DELAY a macro from running at the same time as another macro, or at the same time as another copy of the same macro. If you use their timeout feature, the DELAY turns to a CANCEL of the macro.

I can see why you might think that a semaphore might fix your problem. You are thinking that secondary calls of the macro could be "cancelled" if you use a semaphore correctly. But think about this: if the first trigger of the macro finishes before the second one starts, (which will probably be the case) then that would make using semaphores impossible here.

I think there are better solutions. Let me consider them, but I'm making lunch at the moment. Others might chime in before I get back to you.

1 Like

Here's a version that might work a bit better - note that I changed the dimensions on the exception size to 800x600 for testing:

Terminal- full size window for btop- castero - rg edit.kmmacros (8.2 KB)

Changes:

The key change, I think, is the new action that disables the macro immediately after it's triggered. This prevents it from launching again until it's completely run through—it won't affect the current operation, as that's already under way.

I changed all the window title matching to regular expressions, so they only pay attention to the bit with btop or castero in it. This probably isn't required, though.

Finally, the last step re-enables the macro so it's ready to go again the next time a window resizes.

This may not be ideal, but it seemed to work well in limited testing.

-rob.

1 Like

Amazing, I didn't even know this was possible. For me though, it's only partially working. It will make the window full size, but it won't resize it back down again after. The macro is definitely triggering, but it doesn't move and resize, and there are no errors.

[edit] Also now noticing a side effect of this logic: it's impossible to zoom the front Terminal window manually because it automatically resizes to the default. Hm.

[edit2] Oh god, and just normal usage is triggering the macro so much. :confused: Now I remember why I've been used the typed string trigger this whole time. More thought is needed still.

Okay, whoops. The macro was triggering like crazy because I inadverently had both macros enabled at the same time and somehow cross-referencing each other (I'm dangerously unobservant today, wow). It's still triggering with every window title change (obviously), but it's not nearly as bad as it seemed for a moment there. I also thought the logic could be tidied up a bit with an if-statement rather than a switch, since the window should either be full size or my preferred size, there's no reason to have a separate condition for each name.

For whatever reason, the window moving/resizing is more consistent for me using the Terminal menu actions instead of Keyboard Maestro's.

The side effect of not being able to manually zoom the window without the macro reverting the resize persists, and I'm still thinking about it.

macro image

Terminal- full size window for btop, castero - rg edit copy.kmmacros (21.3 KB)

Why don't we back up to the beginning: Can you explain exactly what it is you'd like your macro to do, just in terms of describing the task and conditions?

-rob.

Sure. When working in the terminal, I typically want the terminal to be half the screen size (103x63), positioned on the left. Then when I launch either btop or castero, I want that terminal window to be automatically made full size (not full screen, just maximum screen size on the desktop). And when I quit either of those running programs, I want the terminal window to return to being 103x63 and positioned on the left of the screen.

It seems like it should be so straightforward, doesn't it?

Thanks ... if you manually resize and move the window, I assume you want it to remain at its new size and location? Would you ever move and resize the window if it had btop or castero running? Or will they always stay full-screen-covering?

-rob.

I do sometimes need to manually resize or move a (103x63) window, but I never need to manually move or resize a full size btop or castero window.

Alright, I think I may have solved for all cases now. It's a little messy and I suspect it could probably be simplified if I knew anything about regex, but it works consistently without any side effects (that I've found thus far). Is there a way to do the regex search for both terms in one action?

macro image

Terminal- full size window for btop, castero - rg edit copy copy.kmmacros (15.7 KB)

After playing with this for a while, I think I'd solve it completely differently if I were doing this for myself: I'd stay away from watching the window title changes, because it's so often and complicated to get the right ones. Instead, I'd create custom macros for those apps I wanted to have treated specially. Here's one for btop:

Download Macro(s): Launch btop.kmmacros (21 KB)

Macro screenshot

Macro notes
  • Macros are always disabled when imported into the Keyboard Maestro Editor.
    • The user must ensure the macro is enabled.
    • The user must also ensure the macro's parent macro-group is enabled.
System information
  • macOS 14.7.1
  • Keyboard Maestro v11.0.3

The macro is started by typing zbtop in Terminal (so you can type btop elsewhere, i.e in a text file, without launching the macro). After typing the trigger string, the macro saves the current window size, resizes the window to fill the screen, and launches btop. It then pauses until btop is active (so it doesn't immediately go to the next step), and then pauses until btop isn't active.

When you exit btop, the window resizes back to its original size and location.

I realize this is completely different than what you've done, and you may not like it at all, but it's how I would do it. Why? It simplifies the task, and prevents any unexpected Terminal window moving or sizing. It also prevents a macro from running hundreds or thousands of times a day as Terminal windows are resized.

It's also really easy to set up for additional apps: Duplicate the existing macro, rename it, change its activation trigger, and then just edit the green box to reflect the app you want the macro to affect. That variable is used in the macro to launch the app and check the window title, so it's the only box you need to edit.

[I see our replies crossed; I'll look at what you've done later.]

-rob.

As it happens, this is exactly how I've been doing it all along, more or less. I have it in a group available only to terminal. But it would run into issues sometimes. Like if it was open for too long, the macro would cancel or timeout even though it shouldn't have, or sometimes switching terminal windows would make it resize when it oughtn't've. Though, I expect your version is better done than my original.

my original macro

Dealing with these issues periodically with btop wasn't too big of a deal since I don't usually need it open for very long, but castero is my new podcast player which will be open for long stretches, so I wanted to try to solve for everything without relying on a Pause until action.

Thanks, I really appreciate all your help!

I looked at the macro, and gave it a bit of a test. It works to resize my window when I launch btop, but it doesn't resize it back down when I quit. But that might be related to the window size check you have.

There is:

.*?btop.*$|.*?castero.*$

That searches for btop or castero in the title.

Interesting…I wonder if there's a timeout that might hit after hours of a macro being paused?

-rob.

Possibly it could be Sonoma vs Sequoia. I was recently forced to upgrade.

Excellent, thanks! That allowed me to simplify the macro a great deal.

Now, I only need a single try/catch to check for btop or castro, and presumably I can easily add new terms with |.*?newterm.*$. If it finds either in the front window, the while loop checks the window isn't full size and resizes if necessary. Otherwise the catch checks if the window is full size and resizes accordingly.

This is working consistently for me on macOS 15.1.1 Keyboard Maestro v11.0.3 to make the appropriate windows full size and 'default' size every time. Additionally, I am able to freely manipulate and move any 'default' window without triggering the macro and having it resize unexpectedly...admittedly though, I'm not entirely sure why because I would expect the catch logic to make it my 'default' size, but it doesn't.

Macro screenshot

Terminal- auto-adjust window for btop, castero.kmmacros (7.5 KB)

I think it was probably due to the macro 'finishing' when switching terminal windows. Sometimes it would resize, other times it wouldn't.

Here's a version that doesn't remain running, and it's incredibly easy to add more apps:

app-Terminal Macros.kmmacros (40 KB)

There are two macros in this set:

Launch screen-size window processes: The macro that launches the apps you want to run in filled-screen mode. Here's what it looks like:

Check process status: A macro that checks to see if a filled-screen app is running.

Note: Do not enable the Check process status macro when you import these two macros; it's enabled and disabled by the macros themselves. You do need to enable the other one, though.

How to use

This solution works for any app you set up in the Launch screen-size window processes macro. It's currently set to handle both btop and castero, but adding another app is this simple:

  1. Add a new Typed String Trigger for the app you want to run. Assign it a shortcut with one non-meaningful first letter (I used 'Z', but it can vary by shortcut, i.e. bbtop and ccastero would be fine), followed by the actual name of the app you want to run.

And that's it, there is no step two.

How it works

The macro strips off the leading character and saves the app name to a global variable, launches the app, saves the current window size, and then resizes the Terminal window to fill the screen. It then pauses to make sure the app has launched, and then enables the process check macro.

The process check macro runs every second (when Terminal is frontmost), and all it does is this:

The process check macro sits idle until the Terminal's window title changes. Once that happens, it checks if there's a stored Terminal window size and the Terminal title does not contain the name of the app.

If both conditions are true, it means the fill-the-screen app has terminated, so the Terminal window size and location are restored, the two global macros are deleted, and then the check process macro disables itself—so it's only active when you have a filled-screen app running.

This solution should avoid the timeout issues you were experiencing, as there's no long-running macro: As soon as you launch a listed process, the screen resizes and the macro quits. And there's nothing running every time you resize a window.

Yes, there's a new macro that runs every second, but in my testing, it takes under 0.04 seconds to run, and I couldn't see any CPU hit at all while it was running.

This is the thing I love about Keyboard Maestro: There are so many ways to solve a problem!

-rob.

Incredible! I never would've thought to solve it this way. The one I made is working consistently and reliably...except I don't actually understand how it's working exactly when I want it to and not working exactly when I don't want it to...feels unsettling like magic :sweat_smile:. So, I'll give definitely give this new macro of yours a try and see how it goes. Thanks again!

Oh jeez, I must've been really tired when I wrote that yesterday. Please use this version instead if you're going to try it—it's so much better:

app-Terminal Macros.kmmacros (40 KB)

(I also replaced the link in the first post of this macro.)

The change? I—doh!—realized I could use the "focused window title changes" trigger on the watcher macro. No need to have it run every second, and no need to wait that portion of a second for it to kick in.

So the watcher macro now triggers whenever the focused window's title changes. But it's also only activated when you run one of the apps in the launcher macro, so it'll sit disabled the rest of the time.

After several iterations, this is exactly the one I'd use on my Mac: It doesn't have to watch every single window resize to see if it needs to work or not, and it no longer runs a macro every second to keep an eye on things.

-rob.

1 Like

Hm. The issue with this is that switching to a different Terminal window disables the watcher macro, so it isn't able to see when the Terminal window with the running app changes. I fully understand if you don't want to spend anymore time thinking about this problem, but I just wanted to mention it.