From 2c53bf4750618490031e0e6cb3c5ddc3810f137e Mon Sep 17 00:00:00 2001 From: boombuler Date: Mon, 7 May 2018 07:58:31 +0200 Subject: [PATCH 1/5] 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 e7d44181b9da285ff5cf19a6ecd172a960e7cf3b Mon Sep 17 00:00:00 2001 From: Karnah Date: Fri, 11 May 2018 12:04:38 +0500 Subject: [PATCH 2/5] 1448: Fixed Center and Right alignment selection text --- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 29 ++++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index f22722a0b5..923fe896f9 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -36,8 +36,8 @@ namespace Avalonia.Skia //Paint.TextEncoding = SKTextEncoding.Utf8; _paint.TextEncoding = SKTextEncoding.Utf16; _paint.IsStroke = false; - _paint.IsAntialias = true; - _paint.LcdRenderText = true; + _paint.IsAntialias = true; + _paint.LcdRenderText = true; _paint.SubpixelText = true; _paint.Typeface = skiaTypeface; _paint.TextSize = (float)(typeface?.FontSize ?? 12); @@ -226,7 +226,26 @@ namespace Avalonia.Skia { float currX = x; string subStr; + float measure; int len; + float factor; + switch (paint.TextAlign) + { + case SKTextAlign.Left: + factor = 0; + break; + case SKTextAlign.Center: + factor = 0.5f; + break; + case SKTextAlign.Right: + factor = 1; + break; + default: + throw new ArgumentOutOfRangeException(); + } + + var textLine = Text.Substring(line.Start, line.Length); + currX -= paint.MeasureText(textLine) * factor; for (int i = line.Start; i < line.Start + line.Length;) { @@ -244,13 +263,15 @@ namespace Avalonia.Skia } subStr = Text.Substring(i, len); + measure = paint.MeasureText(subStr); + currX += measure * factor; ApplyWrapperTo(ref currentPaint, currentWrapper, ref currd, paint, canUseLcdRendering); - + canvas.DrawText(subStr, currX, origin.Y + line.Top + _lineOffset, paint); i += len; - currX += paint.MeasureText(subStr); + currX += measure * (1 - factor); } } } From 903bdf9035063ebf803b23674191323eb4a75e07 Mon Sep 17 00:00:00 2001 From: Karnah Date: Fri, 11 May 2018 12:20:24 +0500 Subject: [PATCH 3/5] Fix AvaloniaFormattedTextLine line width --- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index 923fe896f9..7d39c71b2f 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -559,11 +559,11 @@ namespace Avalonia.Skia measured = LineBreak(Text, curOff, length, _paint, constraint, out trailingnumber); AvaloniaFormattedTextLine line = new AvaloniaFormattedTextLine(); + line.Start = curOff; line.TextLength = measured; subString = Text.Substring(line.Start, line.TextLength); lineWidth = _paint.MeasureText(subString); - line.Start = curOff; line.Length = measured - trailingnumber; line.Width = lineWidth; line.Height = _lineHeight; From 68b6c435aa2a78ce9ea1e8de18a184bc7574d64f Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Sat, 16 Jun 2018 17:43:19 -0500 Subject: [PATCH 4/5] 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); } From e0a626b29ec3eb5ad7b786ccbf12321177df1938 Mon Sep 17 00:00:00 2001 From: "vsevolod.pilipenko" Date: Sun, 17 Jun 2018 18:59:47 +0500 Subject: [PATCH 5/5] Removed duplicated code --- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index bb46ffdf74..9c18d52cea 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -584,7 +584,6 @@ namespace Avalonia.Skia AvaloniaFormattedTextLine line = new AvaloniaFormattedTextLine(); line.Start = curOff; line.TextLength = measured; - line.Start = curOff; subString = Text.Substring(line.Start, line.TextLength); lineWidth = _paint.MeasureText(subString); line.Length = measured - trailingnumber;