Browse Source

Use PixelPoint and PixelRect for device points/rects.

The affected members are:

- `IWindowBaseImpl.Position`
- `IWindowBaseImpl.PositionChanged`
- `ITopLevelImpl.PointToClient`
- `ITopLevelImpl.PointToScreen`
- `IMouseDevice.Position`
- `Screen.Bounds`
- `Screen.WorkingArea`
pull/2250/head
Steven Kirk 7 years ago
parent
commit
4ec2b1c554
  1. 4
      samples/ControlCatalog/Pages/ScreenPage.cs
  2. 6
      src/Android/Avalonia.Android/Platform/SkiaPlatform/PopupImpl.cs
  3. 8
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  4. 4
      src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
  5. 27
      src/Avalonia.Controls/PixelPointEventArgs.cs
  6. 4
      src/Avalonia.Controls/Platform/ITopLevelImpl.cs
  7. 6
      src/Avalonia.Controls/Platform/IWindowBaseImpl.cs
  8. 8
      src/Avalonia.Controls/Platform/Screen.cs
  9. 27
      src/Avalonia.Controls/PointEventArgs.cs
  10. 30
      src/Avalonia.Controls/Primitives/Popup.cs
  11. 10
      src/Avalonia.Controls/Primitives/PopupRoot.cs
  12. 14
      src/Avalonia.Controls/Screens.cs
  13. 1
      src/Avalonia.Controls/ToolTip.cs
  14. 8
      src/Avalonia.Controls/TopLevel.cs
  15. 20
      src/Avalonia.Controls/Window.cs
  16. 10
      src/Avalonia.Controls/WindowBase.cs
  17. 4
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  18. 10
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  19. 2
      src/Avalonia.Input/IMouseDevice.cs
  20. 2
      src/Avalonia.Input/MouseDevice.cs
  21. 15
      src/Avalonia.Native/Helpers.cs
  22. 5
      src/Avalonia.Native/ScreenImpl.cs
  23. 14
      src/Avalonia.Native/WindowImplBase.cs
  24. 8
      src/Avalonia.Visuals/Rendering/IRenderRoot.cs
  25. 12
      src/Avalonia.Visuals/VisualExtensions.cs
  26. 16
      src/Avalonia.X11/X11Screens.cs
  27. 20
      src/Avalonia.X11/X11Window.cs
  28. 4
      src/Gtk/Avalonia.Gtk3/GtkScreen.cs
  29. 4
      src/Gtk/Avalonia.Gtk3/ScreenImpl.cs
  30. 14
      src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs
  31. 4
      src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
  32. 2
      src/Windows/Avalonia.Win32.Interop/Wpf/WpfInteropExtensions.cs
  33. 4
      src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs
  34. 2
      src/Windows/Avalonia.Win32/OleDropTarget.cs
  35. 6
      src/Windows/Avalonia.Win32/ScreenImpl.cs
  36. 4
      src/Windows/Avalonia.Win32/WinScreen.cs
  37. 22
      src/Windows/Avalonia.Win32/WindowImpl.cs
  38. 4
      src/iOS/Avalonia.iOS/TopLevelImpl.cs
  39. 4
      tests/Avalonia.Controls.UnitTests/ButtonTests.cs
  40. 2
      tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
  41. 22
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs
  42. 28
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs
  43. 22
      tests/Avalonia.Controls.UnitTests/WindowTests.cs
  44. 4
      tests/Avalonia.UnitTests/TestRoot.cs
  45. 4
      tests/Avalonia.UnitTests/TestTemplatedRoot.cs

4
samples/ControlCatalog/Pages/ScreenPage.cs

@ -4,6 +4,7 @@ using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Rendering;
namespace ControlCatalog.Pages
{
@ -23,6 +24,7 @@ namespace ControlCatalog.Pages
base.Render(context);
Window w = (Window)VisualRoot;
Screen[] screens = w.Screens.All;
var scaling = ((IRenderRoot)w).RenderScaling;
Pen p = new Pen(Brushes.Black);
if (screens != null)
@ -56,7 +58,7 @@ namespace ControlCatalog.Pages
text.Text = $"Primary: {screen.Primary}";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);
text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new Rect(w.Position, w.Bounds.Size)))}";
text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
}

6
src/Android/Avalonia.Android/Platform/SkiaPlatform/PopupImpl.cs

@ -10,10 +10,10 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{
class PopupImpl : TopLevelImpl, IPopupImpl
{
private Point _position;
private PixelPoint _position;
private bool _isAdded;
Action IWindowBaseImpl.Activated { get; set; }
public Action<Point> PositionChanged { get; set; }
public Action<PixelPoint> PositionChanged { get; set; }
public Action Deactivated { get; set; }
public PopupImpl() : base(ActivityTracker.Current, true)
@ -36,7 +36,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public IScreenImpl Screen { get; }
public Point Position
public PixelPoint Position
{
get { return _position; }
set

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

@ -99,14 +99,14 @@ namespace Avalonia.Android.Platform.SkiaPlatform
if (_view.Holder?.Surface?.IsValid == true) _view.Invalidate();
}
public Point PointToClient(Point point)
public Point PointToClient(PixelPoint point)
{
return point;
return point.ToPoint(1);
}
public Point PointToScreen(Point point)
public PixelPoint PointToScreen(Point point)
{
return point;
return PixelPoint.FromPoint(point, 1);
}
public void SetCursor(IPlatformHandle cursor)

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

@ -49,9 +49,9 @@ namespace Avalonia.Controls.Embedding.Offscreen
public Action<double> ScalingChanged { get; set; }
public void SetInputRoot(IInputRoot inputRoot) => InputRoot = inputRoot;
public virtual Point PointToClient(Point point) => point;
public virtual Point PointToClient(PixelPoint point) => point.ToPoint(1);
public virtual Point PointToScreen(Point point) => point;
public virtual PixelPoint PointToScreen(Point point) => PixelPoint.FromPoint(point, 1);
public virtual void SetCursor(IPlatformHandle cursor)
{

27
src/Avalonia.Controls/PixelPointEventArgs.cs

@ -0,0 +1,27 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Controls
{
/// <summary>
/// Provides <see cref="PixelPoint"/> data for events.
/// </summary>
public class PixelPointEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="PixelPointEventArgs"/> class.
/// </summary>
/// <param name="point">The <see cref=PixelPoint"/> data.</param>
public PixelPointEventArgs(PixelPoint point)
{
Point = point;
}
/// <summary>
/// Gets the <see cref="PixelPoint"/> data.
/// </summary>
public PixelPoint Point { get; }
}
}

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

@ -82,14 +82,14 @@ namespace Avalonia.Platform
/// </summary>
/// <param name="point">The point in screen coordinates.</param>
/// <returns>The point in client coordinates.</returns>
Point PointToClient(Point point);
Point PointToClient(PixelPoint point);
/// <summary>
/// Converts a point from client to screen coordinates.
/// </summary>
/// <param name="point">The point in client coordinates.</param>
/// <returns>The point in screen coordinates.</returns>
Point PointToScreen(Point point);
PixelPoint PointToScreen(Point point);
/// <summary>
/// Sets the cursor associated with the toplevel.

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

@ -27,14 +27,14 @@ namespace Avalonia.Platform
void BeginResizeDrag(WindowEdge edge);
/// <summary>
/// Gets position of the window relatively to the screen
/// Gets the position of the window relative in device pixels.
/// </summary>
Point Position { get; set; }
PixelPoint Position { get; set; }
/// <summary>
/// Gets or sets a method called when the window's position changes.
/// </summary>
Action<Point> PositionChanged { get; set; }
Action<PixelPoint> PositionChanged { get; set; }
/// <summary>
/// Activates the window.

8
src/Avalonia.Controls/Platform/Screen.cs

@ -2,17 +2,17 @@
{
public class Screen
{
public Rect Bounds { get; }
public PixelRect Bounds { get; }
public Rect WorkingArea { get; }
public PixelRect WorkingArea { get; }
public bool Primary { get; }
public Screen(Rect bounds, Rect workingArea, bool primary)
public Screen(PixelRect bounds, PixelRect workingArea, bool primary)
{
this.Bounds = bounds;
this.WorkingArea = workingArea;
this.Primary = primary;
}
}
}
}

27
src/Avalonia.Controls/PointEventArgs.cs

@ -1,27 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Controls
{
/// <summary>
/// Provides <see cref="Point"/> data for events.
/// </summary>
public class PointEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="PointEventArgs"/> class.
/// </summary>
/// <param name="point">The <see cref="Point"/> data.</param>
public PointEventArgs(Point point)
{
Point = point;
}
/// <summary>
/// Gets the <see cref="Point"/> data.
/// </summary>
public Point Point { get; }
}
}

30
src/Avalonia.Controls/Primitives/Popup.cs

@ -380,7 +380,7 @@ namespace Avalonia.Controls.Primitives
/// Gets the position for the popup based on the placement properties.
/// </summary>
/// <returns>The popup's position in screen coordinates.</returns>
protected virtual Point GetPosition()
protected virtual PixelPoint GetPosition()
{
var result = GetPosition(PlacementTarget ?? this.GetVisualParent<Control>(), PlacementMode, PopupRoot,
HorizontalOffset, VerticalOffset);
@ -388,35 +388,31 @@ namespace Avalonia.Controls.Primitives
return result;
}
internal static Point GetPosition(Control target, PlacementMode placement, PopupRoot popupRoot, double horizontalOffset, double verticalOffset)
internal static PixelPoint GetPosition(Control target, PlacementMode placement, PopupRoot popupRoot, double horizontalOffset, double verticalOffset)
{
var zero = default(Point);
var mode = placement;
if (target?.GetVisualRoot() == null)
{
mode = PlacementMode.Pointer;
}
var root = target?.GetVisualRoot();
var mode = root != null ? placement : PlacementMode.Pointer;
var scaling = root?.RenderScaling ?? 1;
switch (mode)
{
case PlacementMode.Pointer:
if (popupRoot != null)
{
// Scales the Horizontal and Vertical offset to screen co-ordinates.
var screenOffset = new Point(horizontalOffset * (popupRoot as ILayoutRoot).LayoutScaling,
verticalOffset * (popupRoot as ILayoutRoot).LayoutScaling);
return (((IInputRoot)popupRoot)?.MouseDevice?.Position ?? default(Point)) + screenOffset;
var screenOffset = PixelPoint.FromPoint(new Point(horizontalOffset, verticalOffset), scaling);
var mouseOffset = ((IInputRoot)popupRoot)?.MouseDevice?.Position ?? default;
return new PixelPoint(
screenOffset.X + mouseOffset.X,
screenOffset.Y + mouseOffset.Y);
}
return default(Point);
return default;
case PlacementMode.Bottom:
return target?.PointToScreen(new Point(0 + horizontalOffset, target.Bounds.Height + verticalOffset)) ??
zero;
return target?.PointToScreen(new Point(0 + horizontalOffset, target.Bounds.Height + verticalOffset)) ?? default;
case PlacementMode.Right:
return target?.PointToScreen(new Point(target.Bounds.Width + horizontalOffset, 0 + verticalOffset)) ?? zero;
return target?.PointToScreen(new Point(target.Bounds.Width + horizontalOffset, 0 + verticalOffset)) ?? default;
default:
throw new InvalidOperationException("Invalid value for Popup.PlacementMode");

10
src/Avalonia.Controls/Primitives/PopupRoot.cs

@ -85,18 +85,18 @@ namespace Avalonia.Controls.Primitives
if (screen != null)
{
var scaling = VisualRoot.RenderScaling;
var screenX = Position.X + (Bounds.Width * scaling) - screen.Bounds.X;
var screenY = Position.Y + (Bounds.Height * scaling) - screen.Bounds.Y;
var bounds = PixelRect.FromRect(Bounds, scaling);
var screenX = Position.X + bounds.Width - screen.Bounds.X;
var screenY = Position.Y + bounds.Height - screen.Bounds.Y;
if (screenX > screen.Bounds.Width)
{
Position = Position.WithX(Position.X - (screenX - screen.Bounds.Width));
Position = Position.WithX(Position.X - screenX - bounds.Width);
}
if (screenY > screen.Bounds.Height)
{
Position = Position.WithY(Position.Y - (screenY - screen.Bounds.Height));
Position = Position.WithY(Position.Y - screenY - bounds.Height);
}
}
}

14
src/Avalonia.Controls/Screens.cs

@ -18,7 +18,7 @@ namespace Avalonia.Controls
_iScreenImpl = iScreenImpl;
}
public Screen ScreenFromBounds(Rect bounds){
public Screen ScreenFromBounds(PixelRect bounds){
Screen currMaxScreen = null;
double maxAreaSize = 0;
@ -39,16 +39,16 @@ namespace Avalonia.Controls
return currMaxScreen;
}
public Screen ScreenFromPoint(Point point)
public Screen ScreenFromPoint(PixelPoint point)
{
return All.FirstOrDefault(x=>x.Bounds.Contains(point));
return All.FirstOrDefault(x => x.Bounds.Contains(point));
}
public Screen ScreenFromVisual(IVisual visual)
{
Point tl = visual.PointToScreen(visual.Bounds.TopLeft);
Point br = visual.PointToScreen(visual.Bounds.BottomRight);
return ScreenFromBounds(new Rect(tl,br));
var tl = visual.PointToScreen(visual.Bounds.TopLeft);
var br = visual.PointToScreen(visual.Bounds.BottomRight);
return ScreenFromBounds(new PixelRect(tl, br));
}
}
}
}

1
src/Avalonia.Controls/ToolTip.cs

@ -236,6 +236,7 @@ namespace Avalonia.Controls
_popup = new PopupRoot { Content = this, };
((ISetLogicalParent)_popup).SetParent(control);
_popup.Position = Popup.GetPosition(control, GetPlacement(control), _popup,
GetHorizontalOffset(control), GetVerticalOffset(control));
_popup.Show();

8
src/Avalonia.Controls/TopLevel.cs

@ -233,15 +233,15 @@ namespace Avalonia.Controls
}
/// <inheritdoc/>
Point IRenderRoot.PointToClient(Point p)
Point IRenderRoot.PointToClient(PixelPoint p)
{
return PlatformImpl?.PointToClient(p) ?? default(Point);
return PlatformImpl?.PointToClient(p) ?? default;
}
/// <inheritdoc/>
Point IRenderRoot.PointToScreen(Point p)
PixelPoint IRenderRoot.PointToScreen(Point p)
{
return PlatformImpl?.PointToScreen(p) ?? default(Point);
return PlatformImpl?.PointToScreen(p) ?? default;
}
/// <summary>

20
src/Avalonia.Controls/Window.cs

@ -462,19 +462,31 @@ namespace Avalonia.Controls
void SetWindowStartupLocation()
{
var scaling = PlatformImpl?.Scaling ?? 1;
// TODO: We really need non-client size here.
var rect = new PixelRect(
PixelPoint.Origin,
PixelSize.FromSize(ClientSize, scaling));
if (WindowStartupLocation == WindowStartupLocation.CenterScreen)
{
var screen = Screens.ScreenFromPoint(Bounds.Position);
var screen = Screens.ScreenFromPoint(Position);
if (screen != null)
Position = screen.WorkingArea.CenterRect(new Rect(ClientSize)).Position;
{
Position = screen.WorkingArea.CenterRect(rect).Position;
}
}
else if (WindowStartupLocation == WindowStartupLocation.CenterOwner)
{
if (Owner != null)
{
var positionAsSize = Owner.ClientSize / 2 - ClientSize / 2;
Position = Owner.Position + new Point(positionAsSize.Width, positionAsSize.Height);
// TODO: We really need non-client size here.
var ownerRect = new PixelRect(
Owner.Position,
PixelSize.FromSize(Owner.ClientSize, scaling));
Position = ownerRect.CenterRect(rect).Position;
}
}
}

10
src/Avalonia.Controls/WindowBase.cs

@ -81,7 +81,7 @@ namespace Avalonia.Controls
/// <summary>
/// Fired when the window position is changed.
/// </summary>
public event EventHandler<PointEventArgs> PositionChanged;
public event EventHandler<PixelPointEventArgs> PositionChanged;
[CanBeNull]
public new IWindowBaseImpl PlatformImpl => (IWindowBaseImpl) base.PlatformImpl;
@ -98,9 +98,9 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the window position in screen coordinates.
/// </summary>
public Point Position
public PixelPoint Position
{
get { return PlatformImpl?.Position ?? default(Point); }
get { return PlatformImpl?.Position ?? PixelPoint.Origin; }
set
{
if (PlatformImpl is IWindowBaseImpl impl)
@ -267,9 +267,9 @@ namespace Avalonia.Controls
/// <see cref="IWindowBaseImpl.PositionChanged"/>.
/// </summary>
/// <param name="pos">The window position.</param>
private void HandlePositionChanged(Point pos)
private void HandlePositionChanged(PixelPoint pos)
{
PositionChanged?.Invoke(this, new PointEventArgs(pos));
PositionChanged?.Invoke(this, new PixelPointEventArgs(pos));
}
/// <summary>

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

@ -35,8 +35,8 @@ namespace Avalonia.DesignerSupport.Remote
{
}
public Point Position { get; set; }
public Action<Point> PositionChanged { get; set; }
public PixelPoint Position { get; set; }
public Action<PixelPoint> PositionChanged { get; set; }
public Action Deactivated { get; set; }
public Action Activated { get; set; }
public Func<bool> Closing { get; set; }

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

@ -29,8 +29,8 @@ namespace Avalonia.DesignerSupport.Remote
public Func<bool> Closing { get; set; }
public Action Closed { get; set; }
public IMouseDevice MouseDevice { get; } = new MouseDevice();
public Point Position { get; set; }
public Action<Point> PositionChanged { get; set; }
public PixelPoint Position { get; set; }
public Action<PixelPoint> PositionChanged { get; set; }
public WindowState WindowState { get; set; }
public Action<WindowState> WindowStateChanged { get; set; }
public IRenderer CreateRenderer(IRenderRoot root) => new ImmediateRenderer(root);
@ -45,9 +45,9 @@ namespace Avalonia.DesignerSupport.Remote
{
}
public Point PointToClient(Point point) => point;
public Point PointToClient(PixelPoint p) => p.ToPoint(1);
public Point PointToScreen(Point point) => point;
public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1);
public void SetCursor(IPlatformHandle cursor)
{
@ -157,6 +157,6 @@ namespace Avalonia.DesignerSupport.Remote
public int ScreenCount => 1;
public Screen[] AllScreens { get; } =
{new Screen(new Rect(0, 0, 4000, 4000), new Rect(0, 0, 4000, 4000), true)};
{new Screen(new PixelRect(0, 0, 4000, 4000), new PixelRect(0, 0, 4000, 4000), true)};
}
}

2
src/Avalonia.Input/IMouseDevice.cs

@ -11,6 +11,6 @@ namespace Avalonia.Input
/// <summary>
/// Gets the mouse position, in screen coordinates.
/// </summary>
Point Position { get; }
PixelPoint Position { get; }
}
}

2
src/Avalonia.Input/MouseDevice.cs

@ -54,7 +54,7 @@ namespace Avalonia.Input
/// <summary>
/// Gets the mouse position, in screen coordinates.
/// </summary>
public Point Position
public PixelPoint Position
{
get;
protected set;

15
src/Avalonia.Native/Helpers.cs

@ -12,11 +12,21 @@ namespace Avalonia.Native
return new Point(pt.X, pt.Y);
}
public static PixelPoint ToAvaloniaPixelPoint(this AvnPoint pt)
{
return new PixelPoint((int)pt.X, (int)pt.Y);
}
public static AvnPoint ToAvnPoint (this Point pt)
{
return new AvnPoint { X = pt.X, Y = pt.Y };
}
public static AvnPoint ToAvnPoint(this PixelPoint pt)
{
return new AvnPoint { X = pt.X, Y = pt.Y };
}
public static AvnSize ToAvnSize (this Size size)
{
return new AvnSize { Height = size.Height, Width = size.Width };
@ -31,5 +41,10 @@ namespace Avalonia.Native
{
return new Rect(rect.X, rect.Y, rect.Width, rect.Height);
}
public static PixelRect ToAvaloniaPixelRect(this AvnRect rect)
{
return new PixelRect((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
}
}
}

5
src/Avalonia.Native/ScreenImpl.cs

@ -29,7 +29,10 @@ namespace Avalonia.Native
{
var screen = _native.GetScreen(i);
result[i] = new Screen(screen.Bounds.ToAvaloniaRect(), screen.WorkingArea.ToAvaloniaRect(), screen.Primary);
result[i] = new Screen(
screen.Bounds.ToAvaloniaPixelRect(),
screen.WorkingArea.ToAvaloniaPixelRect(),
screen.Primary);
}
return result;

14
src/Avalonia.Native/WindowImplBase.cs

@ -159,7 +159,7 @@ namespace Avalonia.Native
void IAvnWindowBaseEvents.PositionChanged(AvnPoint position)
{
_parent.PositionChanged?.Invoke(position.ToAvaloniaPoint());
_parent.PositionChanged?.Invoke(position.ToAvaloniaPixelPoint());
}
void IAvnWindowBaseEvents.RawMouseEvent(AvnRawMouseEventType type, uint timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta)
@ -275,20 +275,20 @@ namespace Avalonia.Native
}
public Point Position
public PixelPoint Position
{
get => _native.GetPosition().ToAvaloniaPoint();
get => _native.GetPosition().ToAvaloniaPixelPoint();
set => _native.SetPosition(value.ToAvnPoint());
}
public Point PointToClient(Point point)
public Point PointToClient(PixelPoint point)
{
return _native.PointToClient(point.ToAvnPoint()).ToAvaloniaPoint();
}
public Point PointToScreen(Point point)
public PixelPoint PointToScreen(Point point)
{
return _native.PointToScreen(point.ToAvnPoint()).ToAvaloniaPoint();
return _native.PointToScreen(point.ToAvnPoint()).ToAvaloniaPixelPoint();
}
public void Hide()
@ -320,7 +320,7 @@ namespace Avalonia.Native
_native.Cursor = newCursor.Cursor;
}
public Action<Point> PositionChanged { get; set; }
public Action<PixelPoint> PositionChanged { get; set; }
public Action<RawInputEventArgs> Input { get; set; }

8
src/Avalonia.Visuals/Rendering/IRenderRoot.cs

@ -41,15 +41,15 @@ namespace Avalonia.Rendering
/// <summary>
/// Converts a point from screen to client coordinates.
/// </summary>
/// <param name="point">The point in screen coordinates.</param>
/// <param name="point">The point in screen device coordinates.</param>
/// <returns>The point in client coordinates.</returns>
Point PointToClient(Point point);
Point PointToClient(PixelPoint point);
/// <summary>
/// Converts a point from client to screen coordinates.
/// </summary>
/// <param name="point">The point in client coordinates.</param>
/// <returns>The point in screen coordinates.</returns>
Point PointToScreen(Point point);
/// <returns>The point in screen device coordinates.</returns>
PixelPoint PointToScreen(Point point);
}
}

12
src/Avalonia.Visuals/VisualExtensions.cs

@ -18,10 +18,14 @@ namespace Avalonia
/// <param name="visual">The visual.</param>
/// <param name="point">The point in screen coordinates.</param>
/// <returns>The point in client coordinates.</returns>
public static Point PointToClient(this IVisual visual, Point point)
public static Point PointToClient(this IVisual visual, PixelPoint point)
{
var p = GetRootAndPosition(visual);
return p.Item1.PointToClient(point - p.Item2);
var (root, offset) = GetRootAndPosition(visual);
var screenOffset = PixelPoint.FromPoint((Point)offset, root.RenderScaling);
var screenPoint = PixelPoint.FromPoint(
new Point(point.X - screenOffset.X, point.Y - screenOffset.Y),
root.RenderScaling);
return root.PointToClient(screenPoint);
}
/// <summary>
@ -30,7 +34,7 @@ namespace Avalonia
/// <param name="visual">The visual.</param>
/// <param name="point">The point in client coordinates.</param>
/// <returns>The point in screen coordinates.</returns>
public static Point PointToScreen(this IVisual visual, Point point)
public static PixelPoint PointToScreen(this IVisual visual, Point point)
{
var p = GetRootAndPosition(visual);
return p.Item1.PointToScreen(point + p.Item2);

16
src/Avalonia.X11/X11Screens.cs

@ -20,7 +20,7 @@ namespace Avalonia.X11
static unsafe X11Screen[] UpdateWorkArea(X11Info info, X11Screen[] screens)
{
var rect = default(Rect);
var rect = default(PixelRect);
foreach (var s in screens)
{
rect = rect.Union(s.Bounds);
@ -46,7 +46,7 @@ namespace Avalonia.X11
return screens;
var pwa = (IntPtr*)prop;
var wa = new Rect(pwa[0].ToInt32(), pwa[1].ToInt32(), pwa[2].ToInt32(), pwa[3].ToInt32());
var wa = new PixelRect(pwa[0].ToInt32(), pwa[1].ToInt32(), pwa[2].ToInt32(), pwa[3].ToInt32());
foreach (var s in screens)
@ -105,7 +105,7 @@ namespace Avalonia.X11
density *= _settings.GlobalScaleFactor;
var bounds = new Rect(mon.X, mon.Y, mon.Width, mon.Height);
var bounds = new PixelRect(mon.X, mon.Y, mon.Width, mon.Height);
screens[c] = new X11Screen(bounds,
mon.Primary != 0,
name,
@ -130,12 +130,12 @@ namespace Avalonia.X11
Screens = UpdateWorkArea(info,
new[]
{
new X11Screen(new Rect(0, 0, geo.width, geo.height), true, "Default", null,
new X11Screen(new PixelRect(0, 0, geo.width, geo.height), true, "Default", null,
settings.GlobalScaleFactor)
});
}
Screens = new[] {new X11Screen(new Rect(0, 0, 1920, 1280), true, "Default", null, settings.GlobalScaleFactor)};
Screens = new[] {new X11Screen(new PixelRect(0, 0, 1920, 1280), true, "Default", null, settings.GlobalScaleFactor)};
}
public X11Screen[] Screens { get; }
@ -220,12 +220,12 @@ namespace Avalonia.X11
{
public bool Primary { get; }
public string Name { get; set; }
public Rect Bounds { get; set; }
public PixelRect Bounds { get; set; }
public Size? PhysicalSize { get; set; }
public double PixelDensity { get; set; }
public Rect WorkingArea { get; set; }
public PixelRect WorkingArea { get; set; }
public X11Screen(Rect bounds, bool primary,
public X11Screen(PixelRect bounds, bool primary,
string name, Size? physicalSize, double? pixelDensity)
{
Primary = primary;

20
src/Avalonia.X11/X11Window.cs

@ -24,12 +24,12 @@ namespace Avalonia.X11
private readonly X11Info _x11;
private bool _invalidated;
private XConfigureEvent? _configure;
private Point? _configurePoint;
private PixelPoint? _configurePoint;
private bool _triggeredExpose;
private IInputRoot _inputRoot;
private readonly IMouseDevice _mouse;
private readonly IKeyboardDevice _keyboard;
private Point? _position;
private PixelPoint? _position;
private PixelSize _realSize;
private IntPtr _handle;
private IntPtr _xic;
@ -235,7 +235,7 @@ namespace Avalonia.X11
public Func<bool> Closing { get; set; }
public Action<WindowState> WindowStateChanged { get; set; }
public Action Closed { get; set; }
public Action<Point> PositionChanged { get; set; }
public Action<PixelPoint> PositionChanged { get; set; }
public IRenderer CreateRenderer(IRenderRoot root) =>
new DeferredRenderer(root, AvaloniaLocator.Current.GetService<IRenderLoop>());
@ -321,13 +321,13 @@ namespace Avalonia.X11
var needEnqueue = (_configure == null);
_configure = ev.ConfigureEvent;
if (ev.ConfigureEvent.override_redirect || ev.ConfigureEvent.send_event)
_configurePoint = new Point(ev.ConfigureEvent.x, ev.ConfigureEvent.y);
_configurePoint = new PixelPoint(ev.ConfigureEvent.x, ev.ConfigureEvent.y);
else
{
XTranslateCoordinates(_x11.Display, _handle, _x11.RootWindow,
0, 0,
out var tx, out var ty, out _);
_configurePoint = new Point(tx, ty);
_configurePoint = new PixelPoint(tx, ty);
}
if (needEnqueue)
Dispatcher.UIThread.Post(() =>
@ -660,9 +660,11 @@ namespace Avalonia.X11
public void Hide() => XUnmapWindow(_x11.Display, _handle);
public Point PointToClient(Point point) => new Point((point.X - Position.X) / Scaling, (point.Y - Position.Y) / Scaling);
public Point PointToClient(PixelPoint point) => new Point((point.X - Position.X) / Scaling, (point.Y - Position.Y) / Scaling);
public Point PointToScreen(Point point) => new Point(point.X * Scaling + Position.X, point.Y * Scaling + Position.Y);
public PixelPoint PointToScreen(Point point) => new PixelPoint(
(int)(point.X * Scaling + Position.X),
(int)(point.Y * Scaling + Position.Y));
public void SetSystemDecorations(bool enabled)
{
@ -716,7 +718,7 @@ namespace Avalonia.X11
public IPlatformHandle Handle { get; }
public Point Position
public PixelPoint Position
{
get => _position ?? default;
set
@ -752,7 +754,7 @@ namespace Avalonia.X11
public IScreenImpl Screen => _platform.Screens;
public Size MaxClientSize => _platform.X11Screens.Screens.Select(s => s.Bounds.Size / s.PixelDensity)
public Size MaxClientSize => _platform.X11Screens.Screens.Select(s => s.Bounds.Size.ToSize(s.PixelDensity))
.OrderByDescending(x => x.Width + x.Height).FirstOrDefault();

4
src/Gtk/Avalonia.Gtk3/GtkScreen.cs

@ -6,7 +6,7 @@ namespace Avalonia.Gtk3
{
private readonly int _screenId;
public GtkScreen(Rect bounds, Rect workingArea, bool primary, int screenId) : base(bounds, workingArea, primary)
public GtkScreen(PixelRect bounds, PixelRect workingArea, bool primary, int screenId) : base(bounds, workingArea, primary)
{
this._screenId = screenId;
}
@ -21,4 +21,4 @@ namespace Avalonia.Gtk3
return (obj is GtkScreen screen) ? this._screenId == screen._screenId : base.Equals(obj);
}
}
}
}

4
src/Gtk/Avalonia.Gtk3/ScreenImpl.cs

@ -27,8 +27,8 @@ namespace Avalonia.Gtk3
GdkRectangle workArea = new GdkRectangle(), geometry = new GdkRectangle();
Native.GdkScreenGetMonitorGeometry(screen, i, ref geometry);
Native.GdkScreenGetMonitorWorkarea(screen, i, ref workArea);
Rect workAreaRect = new Rect(workArea.X, workArea.Y, workArea.Width, workArea.Height);
Rect geometryRect = new Rect(geometry.X, geometry.Y, geometry.Width, geometry.Height);
PixelRect workAreaRect = new PixelRect(workArea.X, workArea.Y, workArea.Width, workArea.Height);
PixelRect geometryRect = new PixelRect(geometry.X, geometry.Y, geometry.Width, geometry.Height);
GtkScreen s = new GtkScreen(geometryRect, workAreaRect, i == primary, i);
screens[i] = s;
}

14
src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs

@ -24,7 +24,7 @@ namespace Avalonia.Gtk3
private readonly EglGlPlatformSurface _egl;
protected readonly List<IDisposable> Disposables = new List<IDisposable>();
private Size _lastSize;
private Point _lastPosition;
private PixelPoint _lastPosition;
private double _lastScaling;
private uint _lastKbdEvent;
private uint _lastSmoothScrollEvent;
@ -383,7 +383,7 @@ namespace Avalonia.Gtk3
public Action<Rect> Paint { get; set; }
public Action<Size> Resized { get; set; }
public Action<double> ScalingChanged { get; set; } //TODO
public Action<Point> PositionChanged { get; set; }
public Action<PixelPoint> PositionChanged { get; set; }
public void Activate() => Native.GtkWidgetActivate(GtkWidget);
@ -402,7 +402,7 @@ namespace Avalonia.Gtk3
Dispatcher.UIThread.Post(() => Input?.Invoke(args), DispatcherPriority.Input);
}
public Point PointToClient(Point point)
public Point PointToClient(PixelPoint point)
{
int x, y;
Native.GdkWindowGetOrigin(Native.GtkWidgetGetWindow(GtkWidget), out x, out y);
@ -410,11 +410,11 @@ namespace Avalonia.Gtk3
return new Point(point.X - x, point.Y - y);
}
public Point PointToScreen(Point point)
public PixelPoint PointToScreen(Point point)
{
int x, y;
Native.GdkWindowGetOrigin(Native.GtkWidgetGetWindow(GtkWidget), out x, out y);
return new Point(point.X + x, point.Y + y);
return new PixelPoint((int)(point.X + x), (int)(point.Y + y));
}
public void SetCursor(IPlatformHandle cursor)
@ -490,13 +490,13 @@ namespace Avalonia.Gtk3
get;
} = new ScreenImpl();
public Point Position
public PixelPoint Position
{
get
{
int x, y;
Native.GtkWindowGetPosition(GtkWidget, out x, out y);
return new Point(x, y);
return new PixelPoint(x, y);
}
set { Native.GtkWindowMove(GtkWidget, (int)value.X, (int)value.Y); }
}

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

@ -51,9 +51,9 @@ namespace Avalonia.LinuxFramebuffer
InputRoot = inputRoot;
}
public Point PointToClient(Point point) => point;
public Point PointToClient(PixelPoint p) => p.ToPoint(1);
public Point PointToScreen(Point point) => point;
public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1);
public void SetCursor(IPlatformHandle cursor)
{

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

@ -3,7 +3,9 @@
static class WpfInteropExtensions
{
public static System.Windows.Point ToWpfPoint(this Point pt) => new System.Windows.Point(pt.X, pt.Y);
public static System.Windows.Point ToWpfPoint(this PixelPoint pt) => new System.Windows.Point(pt.X, pt.Y);
public static Point ToAvaloniaPoint(this System.Windows.Point pt) => new Point(pt.X, pt.Y);
public static PixelPoint ToAvaloniaPixelPoint(this System.Windows.Point pt) => new PixelPoint((int)pt.X, (int)pt.Y);
public static System.Windows.Size ToWpfSize(this Size pt) => new System.Windows.Size(pt.Width, pt.Height);
public static Size ToAvaloniaSize(this System.Windows.Size pt) => new Size(pt.Width, pt.Height);
}

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

@ -135,9 +135,9 @@ namespace Avalonia.Win32.Interop.Wpf
void ITopLevelImpl.SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot;
Point ITopLevelImpl.PointToClient(Point point) => PointFromScreen(point.ToWpfPoint()).ToAvaloniaPoint();
Point ITopLevelImpl.PointToClient(PixelPoint point) => PointFromScreen(point.ToWpfPoint()).ToAvaloniaPoint();
Point ITopLevelImpl.PointToScreen(Point point) => PointToScreen(point.ToWpfPoint()).ToAvaloniaPoint();
PixelPoint ITopLevelImpl.PointToScreen(Point point) => PointToScreen(point.ToWpfPoint()).ToAvaloniaPixelPoint();
protected override void OnLostFocus(RoutedEventArgs e) => LostFocus?.Invoke();

2
src/Windows/Avalonia.Win32/OleDropTarget.cs

@ -177,7 +177,7 @@ namespace Avalonia.Win32
int x = (int)dragPoint;
int y = (int)(dragPoint >> 32);
Point screenPt = new Point(x, y);
var screenPt = new PixelPoint(x, y);
return _target.PointToClient(screenPt);
}
}

6
src/Windows/Avalonia.Win32/ScreenImpl.cs

@ -31,10 +31,10 @@ namespace Avalonia.Win32
{
RECT bounds = monitorInfo.rcMonitor;
RECT workingArea = monitorInfo.rcWork;
Rect avaloniaBounds = new Rect(bounds.left, bounds.top, bounds.right - bounds.left,
PixelRect avaloniaBounds = new PixelRect(bounds.left, bounds.top, bounds.right - bounds.left,
bounds.bottom - bounds.top);
Rect avaloniaWorkArea =
new Rect(workingArea.left, workingArea.top, workingArea.right - workingArea.left,
PixelRect avaloniaWorkArea =
new PixelRect(workingArea.left, workingArea.top, workingArea.right - workingArea.left,
workingArea.bottom - workingArea.top);
screens[index] =
new WinScreen(avaloniaBounds, avaloniaWorkArea, monitorInfo.dwFlags == 1,

4
src/Windows/Avalonia.Win32/WinScreen.cs

@ -7,7 +7,7 @@ namespace Avalonia.Win32
{
private readonly IntPtr _hMonitor;
public WinScreen(Rect bounds, Rect workingArea, bool primary, IntPtr hMonitor) : base(bounds, workingArea, primary)
public WinScreen(PixelRect bounds, PixelRect workingArea, bool primary, IntPtr hMonitor) : base(bounds, workingArea, primary)
{
this._hMonitor = hMonitor;
}
@ -22,4 +22,4 @@ namespace Avalonia.Win32
return (obj is WinScreen screen) ? this._hMonitor == screen._hMonitor : base.Equals(obj);
}
}
}
}

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

@ -87,7 +87,7 @@ namespace Avalonia.Win32
public Action<double> ScalingChanged { get; set; }
public Action<Point> PositionChanged { get; set; }
public Action<PixelPoint> PositionChanged { get; set; }
public Action<WindowState> WindowStateChanged { get; set; }
@ -297,19 +297,19 @@ namespace Avalonia.Win32
UnmanagedMethods.InvalidateRect(_hwnd, ref r, false);
}
public Point PointToClient(Point point)
public Point PointToClient(PixelPoint point)
{
var p = new UnmanagedMethods.POINT { X = (int)point.X, Y = (int)point.Y };
UnmanagedMethods.ScreenToClient(_hwnd, ref p);
return new Point(p.X, p.Y) / Scaling;
}
public Point PointToScreen(Point point)
public PixelPoint PointToScreen(Point point)
{
point *= Scaling;
var p = new UnmanagedMethods.POINT { X = (int)point.X, Y = (int)point.Y };
UnmanagedMethods.ClientToScreen(_hwnd, ref p);
return new Point(p.X, p.Y);
return new PixelPoint(p.X, p.Y);
}
public void SetInputRoot(IInputRoot inputRoot)
@ -357,21 +357,21 @@ namespace Avalonia.Win32
#endif
}
public Point Position
public PixelPoint Position
{
get
{
UnmanagedMethods.RECT rc;
UnmanagedMethods.GetWindowRect(_hwnd, out rc);
return new Point(rc.left, rc.top);
return new PixelPoint(rc.left, rc.top);
}
set
{
UnmanagedMethods.SetWindowPos(
Handle.Handle,
IntPtr.Zero,
(int)value.X,
(int)value.Y,
value.X,
value.Y,
0,
0,
UnmanagedMethods.SetWindowPosFlags.SWP_NOSIZE | UnmanagedMethods.SetWindowPosFlags.SWP_NOACTIVATE);
@ -661,7 +661,7 @@ namespace Avalonia.Win32
return IntPtr.Zero;
case UnmanagedMethods.WindowsMessage.WM_MOVE:
PositionChanged?.Invoke(new Point((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16)));
PositionChanged?.Invoke(new PixelPoint((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16)));
return IntPtr.Zero;
case UnmanagedMethods.WindowsMessage.WM_GETMINMAXINFO:
@ -785,9 +785,9 @@ namespace Avalonia.Win32
return new Point((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16)) / Scaling;
}
private Point PointFromLParam(IntPtr lParam)
private PixelPoint PointFromLParam(IntPtr lParam)
{
return new Point((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16));
return new PixelPoint((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16));
}
private Point ScreenToClient(Point point)

4
src/iOS/Avalonia.iOS/TopLevelImpl.cs

@ -68,9 +68,9 @@ namespace Avalonia.iOS
public void SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot;
public Point PointToClient(Point point) => point;
public Point PointToClient(PixelPoint point) => point.ToPoint(1);
public Point PointToScreen(Point point) => point;
public PixelPoint PointToScreen(Point point) => PixelPoint.FromPoint(point, 1);
public void SetCursor(IPlatformHandle cursor)
{

4
tests/Avalonia.Controls.UnitTests/ButtonTests.cs

@ -238,9 +238,9 @@ namespace Avalonia.Controls.UnitTests
public void Invalidate(Rect rect) => throw new NotImplementedException();
public Point PointToClient(Point point) => throw new NotImplementedException();
public Point PointToClient(PixelPoint p) => throw new NotImplementedException();
public Point PointToScreen(Point point) => throw new NotImplementedException();
public PixelPoint PointToScreen(Point p) => throw new NotImplementedException();
}
private void RaisePointerPressed(Button button, IMouseDevice device, int clickCount, MouseButton mouseButton)

2
tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs

@ -160,7 +160,7 @@ namespace Avalonia.Controls.UnitTests
private IDisposable Application()
{
var screen = new Rect(new Point(), new Size(100, 100));
var screen = new PixelRect(new PixelPoint(), new PixelSize(100, 100));
var screenImpl = new Mock<IScreenImpl>();
screenImpl.Setup(x => x.ScreenCount).Returns(1);
screenImpl.Setup(X => X.AllScreens).Returns( new[] { new Screen(screen, screen, true) });

22
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs

@ -336,25 +336,11 @@ namespace Avalonia.Controls.UnitTests.Presenters
public double LayoutScaling => 1;
public ILayoutManager LayoutManager { get; } = new LayoutManager();
public IRenderTarget CreateRenderTarget()
{
throw new NotImplementedException();
}
public void Invalidate(Rect rect)
{
throw new NotImplementedException();
}
public Point PointToClient(Point point)
{
throw new NotImplementedException();
}
public Point PointToScreen(Point point)
{
throw new NotImplementedException();
}
public IRenderTarget CreateRenderTarget() => throw new NotImplementedException();
public void Invalidate(Rect rect) => throw new NotImplementedException();
public Point PointToClient(PixelPoint p) => throw new NotImplementedException();
public PixelPoint PointToScreen(Point p) => throw new NotImplementedException();
}
private class TestItemsPresenter : ItemsPresenter

28
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs

@ -1077,30 +1077,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
public ILayoutManager LayoutManager { get; } = new LayoutManager();
public IRenderTarget CreateRenderTarget()
{
throw new NotImplementedException();
}
public void Invalidate(Rect rect)
{
throw new NotImplementedException();
}
public Point PointToClient(Point point)
{
throw new NotImplementedException();
}
public Point PointToScreen(Point point)
{
throw new NotImplementedException();
}
protected override Size MeasureOverride(Size availableSize)
{
return base.MeasureOverride(availableSize);
}
public IRenderTarget CreateRenderTarget() => throw new NotImplementedException();
public void Invalidate(Rect rect) => throw new NotImplementedException();
public Point PointToClient(PixelPoint p) => throw new NotImplementedException();
public PixelPoint PointToScreen(Point p) => throw new NotImplementedException();
}
private class TestItemsPresenter : ItemsPresenter

22
tests/Avalonia.Controls.UnitTests/WindowTests.cs

@ -278,8 +278,8 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Window_Should_Be_Centered_When_WindowStartupLocation_Is_CenterScreen()
{
var screen1 = new Mock<Screen>(new Rect(new Size(1920, 1080)), new Rect(new Size(1920, 1040)), true);
var screen2 = new Mock<Screen>(new Rect(new Size(1366, 768)), new Rect(new Size(1366, 728)), false);
var screen1 = new Mock<Screen>(new PixelRect(new PixelSize(1920, 1080)), new PixelRect(new PixelSize(1920, 1040)), true);
var screen2 = new Mock<Screen>(new PixelRect(new PixelSize(1366, 768)), new PixelRect(new PixelSize(1366, 728)), false);
var screens = new Mock<IScreenImpl>();
screens.Setup(x => x.AllScreens).Returns(new Screen[] { screen1.Object, screen2.Object });
@ -294,13 +294,13 @@ namespace Avalonia.Controls.UnitTests
{
var window = new Window(windowImpl.Object);
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
window.Position = new Point(60, 40);
window.Position = new PixelPoint(60, 40);
window.Show();
var expectedPosition = new Point(
screen1.Object.WorkingArea.Size.Width / 2 - window.ClientSize.Width / 2,
screen1.Object.WorkingArea.Size.Height / 2 - window.ClientSize.Height / 2);
var expectedPosition = new PixelPoint(
(int)(screen1.Object.WorkingArea.Size.Width / 2 - window.ClientSize.Width / 2),
(int)(screen1.Object.WorkingArea.Size.Height / 2 - window.ClientSize.Height / 2));
Assert.Equal(window.Position, expectedPosition);
}
@ -330,7 +330,7 @@ namespace Avalonia.Controls.UnitTests
using (UnitTestApplication.Start(parentWindowServices))
{
var parentWindow = new Window();
parentWindow.Position = new Point(60, 40);
parentWindow.Position = new PixelPoint(60, 40);
parentWindow.Show();
@ -338,14 +338,14 @@ namespace Avalonia.Controls.UnitTests
{
var window = new Window();
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
window.Position = new Point(60, 40);
window.Position = new PixelPoint(60, 40);
window.Owner = parentWindow;
window.Show();
var expectedPosition = new Point(
parentWindow.Position.X + parentWindow.ClientSize.Width / 2 - window.ClientSize.Width / 2,
parentWindow.Position.Y + parentWindow.ClientSize.Height / 2 - window.ClientSize.Height / 2);
var expectedPosition = new PixelPoint(
(int)(parentWindow.Position.X + parentWindow.ClientSize.Width / 2 - window.ClientSize.Width / 2),
(int)(parentWindow.Position.Y + parentWindow.ClientSize.Height / 2 - window.ClientSize.Height / 2));
Assert.Equal(window.Position, expectedPosition);
}

4
tests/Avalonia.UnitTests/TestRoot.cs

@ -90,9 +90,9 @@ namespace Avalonia.UnitTests
{
}
public Point PointToClient(Point p) => p;
public Point PointToClient(PixelPoint p) => p.ToPoint(1);
public Point PointToScreen(Point p) => p;
public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1);
void INameScope.Register(string name, object element)
{

4
tests/Avalonia.UnitTests/TestTemplatedRoot.cs

@ -57,9 +57,9 @@ namespace Avalonia.UnitTests
throw new NotImplementedException();
}
public Point PointToClient(Point p) => p;
public Point PointToClient(PixelPoint p) => p.ToPoint(1);
public Point PointToScreen(Point p) => p;
public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1);
void INameScope.Register(string name, object element)
{

Loading…
Cancel
Save