diff --git a/src/Avalonia.Controls/PresentationSource/PresentationSource.Input.cs b/src/Avalonia.Controls/PresentationSource/PresentationSource.Input.cs
new file mode 100644
index 0000000000..53e6e0ea7b
--- /dev/null
+++ b/src/Avalonia.Controls/PresentationSource/PresentationSource.Input.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Threading;
+using Avalonia.Diagnostics;
+using Avalonia.Input;
+using Avalonia.Input.Raw;
+using Avalonia.Logging;
+using Avalonia.Platform;
+using Avalonia.Threading;
+
+namespace Avalonia.Controls;
+
+internal partial class PresentationSource
+{
+ ///
+ /// Handles input from .
+ ///
+ /// The event args.
+ private void HandleInputCore(object state)
+ {
+ using var _ = Diagnostic.BeginLayoutInputPass();
+
+ var e = (RawInputEventArgs)state!;
+ if (e is RawPointerEventArgs pointerArgs)
+ {
+ var hitTestElement = RootElement.InputHitTest(pointerArgs.Position, enabledElementsOnly: false);
+
+ pointerArgs.InputHitTestResult = (hitTestElement, FirstEnabledAncestor(hitTestElement));
+ }
+
+ _inputManager?.ProcessInput(e);
+ }
+
+ private SendOrPostCallback _handleInputCore;
+
+ private void HandleInput(RawInputEventArgs e)
+ {
+ if (PlatformImpl != null)
+ {
+ Dispatcher.UIThread.Send(_handleInputCore, e);
+ }
+ else
+ {
+ Logger.TryGet(LogEventLevel.Warning, LogArea.Control)?.Log(
+ this,
+ "PlatformImpl is null, couldn't handle input.");
+ }
+ }
+
+
+ private static IInputElement? FirstEnabledAncestor(IInputElement? hitTestElement)
+ {
+ var candidate = hitTestElement;
+ while (candidate?.IsEffectivelyEnabled == false)
+ {
+ candidate = (candidate as Visual)?.VisualParent as IInputElement;
+ }
+ return candidate;
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Controls/PresentationSource/PresentationSource.cs b/src/Avalonia.Controls/PresentationSource/PresentationSource.cs
index 5a01cb2d8e..ca9f6a8b92 100644
--- a/src/Avalonia.Controls/PresentationSource/PresentationSource.cs
+++ b/src/Avalonia.Controls/PresentationSource/PresentationSource.cs
@@ -9,7 +9,7 @@ namespace Avalonia.Controls;
internal partial class PresentationSource : IPresentationSource, IDisposable
{
- public ITopLevelImpl PlatformImpl { get; }
+ public ITopLevelImpl? PlatformImpl { get; private set; }
private readonly PointerOverPreProcessor? _pointerOverPreProcessor;
private readonly IDisposable? _pointerOverPreProcessorSubscription;
private readonly IInputManager? _inputManager;
@@ -21,9 +21,14 @@ internal partial class PresentationSource : IPresentationSource, IDisposable
{
RootVisual = rootVisual;
PlatformImpl = platformImpl;
-
+
_inputManager = TryGetService(dependencyResolver);
+ _handleInputCore = HandleInputCore;
+
+ PlatformImpl.SetInputRoot(this);
+ PlatformImpl.Input = HandleInput;
+
_pointerOverPreProcessor = new PointerOverPreProcessor(this);
_pointerOverPreProcessorSubscription = _inputManager?.PreProcess.Subscribe(_pointerOverPreProcessor);
}
@@ -63,6 +68,7 @@ internal partial class PresentationSource : IPresentationSource, IDisposable
public void Dispose()
{
+ PlatformImpl = null;
_pointerOverPreProcessor?.OnCompleted();
_pointerOverPreProcessorSubscription?.Dispose();
}
@@ -96,7 +102,7 @@ internal partial class PresentationSource : IPresentationSource, IDisposable
}
// TODO: Make popup positioner to use PresentationSource internally rather than TopLevel
- public PixelPoint? GetLastPointerPosition(TopLevel topLevel)
+ public PixelPoint? GetLastPointerPosition(Visual topLevel)
{
return _pointerOverPreProcessor?.LastPosition;
}
diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs
index b0be6ad2f3..ac7d629cba 100644
--- a/src/Avalonia.Controls/TopLevel.cs
+++ b/src/Avalonia.Controls/TopLevel.cs
@@ -212,11 +212,9 @@ namespace Avalonia.Controls
Renderer = new CompositingRenderer(this, impl.Compositor, () => PlatformImpl.Surfaces ?? []);
Renderer.SceneInvalidated += SceneInvalidated;
-
- impl.SetInputRoot(_source);
+
impl.Closed = HandleClosed;
- impl.Input = HandleInput;
impl.Paint = HandlePaint;
impl.Resized = HandleResized;
impl.ScalingChanged = HandleScalingChanged;
@@ -815,48 +813,6 @@ namespace Avalonia.Controls
return result;
}
- ///
- /// Handles input from .
- ///
- /// The event args.
- private void HandleInput(RawInputEventArgs e)
- {
- if (PlatformImpl != null)
- {
- Dispatcher.UIThread.Send(static state =>
- {
- using var _ = Diagnostic.BeginLayoutInputPass();
-
- var (topLevel, e) = (ValueTuple)state!;
- if (e is RawPointerEventArgs pointerArgs)
- {
- var hitTestElement = topLevel.InputHitTest(pointerArgs.Position, enabledElementsOnly: false);
-
- pointerArgs.InputHitTestResult = (hitTestElement, FirstEnabledAncestor(hitTestElement));
- }
-
- topLevel._inputManager?.ProcessInput(e);
- }, (this, e));
- }
- else
- {
- Logger.TryGet(LogEventLevel.Warning, LogArea.Control)?.Log(
- this,
- "PlatformImpl is null, couldn't handle input.");
- }
- }
-
- private static IInputElement? FirstEnabledAncestor(IInputElement? hitTestElement)
- {
- var candidate = hitTestElement;
- while (candidate?.IsEffectivelyEnabled == false)
- {
- candidate = (candidate as Visual)?.VisualParent as IInputElement;
- }
-
- return candidate;
- }
-
private void GlobalActualThemeVariantChanged(object? sender, EventArgs e)
{
SetValue(ActualThemeVariantProperty, ((IThemeVariantHost)sender!).ActualThemeVariant, BindingPriority.Template);