Skip to content

feat: pass the exact display scale to FreeRDP - #960

Merged
oskardotglobal merged 1 commit into
winapps-org:mainfrom
oraturk75:scale-desktop-exact
Oct 29, 2026
Merged

oskardotglobal merged 1 commit into
winapps-org:mainfrom
oraturk75:scale-desktop-exact

Conversation

@oraturk75

@oraturk75 oraturk75 commented Aug 21, 2026 •

Copy link
Copy Markdown
Contributor

What this changes

RDP_SCALE was rounded to 100, 140, or 180 because WinApps assumed FreeRDP only supported those values. FreeRDP takes scaling values in three different ways.

/scale-desktop: Can take any integer between 100-500, and this is where full-desktop and RemoteApps scaling is set.

/scale-device: Accepts only 100, 140, and 180. This is the scaling factor for MS Store (UWP) apps.

/scale: This is only a convenience shortcut. It takes one value and assigns it to the above two. It accepts only 100, 140, and 180. This is what WinApps is currently using. So a requested scale of 125 gets rounded to 140 by WinApps before it goes to FreeRDP's /scale option.

This PR sends the exact value through /scale-desktop, rounds it to the nearest supported value, and sends that to /scale-device separately. I set both, because sending only /scale-desktop would change the device scale existing users get today.

As requested, RDP_SCALE now controls RemoteApp launches, while a new RDP_DESKTOP_SCALE controls the full-desktop session. When the user does not set RDP_DESKTOP_SCALE, it takes the value of RDP_SCALE by default.

WinApps now checks the values before sending them. A non-integer stops the launch with an error. Below 100 becomes 100, above 500 becomes 500.

Configuration

RDP_SCALE="100"
RDP_DESKTOP_SCALE="inherit"

The "desktop" in RDP_DESKTOP_SCALE means the full-desktop launch, not FreeRDP's /scale-desktop. WinApps rounds each one to 100, 140, or 180 for /scale-device.

Existing configs don't need to change. A missing RDP_SCALE means 100, and a missing RDP_DESKTOP_SCALE uses whatever RDP_SCALE is.

Testing

Tested against Win11 Pro, FreeRDP 3.32.1, and KDE/wayland; RemoteApps run through XWayland.

Exact scale: I checked the DPI Windows reports for winver, Character Map, Notepad and Paint. Notepad and Paint are Store-packaged win32 apps. As RemoteApps they got 96 DPI at 100 and 120 at 125, over a separate FreeRDP connection with the same values WinApps passes. In the full desktop they got 96, 120 and 144 at 100, 125 and 150. Clicking each RemoteApp's close button also landed in the right spot.

Launch mapping: I captured the FreeRDP commands from a named app, an app opened with a file, manual, and winapps windows. The full desktop got the full-desktop scale and the RemoteApps got RDP_SCALE. Values tested: no scale set (100/100), 125/140, 150/140, 175/180, and 900, which became 500/180. A non-integer stopped the launch with an error.

bash -n, ShellCheck, git diff --check, the full pre-commit suite, and nix flake check all pass.

Full desktop: winapps windows works with both sdl-freerdp3 (WinApps picks it by itself on Wayland) and xfreerdp3. 150 was tested with RDP_SCALE=100 and RDP_DESKTOP_SCALE=150.

Setup: setup.sh's own launches (the RDP access check and the app scan) got the RemoteApp scale, 125/140, with RDP_DESKTOP_SCALE at 175.

For the KDE RemoteApp DPI, click and pair tests I used FreeRDP 3.32.1 with its window size filter removed, because of a separate FreeRDP bug that cuts off some apps at startup (see FreeRDP/FreeRDP#13844). The full desktop and setup tests used the stock clients.

Nothing in this change is DE-specific. I tested on KDE/wayland, but it only passes values to FreeRDP, so it should work the same on any other desktops.

AI Assistance Disclosure

I got help from two AI assistants to write most of the code. I reviewed their work, made the final decisions, and tested it myself.

@oskardotglobal

Copy link
Copy Markdown
Member

So if I understand this correctly, if I set a scale of 158, this will scale the desktop accordingly, but RAILS will still be scaled to 140? That seems unintuitive. Maybe we should just have a seperate scale for desktop and RAILS?

@oskardotglobal oskardotglobal added triage Further information is requested ai Created using assistance of LLMs labels Aug 27, 2026
@oraturk75

Copy link
Copy Markdown
Contributor Author

Good question, and the README wording is what made it ambiguous. Sorry about that.

/scale-device is not the RemoteApp scale. Per MS-RDPBCGR 2.2.1.3.2 these are two distinct fields with different allowed ranges, sent together and each validated against the other: desktopScaleFactor is valid from 100 to 500, and deviceScaleFactor is restricted to 100, 140 or 180. /scale-desktop is what sizes the session, and that includes RemoteApp windows.

I measured this before writing the patch. Winver under RemoteApp, with /scale-device pinned at 100 and only /scale-desktop varied, using the window geometry the server reports:

/scale-desktop window width ratio
100 460 x 423 1.000
125 575 x 521 1.250
150 691 x 621 1.502

Linear fits on both axes are within 2 px across the three points, with a fixed ~31 px offset on height that is window chrome. So at RDP_SCALE=158 the RemoteApp windows scale at 158, not 140.

The old /scale set both fields. Sending only /scale-desktop would silently change deviceScaleFactor from the rounded value WinApps currently sends to FreeRDP's default of 100, so this patch preserves the existing device-factor behavior. That field is the only value being approximated.

I will clarify the README. Does this address your concern, or would you still prefer separate user control of deviceScaleFactor?

@oskardotglobal

oskardotglobal commented Aug 29, 2026 •

Copy link
Copy Markdown
Member

I think a seperate config option for the desktop scale defaulting to the value of RDP_SCALE would be preferred, with RDP_SCALE controlling RemoteApp scaling.

Also, please do not copy-paste the answer of the LLM as the response to my question. As per our policy, we accept AI-generated code, but this is just bad etiquette and doesn't really support your claim of having reviewed the changes by hand.

@oraturk75

Copy link
Copy Markdown
Contributor Author

Hey, I thought more about this PR work and #825, which inspired part of it, and I believe something got lost in the transit. There is no reason why I should not include automatic detection of the primary monitor scale (on Cinnamon/X11) from #825 as part of this PR, since it completes the scaling work already here. I do not have a multi-monitor setup, so I cannot reproduce nor properly test those issues and will leave that part of #825 for someone else.

I will add the separate full-desktop scale option per your request. Also; I have decided to expand this PR to include automatic scale detection. Of course, manual scale settings will always override automatic detection. Is that okay with you?

PS: Sorry about earlier posts, didn't mean any disrespect.

@oskardotglobal

Copy link
Copy Markdown
Member

Sure, automatic scale detection sounds super useful! Also, multi-monitor scaling is a non-trivial issue and FreeRDPs multi-monitor capabilities are dubious anyways, so focusing on single-monitor scale detection seems like the right choice

@oraturk75 oraturk75 changed the title feat: pass the exact display scale to FreeRDP feat: pass the exact display scale to FreeRDP, and detect it automatically Sep 2, 2026
@oraturk75

Copy link
Copy Markdown
Contributor Author

@oskardotglobal Pushed. RDP_SCALE now controls RemoteApps and the new RDP_DESKTOP_SCALE controls the full desktop, defaulting to RDP_SCALE as you asked. Both accept auto, which detects the primary monitor scale on Cinnamon/X11. If detection is unavailable or fails, it falls back to 100, while manual values always override detection. I also clarified the README as promised and updated the title and description for the new scope.

@oraturk75

Copy link
Copy Markdown
Contributor Author

@oskardotglobal Hey, just checking in. Did you had a chance to look at the latest changes?
Please let me know if anything else is needed from me.

@oskardotglobal

Copy link
Copy Markdown
Member

Hi, I still need to find some time to review this properly. Will get back to you

@oskardotglobal oskardotglobal left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After giving this a proper review: this is not something I will merge as-is anytime soon. The long inline awk code is iff and for fact it only supports Cinnamon on X11 it's implemented way and documented way too broadly; until this supports more setups this won't be very useful to many people. Also, the AI-generated prose in the documentation & comments is poorly phrased.

@oraturk75

oraturk75 commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor Author

@oskardotglobal It is hard for me to hit a moving target. I said Cinnamon/X11 up front and you said "sure". So that part isn't new. Also, “poorly phrased” is not actionable, it's “way too broadly”.

Back to work.

I will do better with README and Code Documentation next time. I realize that it is too long, to say the least. No need to point where and what's wrong with the current docs now; they're getting rewritten anyway.

Only auto is DE-specific. The rest of the PR is the same on any desktop.

I can also support GNOME/Wayland through Mutter, which exposes the same monitor data as Cinnamon's Muffin. I can test GNOME/Wayland locally myself, but a second test from someone who uses GNOME as their default DE would be better. Is that enough, or which other environments are required?

I have a pretty good idea how to make the awk code much better, likely without the inline parser at all, but it will wait until your new requirements are clear.

Please let me know. Thanks.

@oskardotglobal

Copy link
Copy Markdown
Member

Sorry, I missed the "Cinnamon/X11" part of your original comment...

What I meant by "implemented too broadly" is that for example, for something implemented currently only for Cinnamon it shouldn't be the default behaviour; the default behaviour should be to configure the scale numerically and then the user can opt-in to autoscaling if they're on a supported DE.

waFixScale is getting a bit complex and the newly added 21 (!) local variables aren't helping. Also, since waDetectHostScale is pretty DE-specific, it should probably detect the DE first and then call a waDetect<DE>HostScale.

@oraturk75

Copy link
Copy Markdown
Contributor Author

Understood on all four.

I will make the default numeric 100 and keep auto opt-in.

I will simplify waFixScale, split waDetectHostScale into DE detection plus waDetect<DE>HostScale, and replace the long inline awk block with a simpler shared parser called by the DE-specific detectors.

I tested GNOME/Wayland, and Mutter-based detection is feasible. Do you want it in this PR or in a follow-up?

I will rewrite the docs to match the final behaviour.

@oskardotglobal

Copy link
Copy Markdown
Member

Put GNOME in a follow-up, take your time.

@oraturk75

Copy link
Copy Markdown
Contributor Author

@oskardotglobal sorry for the late reply, had some health issues and also switched to a new laptop. I'm on KDE/wayland now, not Cinnamon/x11 anymore, so the auto detection I added doesn't even work for me. would it be ok to go back to the original scope and drop auto from this PR? just the numeric scaling; so exact value goes to scale-desktop, rounded one to scale-device, and RDP_DESKTOP_SCALE stays. that also gets rid of the detection code and the long awk code. I'll still clean up waFixScale and rewrite the readme and comments like you asked. that also means no gnome follow-up from me, sorry about that. auto detection can be its own PR later if someone wants it.

@oskardotglobal

Copy link
Copy Markdown
Member

Yes, sure.

WinApps rounded RDP_SCALE to 100, 140 or 180 because FreeRDP's /scale
only accepts those values. /scale-desktop takes any integer from 100 to
500, so the exact value now goes there and 125 stays 125.

The device scale, used by MS Store (UWP) apps, still only takes 100,
140 or 180. WinApps rounds it to the nearest one and passes it as
/scale-device.

RDP_SCALE now sets RemoteApp scaling. The new RDP_DESKTOP_SCALE sets
the scale for 'winapps windows' and defaults to RDP_SCALE.

A non-integer value stops the launch with an error. Values outside
100-500 are set to the nearest limit with a warning. The warning no
longer pops up a notification on every launch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tony Dursun <oraturk75@gmail.com>
@oraturk75
oraturk75 force-pushed the scale-desktop-exact branch from 3c137bc to a871814 Compare October 29, 2026 03:15
@oraturk75 oraturk75 changed the title feat: pass the exact display scale to FreeRDP, and detect it automatically feat: pass the exact display scale to FreeRDP Oct 29, 2026
@oraturk75

Copy link
Copy Markdown
Contributor Author

@oskardotglobal pushed. auto is gone, it's just the numeric scaling now. I also cleaned up waFixScale and rewrote the readme part, and rebased on current main. updated the description too.

@oskardotglobal oskardotglobal left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean. Thanks

@oskardotglobal
oskardotglobal merged commit 0b950dc into winapps-org:main Oct 29, 2026
5 checks passed
@oraturk75

Copy link
Copy Markdown
Contributor Author

thanks for the review and your patience, it's my first merged PR :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai Created using assistance of LLMs triage Further information is requested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants