Skip to content

Commit 1f40464

Browse files
authored
Clipboard rework (#19347)
* New clipboard with IDataTransfer * Move legacy format handling to DataObject wrappers * macOS clipboard rework * Browser clipboard rework * Android clipboard rework * iOS new clipboard * X11 clipboard rework * Simplify IDataTransfer API * Simplify IClipboardImpl API * Add DataFormat documentation * Make DataFormat.SystemName platform specific * Fix clipboard/DnD samples * Fix native clipboard UTI conversion * Adjust IDataTransfer namespaces * Add Obsolete attributes to IDataObject related methods * Better API for DataTransferItem * Tizen clipboard rework * Add missing clipboard extension methods * Split IDataTransferItem into IAsyncDataTransferItem and ISyncDataTransferItem * Rename back ISyncDataTransfer to IDataTransfer * Added IClipboard API suppressions * Make IPlatformDragSource NotClientImplementable * Rename DataFormatKinds * Added DataTransferItem.CreateText/File * Implemented typed DataFormat<T> * Fix X11 text/uri-list encoding * Add API suppressions * Adjust ClipboardUriListHelper stream ownership * Fix legacy clipboard BinaryFormatter deserialization * Fix macOS build
1 parent d060f96 commit 1f40464

File tree

137 files changed

+5920
-1881
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+5920
-1881
lines changed

Avalonia.sln

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,12 @@ EndProject
3838
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}"
3939
ProjectSection(SolutionItems) = preProject
4040
.editorconfig = .editorconfig
41+
src\Shared\CallerArgumentExpressionAttribute.cs = src\Shared\CallerArgumentExpressionAttribute.cs
4142
src\Shared\IsExternalInit.cs = src\Shared\IsExternalInit.cs
4243
src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
43-
src\Shared\NullableAttributes.cs = src\Shared\NullableAttributes.cs
4444
src\Shared\SourceGeneratorAttributes.cs = src\Shared\SourceGeneratorAttributes.cs
4545
src\Shared\StringCompatibilityExtensions.cs = src\Shared\StringCompatibilityExtensions.cs
46+
src\Shared\StreamCompatibilityExtensions.cs = src\Shared\StreamCompatibilityExtensions.cs
4647
EndProjectSection
4748
EndProject
4849
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}"

api/Avalonia.nupkg.xml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids -->
3+
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
4+
<Suppression>
5+
<DiagnosticId>CP0006</DiagnosticId>
6+
<Target>M:Avalonia.Input.Platform.IClipboard.SetDataAsync(Avalonia.Input.IAsyncDataTransfer)</Target>
7+
<Left>baseline/Avalonia/lib/net6.0/Avalonia.Base.dll</Left>
8+
<Right>current/Avalonia/lib/net6.0/Avalonia.Base.dll</Right>
9+
</Suppression>
10+
<Suppression>
11+
<DiagnosticId>CP0006</DiagnosticId>
12+
<Target>M:Avalonia.Input.Platform.IClipboard.TryGetDataAsync</Target>
13+
<Left>baseline/Avalonia/lib/net6.0/Avalonia.Base.dll</Left>
14+
<Right>current/Avalonia/lib/net6.0/Avalonia.Base.dll</Right>
15+
</Suppression>
16+
<Suppression>
17+
<DiagnosticId>CP0006</DiagnosticId>
18+
<Target>M:Avalonia.Input.Platform.IClipboard.TryGetInProcessDataAsync</Target>
19+
<Left>baseline/Avalonia/lib/net6.0/Avalonia.Base.dll</Left>
20+
<Right>current/Avalonia/lib/net6.0/Avalonia.Base.dll</Right>
21+
</Suppression>
22+
<Suppression>
23+
<DiagnosticId>CP0006</DiagnosticId>
24+
<Target>M:Avalonia.Input.Platform.IPlatformDragSource.DoDragDropAsync(Avalonia.Input.PointerEventArgs,Avalonia.Input.IDataTransfer,Avalonia.Input.DragDropEffects)</Target>
25+
<Left>baseline/Avalonia/lib/net6.0/Avalonia.Base.dll</Left>
26+
<Right>current/Avalonia/lib/net6.0/Avalonia.Base.dll</Right>
27+
</Suppression>
28+
<Suppression>
29+
<DiagnosticId>CP0006</DiagnosticId>
30+
<Target>M:Avalonia.Input.Platform.IClipboard.SetDataAsync(Avalonia.Input.IAsyncDataTransfer)</Target>
31+
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
32+
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
33+
</Suppression>
34+
<Suppression>
35+
<DiagnosticId>CP0006</DiagnosticId>
36+
<Target>M:Avalonia.Input.Platform.IClipboard.TryGetDataAsync</Target>
37+
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
38+
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
39+
</Suppression>
40+
<Suppression>
41+
<DiagnosticId>CP0006</DiagnosticId>
42+
<Target>M:Avalonia.Input.Platform.IClipboard.TryGetInProcessDataAsync</Target>
43+
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
44+
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
45+
</Suppression>
46+
<Suppression>
47+
<DiagnosticId>CP0006</DiagnosticId>
48+
<Target>M:Avalonia.Input.Platform.IPlatformDragSource.DoDragDropAsync(Avalonia.Input.PointerEventArgs,Avalonia.Input.IDataTransfer,Avalonia.Input.DragDropEffects)</Target>
49+
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
50+
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
51+
</Suppression>
52+
<Suppression>
53+
<DiagnosticId>CP0006</DiagnosticId>
54+
<Target>M:Avalonia.Input.Platform.IClipboard.SetDataAsync(Avalonia.Input.IAsyncDataTransfer)</Target>
55+
<Left>baseline/Avalonia/lib/netstandard2.0/Avalonia.Base.dll</Left>
56+
<Right>current/Avalonia/lib/netstandard2.0/Avalonia.Base.dll</Right>
57+
</Suppression>
58+
<Suppression>
59+
<DiagnosticId>CP0006</DiagnosticId>
60+
<Target>M:Avalonia.Input.Platform.IClipboard.TryGetDataAsync</Target>
61+
<Left>baseline/Avalonia/lib/netstandard2.0/Avalonia.Base.dll</Left>
62+
<Right>current/Avalonia/lib/netstandard2.0/Avalonia.Base.dll</Right>
63+
</Suppression>
64+
<Suppression>
65+
<DiagnosticId>CP0006</DiagnosticId>
66+
<Target>M:Avalonia.Input.Platform.IClipboard.TryGetInProcessDataAsync</Target>
67+
<Left>baseline/Avalonia/lib/netstandard2.0/Avalonia.Base.dll</Left>
68+
<Right>current/Avalonia/lib/netstandard2.0/Avalonia.Base.dll</Right>
69+
</Suppression>
70+
<Suppression>
71+
<DiagnosticId>CP0006</DiagnosticId>
72+
<Target>M:Avalonia.Input.Platform.IPlatformDragSource.DoDragDropAsync(Avalonia.Input.PointerEventArgs,Avalonia.Input.IDataTransfer,Avalonia.Input.DragDropEffects)</Target>
73+
<Left>baseline/Avalonia/lib/netstandard2.0/Avalonia.Base.dll</Left>
74+
<Right>current/Avalonia/lib/netstandard2.0/Avalonia.Base.dll</Right>
75+
</Suppression>
76+
</Suppressions>

native/Avalonia.Native/inc/com.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ typedef DWORD ULONG;
2828
#define E_UNEXPECTED 0x8000FFFFL
2929
#define E_HANDLE 0x80070006L
3030
#define E_INVALIDARG 0x80070057L
31-
#define COR_E_INVALIDOPERATION 0x80131509L
31+
#define COR_E_INVALIDOPERATION 0x80131509L
32+
#define COR_E_OBJECTDISPOSED 0x80131622L
3233

3334
struct IUnknown
3435
{

native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
EDF8CDCD2964CB01001EE34F /* PlatformSettings.mm in Sources */ = {isa = PBXBuildFile; fileRef = EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */; };
6464
F10084842BFF1F9E0024303E /* TopLevelImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = F10084832BFF1F9E0024303E /* TopLevelImpl.h */; };
6565
F10084862BFF1FB40024303E /* TopLevelImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = F10084852BFF1FB40024303E /* TopLevelImpl.mm */; };
66+
F931F8682E2D43A7004E081E /* clipboard.h in Headers */ = {isa = PBXBuildFile; fileRef = F931F8672E2D43A4004E081E /* clipboard.h */; };
6667
/* End PBXBuildFile section */
6768

6869
/* Begin PBXFileReference section */
@@ -130,6 +131,7 @@
130131
EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSettings.mm; sourceTree = "<group>"; };
131132
F10084832BFF1F9E0024303E /* TopLevelImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLevelImpl.h; sourceTree = "<group>"; };
132133
F10084852BFF1FB40024303E /* TopLevelImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TopLevelImpl.mm; sourceTree = "<group>"; };
134+
F931F8672E2D43A4004E081E /* clipboard.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = clipboard.h; sourceTree = "<group>"; };
133135
/* End PBXFileReference section */
134136

135137
/* Begin PBXFrameworksBuildPhase section */
@@ -189,6 +191,7 @@
189191
1AFD334023E03C4F0042899B /* controlhost.mm */,
190192
5BF943652167AD1D009CAE35 /* cursor.h */,
191193
5B21A981216530F500CEE36E /* cursor.mm */,
194+
F931F8672E2D43A4004E081E /* clipboard.h */,
192195
5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */,
193196
1A465D0F246AB61600C5858B /* dnd.mm */,
194197
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */,
@@ -246,6 +249,7 @@
246249
files = (
247250
37155CE4233C00EB0034DCE9 /* menu.h in Headers */,
248251
F10084842BFF1F9E0024303E /* TopLevelImpl.h in Headers */,
252+
F931F8682E2D43A7004E081E /* clipboard.h in Headers */,
249253
BC11A5BE2608D58F0017BAD0 /* automation.h in Headers */,
250254
183916173528EC2737DBE5E1 /* WindowBaseImpl.h in Headers */,
251255
1839171DCC651B0638603AC4 /* INSWindowHolder.h in Headers */,

native/Avalonia.Native/src/OSX/AvnView.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ - (NSDragOperation)triggerAvnDragEvent: (AvnDragEventType) type info: (id <NSDra
868868
return NSDragOperationNone;
869869
int reffects = (int)parent->TopLevelEvents
870870
->DragEvent(type, point, modifiers, effects,
871-
CreateClipboard([info draggingPasteboard], nil),
871+
CreateClipboard([info draggingPasteboard]),
872872
GetAvnDataObjectHandleFromDraggingInfo(info));
873873

874874
NSDragOperation ret = static_cast<NSDragOperation>(0);

native/Avalonia.Native/src/OSX/StorageProvider.mm

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,35 @@ virtual void SaveFileDialog (IAvnWindow* parentWindowHandle,
355355
}
356356
}
357357

358+
virtual HRESULT TryResolveFileReferenceUri(IAvnString* fileUriStr, IAvnString** ret) override {
359+
if (ret == nullptr)
360+
return E_POINTER;
361+
362+
if (fileUriStr == nullptr)
363+
{
364+
*ret = nullptr;
365+
return S_OK;
366+
}
367+
368+
auto fileUri = [NSURL URLWithString:GetNSStringAndRelease(fileUriStr)];
369+
if (fileUri == nil)
370+
{
371+
*ret = nullptr;
372+
return S_OK;
373+
}
374+
375+
auto filePathUri = [fileUri filePathURL];
376+
if (fileUri == nil)
377+
{
378+
*ret = nullptr;
379+
return S_OK;
380+
}
381+
382+
*ret = CreateAvnString([filePathUri absoluteString]);
383+
return S_OK;
384+
}
385+
386+
358387
private:
359388
NSView* CreateAccessoryView() {
360389
// The label. Add attributes per-OS to match the labels that macOS uses.

native/Avalonia.Native/src/OSX/TopLevelImpl.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,13 @@ class TopLevelImpl : public virtual ComObject,
6161

6262
virtual HRESULT GetCurrentDisplayId (CGDirectDisplayID* ret) override;
6363

64-
virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
65-
IAvnClipboard* clipboard, IAvnDndResultCallback* cb, void* sourceHandle) override;
64+
virtual HRESULT BeginDragAndDropOperation(
65+
AvnDragDropEffects effects,
66+
AvnPoint point,
67+
IAvnClipboardDataSource* source,
68+
IAvnDndResultCallback* callback,
69+
void* sourceHandle) override;
70+
6671
protected:
6772
NSCursor *cursor;
6873
virtual void UpdateAppearance();

native/Avalonia.Native/src/OSX/TopLevelImpl.mm

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "AvnTextInputMethod.h"
88
#include "AvnView.h"
99
#include "common.h"
10+
#include "clipboard.h"
1011

1112
TopLevelImpl::~TopLevelImpl() {
1213
View = nullptr;
@@ -272,13 +273,15 @@
272273

273274
}
274275

275-
HRESULT TopLevelImpl::BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point, IAvnClipboard *clipboard, IAvnDndResultCallback *cb, void *sourceHandle) {
276+
HRESULT TopLevelImpl::BeginDragAndDropOperation(
277+
AvnDragDropEffects effects,
278+
AvnPoint point,
279+
IAvnClipboardDataSource* source,
280+
IAvnDndResultCallback* callback,
281+
void* sourceHandle)
282+
{
276283
START_COM_CALL;
277284

278-
auto item = TryGetPasteboardItem(clipboard);
279-
[item setString:@"" forType:GetAvnCustomDataType()];
280-
if (item == nil)
281-
return E_INVALIDARG;
282285
if (View == NULL)
283286
return E_FAIL;
284287

@@ -301,11 +304,19 @@
301304
}
302305
}
303306

304-
auto dragItem = [[NSDraggingItem alloc] initWithPasteboardWriter:item];
305-
307+
auto itemCount = source->GetItemCount();
308+
auto draggingItems = [NSMutableArray<NSDraggingItem*> arrayWithCapacity:itemCount];
306309
auto dragItemImage = [NSImage imageNamed:NSImageNameMultipleDocuments];
307310
NSRect dragItemRect = {(float) point.X, (float) point.Y, [dragItemImage size].width, [dragItemImage size].height};
308-
[dragItem setDraggingFrame:dragItemRect contents:dragItemImage];
311+
312+
for (auto i = 0; i < itemCount; ++i)
313+
{
314+
auto item = source->GetItem(i);
315+
auto writeableItem = [[WriteableClipboardItem alloc] initWithItem:item source:source];
316+
auto draggingItem = [[NSDraggingItem alloc] initWithPasteboardWriter:writeableItem];
317+
[draggingItem setDraggingFrame:dragItemRect contents:dragItemImage];
318+
[draggingItems addObject:draggingItem];
319+
}
309320

310321
int op = 0;
311322
int ieffects = (int) effects;
@@ -315,8 +326,10 @@
315326
op |= NSDragOperationLink;
316327
if ((ieffects & (int) AvnDragDropEffects::Move) != 0)
317328
op |= NSDragOperationMove;
318-
[View beginDraggingSessionWithItems:@[dragItem] event:nsevent
319-
source:CreateDraggingSource((NSDragOperation) op, cb, sourceHandle)];
329+
330+
[View beginDraggingSessionWithItems:draggingItems
331+
event:nsevent
332+
source:CreateDraggingSource((NSDragOperation) op, callback, sourceHandle)];
320333
return S_OK;
321334
}
322335

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
3+
#include "common.h"
4+
5+
@interface WriteableClipboardItem : NSObject <NSPasteboardWriting>
6+
- (nonnull instancetype) initWithItem:(nonnull IAvnClipboardDataItem*)item source:(nonnull IAvnClipboardDataSource*)source;
7+
@end

0 commit comments

Comments
 (0)