diff --git a/samples/interop/Direct3DInteropSample/MainWindow.cs b/samples/interop/Direct3DInteropSample/MainWindow.cs
index 1ff1e1938b..ad40e81895 100644
--- a/samples/interop/Direct3DInteropSample/MainWindow.cs
+++ b/samples/interop/Direct3DInteropSample/MainWindow.cs
@@ -58,7 +58,7 @@ namespace Direct3DInteropSample
new ModeDescription((int)ClientSize.Width, (int)ClientSize.Height,
new Rational(60, 1), Format.R8G8B8A8_UNorm),
IsWindowed = true,
- OutputHandle = PlatformImpl.Handle.Handle,
+ OutputHandle = PlatformImpl?.Handle.Handle ?? IntPtr.Zero,
SampleDescription = new SampleDescription(1, 0),
SwapEffect = SwapEffect.Discard,
Usage = Usage.RenderTargetOutput
diff --git a/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs b/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
index 4688017187..b8d54fa67b 100644
--- a/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
+++ b/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
@@ -4,6 +4,7 @@ using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Platform;
using Avalonia.Styling;
+using JetBrains.Annotations;
namespace Avalonia.Controls.Embedding
{
@@ -18,6 +19,7 @@ namespace Avalonia.Controls.Embedding
{
}
+ [CanBeNull]
public new IEmbeddableWindowImpl PlatformImpl => (IEmbeddableWindowImpl) base.PlatformImpl;
public void Prepare()
@@ -39,8 +41,9 @@ namespace Avalonia.Controls.Embedding
protected override Size MeasureOverride(Size availableSize)
{
- base.MeasureOverride(PlatformImpl.ClientSize);
- return PlatformImpl.ClientSize;
+ var cs = PlatformImpl?.ClientSize ?? default(Size);
+ base.MeasureOverride(cs);
+ return cs;
}
private readonly NameScope _nameScope = new NameScope();
@@ -63,9 +66,6 @@ namespace Avalonia.Controls.Embedding
public void Unregister(string name) => _nameScope.Unregister(name);
Type IStyleable.StyleKey => typeof(EmbeddableControlRoot);
- public void Dispose()
- {
- PlatformImpl.Dispose();
- }
+ public void Dispose() => PlatformImpl?.Dispose();
}
}
diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs
index 86c1b47521..a999e4ae37 100644
--- a/src/Avalonia.Controls/Primitives/PopupRoot.cs
+++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs
@@ -9,6 +9,7 @@ using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.VisualTree;
+using JetBrains.Annotations;
namespace Avalonia.Controls.Primitives
{
@@ -49,6 +50,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets the platform-specific window implementation.
///
+ [CanBeNull]
public new IPopupImpl PlatformImpl => (IPopupImpl)base.PlatformImpl;
///
@@ -65,10 +67,7 @@ namespace Avalonia.Controls.Primitives
IVisual IHostedVisualTreeRoot.Host => Parent;
///
- public void Dispose()
- {
- this.PlatformImpl.Dispose();
- }
+ public void Dispose() => PlatformImpl?.Dispose();
///
protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs
index f3a6ab92d0..53dd905eca 100644
--- a/src/Avalonia.Controls/TopLevel.cs
+++ b/src/Avalonia.Controls/TopLevel.cs
@@ -14,6 +14,7 @@ using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.VisualTree;
+using JetBrains.Annotations;
namespace Avalonia.Controls
{
@@ -92,13 +93,13 @@ namespace Avalonia.Controls
var rendererFactory = TryGetService(dependencyResolver);
Renderer = rendererFactory?.CreateRenderer(this, renderLoop);
- PlatformImpl.SetInputRoot(this);
+ impl.SetInputRoot(this);
- PlatformImpl.Closed = HandleClosed;
- PlatformImpl.Input = HandleInput;
- PlatformImpl.Paint = HandlePaint;
- PlatformImpl.Resized = HandleResized;
- PlatformImpl.ScalingChanged = HandleScalingChanged;
+ impl.Closed = HandleClosed;
+ impl.Input = HandleInput;
+ impl.Paint = HandlePaint;
+ impl.Resized = HandleResized;
+ impl.ScalingChanged = HandleScalingChanged;
_keyboardNavigationHandler?.SetOwner(this);
@@ -110,7 +111,7 @@ namespace Avalonia.Controls
this.GetObservable(PointerOverElementProperty)
.Select(
x => (x as InputElement)?.GetObservable(CursorProperty) ?? Observable.Empty())
- .Switch().Subscribe(cursor => PlatformImpl.SetCursor(cursor?.PlatformCursor));
+ .Switch().Subscribe(cursor => PlatformImpl?.SetCursor(cursor?.PlatformCursor));
if (_applicationLifecycle != null)
{
@@ -135,10 +136,8 @@ namespace Avalonia.Controls
///
/// Gets the platform-specific window implementation.
///
- public ITopLevelImpl PlatformImpl
- {
- get;
- }
+ [CanBeNull]
+ public ITopLevelImpl PlatformImpl { get; private set; }
///
/// Gets the renderer for the window.
@@ -177,7 +176,7 @@ namespace Avalonia.Controls
Size ILayoutRoot.MaxClientSize => Size.Infinity;
///
- double ILayoutRoot.LayoutScaling => PlatformImpl.Scaling;
+ double ILayoutRoot.LayoutScaling => PlatformImpl?.Scaling ?? 1;
IStyleHost IStyleHost.StylingParent
{
@@ -189,25 +188,27 @@ namespace Avalonia.Controls
///
protected virtual IRenderTarget CreateRenderTarget()
{
+ if(PlatformImpl == null)
+ throw new InvalidOperationException("PlatformImpl isn't available");
return _renderInterface.CreateRenderTarget(PlatformImpl.Surfaces);
}
///
void IRenderRoot.Invalidate(Rect rect)
{
- PlatformImpl.Invalidate(rect);
+ PlatformImpl?.Invalidate(rect);
}
///
Point IRenderRoot.PointToClient(Point p)
{
- return PlatformImpl.PointToClient(p);
+ return PlatformImpl?.PointToClient(p) ?? default(Point);
}
///
Point IRenderRoot.PointToScreen(Point p)
{
- return PlatformImpl.PointToScreen(p);
+ return PlatformImpl?.PointToScreen(p) ?? default(Point);
}
///
@@ -224,6 +225,8 @@ namespace Avalonia.Controls
///
protected virtual void HandleClosed()
{
+ PlatformImpl = null;
+
Closed?.Invoke(this, EventArgs.Empty);
Renderer?.Dispose();
Renderer = null;
diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs
index 75587dcaec..32eaf499f0 100644
--- a/src/Avalonia.Controls/Window.cs
+++ b/src/Avalonia.Controls/Window.cs
@@ -12,6 +12,7 @@ using Avalonia.Platform;
using Avalonia.Styling;
using System.Collections.Generic;
using System.Linq;
+using JetBrains.Annotations;
namespace Avalonia.Controls
{
@@ -87,11 +88,11 @@ namespace Avalonia.Controls
static Window()
{
BackgroundProperty.OverrideDefaultValue(typeof(Window), Brushes.White);
- TitleProperty.Changed.AddClassHandler((s, e) => s.PlatformImpl.SetTitle((string)e.NewValue));
+ TitleProperty.Changed.AddClassHandler((s, e) => s.PlatformImpl?.SetTitle((string)e.NewValue));
HasSystemDecorationsProperty.Changed.AddClassHandler(
- (s, e) => s.PlatformImpl.SetSystemDecorations((bool) e.NewValue));
+ (s, e) => s.PlatformImpl?.SetSystemDecorations((bool) e.NewValue));
- IconProperty.Changed.AddClassHandler((s, e) => s.PlatformImpl.SetIcon(((WindowIcon)e.NewValue).PlatformImpl));
+ IconProperty.Changed.AddClassHandler((s, e) => s.PlatformImpl?.SetIcon(((WindowIcon)e.NewValue).PlatformImpl));
}
///
@@ -109,7 +110,7 @@ namespace Avalonia.Controls
public Window(IWindowImpl impl)
: base(impl)
{
- _maxPlatformClientSize = this.PlatformImpl.MaxClientSize;
+ _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size);
}
///
@@ -129,6 +130,7 @@ namespace Avalonia.Controls
///
/// Gets the platform-specific window implementation.
///
+ [CanBeNull]
public new IWindowImpl PlatformImpl => (IWindowImpl)base.PlatformImpl;
///
@@ -164,8 +166,12 @@ namespace Avalonia.Controls
///
public WindowState WindowState
{
- get { return this.PlatformImpl.WindowState; }
- set { this.PlatformImpl.WindowState = value; }
+ get { return PlatformImpl?.WindowState ?? WindowState.Normal; }
+ set
+ {
+ if (PlatformImpl != null)
+ PlatformImpl.WindowState = value;
+ }
}
///
@@ -189,7 +195,7 @@ namespace Avalonia.Controls
public void Close()
{
s_windows.Remove(this);
- PlatformImpl.Dispose();
+ PlatformImpl?.Dispose();
IsVisible = false;
}
@@ -221,7 +227,7 @@ namespace Avalonia.Controls
{
using (BeginAutoSizing())
{
- PlatformImpl.Hide();
+ PlatformImpl?.Hide();
}
IsVisible = false;
@@ -240,7 +246,7 @@ namespace Avalonia.Controls
using (BeginAutoSizing())
{
- PlatformImpl.Show();
+ PlatformImpl?.Show();
}
}
@@ -278,7 +284,7 @@ namespace Avalonia.Controls
var activated = affectedWindows.Where(w => w.IsActive).FirstOrDefault();
SetIsEnabled(affectedWindows, false);
- var modal = PlatformImpl.ShowDialog();
+ var modal = PlatformImpl?.ShowDialog();
var result = new TaskCompletionSource();
Observable.FromEventPattern(
@@ -287,7 +293,7 @@ namespace Avalonia.Controls
.Take(1)
.Subscribe(_ =>
{
- modal.Dispose();
+ modal?.Dispose();
SetIsEnabled(affectedWindows, true);
activated?.Activate();
result.SetResult((TResult)_dialogResult);
diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs
index 21c248db0c..1f484fd6cb 100644
--- a/src/Avalonia.Controls/WindowBase.cs
+++ b/src/Avalonia.Controls/WindowBase.cs
@@ -9,6 +9,7 @@ using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Platform;
+using JetBrains.Annotations;
namespace Avalonia.Controls
{
@@ -43,10 +44,10 @@ namespace Avalonia.Controls
public WindowBase(IWindowBaseImpl impl, IAvaloniaDependencyResolver dependencyResolver) : base(impl, dependencyResolver)
{
- PlatformImpl.Activated = HandleActivated;
- PlatformImpl.Deactivated = HandleDeactivated;
- PlatformImpl.PositionChanged = HandlePositionChanged;
- this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl.Resize(x));
+ impl.Activated = HandleActivated;
+ impl.Deactivated = HandleDeactivated;
+ impl.PositionChanged = HandlePositionChanged;
+ this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl?.Resize(x));
}
///
@@ -64,6 +65,7 @@ namespace Avalonia.Controls
///
public event EventHandler PositionChanged;
+ [CanBeNull]
public new IWindowBaseImpl PlatformImpl => (IWindowBaseImpl) base.PlatformImpl;
///
@@ -80,8 +82,12 @@ namespace Avalonia.Controls
///
public Point Position
{
- get { return PlatformImpl.Position; }
- set { PlatformImpl.Position = value; }
+ get { return PlatformImpl?.Position ?? default(Point); }
+ set
+ {
+ if (PlatformImpl is IWindowBaseImpl impl)
+ impl.Position = value;
+ }
}
///
@@ -98,7 +104,7 @@ namespace Avalonia.Controls
///
public void Activate()
{
- PlatformImpl.Activate();
+ PlatformImpl?.Activate();
}
///
@@ -110,7 +116,7 @@ namespace Avalonia.Controls
try
{
- PlatformImpl.Hide();
+ PlatformImpl?.Hide();
IsVisible = false;
}
finally
@@ -131,7 +137,7 @@ namespace Avalonia.Controls
EnsureInitialized();
IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
- PlatformImpl.Show();
+ PlatformImpl?.Show();
}
finally
{
@@ -163,10 +169,10 @@ namespace Avalonia.Controls
{
using (BeginAutoSizing())
{
- PlatformImpl.Resize(finalSize);
+ PlatformImpl?.Resize(finalSize);
}
- return base.ArrangeOverride(PlatformImpl.ClientSize);
+ return base.ArrangeOverride(PlatformImpl?.ClientSize ?? default(Size));
}
///
@@ -174,7 +180,7 @@ namespace Avalonia.Controls
///
protected void EnsureInitialized()
{
- if (!this.IsInitialized)
+ if (!IsInitialized)
{
var init = (ISupportInitialize)this;
init.BeginInit();
@@ -268,12 +274,12 @@ namespace Avalonia.Controls
///
/// Starts moving a window with left button being held. Should be called from left mouse button press event handler
///
- public void BeginMoveDrag() => PlatformImpl.BeginMoveDrag();
+ public void BeginMoveDrag() => PlatformImpl?.BeginMoveDrag();
///
/// Starts resizing a window. This function is used if an application has window resizing controls.
/// Should be called from left mouse button press event handler
///
- public void BeginResizeDrag(WindowEdge edge) => PlatformImpl.BeginResizeDrag(edge);
+ public void BeginResizeDrag(WindowEdge edge) => PlatformImpl?.BeginResizeDrag(edge);
}
}
diff --git a/src/Avalonia.DesignerSupport/DesignerAssist.cs b/src/Avalonia.DesignerSupport/DesignerAssist.cs
index c9ae89354c..8d30f3cf25 100644
--- a/src/Avalonia.DesignerSupport/DesignerAssist.cs
+++ b/src/Avalonia.DesignerSupport/DesignerAssist.cs
@@ -75,7 +75,7 @@ namespace Avalonia.DesignerSupport
private static void SetScalingFactor(double factor)
{
PlatformManager.SetDesignerScalingFactor(factor);
- s_currentWindow?.PlatformImpl.Resize(s_currentWindow.ClientSize);
+ s_currentWindow?.PlatformImpl?.Resize(s_currentWindow.ClientSize);
}
static Window s_currentWindow;
@@ -149,6 +149,8 @@ namespace Avalonia.DesignerSupport
s_currentWindow = window;
window.Show();
Design.ApplyDesignerProperties(window, control);
+ // ReSharper disable once PossibleNullReferenceException
+ // Always not null at this point
Api.OnWindowCreated?.Invoke(window.PlatformImpl.Handle.Handle);
Api.OnResize?.Invoke();
}
diff --git a/src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs b/src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs
index bdee85c91e..a484d6c0d2 100644
--- a/src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs
+++ b/src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs
@@ -15,7 +15,7 @@ namespace Avalonia.Win32.Embedding
{
private readonly EmbeddableControlRoot _root = new EmbeddableControlRoot();
- private IntPtr WindowHandle => ((WindowImpl) _root.PlatformImpl).Handle.Handle;
+ private IntPtr WindowHandle => ((WindowImpl) _root?.PlatformImpl)?.Handle?.Handle ?? IntPtr.Zero;
public WinFormsAvaloniaControlHost()
{
@@ -25,6 +25,8 @@ namespace Avalonia.Win32.Embedding
if (_root.IsFocused)
FocusManager.Instance.Focus(null);
_root.GotFocus += RootGotFocus;
+ // ReSharper disable once PossibleNullReferenceException
+ // Always non-null at this point
_root.PlatformImpl.LostFocus += PlatformImpl_LostFocus;
FixPosition();
}