How to retain modifier keys through a menu simulation

I have a bunch of external plugin scripts for Finale music software that are invoked from a menu via KM macro palettes. Some of these scripts detect modifier keys (shift or option) to trigger different behaviour when invoked, but using KM "Press & Hold Modifier" before the menu call still isn't recognized by the plugin. (It works fine during a real manual menu selection). Is there another way I can convince the plugins that a modifier key is being held down, or is some alternative menu behaviour possible in future versions?

This thread may interest you.

Thanks noisnell. The keystrokes don't help. AppleScript needs to be called before and after the menu action ("down" then "up") but for whatever reason still isn't recognised as a "held" state by the target software in the middle.

Just to be sure, did you test that the AppleScript works elsewhere (type a capital letter, for example)?

Good thought, but yes - the program responds as it should to a simple keystroke produced by AppleScript.

Trigger the menu item with AppleScript GUI scripting?

The trick is that those "optional" menu items are always available to System Events -- you don't need to simulate the Shift key modifier. You just need to use the correct menu item name, which is whatever shows when you hold the Shift key down while the item is visible.

Easy example -- Safari's "File"->"Share"->"Email This Page" becomes "Email Link To This Page" when the Shift key is down. So:

tell application "System Events"
	tell process "Safari"
		set frontmost to true
		click menu item "Email Link To This Page" of menu of menu item "Share" of menu "File" of menu bar 1
	end tell
end tell

Change names to suit your app and menu choice and it should work.

Thanks for the thoughtful suggestion Nige, but that isn't what's needed here. It's not the name of the menu item but the response of a PDK plug-in that responds differently depending on the presence of a modifier key after it's been invoked from the menu. Even surrounding the "tell process" with "key down option" and "key up option" doesn't work.

Yet it works correctly if the menu item is selected manually with a held modifier key.

Gotcha. Did you try including the key down/up in the above AppleScript? Using the same example:

tell application "System Events"
	tell process "Safari"
		set frontmost to true
		shift key down
		click menu item "Email Link To This Page" of menu of menu item "Share" of menu "File" of menu bar 1
		shift key up
	end tell
end tell

You may need a slight delay before the "key up" command if the plug-in's a bit slow to respond. But I'm afraid I can't think of anything I have that I can test this on...

I"ve tried precisely that script, with a half second delay before the key up, without success. It's a mystery! Also a slightly different version using "action AXPress" instead of click menu, but this tends to freeze my computer with the shift key irrevocably locked down - not sure why.

Is it actually triggering the menu item, but without the modifier being passed?

And yes, a recommendation born of many stupid errors -- if you are trying an AppleScript with a "key down" step, always remember the "key up" and always have another tell application "System Events" to *X* key up script ready and waiting to go.

Of course, I forgot again this morning, got the click line wrong, the key up wasn't processed, and I spent the next 5 minutes trying to get the damn shift key lifted :man_facepalming:

Finale has a free demo. I've never used it before, but if you've an example of a plug-in (or instructions on how to instal one) that differs in behaviour when triggered with and without the Shift key down then I'll happily poke around...

Thanks for such thorough help. It's quite a process installing the plugin package and understanding how it all works!

It's called RGPLua - installation instructions are here and a suitable (plain text) script is here which you need to save and copy to inside the 'Lua' folder you just created.You then call the script from within Finale at Plug-ins > Lua.

If you call that script without modifiers it opens a setup dialog. With shift or option held it bypasses the dialog and just acts using the last parameters. I need the action scripted because I have over a hundred scripts that are called from a suite of KM macro palettes.

Back on the ranch, this is the best AppleScript I can come up with, that (finally!!!) encloses the problematic menu call in a "try" block.

tell application "Finale" to activate
tell application "System Events"
	key down option
	tell application process "Finale"
		set target_menu to menu item "CrossStaff Offset" of menu "RGPLua" of menu item "RGPLua" of menu "Plug-ins" of menu bar item "Plug-ins" of menu bar 1
			tell target_menu to perform action "AXPress"
		on error
			display dialog "menu action AXPress failed"
		end try
	end tell
	delay 0.5
	key up option
end tell

It calls the menu item in Finale fine but doesn't register the modifier key. Which is weird because in previous incarnations it's called the menu then frozen the modifier down making the computer unusable (pre "try" block). Because it was frozen at the time I can't recall the precise conditions that made the modifiers so "sticky".


My best guess is that this is happening because the plug-in script is getting the keydown status from Finale rather than as a System Event (and no, I don't know the difference!).

You might be able to do something in KM by using Image Detection on the menu items and mouse-clicks, the final click being "with Shift key down". Unfortunately my KM trial ran out yesterday so I've no way of testing.

But I can offer you another, perhaps better, option -- make another plug-ins folder, say "Lua - Overridden", put duplicates of any script you need this "modifier key" behaviour with in there, then edit those scripts to make the modifiers test always evaluate to "true". As an example using the script you linked, comment out line 78 and add a new line below that: if not true or dialog_result ~= finale.EXECMODAL_OK then.

Showing that in context, lines 75-80 of the script would then be:

function cross_staff_offset()
    local modifier_keys_pressed = finenv.QueryInvokedModifierKeys and
            (finenv.QueryInvokedModifierKeys(finale.CMDMODKEY_ALT) or finenv.QueryInvokedModifierKeys(finale.CMDMODKEY_SHIFT))
    --if not modifier_keys_pressed or dialog_result ~= finale.EXECMODAL_OK then
    if not true or dialog_result ~= finale.EXECMODAL_OK then
        -- use global result values so that RetainLuaState remembers them

You can then use KM to call either your "normal" or "overridden" script as required, while still having the "normal" script behave "normally" if you do things manually.

This is based on zero knowledge of either Finale or Lua, and a couple of minutes messing around, so please -- test, test, and test again!

You're likely right about the "Finale" modifier message instead of a "System Event" message. Nothing else makes sense. And yes - the separate folder would work. But it would be simpler to use the plugin's "preset variable" feature to create a different "instance" of the same script that bypasses the dialog.

The modifier response behaviour is a recent innovation to the plugin and saves multiplying the number of script instances (beyond my 100+) - requiring yet another key macro command setup for a simple variant behaviour. I really wanted to see if there was any way to use the menu modifier behaviour from KM to increase versatility without increasing the number of unique macro commands.

It looks like it's not possible.

Not necessary -- you add the variant using a conditional action in your current macro. My thinking on the two-scripts approach was you'd be mimicking the Finale logic.

So you'd have one macro with two triggers -- say, Ctrl-C and Ctrl-Shift-C for "execute Cross Staff, choosing settings" and "execute Cross Staff with previous settings". Your macro would use an "If" action and the %TriggerValue% token to decide which Lua script to run.

It's an extra hotkey command, but it should be easy to remember because it uses the same "Shift for variant" methodology as Finale.

You speak the truth. Thanks again for your help.