Browse Source

Changes after review

pull/7506/head
Max Katz 4 years ago
parent
commit
5e5b8f6ae7
  1. 16
      src/Avalonia.MicroCom/MicroComProxyBase.cs
  2. 10
      src/Windows/Avalonia.Win32/ClipboardImpl.cs
  3. 44
      src/Windows/Avalonia.Win32/DataObject.cs
  4. 8
      src/Windows/Avalonia.Win32/DragSource.cs
  5. 2
      src/Windows/Avalonia.Win32/OleContext.cs
  6. 10
      src/Windows/Avalonia.Win32/OleDataObject.cs
  7. 22
      src/Windows/Avalonia.Win32/OleDropTarget.cs
  8. 1
      src/Windows/Avalonia.Win32/WindowImpl.cs

16
src/Avalonia.MicroCom/MicroComProxyBase.cs

@ -61,6 +61,22 @@ namespace Avalonia.MicroCom
throw new COMException("QueryInterface failed", rv);
}
public bool TryQueryInterface<T>(out T result) where T : IUnknown
{
var guid = MicroComRuntime.GetGuidFor(typeof(T));
var rv = QueryInterface(guid, out var ppv);
if (rv == 0)
{
result = (T)MicroComRuntime.CreateProxyFor(typeof(T), ppv, true);
return true;
}
else
{
result = default;
return false;
}
}
public bool IsDisposed => _nativePointer == IntPtr.Zero;
protected virtual void Dispose(bool disposing)

10
src/Windows/Avalonia.Win32/ClipboardImpl.cs

@ -83,7 +83,7 @@ namespace Avalonia.Win32
while (true)
{
var ptr = MicroCom.MicroComRuntime.GetNativeIntPtr<Win32Com.IDataObject>(wrapper, true);
var ptr = MicroCom.MicroComRuntime.GetNativeIntPtr<Win32Com.IDataObject>(wrapper);
var hr = UnmanagedMethods.OleSetClipboard(ptr);
if (hr == 0)
@ -107,8 +107,8 @@ namespace Avalonia.Win32
if (hr == 0)
{
using var proxy = MicroCom.MicroComRuntime.CreateProxyFor<Win32Com.IDataObject>(dataObject, false);
var wrapper = new OleDataObject(proxy);
using var proxy = MicroCom.MicroComRuntime.CreateProxyFor<Win32Com.IDataObject>(dataObject, true);
using var wrapper = new OleDataObject(proxy);
var formats = wrapper.GetDataFormats().ToArray();
return formats;
}
@ -131,8 +131,8 @@ namespace Avalonia.Win32
if (hr == 0)
{
using var proxy = MicroCom.MicroComRuntime.CreateProxyFor<Win32Com.IDataObject>(dataObject, false);
var wrapper = new OleDataObject(proxy);
using var proxy = MicroCom.MicroComRuntime.CreateProxyFor<Win32Com.IDataObject>(dataObject, true);
using var wrapper = new OleDataObject(proxy);
var rv = wrapper.Get(format);
return rv;
}

44
src/Windows/Avalonia.Win32/DataObject.cs

@ -16,33 +16,43 @@ using IDataObject = Avalonia.Input.IDataObject;
namespace Avalonia.Win32
{
public interface IDisposableDataObject : IDataObject, IDisposable { }
internal static class DataObjectEx
{
public static unsafe IDataObject GetAvaloniaObject(this Win32Com.IDataObject pDataObj)
public static unsafe IDisposableDataObject GetAvaloniaObjectFromCOM(this Win32Com.IDataObject pDataObj)
{
switch (pDataObj)
if (pDataObj is null)
{
throw new ArgumentNullException(nameof(pDataObj));
}
if (pDataObj is IDisposableDataObject disposableDataObject)
{
return disposableDataObject;
}
// If DataObject was created on the our side (drag'n'drop initiated by Avalonia),
// then pDataObj will implement IAvnDataObject interface as well. So we can safely case it back to DataObject.
if (((MicroComProxyBase)pDataObj).TryQueryInterface<Win32Com.IAvnDataObject>(out var avnInterface))
{
using (avnInterface)
{
var ppv = MicroComRuntime.GetNativeIntPtr(avnInterface);
return MicroComRuntime.GetObjectFromCcw(ppv) as DataObject;
}
}
// Otherwise wrap pDataObj into OleDataObject.
else
{
case null:
throw new ArgumentNullException(nameof(pDataObj));
case DataObject avnObj:
return avnObj;
case OleDataObject oleAvnObj:
return oleAvnObj;
default:
var guid = MicroComRuntime.GetGuidFor(typeof(Win32Com.IAvnDataObject));
var rv = ((MicroComProxyBase)pDataObj).QueryInterface(guid, out var ppv);
return rv == 0
? MicroComRuntime.GetObjectFromCcw(ppv) as DataObject
: new OleDataObject(pDataObj);
return new OleDataObject(pDataObj);
}
}
}
internal class DataObject : IDataObject, Win32Com.IAvnDataObject, IMicroComShadowContainer
internal class DataObject : IDisposableDataObject, Win32Com.IAvnDataObject, IMicroComShadowContainer
{
// Compatibility with WinForms + WPF...
internal static readonly byte[] SerializedObjectGUID = new Guid("FD9EA796-3B13-4370-A679-56106BB288FB").ToByteArray();
private static Dictionary<IntPtr, IDataObject> _avnDataObject = new Dictionary<IntPtr, IDataObject>();
class FormatEnumerator : Win32Com.IEnumFORMATETC, IMicroComShadowContainer
{
@ -143,7 +153,7 @@ namespace Avalonia.Win32
public DataObject(IDataObject wrapped)
{
if (_wrapped is DataObject)
if (_wrapped is DataObject || _wrapped is OleDataObject)
{
throw new InvalidOperationException();
}

8
src/Windows/Avalonia.Win32/DragSource.cs

@ -15,12 +15,12 @@ namespace Avalonia.Win32
triggerEvent.Pointer.Capture(null);
var dataObject = new DataObject(data);
var src = new OleDragSource();
using var dataObject = new DataObject(data);
using var src = new OleDragSource();
var allowed = OleDropTarget.ConvertDropEffect(allowedEffects);
var objPtr = MicroCom.MicroComRuntime.GetNativeIntPtr<Win32Com.IDataObject>(dataObject, true);
var srcPtr = MicroCom.MicroComRuntime.GetNativeIntPtr<Win32Com.IDropSource>(src, true);
var objPtr = MicroCom.MicroComRuntime.GetNativeIntPtr<Win32Com.IDataObject>(dataObject);
var srcPtr = MicroCom.MicroComRuntime.GetNativeIntPtr<Win32Com.IDropSource>(src);
UnmanagedMethods.DoDragDrop(objPtr, srcPtr, (int)allowed, out var finalEffect);
return Task.FromResult(OleDropTarget.ConvertDropEffect((Win32Com.DropEffect)finalEffect));

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

@ -47,7 +47,7 @@ namespace Avalonia.Win32
return false;
}
var trgPtr = MicroCom.MicroComRuntime.GetNativeIntPtr(target, false);
var trgPtr = MicroCom.MicroComRuntime.GetNativeIntPtr(target);
return UnmanagedMethods.RegisterDragDrop(hwnd.Handle, trgPtr) == UnmanagedMethods.HRESULT.S_OK;
}

10
src/Windows/Avalonia.Win32/OleDataObject.cs

@ -8,17 +8,18 @@ using System.Runtime.InteropServices.ComTypes;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using Avalonia.Input;
using Avalonia.MicroCom;
using Avalonia.Win32.Interop;
namespace Avalonia.Win32
{
internal class OleDataObject : Avalonia.Input.IDataObject
internal class OleDataObject : IDisposableDataObject
{
private readonly Win32Com.IDataObject _wrapped;
public OleDataObject(Win32Com.IDataObject wrapped)
{
_wrapped = wrapped;
_wrapped = wrapped.CloneReference();
}
public bool Contains(string dataFormat)
@ -183,5 +184,10 @@ namespace Avalonia.Win32
}
return formatsList;
}
public void Dispose()
{
_wrapped.Dispose();
}
}
}

22
src/Windows/Avalonia.Win32/OleDropTarget.cs

@ -3,7 +3,6 @@ using Avalonia.Input.Raw;
using Avalonia.MicroCom;
using Avalonia.Platform;
using Avalonia.Win32.Interop;
using IDataObject = Avalonia.Input.IDataObject;
using DropEffect = Avalonia.Win32.Win32Com.DropEffect;
namespace Avalonia.Win32
@ -14,7 +13,7 @@ namespace Avalonia.Win32
private readonly ITopLevelImpl _tl;
private readonly IDragDropDevice _dragDevice;
private IDataObject _currentDrag = null;
private IDisposableDataObject _currentDrag = null;
public MicroComShadow Shadow { get; set; }
@ -77,7 +76,12 @@ namespace Avalonia.Win32
*pdwEffect= (int)DropEffect.None;
}
_currentDrag = pDataObj.GetAvaloniaObject();
var newDrag = pDataObj.GetAvaloniaObjectFromCOM();
if (_currentDrag != newDrag)
{
_currentDrag?.Dispose();
_currentDrag = newDrag;
}
var args = new RawDragEvent(
_dragDevice,
@ -85,7 +89,7 @@ namespace Avalonia.Win32
_target,
GetDragLocation(pt),
_currentDrag,
ConvertDropEffect((*pdwEffect)),
ConvertDropEffect(*pdwEffect),
ConvertKeyState(grfKeyState)
);
dispatch(args);
@ -129,6 +133,7 @@ namespace Avalonia.Win32
}
finally
{
_currentDrag?.Dispose();
_currentDrag = null;
}
}
@ -143,7 +148,12 @@ namespace Avalonia.Win32
*pdwEffect = (int)DropEffect.None;
}
_currentDrag = pDataObj.GetAvaloniaObject();
var newDrag = pDataObj.GetAvaloniaObjectFromCOM();
if (_currentDrag != newDrag)
{
_currentDrag?.Dispose();
_currentDrag = newDrag;
}
var args = new RawDragEvent(
_dragDevice,
@ -159,6 +169,7 @@ namespace Avalonia.Win32
}
finally
{
_currentDrag?.Dispose();
_currentDrag = null;
}
}
@ -171,6 +182,7 @@ namespace Avalonia.Win32
public void Dispose()
{
_currentDrag?.Dispose();
}
public void OnReferencedFromNative()

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

@ -529,6 +529,7 @@ namespace Avalonia.Win32
if (_dropTarget != null)
{
OleContext.Current?.UnregisterDragDrop(Handle);
_dropTarget.Dispose();
_dropTarget = null;
}

Loading…
Cancel
Save