diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
index fe322d20a..9cc00a8bf 100644
--- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
@@ -1260,6 +1260,13 @@ namespace Terminal.Gui {
}
}
+ ///
+ /// A clipboard implementation for Linux.
+ /// This implementation uses the xclip command to access the clipboard.
+ ///
+ ///
+ /// If xclip is not installed, this implementation will not work.
+ ///
class CursesClipboard : ClipboardBase {
public CursesClipboard ()
{
@@ -1373,6 +1380,12 @@ namespace Terminal.Gui {
}
}
+ ///
+ /// A clipboard implementation for MacOSX.
+ /// This implementation uses the Mac clipboard API (via P/Invoke) to copy/paste.
+ /// The existance of the Mac pbcopy and pbpaste commands
+ /// is used to determine if copy/paste is supported.
+ ///
class MacOSXClipboard : ClipboardBase {
IntPtr nsString = objc_getClass ("NSString");
IntPtr nsPasteboard = objc_getClass ("NSPasteboard");
@@ -1447,6 +1460,12 @@ namespace Terminal.Gui {
static extern IntPtr sel_registerName (string selectorName);
}
+ ///
+ /// A clipboard implementation for Linux, when running under WSL.
+ /// This implementation uses the Windows clipboard to store the data, and uses Windows'
+ /// powershell.exe (launched via WSL interop services) to set/get the Windows
+ /// clipboard.
+ ///
class WSLClipboard : ClipboardBase {
public WSLClipboard ()
{
@@ -1460,9 +1479,10 @@ namespace Terminal.Gui {
bool CheckSupport ()
{
if (string.IsNullOrEmpty (powershellCommand)) {
- var (exitCode, result) = BashRunner.Run ("which pwsh");
+ // Specify pwsh.exe (not pwsh) to ensure we get the Windows version (invoked via WSL)
+ var (exitCode, result) = BashRunner.Run ("which pwsh.exe");
if (exitCode > 0) {
- (exitCode, result) = BashRunner.Run ("which powershell");
+ (exitCode, result) = BashRunner.Run ("which powershell.exe");
}
if (exitCode == 0) {
@@ -1536,18 +1556,6 @@ namespace Terminal.Gui {
Curses.noecho ();
}
}
-
- //using (var clipExe = new System.Diagnostics.Process {
- // StartInfo = new System.Diagnostics.ProcessStartInfo {
- // FileName = "clip.exe",
- // RedirectStandardInput = true
- // }
- //}) {
- // clipExe.Start ();
- // clipExe.StandardInput.Write (text);
- // clipExe.StandardInput.Close ();
- // clipExe.WaitForExit ();
- //}
}
}
}
diff --git a/Terminal.Gui/Core/Clipboard/Clipboard.cs b/Terminal.Gui/Core/Clipboard/Clipboard.cs
index 4570bba5e..a260ef8e9 100644
--- a/Terminal.Gui/Core/Clipboard/Clipboard.cs
+++ b/Terminal.Gui/Core/Clipboard/Clipboard.cs
@@ -3,8 +3,27 @@ using System;
namespace Terminal.Gui {
///
- /// Provides cut, copy, and paste support for the clipboard with OS interaction.
+ /// Provides cut, copy, and paste support for the OS clipboard.
///
+ ///
+ ///
+ /// On Windows, the class uses the Windows Clipboard APIs via P/Invoke.
+ ///
+ ///
+ /// On Linux, when not running under Windows Subsystem for Linux (WSL),
+ /// the class uses the xclip command line tool. If xclip is not installed,
+ /// the clipboard will not work.
+ ///
+ ///
+ /// On Linux, when running under Windows Subsystem for Linux (WSL),
+ /// the class launches Windows' powershell.exe via WSL interop and uses the
+ /// "Set-Clipboard" and "Get-Clipboard" Powershell CmdLets.
+ ///
+ ///
+ /// On the Mac, the class uses the MacO OS X pbcopy and pbpaste command line tools
+ /// and the Mac clipboard APIs vai P/Invoke.
+ ///
+ ///
public static class Clipboard {
static ustring contents;
@@ -25,7 +44,10 @@ namespace Terminal.Gui {
}
set {
try {
- if (IsSupported && value != null) {
+ if (IsSupported) {
+ if (value == null) {
+ value = string.Empty;
+ }
Application.Driver.Clipboard.SetClipboardData (value.ToString ());
}
contents = value;
@@ -40,32 +62,37 @@ namespace Terminal.Gui {
///
/// Returns true if the environmental dependencies are in place to interact with the OS clipboard.
///
+ ///
+ /// The first time IsSupported is called, it will spawn a process (e.g. "bash xclip" or "powershell.exe"
+ /// to determine if the clipboard is supported byt the OS platform. This is a one-time cost.
+ ///
public static bool IsSupported { get => Application.Driver.Clipboard.IsSupported; }
///
- /// Gets the operation system clipboard if possible.
+ /// Copies the contents of the OS clipboard to if possible.
///
- /// Clipboard contents read
- /// true if it was possible to read the OS clipboard.
+ /// The contents of the OS clipboard if successful, if not.
+ /// the OS clipboard was retrieved, otherwise.
public static bool TryGetClipboardData (out string result)
{
- if (Application.Driver.Clipboard.TryGetClipboardData (out result)) {
+ if (IsSupported && Application.Driver.Clipboard.TryGetClipboardData (out result)) {
if (contents != result) {
contents = result;
}
return true;
}
+ result = string.Empty;
return false;
}
///
- /// Sets the operation system clipboard if possible.
+ /// Pastes the to the OS clipboard if possible.
///
- ///
- /// True if the clipboard content was set successfully.
+ /// The text to paste to the OS clipboard.
+ /// the OS clipboard was set, otherwise.
public static bool TrySetClipboardData (string text)
{
- if (Application.Driver.Clipboard.TrySetClipboardData (text)) {
+ if (IsSupported && Application.Driver.Clipboard.TrySetClipboardData (text)) {
contents = text;
return true;
}
diff --git a/UnitTests/ClipboardTests.cs b/UnitTests/ClipboardTests.cs
index d8d242e56..6ba45d76e 100644
--- a/UnitTests/ClipboardTests.cs
+++ b/UnitTests/ClipboardTests.cs
@@ -120,7 +120,8 @@ namespace Terminal.Gui.ConsoleDrivers {
} else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) {
if (Is_WSL_Platform ()) {
try {
- RunClipboardProcess ("pwsh", $"-noprofile -command \"Set-Clipboard -Value \\\"{clipText}\\\"\"");
+ // This runs the WINDOWS version of powershell.exe via WSL.
+ RunClipboardProcess ("powershell.exe", $"-noprofile -command \"Set-Clipboard -Value \\\"{clipText}\\\"\"");
} catch {
failed = true;
}