Skip to content

feat(displaycontrol): let a server handler override its capabilities - #1917

Open
Greg Lamberson (glamberson) wants to merge 4 commits into
Devolutions:masterfrom
lamco-admin:feat/displaycontrol-capabilities-override
Open

Greg Lamberson (glamberson) wants to merge 4 commits into
Devolutions:masterfrom
lamco-admin:feat/displaycontrol-capabilities-override

Conversation

@glamberson

Copy link
Copy Markdown
Contributor

Summary

  • DisplayControlServer::start() sends DisplayControlCapabilities::new(1, 3840, 2400) unconditionally, so every server using this crate is capped at one monitor with no way to advertise more.
  • Added a default trait method on DisplayControlHandler, capabilities(), that start() now calls instead of the hardcoded literal.
  • The default returns the same (1, 3840, 2400) values, so any existing implementation that does not override it keeps its current behavior unchanged.
  • A handler serving more than one monitor can override capabilities() to report the real count.

Validation

cargo xtask check fmt/lints/tests/typos/locks all pass.

Notes

  • Additive only: one new trait method with a default body, one call-site change in start(). No existing implementor is affected unless it opts in.

DisplayControlServer::start() hardcoded DisplayControlCapabilities::new(1,
3840, 2400), giving every server a fixed single-monitor cap with no way
to advertise more. Added a default trait method mirroring the existing
monitor_layout() pattern, so a handler serving multiple monitors can
override it; anything that doesn't override it keeps today's exact
behavior.
@github-actions github-actions Bot added maintainer-required Maintainer review or intervention is required risk/unknown Risk could not be determined automatically; needs maintainer-level scrutiny scope/core Touches the core architectural tier size/XS Size: up to 49 counted lines and 2 files labels Sep 8, 2026
@CBenoit
Benoît Cortier (CBenoit) requested a balanced review from Copilot September 9, 2026 00:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The implementation is sound; the only unresolved comment is a non-blocking documentation nit.

Pull request overview

Enables display-control handlers to customize advertised monitor capabilities while preserving existing defaults.

Changes:

  • Adds an overridable capabilities() method.
  • Uses handler-provided capabilities during startup.
File summaries
File Review
crates/ironrdp-displaycontrol/src/server.rs Capability customization is additive. Minor documentation issue: the example must handle the DecodeResult returned by DisplayControlCapabilities::new(...).
Review details

Suppressed comments (1)

crates/ironrdp-displaycontrol/src/server.rs:20

  • DisplayControlCapabilities::new(...) returns a DecodeResult, so the documented expression cannot be returned directly from this method. Avoid presenting it as a valid return expression unless the validation result is handled explicitly.
    /// A handler serving more than one monitor should override this to
    /// return `DisplayControlCapabilities::new(monitor_count, 3840, 2400)`.
  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Balanced

Comment thread crates/ironrdp-displaycontrol/src/server.rs Outdated
@CBenoit Benoît Cortier (CBenoit) removed the maintainer-required Maintainer review or intervention is required label Sep 9, 2026
…edback

Removes the today and current framing CBenoit flagged as unnecessary
historical wording, and fixes the override example to show the
DecodeResult being unwrapped, matching what the default implementation
already does.
@github-actions github-actions Bot added kind/protocol Affects RDP or related protocol behavior maintainer-required Maintainer review or intervention is required risk/high Substantial core public API impact, or fail-closed triage; needs maintainer-level scrutiny and removed risk/unknown Risk could not be determined automatically; needs maintainer-level scrutiny labels Sep 9, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Additive, well-scoped change: DisplayControlServer::start() now takes the DISPLAYCONTROL_CAPS_PDU contents from a new defaulted DisplayControlHandler::capabilities() instead of a hardcoded (1, 3840, 2400) literal. I verified the default stays within the crate's internal limits (MAX_SUPPORTED_MONITORS 1024, MAX_MONITOR_AREA_FACTOR 16384 in pdu/mod.rs), so its expect never fires and the encoded PDU is byte-identical to before; non-overriding implementors are unaffected, and the hook mirrors the existing monitor_layout() and egfx preferred_capabilities() patterns. One merged issue (three duplicate specialist findings): the infallible signature deletes start()'s decode_err! error path and the doc example encourages .expect, so an override built from runtime state that exceeds the crate limits panics during channel start; a Result-returning hook would preserve error propagation. No other correctness, protocol, or maintainability concerns found.

Comment thread crates/ironrdp-displaycontrol/src/server.rs
@github-actions github-actions Bot added ai-reviewed/1 One automated review completed and removed maintainer-required Maintainer review or intervention is required labels Sep 9, 2026
… error

capabilities() was declared infallible, so the only way an overrider
could report invalid values (a monitor count or area factor combination
DisplayControlCapabilities::new rejects) was to panic. That panic runs
inside start(), a DvcProcessor callback, and unwinds through it rather
than surfacing as a recoverable PduResult::Err. The trait method now
returns PduResult<DisplayControlCapabilities>, and start() propagates
via the same decode_err! conversion process() already uses.

Adds a regression test exercising start() with an out-of-range override.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Additive and correct. DisplayControlHandler::capabilities() defaults to DisplayControlCapabilities::new(1, 3840, 2400), reproducing the previous hardcoded start() output exactly, so the sole in-repo implementor (ironrdp-server's DisplayControlBackend, which does not override) is unaffected. start() propagates handler errors via the same decode_err! bridge process() uses; validation bounds in calculate_monitor_area are unchanged and one spec-conformant CAPS PDU is still sent at channel start. The doc comment accurately explains the fallibility and panic-abort risk. The added error-path test compiles against existing test dependencies and asserts real behavior. Changelog updates are automated via release-plz/git-cliff, so no manual CHANGELOG edit is expected. One low-severity gap remains: no test verifies a valid override's values reach the encoded start message, the error assertion does not check the error kind, and the default output stays untested.

Comment thread crates/ironrdp-testsuite-core/tests/displaycontrol/mod.rs
@github-actions github-actions Bot added ai-reviewed/2 Final automated review completed maintainer-required Maintainer review or intervention is required and removed ai-reviewed/1 One automated review completed labels Sep 11, 2026
The PR's core claim is that a handler can override capabilities() to
advertise more than one monitor, but nothing verified a valid
override's values were actually encoded into the DISPLAYCONTROL_CAPS_PDU
returned by DisplayControlServer::start(). The one existing test only
asserted that an invalid override errors, proving handler invocation
and error propagation but not correct encoding.

Added a positive-path test overriding capabilities() to (2, 3840, 2400)
and decoding the resulting DVC message back to confirm the values reach
the wire, plus a test pinning the default (1, 3840, 2400) capabilities()
impl, which predates this PR as a hardcoded start() literal and was
never covered by a test either.
@CBenoit

Benoît Cortier (CBenoit) commented Sep 16, 2026

Copy link
Copy Markdown
Member

Hi Greg Lamberson (@glamberson)
This is looking good to me, but may I confirm with you if you pushed everything on your side? I see you answered a comment above as addressed with more tests, but I don’t see them.
Thanks!

@glamberson

Copy link
Copy Markdown
Contributor Author

Oops! I hadn't pushed that commit yet. Just pushed 3bb21ee, which adds the two tests: One confirming a multi-monitor override actually encodes into the DISPLAYCONTROL_CAPS_PDU, the other pinning the default (1, 3840, 2400) capabilities that predate this PR. All xtask gates pass.

Thanks for catching it.

@github-actions github-actions Bot added size/S Size: up to 199 counted lines and 5 files; exceeds XS in either measure triage/overlap This issue or pull request already exists or overlaps and removed size/XS Size: up to 49 counted lines and 2 files labels Sep 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request may overlap with #1918.

Both PRs center on the same DISPLAYCONTROL capabilities extension point: this PR adds the fallible, overridable DisplayControlHandler::capabilities() in ironrdp-displaycontrol, while #1918 implements that override in ironrdp-server's DisplayControlBackend backed by a new RdpServerDisplay::monitor_count() to advertise real monitor counts. Shared scope around what DISPLAYCONTROL_CAPS_PDU values are sent at channel start; flagged for human assessment, not a redundancy verdict.

This notice is advisory only. Automated review continues as usual, and how these pull requests relate is for maintainers and authors to decide.

Note

LLM-assisted content (no human feedback).

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

Labels

ai-reviewed/2 Final automated review completed kind/protocol Affects RDP or related protocol behavior maintainer-required Maintainer review or intervention is required risk/high Substantial core public API impact, or fail-closed triage; needs maintainer-level scrutiny scope/core Touches the core architectural tier size/S Size: up to 199 counted lines and 5 files; exceeds XS in either measure triage/overlap This issue or pull request already exists or overlaps

Development

Successfully merging this pull request may close these issues.

3 participants