Skip to main content
Known Participant
Oct 31, 2026 11:05 AM UTC
Question

When does LrDevelopController.setValue bind a local exposure edit to a mask?

In Lightroom Classic 15.5 with SDK 15.3, suppose mask A is selected when a plug-in calls LrDevelopController.setValue for local exposure. If the user selects mask B immediately after the call returns, is the edit guaranteed to apply to A? At what point does Lightroom bind the edit to its target?

Is there a supported API or callback that lets the plug-in confirm that this particular edit completed on mask A, even if B is now selected?

    3 replies

    johnrellis
    Legend
    Nov 2, 2026 9:38 PM UTC

    [View this post in your web browser. It contains formatting and images that don't appear in email.]

     

    For local exposure, does setValue resolve and bind the selected mask before the call returns, so selecting mask B immediately afterwards cannot redirect that edit from mask A to B? Is there a documented guarantee that the selected-mask check and setValue can run without a selection change between them?

     

    If there isn’t another concurrent thread also invoking LrDevelopController, and if the user isn’t making changes in the UI, then the same get/set principle applies. The currently selected mask won’t change without the plugin explicitly changing it via LrDevelopController. This guarantee isn’t documented anywhere, but almost nothing about the SDK is explicitly guaranteed.


    You can get and set the currently selected mask tool and mask using the LrDevelopController functions get/setSelectedMask(). So you can test the “guarantee” by calling getSelectedMask(), changing local exposure, then doing getSelectedMask() again to verify the selected mask hasn’t changed.

     

    Note that if the plugin is calling LrDevelopController from a floating dialog or a background thread, there is definitely the possibility the selected mask could change between a get and set, e.g. by the user or a background task. The original design of the SDK was that all tasks were non-preemptive -- no other UI tasks could run while a plugin’s task was running. But unfortunately, there are many API calls that can yield to the task scheduler and run another task, including the main UI thread. Adobe doesn’t document which API calls can yield, so you have to test it yourself (very tediously).  Thus, writing a correct floating dialog-based plugin can be quite tricky.  I’ve got a very old post somewhere in this forum that I can’t find due to the new platform’s horrendously bad search.

     

     

     

    Translate
    zhp3nnAuthor
    Known Participant
    Nov 1, 2026 3:24 PM UTC

    Thanks, that clarifies the expected immediate readback. I am not reporting a confirmed SDK bug; the remaining question is target ownership during a selection change.

    For local exposure, does setValue resolve and bind the selected mask before the call returns, so selecting mask B immediately afterwards cannot redirect that edit from mask A to B? Is there a documented guarantee that the selected-mask check and setValue can run without a selection change between them?

    If getValue then refers to the newly selected mask, is there a supported way to confirm the original edit on mask A, or is this limited to inspecting A’s settings? A reference to the relevant SDK guarantee would be very helpful.

    Translate
    johnrellis
    Legend
    Oct 31, 2026 6:17 PM UTC

    The intent of LrDevelopController is that changes made to the image via the API’s functions take effect “immediately”: a getValue() following a setValue() should return the new value. There is no need to perform setValue() within a database transaction (catalog:withWriteAccessDo()), as there is with the LrPhoto methods.

     

    If you’re observing different behavior, I think that’s a possible bug that should be narrowed down.

    Translate