Browse Source

Rest of the platforms

pull/18340/head
Nikita Tsukanov 1 year ago
parent
commit
0bfb7e10ee
  1. 18
      native/Avalonia.Native/src/OSX/clipboard.mm
  2. 2
      samples/ControlCatalog/Pages/ClipboardPage.xaml.cs
  3. 2
      src/Android/Avalonia.Android/Platform/ClipboardImpl.cs
  4. 12
      src/Avalonia.Base/Input/Platform/IClipboard.cs
  5. 1
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  6. 25
      src/Avalonia.Native/ClipboardImpl.cs
  7. 4
      src/Avalonia.Native/avn.idl
  8. 2
      src/Avalonia.X11/X11Clipboard.cs
  9. 2
      src/Browser/Avalonia.Browser/ClipboardImpl.cs
  10. 50
      src/Headless/Avalonia.Headless/HeadlessPlatformStubs.cs
  11. 2
      src/Tizen/Avalonia.Tizen/NuiClipboardImpl.cs
  12. 2
      src/Windows/Avalonia.Win32/ClipboardImpl.cs
  13. 2
      src/iOS/Avalonia.iOS/ClipboardImpl.cs
  14. 27
      tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs
  15. 27
      tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

18
native/Avalonia.Native/src/OSX/clipboard.mm

@ -148,17 +148,20 @@ public:
}
virtual HRESULT Clear() override
virtual HRESULT Clear(int64_t* rv) override
{
START_COM_CALL;
@autoreleasepool
{
if(_item != nil)
{
_item = [NSPasteboardItem new];
return 0;
}
else
{
[_pb clearContents];
*rv = [_pb clearContents];
[_pb setString:@"" forType:NSPasteboardTypeString];
}
@ -166,6 +169,17 @@ public:
}
}
virtual HRESULT GetChangeCount(int64_t* rv) override
{
START_COM_CALL;
if(_item == nil)
{
*rv = [_pb changeCount];
return S_OK;
}
return E_NOTIMPL;
}
virtual HRESULT ObtainFormats(IAvnStringArray** ppv) override
{
START_COM_CALL;

2
samples/ControlCatalog/Pages/ClipboardPage.xaml.cs

@ -167,7 +167,7 @@ namespace ControlCatalog.Pages
try
{
_checkingClipboardDataObject = true;
var task = (TopLevel.GetTopLevel(this)?.Clipboard as IClipboard2)?.TryGetInProcessDataObjectAsync();
var task = TopLevel.GetTopLevel(this)?.Clipboard?.TryGetInProcessDataObjectAsync();
var owns = task != null && (await task) == _storedDataObject && _storedDataObject != null;
OwnsClipboardDataObject.Text = owns ? "Yes" : "No";
OwnsClipboardDataObject.Foreground = owns ? Brushes.Green : Brushes.Red;

2
src/Android/Avalonia.Android/Platform/ClipboardImpl.cs

@ -55,5 +55,7 @@ namespace Avalonia.Android.Platform
public Task<string[]> GetFormatsAsync() => throw new PlatformNotSupportedException();
public Task<object?> GetDataAsync(string format) => throw new PlatformNotSupportedException();
public Task<IDataObject?> TryGetInProcessDataObjectAsync() => Task.FromResult<IDataObject?>(null);
}
}

12
src/Avalonia.Base/Input/Platform/IClipboard.cs

@ -17,10 +17,14 @@ namespace Avalonia.Input.Platform
Task<string[]> GetFormatsAsync();
Task<object?> GetDataAsync(string format);
}
public interface IClipboard2 : IClipboard
{
/// <summary>
/// If clipboard contains the IDataObject that was set by a previous call to <see cref="SetDataObjectAsync"/>,
/// return said IDataObject instance. Otherwise, return null.
/// Note that not every platform supports that method, on unsupported platforms this method will always return
/// null
/// </summary>
/// <returns></returns>
Task<IDataObject?> TryGetInProcessDataObjectAsync();
}
}

1
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@ -225,6 +225,7 @@ namespace Avalonia.DesignerSupport.Remote
public Task<string[]> GetFormatsAsync() => Task.FromResult(Array.Empty<string>());
public Task<object> GetDataAsync(string format) => Task.FromResult((object)null);
public Task<IDataObject> TryGetInProcessDataObjectAsync() => Task.FromResult<IDataObject>(null);
}
class CursorFactoryStub : ICursorFactory

25
src/Avalonia.Native/ClipboardImpl.cs

@ -17,6 +17,8 @@ namespace Avalonia.Native
class ClipboardImpl : IClipboard, IDisposable
{
private IAvnClipboard? _native;
private IDataObject? _savedDataObject;
private long _lastClearChangeCount;
// TODO hide native types behind IAvnClipboard abstraction, so managed side won't depend on macOS.
private const string NSPasteboardTypeString = "public.utf8-plain-text";
@ -30,10 +32,15 @@ namespace Avalonia.Native
private IAvnClipboard Native
=> _native ?? throw new ObjectDisposedException(nameof(ClipboardImpl));
private void ClearCore()
{
_savedDataObject = null;
_lastClearChangeCount = Native.Clear();
}
public Task ClearAsync()
{
Native.Clear();
ClearCore();
return Task.CompletedTask;
}
@ -47,7 +54,7 @@ namespace Avalonia.Native
{
var native = Native;
native.Clear();
ClearCore();
if (text != null)
native.SetText(NSPasteboardTypeString, text);
@ -83,6 +90,7 @@ namespace Avalonia.Native
public void Dispose()
{
_savedDataObject = null;
_native?.Dispose();
_native = null;
}
@ -111,7 +119,7 @@ namespace Avalonia.Native
public unsafe Task SetDataObjectAsync(IDataObject data)
{
Native.Clear();
ClearCore();
// If there is multiple values with the same "to" format, prefer these that were not mapped.
var formats = data.GetDataFormats().Select(f =>
@ -163,6 +171,8 @@ namespace Avalonia.Native
break;
}
}
_savedDataObject = data;
return Task.CompletedTask;
}
@ -182,6 +192,13 @@ namespace Avalonia.Native
using (var n = Native.GetBytes(format))
return n.Bytes;
}
public Task<IDataObject?> TryGetInProcessDataObjectAsync()
{
if (Native.ChangeCount != _lastClearChangeCount)
_savedDataObject = null;
return Task.FromResult(_savedDataObject);
}
}
class ClipboardDataObject : IDataObject, IDisposable

4
src/Avalonia.Native/avn.idl

@ -2,6 +2,7 @@
@clr-access internal
@clr-map bool int
@clr-map u_int64_t ulong
@clr-map int64_t long
@clr-map long IntPtr
@cpp-preamble @@
#pragma once
@ -972,7 +973,8 @@ interface IAvnClipboard : IUnknown
HRESULT SetBytes(char* type, void* utf8Text, int len);
HRESULT GetBytes(char* type, IAvnString**ppv);
HRESULT Clear();
HRESULT Clear(int64_t* ret);
HRESULT GetChangeCount(int64_t* ret);
}
[uuid(3f998545-f027-4d4d-bd2a-1a80926d984e)]

2
src/Avalonia.X11/X11Clipboard.cs

@ -9,7 +9,7 @@ using Avalonia.Input.Platform;
using static Avalonia.X11.XLib;
namespace Avalonia.X11
{
internal class X11Clipboard : IClipboard, IClipboard2
internal class X11Clipboard : IClipboard
{
private readonly X11Info _x11;
private IDataObject? _storedDataObject;

2
src/Browser/Avalonia.Browser/ClipboardImpl.cs

@ -25,5 +25,7 @@ namespace Avalonia.Browser
public Task<string[]> GetFormatsAsync() => Task.FromResult(Array.Empty<string>());
public Task<object?> GetDataAsync(string format) => Task.FromResult<object?>(null);
public Task<IDataObject?> TryGetInProcessDataObjectAsync() => Task.FromResult<IDataObject?>(null);
}
}

50
src/Headless/Avalonia.Headless/HeadlessPlatformStubs.cs

@ -23,65 +23,45 @@ namespace Avalonia.Headless
{
internal class HeadlessClipboardStub : IClipboard
{
private string? _text;
private IDataObject? _data;
public Task<string?> GetTextAsync()
{
return Task.Run(() => _text);
return Task.FromResult(_data?.GetText());
}
public Task SetTextAsync(string? text)
{
return Task.Run(() => _text = text);
var data = new DataObject();
if (text != null)
data.Set(DataFormats.Text, text);
_data = data;
return Task.CompletedTask;
}
public Task ClearAsync()
{
return Task.Run(() => _text = null);
_data = null;
return Task.CompletedTask;
}
public Task SetDataObjectAsync(IDataObject data)
{
return Task.Run(() => _data = data);
_data = data;
return Task.CompletedTask;
}
public Task<string[]> GetFormatsAsync()
{
return Task.Run(() =>
{
if (_data is not null)
{
return _data.GetDataFormats().ToArray();
}
if (_text is not null)
{
return new[] { DataFormats.Text };
}
return Array.Empty<string>();
});
return Task.FromResult<string[]>(_data?.GetDataFormats().ToArray() ?? []);
}
public async Task<object?> GetDataAsync(string format)
public Task<object?> GetDataAsync(string format)
{
return await Task.Run(() =>
{
if (format == DataFormats.Text)
return _text;
if (format == DataFormats.Files && _data is not null)
return _data.GetFiles();
if (format == DataFormats.FileNames && _data is not null)
{
#pragma warning disable CS0618 // Type or member is obsolete
return _data.GetFileNames();
#pragma warning restore CS0618 // Type or member is obsolete
}
else
return (object?)_data;
});
return Task.FromResult(_data?.Get(format));
}
public Task<IDataObject?> TryGetInProcessDataObjectAsync() => Task.FromResult(_data);
}
internal class HeadlessCursorFactoryStub : ICursorFactory

2
src/Tizen/Avalonia.Tizen/NuiClipboardImpl.cs

@ -73,4 +73,6 @@ internal class NuiClipboardImpl : IClipboard
public Task<string[]> GetFormatsAsync() =>
throw new PlatformNotSupportedException();
public Task<IDataObject?> TryGetInProcessDataObjectAsync() => Task.FromResult<IDataObject?>(null);
}

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

@ -11,7 +11,7 @@ using MicroCom.Runtime;
namespace Avalonia.Win32
{
internal class ClipboardImpl : IClipboard2
internal class ClipboardImpl : IClipboard
{
private const int OleRetryCount = 10;
private const int OleRetryDelay = 100;

2
src/iOS/Avalonia.iOS/ClipboardImpl.cs

@ -57,5 +57,7 @@ namespace Avalonia.iOS
return Task.FromResult<object?>(null);
}
public Task<IDataObject?> TryGetInProcessDataObjectAsync() => Task.FromResult<IDataObject?>(null);
}
}

27
tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs

@ -1005,31 +1005,6 @@ namespace Avalonia.Controls.UnitTests
}
}
internal class ClipboardStub : IClipboard // in order to get tests working that use the clipboard
{
private string _text;
public Task<string> GetTextAsync() => Task.FromResult(_text);
public Task SetTextAsync(string text)
{
_text = text;
return Task.CompletedTask;
}
public Task ClearAsync()
{
_text = null;
return Task.CompletedTask;
}
public Task SetDataObjectAsync(IDataObject data) => Task.CompletedTask;
public Task<string[]> GetFormatsAsync() => Task.FromResult(Array.Empty<string>());
public Task<object> GetDataAsync(string format) => Task.FromResult((object)null);
}
private class TestTopLevel : TopLevel
{
private readonly ILayoutManager _layoutManager;
@ -1048,7 +1023,7 @@ namespace Avalonia.Controls.UnitTests
var clipboard = new Mock<ITopLevelImpl>();
clipboard.Setup(x => x.Compositor).Returns(RendererMocks.CreateDummyCompositor());
clipboard.Setup(r => r.TryGetFeature(typeof(IClipboard)))
.Returns(new ClipboardStub());
.Returns(new HeadlessClipboardStub());
clipboard.SetupGet(x => x.RenderScaling).Returns(1);
return clipboard;
}

27
tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

@ -1973,31 +1973,6 @@ namespace Avalonia.Controls.UnitTests
}
}
private class ClipboardStub : IClipboard // in order to get tests working that use the clipboard
{
private string? _text;
public Task<string?> GetTextAsync() => Task.FromResult(_text);
public Task SetTextAsync(string? text)
{
_text = text;
return Task.CompletedTask;
}
public Task ClearAsync()
{
_text = null;
return Task.CompletedTask;
}
public Task SetDataObjectAsync(IDataObject data) => Task.CompletedTask;
public Task<string[]> GetFormatsAsync() => Task.FromResult(Array.Empty<string>());
public Task<object?> GetDataAsync(string format) => Task.FromResult((object?)null);
}
private class TestTopLevel : TopLevel
{
private readonly ILayoutManager _layoutManager;
@ -2016,7 +1991,7 @@ namespace Avalonia.Controls.UnitTests
var clipboard = new Mock<ITopLevelImpl>();
clipboard.Setup(x => x.Compositor).Returns(RendererMocks.CreateDummyCompositor());
clipboard.Setup(r => r.TryGetFeature(typeof(IClipboard)))
.Returns(new ClipboardStub());
.Returns(new HeadlessClipboardStub());
clipboard.SetupGet(x => x.RenderScaling).Returns(1);
return clipboard;
}

Loading…
Cancel
Save