diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs index 66f6aeb757..c5e3622404 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs @@ -87,6 +87,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform public Action ScalingChanged { get; set; } + public Action PositionChanged { get; set; } + public View View => this; Action ITopLevelImpl.Activated { get; set; } diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj index 7a04e0747c..336f7da2dc 100644 --- a/src/Avalonia.Controls/Avalonia.Controls.csproj +++ b/src/Avalonia.Controls/Avalonia.Controls.csproj @@ -56,6 +56,7 @@ + diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs index b06c4b9695..087a333e8a 100644 --- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs +++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs @@ -72,6 +72,11 @@ namespace Avalonia.Platform /// Action ScalingChanged { get; set; } + /// + /// Gets or sets a method called when the window's position changes. + /// + Action PositionChanged { get; set; } + /// /// Activates the window. /// diff --git a/src/Avalonia.Controls/PointEventArgs.cs b/src/Avalonia.Controls/PointEventArgs.cs new file mode 100644 index 0000000000..4173d367d0 --- /dev/null +++ b/src/Avalonia.Controls/PointEventArgs.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 +{ + /// + /// Provides data for events. + /// + public class PointEventArgs : EventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The data. + public PointEventArgs(Point point) + { + Point = point; + } + + /// + /// Gets the data. + /// + public Point Point { get; } + } +} diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 59a3072c23..47660b27e8 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -105,6 +105,7 @@ namespace Avalonia.Controls PlatformImpl.Input = HandleInput; PlatformImpl.Resized = HandleResized; PlatformImpl.ScalingChanged = HandleScalingChanged; + PlatformImpl.PositionChanged = HandlePositionChanged; _keyboardNavigationHandler?.SetOwner(this); _accessKeyHandler?.SetOwner(this); @@ -138,6 +139,11 @@ namespace Avalonia.Controls /// public event EventHandler Deactivated; + /// + /// Fired when the window position is changed. + /// + public event EventHandler PositionChanged; + /// /// Gets or sets the client size of the window. /// @@ -395,6 +401,16 @@ namespace Avalonia.Controls _inputManager.ProcessInput(e); } + /// + /// Handles a window position change notification from + /// . + /// + /// The window position. + private void HandlePositionChanged(Point pos) + { + PositionChanged?.Invoke(this, new PointEventArgs(pos)); + } + /// /// Starts moving a window with left button being held. Should be called from left mouse button press event handler /// diff --git a/src/Gtk/Avalonia.Gtk/WindowImpl.cs b/src/Gtk/Avalonia.Gtk/WindowImpl.cs index c1a69e8932..bb3c3e6b7b 100644 --- a/src/Gtk/Avalonia.Gtk/WindowImpl.cs +++ b/src/Gtk/Avalonia.Gtk/WindowImpl.cs @@ -10,9 +10,7 @@ namespace Avalonia.Gtk { private Gtk.Window _window; private Gtk.Window Window => _window ?? (_window = (Gtk.Window) Widget); - - - + public WindowImpl(Gtk.WindowType type) : base(new PlatformHandleAwareWindow(type)) { Init(); @@ -29,8 +27,10 @@ namespace Avalonia.Gtk Window.FocusActivated += OnFocusActivated; Window.ConfigureEvent += OnConfigureEvent; _lastClientSize = ClientSize; + _lastPosition = Position; } private Size _lastClientSize; + private Point _lastPosition; void OnConfigureEvent(object o, Gtk.ConfigureEventArgs args) { var evnt = args.Event; @@ -42,6 +42,14 @@ namespace Avalonia.Gtk Resized(newSize); _lastClientSize = newSize; } + + var newPosition = new Point(evnt.X, evnt.Y); + + if (newPosition != _lastPosition) + { + PositionChanged(newPosition); + _lastPosition = newPosition; + } } public override Size ClientSize @@ -107,12 +115,12 @@ namespace Avalonia.Gtk return Disposable.Empty; } - + public override void SetSystemDecorations(bool enabled) => Window.Decorated = enabled; - + public override void SetIcon(IWindowIconImpl icon) { Window.Icon = ((IconImpl)icon).Pixbuf; } } -} \ No newline at end of file +} diff --git a/src/Gtk/Avalonia.Gtk/WindowImplBase.cs b/src/Gtk/Avalonia.Gtk/WindowImplBase.cs index c0020f5e6f..759d35b1fc 100644 --- a/src/Gtk/Avalonia.Gtk/WindowImplBase.cs +++ b/src/Gtk/Avalonia.Gtk/WindowImplBase.cs @@ -122,6 +122,8 @@ namespace Avalonia.Gtk public Action Paint { get; set; } public Action Resized { get; set; } + + public Action PositionChanged { get; set; } public Action ScalingChanged { get; set; } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 62fbdda275..872a7cf36b 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -55,6 +55,8 @@ namespace Avalonia.Win32 public Action ScalingChanged { get; set; } + public Action PositionChanged { get; set; } + public Thickness BorderThickness { get @@ -561,6 +563,10 @@ namespace Avalonia.Win32 } return IntPtr.Zero; + + case UnmanagedMethods.WindowsMessage.WM_MOVE: + PositionChanged?.Invoke(new Point((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16))); + return IntPtr.Zero; } if (e != null && Input != null) diff --git a/src/iOS/Avalonia.iOS/AvaloniaView.cs b/src/iOS/Avalonia.iOS/AvaloniaView.cs index 505a88ecd5..8b14d09573 100644 --- a/src/iOS/Avalonia.iOS/AvaloniaView.cs +++ b/src/iOS/Avalonia.iOS/AvaloniaView.cs @@ -27,6 +27,7 @@ namespace Avalonia.iOS private readonly UIViewController _controller; private IInputRoot _inputRoot; private readonly KeyboardEventsHelper _keyboardHelper; + private Point _position; public AvaloniaView(UIWindow window, UIViewController controller) : base(onFrame => PlatformThreadingInterface.Instance.Render = onFrame) { @@ -72,6 +73,7 @@ namespace Avalonia.iOS public Action Paint { get; set; } public Action Resized { get; set; } public Action ScalingChanged { get; set; } + public Action PositionChanged { get; set; } public IPlatformHandle Handle => AvaloniaPlatformHandle; @@ -136,7 +138,15 @@ namespace Avalonia.iOS //Not supported } - public Point Position { get; set; } + public Point Position + { + get { return _position; } + set + { + _position = value; + PositionChanged?.Invoke(_position); + } + } public Size MaxClientSize => Bounds.Size.ToAvalonia(); public void SetTitle(string title)