Add orientation to DirectXOutput model to detect orientation of non-primary monitors.

This commit is contained in:
Jared Goodwin 2021-05-07 16:54:39 -07:00
parent cdc7ba818d
commit 8ca0f77aa8
4 changed files with 93 additions and 9 deletions

View File

@ -40,7 +40,6 @@ namespace Remotely.Desktop.Core.Services
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest)
{
try
{
var sendFramesLock = new SemaphoreSlim(1, 1);
@ -49,6 +48,7 @@ namespace Remotely.Desktop.Core.Services
var currentQuality = _maxQuality;
Bitmap currentFrame = null;
Bitmap previousFrame = null;
var sw = Stopwatch.StartNew();
var viewer = ServiceContainer.Instance.GetRequiredService<Viewer>();
viewer.Name = screenCastRequest.RequesterName;
@ -118,6 +118,9 @@ namespace Remotely.Desktop.Core.Services
{
try
{
TaskHelper.DelayUntil(() => sw.Elapsed.TotalMilliseconds > 40, TimeSpan.FromSeconds(5));
sw.Restart();
if (viewer.IsUsingWebRtcVideo)
{
Thread.Sleep(100);

View File

@ -10,17 +10,20 @@ namespace Remotely.Desktop.Win.Models
public DirectXOutput(Adapter1 adapter,
SharpDX.Direct3D11.Device device,
OutputDuplication outputDuplication,
Texture2D texture2D)
Texture2D texture2D,
DisplayModeRotation rotation)
{
Adapter = adapter;
Device = device;
OutputDuplication = outputDuplication;
Texture2D = texture2D;
Rotation = rotation;
}
public Adapter1 Adapter { get; }
public SharpDX.Direct3D11.Device Device { get; }
public OutputDuplication OutputDuplication { get; }
public DisplayModeRotation Rotation { get; }
public Texture2D Texture2D { get; }
public void Dispose()

View File

@ -34,6 +34,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
@ -91,15 +92,14 @@ namespace Remotely.Desktop.Win.Services
Logger.Write("Init needed in GetNextFrame.");
Init();
}
// Sometimes DX will result in a timeout, even when there are changes
// on the screen. I've observed this when a laptop lid is closed, or
// on some machines that aren't connected to a monitor. This will
// have it fall back to BitBlt in those cases.
// TODO: Make DX capture work with changed screen orientation.
if (_directxScreens.ContainsKey(SelectedScreen) &&
SystemInformation.ScreenOrientation != ScreenOrientation.Angle270 &&
SystemInformation.ScreenOrientation != ScreenOrientation.Angle90)
if (_directxScreens.TryGetValue(SelectedScreen, out var dxDisplay) &&
dxDisplay.Rotation == DisplayModeRotation.Identity)
{
var (result, frame) = GetDirectXFrame();
@ -337,7 +337,8 @@ namespace Remotely.Desktop.Win.Services
new DirectXOutput(adapter,
device,
output1.DuplicateOutput(device),
texture2D));
texture2D,
output1.Description.Rotation));
}
catch (Exception ex)
{

View File

@ -1054,6 +1054,79 @@ namespace Remotely.Shared.Win32
MAPVK_VK_TO_VSC_EX = 4
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
public struct DEVMODE
{
public const int CCHDEVICENAME = 32;
public const int CCHFORMNAME = 32;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
[FieldOffset(0)]
public string dmDeviceName;
[FieldOffset(32)]
public Int16 dmSpecVersion;
[FieldOffset(34)]
public Int16 dmDriverVersion;
[FieldOffset(36)]
public Int16 dmSize;
[FieldOffset(38)]
public Int16 dmDriverExtra;
[FieldOffset(40)]
public short dmFields;
[FieldOffset(44)]
Int16 dmOrientation;
[FieldOffset(46)]
Int16 dmPaperSize;
[FieldOffset(48)]
Int16 dmPaperLength;
[FieldOffset(50)]
Int16 dmPaperWidth;
[FieldOffset(52)]
Int16 dmScale;
[FieldOffset(54)]
Int16 dmCopies;
[FieldOffset(56)]
Int16 dmDefaultSource;
[FieldOffset(58)]
Int16 dmPrintQuality;
[FieldOffset(44)]
public POINT dmPosition;
[FieldOffset(52)]
public Int32 dmDisplayOrientation;
[FieldOffset(56)]
public Int32 dmDisplayFixedOutput;
[FieldOffset(60)]
public short dmColor; // See note below!
[FieldOffset(62)]
public short dmDuplex; // See note below!
[FieldOffset(64)]
public short dmYResolution;
[FieldOffset(66)]
public short dmTTOption;
[FieldOffset(68)]
public short dmCollate; // See note below!
[FieldOffset(70)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
public string dmFormName;
[FieldOffset(102)]
public Int16 dmLogPixels;
[FieldOffset(104)]
public Int32 dmBitsPerPel;
[FieldOffset(108)]
public Int32 dmPelsWidth;
[FieldOffset(112)]
public Int32 dmPelsHeight;
[FieldOffset(116)]
public Int32 dmDisplayFlags;
[FieldOffset(116)]
public Int32 dmNup;
[FieldOffset(120)]
public Int32 dmDisplayFrequency;
}
#endregion
#region Structs
@ -1070,10 +1143,11 @@ namespace Remotely.Shared.Win32
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public Int32 x;
public Int32 y;
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct CursorInfo
{
@ -1185,6 +1259,9 @@ namespace Remotely.Shared.Win32
[DllImport("user32.dll")]
public static extern bool EnumDesktopsA(IntPtr hwinsta, EnumDesktopsDelegate lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
public static extern bool EnumDisplaySettingsEx(string lpszDeviceName, uint iModeNum, out DEVMODE lpDevMode, uint dwFlags);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr OpenInputDesktop(uint dwFlags, bool fInherit, ACCESS_MASK dwDesiredAccess);