Browse Source

Merge pull request #6076 from ngarside/totalsize

Add API to get the total size of a window.
# Conflicts:
#	src/Avalonia.Controls/ApiCompatBaseline.txt
#	src/Avalonia.X11/X11Window.cs
release/0.10.7
Max Katz 5 years ago
committed by Dan Walmsley
parent
commit
ec8c9c6c50
  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. 2
      src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
  5. 5
      src/Avalonia.Controls/Platform/ITopLevelImpl.cs
  6. 18
      src/Avalonia.Controls/TopLevel.cs
  7. 1
      src/Avalonia.Controls/WindowBase.cs
  8. 1
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  9. 1
      src/Avalonia.Headless/HeadlessWindowImpl.cs
  10. 14
      src/Avalonia.Native/WindowImplBase.cs
  11. 1
      src/Avalonia.Native/avn.idl
  12. 24
      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. 15
      src/Windows/Avalonia.Win32/WindowImpl.cs
  17. 1
      src/iOS/Avalonia.iOS/AvaloniaView.cs

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

@ -229,6 +229,21 @@ public:
}
}
virtual HRESULT GetFrameSize(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
{
START_COM_CALL;

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? FrameSize => null;
public IMouseDevice MouseDevice { get; } = new MouseDevice();
public Action Closed { get; set; }

4
src/Avalonia.Controls/ApiCompatBaseline.txt

@ -9,6 +9,8 @@ MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.Off
MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Notifications.NotificationCard.CloseOnClickProperty' does not exist in the implementation but it does exist in the contract.
EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints Avalonia.Platform.ExtendClientAreaChromeHints.Default' is (System.Int32)2 in the implementation but (System.Int32)1 in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Nullable<Avalonia.Size> Avalonia.Platform.ITopLevelImpl.FrameSize' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Nullable<Avalonia.Size> Avalonia.Platform.ITopLevelImpl.FrameSize.get()' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Action<Avalonia.Size, Avalonia.Platform.PlatformResizeReason> Avalonia.Platform.ITopLevelImpl.Resized.get()' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Action<Avalonia.Size> Avalonia.Platform.ITopLevelImpl.Resized.get()' is present in the contract but not in the implementation.
MembersMustExist : Member 'public System.Action<Avalonia.Size> Avalonia.Platform.ITopLevelImpl.Resized.get()' does not exist in the implementation but it does exist in the contract.
@ -24,4 +26,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platfor
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size)' is present in the contract but not in the implementation.
MembersMustExist : Member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size)' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size, Avalonia.Platform.PlatformResizeReason)' is present in the implementation but not in the contract.
Total Issues: 25
Total Issues: 27

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

@ -35,6 +35,8 @@ namespace Avalonia.Controls.Embedding.Offscreen
}
}
public Size? FrameSize => null;
public double RenderScaling
{
get { return _scaling; }

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

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

18
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="FrameSize"/> property.
/// </summary>
public static readonly DirectProperty<TopLevel, Size?> FrameSizeProperty =
AvaloniaProperty.RegisterDirect<TopLevel, Size?>(nameof(FrameSize), o => o.FrameSize);
/// <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? _frameSize;
private WindowTransparencyLevel _actualTransparencyLevel;
private ILayoutManager _layoutManager;
private Border _transparencyFallbackBorder;
@ -162,6 +169,7 @@ namespace Avalonia.Controls
styler?.ApplyStyles(this);
ClientSize = impl.ClientSize;
FrameSize = impl.FrameSize;
this.GetObservable(PointerOverElementProperty)
.Select(
@ -198,6 +206,15 @@ namespace Avalonia.Controls
protected set { SetAndRaise(ClientSizeProperty, ref _clientSize, value); }
}
/// <summary>
/// Gets or sets the total size of the window.
/// </summary>
public Size? FrameSize
{
get { return _frameSize; }
protected set { SetAndRaise(FrameSizeProperty, ref _frameSize, value); }
}
/// <summary>
/// Gets or sets the <see cref="WindowTransparencyLevel"/> that the TopLevel should use when possible.
/// </summary>
@ -371,6 +388,7 @@ namespace Avalonia.Controls
protected virtual void HandleResized(Size clientSize, PlatformResizeReason reason)
{
ClientSize = clientSize;
FrameSize = PlatformImpl.FrameSize;
Width = clientSize.Width;
Height = clientSize.Height;
LayoutManager.ExecuteLayoutPass();

1
src/Avalonia.Controls/WindowBase.cs

@ -212,6 +212,7 @@ namespace Avalonia.Controls
protected override void HandleResized(Size clientSize, PlatformResizeReason reason)
{
ClientSize = clientSize;
FrameSize = PlatformImpl.FrameSize;
LayoutManager.ExecuteLayoutPass();
Renderer?.Resized(clientSize);
}

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? FrameSize => null;
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? FrameSize => null;
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? FrameSize
{
get
{
if (_native != null)
{
var s = _native.FrameSize;
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

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

24
src/Avalonia.X11/X11Window.cs

@ -296,6 +296,30 @@ namespace Avalonia.X11
public Size ClientSize => new Size(_realSize.Width / RenderScaling, _realSize.Height / RenderScaling);
public Size? FrameSize
{
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 null;
}
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

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

@ -61,6 +61,7 @@ namespace Avalonia.LinuxFramebuffer
}
public Size ClientSize => ScaledSize;
public Size? FrameSize => null;
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.FrameSize => null;
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);

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

@ -214,6 +214,21 @@ namespace Avalonia.Win32
}
}
public Size? FrameSize
{
get
{
if (DwmIsCompositionEnabled(out var compositionEnabled) != 0 || !compositionEnabled)
{
GetWindowRect(_hwnd, out var rcWindow);
return new Size(rcWindow.Width, rcWindow.Height) / RenderScaling;
}
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? FrameSize => null;
public double RenderScaling => _view.ContentScaleFactor;
public IEnumerable<object> Surfaces { get; set; }
public Action<RawInputEventArgs> Input { get; set; }

Loading…
Cancel
Save