5 Replies Latest reply on Nov 18, 2010 1:51 PM by areohbee

    Mac Question: Anybody know how to get services or keyboard shortcuts to work in a plugin?

    areohbee Level 6

      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?




        • 1. Re: Mac Question: Anybody know how to get services or keyboard shortcuts to work in a plugin?
          areohbee Level 6

          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.

          • 2. Re: Mac Question: Anybody know how to get services or keyboard shortcuts to work in a plugin?
            sschultz lr3

            Do you have to enable "Universal Access" in System Preferences or can you circumvent this?

            How does a real call look like?

            • 3. Re: Mac Question: Anybody know how to get services or keyboard shortcuts to work in a plugin?
              areohbee Level 6

              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 )


                  scriptTbl[#scriptTbl + 1] = "-e 'keystroke \"" .. keyStr .. "\"'"


                  if keyUps then
                      tab:appendArray( scriptTbl, keyUps )


                  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.



                      Send mac-modified keystroke sequence to mac os / lightroom.
                      Format examples:


                      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 )
                      error( "No keystroke" )
                  local keyDownTbl = {}
                  local keyUpTbl = {}
                  if keyMods:find( 'Shift' ) then
                      keyDownTbl[#keyDownTbl + 1] = "-e 'key down shift'"
                      keyUpTbl[#keyUpTbl + 1] = "-e 'key up shift'"
                  if keyMods:find( 'Option' ) then
                      keyDownTbl[#keyDownTbl + 1] = "-e 'key down option'"
                      keyUpTbl[#keyUpTbl + 1] = "-e 'key up option'"
                  if keyMods:find( 'Cmd' ) then
                      keyDownTbl[#keyDownTbl + 1] = "-e 'key down command'"
                      keyUpTbl[#keyUpTbl + 1] = "-e 'key up command'"
                  if keyMods:find( 'Ctrl' ) then
                      keyDownTbl[#keyDownTbl + 1] = "-e 'key down control'"
                      keyUpTbl[#keyUpTbl + 1] = "-e 'key up control'"
                  return self:sendUnmodifiedKeys( keyStr, keyDownTbl, keyUpTbl )

              • 4. Re: Mac Question: Anybody know how to get services or keyboard shortcuts to work in a plugin?
                johnrellis Most Valuable Participant

                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.

                1 person found this helpful
                • 5. Re: Mac Question: Anybody know how to get services or keyboard shortcuts to work in a plugin?
                  areohbee Level 6



                  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:


                  • Keystrokes are best directed at Lightroom proper - they can not be directed at edit fields and as you've pointed out, they will fail if Lr dialog boxes get in the way (as presently programmed by me anyway).


                  However, there are cases where they may also work just fine:


                  • Plugin has been invoked in Library mode, and no dialog boxes have popped up - so far things like "p" for pick and Ctrl/Cmd-S for saving metadata have worked for me.


                  Summary: Consider alternative work-arounds first, and if none seem better, then use with caution, test well, and document any gotchas for the user.