diff --git a/CefGlue.Avalonia/AvaloniaBrowserProcessHandler.cs b/CefGlue.Avalonia/AvaloniaBrowserProcessHandler.cs index ec64113d..744fb349 100644 --- a/CefGlue.Avalonia/AvaloniaBrowserProcessHandler.cs +++ b/CefGlue.Avalonia/AvaloniaBrowserProcessHandler.cs @@ -1,6 +1,6 @@ -using System; +using System; using System.Reactive.Linq; -using Avalonia.ReactiveUI; +using ReactiveUI.Avalonia; using Xilium.CefGlue.Common.Handlers; namespace Xilium.CefGlue.Avalonia diff --git a/CefGlue.Avalonia/CefGlue.Avalonia.csproj b/CefGlue.Avalonia/CefGlue.Avalonia.csproj index 90db6b3b..50bfd5cc 100644 --- a/CefGlue.Avalonia/CefGlue.Avalonia.csproj +++ b/CefGlue.Avalonia/CefGlue.Avalonia.csproj @@ -20,8 +20,8 @@ - - + + diff --git a/CefGlue.Avalonia/InputExtensions.cs b/CefGlue.Avalonia/InputExtensions.cs index 933af370..6bec569f 100644 --- a/CefGlue.Avalonia/InputExtensions.cs +++ b/CefGlue.Avalonia/InputExtensions.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using Avalonia; using Avalonia.Input; using Avalonia.VisualTree; @@ -200,21 +200,23 @@ public static CefDragData GetDragData(this DragEventArgs e) { var dragData = CefDragData.Create(); - // Files - if (e.Data.Contains(DataFormats.FileNames)) + // Avalonia 12 uses DataTransfer.TryGetFiles for asynchronous strongly-typed file extraction + var files = e.DataTransfer.TryGetFiles(); + if (files != null) { - var files = (string[])e.Data.GetFileNames(); - foreach (var filePath in files) + foreach (var file in files) { - var displayName = Path.GetFileName(filePath); + var filePath = file.Path.LocalPath; + var displayName = file.Name; dragData.AddFile(filePath.Replace("\\", "/"), displayName); } } - // Text - if (e.Data.Contains(DataFormats.Text)) + // Avalonia 12 Using DataTransfer.TryGetText for Strongly-Typed Text Extraction + var text = e.DataTransfer.TryGetText(); + if (!string.IsNullOrWhiteSpace(text)) { - dragData.SetFragmentText(e.Data.GetText()); + dragData.SetFragmentText(text); } return dragData; diff --git a/CefGlue.Avalonia/Platform/AvaloniaControl.cs b/CefGlue.Avalonia/Platform/AvaloniaControl.cs index 4ae258d8..e2f3b7b1 100644 --- a/CefGlue.Avalonia/Platform/AvaloniaControl.cs +++ b/CefGlue.Avalonia/Platform/AvaloniaControl.cs @@ -45,7 +45,7 @@ private void OnLayoutUpdated(object sender, EventArgs e) SizeChanged?.Invoke(new CefSize((int)_control.Bounds.Width, (int)_control.Bounds.Height)); } - private void OnGotFocus(object sender, GotFocusEventArgs e) + private void OnGotFocus(object sender, FocusChangedEventArgs e) { GotFocus?.Invoke(); } @@ -128,7 +128,7 @@ public void OpenContextMenu(IEnumerable menuEntries, int x, int y, Ce menu.PlacementAnchor = PopupAnchor.TopLeft; menu.PlacementGravity = PopupGravity.BottomRight; - menu.PlacementMode = PlacementMode.AnchorAndGravity; + menu.Placement = PlacementMode.AnchorAndGravity; menu.PlacementRect = new Rect(x, y, 1, 1); menu.Open(_control); }, diff --git a/CefGlue.Avalonia/Platform/AvaloniaOffScreenControlHost.cs b/CefGlue.Avalonia/Platform/AvaloniaOffScreenControlHost.cs index c2142a5b..346cc72a 100644 --- a/CefGlue.Avalonia/Platform/AvaloniaOffScreenControlHost.cs +++ b/CefGlue.Avalonia/Platform/AvaloniaOffScreenControlHost.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Avalonia; using Avalonia.Collections; @@ -173,7 +173,7 @@ private void OnPointerMoved(object sender, PointerEventArgs e) MouseMoved?.Invoke(e.AsCefMouseEvent(MousePositionReferential)); } - private void OnLostFocus(object sender, RoutedEventArgs e) + private void OnLostFocus(object sender, FocusChangedEventArgs e) { LostFocus?.Invoke(); } @@ -190,13 +190,16 @@ private void OnDetachedFromVisualTree(object sender, VisualTreeAttachmentEventAr private void OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e) { VisibilityChanged?.Invoke(true); - if (e.Root is Window newWindow) + if (e.RootVisual is Window newWindow) { _windowStateChangedObservable = newWindow.GetPropertyChangedObservable(Window.WindowStateProperty).Subscribe(OnHostWindowStateChanged); } - if (e.Root.RenderScaling != RenderSurface.DeviceScaleFactor) + + // In Avalonia 12, safely read the current window's scaling factor through TopLevel + var topLevel = TopLevel.GetTopLevel(_control); + if (topLevel != null && topLevel.RenderScaling != RenderSurface.DeviceScaleFactor) { - RenderSurface.DeviceScaleFactor = (float)e.Root.RenderScaling; + RenderSurface.DeviceScaleFactor = (float)topLevel.RenderScaling; ScreenInfoChanged?.Invoke(RenderSurface.DeviceScaleFactor); } } @@ -268,10 +271,19 @@ public async Task StartDrag(CefDragData dragData, CefDrag var lastPointerEvent = this._lastPointerEvent; // story a copy, since this might be other thread if (lastPointerEvent != null) { - var dataObject = new DataObject(); - dataObject.Set(DataFormats.Text, dragData.FragmentText); + // Replace the deprecated DataObject with the officially recommended DataTransfer + var dataObject = new DataTransfer(); + if (!string.IsNullOrEmpty(dragData.FragmentText)) + { + var item = new DataTransferItem(); + item.SetText(dragData.FragmentText); + dataObject.Add(item); + } + + // Use asynchronous DoDragDropAsync to trigger the OS's native drag-and-drop action + var result = await Dispatcher.UIThread.InvokeAsync(() => + DragDrop.DoDragDropAsync(lastPointerEvent, dataObject, allowedOps.AsDragDropEffects())); - var result = await Dispatcher.UIThread.InvokeAsync(() => DragDrop.DoDragDrop(lastPointerEvent, dataObject, allowedOps.AsDragDropEffects())); this._lastPointerEvent = null; _previousCursor = null; _currentDragCursor = null; diff --git a/CefGlue.Avalonia/Platform/AvaloniaPopup.cs b/CefGlue.Avalonia/Platform/AvaloniaPopup.cs index 320c9fe5..331daa8b 100644 --- a/CefGlue.Avalonia/Platform/AvaloniaPopup.cs +++ b/CefGlue.Avalonia/Platform/AvaloniaPopup.cs @@ -45,7 +45,8 @@ public void Open() { Dispatcher.UIThread.Post(() => { - _popup.Show(_popup.PlacementTarget.GetVisualRoot() as Window); + // Use TopLevel.GetTopLevel to dynamically get ownership of the current rendering root window + _popup.Show(TopLevel.GetTopLevel(_popup.PlacementTarget) as Window); }); } diff --git a/CefGlue.Avalonia/Platform/ExtendedAvaloniaPopup.cs b/CefGlue.Avalonia/Platform/ExtendedAvaloniaPopup.cs index 6d5b73b6..047b2be5 100644 --- a/CefGlue.Avalonia/Platform/ExtendedAvaloniaPopup.cs +++ b/CefGlue.Avalonia/Platform/ExtendedAvaloniaPopup.cs @@ -15,7 +15,7 @@ internal class ExtendedAvaloniaPopup : Window public ExtendedAvaloniaPopup() { CanResize = false; - SystemDecorations = SystemDecorations.None; + WindowDecorations = WindowDecorations.None; Focusable = false; Topmost = true; ShowActivated = false; diff --git a/CefGlue.Demo.Avalonia/CefGlue.Demo.Avalonia.csproj b/CefGlue.Demo.Avalonia/CefGlue.Demo.Avalonia.csproj index 96af4d77..404e32e6 100644 --- a/CefGlue.Demo.Avalonia/CefGlue.Demo.Avalonia.csproj +++ b/CefGlue.Demo.Avalonia/CefGlue.Demo.Avalonia.csproj @@ -31,8 +31,9 @@ + + - diff --git a/CefGlue.Tests/Events/EventsTests.cs b/CefGlue.Tests/Events/EventsTests.cs index adecbe6f..d01b87b2 100644 --- a/CefGlue.Tests/Events/EventsTests.cs +++ b/CefGlue.Tests/Events/EventsTests.cs @@ -50,7 +50,7 @@ void OnBrowserLoadError(object sender, LoadErrorEventArgs e) taskCompletionSource.SetResult(true); } Browser.LoadError += OnBrowserLoadError; - Browser.Address = "http://0.0.0.0"; // navigate to an invalid url + Browser.Address = "http://invalidurl"; // navigate to an invalid url await taskCompletionSource.Task; } diff --git a/CefGlue.Tests/Javascript/JavascriptEvaluationTests.cs b/CefGlue.Tests/Javascript/JavascriptEvaluationTests.cs index 6c52fb50..130b01d9 100644 --- a/CefGlue.Tests/Javascript/JavascriptEvaluationTests.cs +++ b/CefGlue.Tests/Javascript/JavascriptEvaluationTests.cs @@ -46,7 +46,8 @@ public async Task DateTimeReturn() { var expected = DateTime.Parse("2022-12-20T15:50:21.817Z"); var result = await EvaluateJavascript($"return new Date('{expected.ToString("o", CultureInfo.InvariantCulture)}');"); - Assert.AreEqual(expected, result); + // Align to UTC before comparison to eliminate local Ticks deviation + Assert.AreEqual(expected.ToUniversalTime(), result.ToUniversalTime()); } [Test] diff --git a/CefGlue.Tests/Javascript/NativeObjectInteropTests.cs b/CefGlue.Tests/Javascript/NativeObjectInteropTests.cs index 2b8c5041..c582fa43 100644 --- a/CefGlue.Tests/Javascript/NativeObjectInteropTests.cs +++ b/CefGlue.Tests/Javascript/NativeObjectInteropTests.cs @@ -208,7 +208,7 @@ public async Task MethodParamsArePassed() Assert.AreEqual(4, result.Length); Assert.AreEqual(Arg1, result[0]); Assert.AreEqual(Arg2, result[1]); - Assert.AreEqual(DateTime.Parse(Date), result[2]); + Assert.AreEqual(DateTime.Parse(Date).ToUniversalTime(), ((DateTime)result[2]).ToUniversalTime()); Assert.AreEqual(true, result[3]); } @@ -297,7 +297,7 @@ public async Task MethodWithObjectParamIsPassed() var arg = (Person) result[0]; Assert.AreEqual("cef", arg.Name); Assert.AreEqual(10, arg.Age); - Assert.AreEqual(DateTime.Parse(Date), arg.BirthDate); + Assert.AreEqual(DateTime.Parse(Date).ToUniversalTime(), arg.BirthDate.ToUniversalTime()); } [Test] @@ -407,7 +407,7 @@ public async Task NativeObjectMethodDateTimeResultIsReturned() var result = await nativeObject.ResultTask; // Assert - Assert.AreEqual(nativeObject.MethodWithDateTimeReturn(), result); + Assert.AreEqual(nativeObject.MethodWithDateTimeReturn().ToUniversalTime(), ((DateTime)result).ToUniversalTime()); } [Test] @@ -420,7 +420,7 @@ public async Task NativeObjectMethodObjectResultIsReturned() var expected = nativeObject.MethodWithObjectReturn(); Assert.AreEqual(expected.Name, result.Name); Assert.AreEqual(expected.Age, result.Age); - Assert.AreEqual(expected.BirthDate, result.BirthDate); + Assert.AreEqual(expected.BirthDate.ToUniversalTime(), result.BirthDate.ToUniversalTime()); Assert.AreEqual(expected.Photo, result.Photo); } diff --git a/Directory.Build.props b/Directory.Build.props index 53034066..776c87a6 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ net8.0 latest 120.1.8 - 11.0.9 + 12.1.0 120.1.8 120.1.8 x64;ARM64 diff --git a/Directory.Packages.props b/Directory.Packages.props index d4afe4c8..0a1307d5 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,49 +1,43 @@ - - true - - + + true + + - - $(PrivateAssets);compile - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + $(PrivateAssets);compile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file