Browse Source

Propagate mouse pointer capture to Win32 API

pull/2629/head
Nikita Tsukanov 7 years ago
parent
commit
85a5288fdd
  1. 9
      src/Avalonia.Input/MouseDevice.cs
  2. 6
      src/Avalonia.Input/Pointer.cs
  3. 28
      src/Windows/Avalonia.Win32.Interop/Wpf/WpfMouseDevice.cs
  4. 26
      src/Windows/Avalonia.Win32/Input/WindowsMouseDevice.cs
  5. 2
      src/Windows/Avalonia.Win32/WindowImpl.cs

9
src/Avalonia.Input/MouseDevice.cs

@ -20,8 +20,13 @@ namespace Avalonia.Input
private Rect _lastClickRect;
private ulong _lastClickTime;
private readonly Pointer _pointer = new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true);
private readonly Pointer _pointer;
public MouseDevice(Pointer pointer = null)
{
_pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true);
}
/// <summary>
/// Gets the control that is currently capturing by the mouse, if any.
/// </summary>
@ -51,7 +56,7 @@ namespace Avalonia.Input
/// within the control's bounds or not. The current mouse capture control is exposed
/// by the <see cref="Captured"/> property.
/// </remarks>
public virtual void Capture(IInputElement control)
public void Capture(IInputElement control)
{
_pointer.Capture(control);
}

6
src/Avalonia.Input/Pointer.cs

@ -27,6 +27,11 @@ namespace Avalonia.Input
var seen = new HashSet<IInputElement>(control1.GetSelfAndVisualAncestors().OfType<IInputElement>());
return control2.GetSelfAndVisualAncestors().OfType<IInputElement>().FirstOrDefault(seen.Contains);
}
protected virtual void PlatformCapture(IInputElement element)
{
}
public void Capture(IInputElement control)
{
@ -34,6 +39,7 @@ namespace Avalonia.Input
Captured.DetachedFromVisualTree -= OnCaptureDetached;
var oldCapture = control;
Captured = control;
PlatformCapture(control);
if (oldCapture != null)
{
var commonParent = FindCommonParent(control, oldCapture);

28
src/Windows/Avalonia.Win32.Interop/Wpf/WpfMouseDevice.cs

@ -9,22 +9,32 @@ namespace Avalonia.Win32.Interop.Wpf
{
private readonly WpfTopLevelImpl _impl;
public WpfMouseDevice(WpfTopLevelImpl impl)
public WpfMouseDevice(WpfTopLevelImpl impl) : base(new WpfMousePointer(impl))
{
_impl = impl;
}
public override void Capture(IInputElement control)
class WpfMousePointer : Pointer
{
if (control == null)
private readonly WpfTopLevelImpl _impl;
public WpfMousePointer(WpfTopLevelImpl impl) : base(Pointer.GetNextFreeId(), PointerType.Mouse, true)
{
_impl = impl;
}
protected override void PlatformCapture(IInputElement control)
{
System.Windows.Input.Mouse.Capture(null);
if (control == null)
{
System.Windows.Input.Mouse.Capture(null);
}
else if ((control.GetVisualRoot() as EmbeddableControlRoot)?.PlatformImpl != _impl)
throw new ArgumentException("Visual belongs to unknown toplevel");
else
System.Windows.Input.Mouse.Capture(_impl);
}
else if ((control.GetVisualRoot() as EmbeddableControlRoot)?.PlatformImpl != _impl)
throw new ArgumentException("Visual belongs to unknown toplevel");
else
System.Windows.Input.Mouse.Capture(_impl);
base.Capture(control);
}
}
}

26
src/Windows/Avalonia.Win32/Input/WindowsMouseDevice.cs

@ -1,7 +1,10 @@
// 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;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.VisualTree;
using Avalonia.Win32.Interop;
namespace Avalonia.Win32.Input
@ -10,23 +13,32 @@ namespace Avalonia.Win32.Input
{
public static WindowsMouseDevice Instance { get; } = new WindowsMouseDevice();
public WindowsMouseDevice() : base(new WindowsMousePointer())
{
}
public WindowImpl CurrentWindow
{
get;
set;
}
public override void Capture(IInputElement control)
class WindowsMousePointer : Pointer
{
base.Capture(control);
if (control != null)
public WindowsMousePointer() : base(Pointer.GetNextFreeId(),PointerType.Mouse, true)
{
UnmanagedMethods.SetCapture(CurrentWindow.Handle.Handle);
}
else
protected override void PlatformCapture(IInputElement element)
{
UnmanagedMethods.ReleaseCapture();
var hwnd = ((element?.GetVisualRoot() as TopLevel)?.PlatformImpl as WindowImpl)
?.Handle.Handle;
if (hwnd.HasValue && hwnd != IntPtr.Zero)
UnmanagedMethods.SetCapture(hwnd.Value);
else
UnmanagedMethods.ReleaseCapture();
}
}
}

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

@ -336,6 +336,7 @@ namespace Avalonia.Win32
public void BeginMoveDrag()
{
WindowsMouseDevice.Instance.Capture(null);
UnmanagedMethods.DefWindowProc(_hwnd, (int)UnmanagedMethods.WindowsMessage.WM_NCLBUTTONDOWN,
new IntPtr((int)UnmanagedMethods.HitTestValues.HTCAPTION), IntPtr.Zero);
}
@ -357,6 +358,7 @@ namespace Avalonia.Win32
#if USE_MANAGED_DRAG
_managedDrag.BeginResizeDrag(edge, ScreenToClient(MouseDevice.Position));
#else
WindowsMouseDevice.Instance.Capture(null);
UnmanagedMethods.DefWindowProc(_hwnd, (int)UnmanagedMethods.WindowsMessage.WM_NCLBUTTONDOWN,
new IntPtr((int)EdgeDic[edge]), IntPtr.Zero);
#endif

Loading…
Cancel
Save