You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(display): size virtual displays from the client's image area
The stream protocol carries pixels, never physical dimensions, so the host
cannot tell a 2504-pixel-wide phone panel from a 2504-pixel-wide monitor.
effective_virtual_display_scale_percent() therefore guessed a Windows scale
from the short edge alone, and buttons, text, and the cursor landed at a
different physical size on the client than they have on the host's monitor.
Add dd_virtual_display_image_width_mm: the measured width, in millimetres, of
the image area the client actually displays. When set, the virtual display
advertises that size through its synthetic EDID and Windows derives DPI from it
the same way it does for a real monitor. The Windows scale becomes a value
derived from the measurement rather than the primary input, which is both more
precise than a picked percentage and closer to how Windows expects to be told
about a display.
The width describes the image area, not the device. A letterboxed stream is
smaller than the panel carrying it, so the height is derived from the width and
the requested mode's pixel aspect instead of from the panel's shape.
Both halves stay pure functions of the configuration. Reconnecting re-runs them
against a display that already carries the previous answer, so neither may read
back what it wrote last time; a covering test pins that down. An explicit
dd_virtual_display_scale still wins, and 0 still leaves the Windows DPI setting
untouched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: src/config.h
+1Lines changed: 1 addition & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -231,6 +231,7 @@ namespace config {
231
231
bool use_sunshine_virtual_display_driver; ///< Use the Vibepollo Display Driver instead of rollback drivers such as SudoVDA.
232
232
bool activate_virtual_display; ///< Auto-activate Sunshine virtual display when selected as the target output.
233
233
int virtual_display_scale_percent; ///< Windows scale for virtual displays (-1 is resolution-based; 0 preserves Windows' choice).
234
+
int virtual_display_image_width_mm; ///< Width of the client's visible image area in millimetres (0 disables). Drives the synthetic EDID so Windows derives DPI from a real physical size.
234
235
int virtual_display_permanent_count; ///< Number of always-present Sunshine virtual displays to request when explicitly configured.
235
236
bool virtual_display_permanent_count_configured; ///< False preserves installs that predate this setting.
236
237
std::vector<std::string> snapshot_exclude_devices; ///< Device IDs to skip when saving display snapshots.
Copy file name to clipboardExpand all lines: src_assets/common/assets/web/public/assets/locale/ui/en.json
+4Lines changed: 4 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -1362,6 +1362,10 @@
1362
1362
"description": "Keep up to four virtual monitors outside streams. 0 creates them only when needed.",
1363
1363
"label": "Always-available virtual displays"
1364
1364
},
1365
+
"dd_virtual_display_image_width_mm": {
1366
+
"description": "Width of the image area your client actually displays, in millimetres. Windows reads it from the virtual display's EDID and derives DPI from it, so buttons and the cursor match the physical size they have on the host monitor. Measure the image area, not the device: a letterboxed stream is smaller than the panel. 0 disables it. Examples: 345 for an Alienware m16 R2 at 2560x1600, 151 for a Galaxy Z Fold8 Ultra inner panel at 2504x2256.",
1367
+
"label": "Client image width (mm)"
1368
+
},
1365
1369
"dd_virtual_display_scale": {
1366
1370
"description": "Adjust interface size without changing the resolution requested by the client.",
0 commit comments