Browse Source

Introduce TopLevelImpl.TryGetFeature instead of having multiple interfaces per feature

pull/10129/head
Max Katz 3 years ago
parent
commit
f5a81d71e2
  1. 4
      src/Android/Avalonia.Android/Platform/AndroidSystemNavigationManager.cs
  2. 46
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  3. 1
      src/Avalonia.Base/Platform/IOptionalFeatureProvider.cs
  4. 8
      src/Avalonia.Base/Platform/SystemNavigationManagerImpl.cs
  5. 2
      src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
  6. 2
      src/Avalonia.Controls/NativeControlHost.cs
  7. 3
      src/Avalonia.Controls/NativeMenu.Export.cs
  8. 6
      src/Avalonia.Controls/Platform/INativeControlHostImpl.cs
  9. 2
      src/Avalonia.Controls/Platform/ITopLevelImpl.cs
  10. 11
      src/Avalonia.Controls/Platform/ITopLevelImplWithStorageProvider.cs
  11. 13
      src/Avalonia.Controls/Platform/ITopLevelImplWithTextInputMethod.cs
  12. 6
      src/Avalonia.Controls/Platform/ITopLevelNativeMenuExporter.cs
  13. 9
      src/Avalonia.Controls/TopLevel.cs
  14. 14
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  15. 1
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  16. 11
      src/Avalonia.Headless/HeadlessWindowImpl.cs
  17. 18
      src/Avalonia.Native/WindowImpl.cs
  18. 21
      src/Avalonia.Native/WindowImplBase.cs
  19. 45
      src/Avalonia.X11/X11Window.cs
  20. 4
      src/Browser/Avalonia.Browser/BrowserSystemNavigationManager.cs
  21. 36
      src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs
  22. 1
      src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
  23. 2
      src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs
  24. 32
      src/Windows/Avalonia.Win32/WindowImpl.cs
  25. 31
      src/iOS/Avalonia.iOS/AvaloniaView.cs
  26. 4
      tests/Avalonia.UnitTests/CompositorTestServices.cs

4
src/Android/Avalonia.Android/Platform/AndroidSystemNavigationManager.cs

@ -4,11 +4,11 @@ using Avalonia.Platform;
namespace Avalonia.Android.Platform
{
internal class AndroidSystemNavigationManager : ISystemNavigationManager
internal class AndroidSystemNavigationManagerImpl : ISystemNavigationManagerImpl
{
public event EventHandler<RoutedEventArgs> BackRequested;
public AndroidSystemNavigationManager(IActivityNavigationService? navigationService)
public AndroidSystemNavigationManagerImpl(IActivityNavigationService? navigationService)
{
if(navigationService != null)
{

46
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -31,9 +31,7 @@ using Android.Graphics.Drawables;
namespace Avalonia.Android.Platform.SkiaPlatform
{
class TopLevelImpl : IAndroidView, ITopLevelImpl, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo,
ITopLevelImplWithTextInputMethod, ITopLevelImplWithNativeControlHost, ITopLevelImplWithStorageProvider,
ITopLevelWithSystemNavigationManager
class TopLevelImpl : IAndroidView, ITopLevelImpl, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo
{
private readonly IGlPlatformSurface _gl;
private readonly IFramebufferPlatformSurface _framebuffer;
@ -41,6 +39,9 @@ namespace Avalonia.Android.Platform.SkiaPlatform
private readonly AndroidKeyboardEventsHelper<TopLevelImpl> _keyboardHelper;
private readonly AndroidMotionEventsHelper _pointerHelper;
private readonly AndroidInputMethod<ViewImpl> _textInputMethod;
private readonly INativeControlHostImpl _nativeControlHost;
private readonly IStorageProvider _storageProvider;
private readonly ISystemNavigationManagerImpl _systemNavigationManager;
private ViewImpl _view;
public TopLevelImpl(AvaloniaView avaloniaView, bool placeOnTop = false)
@ -57,10 +58,10 @@ namespace Avalonia.Android.Platform.SkiaPlatform
MaxClientSize = new PixelSize(_view.Resources.DisplayMetrics.WidthPixels,
_view.Resources.DisplayMetrics.HeightPixels).ToSize(RenderScaling);
NativeControlHost = new AndroidNativeControlHostImpl(avaloniaView);
StorageProvider = new AndroidStorageProvider((Activity)avaloniaView.Context);
_nativeControlHost = new AndroidNativeControlHostImpl(avaloniaView);
_storageProvider = new AndroidStorageProvider((Activity)avaloniaView.Context);
SystemNavigationManager = new AndroidSystemNavigationManager(avaloniaView.Context as IActivityNavigationService);
_systemNavigationManager = new AndroidSystemNavigationManagerImpl(avaloniaView.Context as IActivityNavigationService);
}
public virtual Point GetAvaloniaPointFromEvent(MotionEvent e, int pointerIndex) =>
@ -294,14 +295,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public double Scaling => RenderScaling;
public ITextInputMethodImpl TextInputMethod => _textInputMethod;
public INativeControlHostImpl NativeControlHost { get; }
public IStorageProvider StorageProvider { get; }
public ISystemNavigationManager SystemNavigationManager { get; }
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel)
{
if (TransparencyLevel != transparencyLevel)
@ -386,6 +379,31 @@ namespace Avalonia.Android.Platform.SkiaPlatform
}
}
}
public virtual object TryGetFeature(Type featureType)
{
if (featureType == typeof(IStorageProvider))
{
return _storageProvider;
}
if (featureType == typeof(ITextInputMethodImpl))
{
return _textInputMethod;
}
if (featureType == typeof(ISystemNavigationManagerImpl))
{
return _systemNavigationManager;
}
if (featureType == typeof(INativeControlHostImpl))
{
return _nativeControlHost;
}
return null;
}
}
internal class AvaloniaInputConnection : BaseInputConnection

1
src/Avalonia.Base/Platform/IOptionalFeatureProvider.cs

@ -23,5 +23,4 @@ public static class OptionalFeatureProviderExtensions
rv = provider.TryGetFeature<T>();
return rv != null;
}
}

8
src/Avalonia.Base/Platform/SystemNavigationManager.cs → src/Avalonia.Base/Platform/SystemNavigationManagerImpl.cs

@ -5,13 +5,7 @@ using Avalonia.Metadata;
namespace Avalonia.Platform
{
[Unstable]
public interface ITopLevelWithSystemNavigationManager
{
ISystemNavigationManager SystemNavigationManager { get; }
}
[Unstable]
public interface ISystemNavigationManager
public interface ISystemNavigationManagerImpl
{
public event EventHandler<RoutedEventArgs>? BackRequested;
}

2
src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs

@ -94,5 +94,7 @@ namespace Avalonia.Controls.Embedding.Offscreen
public WindowTransparencyLevel TransparencyLevel { get; private set; }
public IPopupImpl? CreatePopup() => null;
public virtual object? TryGetFeature(Type featureType) => null;
}
}

2
src/Avalonia.Controls/NativeControlHost.cs

@ -58,7 +58,7 @@ namespace Avalonia.Controls
private void UpdateHost()
{
_queuedForMoveResize = false;
_currentHost = (_currentRoot?.PlatformImpl as ITopLevelImplWithNativeControlHost)?.NativeControlHost;
_currentHost = _currentRoot?.PlatformImpl?.TryGetFeature<INativeControlHostImpl>();
if (_currentHost != null)
{

3
src/Avalonia.Controls/NativeMenu.Export.cs

@ -1,6 +1,7 @@
using System;
using Avalonia.Controls.Platform;
using Avalonia.Reactive;
using Avalonia.Platform;
namespace Avalonia.Controls
{
@ -21,7 +22,7 @@ namespace Avalonia.Controls
public NativeMenuInfo(TopLevel target)
{
Exporter = (target.PlatformImpl as ITopLevelImplWithNativeMenuExporter)?.NativeMenuExporter;
Exporter = target.PlatformImpl?.TryGetFeature<ITopLevelNativeMenuExporter>();
if (Exporter != null)
{
Exporter.OnIsNativeMenuExportedChanged += delegate

6
src/Avalonia.Controls/Platform/INativeControlHostImpl.cs

@ -29,10 +29,4 @@ namespace Avalonia.Controls.Platform
void HideWithSize(Size size);
void ShowInBounds(Rect rect);
}
[Unstable]
public interface ITopLevelImplWithNativeControlHost
{
INativeControlHostImpl? NativeControlHost { get; }
}
}

2
src/Avalonia.Controls/Platform/ITopLevelImpl.cs

@ -51,7 +51,7 @@ namespace Avalonia.Platform
/// <see cref="IPopupImpl"/>.
/// </remarks>
[Unstable]
public interface ITopLevelImpl : IDisposable
public interface ITopLevelImpl : IOptionalFeatureProvider, IDisposable
{
/// <summary>
/// Gets the client size of the toplevel.

11
src/Avalonia.Controls/Platform/ITopLevelImplWithStorageProvider.cs

@ -1,11 +0,0 @@
using Avalonia.Metadata;
using Avalonia.Platform;
using Avalonia.Platform.Storage;
namespace Avalonia.Controls.Platform;
[Unstable]
public interface ITopLevelImplWithStorageProvider : ITopLevelImpl
{
public IStorageProvider StorageProvider { get; }
}

13
src/Avalonia.Controls/Platform/ITopLevelImplWithTextInputMethod.cs

@ -1,13 +0,0 @@
using Avalonia.Input;
using Avalonia.Input.TextInput;
using Avalonia.Metadata;
using Avalonia.Platform;
namespace Avalonia.Controls.Platform
{
[Unstable]
public interface ITopLevelImplWithTextInputMethod : ITopLevelImpl
{
public ITextInputMethodImpl? TextInputMethod { get; }
}
}

6
src/Avalonia.Controls/Platform/ITopLevelNativeMenuExporter.cs

@ -23,10 +23,4 @@ namespace Avalonia.Controls.Platform
{
INativeMenuExporter? NativeMenuExporter { get; }
}
[Unstable]
public interface ITopLevelImplWithNativeMenuExporter : ITopLevelImpl
{
ITopLevelNativeMenuExporter? NativeMenuExporter { get; }
}
}

9
src/Avalonia.Controls/TopLevel.cs

@ -216,9 +216,9 @@ namespace Avalonia.Controls
_pointerOverPreProcessor = new PointerOverPreProcessor(this);
_pointerOverPreProcessorSubscription = _inputManager?.PreProcess.Subscribe(_pointerOverPreProcessor);
if(impl is ITopLevelWithSystemNavigationManager topLevelWithSystemNavigation)
if(impl.TryGetFeature<ISystemNavigationManagerImpl>() is {} systemNavigationManager)
{
topLevelWithSystemNavigation.SystemNavigationManager.BackRequested += (s, e) =>
systemNavigationManager.BackRequested += (s, e) =>
{
e.RoutedEvent = BackRequestedEvent;
RaiseEvent(e);
@ -382,7 +382,7 @@ namespace Avalonia.Controls
public IStorageProvider StorageProvider => _storageProvider
??= AvaloniaLocator.Current.GetService<IStorageProviderFactory>()?.CreateProvider(this)
?? (PlatformImpl as ITopLevelImplWithStorageProvider)?.StorageProvider
?? PlatformImpl?.TryGetFeature<IStorageProvider>()
?? throw new InvalidOperationException("StorageProvider platform implementation is not available.");
/// <inheritdoc/>
@ -616,7 +616,6 @@ namespace Avalonia.Controls
// Do nothing becuase TopLevel should't apply MirrorTransform on himself.
}
ITextInputMethodImpl? ITextInputMethodRoot.InputMethod =>
(PlatformImpl as ITopLevelImplWithTextInputMethod)?.TextInputMethod;
ITextInputMethodImpl? ITextInputMethodRoot.InputMethod => PlatformImpl?.TryGetFeature<ITextInputMethodImpl>();
}
}

14
src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@ -11,7 +11,7 @@ using Avalonia.Threading;
namespace Avalonia.DesignerSupport.Remote
{
class PreviewerWindowImpl : RemoteServerTopLevelImpl, IWindowImpl, ITopLevelImplWithStorageProvider
class PreviewerWindowImpl : RemoteServerTopLevelImpl, IWindowImpl
{
private readonly IAvaloniaRemoteTransportConnection _transport;
@ -92,8 +92,16 @@ namespace Avalonia.DesignerSupport.Remote
public bool NeedsManagedDecorations => false;
public IStorageProvider StorageProvider => new NoopStorageProvider();
public override object TryGetFeature(Type featureType)
{
if (featureType == typeof(IStorageProvider))
{
return new NoopStorageProvider();
}
return base.TryGetFeature(featureType);
}
public void Activate()
{
}

1
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@ -194,6 +194,7 @@ namespace Avalonia.DesignerSupport.Remote
public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { }
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1);
public object TryGetFeature(Type featureType) => null;
}
class ClipboardStub : IClipboard

11
src/Avalonia.Headless/HeadlessWindowImpl.cs

@ -18,7 +18,7 @@ using Avalonia.Utilities;
namespace Avalonia.Headless
{
class HeadlessWindowImpl : IWindowImpl, IPopupImpl, IFramebufferPlatformSurface, IHeadlessWindow, ITopLevelImplWithStorageProvider
class HeadlessWindowImpl : IWindowImpl, IPopupImpl, IFramebufferPlatformSurface, IHeadlessWindow
{
private IKeyboardDevice _keyboard;
private Stopwatch _st = Stopwatch.StartNew();
@ -247,8 +247,15 @@ namespace Avalonia.Headless
public Action LostFocus { get; set; }
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => new AcrylicPlatformCompensationLevels(1, 1, 1);
public object TryGetFeature(Type featureType)
{
if (featureType == typeof(IStorageProvider))
{
return new NoopStorageProvider();
}
public IStorageProvider StorageProvider => new NoopStorageProvider();
return null;
}
void IHeadlessWindow.KeyPress(Key key, RawInputModifiers modifiers)
{

18
src/Avalonia.Native/WindowImpl.cs

@ -11,14 +11,14 @@ using Avalonia.Platform.Interop;
namespace Avalonia.Native
{
internal class WindowImpl : WindowBaseImpl, IWindowImpl, ITopLevelImplWithNativeMenuExporter
internal class WindowImpl : WindowBaseImpl, IWindowImpl
{
private readonly AvaloniaNativePlatformOptions _opts;
private readonly AvaloniaNativeGlPlatformGraphics _glFeature;
IAvnWindow _native;
private double _extendTitleBarHeight = -1;
private DoubleClickHelper _doubleClickHelper;
private readonly ITopLevelNativeMenuExporter _nativeMenuExporter;
internal WindowImpl(IAvaloniaNativeFactory factory, AvaloniaNativePlatformOptions opts,
AvaloniaNativeGlPlatformGraphics glFeature) : base(factory, opts, glFeature)
@ -32,7 +32,7 @@ namespace Avalonia.Native
Init(_native = factory.CreateWindow(e, glFeature.SharedContext.Context), factory.CreateScreens());
}
NativeMenuExporter = new AvaloniaNativeMenuExporter(_native, factory);
_nativeMenuExporter = new AvaloniaNativeMenuExporter(_native, factory);
}
class WindowEvents : WindowBaseEvents, IAvnWindowEvents
@ -209,8 +209,6 @@ namespace Avalonia.Native
public Func<WindowCloseReason, bool> Closing { get; set; }
public ITopLevelNativeMenuExporter NativeMenuExporter { get; }
public void Move(PixelPoint point) => Position = point;
public override IPopupImpl CreatePopup() =>
@ -227,5 +225,15 @@ namespace Avalonia.Native
{
_native.SetEnabled(enable.AsComBool());
}
public override object TryGetFeature(Type featureType)
{
if (featureType == typeof(ITopLevelNativeMenuExporter))
{
return _nativeMenuExporter;
}
return base.TryGetFeature(featureType);
}
}
}

21
src/Avalonia.Native/WindowImplBase.cs

@ -47,7 +47,7 @@ namespace Avalonia.Native
}
internal abstract class WindowBaseImpl : IWindowBaseImpl,
IFramebufferPlatformSurface, ITopLevelImplWithNativeControlHost, ITopLevelImplWithStorageProvider
IFramebufferPlatformSurface
{
protected readonly IAvaloniaNativeFactory _factory;
protected IInputRoot _inputRoot;
@ -62,6 +62,7 @@ namespace Avalonia.Native
private double _savedScaling;
private GlPlatformSurface _glSurface;
private NativeControlHostImpl _nativeControlHost;
private IStorageProvider _storageProvider;
internal WindowBaseImpl(IAvaloniaNativeFactory factory, AvaloniaNativePlatformOptions opts,
AvaloniaNativeGlPlatformGraphics glFeature)
@ -72,7 +73,6 @@ namespace Avalonia.Native
_keyboard = AvaloniaLocator.Current.GetService<IKeyboardDevice>();
_mouse = new MouseDevice();
_cursorFactory = AvaloniaLocator.Current.GetService<ICursorFactory>();
StorageProvider = new SystemDialogs(this, _factory.CreateSystemDialogs());
}
protected void Init(IAvnWindowBase window, IAvnScreens screens)
@ -87,6 +87,7 @@ namespace Avalonia.Native
_savedLogicalSize = ClientSize;
_savedScaling = RenderScaling;
_nativeControlHost = new NativeControlHostImpl(_native.CreateNativeControlHost());
_storageProvider = new SystemDialogs(this, _factory.CreateSystemDialogs());
var monitor = Screen.AllScreens.OrderBy(x => x.Scaling)
.FirstOrDefault(m => m.Bounds.Contains(Position));
@ -508,9 +509,21 @@ namespace Avalonia.Native
}
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 0, 0);
public virtual object TryGetFeature(Type featureType)
{
if (featureType == typeof(INativeControlHostImpl))
{
return _nativeControlHost;
}
if (featureType == typeof(IStorageProvider))
{
return _storageProvider;
}
public IPlatformHandle Handle { get; private set; }
return null;
}
public IStorageProvider StorageProvider { get; }
public IPlatformHandle Handle { get; private set; }
}
}

45
src/Avalonia.X11/X11Window.cs

@ -27,11 +27,7 @@ using static Avalonia.X11.XLib;
// ReSharper disable StringLiteralTypo
namespace Avalonia.X11
{
unsafe partial class X11Window : IWindowImpl, IPopupImpl, IXI2Client,
ITopLevelImplWithNativeMenuExporter,
ITopLevelImplWithNativeControlHost,
ITopLevelImplWithTextInputMethod,
ITopLevelImplWithStorageProvider
unsafe partial class X11Window : IWindowImpl, IPopupImpl, IXI2Client
{
private readonly AvaloniaX11Platform _platform;
private readonly bool _popup;
@ -43,6 +39,9 @@ namespace Avalonia.X11
private readonly MouseDevice _mouse;
private readonly TouchDevice _touch;
private readonly IKeyboardDevice _keyboard;
private readonly ITopLevelNativeMenuExporter _nativeMenuExporter;
private readonly IStorageProvider _storageProvider;
private readonly X11NativeControlHost _nativeControlHost;
private PixelPoint? _position;
private PixelSize _realSize;
private IntPtr _handle;
@ -199,8 +198,8 @@ namespace Avalonia.X11
if(_popup)
PopupPositioner = new ManagedPopupPositioner(new ManagedPopupPositionerPopupImplHelper(popupParent, MoveResize));
if (platform.Options.UseDBusMenu)
NativeMenuExporter = DBusMenuExporter.TryCreateTopLevelNativeMenu(_handle);
NativeControlHost = new X11NativeControlHost(_platform, this);
_nativeMenuExporter = DBusMenuExporter.TryCreateTopLevelNativeMenu(_handle);
_nativeControlHost = new X11NativeControlHost(_platform, this);
InitializeIme();
XChangeProperty(_x11.Display, _handle, _x11.Atoms.WM_PROTOCOLS, _x11.Atoms.XA_ATOM, 32,
@ -213,7 +212,7 @@ namespace Avalonia.X11
_x11.Atoms.XA_CARDINAL, 32, PropertyMode.Replace, ref _xSyncCounter, 1);
}
StorageProvider = new CompositeStorageProvider(new Func<Task<IStorageProvider>>[]
_storageProvider = new CompositeStorageProvider(new Func<Task<IStorageProvider>>[]
{
() => _platform.Options.UseDBusFilePicker ? DBusSystemDialog.TryCreate(Handle) : Task.FromResult<IStorageProvider>(null),
() => GtkSystemDialog.TryCreate(this),
@ -796,6 +795,31 @@ namespace Avalonia.X11
Cleanup();
}
public virtual object TryGetFeature(Type featureType)
{
if (featureType == typeof(ITopLevelNativeMenuExporter))
{
return _nativeMenuExporter;
}
if (featureType == typeof(IStorageProvider))
{
return _storageProvider;
}
if (featureType == typeof(ITextInputMethodImpl))
{
return _ime;
}
if (featureType == typeof(INativeControlHostImpl))
{
return _nativeControlHost;
}
return null;
}
void Cleanup()
{
if (_rawEventGrouper != null)
@ -1195,9 +1219,6 @@ namespace Avalonia.X11
}
public IPopupPositioner PopupPositioner { get; }
public ITopLevelNativeMenuExporter NativeMenuExporter { get; }
public INativeControlHostImpl NativeControlHost { get; }
public ITextInputMethodImpl TextInputMethod => _ime;
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) =>
_transparencyHelper?.SetTransparencyRequest(transparencyLevel);
@ -1215,8 +1236,6 @@ namespace Avalonia.X11
public bool NeedsManagedDecorations => false;
public IStorageProvider StorageProvider { get; }
public class SurfacePlatformHandle : IPlatformNativeSurfaceHandle
{
private readonly X11Window _owner;

4
src/Browser/Avalonia.Browser/BrowserSystemNavigationManager.cs

@ -5,11 +5,11 @@ using Avalonia.Platform;
namespace Avalonia.Browser
{
internal class BrowserSystemNavigationManager : ISystemNavigationManager
internal class BrowserSystemNavigationManagerImpl : ISystemNavigationManagerImpl
{
public event EventHandler<RoutedEventArgs>? BackRequested;
public BrowserSystemNavigationManager()
public BrowserSystemNavigationManagerImpl()
{
NavigationHelper.AddBackHandler(() =>
{

36
src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs

@ -19,8 +19,7 @@ using Avalonia.Rendering.Composition;
namespace Avalonia.Browser
{
internal class BrowserTopLevelImpl : ITopLevelImplWithTextInputMethod, ITopLevelImplWithNativeControlHost, ITopLevelImplWithStorageProvider,
ITopLevelWithSystemNavigationManager
internal class BrowserTopLevelImpl : ITopLevelImpl
{
private Size _clientSize;
private IInputRoot? _inputRoot;
@ -29,6 +28,9 @@ namespace Avalonia.Browser
private readonly TouchDevice _touchDevice;
private readonly PenDevice _penDevice;
private string _currentCursor = CssCursor.Default;
private readonly INativeControlHostImpl _nativeControlHost;
private readonly IStorageProvider _storageProvider;
private readonly ISystemNavigationManagerImpl _systemNavigationManager;
public BrowserTopLevelImpl(AvaloniaView avaloniaView)
{
@ -38,7 +40,9 @@ namespace Avalonia.Browser
AcrylicCompensationLevels = new AcrylicPlatformCompensationLevels(1, 1, 1);
_touchDevice = new TouchDevice();
_penDevice = new PenDevice();
NativeControlHost = _avaloniaView.GetNativeControlHostImpl();
_nativeControlHost = _avaloniaView.GetNativeControlHostImpl();
_storageProvider = new BrowserStorageProvider();
_systemNavigationManager = new BrowserSystemNavigationManagerImpl();
}
public ulong Timestamp => (ulong)_sw.ElapsedMilliseconds;
@ -236,11 +240,29 @@ namespace Avalonia.Browser
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; }
public ITextInputMethodImpl TextInputMethod => _avaloniaView;
public object? TryGetFeature(Type featureType)
{
if (featureType == typeof(IStorageProvider))
{
return _storageProvider;
}
public INativeControlHostImpl? NativeControlHost { get; }
public IStorageProvider StorageProvider { get; } = new BrowserStorageProvider();
if (featureType == typeof(ITextInputMethodImpl))
{
return _avaloniaView;
}
public ISystemNavigationManager SystemNavigationManager { get; } = new BrowserSystemNavigationManager();
if (featureType == typeof(ISystemNavigationManagerImpl))
{
return _systemNavigationManager;
}
if (featureType == typeof(INativeControlHostImpl))
{
return _nativeControlHost;
}
return null;
}
}
}

1
src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs

@ -77,5 +77,6 @@ namespace Avalonia.LinuxFramebuffer
public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { }
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1);
public object TryGetFeature(Type featureType) => null;
}
}

2
src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs

@ -261,5 +261,7 @@ namespace Avalonia.Win32.Interop.Wpf
public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { }
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1);
public object TryGetFeature(Type featureType) => null;
}
}

32
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -35,10 +35,7 @@ namespace Avalonia.Win32
/// Window implementation for Win32 platform.
/// </summary>
[Unstable]
public partial class WindowImpl : IWindowImpl, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo,
ITopLevelImplWithNativeControlHost,
ITopLevelImplWithTextInputMethod,
ITopLevelImplWithStorageProvider
public partial class WindowImpl : IWindowImpl, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo
{
private static readonly List<WindowImpl> s_instances = new List<WindowImpl>();
@ -83,6 +80,7 @@ namespace Avalonia.Win32
private readonly bool _wmPointerEnabled;
private Win32NativeControlHost _nativeControlHost;
private IStorageProvider _storageProvider;
private WndProc _wndProcDelegate;
private string _className;
private IntPtr _hwnd;
@ -183,7 +181,7 @@ namespace Avalonia.Win32
}
Screen = new ScreenImpl();
StorageProvider = new Win32StorageProvider(this);
_storageProvider = new Win32StorageProvider(this);
_nativeControlHost = new Win32NativeControlHost(this, _isUsingComposition);
s_instances.Add(this);
@ -322,6 +320,26 @@ namespace Avalonia.Win32
private bool IsMouseInPointerEnabled => _wmPointerEnabled && IsMouseInPointerEnabled();
public object TryGetFeature(Type featureType)
{
if (featureType == typeof(ITextInputMethodImpl))
{
return Imm32InputMethod.Current;
}
if (featureType == typeof(INativeControlHostImpl))
{
return _nativeControlHost;
}
if (featureType == typeof(IStorageProvider))
{
return _storageProvider;
}
return null;
}
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel)
{
TransparencyLevel = EnableBlur(transparencyLevel);
@ -1465,10 +1483,6 @@ namespace Avalonia.Win32
public void Dispose() => _owner._resizeReason = _restore;
}
public ITextInputMethodImpl TextInputMethod => Imm32InputMethod.Current;
public IStorageProvider StorageProvider { get; }
private class WindowImplPlatformHandle : IPlatformNativeSurfaceHandle
{
private readonly WindowImpl _owner;

31
src/iOS/Avalonia.iOS/AvaloniaView.cs

@ -68,17 +68,18 @@ namespace Avalonia.iOS
settings?.TraitCollectionDidChange();
}
internal class TopLevelImpl : ITopLevelImplWithTextInputMethod, ITopLevelImplWithNativeControlHost,
ITopLevelImplWithStorageProvider
internal class TopLevelImpl : ITopLevelImpl
{
private readonly AvaloniaView _view;
private readonly INativeControlHostImpl _nativeControlHost;
private readonly IStorageProvider _storageProvider;
public AvaloniaView View => _view;
public TopLevelImpl(AvaloniaView view)
{
_view = view;
NativeControlHost = new NativeControlHostImpl(_view);
StorageProvider = new IOSStorageProvider(view);
_nativeControlHost = new NativeControlHostImpl(_view);
_storageProvider = new IOSStorageProvider(view);
}
public void Dispose()
@ -157,9 +158,25 @@ namespace Avalonia.iOS
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } =
new AcrylicPlatformCompensationLevels();
public ITextInputMethodImpl? TextInputMethod => _view;
public INativeControlHostImpl NativeControlHost { get; }
public IStorageProvider StorageProvider { get; }
public object? TryGetFeature(Type featureType)
{
if (featureType == typeof(IStorageProvider))
{
return _storageProvider;
}
if (featureType == typeof(ITextInputMethodImpl))
{
return _view;
}
if (featureType == typeof(INativeControlHostImpl))
{
return _nativeControlHost;
}
return null;
}
}
[Export("layerClass")]

4
tests/Avalonia.UnitTests/CompositorTestServices.cs

@ -203,5 +203,7 @@ public class CompositorTestServices : IDisposable
}
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; }
public object TryGetFeature(Type featureType) => null;
}
}
}

Loading…
Cancel
Save