Any workaround for plugins/commands hotkeys?

Since the official hotkeys support doesn’t seem to come anytime soon I was wondering if any workarounds exist in Photoshop? That don’t require to build some obscure C++ hybrid plugin with keyboard listener.
I thought making a psjs script that somehow calls a command/function/event on the panel would work however I can’t seem to find a way of communicating with the plugin.
What I tried:

  • using pluginManager to invoke a command: uxp.pluginManageris undefined in the script (maybe because enablePluginCommunication permissions can’t be set for scripts?);
  • using action.recordAction() to emit an event: I’m getting an error that recordAction isn’t supported in scripts;
  • finding the command menu ID and using it in ps.core.performMenuCommand() : this doesn’t seem to do anything;
  • adding an history step and listening for history events on the panel. This kinda worked but even an empty script with suspendHistory takes several seconds to execute?? unless I’m doing something wrong?

Anything else I could try? All this is depressing :frowning:

Closest thing I found is to register a function as a command and than record an action while running it. Than you set a hotkey for the action.

DUDE. I FOUND SOMETHING JUST TODAY. LIKE 5 MINS AGO.

You can attach a notificationListener using your plugin. So that means, you can have it play something each time some event occurs. Now, how useful is this you might ask? Very useful actually.

Create an empty action underneath a folder in your action panel. The action will have nothing. Just empty. Now, you can have it listen so that when you play that specific action only, it does something.

Let me show you my shitty code that I created 5 mins ago that works.

        await action.addNotificationListener(['play'], (event, descriptor) => {
            if (!descriptor._isCommand && descriptor._target[0]._name === 'PlayAction') {
                alert('Fucking works. I am so happy.')
            }
            else {
                console.log('Event: ', event, '\nDescriptor: ', descriptor)
            }
        })

So, basically, in this case, ‘play’ is just the event it listens to. Descriptor is the actual object when that event is captured. I would suggest console logging the event and descriptor to see what works for you but for me this works.

It just listens until I play an action called ‘PlayAction’ (Placeholder name for now) and if it does, it runs some code. Now, for some reason, each event gets logged twice, so the !descriptor._isCommand makes it only passes once.

image

Here is what I mean. No idea why. Hopefully this helps!!!

3 Likes

Thanks! While writing the topic I had an assumption that psjs scripts can be added to File > Scripts menu (or any other menu?) but it seems that I was wrong… I guess for the “”“security”“” reasons you can only call them by dropping the scripts into the app, using inside Actions or by using the File > Scripts > Browse menu which makes them useless. I don’t understand this design decision at all. So unfortunately I believe .jsx are the only plausible way of using hotkeys outside or Actions hotkeys restricted to F-keys.

I’m also digging the recorded actions option, following this topic: Action calling UXP plugin functionality example - #2 by sttk3. For example on the panel you can have

window.myFunction = async () => { console.log("triggered ) };

and in JSX you have

  var desc1 = new ActionDescriptor();
  desc1.putString(stringIDToTypeID("pluginID"), "com.panel.id"); // panel ID goes here
  desc1.putString(stringIDToTypeID("pluginName"), "Panel Name"); // panel Name goes here
  desc1.putString(charIDToTypeID('Ttl '), "Action Title"); // A title for modal
  desc1.putString(stringIDToTypeID("methodName"), "myFunction"); // name of the function to be executed on the panel;
  var desc2 = new ActionDescriptor();
  desc1.putBoolean(stringIDToTypeID("useLoader"), true);
  var ref1 = new ActionReference();
  ref1.putEnumerated(charIDToTypeID('capp'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
  desc1.putReference(charIDToTypeID('null'), ref1);
  executeAction(stringIDToTypeID('scriptAction'), desc1, DialogModes.NO);

that will trigger the myFunction() on the panel. Unfortunately it seems that most of async functions inside this top level function lock Photoshop with a modal popup. For example I can read a text file without problems within this function but calling a batchplay shows the never ending modal popup. It could be that the function should be wrapped in some obscure executeContext callback or another UXP bullshit… haven’t figured it out yet.

@M3mber, man, this is fantastic, your method worked perfectly for me, I’ve been dreaming about this for years, now I can execute any function from my UXP panel directly through shortcuts. THANKS FOR SHARING. :clap: :clap:

No worries man. I’ve always wanted shortcuts as well. However, since UXP doesn’t allow it, I tried looking for any other workaround. Unfortunately, I don’t know how to code in C++ so I couldn’t make a hybrid plugin, which according to what I read would be able to have normal shortcuts. I spent one whole evening looking through all the libraries I can use in PS and noticed the notificationListeners. Originally I was planning on having it listen to random events that are very unlikely to happen, however, then I noticed actions are also possible and here we are.

Still, I would prefer normal shortcuts, rather than the function key shortcuts I can assign to actions. Ig we need to do the most with what we have

1 Like