sp-picker-bug-repro.zip (16.8 KB)
Files
There is no build step and no dependencies.
| File |
Purpose |
sp-picker-repro.ccx |
pre-built plugin |
package.json |
script runner |
package.sh |
Builds a .ccx for loading without the debugger |
src/manifest.json |
Panel + command entrypoints, manifest v5 |
src/index.html |
The picker, the metrics readout, and the divider |
src/index.css |
Panel styling, theme-aware per Photoshop’s four themes |
src/plugin/plugin.js |
Entrypoint registration, DOM instrumentation, logging |
src/plugin/controls.js |
The control group below the divider |
Recordings
gif highlight

full video
Bug Information
Minimal reproduction:
- on a secondary display, an
sp-picker’s menu never appears and cannot be used.
- the sp-picker itself takes focus and shows its focus outline, but the menu is never painted.
The panel instruments the DOM at the moment the menu should be visible. Every property we can read is identical on the working and failing displays: the menu is in the document, computed-visible, and correctly sized. Only the painting differs.
Observed in:
- Photoshop 27.9.1
- UXP manifest v5
- Windows 11
Repro Steps
Load this plugin with the UXP Developer Tool (src/manifest.json), or run ./package.sh and install the resulting .ccx. It reproduces with and without the debugger attached.
- With the panel on the primary display, click the picker. The menu opens below the control and works normally.
- Drag the panel to a secondary display.
- Click the picker again.
Expected: the menu opens below the picker, as on the primary display.
Actual: no menu appears, and no option can be selected. The picker takes focus and draws its focus outline, so the control looks active but is unusable.
Dragging back to the primary display restores it immediately, with no reload and no re-initialisation.
An unexplained workaround
Clicking into a text field, focus only and no keystroke, makes the picker start working on the secondary display.
The text field does not have to be in the plugin. Focusing a text input in one of Photoshop’s own panels, such as the Swatches search box, has the same effect. So this is not about the plugin’s DOM, Spectrum, or the panel’s own focus state.
The control group in the panel includes both text controls so the in-plugin version is reproducible.
A related observation, possibly the same underlying gap:
- before clicking the panel at all, Tab triggers Photoshop’s own show/hide-panels shortcut
- before clicking into a text field, Tab does nothing inside the panel
- after clicking into a text box, Tab and the sp-picker begin working as expected
What the debug logs show
Clicking the picker logs the menu’s root, overlay host, computed visibility, and rect. These are byte-identical on both displays:
menu rect: x=1 y=5 w=286 h=166
menu root: document
menu host: (none — still inline)
menu vis : display=block visibility=visible opacity=1
Read directly, that says the menu is laid out at a normal size, it lives in the plugin’s own document, it was never reparented into a popup or overlay surface, and CSS considers it fully visible.
The DOM believes the menu is visible and correctly placed. It is not drawn.
What this rules out
Each of these was a working hypothesis, and each is contradicted by the readings above:
- Off-screen positioning. The menu’s rect is the same on both displays and sits within the panel. Nothing is measured off-screen.
- Overlay mispositioning. There is no overlay.
closest("[popover], sp-overlay, sp-popover, dialog") returns nothing, and the menu is inline.
- CSS hiding it.
display=block visibility=visible opacity=1.
- A layout failure. The menu has a real size,
286×166, on both displays.
- Display scaling. Ruled out separately, see below.
- The UXP debugger. Reproduces when loaded from a packaged
.ccx with no debugger attached.
Ruled out: display scaling
The first hypothesis was a DPI/scale mismatch between displays, on the strength of Adobe’s own known issue:
window.devicePixelRatio … always returns 1. This is incorrect … window.devicePixelRatio may not always match an element’s pixel ratio if the element is visible on a screen with a different pixel ratio from the primary screen.
This was not applicable to the sp-picker bug. It predicts no failure when both displays share a scale factor, and I tested exactly that case:
- One physical panel, split 50/50 across two HDMI inputs. Windows sees two displays, but they are the same monitor, with identical resolution, DPI, and scale factor by construction.
- The picker works on the half Windows designates primary.
- The picker fails on the half Windows designates secondary.
With scaling held constant, the bug still tracks the primary/secondary designation exactly.