From b3ea8886dd13b394e96a2784c924dc977a3e2058 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 21:58:02 +0000 Subject: [PATCH 1/2] Initial plan From 66d280c30135c5df4a3d2e766326653dbb8a8bd9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 22:10:22 +0000 Subject: [PATCH 2/2] Implement monitor layout visualization, switch animation, and thumbnail previews Co-authored-by: Undermozes <58026189+Undermozes@users.noreply.github.com> --- Desktop.Linux/Services/ScreenCapturerLinux.cs | 67 +++++++++++++ .../Abstractions/IScreenCapturer.cs | 6 +- Desktop.Shared/Services/ScreenCaster.cs | 2 + Desktop.Shared/Services/Viewer.cs | 42 +++++++- .../ViewModels/Fakes/FakeMainViewViewModel.cs | 5 + Desktop.Win/Services/ScreenCapturerWin.cs | 38 ++++++++ Server/wwwroot/css/remote-control.css | 58 +++++++++++ Server/wwwroot/src/DtoMessageHandler.js | 12 ++- Server/wwwroot/src/DtoMessageHandler.js.map | 2 +- Server/wwwroot/src/DtoMessageHandler.ts | 16 ++- Server/wwwroot/src/Enums/DtoType.js | 1 + Server/wwwroot/src/Enums/DtoType.js.map | 2 +- Server/wwwroot/src/Enums/DtoType.ts | 3 +- Server/wwwroot/src/Interfaces/Dtos.js.map | 2 +- Server/wwwroot/src/Interfaces/Dtos.ts | 17 ++++ Server/wwwroot/src/MessageSender.js | 6 +- Server/wwwroot/src/MessageSender.js.map | 2 +- Server/wwwroot/src/MessageSender.ts | 8 +- Server/wwwroot/src/UI.js | 78 ++++++++++++++- Server/wwwroot/src/UI.js.map | 2 +- Server/wwwroot/src/UI.ts | 97 +++++++++++++++++-- Shared/Models/Dtos/DisplayLayoutDto.cs | 25 +++++ Shared/Models/Dtos/DtoType.cs | 4 +- Shared/Models/Dtos/ScreenDataDto.cs | 3 + Shared/Models/Dtos/ScreenThumbnailDto.cs | 19 ++++ 25 files changed, 490 insertions(+), 27 deletions(-) create mode 100644 Shared/Models/Dtos/DisplayLayoutDto.cs create mode 100644 Shared/Models/Dtos/ScreenThumbnailDto.cs diff --git a/Desktop.Linux/Services/ScreenCapturerLinux.cs b/Desktop.Linux/Services/ScreenCapturerLinux.cs index f47ea059c..0dd194bfb 100644 --- a/Desktop.Linux/Services/ScreenCapturerLinux.cs +++ b/Desktop.Linux/Services/ScreenCapturerLinux.cs @@ -2,6 +2,7 @@ using Remotely.Desktop.Shared.Services; using Microsoft.Extensions.Logging; using Remotely.Shared.Primitives; +using Remotely.Shared.Models.Dtos; using SkiaSharp; using System.Drawing; using System.Runtime.InteropServices; @@ -46,6 +47,72 @@ public IEnumerable GetDisplayNames() return _x11Screens.Keys.Select(x => x.ToString()); } + public IEnumerable GetDisplayLayouts() + { + return _x11Screens.Select(kvp => new DisplayLayoutDto + { + DisplayName = kvp.Key, + X = kvp.Value.x, + Y = kvp.Value.y, + Width = kvp.Value.width, + Height = kvp.Value.height, + IsPrimary = kvp.Value.primary + }); + } + + public Result GetDisplayThumbnail(string displayName) + { + try + { + if (!_x11Screens.TryGetValue(displayName, out var screen)) + { + return Result.Fail($"Display '{displayName}' not found."); + } + + var bounds = new Rectangle(screen.x, screen.y, screen.width, screen.height); + var bitmap = new SKBitmap(bounds.Width, bounds.Height); + var window = LibX11.XDefaultRootWindow(Display); + + var imagePointer = LibX11.XGetImage(Display, + window, + bounds.X, + bounds.Y, + bounds.Width, + bounds.Height, + ~0, + 2); + + if (imagePointer == nint.Zero) + { + return Result.Ok(bitmap); + } + + var image = Marshal.PtrToStructure(imagePointer); + var pixels = bitmap.GetPixels(); + unsafe + { + var scan1 = (byte*)pixels.ToPointer(); + var scan2 = (byte*)image.data.ToPointer(); + var bytesPerPixel = bitmap.BytesPerPixel; + var totalSize = bitmap.Height * bitmap.Width * bytesPerPixel; + for (var counter = 0; counter < totalSize; counter++) + { + scan1[counter] = scan2[counter]; + } + } + + Marshal.DestroyStructure(imagePointer); + LibX11.XDestroyImage(imagePointer); + + return Result.Ok(bitmap); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error while capturing thumbnail for display {displayName}.", displayName); + return Result.Fail(ex); + } + } + public SKRect GetFrameDiffArea() { if (_currentFrame is null) diff --git a/Desktop.Shared/Abstractions/IScreenCapturer.cs b/Desktop.Shared/Abstractions/IScreenCapturer.cs index 960c41c91..6d972d6ab 100644 --- a/Desktop.Shared/Abstractions/IScreenCapturer.cs +++ b/Desktop.Shared/Abstractions/IScreenCapturer.cs @@ -1,4 +1,5 @@ -using Remotely.Shared.Primitives; +using Remotely.Shared.Models.Dtos; +using Remotely.Shared.Primitives; using SkiaSharp; using System.Drawing; @@ -13,12 +14,15 @@ public interface IScreenCapturer : IDisposable bool IsGpuAccelerated { get; } string SelectedScreen { get; } IEnumerable GetDisplayNames(); + IEnumerable GetDisplayLayouts(); SKRect GetFrameDiffArea(); Result GetImageDiff(); Result GetNextFrame(); + Result GetDisplayThumbnail(string displayName); + int GetScreenCount(); Rectangle GetVirtualScreenBounds(); diff --git a/Desktop.Shared/Services/ScreenCaster.cs b/Desktop.Shared/Services/ScreenCaster.cs index d4eaa45fe..fcd2d6dc6 100644 --- a/Desktop.Shared/Services/ScreenCaster.cs +++ b/Desktop.Shared/Services/ScreenCaster.cs @@ -116,6 +116,8 @@ await viewer.SendScreenData( screenBounds.Width, screenBounds.Height); + await viewer.SendScreenThumbnails(); + await viewer.SendCursorChange(_cursorIconWatcher.GetCurrentCursor()); await viewer.SendWindowsSessions(); diff --git a/Desktop.Shared/Services/Viewer.cs b/Desktop.Shared/Services/Viewer.cs index e8bff4af7..d89067b66 100644 --- a/Desktop.Shared/Services/Viewer.cs +++ b/Desktop.Shared/Services/Viewer.cs @@ -36,6 +36,7 @@ public interface IViewer : IDisposable Task SendDesktopStream(IAsyncEnumerable asyncEnumerable, Guid streamId); Task SendFile(FileUpload fileUpload, Action progressUpdateCallback, CancellationToken cancelToken); Task SendScreenData(string selectedDisplay, IEnumerable displayNames, int screenWidth, int screenHeight); + Task SendScreenThumbnails(); Task SendScreenSize(int width, int height); Task SendSessionMetrics(SessionMetricsDto metrics); Task SendWindowsSessions(); @@ -273,11 +274,50 @@ public async Task SendScreenData( DisplayNames = displayNames, SelectedDisplay = selectedDisplay, ScreenWidth = screenWidth, - ScreenHeight = screenHeight + ScreenHeight = screenHeight, + DisplayLayouts = Capturer.GetDisplayLayouts().ToArray() }; await TrySendToViewer(dto, DtoType.ScreenData, ViewerConnectionId); } + public async Task SendScreenThumbnails() + { + foreach (var displayName in Capturer.GetDisplayNames()) + { + try + { + var thumbnailResult = Capturer.GetDisplayThumbnail(displayName); + if (!thumbnailResult.IsSuccess || thumbnailResult.Value is null) + { + continue; + } + + using var bitmap = thumbnailResult.Value; + const int maxWidth = 320; + int thumbWidth = Math.Min(maxWidth, bitmap.Width); + int thumbHeight = (int)Math.Round((double)bitmap.Height / bitmap.Width * thumbWidth); + + using var scaledBitmap = bitmap.Resize(new SkiaSharp.SKImageInfo(thumbWidth, thumbHeight), SkiaSharp.SKFilterQuality.Low); + using var image = SkiaSharp.SKImage.FromBitmap(scaledBitmap); + using var data = image.Encode(SkiaSharp.SKEncodedImageFormat.Jpeg, 50); + var jpegBytes = data.ToArray(); + + var thumbnailDto = new ScreenThumbnailDto + { + DisplayName = displayName, + ImageBytes = jpegBytes, + Width = thumbWidth, + Height = thumbHeight + }; + await TrySendToViewer(thumbnailDto, DtoType.ScreenThumbnail, ViewerConnectionId); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error while sending thumbnail for display {displayName}.", displayName); + } + } + } + public async Task SendScreenSize(int width, int height) { var dto = new ScreenSizeDto(width, height); diff --git a/Desktop.UI/ViewModels/Fakes/FakeMainViewViewModel.cs b/Desktop.UI/ViewModels/Fakes/FakeMainViewViewModel.cs index 939946a3c..e8a9be663 100644 --- a/Desktop.UI/ViewModels/Fakes/FakeMainViewViewModel.cs +++ b/Desktop.UI/ViewModels/Fakes/FakeMainViewViewModel.cs @@ -144,6 +144,11 @@ public Task SendScreenData(string selectedDisplay, IEnumerable displayNa return Task.CompletedTask; } + public Task SendScreenThumbnails() + { + return Task.CompletedTask; + } + public Task SendScreenSize(int width, int height) { return Task.CompletedTask; diff --git a/Desktop.Win/Services/ScreenCapturerWin.cs b/Desktop.Win/Services/ScreenCapturerWin.cs index ca06b0128..36d790d55 100644 --- a/Desktop.Win/Services/ScreenCapturerWin.cs +++ b/Desktop.Win/Services/ScreenCapturerWin.cs @@ -24,6 +24,7 @@ using Remotely.Desktop.Shared.Abstractions; using Remotely.Desktop.Shared.Services; using Remotely.Shared.Models; +using Remotely.Shared.Models.Dtos; using Bitbound.SimpleMessenger; using Remotely.Desktop.Win.Helpers; using Remotely.Desktop.Win.Models; @@ -112,6 +113,43 @@ public IEnumerable GetDisplayNames() .Select(x => x.DeviceName); } + public IEnumerable GetDisplayLayouts() + { + return DisplaysEnumerationHelper.GetDisplays().Select(d => new DisplayLayoutDto + { + DisplayName = d.DeviceName, + X = d.MonitorArea.X, + Y = d.MonitorArea.Y, + Width = d.MonitorArea.Width, + Height = d.MonitorArea.Height, + IsPrimary = d.IsPrimary + }); + } + + public Result GetDisplayThumbnail(string displayName) + { + try + { + if (!_displays.TryGetValue(displayName, out var display)) + { + return Result.Fail($"Display '{displayName}' not found."); + } + + var area = display.MonitorArea; + using var bitmap = new Bitmap(area.Width, area.Height, PixelFormat.Format32bppArgb); + using (var graphic = Graphics.FromImage(bitmap)) + { + graphic.CopyFromScreen(area.Left, area.Top, 0, 0, new Size(area.Width, area.Height)); + } + return Result.Ok(bitmap.ToSKBitmap()); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error while capturing thumbnail for display {displayName}.", displayName); + return Result.Fail(ex); + } + } + public SKRect GetFrameDiffArea() { if (CurrentFrame is null) diff --git a/Server/wwwroot/css/remote-control.css b/Server/wwwroot/css/remote-control.css index 3c9adb52d..4c25effb6 100644 --- a/Server/wwwroot/css/remote-control.css +++ b/Server/wwwroot/css/remote-control.css @@ -480,3 +480,61 @@ footer { grid-template-columns: 0 2fr 1fr; } } + +/* Monitor switch animation */ +@keyframes switching-fade { + 0% { opacity: 1; } + 50% { opacity: 0.2; } + 100% { opacity: 1; } +} + +#screenViewer.switching { + animation: switching-fade 0.3s ease-in-out; +} + +/* Monitor layout diagram */ +.monitor-layout-diagram { + display: flex; + justify-content: center; + padding: 6px 4px 4px 4px; + cursor: default; +} + +.monitor-layout-rect { + fill: rgba(80, 120, 200, 0.3); + stroke: rgba(100, 150, 230, 0.8); + stroke-width: 1.5; + cursor: pointer; + transition: fill 0.15s ease; +} + +.monitor-layout-rect:hover { + fill: rgba(80, 120, 200, 0.6); +} + +.monitor-layout-rect-selected { + fill: rgba(0, 160, 120, 0.45); + stroke: rgba(0, 200, 150, 0.9); +} + +/* Monitor thumbnail buttons */ +#screenSelectMenu button { + display: flex; + flex-direction: column; + align-items: center; + padding: 6px; + gap: 4px; + width: 100%; + height: auto; + min-height: 40px; +} + +.monitor-thumbnail { + max-width: 160px; + width: 100%; + height: auto; + border-radius: 3px; + display: block; + background-color: rgba(40, 40, 40, 0.5); + min-height: 20px; +} diff --git a/Server/wwwroot/src/DtoMessageHandler.js b/Server/wwwroot/src/DtoMessageHandler.js index 647035303..4483068de 100644 --- a/Server/wwwroot/src/DtoMessageHandler.js +++ b/Server/wwwroot/src/DtoMessageHandler.js @@ -31,6 +31,8 @@ export class DtoMessageHandler { this.HandleFile(wrapper); case DtoType.SessionMetrics: await this.HandleSessionMetrics(wrapper); + case DtoType.ScreenThumbnail: + this.HandleScreenThumbnail(wrapper); default: break; } @@ -71,15 +73,23 @@ export class DtoMessageHandler { document.title = `${screenDataDto.MachineName} - Remote Control Session`; UI.ToggleConnectUI(false); UI.SetScreenSize(screenDataDto.ScreenWidth, screenDataDto.ScreenHeight); - UI.UpdateDisplays(screenDataDto.SelectedDisplay, screenDataDto.DisplayNames); + UI.UpdateDisplays(screenDataDto.SelectedDisplay, screenDataDto.DisplayNames, screenDataDto.DisplayLayouts); } HandleScreenSize(wrapper) { let screenSizeDto = TryComplete(wrapper); if (!screenSizeDto) { return; } + UI.ScreenViewer.classList.remove("switching"); UI.SetScreenSize(screenSizeDto.Width, screenSizeDto.Height); } + HandleScreenThumbnail(wrapper) { + let thumbnailDto = TryComplete(wrapper); + if (!thumbnailDto) { + return; + } + UI.UpdateThumbnail(thumbnailDto.DisplayName, thumbnailDto.ImageBytes); + } async HandleSessionMetrics(wrapper) { let metricsDto = TryComplete(wrapper); if (!metricsDto) { diff --git a/Server/wwwroot/src/DtoMessageHandler.js.map b/Server/wwwroot/src/DtoMessageHandler.js.map index 7384c8c4c..78bebc597 100644 --- a/Server/wwwroot/src/DtoMessageHandler.js.map +++ b/Server/wwwroot/src/DtoMessageHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"DtoMessageHandler.js","sourceRoot":"","sources":["DtoMessageHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAYnC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,MAAM,OAAO,GAAgB,MAAM,CAAC,aAAa,CAAC,CAAC;AAEnD,MAAM,OAAO,iBAAiB;IAE1B,KAAK,CAAC,kBAAkB,CAAC,IAAiB;QACtC,IAAI,OAAO,GAAG,OAAO,CAAC,MAAM,CAAa,IAAI,CAAC,CAAC;QAC/C,QAAQ,OAAO,CAAC,OAAO,EAAE,CAAC;YACtB,KAAK,OAAO,CAAC,WAAW;gBACpB,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;gBACtC,MAAM;YACV,KAAK,OAAO,CAAC,aAAa;gBACtB,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;gBAClC,MAAM;YACV,KAAK,OAAO,CAAC,YAAY;gBACrB,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBACjC,MAAM;YACV,KAAK,OAAO,CAAC,UAAU;gBACnB,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;gBAC/B,MAAM;YACV,KAAK,OAAO,CAAC,UAAU;gBACnB,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAA;gBAC9B,MAAM;YACV,KAAK,OAAO,CAAC,eAAe;gBACxB,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAA;gBACnC,MAAM;YACV,KAAK,OAAO,CAAC,IAAI;gBACb,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAC7B,KAAK,OAAO,CAAC,cAAc;gBACvB,MAAM,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;YAC7C;gBACI,MAAM;QACd,CAAC;IACL,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,OAAmB;QACvC,IAAI,WAAW,GAAG,WAAW,CAAiB,OAAO,CAAC,CAAC;QAEvD,IAAI,CAAC,WAAW,EAAE,CAAC;YACf,OAAO;QACX,CAAC;QAED,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,mBAAmB,CAAC,OAAmB;QACnC,IAAI,aAAa,GAAG,WAAW,CAAmB,OAAO,CAAC,CAAC;QAE3D,IAAI,CAAC,aAAa,EAAE,CAAC;YACjB,OAAO;QACX,CAAC;QAED,SAAS,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;IAC7E,CAAC;IACD,kBAAkB,CAAC,OAAmB;QAClC,IAAI,YAAY,GAAG,WAAW,CAAkB,OAAO,CAAC,CAAC;QAEzD,IAAI,CAAC,YAAY,EAAE,CAAC;YAChB,OAAO;QACX,CAAC;QAED,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,UAAU,EAAE,YAAY,CAAC,QAAQ,EAAE,YAAY,CAAC,QAAQ,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;IACrH,CAAC;IACD,UAAU,CAAC,OAAmB;QAC1B,IAAI,IAAI,GAAG,WAAW,CAAU,OAAO,CAAC,CAAC;QAEzC,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,OAAO;QACX,CAAC;QAED,WAAW,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IACD,gBAAgB,CAAC,OAAmB;QAChC,IAAI,aAAa,GAAG,WAAW,CAAgB,OAAO,CAAC,CAAC;QAExD,IAAI,CAAC,aAAa,EAAE,CAAC;YACjB,OAAO;QACX,CAAC;QAED,QAAQ,CAAC,KAAK,GAAG,GAAG,aAAa,CAAC,WAAW,2BAA2B,CAAC;QACzE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAC1B,EAAE,CAAC,aAAa,CAAC,aAAa,CAAC,WAAW,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;QACxE,EAAE,CAAC,cAAc,CAAC,aAAa,CAAC,eAAe,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACjF,CAAC;IAED,gBAAgB,CAAC,OAAmB;QAChC,IAAI,aAAa,GAAG,WAAW,CAAgB,OAAO,CAAC,CAAC;QAExD,IAAI,CAAC,aAAa,EAAE,CAAC;YACjB,OAAO;QACX,CAAC;QAED,EAAE,CAAC,aAAa,CAAC,aAAa,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,OAAmB;QAC1C,IAAI,UAAU,GAAG,WAAW,CAAoB,OAAO,CAAC,CAAC;QAEzD,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,OAAO;QACX,CAAC;QAED,EAAE,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;IAED,qBAAqB,CAAC,OAAmB;QACrC,IAAI,kBAAkB,GAAG,WAAW,CAAqB,OAAO,CAAC,CAAC;QAElE,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACtB,OAAO;QACX,CAAC;QAED,EAAE,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;IACjE,CAAC;CACJ"} \ No newline at end of file +{"version":3,"file":"DtoMessageHandler.js","sourceRoot":"","sources":["DtoMessageHandler.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/Server/wwwroot/src/DtoMessageHandler.ts b/Server/wwwroot/src/DtoMessageHandler.ts index 293360ce7..fd1c535f4 100644 --- a/Server/wwwroot/src/DtoMessageHandler.ts +++ b/Server/wwwroot/src/DtoMessageHandler.ts @@ -9,6 +9,7 @@ import { CursorChangeDto, ScreenDataDto, ScreenSizeDto, + ScreenThumbnailDto, FileDto, WindowsSessionsDto, DtoWrapper, @@ -47,6 +48,8 @@ export class DtoMessageHandler { this.HandleFile(wrapper); case DtoType.SessionMetrics: await this.HandleSessionMetrics(wrapper); + case DtoType.ScreenThumbnail: + this.HandleScreenThumbnail(wrapper); default: break; } @@ -99,7 +102,7 @@ export class DtoMessageHandler { document.title = `${screenDataDto.MachineName} - Remote Control Session`; UI.ToggleConnectUI(false); UI.SetScreenSize(screenDataDto.ScreenWidth, screenDataDto.ScreenHeight); - UI.UpdateDisplays(screenDataDto.SelectedDisplay, screenDataDto.DisplayNames); + UI.UpdateDisplays(screenDataDto.SelectedDisplay, screenDataDto.DisplayNames, screenDataDto.DisplayLayouts); } HandleScreenSize(wrapper: DtoWrapper) { @@ -109,9 +112,20 @@ export class DtoMessageHandler { return; } + UI.ScreenViewer.classList.remove("switching"); UI.SetScreenSize(screenSizeDto.Width, screenSizeDto.Height); } + HandleScreenThumbnail(wrapper: DtoWrapper) { + let thumbnailDto = TryComplete(wrapper); + + if (!thumbnailDto) { + return; + } + + UI.UpdateThumbnail(thumbnailDto.DisplayName, thumbnailDto.ImageBytes); + } + async HandleSessionMetrics(wrapper: DtoWrapper) { let metricsDto = TryComplete(wrapper); diff --git a/Server/wwwroot/src/Enums/DtoType.js b/Server/wwwroot/src/Enums/DtoType.js index a6a22ff5c..323633564 100644 --- a/Server/wwwroot/src/Enums/DtoType.js +++ b/Server/wwwroot/src/Enums/DtoType.js @@ -25,5 +25,6 @@ export var DtoType; DtoType[DtoType["OpenFileTransferWindow"] = 27] = "OpenFileTransferWindow"; DtoType[DtoType["SessionMetrics"] = 28] = "SessionMetrics"; DtoType[DtoType["QualityMode"] = 29] = "QualityMode"; + DtoType[DtoType["ScreenThumbnail"] = 30] = "ScreenThumbnail"; })(DtoType || (DtoType = {})); //# sourceMappingURL=DtoType.js.map \ No newline at end of file diff --git a/Server/wwwroot/src/Enums/DtoType.js.map b/Server/wwwroot/src/Enums/DtoType.js.map index 5e0873e8f..9af881633 100644 --- a/Server/wwwroot/src/Enums/DtoType.js.map +++ b/Server/wwwroot/src/Enums/DtoType.js.map @@ -1 +1 @@ -{"version":3,"file":"DtoType.js","sourceRoot":"","sources":["DtoType.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,OA0BX;AA1BD,WAAY,OAAO;IACf,iDAAc,CAAA;IACd,iDAAc,CAAA;IACd,uDAAiB,CAAA;IACjB,mDAAe,CAAA;IACf,qDAAgB,CAAA;IAChB,qDAAgB,CAAA;IAChB,+CAAa,CAAA;IACb,+CAAa,CAAA;IACb,4CAAY,CAAA;IACZ,oCAAQ,CAAA;IACR,kDAAe,CAAA;IACf,4CAAY,CAAA;IACZ,wCAAU,CAAA;IACV,kDAAe,CAAA;IACf,oDAAgB,CAAA;IAChB,8DAAqB,CAAA;IACrB,sDAAiB,CAAA;IACjB,8CAAa,CAAA;IACb,sCAAS,CAAA;IACT,4DAAoB,CAAA;IACpB,0DAAmB,CAAA;IACnB,wDAAkB,CAAA;IAClB,0EAA2B,CAAA;IAC3B,0DAAmB,CAAA;IACnB,oDAAgB,CAAA;AACpB,CAAC,EA1BW,OAAO,KAAP,OAAO,QA0BlB"} \ No newline at end of file +{"version":3,"file":"DtoType.js","sourceRoot":"","sources":["DtoType.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,OA2BX;AA3BD,WAAY,OAAO;IACf,iDAAc,CAAA;IACd,iDAAc,CAAA;IACd,uDAAiB,CAAA;IACjB,mDAAe,CAAA;IACf,qDAAgB,CAAA;IAChB,qDAAgB,CAAA;IAChB,+CAAa,CAAA;IACb,+CAAa,CAAA;IACb,4CAAY,CAAA;IACZ,oCAAQ,CAAA;IACR,kDAAe,CAAA;IACf,4CAAY,CAAA;IACZ,wCAAU,CAAA;IACV,kDAAe,CAAA;IACf,oDAAgB,CAAA;IAChB,8DAAqB,CAAA;IACrB,sDAAiB,CAAA;IACjB,8CAAa,CAAA;IACb,sCAAS,CAAA;IACT,4DAAoB,CAAA;IACpB,0DAAmB,CAAA;IACnB,wDAAkB,CAAA;IAClB,0EAA2B,CAAA;IAC3B,0DAAmB,CAAA;IACnB,oDAAgB,CAAA;IAChB,4DAAoB,CAAA;AACxB,CAAC,EA3BW,OAAO,KAAP,OAAO,QA2BlB"} \ No newline at end of file diff --git a/Server/wwwroot/src/Enums/DtoType.ts b/Server/wwwroot/src/Enums/DtoType.ts index b0a47691a..abdbcde82 100644 --- a/Server/wwwroot/src/Enums/DtoType.ts +++ b/Server/wwwroot/src/Enums/DtoType.ts @@ -23,5 +23,6 @@ FrameReceived = 25, OpenFileTransferWindow = 27, SessionMetrics = 28, - QualityMode = 29 + QualityMode = 29, + ScreenThumbnail = 30 } \ No newline at end of file diff --git a/Server/wwwroot/src/Interfaces/Dtos.js.map b/Server/wwwroot/src/Interfaces/Dtos.js.map index 88edbc9f0..a45f8600b 100644 --- a/Server/wwwroot/src/Interfaces/Dtos.js.map +++ b/Server/wwwroot/src/Interfaces/Dtos.js.map @@ -1 +1 @@ -{"version":3,"file":"Dtos.js","sourceRoot":"","sources":["Dtos.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"Dtos.js","sourceRoot":"","sources":["Dtos.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/Server/wwwroot/src/Interfaces/Dtos.ts b/Server/wwwroot/src/Interfaces/Dtos.ts index 5e1404c1c..7fa43fde0 100644 --- a/Server/wwwroot/src/Interfaces/Dtos.ts +++ b/Server/wwwroot/src/Interfaces/Dtos.ts @@ -144,6 +144,23 @@ export interface ScreenDataDto { MachineName: string; ScreenWidth: number; ScreenHeight: number; + DisplayLayouts: DisplayLayoutDto[]; +} + +export interface DisplayLayoutDto { + DisplayName: string; + X: number; + Y: number; + Width: number; + Height: number; + IsPrimary: boolean; +} + +export interface ScreenThumbnailDto { + DisplayName: string; + ImageBytes: Uint8Array; + Width: number; + Height: number; } export interface ScreenSizeDto { diff --git a/Server/wwwroot/src/MessageSender.js b/Server/wwwroot/src/MessageSender.js index 69aa68afc..5305baded 100644 --- a/Server/wwwroot/src/MessageSender.js +++ b/Server/wwwroot/src/MessageSender.js @@ -1,7 +1,7 @@ import { ViewerApp } from "./App.js"; import { CtrlAltDelDto, KeyDownDto, KeyPressDto, KeyUpDto, MouseDownDto, MouseMoveDto, MouseUpDto, MouseWheelDto, SelectScreenDto, TapDto, ToggleAudioDto, ToggleBlockInputDto, TextTransferDto, FileDto, WindowsSessionsDto, EmptyDto, FrameReceivedDto, SetQualityModeDto } from "./Interfaces/Dtos.js"; import { CreateGUID } from "./Utilities.js"; -import { FileTransferProgress } from "./UI.js"; +import { FileTransferProgress, ScreenViewer, ShowToast } from "./UI.js"; import { DtoType } from "./Enums/DtoType.js"; import { RemoteControlMode } from "./Enums/RemoteControlMode.js"; export class MessageSender { @@ -18,8 +18,10 @@ export class MessageSender { var dto = new FrameReceivedDto(timestamp); await ViewerApp.ViewerHubConnection.SendDtoToClient(dto, DtoType.FrameReceived); } - async SendSelectScreen(displayName) { + async SendSelectScreen(displayName, displayLabel) { var dto = new SelectScreenDto(displayName); + ScreenViewer.classList.add("switching"); + ShowToast(`Switching to ${displayLabel || displayName}...`); await ViewerApp.ViewerHubConnection.SendDtoToClient(dto, DtoType.SelectScreen); } async SendMouseMove(percentX, percentY) { diff --git a/Server/wwwroot/src/MessageSender.js.map b/Server/wwwroot/src/MessageSender.js.map index 562d2a5ec..ad8edd0fd 100644 --- a/Server/wwwroot/src/MessageSender.js.map +++ b/Server/wwwroot/src/MessageSender.js.map @@ -1 +1 @@ -{"version":3,"file":"MessageSender.js","sourceRoot":"","sources":["MessageSender.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"MessageSender.js","sourceRoot":"","sources":["MessageSender.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/Server/wwwroot/src/MessageSender.ts b/Server/wwwroot/src/MessageSender.ts index 73dbe078b..cd2883957 100644 --- a/Server/wwwroot/src/MessageSender.ts +++ b/Server/wwwroot/src/MessageSender.ts @@ -1,4 +1,4 @@ -import { ViewerApp } from "./App.js"; +import { ViewerApp } from "./App.js"; import { CtrlAltDelDto, KeyDownDto, @@ -21,7 +21,7 @@ import { SetQualityModeDto } from "./Interfaces/Dtos.js"; import { CreateGUID } from "./Utilities.js"; -import { FileTransferProgress } from "./UI.js"; +import { FileTransferProgress, ScreenViewer, ShowToast } from "./UI.js"; import { DtoType } from "./Enums/DtoType.js"; import { RemoteControlMode } from "./Enums/RemoteControlMode.js"; @@ -39,8 +39,10 @@ export class MessageSender { var dto = new FrameReceivedDto(timestamp); await ViewerApp.ViewerHubConnection.SendDtoToClient(dto, DtoType.FrameReceived); } - async SendSelectScreen(displayName: string) { + async SendSelectScreen(displayName: string, displayLabel?: string) { var dto = new SelectScreenDto(displayName); + ScreenViewer.classList.add("switching"); + ShowToast(`Switching to ${displayLabel || displayName}...`); await ViewerApp.ViewerHubConnection.SendDtoToClient(dto, DtoType.SelectScreen); } async SendMouseMove(percentX: number, percentY: number) { diff --git a/Server/wwwroot/src/UI.js b/Server/wwwroot/src/UI.js index de41d2ff2..560752c92 100644 --- a/Server/wwwroot/src/UI.js +++ b/Server/wwwroot/src/UI.js @@ -60,6 +60,15 @@ export var QualityModeLabel = document.getElementById("qualityModeLabel"); export var QualityAutoButton = document.getElementById("qualityAutoButton"); export var QualityPerformanceButton = document.getElementById("qualityPerformanceButton"); export var QualityHighButton = document.getElementById("qualityHighButton"); +const _thumbnailMap = new Map(); +export function UpdateThumbnail(displayName, imageBytes) { + var base64 = ConvertUInt8ArrayToBase64(imageBytes); + _thumbnailMap.set(displayName, `data:image/jpeg;base64,${base64}`); + var img = document.querySelector(`[data-display="${CSS.escape(displayName)}"] img`); + if (img) { + img.src = _thumbnailMap.get(displayName); + } +} export function CloseAllPopupMenus(exceptMenuId) { PopupMenus.forEach(x => { if (x.id != exceptMenuId) { @@ -150,25 +159,84 @@ export function UpdateCursor(imageBytes, hotSpotX, hotSpotY, cssOverride) { ScreenViewer.style.cursor = `url('data:image/png;base64,${base64}') ${hotSpotX} ${hotSpotY}, default`; } } -export function UpdateDisplays(selectedDisplay, displayNames) { +export function UpdateDisplays(selectedDisplay, displayNames, displayLayouts) { ScreenSelectMenu.innerHTML = ""; + if (displayLayouts && displayLayouts.length > 1) { + var layoutContainer = RenderMonitorLayout(selectedDisplay, displayLayouts); + ScreenSelectMenu.appendChild(layoutContainer); + } for (let i = 0; i < displayNames.length; i++) { var button = document.createElement("button"); - button.innerHTML = `Monitor ${i}`; + button.setAttribute("data-display", displayNames[i]); + var img = document.createElement("img"); + img.className = "monitor-thumbnail"; + img.alt = `Monitor ${i + 1} (${displayNames[i]})`; + var cachedSrc = _thumbnailMap.get(displayNames[i]); + if (cachedSrc) { + img.src = cachedSrc; + } + var label = document.createElement("span"); + label.innerText = `Monitor ${i + 1}`; if (displayNames[i] == selectedDisplay) { button.classList.add("toggled"); } + button.appendChild(img); + button.appendChild(label); ScreenSelectMenu.appendChild(button); button.onclick = (ev) => { - ViewerApp.MessageSender.SendSelectScreen(displayNames[i]); + ViewerApp.MessageSender.SendSelectScreen(displayNames[i], `Monitor ${i + 1}`); ScreenSelectMenu.classList.toggle("open"); - ScreenSelectMenu.querySelectorAll("button").forEach(button => { - button.classList.remove("toggled"); + ScreenSelectMenu.querySelectorAll("button").forEach(btn => { + btn.classList.remove("toggled"); }); ev.currentTarget.classList.add("toggled"); }; } } +export function RenderMonitorLayout(selectedDisplay, layouts) { + var container = document.createElement("div"); + container.className = "monitor-layout-diagram"; + var minX = Math.min(...layouts.map(l => l.X)); + var minY = Math.min(...layouts.map(l => l.Y)); + var maxX = Math.max(...layouts.map(l => l.X + l.Width)); + var maxY = Math.max(...layouts.map(l => l.Y + l.Height)); + var totalW = maxX - minX || 1; + var totalH = maxY - minY || 1; + const svgW = 200; + const svgH = Math.max(40, Math.round(svgW * totalH / totalW)); + const padding = 4; + var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + svg.setAttribute("width", String(svgW + padding * 2)); + svg.setAttribute("height", String(svgH + padding * 2)); + svg.setAttribute("viewBox", `0 0 ${svgW + padding * 2} ${svgH + padding * 2}`); + svg.style.display = "block"; + for (let li = 0; li < layouts.length; li++) { + var layout = layouts[li]; + var rx = padding + Math.round((layout.X - minX) / totalW * svgW); + var ry = padding + Math.round((layout.Y - minY) / totalH * svgH); + var rw = Math.max(1, Math.round(layout.Width / totalW * svgW) - 2); + var rh = Math.max(1, Math.round(layout.Height / totalH * svgH) - 2); + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + rect.setAttribute("x", String(rx)); + rect.setAttribute("y", String(ry)); + rect.setAttribute("width", String(rw)); + rect.setAttribute("height", String(rh)); + rect.setAttribute("rx", "3"); + rect.classList.add("monitor-layout-rect"); + if (layout.DisplayName === selectedDisplay) { + rect.classList.add("monitor-layout-rect-selected"); + } + var displayName = layout.DisplayName; + var monitorLabel = `Monitor ${li + 1}`; + rect.addEventListener("click", () => { + ViewerApp.MessageSender.SendSelectScreen(displayName, monitorLabel); + ScreenSelectMenu.classList.toggle("open"); + }); + svg.appendChild(rect); + } + container.appendChild(svg); + return container; +} export function UpdateMetrics(metricsDto) { FpsDiv.innerHTML = metricsDto.Fps.toFixed(0); MbpsDiv.innerHTML = metricsDto.Mbps.toFixed(2); diff --git a/Server/wwwroot/src/UI.js.map b/Server/wwwroot/src/UI.js.map index 09f3ca7ca..2a70eeb1d 100644 --- a/Server/wwwroot/src/UI.js.map +++ b/Server/wwwroot/src/UI.js.map @@ -1 +1 @@ -{"version":3,"file":"UI.js","sourceRoot":"","sources":["UI.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"UI.js","sourceRoot":"","sources":["UI.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/Server/wwwroot/src/UI.ts b/Server/wwwroot/src/UI.ts index 6ba2f2dbc..559d7cdfd 100644 --- a/Server/wwwroot/src/UI.ts +++ b/Server/wwwroot/src/UI.ts @@ -3,7 +3,7 @@ import { ConvertUInt8ArrayToBase64 } from "./Utilities.js"; import { WindowsSession } from "./Models/WindowsSession.js"; import { WindowsSessionType } from "./Enums/WindowsSessionType.js"; import { RemoteControlMode } from "./Enums/RemoteControlMode.js"; -import { SessionMetricsDto } from "./Interfaces/Dtos.js"; +import { SessionMetricsDto, DisplayLayoutDto } from "./Interfaces/Dtos.js"; export var AudioButton = document.getElementById("audioButton") as HTMLButtonElement; export var MenuButton = document.getElementById("menuButton") as HTMLButtonElement; @@ -64,6 +64,18 @@ export var QualityAutoButton = document.getElementById("qualityAutoButton") as H export var QualityPerformanceButton = document.getElementById("qualityPerformanceButton") as HTMLButtonElement; export var QualityHighButton = document.getElementById("qualityHighButton") as HTMLButtonElement; +const _thumbnailMap = new Map(); + +export function UpdateThumbnail(displayName: string, imageBytes: Uint8Array): void { + var base64 = ConvertUInt8ArrayToBase64(imageBytes); + _thumbnailMap.set(displayName, `data:image/jpeg;base64,${base64}`); + + var img = document.querySelector(`[data-display="${CSS.escape(displayName)}"] img`) as HTMLImageElement; + if (img) { + img.src = _thumbnailMap.get(displayName); + } +} + export function CloseAllPopupMenus(exceptMenuId: string) { PopupMenus.forEach(x => { if (x.id != exceptMenuId) { @@ -173,26 +185,99 @@ export function UpdateCursor(imageBytes: Uint8Array, hotSpotX: number, hotSpotY: } } -export function UpdateDisplays(selectedDisplay: string, displayNames: string[]) { +export function UpdateDisplays(selectedDisplay: string, displayNames: string[], displayLayouts?: DisplayLayoutDto[]) { ScreenSelectMenu.innerHTML = ""; + + if (displayLayouts && displayLayouts.length > 1) { + var layoutContainer = RenderMonitorLayout(selectedDisplay, displayLayouts); + ScreenSelectMenu.appendChild(layoutContainer); + } + for (let i = 0; i < displayNames.length; i++) { var button = document.createElement("button"); - button.innerHTML = `Monitor ${i}`; + button.setAttribute("data-display", displayNames[i]); + + var img = document.createElement("img"); + img.className = "monitor-thumbnail"; + img.alt = `Monitor ${i + 1} (${displayNames[i]})`; + var cachedSrc = _thumbnailMap.get(displayNames[i]); + if (cachedSrc) { + img.src = cachedSrc; + } + + var label = document.createElement("span"); + label.innerText = `Monitor ${i + 1}`; + if (displayNames[i] == selectedDisplay) { button.classList.add("toggled"); } + button.appendChild(img); + button.appendChild(label); ScreenSelectMenu.appendChild(button); button.onclick = (ev: MouseEvent) => { - ViewerApp.MessageSender.SendSelectScreen(displayNames[i]); + ViewerApp.MessageSender.SendSelectScreen(displayNames[i], `Monitor ${i + 1}`); ScreenSelectMenu.classList.toggle("open"); - ScreenSelectMenu.querySelectorAll("button").forEach(button => { - button.classList.remove("toggled"); + ScreenSelectMenu.querySelectorAll("button").forEach(btn => { + btn.classList.remove("toggled"); }); (ev.currentTarget as HTMLButtonElement).classList.add("toggled"); }; } } +export function RenderMonitorLayout(selectedDisplay: string, layouts: DisplayLayoutDto[]): HTMLElement { + var container = document.createElement("div"); + container.className = "monitor-layout-diagram"; + + var minX = Math.min(...layouts.map(l => l.X)); + var minY = Math.min(...layouts.map(l => l.Y)); + var maxX = Math.max(...layouts.map(l => l.X + l.Width)); + var maxY = Math.max(...layouts.map(l => l.Y + l.Height)); + var totalW = maxX - minX || 1; + var totalH = maxY - minY || 1; + + const svgW = 200; + const svgH = Math.max(40, Math.round(svgW * totalH / totalW)); + const padding = 4; + + var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + svg.setAttribute("width", String(svgW + padding * 2)); + svg.setAttribute("height", String(svgH + padding * 2)); + svg.setAttribute("viewBox", `0 0 ${svgW + padding * 2} ${svgH + padding * 2}`); + svg.style.display = "block"; + + for (let li = 0; li < layouts.length; li++) { + var layout = layouts[li]; + var rx = padding + Math.round((layout.X - minX) / totalW * svgW); + var ry = padding + Math.round((layout.Y - minY) / totalH * svgH); + var rw = Math.max(1, Math.round(layout.Width / totalW * svgW) - 2); + var rh = Math.max(1, Math.round(layout.Height / totalH * svgH) - 2); + + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + rect.setAttribute("x", String(rx)); + rect.setAttribute("y", String(ry)); + rect.setAttribute("width", String(rw)); + rect.setAttribute("height", String(rh)); + rect.setAttribute("rx", "3"); + rect.classList.add("monitor-layout-rect"); + if (layout.DisplayName === selectedDisplay) { + rect.classList.add("monitor-layout-rect-selected"); + } + + var displayName = layout.DisplayName; + var monitorLabel = `Monitor ${li + 1}`; + rect.addEventListener("click", () => { + ViewerApp.MessageSender.SendSelectScreen(displayName, monitorLabel); + ScreenSelectMenu.classList.toggle("open"); + }); + + svg.appendChild(rect); + } + + container.appendChild(svg); + return container; +} + export function UpdateMetrics(metricsDto: SessionMetricsDto) { FpsDiv.innerHTML = metricsDto.Fps.toFixed(0); diff --git a/Shared/Models/Dtos/DisplayLayoutDto.cs b/Shared/Models/Dtos/DisplayLayoutDto.cs new file mode 100644 index 000000000..3270bcafd --- /dev/null +++ b/Shared/Models/Dtos/DisplayLayoutDto.cs @@ -0,0 +1,25 @@ +using System.Runtime.Serialization; + +namespace Remotely.Shared.Models.Dtos; + +[DataContract] +public class DisplayLayoutDto +{ + [DataMember(Name = "DisplayName")] + public string DisplayName { get; init; } = string.Empty; + + [DataMember(Name = "X")] + public int X { get; init; } + + [DataMember(Name = "Y")] + public int Y { get; init; } + + [DataMember(Name = "Width")] + public int Width { get; init; } + + [DataMember(Name = "Height")] + public int Height { get; init; } + + [DataMember(Name = "IsPrimary")] + public bool IsPrimary { get; init; } +} diff --git a/Shared/Models/Dtos/DtoType.cs b/Shared/Models/Dtos/DtoType.cs index b8a758032..1c2dfb212 100644 --- a/Shared/Models/Dtos/DtoType.cs +++ b/Shared/Models/Dtos/DtoType.cs @@ -54,5 +54,7 @@ public enum DtoType [EnumMember] SessionMetrics = 28, [EnumMember] - QualityMode = 29 + QualityMode = 29, + [EnumMember] + ScreenThumbnail = 30 } diff --git a/Shared/Models/Dtos/ScreenDataDto.cs b/Shared/Models/Dtos/ScreenDataDto.cs index c6372b12a..5838d2e9b 100644 --- a/Shared/Models/Dtos/ScreenDataDto.cs +++ b/Shared/Models/Dtos/ScreenDataDto.cs @@ -19,4 +19,7 @@ public class ScreenDataDto [DataMember(Name = "ScreenHeight")] public int ScreenHeight { get; init; } + + [DataMember(Name = "DisplayLayouts")] + public IEnumerable DisplayLayouts { get; init; } = Enumerable.Empty(); } diff --git a/Shared/Models/Dtos/ScreenThumbnailDto.cs b/Shared/Models/Dtos/ScreenThumbnailDto.cs new file mode 100644 index 000000000..c3b8be6b0 --- /dev/null +++ b/Shared/Models/Dtos/ScreenThumbnailDto.cs @@ -0,0 +1,19 @@ +using System.Runtime.Serialization; + +namespace Remotely.Shared.Models.Dtos; + +[DataContract] +public class ScreenThumbnailDto +{ + [DataMember(Name = "DisplayName")] + public string DisplayName { get; init; } = string.Empty; + + [DataMember(Name = "ImageBytes")] + public byte[] ImageBytes { get; init; } = Array.Empty(); + + [DataMember(Name = "Width")] + public int Width { get; init; } + + [DataMember(Name = "Height")] + public int Height { get; init; } +}