Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,7 @@ public DataObject()
/// </summary>
public DataObject(object data)
{
if (data is DataObject dataObject)
{
_innerData = dataObject._innerData;
}
else if (data is IDataObject iDataObject)
if (data is IDataObject iDataObject)
{
_innerData = Composition.CreateFromWinFormsDataObject(iDataObject);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -699,4 +699,33 @@ public void Clipboard_SetDataObject_Text()
byte[] array = stream.ToArray();
array.Should().BeEquivalentTo("Hello, World!\0"u8.ToArray());
}

[WinFormsFact]
public void Clipboard_DerivedDataObject_DataPresent()
{
// https://github.com/dotnet/winforms/issues/12789
SomeDataObject data = new();

// This was provided as a workaround for the above and should not break, but should
// also work without it.
data.SetData(SomeDataObject.Format, data);

Clipboard.SetDataObject(data);
Clipboard.ContainsData(SomeDataObject.Format).Should().BeTrue();
Clipboard.GetDataObject()!.GetDataPresent(SomeDataObject.Format).Should().BeTrue();

data = new();
Clipboard.SetDataObject(data);
Clipboard.ContainsData(SomeDataObject.Format).Should().BeTrue();
Clipboard.GetDataObject()!.GetDataPresent(SomeDataObject.Format).Should().BeTrue();
}

public class SomeDataObject : DataObject
{
public static string Format => "SomeDataObjectId";
public override string[] GetFormats() => [Format];

public override bool GetDataPresent(string format, bool autoConvert)
=> format == Format || base.GetDataPresent(format, autoConvert);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2657,4 +2657,77 @@ public unsafe void DataObject_ComTypesIDataObject_MockRoundTrip_IsWrapped()
IDataObject outData = dropTargetAccessor.CreateDelegate<CreateWinFormsDataObjectForOutgoingDropData>()(inDataPtr);
outData.Should().BeSameAs(inData);
}

[Fact]
public void DataObject_CreateFromDataObject_DoesNotUnwrapDataStore()
{
// The inner data should not have it's data store unwrapped.
DataObject dataObject = new();
DataObject wrapped = new(dataObject);
DataObject.Composition composition = wrapped.TestAccessor().Dynamic._innerData;
IDataObject original = composition.TestAccessor().Dynamic._winFormsDataObject;
original.Should().BeSameAs(dataObject);
}

[Fact]
public void DataObject_CreateFromDataObject_VirtualsAreCalled()
{
Mock<DataObject> mock = new(MockBehavior.Loose);
DataObject wrapped = new(mock.Object);

wrapped.GetData("Foo", false);
mock.Verify(o => o.GetData("Foo", false), Times.Once());
mock.VerifyNoOtherCalls();
mock.Reset();

wrapped.GetData("Foo");
mock.Verify(o => o.GetData("Foo", true), Times.Once());
mock.VerifyNoOtherCalls();
mock.Reset();

wrapped.GetData(typeof(string));
mock.Verify(o => o.GetData("System.String", true), Times.Once());
mock.VerifyNoOtherCalls();
mock.Reset();

wrapped.GetDataPresent("Foo", false);
mock.Verify(o => o.GetDataPresent("Foo", false), Times.Once());
mock.VerifyNoOtherCalls();
mock.Reset();

wrapped.GetDataPresent("Foo");
mock.Verify(o => o.GetDataPresent("Foo", true), Times.Once());
mock.VerifyNoOtherCalls();
mock.Reset();

wrapped.GetDataPresent(typeof(string));
mock.Verify(o => o.GetDataPresent("System.String", true), Times.Once());
mock.VerifyNoOtherCalls();
mock.Reset();

wrapped.GetFormats(false);
mock.Verify(o => o.GetFormats(false), Times.Once());
mock.VerifyNoOtherCalls();
mock.Reset();

wrapped.GetFormats();
mock.Verify(o => o.GetFormats(true), Times.Once());
mock.VerifyNoOtherCalls();
mock.Reset();

wrapped.SetData("Foo", "Bar");
mock.Verify(o => o.SetData("Foo", "Bar"), Times.Once());
mock.VerifyNoOtherCalls();
mock.Reset();

wrapped.SetData(typeof(string), "Bar");
mock.Verify(o => o.SetData(typeof(string), "Bar"), Times.Once());
mock.VerifyNoOtherCalls();
mock.Reset();

wrapped.SetData("Bar");
mock.Verify(o => o.SetData("Bar"), Times.Once());
mock.VerifyNoOtherCalls();
mock.Reset();
}
}