Skip to content

fix(web): stop mouseOut from clearing keyboard state; add sendKey + desktopScaleFactor - #3

Open
asjdf wants to merge 2 commits into
masterfrom
upstream-web-input-and-scale
Open

asjdf wants to merge 2 commits into
masterfrom
upstream-web-input-and-scale

Conversation

@asjdf

@asjdf asjdf commented Sep 16, 2026

Copy link
Copy Markdown
Member

Also split out of #1, independent of #2 (the tearing fix) — the two can land in either order.

One input bug fix and two host-facing APIs, all in the web client. No Termium-specific behaviour.

mouseOut no longer releases the keyboard

mouseOut called releaseAllInputs, which releases keyboard state along with the mouse. A host that holds a sticky modifier — an on-screen Ctrl for a shortcut the browser or OS would otherwise swallow — loses it the instant the pointer moves onto an overlay toolbar, since leaving the canvas is precisely what that gesture does.

Releasing the three mouse buttons is enough. That is all the original stuck-right-click fix needed, and it leaves keyboard state intact. Unlike mouseIn, there is no trustworthy event.buttons to diff against once the pointer is gone, so all three are released unconditionally.

mouseInput.test.ts is updated accordingly: the existing regression test asserted releaseAllInputs specifically, and now asserts that every button goes up and that keyboard state is untouched.

sendKey(code, down?)

Injects a single key by KeyboardEvent.code. Omitting down sends press+release; passing a bool drives a sticky modifier.

This is how a host implements an on-screen Ctrl+Alt+Del button without asking the browser for a chord the OS has already taken. The existing helpers (ctrlAltDel, ctrlC, …) only cover fixed combinations, so there is currently no way to send an arbitrary single key.

desktopScaleFactor(percent)

Exposes the RDP CS_CORE DesktopScaleFactor field, letting a HiDPI client ask Windows to scale its own chrome and fonts instead of rendering at native size and getting downscaled. Pair it with Math.round(devicePixelRatio * 100) and a HiDPI framebuffer.

Values outside the spec's 100..=500 range fall back to 0 with a warning; 0 omits the field, which is the current behaviour, so this is opt-in and changes nothing for existing callers.

Testing

  • npm test green (19 tests), svelte-check 0 errors, prettier and eslint clean across both iron-remote-desktop and iron-remote-desktop-rdp.
  • cargo clippy --target wasm32-unknown-unknown and cargo fmt --check clean.
  • sendKey verified against a Windows host for Ctrl+Alt+Del and for sticky Ctrl held across a click; desktopScaleFactor(200) confirmed to make the server render at 200% chrome scaling.

Each change is a separate commit if you would rather take only some of them.

`mouseOut` called `releaseAllInputs`, which releases the keyboard along
with the mouse. Any host UI that holds a sticky modifier — an on-screen
Ctrl for a shortcut the OS would otherwise intercept, say — loses it the
moment the pointer moves onto an overlay toolbar, because leaving the
canvas is exactly what that gesture does.

Release the three mouse buttons instead. That is all the original
stuck-right-click fix needed: the buttons go up, and keyboard state
survives the pointer leaving.

Unlike `mouseIn`, there is no trustworthy `event.buttons` to diff
against once the pointer is gone, so all three are released
unconditionally.
Two capabilities a host embedding the component cannot express today.

`sendKey(code, down?)` injects a single key by `KeyboardEvent.code`.
Omitting `down` sends press+release; passing a bool drives a sticky
modifier. This is how an on-screen Ctrl+Alt+Del button gets implemented
without asking the browser for a chord the OS has already taken, and the
existing `ctrlAltDel`-style helpers cover only fixed combinations.

`desktopScaleFactor(percent)` exposes the CS_CORE DesktopScaleFactor
field, so a HiDPI client can ask Windows to scale its own chrome and
fonts rather than rendering at native size and being downscaled. Values
outside the spec's 100..=500 range fall back to 0 (server default) with
a warning; 0 keeps the field omitted, which is the current behaviour.
@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 14 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 0ddb0064-3902-40b8-b54e-4cbd28607071

📥 Commits

Reviewing files that changed from the base of the PR and between af6feb6 and d6b93e5.

📒 Files selected for processing (6)
  • crates/ironrdp-web/src/session.rs
  • web-client/iron-remote-desktop-rdp/src/main.ts
  • web-client/iron-remote-desktop/src/interfaces/UserInteraction.ts
  • web-client/iron-remote-desktop/src/services/PublicAPI.ts
  • web-client/iron-remote-desktop/src/services/mouseInput.test.ts
  • web-client/iron-remote-desktop/src/services/remote-desktop.service.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant