Skip to content

Add monitor layout visualization, switch animation, and thumbnail previews to viewer - #11

Merged
Undermozes merged 2 commits into
masterfrom
copilot/enhance-monitor-layout-visualization
Mar 11, 2026
Merged

Undermozes merged 2 commits into
masterfrom
copilot/enhance-monitor-layout-visualization

Conversation

Copilot AI commented Mar 11, 2026 •

Copy link
Copy Markdown

The viewer's "Monitors" dropdown showed only opaque identifiers ("Monitor 0", "Monitor 1") with no spatial or visual context. This adds three UX improvements: an SVG layout diagram showing physical monitor arrangement, a fade animation on monitor switch, and per-monitor JPEG thumbnail previews.

Backend

  • DisplayLayoutDto (new): carries X, Y, Width, Height, IsPrimary, DisplayName per monitor
  • ScreenDataDto: extended with DisplayLayouts array
  • ScreenThumbnailDto (new): carries DisplayName + JPEG bytes; DtoType.ScreenThumbnail = 30 added
  • IScreenCapturer: two new methods — GetDisplayLayouts() and GetDisplayThumbnail(string displayName)
    • Windows: GetDisplayLayouts() reads from DisplaysEnumerationHelper; GetDisplayThumbnail() uses BitBlt per-monitor
    • Linux: GetDisplayLayouts() reads Xrandr XRRMonitorInfo; GetDisplayThumbnail() uses XGetImage
  • Viewer.SendScreenData(): now populates DisplayLayouts from the capturer
  • Viewer.SendScreenThumbnails() (new): loops all displays, captures a JPEG (max 320px wide, quality 50), sends one ScreenThumbnailDto per display
  • ScreenCaster: calls SendScreenThumbnails() immediately after SendScreenData()

Frontend

  • DtoType.ts / Dtos.ts: ScreenThumbnail = 30, DisplayLayoutDto, ScreenThumbnailDto, updated ScreenDataDto
  • UI.ts:
    • RenderMonitorLayout(): renders an SVG diagram of monitor physical layout; clicking a rect triggers SendSelectScreen()
    • UpdateDisplays(): shows the SVG diagram (multi-monitor only) plus per-button thumbnail <img> elements
    • UpdateThumbnail(): stores incoming thumbnails in a Map and updates visible <img> elements
  • MessageSender.ts / DtoMessageHandler.ts: SendSelectScreen() adds .switching CSS class + toast; HandleScreenSize() removes the class when the new frame size arrives
  • remote-control.css: 300ms keyframe fade for .switching, SVG layout rect styles, thumbnail button layout

Please read the following. Do not delete below this line.

Thank you for your contribution to the Remotely project. It is required that contributors assign copyright to Immense Networks so we retain full ownership of the project.

This makes it easier for other entities to use the software because they only have to deal with one copyright holder. It also gives me assurance that we'll be able to make decisions in the future without gathering and consulting all contributors.

While this may seem odd, many open source maintainers practice this. Here are a couple well-known examples:

A nice article on the topic can be found here: https://haacked.com/archive/2006/01/26/WhoOwnstheCopyrightforAnOpenSourceProject.aspx/

By submitting this PR, you agree to the following:

You hereby assign copyright in this PR's code to the Remotely project and its copyright holder, Immense Networks, to be licensed under the same terms as the rest of the code. You agree to relinquish any and all copyright interest in the software, to the detriment of your heirs and successors.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • av-build-tel-api-v1.avaloniaui.net
    • Triggering command: /usr/share/dotnet/dotnet dotnet exec --runtimeconfig /home/REDACTED/.nuget/packages/avalonia.buildservices/0.0.29/tools/netstandard2.0/runtimeconfig.json /home/REDACTED/.nuget/packages/avalonia.buildservices/0.0.29/tools/netstandard2.0/Avalonia.BuildServices.Collector.dll (dns block)
  • www.myget.org
    • Triggering command: /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp (dns block)
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /home/REDACTED/work/Remotely/Remotely/Remotely.sln --packages /tmp/codeql-scratch-308cdbf2ab4d8643/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-308cdbf2ab4d8643/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-308cdbf2ab4d8643/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true (dns block)

If you need me to access, download, or install something from one of these locations, you can either:


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…il previews

Co-authored-by: Undermozes <58026189+Undermozes@users.noreply.github.com>
Copilot AI changed the title [WIP] Add monitor layout visualization for improved user experience Add monitor layout visualization, switch animation, and thumbnail previews to viewer Mar 11, 2026
@Undermozes
Undermozes marked this pull request as ready for review March 11, 2026 22:15
@Undermozes
Undermozes merged commit cf87d00 into master Mar 11, 2026
1 check passed
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.

2 participants