private void ConfigureCopypastaStateMachine() { _copypastaStateMachine.Configure(CopypastaState.Idle) .Permit(CopypastaTrigger.ClipboardUpdated, CopypastaState.Copying) .Ignore(CopypastaTrigger.CtrlCPressed) .Permit(CopypastaTrigger.CtrlVPressed, CopypastaState.Pasting) .Ignore(CopypastaTrigger.EscPressed) .Ignore(CopypastaTrigger.KeyPressed) .Ignore(CopypastaTrigger.ModifierPressed) .Ignore(CopypastaTrigger.Timeout) .OnEntry(transition => { _ctrlCHandled = false; _ctrlVHandled = true; _escPressHandled = false; _keyPressHandled = false; _modifierPressHandled = false; _notificationDispatcher.CloseNotification(); Console.WriteLine($"State={_copypastaStateMachine.State}"); }); _copypastaStateMachine.Configure(CopypastaState.Copying) .PermitReentry(CopypastaTrigger.ClipboardUpdated) .Permit(CopypastaTrigger.CtrlCPressed, CopypastaState.Idle) .Permit(CopypastaTrigger.CtrlVPressed, CopypastaState.Pasting) .Permit(CopypastaTrigger.EscPressed, CopypastaState.Idle) .Permit(CopypastaTrigger.KeyPressed, CopypastaState.BindingClipboardToKey) .Ignore(CopypastaTrigger.ModifierPressed) .Permit(CopypastaTrigger.Timeout, CopypastaState.Idle) .OnEntry(() => { _ctrlCHandled = true; _ctrlVHandled = true; _escPressHandled = true; _keyPressHandled = true; _modifierPressHandled = false; // Update clipboard history var clipboardData = _clipboard.ClipboardData; _historyRecordSwap = _clipboardHistoryManager.AddHistoryRecord(Key.None, clipboardData); _notificationDispatcher.ShowNotification(new CopyingNotificationModel()); Console.WriteLine($"State={_copypastaStateMachine.State}"); }); _copypastaStateMachine.Configure(CopypastaState.BindingClipboardToKey) .Permit(CopypastaTrigger.ClipboardUpdated, CopypastaState.Copying) .Ignore(CopypastaTrigger.CtrlCPressed) .Permit(CopypastaTrigger.CtrlVPressed, CopypastaState.Pasting) .Ignore(CopypastaTrigger.EscPressed) .Ignore(CopypastaTrigger.KeyPressed) .Ignore(CopypastaTrigger.ModifierPressed) .Ignore(CopypastaTrigger.Timeout) .Permit(CopypastaTrigger.ClipboardBound, CopypastaState.ShowingClipboardBinding) .OnEntryFrom(_keyPressedTrigger, key => { _ctrlCHandled = false; _ctrlVHandled = true; _escPressHandled = false; _keyPressHandled = false; _modifierPressHandled = false; // Bind clipboard to key _clipboardBindingManager.AddBinding(key, _historyRecordSwap.ClipboardData); // Update clipboard history _historyRecordSwap.Key = key; Console.WriteLine($"State={_copypastaStateMachine.State}"); }); _copypastaStateMachine.Configure(CopypastaState.ShowingClipboardBinding) .Permit(CopypastaTrigger.ClipboardUpdated, CopypastaState.Copying) .Ignore(CopypastaTrigger.CtrlCPressed) .Permit(CopypastaTrigger.CtrlVPressed, CopypastaState.Pasting) .Permit(CopypastaTrigger.EscPressed, CopypastaState.Idle) .Ignore(CopypastaTrigger.KeyPressed) .Ignore(CopypastaTrigger.ModifierPressed) .Permit(CopypastaTrigger.Timeout, CopypastaState.Idle) .OnEntry(() => { _ctrlCHandled = false; _ctrlVHandled = true; _escPressHandled = false; _keyPressHandled = false; _modifierPressHandled = false; _notificationDispatcher.ShowNotification(new BoundNotificationModel { Key = _historyRecordSwap.Key, ClipboardData = _historyRecordSwap.ClipboardData }); Console.WriteLine($"State={_copypastaStateMachine.State}"); }); _copypastaStateMachine.Configure(CopypastaState.Pasting) .Permit(CopypastaTrigger.ClipboardUpdated, CopypastaState.Copying) .Ignore(CopypastaTrigger.CtrlCPressed) .Permit(CopypastaTrigger.CtrlVPressed, CopypastaState.Idle) .Permit(CopypastaTrigger.EscPressed, CopypastaState.Idle) .Permit(CopypastaTrigger.KeyPressed, CopypastaState.MovingDataToClipboard) .Ignore(CopypastaTrigger.ModifierPressed) .Permit(CopypastaTrigger.Timeout, CopypastaState.Idle) .OnEntry(() => { _ctrlCHandled = false; _ctrlVHandled = false; _escPressHandled = true; _keyPressHandled = true; _modifierPressHandled = false; _notificationDispatcher.ShowNotification(new PastingNotificationModel()); Console.WriteLine($"State={_copypastaStateMachine.State}"); }); _copypastaStateMachine.Configure(CopypastaState.MovingDataToClipboard) .Permit(CopypastaTrigger.ClipboardUpdated, CopypastaState.SimulatingCtrlV) .Ignore(CopypastaTrigger.CtrlCPressed) .Ignore(CopypastaTrigger.CtrlVPressed) .Ignore(CopypastaTrigger.EscPressed) .Ignore(CopypastaTrigger.KeyPressed) .Ignore(CopypastaTrigger.ModifierPressed) .Ignore(CopypastaTrigger.Timeout) .Permit(CopypastaTrigger.NoDataOnKey, CopypastaState.Idle) .OnEntryFrom(_keyPressedTrigger, key => { _ctrlCHandled = true; _ctrlVHandled = true; _escPressHandled = false; _keyPressHandled = false; _modifierPressHandled = false; var clipboardItem = _clipboardBindingManager.GetBindingData(key); if (clipboardItem == null) { _copypastaStateMachine.Fire(CopypastaTrigger.NoDataOnKey); return; } // Save clipboard to swap - to restore previous data _clipboardSwap = _clipboard.ClipboardData; // Write to clipboard _clipboard.ClipboardData = clipboardItem; Console.WriteLine($"State={_copypastaStateMachine.State}"); }); _copypastaStateMachine.Configure(CopypastaState.SimulatingCtrlV) .Ignore(CopypastaTrigger.ClipboardUpdated) .Ignore(CopypastaTrigger.CtrlCPressed) .Permit(CopypastaTrigger.CtrlVPressed, CopypastaState.RestoringClipboard) .Ignore(CopypastaTrigger.EscPressed) .Ignore(CopypastaTrigger.KeyPressed) .Ignore(CopypastaTrigger.ModifierPressed) .Ignore(CopypastaTrigger.Timeout) .OnEntry(() => { _ctrlCHandled = true; _ctrlVHandled = false; _escPressHandled = false; _keyPressHandled = false; _modifierPressHandled = false; // Simulate key up for V key. This prevents interfering with simulated Ctrl+V when pasting from V key. _inputSimulator.Keyboard.KeyUp(VirtualKeyCode.VK_V); // Simulate Ctrl+V _inputSimulator.Keyboard.ModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.VK_V); // TODO: This can be removed once support for delayed clipboard rendering is added // Wait for programs to paste data once Ctrl+V is pressed Thread.Sleep(100); Console.WriteLine($"State={_copypastaStateMachine.State}"); }); _copypastaStateMachine.Configure(CopypastaState.RestoringClipboard) .Permit(CopypastaTrigger.ClipboardUpdated, CopypastaState.Idle) .Ignore(CopypastaTrigger.CtrlCPressed) .Permit(CopypastaTrigger.CtrlVPressed, CopypastaState.Pasting) .Ignore(CopypastaTrigger.EscPressed) .Ignore(CopypastaTrigger.KeyPressed) .Ignore(CopypastaTrigger.ModifierPressed) .Ignore(CopypastaTrigger.Timeout) .OnEntry(() => { _ctrlCHandled = false; _ctrlVHandled = true; _escPressHandled = false; _keyPressHandled = false; _modifierPressHandled = false; // Restore previous data _clipboard.ClipboardData = _clipboardSwap; Console.WriteLine($"State={_copypastaStateMachine.State}"); }); }