Browse Source

Squash toplevel-totalsize

pull/6076/head
Nathan Garside 5 years ago
parent
commit
9feb2376a0
  1. 15
      native/Avalonia.Native/src/OSX/window.mm
  2. 2
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  3. 4
      src/Avalonia.Controls/ApiCompatBaseline.txt
  4. 10
      src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
  5. 5
      src/Avalonia.Controls/Platform/ITopLevelImpl.cs
  6. 19
      src/Avalonia.Controls/TopLevel.cs
  7. 1
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  8. 1
      src/Avalonia.Headless/HeadlessWindowImpl.cs
  9. 14
      src/Avalonia.Native/WindowImplBase.cs
  10. 1
      src/Avalonia.Native/avn.idl
  11. 10
      src/Avalonia.X11/X11Structs.cs
  12. 31
      src/Avalonia.X11/X11Window.cs
  13. 1
      src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
  14. 1
      src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs
  15. 23
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  16. 10
      src/Windows/Avalonia.Win32/WindowImpl.cs
  17. 1
      src/iOS/Avalonia.iOS/AvaloniaView.cs
  18. 1
      tests/Avalonia.UnitTests/MockWindowingPlatform.cs

15
native/Avalonia.Native/src/OSX/window.mm

@ -202,6 +202,21 @@ public:
}
}
virtual HRESULT GetTotalSize(AvnSize* ret) override
{
@autoreleasepool
{
if(ret == nullptr)
return E_POINTER;
auto frame = [Window frame];
ret->Width = frame.size.width;
ret->Height = frame.size.height;
return S_OK;
}
}
virtual HRESULT GetScaling (double* ret) override
{
@autoreleasepool

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

@ -55,6 +55,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public virtual Size ClientSize => Size.ToSize(RenderScaling);
public Size TotalSize => ClientSize;
public IMouseDevice MouseDevice { get; } = new MouseDevice();
public Action Closed { get; set; }

4
src/Avalonia.Controls/ApiCompatBaseline.txt

@ -11,4 +11,6 @@ EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.ICursorImpl)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' is present in the contract but not in the implementation.
MembersMustExist : Member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
Total Issues: 12
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Size Avalonia.Platform.ITopLevelImpl.TotalSize' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Size Avalonia.Platform.ITopLevelImpl.TotalSize.get()' is present in the implementation but not in the contract.
Total Issues: 14

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

@ -35,6 +35,16 @@ namespace Avalonia.Controls.Embedding.Offscreen
}
}
public Size TotalSize
{
get { return _clientSize; }
set
{
_clientSize = value;
Resized?.Invoke(value);
}
}
public double RenderScaling
{
get { return _scaling; }

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

@ -22,6 +22,11 @@ namespace Avalonia.Platform
/// </summary>
Size ClientSize { get; }
/// <summary>
/// Gets the total size of the toplevel, excluding shadows.
/// </summary>
Size TotalSize { get; }
/// <summary>
/// Gets the scaling factor for the toplevel. This is used for rendering.
/// </summary>

19
src/Avalonia.Controls/TopLevel.cs

@ -42,6 +42,12 @@ namespace Avalonia.Controls
public static readonly DirectProperty<TopLevel, Size> ClientSizeProperty =
AvaloniaProperty.RegisterDirect<TopLevel, Size>(nameof(ClientSize), o => o.ClientSize);
/// <summary>
/// Defines the <see cref="TotalSize"/> property.
/// </summary>
public static readonly DirectProperty<TopLevel, Size> TotalSizeProperty =
AvaloniaProperty.RegisterDirect<TopLevel, Size>(nameof(TotalSize), o => o.TotalSize);
/// <summary>
/// Defines the <see cref="IInputRoot.PointerOverElement"/> property.
/// </summary>
@ -74,6 +80,7 @@ namespace Avalonia.Controls
private readonly IPlatformRenderInterface _renderInterface;
private readonly IGlobalStyles _globalStyles;
private Size _clientSize;
private Size _totalSize;
private WindowTransparencyLevel _actualTransparencyLevel;
private ILayoutManager _layoutManager;
private Border _transparencyFallbackBorder;
@ -84,6 +91,7 @@ namespace Avalonia.Controls
static TopLevel()
{
AffectsMeasure<TopLevel>(ClientSizeProperty);
AffectsMeasure<TopLevel>(TotalSizeProperty);
TransparencyLevelHintProperty.Changed.AddClassHandler<TopLevel>(
(tl, e) =>
@ -194,9 +202,18 @@ namespace Avalonia.Controls
public Size ClientSize
{
get { return _clientSize; }
protected set { SetAndRaise(ClientSizeProperty, ref _clientSize, value); }
protected set
{
SetAndRaise(ClientSizeProperty, ref _clientSize, value);
SetAndRaise(TotalSizeProperty, ref _totalSize, PlatformImpl.TotalSize);
}
}
/// <summary>
/// Gets or sets the total size of the window.
/// </summary>
public Size TotalSize => _totalSize;
/// <summary>
/// Gets or sets the <see cref="WindowTransparencyLevel"/> that the TopLevel should use when possible.
/// </summary>

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

@ -21,6 +21,7 @@ namespace Avalonia.DesignerSupport.Remote
public IPlatformHandle Handle { get; }
public Size MaxAutoSizeHint { get; }
public Size ClientSize { get; }
public Size TotalSize => ClientSize;
public double RenderScaling { get; } = 1.0;
public double DesktopScaling => 1.0;
public IEnumerable<object> Surfaces { get; }

1
src/Avalonia.Headless/HeadlessWindowImpl.cs

@ -41,6 +41,7 @@ namespace Avalonia.Headless
}
public Size ClientSize { get; set; }
public Size TotalSize => ClientSize;
public double RenderScaling { get; } = 1;
public double DesktopScaling => RenderScaling;
public IEnumerable<object> Surfaces { get; }

14
src/Avalonia.Native/WindowImplBase.cs

@ -104,6 +104,20 @@ namespace Avalonia.Native
}
}
public Size TotalSize
{
get
{
if (_native != null)
{
var s = _native.TotalSize;
return new Size(s.Width, s.Height);
}
return default;
}
}
public IEnumerable<object> Surfaces => new[] {
(_gpu ? _glSurface : (object)null),
this

1
src/Avalonia.Native/avn.idl

@ -435,6 +435,7 @@ interface IAvnWindowBase : IUnknown
HRESULT Close();
HRESULT Activate();
HRESULT GetClientSize(AvnSize*ret);
HRESULT GetTotalSize(AvnSize*ret);
HRESULT GetScaling(double*ret);
HRESULT SetMinMaxSize(AvnSize minSize, AvnSize maxSize);
HRESULT Resize(double width, double height);

10
src/Avalonia.X11/X11Structs.cs

@ -1740,6 +1740,16 @@ namespace Avalonia.X11 {
public short W;
public short H;
}
[StructLayout (LayoutKind.Sequential)]
[Serializable]
internal struct XFrameExtents
{
public int Left;
public int Right;
public int Top;
public int Bottom;
}
[StructLayout (LayoutKind.Sequential)]

31
src/Avalonia.X11/X11Window.cs

@ -297,6 +297,30 @@ namespace Avalonia.X11
public Size ClientSize => new Size(_realSize.Width / RenderScaling, _realSize.Height / RenderScaling);
public Size TotalSize
{
get
{
XGetWindowProperty(_x11.Display, _handle, _x11.Atoms._NET_FRAME_EXTENTS, IntPtr.Zero,
new IntPtr(4), false, (IntPtr)Atom.AnyPropertyType, out var _,
out var _, out var nitems, out var _, out var prop);
if (nitems.ToInt64() != 4)
{
// Window hasn't been mapped by the WM yet, so can't get the extents.
return ClientSize;
}
var data = (IntPtr*)prop.ToPointer();
var extents = new Thickness(data[0].ToInt32(), data[2].ToInt32(), data[1].ToInt32(), data[3].ToInt32());
XFree(prop);
return new Size(
(_realSize.Width + extents.Left + extents.Right) / RenderScaling,
(_realSize.Height + extents.Top + extents.Bottom) / RenderScaling);
}
}
public double RenderScaling
{
get
@ -589,6 +613,13 @@ namespace Avalonia.X11
private void OnPropertyChange(IntPtr atom, bool hasValue)
{
if (atom == _x11.Atoms._NET_FRAME_EXTENTS)
{
// Occurs once the window has been mapped, which is the earliest the extents
// can be retrieved, so invoke event to force update of TopLevel.TotalSize.
Resized.Invoke(ClientSize);
}
if (atom == _x11.Atoms._NET_WM_STATE)
{
WindowState state = WindowState.Normal;

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

@ -62,6 +62,7 @@ namespace Avalonia.LinuxFramebuffer
}
public Size ClientSize => ScaledSize;
public Size TotalSize => ClientSize;
public IMouseDevice MouseDevice => new MouseDevice();
public IPopupImpl CreatePopup() => null;

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

@ -100,6 +100,7 @@ namespace Avalonia.Win32.Interop.Wpf
}
Size ITopLevelImpl.ClientSize => _finalSize;
Size ITopLevelImpl.TotalSize => _finalSize;
IMouseDevice ITopLevelImpl.MouseDevice => _mouse;
double ITopLevelImpl.RenderScaling => PresentationSource.FromVisual(this)?.CompositionTarget?.TransformToDevice.M11 ?? 1;

23
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@ -745,6 +745,26 @@ namespace Avalonia.Win32.Interop
WM_DISPATCH_WORK_ITEM = WM_USER,
}
public enum DwmWindowAttribute : uint
{
DWMWA_NCRENDERING_ENABLED = 1,
DWMWA_NCRENDERING_POLICY,
DWMWA_TRANSITIONS_FORCEDISABLED,
DWMWA_ALLOW_NCPAINT,
DWMWA_CAPTION_BUTTON_BOUNDS,
DWMWA_NONCLIENT_RTL_LAYOUT,
DWMWA_FORCE_ICONIC_REPRESENTATION,
DWMWA_FLIP3D_POLICY,
DWMWA_EXTENDED_FRAME_BOUNDS,
DWMWA_HAS_ICONIC_BITMAP,
DWMWA_DISALLOW_PEEK,
DWMWA_EXCLUDED_FROM_PEEK,
DWMWA_CLOAK,
DWMWA_CLOAKED,
DWMWA_FREEZE_REPRESENTATION,
DWMWA_LAST
};
public enum MapVirtualKeyMapTypes : uint
{
MAPVK_VK_TO_VSC = 0x00,
@ -1388,6 +1408,9 @@ namespace Avalonia.Win32.Interop
[DllImport("dwmapi.dll")]
public static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);
[DllImport("dwmapi.dll")]
public static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out RECT pvAttribute, int cbAttribute);
[DllImport("dwmapi.dll")]
public static extern int DwmIsCompositionEnabled(out bool enabled);

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

@ -213,6 +213,16 @@ namespace Avalonia.Win32
}
}
public Size TotalSize
{
get
{
DwmGetWindowAttribute(_hwnd, (int)DwmWindowAttribute.DWMWA_EXTENDED_FRAME_BOUNDS, out var rect, Marshal.SizeOf(typeof(RECT)));
return new Size(rect.Width, rect.Height) / RenderScaling;
}
}
public IScreenImpl Screen { get; }
public IPlatformHandle Handle { get; private set; }

1
src/iOS/Avalonia.iOS/AvaloniaView.cs

@ -91,6 +91,7 @@ namespace Avalonia.iOS
}
public Size ClientSize => new Size(_view.Bounds.Width, _view.Bounds.Height);
public Size TotalSize => ClientSize;
public double RenderScaling => _view.ContentScaleFactor;
public IEnumerable<object> Surfaces { get; set; }
public Action<RawInputEventArgs> Input { get; set; }

1
tests/Avalonia.UnitTests/MockWindowingPlatform.cs

@ -29,6 +29,7 @@ namespace Avalonia.UnitTests
windowImpl.SetupAllProperties();
windowImpl.Setup(x => x.ClientSize).Returns(() => clientSize);
windowImpl.Setup(x => x.TotalSize).Returns(() => clientSize);
windowImpl.Setup(x => x.MaxAutoSizeHint).Returns(s_screenSize);
windowImpl.Setup(x => x.DesktopScaling).Returns(1);
windowImpl.Setup(x => x.RenderScaling).Returns(1);

Loading…
Cancel
Save