From 2c53bf4750618490031e0e6cb3c5ddc3810f137e Mon Sep 17 00:00:00 2001 From: boombuler Date: Mon, 7 May 2018 07:58:31 +0200 Subject: [PATCH 1/2] send the modifiers with drag events --- .../Platform/InProcessDragSource.cs | 2 +- src/Avalonia.Input/DragDropDevice.cs | 24 +++++------ src/Avalonia.Input/DragEventArgs.cs | 5 ++- src/Avalonia.Input/Raw/RawDragEvent.cs | 4 +- src/OSX/Avalonia.MonoMac/TopLevelImpl.cs | 4 +- .../Interop/UnmanagedMethods.cs | 6 +-- src/Windows/Avalonia.Win32/OleDragSource.cs | 9 ++-- src/Windows/Avalonia.Win32/OleDropTarget.cs | 43 +++++++++++++++---- 8 files changed, 65 insertions(+), 32 deletions(-) diff --git a/src/Avalonia.Controls/Platform/InProcessDragSource.cs b/src/Avalonia.Controls/Platform/InProcessDragSource.cs index e136efe2a9..adbd1632b7 100644 --- a/src/Avalonia.Controls/Platform/InProcessDragSource.cs +++ b/src/Avalonia.Controls/Platform/InProcessDragSource.cs @@ -60,7 +60,7 @@ namespace Avalonia.Platform { _lastPosition = pt; - RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData, _allowedEffects); + RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData, _allowedEffects, modifiers); var tl = root.GetSelfAndVisualAncestors().OfType().FirstOrDefault(); tl.PlatformImpl.Input(rawEvent); diff --git a/src/Avalonia.Input/DragDropDevice.cs b/src/Avalonia.Input/DragDropDevice.cs index 9fb100371f..0692b21c66 100644 --- a/src/Avalonia.Input/DragDropDevice.cs +++ b/src/Avalonia.Input/DragDropDevice.cs @@ -19,11 +19,11 @@ namespace Avalonia.Input return null; } - private DragDropEffects RaiseDragEvent(Interactive target, IInputElement inputRoot, Point point, RoutedEvent routedEvent, DragDropEffects operation, IDataObject data) + private DragDropEffects RaiseDragEvent(Interactive target, IInputElement inputRoot, Point point, RoutedEvent routedEvent, DragDropEffects operation, IDataObject data, InputModifiers modifiers) { if (target == null) return DragDropEffects.None; - var args = new DragEventArgs(routedEvent, data, target, inputRoot.TranslatePoint(point, target)) + var args = new DragEventArgs(routedEvent, data, target, inputRoot.TranslatePoint(point, target), modifiers) { RoutedEvent = routedEvent, DragEffects = operation @@ -32,24 +32,24 @@ namespace Avalonia.Input return args.DragEffects; } - private DragDropEffects DragEnter(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects) + private DragDropEffects DragEnter(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects, InputModifiers modifiers) { _lastTarget = GetTarget(inputRoot, point); - return RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DragEnterEvent, effects, data); + return RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DragEnterEvent, effects, data, modifiers); } - private DragDropEffects DragOver(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects) + private DragDropEffects DragOver(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects, InputModifiers modifiers) { var target = GetTarget(inputRoot, point); if (target == _lastTarget) - return RaiseDragEvent(target, inputRoot, point, DragDrop.DragOverEvent, effects, data); + return RaiseDragEvent(target, inputRoot, point, DragDrop.DragOverEvent, effects, data, modifiers); try { if (_lastTarget != null) _lastTarget.RaiseEvent(new RoutedEventArgs(DragDrop.DragLeaveEvent)); - return RaiseDragEvent(target, inputRoot, point, DragDrop.DragEnterEvent, effects, data); + return RaiseDragEvent(target, inputRoot, point, DragDrop.DragEnterEvent, effects, data, modifiers); } finally { @@ -71,11 +71,11 @@ namespace Avalonia.Input } } - private DragDropEffects Drop(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects) + private DragDropEffects Drop(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects, InputModifiers modifiers) { try { - return RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DropEvent, effects, data); + return RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DropEvent, effects, data, modifiers); } finally { @@ -94,16 +94,16 @@ namespace Avalonia.Input switch (e.Type) { case RawDragEventType.DragEnter: - e.Effects = DragEnter(e.InputRoot, e.Location, e.Data, e.Effects); + e.Effects = DragEnter(e.InputRoot, e.Location, e.Data, e.Effects, e.Modifiers); break; case RawDragEventType.DragOver: - e.Effects = DragOver(e.InputRoot, e.Location, e.Data, e.Effects); + e.Effects = DragOver(e.InputRoot, e.Location, e.Data, e.Effects, e.Modifiers); break; case RawDragEventType.DragLeave: DragLeave(e.InputRoot); break; case RawDragEventType.Drop: - e.Effects = Drop(e.InputRoot, e.Location, e.Data, e.Effects); + e.Effects = Drop(e.InputRoot, e.Location, e.Data, e.Effects, e.Modifiers); break; } } diff --git a/src/Avalonia.Input/DragEventArgs.cs b/src/Avalonia.Input/DragEventArgs.cs index 669fd846a1..915ee4ee5c 100644 --- a/src/Avalonia.Input/DragEventArgs.cs +++ b/src/Avalonia.Input/DragEventArgs.cs @@ -13,6 +13,8 @@ namespace Avalonia.Input public IDataObject Data { get; private set; } + public InputModifiers Modifiers { get; private set; } + public Point GetPosition(IVisual relativeTo) { var point = new Point(0, 0); @@ -29,12 +31,13 @@ namespace Avalonia.Input return point; } - public DragEventArgs(RoutedEvent routedEvent, IDataObject data, Interactive target, Point targetLocation) + public DragEventArgs(RoutedEvent routedEvent, IDataObject data, Interactive target, Point targetLocation, InputModifiers modifiers) : base(routedEvent) { this.Data = data; this._target = target; this._targetLocation = targetLocation; + this.Modifiers = modifiers; } } diff --git a/src/Avalonia.Input/Raw/RawDragEvent.cs b/src/Avalonia.Input/Raw/RawDragEvent.cs index 49125b4c07..80653b4873 100644 --- a/src/Avalonia.Input/Raw/RawDragEvent.cs +++ b/src/Avalonia.Input/Raw/RawDragEvent.cs @@ -11,9 +11,10 @@ namespace Avalonia.Input.Raw public IDataObject Data { get; } public DragDropEffects Effects { get; set; } public RawDragEventType Type { get; } + public InputModifiers Modifiers { get; } public RawDragEvent(IDragDropDevice inputDevice, RawDragEventType type, - IInputElement inputRoot, Point location, IDataObject data, DragDropEffects effects) + IInputElement inputRoot, Point location, IDataObject data, DragDropEffects effects, InputModifiers modifiers) :base(inputDevice, 0) { Type = type; @@ -21,6 +22,7 @@ namespace Avalonia.Input.Raw Location = location; Data = data; Effects = effects; + Modifiers = modifiers; } } } \ No newline at end of file diff --git a/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs b/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs index db7f29f05b..f661cc0450 100644 --- a/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs +++ b/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs @@ -164,8 +164,10 @@ namespace Avalonia.MonoMac var dragOp = DraggingInfo.ConvertDragOperation(sender.DraggingSourceOperationMask); DraggingInfo info = new DraggingInfo(sender); + var pt = TranslateLocalPoint(info.Location); - var args = new RawDragEvent(dragDevice, type, root, pt, info, dragOp); + // TODO: Find a way to obtain the InputModifiers... + var args = new RawDragEvent(dragDevice, type, root, pt, info, dragOp, InputModifiers.None); input(args); return DraggingInfo.ConvertDragOperation(args.Effects); } diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 5c24aa1c69..b115f2af4e 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -218,6 +218,8 @@ namespace Avalonia.Win32.Interop MK_SHIFT = 0x0004, + MK_ALT = 0x0020, + MK_XBUTTON1 = 0x0020, MK_XBUTTON2 = 0x0040 @@ -1381,9 +1383,7 @@ namespace Avalonia.Win32.Interop Link = 4, Scroll = -2147483648, } - - - + [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("00000122-0000-0000-C000-000000000046")] diff --git a/src/Windows/Avalonia.Win32/OleDragSource.cs b/src/Windows/Avalonia.Win32/OleDragSource.cs index 522014abc0..a87995952a 100644 --- a/src/Windows/Avalonia.Win32/OleDragSource.cs +++ b/src/Windows/Avalonia.Win32/OleDragSource.cs @@ -11,10 +11,11 @@ namespace Avalonia.Win32 private const int DRAGDROP_S_DROP = 0x00040100; private const int DRAGDROP_S_CANCEL = 0x00040101; - private const int KEYSTATE_LEFTMB = 1; - private const int KEYSTATE_MIDDLEMB = 16; - private const int KEYSTATE_RIGHTMB = 2; - private static readonly int[] MOUSE_BUTTONS = new int[] { KEYSTATE_LEFTMB, KEYSTATE_MIDDLEMB, KEYSTATE_RIGHTMB }; + private static readonly int[] MOUSE_BUTTONS = new int[] { + (int)UnmanagedMethods.ModifierKeys.MK_LBUTTON, + (int)UnmanagedMethods.ModifierKeys.MK_MBUTTON, + (int)UnmanagedMethods.ModifierKeys.MK_RBUTTON + }; public int QueryContinueDrag(int fEscapePressed, int grfKeyState) { diff --git a/src/Windows/Avalonia.Win32/OleDropTarget.cs b/src/Windows/Avalonia.Win32/OleDropTarget.cs index 973564a3d1..6a10cc7e98 100644 --- a/src/Windows/Avalonia.Win32/OleDropTarget.cs +++ b/src/Windows/Avalonia.Win32/OleDropTarget.cs @@ -45,6 +45,26 @@ namespace Avalonia.Win32 return result; } + private static InputModifiers ConvertKeyState(int grfKeyState) + { + InputModifiers modifiers = InputModifiers.None; + var state = (UnmanagedMethods.ModifierKeys)grfKeyState; + + if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_LBUTTON)) + modifiers |= InputModifiers.LeftMouseButton; + if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_MBUTTON)) + modifiers |= InputModifiers.MiddleMouseButton; + if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_RBUTTON)) + modifiers |= InputModifiers.RightMouseButton; + if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_SHIFT)) + modifiers |= InputModifiers.Shift; + if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_CONTROL)) + modifiers |= InputModifiers.Control; + if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_ALT)) + modifiers |= InputModifiers.Alt; + return modifiers; + } + UnmanagedMethods.HRESULT IDropTarget.DragEnter(IOleDataObject pDataObj, int grfKeyState, long pt, ref DropEffect pdwEffect) { var dispatch = _tl?.Input; @@ -56,13 +76,15 @@ namespace Avalonia.Win32 _currentDrag = pDataObj as IDataObject; if (_currentDrag == null) _currentDrag = new OleDataObject(pDataObj); + var args = new RawDragEvent( _dragDevice, RawDragEventType.DragEnter, _target, GetDragLocation(pt), _currentDrag, - ConvertDropEffect(pdwEffect) + ConvertDropEffect(pdwEffect), + ConvertKeyState(grfKeyState) ); dispatch(args); pdwEffect = ConvertDropEffect(args.Effects); @@ -85,7 +107,8 @@ namespace Avalonia.Win32 _target, GetDragLocation(pt), _currentDrag, - ConvertDropEffect(pdwEffect) + ConvertDropEffect(pdwEffect), + ConvertKeyState(grfKeyState) ); dispatch(args); pdwEffect = ConvertDropEffect(args.Effects); @@ -98,12 +121,13 @@ namespace Avalonia.Win32 try { _tl?.Input(new RawDragEvent( - _dragDevice, - RawDragEventType.DragLeave, - _target, - default(Point), - null, - DragDropEffects.None + _dragDevice, + RawDragEventType.DragLeave, + _target, + default(Point), + null, + DragDropEffects.None, + InputModifiers.None )); return UnmanagedMethods.HRESULT.S_OK; } @@ -134,7 +158,8 @@ namespace Avalonia.Win32 _target, GetDragLocation(pt), _currentDrag, - ConvertDropEffect(pdwEffect) + ConvertDropEffect(pdwEffect), + ConvertKeyState(grfKeyState) ); dispatch(args); pdwEffect = ConvertDropEffect(args.Effects); From 68b6c435aa2a78ce9ea1e8de18a184bc7574d64f Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Sat, 16 Jun 2018 17:43:19 -0500 Subject: [PATCH 2/2] Add MonoMac implementation. --- src/OSX/Avalonia.MonoMac/TopLevelImpl.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs b/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs index f661cc0450..b528d84e4c 100644 --- a/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs +++ b/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs @@ -166,8 +166,7 @@ namespace Avalonia.MonoMac DraggingInfo info = new DraggingInfo(sender); var pt = TranslateLocalPoint(info.Location); - // TODO: Find a way to obtain the InputModifiers... - var args = new RawDragEvent(dragDevice, type, root, pt, info, dragOp, InputModifiers.None); + var args = new RawDragEvent(dragDevice, type, root, pt, info, dragOp, GetModifiers(NSEvent.CurrentModifierFlags)); input(args); return DraggingInfo.ConvertDragOperation(args.Effects); }