diff --git a/Desktop.Core/Services/Viewer.cs b/Desktop.Core/Services/Viewer.cs index 72094338..f273a75a 100644 --- a/Desktop.Core/Services/Viewer.cs +++ b/Desktop.Core/Services/Viewer.cs @@ -94,7 +94,7 @@ namespace Remotely.Desktop.Core.Services ImageQuality = Math.Min(DefaultQuality, ImageQuality + 2); } - // Limit to 20 FPS. + // Limit FPS. _ = TaskHelper.DelayUntil(() => !PendingSentFrames.TryPeek(out var result) || DateTimeOffset.Now - result.Timestamp > TimeSpan.FromMilliseconds(50), TimeSpan.FromSeconds(5)); diff --git a/Desktop.Win/Services/ScreenCapturerWin.cs b/Desktop.Win/Services/ScreenCapturerWin.cs index ff282f11..20fc7c59 100644 --- a/Desktop.Win/Services/ScreenCapturerWin.cs +++ b/Desktop.Win/Services/ScreenCapturerWin.cs @@ -82,66 +82,47 @@ namespace Remotely.Desktop.Win.Services { lock (_screenBoundsLock) { - Bitmap returnFrame = null; - var frameCompletedEvent = new ManualResetEventSlim(); - - // This is necessary to ensure SwitchToInputDesktop works. Threads - // that have hooks in the current desktop will not succeed. - var captureThread = new Thread(() => + try { - try - { - Win32Interop.SwitchToInputDesktop(); + Win32Interop.SwitchToInputDesktop(); - if (NeedsInit) + if (NeedsInit) + { + 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.TryGetValue(SelectedScreen, out var dxDisplay) && + dxDisplay.Rotation == DisplayModeRotation.Identity) + { + var (result, frame) = GetDirectXFrame(); + + if (result == GetDirectXFrameResult.Timeout) { - Logger.Write("Init needed in GetNextFrame."); - Init(); - NeedsInit = false; + return null; } - // 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.TryGetValue(SelectedScreen, out var dxDisplay) && - dxDisplay.Rotation == DisplayModeRotation.Identity) + if (result == GetDirectXFrameResult.Success) { - var (result, frame) = GetDirectXFrame(); - - if (result == GetDirectXFrameResult.Timeout) - { - return; - } - - if (result == GetDirectXFrameResult.Success) - { - returnFrame = frame; - return; - } + return frame; } - - returnFrame = GetBitBltFrame(); - } - catch (Exception e) - { - Logger.Write(e); - NeedsInit = true; - } - finally - { - frameCompletedEvent.Set(); - } - }); - captureThread.SetApartmentState(ApartmentState.STA); - captureThread.Start(); + return GetBitBltFrame(); - frameCompletedEvent.Wait(); + } + catch (Exception e) + { + Logger.Write(e); + NeedsInit = true; + } - return returnFrame; + return null; } } @@ -168,6 +149,8 @@ namespace Remotely.Desktop.Win.Services InitDirectX(); ScreenChanged?.Invoke(this, CurrentScreenBounds); + + NeedsInit = false; } public void SetSelectedScreen(string displayName) diff --git a/Shared/Win32/Win32Interop.cs b/Shared/Win32/Win32Interop.cs index c9934089..a6b51641 100644 --- a/Shared/Win32/Win32Interop.cs +++ b/Shared/Win32/Win32Interop.cs @@ -207,16 +207,17 @@ namespace Remotely.Shared.Win32 public static bool SwitchToInputDesktop() { - var inputDesktop = OpenInputDesktop(); try { + CloseDesktop(_lastInputDesktop); + var inputDesktop = OpenInputDesktop(); + if (inputDesktop == IntPtr.Zero) { return false; } var result = SetThreadDesktop(inputDesktop) && SwitchDesktop(inputDesktop); - CloseDesktop(_lastInputDesktop); _lastInputDesktop = inputDesktop; return result; }