Skip to content

Commit 337a56f

Browse files
authored
Throw ObjectDisposedException for ClipboardImpl/ClipboardDataObject (#17472)
1 parent 0fdd84f commit 337a56f

File tree

1 file changed

+41
-28
lines changed

1 file changed

+41
-28
lines changed

src/Avalonia.Native/ClipboardImpl.cs

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System;
1+
#nullable enable
2+
3+
using System;
24
using System.Collections.Generic;
35
using System.Linq;
46
using System.Threading.Tasks;
@@ -9,13 +11,12 @@
911
using Avalonia.Native.Interop;
1012
using Avalonia.Platform.Storage;
1113
using Avalonia.Platform.Storage.FileIO;
12-
using MicroCom.Runtime;
1314

1415
namespace Avalonia.Native
1516
{
1617
class ClipboardImpl : IClipboard, IDisposable
1718
{
18-
private IAvnClipboard _native;
19+
private IAvnClipboard? _native;
1920

2021
// TODO hide native types behind IAvnClipboard abstraction, so managed side won't depend on macOS.
2122
private const string NSPasteboardTypeString = "public.utf8-plain-text";
@@ -26,33 +27,38 @@ public ClipboardImpl(IAvnClipboard native)
2627
_native = native;
2728
}
2829

30+
private IAvnClipboard Native
31+
=> _native ?? throw new ObjectDisposedException(nameof(ClipboardImpl));
32+
2933
public Task ClearAsync()
3034
{
31-
_native.Clear();
35+
Native.Clear();
3236

3337
return Task.CompletedTask;
3438
}
3539

36-
public Task<string> GetTextAsync()
40+
public Task<string?> GetTextAsync()
3741
{
38-
using (var text = _native.GetText(NSPasteboardTypeString))
39-
return Task.FromResult(text.String);
42+
using (var text = Native.GetText(NSPasteboardTypeString))
43+
return Task.FromResult<string?>(text.String);
4044
}
4145

42-
public unsafe Task SetTextAsync(string text)
46+
public Task SetTextAsync(string? text)
4347
{
44-
_native.Clear();
48+
var native = Native;
49+
50+
native.Clear();
4551

4652
if (text != null)
47-
_native.SetText(NSPasteboardTypeString, text);
53+
native.SetText(NSPasteboardTypeString, text);
4854

4955
return Task.CompletedTask;
5056
}
5157

5258
public IEnumerable<string> GetFormats()
5359
{
5460
var rv = new HashSet<string>();
55-
using (var formats = _native.ObtainFormats())
61+
using (var formats = Native.ObtainFormats())
5662
{
5763
var cnt = formats.Count;
5864
for (uint c = 0; c < cnt; c++)
@@ -81,27 +87,31 @@ public void Dispose()
8187
_native = null;
8288
}
8389

84-
public IEnumerable<string> GetFileNames()
90+
public IEnumerable<string>? GetFileNames()
8591
{
86-
using (var strings = _native.GetStrings(NSFilenamesPboardType))
92+
using (var strings = Native.GetStrings(NSFilenamesPboardType))
8793
return strings?.ToStringArray();
8894
}
8995

90-
public IEnumerable<IStorageItem> GetFiles()
96+
public IEnumerable<IStorageItem>? GetFiles()
9197
{
9298
var storageApi = (StorageProviderApi)AvaloniaLocator.Current.GetRequiredService<IStorageProviderFactory>();
9399

94100
// TODO: use non-deprecated AppKit API to get NSUri instead of file names.
95-
return GetFileNames()?
101+
var fileNames = GetFileNames();
102+
if (fileNames is null)
103+
return null;
104+
105+
return fileNames
96106
.Select(f => StorageProviderHelpers.TryGetUriFromFilePath(f, false) is { } uri
97107
? storageApi.TryGetStorageItem(uri)
98108
: null)
99-
.Where(f => f is not null);
109+
.Where(f => f is not null)!;
100110
}
101111

102112
public unsafe Task SetDataObjectAsync(IDataObject data)
103113
{
104-
_native.Clear();
114+
Native.Clear();
105115

106116
// If there is multiple values with the same "to" format, prefer these that were not mapped.
107117
var formats = data.GetDataFormats().Select(f =>
@@ -125,26 +135,26 @@ public unsafe Task SetDataObjectAsync(IDataObject data)
125135
switch (o)
126136
{
127137
case string s:
128-
_native.SetText(toFormat, s);
138+
Native.SetText(toFormat, s);
129139
break;
130140
case IEnumerable<IStorageItem> storageItems:
131141
using (var strings = new AvnStringArray(storageItems
132142
.Select(s => s.TryGetLocalPath())
133143
.Where(p => p is not null)))
134144
{
135-
_native.SetStrings(toFormat, strings);
145+
Native.SetStrings(toFormat, strings);
136146
}
137147
break;
138148
case IEnumerable<string> managedStrings:
139149
using (var strings = new AvnStringArray(managedStrings))
140150
{
141-
_native.SetStrings(toFormat, strings);
151+
Native.SetStrings(toFormat, strings);
142152
}
143153
break;
144154
case byte[] bytes:
145155
{
146156
fixed (byte* pbytes = bytes)
147-
_native.SetBytes(toFormat, pbytes, bytes.Length);
157+
Native.SetBytes(toFormat, pbytes, bytes.Length);
148158
break;
149159
}
150160
default:
@@ -161,23 +171,23 @@ public Task<string[]> GetFormatsAsync()
161171
return Task.FromResult(GetFormats().ToArray());
162172
}
163173

164-
public async Task<object> GetDataAsync(string format)
174+
public async Task<object?> GetDataAsync(string format)
165175
{
166176
if (format == DataFormats.Text || format == NSPasteboardTypeString)
167177
return await GetTextAsync();
168178
if (format == DataFormats.FileNames || format == NSFilenamesPboardType)
169179
return GetFileNames();
170180
if (format == DataFormats.Files)
171181
return GetFiles();
172-
using (var n = _native.GetBytes(format))
182+
using (var n = Native.GetBytes(format))
173183
return n.Bytes;
174184
}
175185
}
176186

177187
class ClipboardDataObject : IDataObject, IDisposable
178188
{
179-
private ClipboardImpl _clipboard;
180-
private List<string> _formats;
189+
private ClipboardImpl? _clipboard;
190+
private List<string>? _formats;
181191

182192
public ClipboardDataObject(IAvnClipboard clipboard)
183193
{
@@ -190,14 +200,17 @@ public void Dispose()
190200
_clipboard = null;
191201
}
192202

193-
List<string> Formats => _formats ??= _clipboard.GetFormats().ToList();
203+
private ClipboardImpl Clipboard
204+
=> _clipboard ?? throw new ObjectDisposedException(nameof(ClipboardDataObject));
205+
206+
private List<string> Formats => _formats ??= Clipboard.GetFormats().ToList();
194207

195208
public IEnumerable<string> GetDataFormats() => Formats;
196209

197210
public bool Contains(string dataFormat) => Formats.Contains(dataFormat);
198211

199-
public object Get(string dataFormat) => _clipboard.GetDataAsync(dataFormat).GetAwaiter().GetResult();
212+
public object? Get(string dataFormat) => Clipboard.GetDataAsync(dataFormat).GetAwaiter().GetResult();
200213

201-
public Task SetFromDataObjectAsync(IDataObject dataObject) => _clipboard.SetDataObjectAsync(dataObject);
214+
public Task SetFromDataObjectAsync(IDataObject dataObject) => Clipboard.SetDataObjectAsync(dataObject);
202215
}
203216
}

0 commit comments

Comments
 (0)