Keyboard shortcut to run a PSJS

Hello! :slight_smile:

Is there any way of executing a PSJS using a keyboard shortcut? With JSX and JSXBIN we could either:

  • use the <javascriptresource> hack as mentionned in here so that then we could add a keyboard shortcut or call it from an action with a keyboard shortcut.
  • have our script in the Presets/Scripts folder and then it’d list in the File > Script, and then add a keyboard shortcut on the script that’s in there or call it from an action.

With PSJS, none of these seem to work. Is there an alternative solution I missed? To me that was really the main interest for scripts :upside_down_face:

1 Like

Any update on this by any chance? :smiling_face_with_tear:

FWIW this is not a UXP question really, but it is relevant for beginners like me. C:\Program Files\Adobe\Adobe Photoshop 2024\Presets\Scripts\ will likely lead you to a protected folder (in windows) that once a JSX file is placed in, on reload of Photoshop, you should see it in the File Scripts Menu and be able to hotkey it as normal in photoshop.

That said, the other great thing about this, is the psjs compatible syntax like UXP uses is available, including the requires directive you see, which as I understand it, is not otherwise available to JSX files (or psjs) run through Photoshop without being specifically called in the file >scripts >browse menu.

As you build your UXP app or even your workflow, its nice to be able to put (more or less) future proofed scripts in there ( I say this mostly having generated alchemist stuff but even sometimes the “copy javascript” from the actions panel didnt seem to work out of the box when running a jsx).

I’m not sure we talk about the same thing here.

I’m not talking about UXP, per se, but PSJS files. I have scripts (relying on UXP) I created for panels, but some retouchers I work with want to call these scripts using a custom keyboard shortcut. As far as I know, it’s impossible to add keyboard shortcuts to a panel at the moment, and you cannot listen to keyboard events outside of a panel. So, the only possibility is to create PSJS script files, relying on UXP, to avoid having to recreate everything with CEP in a JSX script file.

However, while you can add a JSX/CEP file in the Photoshop script folder, either on MacOS or Windows, and it will show in the File>Script menu of Photoshop, or using the hack, you can have it in the Filter menu, and then give it a keyboard shortcut, PSJS won’t show anywhere. The only solution so far is to create an action that calls the PSJS script and then give that action a keyboard shortcut. The only issue here is that the actions have a minimal choice of keyboard shortcuts and can only be called from a function key…which on certain keyboards is far from practical.

So, what I’m asking is, am I missing something? Is there any other way to call a PSJS file using a truly custom keyboard shortcut? Is it something that is planned for the future?

I think that for now it is not possible to do what you ask, psjs files unfortunately are not displayed in the photoshop menus as happens with jsx files, so it is impossible,
perhaps you can create a button in the uxp panel that calls the psjs file but not associate a keyboard shortcut.

I use AutoHotKey with COM to call actions, which I don’t know if that helps you (and won’t if your guys are on macintosh), but it lets you remap anything really regardless of what Photoshops limitations are in the keyboard shortcuts menu. I am gradually updating my v1 to v2 code but here is code in v1, kind of an idea of how you might go about making a hotkey to use Photoshop’s COM to call an Action, which might circumvent the issue you are having on the keyboard shortcut limitation, but note this is AHK v1 syntax (not difficult to convert to v2 though just the class implementation would need to be different for the constructor). This is more or less lifted from what I use every day):

;this can literally be any key combination you could think of like Ctrl + 1
^1::
!SC0C1::
	;MsgBox Alt G1 or Ctrl 1
	p:=""
	p:=new PS()
	p.AppRef.doAction("HorizontalMirrorTransform","yourActionSetName")
return
Class PS {
	AppRef:="",docRef:=""
	__New() {
		try {
			this.AppRef:=ComObjectCreate("Photoshop.Application")
		}
		catch {
			MsgBox % "You may have the transform active, or a dialog open?  Close them and try again as Photoshop is in a blocking state."
		}
		this.docRef:=this.AppRef.activeDocument
		return this
	}
;you can do other cool stuff outside of scripting in effect with access to the model but its not as straightforward at times
	;applyA(styleName:="BlackStroke")
	;{
	;	this.docRef.activeLayer.applyStyle(styleName)
	;}
}

I have other thoughts, and technically, if you just wanted to get ‘more hacky’ to make it work you could just put the scripts in the scripts folder and I believe you could call them with something like:

DllCall("PostMessage", "Ptr", WinActive("ahk_class Photoshop ahk_exe Photoshop.exe"), "UInt", 0x111, "Ptr", -20019, "Ptr", 0)

but you need to know the offset of the menu item. There are more native ways to do that in AutoHotKey also which basically just points to the menu by the order it appears (as I understand it). I also want to say I have two other ideas that might work but they would be a reach and not work as reliably. My only foray into UXP has a webview2 that sniffs keyboard events, but that of course only works inside the panel and then you don’t want conflicts and race conditions so that would probably be difficult to implement (where if you are a panel the keyboard functions differently). Let me know if you have any questions and I will try and reply quickly.

I realized today the code I posted above will have an issue with the constructor on subsequent calls in certain instances. To dumb it down, you can try a less error chatty method (might violate DRY but just to give working example):

!SC0C1::
	;MsgBox Alt G1
	try {
		p:=""
		p:=ComObjectCreate("Photoshop.Application")
		p.doAction("HorizontalMirrorTransform","yourActionSetName")
	}
return

and to quickly add, in an effort to bring the above back towards a UXP conversation, it appears to me that something like:

const psCore = require('photoshop').core.performMenuCommand({commandID: -20019 });

is functionally equivalent of clicking it in the menu at the top which is like the AHK DllCall / WinMenuSelect example posted above, except it appears to be UXP native.

Other posts have warned that this may change frequently, possibly between reloads of the application, but I have not encountered a change in the commandID for my plugin except when I reload the plugin itself with the application already loaded.

Thereafter following a reboot of photoshop it resets to that number … making it pretty handy for me anyway as the webview2 handler can effectively hide the panel on click natively.

I also note this is loaded through a ccx and I believe that commandID # changes may be related to the total number of items present in some or all of the menus at the top, and I hypothesize that its like a push stack - so possibly network or drive connectivity or rapid debugging adjust the total menu count making it appear unreliable. Presumably if you knew the normal total count of menu items, you could guess where the UXP plugin would be if it were reloaded (that’s a big guess but I guess it should be easy enough to test).