Is there any way to turn off document refresh while code makes changes?

I’m writing a plugin that makes a few little changes to several layers in each of several documents. As a result the document display flashes and jumps in a very annoying way for a few seconds. Is there any way to turn off the document refresh, or just to limit which events it responds to?

Both the document itself and all the background of the pasteboard flash (I usually run in dark mode and it switches between that and white).

FWIW, I’ve tried:

  • making the changes in a document created with core.createTemporaryDocument. The description does say “This document does not appear in the UI, and there are limitations with some editing features.” I have yet to figure out what you can actually do with one; most of the Document object returned is empty, not even access to its layers property.

  • fiddling with the action playback options, because there are some threads around that say that could help in similar situations with ExtendScript. I can’t see any effect on UXP and BatchPlay.

  • I looked for a way to zoom right out or right in on a document to reduce the visual impact of refreshes, but couldn’t find one.

  • I tried core.redrawDocument at strategic moments, but couldn’t see any difference.

Chunks of the work are done with batchPlay, but I’ve steered clear of chaining batchPlay calls into one because there seem to be enough comments about problems with that!

FWIW, I do suspend history on each doc as I work on it, but that doesn’t seem to have any impact on redraw frequency.

Any other thoughts?

I assume you execute all within “single execute as modal” state since you suspend history, right?

Yes, that’s correct, most of the code is in one big modal execution context.

I’ve never been sure whether it’s worth breaking those into smaller units but it’s easier to make one big blob …

I’ve just been experimenting with multi-action batchPlay calls, but so far it’s not making much, if any, difference.

I was surprised to see the Photoshop ‘home’ screen when I stopped on some breakpoints. If I waited for a few seconds the active document would then get shown. At other times the response is instantaneous and flickering fast.

Even without the debugger I can now see that the home screen keeps appearing and disappearing; the big blue ‘new file’ and the white ‘read article’ buttons are very visible, now that I know what I’m looking at,

The sequence I’m following is:

  1. Create new document

  2. For each source document:

  • Make a temporary duplicate of the doc

  • Massage it a bit, e.g. changing colour mode, converting all layers into a smart object etc. I now have all of this in a single, multi-step batchPlay

  • Copy the contents of the temporary document (usually only one layer) into the new document at the top of the layer list (I tried the bottom as well, and it doesn’t make any visible difference).

  • Close the temporary file without saving

Thanks

You could disable homescreen if there is nothing better you could do. At least for the time of modal state. Not sure if this one requires PS restart.

I just tried disabling the home screen manually, and it does look as if you need to restart Photoshop. When I turned it off and on around my code with batchPlay it had no effect. Shame, because it did make a small improvement.

I’m seeing that there are a lot of factors that have an impact; making sure that the history and layers palettes aren’t showing improves things a little bit as well.

The biggest improvement comes from setting up with all windows arranged as, for example, “tile all vertically”. If I do that then only one of those tiles flickers at a time, which is much less annoying.

But although I could see the commands to do that through Alchemist*, if I try to call them in my code I get “must be in modal execution” if it’s outside, and “command not currently available” if it’s inside the modal scope. I did try putting each of those batchPlay calls into its own modal execution context, before and after the one that encapsulates most of the code, but still get “command not available”.

const bpres = await batchPlay([{
          _obj: "invokeCommand",
          commandID: 5933,
          kcanDispatchWhileModal: true,
          _options: {
            dialogOptions: "dontDisplay",
            modalBehavior: "execute"
          }
        }
      ], {});

But then I tried the same thing using core.performMenuCommand, and that works!

I had been starting to wonder if I would have to put a warning on my plugin description with a list of mitigations that anyone who is sensitive to flashing lights can do when using it. But this looks like a good workround.

Now, I wonder how I can discover the initial arrangement that the user has set up so I can restore that at the end instead of just consolidating to tabs …

But that will have to wait till later

Martin

  • I’m not sure if I offered my deep thanks for Alchemist; I don’t think I could put together a plugin that does useful things without it!

This message is pretty much useless in any scenario. It usually means, that some pre-requisites are not met. For example, if you try to delete an active layer without actually having selected any, IIRC you would get this message. There were more similar cases, but can’t recall exactly what. Basically you need to do something first to make that command available

You can’t have fine control over all document windows. You can use menu commands… but that will give you basic control.

Also sometimes you can have multiple windows for the same document but as far I know this is impossible to detect in scripting. And if don’t know about it, you cannot recreate it.

Thanks. So I’m just going with tiling all open images to start with and then switching to tabs at the end. I’ve added a checkbox for people to use if they don’t want me to mess with their window settings. I think that’ll be enough.

Not sure of the proper etiquette here.

I’m happy with the solution described above. Well, maybe not happy, but it’s useable.

Should I mark the original question as answered?

That is good idea. I think you can change once there is the better solution. Or even add your own reply with the solution and mark your own reply as the correct answer.

1 Like

I understand that a flashing screen might be problematic for those sensitive to it. However, I’d like to offer a different perspective by sharing something I once read.

A company was concerned that their elevators were too slow, causing frustration among people waiting for them. They hired an advisor to find a solution. Surprisingly, the advisor suggested placing mirrors on each floor. By allowing people to observe themselves in the mirrors, the wait felt shorter. The company implemented this idea, and it successfully addressed the issue.

This situation has a parallel here. If you were able to display a static screen, then users might become frustrated with how long they had to look at it. However, by showing progress through interim screens, you maintain their interest and give the impression that things are steadily moving along. Essentially, this approach lets you implement a longer processing sequence without testing the user’s patience.

It is possible to partially confine the flashing to monochrome by adjusting the saturation settings. To do this, navigate to Edit > Color Settings > Desaturate Monitor Colors By… and increase the desaturation from the default 20% to 100%. This seems to makes the flashing less intense. Once processing is complete, the setting can be restored back to 20%.

This can be automated by the following command steps.

// Set desaturation settings of the current application to 100% {“_obj”:“set”,“_target”:[{“_property”:“colorSettings”,“_ref”:“property”},{“_enum”:“ordinal”,“_ref”:“application”,“_value”:“targetEnum”}],“to”:{“_obj”:“colorSettings”,“monitorCompression”:100.0}},

// Set desaturation settings of the current application to 20% {“_obj”:“set”,“_target”:[{“_property”:“colorSettings”,“_ref”:“property”},{“_enum”:“ordinal”,“_ref”:“application”,“_value”:“targetEnum”}],“to”:{“_obj”:“colorSettings”,“monitorCompression”:20.0}}

(Note however, that if the processing in some way freezes, then you could leave your user with Photoshop images stuck in monochrome.)

Finally, it is unclear whether flashing screens pose a significant problem. Motorola/Lenovo phones and tablets, for example, deliberately display a series of flashing images during their ‘Hello Moto’ start up sequence. While some users find it disconcerting, it hasn’t been widely flagged as an issue.

Thanks TeeJay, but a full-screen flash at something a bit over one per second, of all the images I’m merging, interspersed with the Photoshop home screen was REALLY annoying. And I don’t have any photo sensitivity to worry about!

Hi MartinB, I suspect it is dependent upon the particular application. My remarks are applicable to my application but even that is a subjective judgement.

It might be worth manually setting the desaturation to 100% to see whether it improves the situation for your current implementation. The flashing foreground images become monochrome but the background does not. I judged that in my situation this was an improvement so I have now implemented this programmatically within my software.