From 5a343fa9c6f7d243484e1030e24f71f40865f9c1 Mon Sep 17 00:00:00 2001 From: Nate Bross Date: Mon, 27 Apr 2026 19:17:38 -0500 Subject: [PATCH] fix: dispatch Ctrl+V via tunnel preview so editor paste works --- src/SharpFM/MainWindow.axaml | 5 ++++- src/SharpFM/MainWindow.axaml.cs | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/SharpFM/MainWindow.axaml b/src/SharpFM/MainWindow.axaml index 82d6f26..33c4a91 100644 --- a/src/SharpFM/MainWindow.axaml +++ b/src/SharpFM/MainWindow.axaml @@ -22,7 +22,10 @@ - + diff --git a/src/SharpFM/MainWindow.axaml.cs b/src/SharpFM/MainWindow.axaml.cs index 025e31c..8670496 100644 --- a/src/SharpFM/MainWindow.axaml.cs +++ b/src/SharpFM/MainWindow.axaml.cs @@ -4,6 +4,10 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.VisualTree; +using AvaloniaEdit; +using AvaloniaEdit.Editing; using SharpFM.Diagnostics; using SharpFM.Plugin; using SharpFM.Plugin.UI; @@ -34,6 +38,9 @@ public MainWindow() if (rawClipboard != null) rawClipboard.Click += (_, _) => new RawClipboardWindow().Show(this); + // Tunnel-phase Ctrl+V — see OnPreviewKeyDown. + AddHandler(KeyDownEvent, OnPreviewKeyDown, RoutingStrategies.Tunnel); + // Wire up plugin UI when DataContext is set DataContextChanged += OnDataContextChanged; } @@ -243,4 +250,34 @@ private void CloseTab_Click(object? sender, Avalonia.Interactivity.RoutedEventAr if ((sender as Button)?.Tag is OpenTabViewModel tab) vm.OpenTabs.Close(tab); } + + // Ctrl+V dispatch (issue #197). A Window-level KeyBinding fires before + // the focused control sees the keystroke, which broke plain-text paste + // in the script editor and the search box. Bubble-phase OnKeyDown does + // the opposite — text editors mark Ctrl+V handled, so the Window never + // sees the global case. Tunnel-phase preview lets us inspect the key + // first and decide based on focus: hand off to text editors, otherwise + // intercept for the FileMaker-clip paste. + private void OnPreviewKeyDown(object? sender, KeyEventArgs e) + { + if (e.Key != Key.V) return; + if (e.KeyModifiers != KeyModifiers.Control) return; + if (IsTextInputFocused()) return; + if (DataContext is not MainWindowViewModel vm) return; + + e.Handled = true; + _ = vm.PasteFileMakerClipData(); + } + + private bool IsTextInputFocused() + { + var focused = FocusManager?.GetFocusedElement() as Visual; + while (focused is not null) + { + if (focused is TextBox or TextEditor or TextArea) + return true; + focused = focused.GetVisualParent(); + } + return false; + } }