using System.Diagnostics; using Toak.Core; using Toak.Core.Interfaces; namespace Toak.IO.Injectors; /// /// Text injector that writes text to the Wayland clipboard via wl-copy /// and then pastes it using Ctrl+V via wtype. /// public class WlClipboardTextInjector(INotifications notifications) : ITextInjector { private readonly INotifications _notifications = notifications; public Task InjectTextAsync(string text) { Logger.LogDebug("Injecting text using wl-clipboard..."); if (string.IsNullOrWhiteSpace(text)) return Task.CompletedTask; try { // Write the full text to wl-copy via stdin var copyInfo = new ProcessStartInfo { FileName = Constants.Commands.ClipboardWayland, UseShellExecute = false, CreateNoWindow = true, RedirectStandardInput = true }; using var copyProcess = Process.Start(copyInfo); if (copyProcess != null) { copyProcess.StandardInput.Write(text); copyProcess.StandardInput.Close(); copyProcess.WaitForExit(); } Task.Delay(100).Wait(); // Simulate Ctrl+V to paste into the focused window var pasteInfo = new ProcessStartInfo { FileName = Constants.Commands.TypeWayland, Arguments = "-M ctrl -k v -m ctrl", UseShellExecute = false, CreateNoWindow = true }; var pasteProcess = Process.Start(pasteInfo); pasteProcess?.WaitForExit(); } catch (Exception ex) { Console.WriteLine($"[WlClipboardTextInjector] Error injecting text: {ex.Message}"); _notifications.Notify("Injection Error", "Could not type text into window."); } return Task.CompletedTask; } public async Task InjectStreamAsync(IAsyncEnumerable tokenStream) { Logger.LogDebug("Setting up stream injection using wl-clipboard..."); var fullText = string.Empty; try { // Collect all tokens first await foreach (var token in tokenStream) { Logger.LogDebug($"Buffering token: '{token}'"); fullText += token; } // Write the full text to wl-copy via stdin var copyInfo = new ProcessStartInfo { FileName = Constants.Commands.ClipboardWayland, UseShellExecute = false, CreateNoWindow = true, RedirectStandardInput = true }; using var copyProcess = Process.Start(copyInfo); if (copyProcess != null) { await copyProcess.StandardInput.WriteAsync(fullText); copyProcess.StandardInput.Close(); await copyProcess.WaitForExitAsync(); } await Task.Delay(100); // Simulate Ctrl+V to paste into the focused window var pasteInfo = new ProcessStartInfo { FileName = Constants.Commands.TypeWayland, Arguments = "-M ctrl -k v -m ctrl", UseShellExecute = false, CreateNoWindow = true }; using var pasteProcess = Process.Start(pasteInfo); if (pasteProcess != null) await pasteProcess.WaitForExitAsync(); } catch (Exception ex) { Console.WriteLine($"[WlClipboardTextInjector] Error injecting text stream: {ex.Message}"); _notifications.Notify("Injection Error", "Could not type text stream into window."); } return fullText; } }