Intercept many hotkeys and conditionally insert an action before them

I don't recall ever saying "KM can't do that," because I usually can find a way, but for that statement I don't think it's possible. There are many people here smarter than me, and maybe they can think of a way to do that. Basically, it sounds like you are trying to replace the KM Engine's mechanics with another kind of layered engine to override the real engine's mechanics. That's asking too much.

What I believe is possible is what you describe as not preferable, which is "adding a ton of hotkeys to the trigger conditions of a 'frontmost window validation' macro". Maybe then.

In any case, I have a question. When you talk about hotkeys, are any of those hotkeys "regular characters" like A-Z, or are they simply limited to function keys? I don't think you specified. That might make a difference to the solution. This is important, I think.

I have a totally different approach that might satisfy you. I'm trying to think outside the box. Instead of trying to solve the problem by going to a ton of work to interpret function keys, why don't you just have an annoying noise or beep sound off whenever that Properties window appears? That's how I would address this issue. I think that can be done with perhaps a single action in a single macro.

1 Like

To add on to what @Airy said, the above seems problematic to me: These two trigger conditions are at odds with each other. You can trigger a macro when a focused window title changes, or you can trigger a macro based on detecting hot keys. But you can't have a two-stage trigger, where after detecting a focused window change the macro is then trapping all keyboard input ... at least I don't think you can.

I tried a quick trial macro, where the trigger was "The focused window title changes." The macro had but one action, Pause until the key state changes, with the pause ending when "the pressed keys change."

I launched it, switched apps, and hit Command-A to select all. The macro ran right until I pressed Command-A, at which point it ended and my Command-A was sent to the foreground window.

I tried the same thing with an Until loop, waiting until a Key Condition changed. Same problem: The key goes to the window before Keyboard Maestro ever sees it.

I can't think of a way you could start trapping all the keystrokes after the focused window changes. Based on my quick trial, as soon as the event occurs that can make the macro proceed, the keys are sent to the app, and aren't seen by Keyboard Maestro.

Maybe there's some other tricky way around it, but given that the keys seem to get passed immediately, I can't think of one—I think your multiple triggers approach might be the only way.

Along @Airy's line of thinking, you could have Keyboard Maestro put a bright red box up in the corner of the screen whenever that window is frontmost ... or change your desktop picture ... or some other visually noticeable thing.

-rob.

1 Like

Hey, you could even use the KM action "Highlight" to place a big blue box (or even a little animation) over the new window, and also include a Beep sound. It wouldn't be hard to get the Highlight box to match the window's position. My only grip here is that the Highlight action displays only the colour Blue. I would prefer a choice of colours, like you suggested, Red.

1 Like

It is never a good thing to intercept keystrokes, and then resend them.

This is because keystrokes are handled by a queue in the system, and so if you take things out of the queue and then add them back in to the queue they will get out of order with other events (any keys that aren't handled for example).

You could perhaps use the Focused Window trigger to detect when the Media Item Properties window is focussed and then do something to alert you to the danger (Speak Text for example), or even immediately deactivate it by focusing another window (perhaps have a macro that temporarily disables this macro and focuses the Media Item Properties window to access it when you are prepared?).

1 Like

Here's an interesting one-line macro that gives you a slight animation around any new window or application that wakes up. It triggers upon "an app activating" or "any window changing title" which captures most kinds of apps and most kinds of windows.

It's quite cool, however I think I'd rather see a different colour than blue, a different border size, and a different border width. In that case, I probably should be looking at modifying this and use Create Custom HTML action.

Highlight New App or WIndow (v11.0.2)

Highlight Location.kmactions (694 B)

Keyboard Maestro Export

1 Like

Good ideas and info. thanks!

and yes, some of the keys I'd want to filter would be single keystrokes like space, return/enter, directional arrows, tab, and a few others.

and since i work on audio full time, it would get annoying to have a sound for that window getting focus since i have it open a lot of the time for a number of editing steps. however, just figuring out how to monitor and trigger a macro on frontmost/focused window changing to that one (preferably without having a constantly-running loop checking it every second, since that would cause other issues, not to mention a performance hit) would be great.

and i know the concept i came up with is pretty challenging, maybe not even possible with KM. Just wanted to toss it out there to see if there might be a way to make it work, since I can think of some other areas where it would also be useful to apply a similar re-routing/changing window focus before passing keystrokes.

and, if nothing else, i figured it would be a fun challenge for some of the real gurus in this forum. :slight_smile:

just

I love a challenge. But as two of the real geniuses said above, this one isn't possible.

Well then maybe you could settle for a visual indicator. The blue box code I created for you above is interesting, but I'm not satisfied with it myself, so I'm working on another visual solution. Right now I'm making the window or the screen briefly flash a light pastel red, and I'm testing it to see if I like it. However the Custom HTML action that I'm using is quite challenging for me, so I'm struggling to debug it.

thanks for the response! and yes, that's what i was able to get working as well: waiting for key input that gets passed to the app.

however, I did once run into an issue unintentionally when sending keys from an applescript running within a KM macro. the keystrokes sent from applescript were triggering a macro in KM. So i was thinking it might be possible to use applescript & system events to do the catching and sending keystrokes instead of KM. Then it should be possible to have them triggering other stuff in KM or the target app depending on how the script is written, and whether the keys are sent from applescript/system events, or assigned as a variable to KM, and sent from KM engine.

however, i think the visual indicator you mentioned might be a good stopgap solution for now. is it possible to draw a thick red border (maybe 10 px) around a window using KM and not steal focus?

ideally, when i'm working really fast, it'd be preferable to always have certain keys automatically switch back to the main edit window before being sent to the app, just to avoid needing to hit an extra key or click it manually every time after entering something in media item properties window.

but until i can figure out a way to do this without creating conflicts for a number of existing keystrokes/hotkeys, or needing to add an action to every one of them to check and handle the focused window condition (thus also significantly slowing the performance of some of them that i regularly use in rapid succession), at least the big red visual indicator should help me avoid having the wrong window focused when trying to perform certain actions.

now the question is: which action do i use in KM 9 to draw a colored border around a focused window, or maybe (if possible) change its color?

Thanks, Peter. Good points as well.

And while i do have a number of macros that will successfully send their triggering hotkeys to an app as a result of an if > otherwise condition, i understand the concern over queueing and execution order.

the big problem with the solutions you mentioned is that i'm quite regularly quickly switching between the media item properties window and other windows while working on sounds, so i don't want something changing the focus from it in most cases - just when hitting certain keys when that window is focused, which should be triggering stuff in the main window (and i have some of them set as global hotkeys that normally work this way), but in some cases, won't.

here's an example: spacebar normally will start/stop playback of the main transport. it's set to global, so will work with any other window focused. however, when editing text fields, i still want to use the spacebar to enter spaces, so I don't have it set to "global and ignore text fields" (would perform the assigned "play/stop" action even when typing in a text field). and if i accidentally switch to the media item properties window, i could hit space and replace the text of whichever text field is selected, or check/uncheck a box in the properties of any selected items. then, if i hit enter afterwards, or change something else in the properties intentionally later and click apply/ok, then that accidental change gets committed.

i suppose there may be no way around it other than adding a new macro with the necessary conditional check for window focus, blocking input from certain problematic keystrokes being sent to the focused app (curious what the best way to do this would be?), and triggering an action to instead switch focus to the main edit window when any of those keys are hit in that case. then i could just as easily hit the same key(s) again with the correct window focused - probably safer/simpler than intercepting and buffering them, and adding the window focus switch in between.

Cool. I wasn't aware of this one. Thanks! :slight_smile:

Nice! Please do share what you come up with if/when you get it working to your satisfaction. thanks!

One solution is the code I uploaded for you above. But the blue frame wasn't noticeable enough for my taste. I'm working on a cool solution that colours each open window with a red tint for one second. The problem I'm having is that I struggling to pass the correct values for the location of the window to the Custom HMTL action. There are other people here who are much better than me with that action, so maybe if I paste the code that I have so far, they might be willing to patch it. I think I'll post it here in a minute in the hope that someone else can fix it, because I'm struggling and I know others have the skill to correct it.

EDIT: I'm getting close. I'm not going to give up yet. I want to solve this.

Okay, my solution should be working now, but there's a problem that's causing it to fail. The reason it's failing is explained below. I suppose I could come up with another solution, but before I do that, I want to find out if this clean approach can be fixed. Maybe someone can tell me how to fix this.

The simple problem seems to be that the Custom HTML action seems to be rejecting a variable token in its Text field. I was not expecting this. In almost any other action I know in KM, if the field is labelled with a "T" at the right hand side, you are allowed to place a variable in it. But in this action, it seems you are not. I don't understand that limitation for this action. Is there anyone here who can confirm or refute my observations, or better, explain why this action does not support variable tokens?

In the Text Fields page on the KM wiki it says "most text fields allow the use of tokens"...

https://wiki.keyboardmaestro.com/Text_Fields

And yet in the Custom HTML action documentation it does not say that this action does not support tokens:...

https://wiki.keyboardmaestro.com/action/Custom_HTML_Prompt

And now, as I'm testing other actions, I'm finding quite a few actions whose text fields do not support tokens.

Here's the text:

<!DOCTYPE html>
<html>
<body style="background-color:rgba(255,15,15,0.05);">
<body data-kmwindowid="$KMVAR_LocalWindow" ... >
<body data-kmwindow="%Calculate%WINDOW(Left),WINDOW(top),WINDOW(width),WINDOW(height)%">
<script>
async function kmResize() {
}
</script>
<body onload="kmResize()">
</body>
</html>

P.S. True, I didn't delete the temporary file after using it. This will be fixed when the macro works. Also, if you're wondering why I need a variable filename at all, it's because the user may invoke this macro multiple times before the previous instance is finished. I can see a fix, but the fix is very ugly and I don't want to do that if I don't have to.

If you look at my The Decision Maker macro, the method I use to make that prompt supports tokens in the variable that builds the HTML—I just tested it to be sure, adding a line that showed the window's location via tokens, and it worked as expected.

I build the HTML in a variable, where you can use tokens and Keyboard Maestro variables at will. Then, when it's time to display the box, it's done using a bit of Javascript:

I don't know if your solution requires using the file, but even if it did, if you read it into a variable first, then use the Javascript to display it, that should force the tokens to be interpreted.

(I am far from an expert on any of this subject matter; this is just what I figured out when I was trying to get variable and token replacements working with Keyboard Maestro variables in HTML code. There's probably a much better way to do this, but this works for me.)

-rob.

Thanks, I'm a little too tired to examine it now.

I think I forgot to mention there is a minor bug in my code above. I'm using a $KMVAR when I should be using a %Variable%%. But it doesn't invalidate my question.

There's a difference in KM between "text fields" (which have a little "T" in the top-right corner when active) and "fields in which you can enter text" (which don't). It looks like the field in the "HTML Prompt" action is a "script field" and, as such, isn't processed for text tokens (see bottom of Text Fields [Keyboard Maestro Wiki]).

Noodling around...

What you could do is throw a transparent "Custom HTML Prompt" over the "Media Item Properties" window. That would let you see the properties but you wouldn't be able to click on anything -- and a quick test with KM Editor windows suggests you can't type into active fields on a "covered" window, either.

Excuse the shonky HTML, but something like:

<html>
<body data-kmwindow="WINDOW(0,Left),WINDOW(0,Top),WINDOW(0,Width),WINDOW(0,Height)">
<p style="font-size: 120pt;" onclick="window.KeyboardMaestro.Cancel()">Click me to edit!</p>
</body>
</html>

...in an async "Custom HTML Prompt" action, in a macro that's triggered whenever the "Properties" window gains focus, could do it. For now you just click "Click me to edit!" to close the HTML window and access the previously-covered target.

It could, obviously, be made much prettier!

I'm not sure how this could solve the issue. i don't need to prevent the window from being clicked. It can be made frontmost/keyboard-focused either by app shortcut (F2), or by using the macOS shortcuts to cycle through app windows (⌘+` and ⌘+⇧+` ). The issue is, when the window becomes frontmost (which would trigger the macro), pressing keys like spacebar, enter, tab, or arrow keys will change already-focused fields in the properties window.

I'm skeptical and suspect this would still happen even if there's a transparent HTML window in front of it. But I'll give it a try later to see for sure. thanks!

I'll admit that I was very surprised! But it does make sense -- when an HTML Prompt appears it has focus, so any keystrokes will be directed at it rather than the window it is covering, but because it is a window of a background-only app the "frontmost app" is still the original, so ⌘-key combos like ⌘` still work.

It seems to work with TextEdit, so it might work for you.

Here's a demo macro. You'll need to set up three fresh documents in TextEdit, one of them "Untitled 3" (or change the "If..." condition to match one of the window names). Type away in one window, ⌘` to "Untitled 3", and the HTML prompt should pop up and nothing you type will hit the "Untitled 3" window. ⌘` to another TextEdit window and you can carry on typing as before.

One gotcha is that, as written, you'll get a new HTML prompt every time you switch back to "Untitled 3". If this does do what you want then that should be solvable, probably by closing the Prompt window when the "covered" window is no longer activated.

HTML Masking Prompt.kmmacros (2.6 KB)

Image

This is outside the scope of this forum, but …

My understanding is that you never want certain keystrokes to trigger changes to media item properties. If so, why don't you just change or delete the keyboard shortcuts for the relevant commands in Reaper?

(For those who don't know Reaper, it's extremely customizable. If I were faced with a problem like this, I would attempt to fix it within Reaper before attempting anything complicated in KM.)