Browse Source

Added managed BeginResizeDrag implementation

pull/1005/head
Nikita Tsukanov 9 years ago
parent
commit
d3390ac553
  1. 4
      samples/ControlCatalog/DecoratedWindow.xaml.cs
  2. 3
      src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj
  3. 13
      src/OSX/Avalonia.MonoMac/TopLevelImpl.cs
  4. 21
      src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs
  5. 85
      src/Shared/WindowResizeDragHelper.cs
  6. 1
      src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems
  7. 21
      src/Windows/Avalonia.Win32/WindowImpl.cs

4
samples/ControlCatalog/DecoratedWindow.xaml.cs

@ -33,8 +33,8 @@ namespace ControlCatalog
};
SetupSide("Left", StandardCursorType.LeftSide, WindowEdge.West);
SetupSide("Right", StandardCursorType.RightSide, WindowEdge.East);
SetupSide("Top", StandardCursorType.TopSide, WindowEdge.South);
SetupSide("Bottom", StandardCursorType.BottomSize, WindowEdge.North);
SetupSide("Top", StandardCursorType.TopSide, WindowEdge.North);
SetupSide("Bottom", StandardCursorType.BottomSize, WindowEdge.South);
SetupSide("TopLeft", StandardCursorType.TopLeftCorner, WindowEdge.NorthWest);
SetupSide("TopRight", StandardCursorType.TopRightCorner, WindowEdge.NorthEast);
SetupSide("BottomLeft", StandardCursorType.BottomLeftCorner, WindowEdge.SouthWest);

3
src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj

@ -3,6 +3,9 @@
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\Shared\WindowResizeDragHelper.cs" Link="WindowResizeDragHelper.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MonoMac.NetStandard" Version="0.0.3" />
</ItemGroup>

13
src/OSX/Avalonia.MonoMac/TopLevelImpl.cs

@ -22,6 +22,11 @@ namespace Avalonia.MonoMac
View = new TopLevelView(this);
}
protected virtual void OnInput(RawInputEventArgs args)
{
Input?.Invoke(args);
}
[Adopts("NSTextInputClient")]
public class TopLevelView : NSView
{
@ -135,11 +140,11 @@ namespace Avalonia.MonoMac
if (delta.X == 0 && delta.Y == 0)
return;
// ReSharper restore CompareOfFloatsByEqualityOperator
_tl.Input?.Invoke(new RawMouseWheelEventArgs(_mouse, ts, _tl.InputRoot, loc,
_tl.OnInput(new RawMouseWheelEventArgs(_mouse, ts, _tl.InputRoot, loc,
delta, mod));
}
else
_tl.Input?.Invoke(new RawMouseEventArgs(_mouse, ts, _tl.InputRoot, type, loc, mod));
_tl.OnInput(new RawMouseEventArgs(_mouse, ts, _tl.InputRoot, type, loc, mod));
}
public override void MouseMoved(NSEvent theEvent)
@ -229,7 +234,7 @@ namespace Avalonia.MonoMac
var code = KeyTransform.TransformKeyCode(ev.KeyCode);
if (!code.HasValue)
return;
_tl.Input?.Invoke(new RawKeyEventArgs(_keyboard, GetTimeStamp(ev),
_tl.OnInput(new RawKeyEventArgs(_keyboard, GetTimeStamp(ev),
type, code.Value, GetModifiers(ev.ModifierFlags)));
}
@ -294,7 +299,7 @@ namespace Avalonia.MonoMac
public void InsertText(NSString str, NSRange range)
{
//TODO: timestamp
_tl.Input?.Invoke(new RawTextInputEventArgs(_keyboard, 0, str.ToString()));
_tl.OnInput(new RawTextInputEventArgs(_keyboard, 0, str.ToString()));
}
[Export("characterIndexForPoint:")]

21
src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs

@ -1,5 +1,6 @@
using System;
using Avalonia.Controls;
using Avalonia.Input.Raw;
using Avalonia.Platform;
using MonoMac.AppKit;
using MonoMac.CoreGraphics;
@ -9,10 +10,12 @@ namespace Avalonia.MonoMac
{
class WindowBaseImpl : TopLevelImpl, IWindowBaseImpl
{
private readonly ManagedWindowResizeDragHelper _managedDrag;
public CustomWindow Window { get; private set; }
public WindowBaseImpl()
{
_managedDrag = new ManagedWindowResizeDragHelper(this, _ => { }, ResizeForManagedDrag);
Window = new CustomWindow(this)
{
StyleMask = NSWindowStyle.Titled,
@ -92,7 +95,7 @@ namespace Avalonia.MonoMac
public Point Position
{
get => Window.Frame.ToAvaloniaRect().BottomLeft.ConvertPointY();
set => Window.CascadeTopLeftFromPoint(value.ToMonoMacPoint().ConvertPointY());
set => Window.SetFrameTopLeftPoint(value.ToMonoMacPoint().ConvertPointY());
}
@ -126,11 +129,25 @@ namespace Avalonia.MonoMac
public void BeginResizeDrag(WindowEdge edge)
{
//TODO: Intercept mouse events and implement resize drag manually
var screenPoint = NSEvent.CurrentMouseLocation.ConvertPointY().ToAvaloniaPoint();
_managedDrag.BeginResizeDrag(edge, PointToClient(screenPoint));
}
protected override void OnInput(RawInputEventArgs args)
{
if (_managedDrag.PreprocessInputEvent(ref args))
return;
base.OnInput(args);
}
public void Activate() => Window.MakeKeyWindow();
public void ResizeForManagedDrag(Rect rc)
{
var frame = new CGRect(rc.X, rc.Position.ConvertPointY().Y - rc.Height, rc.Width, rc.Height);
Window.SetFrame(frame, true);
}
public void Resize(Size clientSize)
{
var pos = Position;

85
src/Shared/WindowResizeDragHelper.cs

@ -0,0 +1,85 @@
using System;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Platform;
namespace Avalonia
{
internal class ManagedWindowResizeDragHelper
{
private readonly IWindowBaseImpl _window;
private readonly Action<bool> _captureMouse;
private readonly Action<Rect> _resize;
private WindowEdge? _edge;
private Point _prevPoint;
public ManagedWindowResizeDragHelper(IWindowBaseImpl window, Action<bool> captureMouse, Action<Rect> resize = null)
{
_window = window;
_captureMouse = captureMouse;
_resize = resize;
}
public void BeginResizeDrag(WindowEdge edge, Point currentMousePosition)
{
_captureMouse(true);
_prevPoint = currentMousePosition;
_edge = edge;
}
public bool PreprocessInputEvent(ref RawInputEventArgs e)
{
if (_edge == null)
return false;
if (e is RawMouseEventArgs args)
{
if (args.Type == RawMouseEventType.LeftButtonUp)
{
_edge = null;
_captureMouse(false);
}
if (args.Type == RawMouseEventType.Move)
{
MoveWindow(args.Position);
return true;
}
_edge = null;
}
return false;
}
private void MoveWindow(Point position)
{
var diff = position - _prevPoint;
var edge = _edge.Value;
var rc = new Rect(_window.Position, _window.ClientSize);
if (edge == WindowEdge.East || edge == WindowEdge.NorthEast || edge == WindowEdge.SouthEast)
{
rc = rc.WithWidth(rc.Width + diff.X);
_prevPoint = _prevPoint.WithX(position.X);
}
if (edge == WindowEdge.West || edge == WindowEdge.NorthWest || edge == WindowEdge.SouthWest)
rc = rc.WithX(rc.X + diff.X).WithWidth(rc.Width - diff.X);
if (edge == WindowEdge.South || edge == WindowEdge.SouthWest || edge == WindowEdge.SouthEast)
{
rc = rc.WithHeight(rc.Height + diff.Y);
_prevPoint = _prevPoint.WithY(position.Y);
}
if (edge == WindowEdge.North || edge == WindowEdge.NorthWest || edge == WindowEdge.NorthEast)
rc = rc.WithY(rc.Y + diff.Y).WithHeight(rc.Height - diff.Y);
if (_resize != null)
_resize(rc);
else
{
if (_window.Position != rc.Position)
_window.Position = rc.Position;
if (_window.ClientSize != rc.Size)
_window.Resize(rc.Size);
}
}
}
}

1
src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems

@ -24,6 +24,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Win32Platform.cs" />
<Compile Include="$(MSBuildThisFileDirectory)WindowFramebuffer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)WindowImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\Shared\WindowResizeDragHelper.cs" />
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>

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

@ -38,9 +38,21 @@ namespace Avalonia.Win32
private double _scaling = 1;
private WindowState _showWindowState;
private FramebufferManager _framebuffer;
#if USE_MANAGED_DRAG
private readonly ManagedWindowResizeDragHelper _managedDrag;
#endif
public WindowImpl()
{
#if USE_MANAGED_DRAG
_managedDrag = new ManagedWindowResizeDragHelper(this, capture =>
{
if (capture)
UnmanagedMethods.SetCapture(Handle.Handle);
else
UnmanagedMethods.ReleaseCapture();
});
#endif
CreateWindow();
_framebuffer = new FramebufferManager(_hwnd);
s_instances.Add(this);
@ -327,8 +339,12 @@ namespace Avalonia.Win32
public void BeginResizeDrag(WindowEdge edge)
{
#if USE_MANAGED_DRAG
_managedDrag.BeginResizeDrag(edge, ScreenToClient(MouseDevice.Position));
#else
UnmanagedMethods.DefWindowProc(_hwnd, (int)UnmanagedMethods.WindowsMessage.WM_NCLBUTTONDOWN,
new IntPtr((int)EdgeDic[edge]), IntPtr.Zero);
#endif
}
public Point Position
@ -583,6 +599,11 @@ namespace Avalonia.Win32
PositionChanged?.Invoke(new Point((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16)));
return IntPtr.Zero;
}
#if USE_MANAGED_DRAG
if (_managedDrag.PreprocessInputEvent(ref e))
return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
#endif
if (e != null && Input != null)
{

Loading…
Cancel
Save