Browse Source

Implemented clipboard

pull/875/head
Nikita Tsukanov 9 years ago
parent
commit
cc60c6e5dd
  1. 1
      src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
  2. 53
      src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs
  3. 2
      src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs
  4. 23
      src/Gtk/Avalonia.Gtk3/Interop/Native.cs
  5. 13
      src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs
  6. 9
      src/Gtk/Avalonia.Gtk3/Stubs.cs
  7. 8
      src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs

1
src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj

@ -44,6 +44,7 @@
<Compile Include="..\Avalonia.Gtk\KeyTransform.cs">
<Link>KeyTransform.cs</Link>
</Compile>
<Compile Include="ClipboardImpl.cs" />
<Compile Include="FramebufferManager.cs" />
<Compile Include="GdkKey.cs" />
<Compile Include="Gtk3Platform.cs" />

53
src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Gtk3.Interop;
using Avalonia.Input.Platform;
namespace Avalonia.Gtk3
{
class ClipboardImpl : IClipboard
{
IntPtr GetClipboard() => Native.GtkClipboardGetForDisplay(Native.GdkGetDefaultDisplay(), IntPtr.Zero);
static void OnText(IntPtr clipboard, IntPtr utf8string, IntPtr userdata)
{
var handle = GCHandle.FromIntPtr(userdata);
((TaskCompletionSource<string>) handle.Target)
.TrySetResult(Utf8Buffer.StringFromPtr(utf8string));
handle.Free();
}
private static readonly Native.D.GtkClipboardTextReceivedFunc OnTextDelegate = OnText;
static ClipboardImpl()
{
GCHandle.Alloc(OnTextDelegate);
}
public Task<string> GetTextAsync()
{
var tcs = new TaskCompletionSource<string>();
Native.GtkClipboardRequestText(GetClipboard(), OnTextDelegate, GCHandle.ToIntPtr(GCHandle.Alloc(tcs)));
return tcs.Task;
}
public Task SetTextAsync(string text)
{
using (var buf = new Utf8Buffer(text))
Native.GtkClipboardSetText(GetClipboard(), buf, buf.ByteLen);
return Task.FromResult(0);
}
public Task ClearAsync()
{
Native.GtkClipboardRequestClear(GetClipboard());
return Task.FromResult(0);
}
}
}

2
src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs

@ -30,7 +30,7 @@ namespace Avalonia.Gtk3
s_tlsMarker = true;
AvaloniaLocator.CurrentMutable.Bind<IWindowingPlatform>().ToConstant(Instance)
.Bind<IClipboard>().ToSingleton<ClipboardStub>()
.Bind<IClipboard>().ToSingleton<ClipboardImpl>()
.Bind<IStandardCursorFactory>().ToConstant(new CursorFactoryStub())
.Bind<IKeyboardDevice>().ToConstant(Keyboard)
.Bind<IMouseDevice>().ToConstant(Mouse)

23
src/Gtk/Avalonia.Gtk3/Interop/Native.cs

@ -57,6 +57,9 @@ namespace Avalonia.Gtk3.Interop
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate int gdk_screen_get_width(IntPtr screen);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate IntPtr gdk_display_get_default();
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate int gdk_window_get_origin(IntPtr gdkWindow, out int x, out int y);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
@ -145,6 +148,18 @@ namespace Avalonia.Gtk3.Interop
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_begin_resize_drag(IntPtr window, WindowEdge edge, gint button, gint root_x, gint root_y, guint32 timestamp);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_clipboard_get_for_display(IntPtr display, IntPtr atom);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_clipboard_request_text(IntPtr clipboard, GtkClipboardTextReceivedFunc callback, IntPtr user_data);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_clipboard_set_text(IntPtr clipboard, Utf8Buffer text, int len);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_clipboard_clear(IntPtr clipboard);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
public delegate ulong g_signal_connect_object(IntPtr instance, Utf8Buffer signal, IntPtr handler, IntPtr userData, int flags);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
@ -165,6 +180,9 @@ namespace Avalonia.Gtk3.Interop
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool timeout_callback(IntPtr data);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void GtkClipboardTextReceivedFunc(IntPtr clipboard, IntPtr utf8string, IntPtr userdata);
}
@ -195,6 +213,10 @@ namespace Avalonia.Gtk3.Interop
public static D.gdk_window_invalidate_rect GdkWindowInvalidateRect;
public static D.gtk_widget_queue_draw_area GtkWidgetQueueDrawArea;
public static D.gtk_widget_activate GtkWidgetActivate;
public static D.gtk_clipboard_get_for_display GtkClipboardGetForDisplay;
public static D.gtk_clipboard_request_text GtkClipboardRequestText;
public static D.gtk_clipboard_set_text GtkClipboardSetText;
public static D.gtk_clipboard_clear GtkClipboardRequestClear;
public static D.gtk_im_multicontext_new GtkImMulticontextNew;
@ -202,6 +224,7 @@ namespace Avalonia.Gtk3.Interop
public static D.gtk_im_context_set_client_window GtkImContextSetClientWindow;
public static D.gdk_screen_get_height GdkScreenGetHeight;
public static D.gdk_display_get_default GdkGetDefaultDisplay;
public static D.gdk_screen_get_width GdkScreenGetWidth;
public static D.gdk_screen_get_root_window GdkScreenGetRootWindow;
public static D.gdk_window_get_origin GdkWindowGetOrigin;

13
src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs

@ -16,6 +16,8 @@ namespace Avalonia.Gtk3.Interop
handle = _gchandle.AddrOfPinnedObject();
}
public int ByteLen => _data.Length;
protected override bool ReleaseHandle()
{
if (handle != IntPtr.Zero)
@ -28,5 +30,16 @@ namespace Avalonia.Gtk3.Interop
}
public override bool IsInvalid => handle == IntPtr.Zero;
public static unsafe string StringFromPtr(IntPtr s)
{
var pstr = (byte*)s;
int len;
for (len = 0; pstr[len] != 0; len++) ;
var bytes = new byte[len];
Marshal.Copy(s, bytes, 0, len);
return Encoding.UTF8.GetString(bytes, 0, len);
}
}
}

9
src/Gtk/Avalonia.Gtk3/Stubs.cs

@ -14,15 +14,6 @@ using Avalonia.Platform;
namespace Avalonia.Gtk3
{
class ClipboardStub : IClipboard
{
public Task<string> GetTextAsync() => Task.FromResult("");
public Task SetTextAsync(string text) => Task.FromResult(0);
public Task ClearAsync() => Task.FromResult(0);
}
class CursorFactoryStub : IStandardCursorFactory
{
public IPlatformHandle GetCursor(StandardCursorType cursorType) => new PlatformHandle(IntPtr.Zero, "STUB");

8
src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs

@ -170,13 +170,7 @@ namespace Avalonia.Gtk3
private unsafe bool OnCommit(IntPtr gtkwidget, IntPtr utf8string, IntPtr userdata)
{
var pstr = (byte*)utf8string;
int len;
for (len = 0; pstr[len] != 0; len++) ;
var bytes = new byte[len];
Marshal.Copy(utf8string, bytes, 0, len);
Input(new RawTextInputEventArgs(Gtk3Platform.Keyboard, _lastKbdEvent, Encoding.UTF8.GetString(bytes, 0, len)));
Input(new RawTextInputEventArgs(Gtk3Platform.Keyboard, _lastKbdEvent, Utf8Buffer.StringFromPtr(utf8string)));
return true;
}

Loading…
Cancel
Save