From 687be3b6fd248ccd7888debffaee69ce3087dcbe Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Thu, 27 Jul 2023 21:07:03 -0500 Subject: [PATCH] Update to Avalonia@e394ca59 (Jul 27 2023) (#38) --- .../Avalonia.Mac/AvaloniaNativePlatform.cs | 10 +++- .../Avalonia.Win32/IBlurHost.cs | 3 +- .../Avalonia.Win32/WinUiCompositionShared.cs | 11 ++-- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 2 +- .../Avalonia.Win32/WindowImpl.cs | 23 +++++--- .../Avalonia.X11/X11Clipboard.cs | 54 ++++++++++++------- src/Modern.WindowKit/Avalonia.X11/X11Info.cs | 16 +++++- .../Avalonia.X11/X11Platform.cs | 6 +-- .../Avalonia.X11/X11Structs.cs | 5 +- .../Avalonia.X11/X11Window.Ime.cs | 13 +++-- src/Modern.WindowKit/Avalonia.X11/XLib.cs | 2 +- .../AvaloniaSynchronizationContext.cs | 7 +-- src/Modern.WindowKit/Dispatcher.Invoke.cs | 16 +++--- src/Modern.WindowKit/Dispatcher.MainLoop.cs | 2 +- src/Modern.WindowKit/Dispatcher.Queue.cs | 20 ++++--- src/Modern.WindowKit/Dispatcher.Timers.cs | 2 +- src/Modern.WindowKit/Dispatcher.cs | 5 +- src/Modern.WindowKit/DispatcherFrame.cs | 8 ++- src/Modern.WindowKit/DispatcherOperation.cs | 2 +- src/Modern.WindowKit/DispatcherTimer.cs | 14 ++--- 20 files changed, 145 insertions(+), 76 deletions(-) diff --git a/src/Modern.WindowKit/Avalonia.Mac/AvaloniaNativePlatform.cs b/src/Modern.WindowKit/Avalonia.Mac/AvaloniaNativePlatform.cs index 1b48ad3..4820f26 100644 --- a/src/Modern.WindowKit/Avalonia.Mac/AvaloniaNativePlatform.cs +++ b/src/Modern.WindowKit/Avalonia.Mac/AvaloniaNativePlatform.cs @@ -3,9 +3,7 @@ using Modern.WindowKit.Controls.Platform; using Modern.WindowKit.Input; using Modern.WindowKit.Input.Platform; -using Modern.WindowKit.MicroCom; using Modern.WindowKit.Mac.Interop; -//using Modern.WindowKit.OpenGL; using Modern.WindowKit.Platform; //using Modern.WindowKit.Rendering; //using Modern.WindowKit.Rendering.Composition; @@ -163,6 +161,14 @@ void DoInitialize(AvaloniaNativePlatformOptions options) //Compositor = new Compositor(_platformGraphics, true); + + AppDomain.CurrentDomain.ProcessExit += OnProcessExit; + } + + private void OnProcessExit(object? sender, EventArgs e) + { + AppDomain.CurrentDomain.ProcessExit -= OnProcessExit; + _factory.Dispose(); } //public ITrayIconImpl CreateTrayIcon() diff --git a/src/Modern.WindowKit/Avalonia.Win32/IBlurHost.cs b/src/Modern.WindowKit/Avalonia.Win32/IBlurHost.cs index d994397..03724cf 100644 --- a/src/Modern.WindowKit/Avalonia.Win32/IBlurHost.cs +++ b/src/Modern.WindowKit/Avalonia.Win32/IBlurHost.cs @@ -4,7 +4,8 @@ internal enum BlurEffect { None, Acrylic, - Mica + MicaLight, + MicaDark } internal interface IBlurHost diff --git a/src/Modern.WindowKit/Avalonia.Win32/WinUiCompositionShared.cs b/src/Modern.WindowKit/Avalonia.Win32/WinUiCompositionShared.cs index afe442a..9b22eed 100644 --- a/src/Modern.WindowKit/Avalonia.Win32/WinUiCompositionShared.cs +++ b/src/Modern.WindowKit/Avalonia.Win32/WinUiCompositionShared.cs @@ -9,8 +9,9 @@ internal class WinUiCompositionShared : IDisposable //public ICompositor5 Compositor5 { get; } //public ICompositorDesktopInterop DesktopInterop { get; } //public ICompositionBrush BlurBrush { get; } - //public ICompositionBrush? MicaBrush { get; } - //public object SyncRoot { get; } = new(); + //public ICompositionBrush? MicaBrushLight { get; } + //public ICompositionBrush? MicaBrushDark { get; } + public object SyncRoot { get; } = new(); public static readonly Version MinWinCompositionVersion = new(10, 0, 17134); public static readonly Version MinAcrylicVersion = new(10, 0, 15063); @@ -21,14 +22,16 @@ internal class WinUiCompositionShared : IDisposable // Compositor = compositor.CloneReference(); // Compositor5 = compositor.QueryInterface(); // BlurBrush = WinUiCompositionUtils.CreateAcrylicBlurBackdropBrush(compositor); - // MicaBrush = WinUiCompositionUtils.CreateMicaBackdropBrush(compositor); + // MicaBrushLight = WinUiCompositionUtils.CreateMicaBackdropBrush(compositor, 242, 0.6f); + // MicaBrushDark = WinUiCompositionUtils.CreateMicaBackdropBrush(compositor, 32, 0.8f); // DesktopInterop = compositor.QueryInterface(); //} public void Dispose() { //BlurBrush.Dispose(); - //MicaBrush?.Dispose(); + //MicaBrushLight?.Dispose(); + //MicaBrushDark?.Dispose(); //DesktopInterop.Dispose(); //Compositor.Dispose(); //Compositor5.Dispose(); diff --git a/src/Modern.WindowKit/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Modern.WindowKit/Avalonia.Win32/WindowImpl.AppWndProc.cs index 3eab67c..0b92873 100644 --- a/src/Modern.WindowKit/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Modern.WindowKit/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -59,7 +59,7 @@ protected virtual unsafe IntPtr AppWndProc(IntPtr hWnd, uint msg, IntPtr wParam, case WindowsMessage.WM_NCCALCSIZE: { - if (ToInt32(wParam) == 1 && !HasFullDecorations || _isClientAreaExtended) + if (ToInt32(wParam) == 1 && _windowProperties.Decorations == SystemDecorations.None || _isClientAreaExtended) { return IntPtr.Zero; } diff --git a/src/Modern.WindowKit/Avalonia.Win32/WindowImpl.cs b/src/Modern.WindowKit/Avalonia.Win32/WindowImpl.cs index e3d0aba..de25707 100644 --- a/src/Modern.WindowKit/Avalonia.Win32/WindowImpl.cs +++ b/src/Modern.WindowKit/Avalonia.Win32/WindowImpl.cs @@ -106,6 +106,7 @@ internal partial class WindowImpl : IWindowImpl //, EglGlPlatformSurface.IEglWin //private static POINTER_PEN_INFO[]? s_historyPenInfos; //private static POINTER_INFO[]? s_historyInfos; //private static MOUSEMOVEPOINT[]? s_mouseHistoryInfos; + private PlatformThemeVariant _currentThemeVariant; public WindowImpl() { @@ -474,7 +475,12 @@ private void SetTransparencyMica(Version windowsVersion) return; SetUseHostBackdropBrush(false); - _blurHost?.SetBlur(BlurEffect.Mica); + _blurHost?.SetBlur(_currentThemeVariant switch + { + PlatformThemeVariant.Light => BlurEffect.MicaLight, + PlatformThemeVariant.Dark => BlurEffect.MicaDark, + _ => throw new ArgumentOutOfRangeException() + }); } private void SetAccentState(AccentState state) @@ -778,6 +784,7 @@ public void SetTopmost(bool value) public unsafe void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { + _currentThemeVariant = themeVariant; if (Win32Platform.WindowsVersion.Build >= 22000) { var pvUseBackdropBrush = themeVariant == PlatformThemeVariant.Dark ? 1 : 0; @@ -786,6 +793,10 @@ public unsafe void SetFrameThemeVariant(PlatformThemeVariant themeVariant) (int)DwmWindowAttribute.DWMWA_USE_IMMERSIVE_DARK_MODE, &pvUseBackdropBrush, sizeof(int)); + if (TransparencyLevel == WindowTransparencyLevel.Mica) + { + SetTransparencyMica(Win32Platform.WindowsVersion); + } } } @@ -1329,14 +1340,12 @@ private void UpdateWindowProperties(WindowProperties newProperties, bool forceCh if (!_isFullScreenActive) { - var margin = newProperties.Decorations == SystemDecorations.BorderOnly ? 1 : 0; - var margins = new MARGINS { - cyBottomHeight = margin, - cxRightWidth = margin, - cxLeftWidth = margin, - cyTopHeight = margin + cyBottomHeight = 0, + cxRightWidth = 0, + cxLeftWidth = 0, + cyTopHeight = 0 }; DwmExtendFrameIntoClientArea(_hwnd, ref margins); diff --git a/src/Modern.WindowKit/Avalonia.X11/X11Clipboard.cs b/src/Modern.WindowKit/Avalonia.X11/X11Clipboard.cs index 8defc05..336b8cb 100644 --- a/src/Modern.WindowKit/Avalonia.X11/X11Clipboard.cs +++ b/src/Modern.WindowKit/Avalonia.X11/X11Clipboard.cs @@ -14,6 +14,7 @@ internal class X11Clipboard : IClipboard private readonly X11Info _x11; private IDataObject _storedDataObject; private IntPtr _handle; + private TaskCompletionSource _storeAtomTcs; private TaskCompletionSource _requestedFormatsTcs; private TaskCompletionSource _requestedDataTcs; private readonly IntPtr[] _textAtoms; @@ -52,6 +53,12 @@ private Encoding GetStringEncoding(IntPtr atom) private unsafe void OnEvent(ref XEvent ev) { + if (ev.type == XEventName.SelectionClear) + { + _storeAtomTcs?.TrySetResult(true); + return; + } + if (ev.type == XEventName.SelectionRequest) { var sel = ev.SelectionRequestEvent; @@ -82,18 +89,9 @@ IntPtr WriteTargetToProperty(IntPtr target, IntPtr window, IntPtr property) Encoding textEnc; if (target == _x11.Atoms.TARGETS) { - var atoms = new HashSet { _x11.Atoms.TARGETS, _x11.Atoms.MULTIPLE }; - foreach (var fmt in _storedDataObject.GetDataFormats()) - { - if (fmt == DataFormats.Text) - foreach (var ta in _textAtoms) - atoms.Add(ta); - else - atoms.Add(_x11.Atoms.GetAtom(fmt)); - } - + var atoms = ConvertDataObject(_storedDataObject); XChangeProperty(_x11.Display, window, property, - _x11.Atoms.XA_ATOM, 32, PropertyMode.Replace, atoms.ToArray(), atoms.Count); + _x11.Atoms.XA_ATOM, 32, PropertyMode.Replace, atoms, atoms.Length); return property; } else if(target == _x11.Atoms.SAVE_TARGETS && _x11.Atoms.SAVE_TARGETS != IntPtr.Zero) @@ -252,21 +250,42 @@ public async Task GetTextAsync() return (string)await SendDataRequest(target); } - private void StoreAtomsInClipboardManager(IntPtr[] atoms) + + private IntPtr[] ConvertDataObject(IDataObject data) { - if (_x11.Atoms.CLIPBOARD_MANAGER != IntPtr.Zero && _x11.Atoms.SAVE_TARGETS != IntPtr.Zero) + var atoms = new HashSet { _x11.Atoms.TARGETS, _x11.Atoms.MULTIPLE }; + foreach (var fmt in data.GetDataFormats()) + { + if (fmt == DataFormats.Text) + foreach (var ta in _textAtoms) + atoms.Add(ta); + else + atoms.Add(_x11.Atoms.GetAtom(fmt)); + } + return atoms.ToArray(); + } + + private Task StoreAtomsInClipboardManager(IDataObject data) { + if (_x11.Atoms.CLIPBOARD_MANAGER != IntPtr.Zero && _x11.Atoms.SAVE_TARGETS != IntPtr.Zero) + { var clipboardManager = XGetSelectionOwner(_x11.Display, _x11.Atoms.CLIPBOARD_MANAGER); if (clipboardManager != IntPtr.Zero) - { + { + if (_storeAtomTcs == null || _storeAtomTcs.Task.IsCompleted) + _storeAtomTcs = new TaskCompletionSource(); + + var atoms = ConvertDataObject(data); XChangeProperty(_x11.Display, _handle, _avaloniaSaveTargetsAtom, _x11.Atoms.XA_ATOM, 32, PropertyMode.Replace, atoms, atoms.Length); XConvertSelection(_x11.Display, _x11.Atoms.CLIPBOARD_MANAGER, _x11.Atoms.SAVE_TARGETS, _avaloniaSaveTargetsAtom, _handle, IntPtr.Zero); + return _storeAtomTcs.Task; } } - } + return Task.CompletedTask; + } public Task SetTextAsync(string text) { @@ -283,9 +302,8 @@ public Task ClearAsync() public Task SetDataObjectAsync(IDataObject data) { _storedDataObject = data; - XSetSelectionOwner(_x11.Display, _x11.Atoms.CLIPBOARD, _handle, IntPtr.Zero); - StoreAtomsInClipboardManager(_textAtoms); - return Task.CompletedTask; + XSetSelectionOwner(_x11.Display, _x11.Atoms.CLIPBOARD, _handle, IntPtr.Zero); + return StoreAtomsInClipboardManager(data); } public async Task GetFormatsAsync() diff --git a/src/Modern.WindowKit/Avalonia.X11/X11Info.cs b/src/Modern.WindowKit/Avalonia.X11/X11Info.cs index 58310e9..4f1de86 100644 --- a/src/Modern.WindowKit/Avalonia.X11/X11Info.cs +++ b/src/Modern.WindowKit/Avalonia.X11/X11Info.cs @@ -35,6 +35,9 @@ internal unsafe class X11Info public bool HasXSync { get; set; } public IntPtr DefaultFontSet { get; set; } + [DllImport("libc")] + private static extern void setlocale(int type, string s); + public unsafe X11Info(IntPtr display, IntPtr deferredDisplay, bool useXim) { Display = display; @@ -49,6 +52,9 @@ public unsafe X11Info(IntPtr display, IntPtr deferredDisplay, bool useXim) DefaultFontSet = XCreateFontSet(Display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", out var _, out var _, IntPtr.Zero); + // We have problems with text input otherwise + setlocale(0, ""); + if (useXim) { XSetLocaleModifiers(""); @@ -59,7 +65,15 @@ public unsafe X11Info(IntPtr display, IntPtr deferredDisplay, bool useXim) if (Xim == IntPtr.Zero) { - XSetLocaleModifiers("@im=none"); + if (XSetLocaleModifiers("@im=none") == IntPtr.Zero) + { + setlocale(0, "en_US.UTF-8"); + if (XSetLocaleModifiers("@im=none") == IntPtr.Zero) + { + setlocale(0, "C.UTF-8"); + XSetLocaleModifiers("@im=none"); + } + } Xim = XOpenIM(display, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); } diff --git a/src/Modern.WindowKit/Avalonia.X11/X11Platform.cs b/src/Modern.WindowKit/Avalonia.X11/X11Platform.cs index d9d1ac0..f2dbcd1 100644 --- a/src/Modern.WindowKit/Avalonia.X11/X11Platform.cs +++ b/src/Modern.WindowKit/Avalonia.X11/X11Platform.cs @@ -36,8 +36,7 @@ internal class AvaloniaX11Platform : IWindowingPlatform public IntPtr OrphanedWindow { get; private set; } public X11Globals Globals { get; private set; } public ManualRawEventGrouperDispatchQueue EventGrouperDispatchQueue { get; } = new(); - [DllImport("libc")] - private static extern void setlocale(int type, string s); + public void Initialize(X11PlatformOptions options) { Options = options; @@ -50,9 +49,6 @@ public void Initialize(X11PlatformOptions options) // useXim = true; //} - // We have problems with text input otherwise - setlocale(0, ""); - XInitThreads(); Display = XOpenDisplay(IntPtr.Zero); if (Display == IntPtr.Zero) diff --git a/src/Modern.WindowKit/Avalonia.X11/X11Structs.cs b/src/Modern.WindowKit/Avalonia.X11/X11Structs.cs index 1329f16..d960743 100644 --- a/src/Modern.WindowKit/Avalonia.X11/X11Structs.cs +++ b/src/Modern.WindowKit/Avalonia.X11/X11Structs.cs @@ -1109,7 +1109,7 @@ internal struct MotifWmHints { public override string ToString () { - return string.Format("MotifWmHints Ensure(Dispatcher.UIThread, priority); + public static RestoreContext Ensure(Dispatcher dispatcher, DispatcherPriority priority) { if (Current is AvaloniaSynchronizationContext avaloniaContext && avaloniaContext.Priority == priority) return default; var oldContext = Current; - Dispatcher.UIThread.VerifyAccess(); - SetSynchronizationContext(Dispatcher.UIThread.GetContextWithPriority(priority)); + dispatcher.VerifyAccess(); + SetSynchronizationContext(dispatcher.GetContextWithPriority(priority)); return new RestoreContext(oldContext); } } diff --git a/src/Modern.WindowKit/Dispatcher.Invoke.cs b/src/Modern.WindowKit/Dispatcher.Invoke.cs index 905c7b5..073d004 100644 --- a/src/Modern.WindowKit/Dispatcher.Invoke.cs +++ b/src/Modern.WindowKit/Dispatcher.Invoke.cs @@ -90,7 +90,7 @@ public void Invoke(Action callback, DispatcherPriority priority, CancellationTok { if (callback == null) { - throw new ArgumentNullException("callback"); + throw new ArgumentNullException(nameof(callback)); } DispatcherPriority.Validate(priority, "priority"); @@ -98,7 +98,7 @@ public void Invoke(Action callback, DispatcherPriority priority, CancellationTok if (timeout.TotalMilliseconds < 0 && timeout != TimeSpan.FromMilliseconds(-1)) { - throw new ArgumentOutOfRangeException("timeout"); + throw new ArgumentOutOfRangeException(nameof(timeout)); } // Fast-Path: if on the same thread, and invoking at Send priority, @@ -106,7 +106,7 @@ public void Invoke(Action callback, DispatcherPriority priority, CancellationTok // call the callback directly. if (!cancellationToken.IsCancellationRequested && priority == DispatcherPriority.Send && CheckAccess()) { - using (AvaloniaSynchronizationContext.Ensure(priority)) + using (AvaloniaSynchronizationContext.Ensure(this, priority)) callback(); return; } @@ -212,7 +212,7 @@ public TResult Invoke(Func callback, DispatcherPriority priori { if (callback == null) { - throw new ArgumentNullException("callback"); + throw new ArgumentNullException(nameof(callback)); } DispatcherPriority.Validate(priority, "priority"); @@ -220,7 +220,7 @@ public TResult Invoke(Func callback, DispatcherPriority priori if (timeout.TotalMilliseconds < 0 && timeout != TimeSpan.FromMilliseconds(-1)) { - throw new ArgumentOutOfRangeException("timeout"); + throw new ArgumentOutOfRangeException(nameof(timeout)); } // Fast-Path: if on the same thread, and invoking at Send priority, @@ -228,7 +228,7 @@ public TResult Invoke(Func callback, DispatcherPriority priori // call the callback directly. if (!cancellationToken.IsCancellationRequested && priority == DispatcherPriority.Send && CheckAccess()) { - using (AvaloniaSynchronizationContext.Ensure(priority)) + using (AvaloniaSynchronizationContext.Ensure(this, priority)) return callback(); } @@ -304,7 +304,7 @@ public DispatcherOperation InvokeAsync(Action callback, DispatcherPriority prior { if (callback == null) { - throw new ArgumentNullException("callback"); + throw new ArgumentNullException(nameof(callback)); } DispatcherPriority.Validate(priority, "priority"); @@ -379,7 +379,7 @@ public DispatcherOperation InvokeAsync(Func callback, { if (callback == null) { - throw new ArgumentNullException("callback"); + throw new ArgumentNullException(nameof(callback)); } DispatcherPriority.Validate(priority, "priority"); diff --git a/src/Modern.WindowKit/Dispatcher.MainLoop.cs b/src/Modern.WindowKit/Dispatcher.MainLoop.cs index 0adcddc..5a94bee 100644 --- a/src/Modern.WindowKit/Dispatcher.MainLoop.cs +++ b/src/Modern.WindowKit/Dispatcher.MainLoop.cs @@ -49,7 +49,7 @@ public void PushFrame(DispatcherFrame frame) try { _frames.Push(frame); - using (AvaloniaSynchronizationContext.Ensure(DispatcherPriority.Normal)) + using (AvaloniaSynchronizationContext.Ensure(this, DispatcherPriority.Normal)) frame.Run(_controlledImpl); } finally diff --git a/src/Modern.WindowKit/Dispatcher.Queue.cs b/src/Modern.WindowKit/Dispatcher.Queue.cs index c8ca929..dd4ca01 100644 --- a/src/Modern.WindowKit/Dispatcher.Queue.cs +++ b/src/Modern.WindowKit/Dispatcher.Queue.cs @@ -9,7 +9,9 @@ public partial class Dispatcher private readonly DispatcherPriorityQueue _queue = new(); private bool _signaled; private bool _explicitBackgroundProcessingRequested; - private const int MaximumTimeProcessingBackgroundJobs = 50; + private const int MaximumInputStarvationTimeInFallbackMode = 50; + private const int MaximumInputStarvationTimeInExplicitProcessingExplicitMode = 50; + private int _maximumInputStarvationTime; void RequestBackgroundProcessing() { @@ -35,8 +37,8 @@ private void OnReadyForExplicitBackgroundProcessing() lock (InstanceLock) { _explicitBackgroundProcessingRequested = false; - ExecuteJobsCore(); } + ExecuteJobsCore(true); } /// @@ -130,10 +132,10 @@ private void Signaled() lock (InstanceLock) _signaled = false; - ExecuteJobsCore(); + ExecuteJobsCore(false); } - void ExecuteJobsCore() + void ExecuteJobsCore(bool fromExplicitBackgroundProcessingCallback) { long? backgroundJobExecutionStartedAt = null; while (true) @@ -151,7 +153,6 @@ void ExecuteJobsCore() if (job.Priority > DispatcherPriority.Input) { ExecuteJob(job); - backgroundJobExecutionStartedAt = null; } // If platform supports pending input query, ask the platform if we can continue running low priority jobs else if (_pendingInputImpl?.CanQueryPendingInput == true) @@ -164,6 +165,13 @@ void ExecuteJobsCore() return; } } + // We can't ask if the implementation has pending input, so we should let it to call us back + // Once it thinks that input is handled + else if (_backgroundProcessingImpl != null && !fromExplicitBackgroundProcessingCallback) + { + RequestBackgroundProcessing(); + return; + } // We can't check if there is pending input, but still need to enforce interactivity // so we stop processing background jobs after some timeout and start a timer to continue later else @@ -171,7 +179,7 @@ void ExecuteJobsCore() if (backgroundJobExecutionStartedAt == null) backgroundJobExecutionStartedAt = Now; - if (Now - backgroundJobExecutionStartedAt.Value > MaximumTimeProcessingBackgroundJobs) + if (Now - backgroundJobExecutionStartedAt.Value > _maximumInputStarvationTime) { _signaled = true; RequestBackgroundProcessing(); diff --git a/src/Modern.WindowKit/Dispatcher.Timers.cs b/src/Modern.WindowKit/Dispatcher.Timers.cs index 5e8e973..946b983 100644 --- a/src/Modern.WindowKit/Dispatcher.Timers.cs +++ b/src/Modern.WindowKit/Dispatcher.Timers.cs @@ -127,7 +127,7 @@ private void OnOSTimer() if (needToPromoteTimers) PromoteTimers(); if (needToProcessQueue) - ExecuteJobsCore(); + ExecuteJobsCore(false); UpdateOSTimer(); } diff --git a/src/Modern.WindowKit/Dispatcher.cs b/src/Modern.WindowKit/Dispatcher.cs index e6982a0..435e64d 100644 --- a/src/Modern.WindowKit/Dispatcher.cs +++ b/src/Modern.WindowKit/Dispatcher.cs @@ -34,6 +34,9 @@ internal Dispatcher(IDispatcherImpl impl) _controlledImpl = _impl as IControlledDispatcherImpl; _pendingInputImpl = _impl as IDispatcherImplWithPendingInput; _backgroundProcessingImpl = _impl as IDispatcherImplWithExplicitBackgroundProcessing; + _maximumInputStarvationTime = _backgroundProcessingImpl == null ? + MaximumInputStarvationTimeInFallbackMode : + MaximumInputStarvationTimeInExplicitProcessingExplicitMode; if (_backgroundProcessingImpl != null) _backgroundProcessingImpl.ReadyForBackgroundProcessing += OnReadyForExplicitBackgroundProcessing; } @@ -67,7 +70,7 @@ private static Dispatcher CreateUIThreadDispatcher() /// The current thread is not the UI thread. /// public void VerifyAccess() - { + { if (!CheckAccess()) { // Used to inline VerifyAccess. diff --git a/src/Modern.WindowKit/DispatcherFrame.cs b/src/Modern.WindowKit/DispatcherFrame.cs index 471654e..fcee33f 100644 --- a/src/Modern.WindowKit/DispatcherFrame.cs +++ b/src/Modern.WindowKit/DispatcherFrame.cs @@ -38,10 +38,14 @@ public DispatcherFrame() : this(true) /// for their important criteria to be met. These frames /// should have a timeout associated with them. /// - public DispatcherFrame(bool exitWhenRequested) + public DispatcherFrame(bool exitWhenRequested) : this(Dispatcher.UIThread, exitWhenRequested) { - Dispatcher = Dispatcher.UIThread; Dispatcher.VerifyAccess(); + } + + internal DispatcherFrame(Dispatcher dispatcher, bool exitWhenRequested) + { + Dispatcher = dispatcher; _exitWhenRequested = exitWhenRequested; _continue = true; } diff --git a/src/Modern.WindowKit/DispatcherOperation.cs b/src/Modern.WindowKit/DispatcherOperation.cs index 478ed66..7b75c82 100644 --- a/src/Modern.WindowKit/DispatcherOperation.cs +++ b/src/Modern.WindowKit/DispatcherOperation.cs @@ -258,7 +258,7 @@ internal void Execute() try { - using (AvaloniaSynchronizationContext.Ensure(Priority)) + using (AvaloniaSynchronizationContext.Ensure(Dispatcher, Priority)) InvokeCore(); } finally diff --git a/src/Modern.WindowKit/DispatcherTimer.cs b/src/Modern.WindowKit/DispatcherTimer.cs index 1ba8ac4..3f56da9 100644 --- a/src/Modern.WindowKit/DispatcherTimer.cs +++ b/src/Modern.WindowKit/DispatcherTimer.cs @@ -62,7 +62,7 @@ public DispatcherTimer(TimeSpan interval, DispatcherPriority priority, EventHand { if (callback == null) { - throw new ArgumentNullException("callback"); + throw new ArgumentNullException(nameof(callback)); } Tick += callback; @@ -112,11 +112,11 @@ public TimeSpan Interval bool updateOSTimer = false; if (value.TotalMilliseconds < 0) - throw new ArgumentOutOfRangeException("value", + throw new ArgumentOutOfRangeException(nameof(value), "TimeSpan period must be greater than or equal to zero."); if (value.TotalMilliseconds > Int32.MaxValue) - throw new ArgumentOutOfRangeException("value", + throw new ArgumentOutOfRangeException(nameof(value), "TimeSpan period must be less than or equal to Int32.MaxValue."); lock (_instanceLock) @@ -253,20 +253,20 @@ internal DispatcherTimer(Dispatcher dispatcher, DispatcherPriority priority, Tim { if (dispatcher == null) { - throw new ArgumentNullException("dispatcher"); + throw new ArgumentNullException(nameof(dispatcher)); } DispatcherPriority.Validate(priority, "priority"); if (priority == DispatcherPriority.Inactive) { - throw new ArgumentException("Specified priority is not valid.", "priority"); + throw new ArgumentException("Specified priority is not valid.", nameof(priority)); } if (interval.TotalMilliseconds < 0) - throw new ArgumentOutOfRangeException("interval", "TimeSpan period must be greater than or equal to zero."); + throw new ArgumentOutOfRangeException(nameof(interval), "TimeSpan period must be greater than or equal to zero."); if (interval.TotalMilliseconds > Int32.MaxValue) - throw new ArgumentOutOfRangeException("interval", + throw new ArgumentOutOfRangeException(nameof(interval), "TimeSpan period must be less than or equal to Int32.MaxValue.");