Copy link to clipboard
Copied
I have a plugin that really benefits from being able to press a single key to issue a multi-key sequence.
I'm doing this on WIndows using AutoHotKey, and it works great on Mac using QuickKeys, but I'd like to find a way to do it without requiring the user to purchase QuickKeys. I've been able to use Automator to define a script that issues the desired keystrokes, and tie it to the keyboard as a shortcut initiated service, and this works in Lightroom proper, but is disabled when using my plugin.
Any ideas?
Thanks,
Rob
Copy link to clipboard
Copied
So now I have:
on the fly applescript (osascript -e ... -e ... -e ...) to send various keystrokes to Lightroom on Mac - that's working great although not fully validated.
Copy link to clipboard
Copied
Do you have to enable "Universal Access" in System Preferences or can you circumvent this?
How does a real call look like?
Copy link to clipboard
Copied
Sorry I may have confused.
Original post was about getting keyboard shortcuts set up for the user, and the follow-up/reply post was about issuing keystrokes programmatically.
Regarding the former, maybe univesal access is required - dont really know.
Regarding the latter, the following code is part of the framework available at https://www.assembla.com/spaces/lrdevplugin/
It allows a plugin to send keystrokes like "p" to pick a photo, or "Cmd-S" to save metadata. There is a windows counterpart as well...
--[[
Send key string verbatim to Lightroom.
Uses applescript string passed to osascript.
--]]
function Mac:sendUnmodifiedKeys( keyStr, keyDowns, keyUps )
local scriptTbl = {}
scriptTbl[#scriptTbl + 1] = "-e 'tell application \"Lightroom\" to activate'"
scriptTbl[#scriptTbl + 1] = "-e 'tell application \"System Events\"'"
if keyDowns then
tab:appendArray( scriptTbl, keyDowns )
end
scriptTbl[#scriptTbl + 1] = "-e 'keystroke \"" .. keyStr .. "\"'"
if keyUps then
tab:appendArray( scriptTbl, keyUps )
end
scriptTbl[#scriptTbl + 1] = "-e 'end tell'"
local scriptStr = table.concat( scriptTbl, ' ' )
local command = 'osascript'
local params = scriptStr
return self:executeCommand( command, params ) -- no targets, no output.
end
--[[
Send mac-modified keystroke sequence to mac os / lightroom.
Format examples:
Ctrl-S
Cmd-FS
ShiftCtrl-S
i.e. mash the modifiers together (in any order), follow with a dash, then mash the keystrokes together (order matters).
--]]
function Mac:sendModifiedKeys( modKeys )
local k1, k2 = modKeys:find( '-' )
local keyMods
local keyStr
if k1 then
keyStr = modKeys:sub( k2 + 1 )
keyMods = modKeys:sub( 1, k1 - 1 )
else
error( "No keystroke" )
end
local keyDownTbl = {}
local keyUpTbl = {}
if keyMods:find( 'Shift' ) then
keyDownTbl[#keyDownTbl + 1] = "-e 'key down shift'"
keyUpTbl[#keyUpTbl + 1] = "-e 'key up shift'"
end
if keyMods:find( 'Option' ) then
keyDownTbl[#keyDownTbl + 1] = "-e 'key down option'"
keyUpTbl[#keyUpTbl + 1] = "-e 'key up option'"
end
if keyMods:find( 'Cmd' ) then
keyDownTbl[#keyDownTbl + 1] = "-e 'key down command'"
keyUpTbl[#keyUpTbl + 1] = "-e 'key up command'"
end
if keyMods:find( 'Ctrl' ) then
keyDownTbl[#keyDownTbl + 1] = "-e 'key down control'"
keyUpTbl[#keyUpTbl + 1] = "-e 'key up control'"
end
return self:sendUnmodifiedKeys( keyStr, keyDownTbl, keyUpTbl )
end
Copy link to clipboard
Copied
Very neat. I'll be interested to learn your experience in how this works out in your plugins.
In the past, in different contexts, my experience with keystroke stuffing (on Windows) was that it was "fragile". I've thought a bit, and here are some of the issues I've encountered in the past:
It's hard to handle dynamic application behavior. A simple example is LR's Library menu -- when a non-folder source is selected, there is one menu command (Plug-in Extras) with S shortcut key, but when a folder source is selected, there are two (Plug-in Extras, Synchronize Folders), and thus the keystrokes needed to invoke Plug-in Extras vary depending on the LR source. Since I rarely use folders as sources in LR (my workflow is not folder-based), I didn't even see this behavior until an Any File user point it out to me. In general, the developer of a plugin using keystroke stuffing would have to carefully test it out in all the different LR contexts in which the plugin might be invoked).
More complicated behavior, such as confirmation dialog boxes that only appear based on selection or application state, can be more problematic.
Manipulating dialog boxes has been troublesome for the utilities I've used. They typically have some facility for waiting until a dialog box appears, and then resuming the keystroke stuffing. But if the application doesn't use the standard Windows toolkits (and at least some Adobe applications don't), the utilities may not be able to find the dialog box by name. So then you have to program in a delay in your macro. If you make the delay too short, the macro will fail. If you make it too long, the user has to wait. And if the user starts typing during the middle of the macro execution, you'll get unpredictable results.
A lot of apps don't follow the Windows conventions and don't fully implement the standard tab, cursor key, and enter semantics (again, I've experienced that with Adobe apps). While the utilities allow you to use relative mouse coordinates to "move" the mouse and make mouse clicks, that's incredibly fragile, since the app window could have different layout each time it's invoked.
Despite all this, I've used keystroke macros to automate routine tasks in Photoshop Elements Editor (which disabled the action recording of full Photoshop) and Photosohop Elements Organizer. But they were not entirely reliable. But it may very well be that the uses you're envisioning for LR plugins will be straightforward and robust enough.
Copy link to clipboard
Copied
John,
Thank you for pointing out some of the "gotchas".
I agree that keyboard stuffing is not a panacea, to say the least.
That said, it can be a potential solution when there are no other alternatives.
Some things:
However, there are cases where they may also work just fine:
Summary: Consider alternative work-arounds first, and if none seem better, then use with caution, test well, and document any gotchas for the user.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now