Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/SharpFM/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
<KeyBinding Gesture="Ctrl+N" Command="{Binding NewScriptCommand}" />
<KeyBinding Gesture="Ctrl+Shift+N" Command="{Binding NewTableCommand}" />
<KeyBinding Gesture="Ctrl+Shift+C" Command="{Binding CopySelectedToClip}" />
<KeyBinding Gesture="Ctrl+V" Command="{Binding PasteFileMakerClipData}" />
<!-- Ctrl+V is wired in code-behind via a tunnel-phase preview
handler so it can defer to the focused text editor (TextBox /
AvaloniaEdit) and only fall through to the FileMaker-clip
paste when focus is on the tree, tabs, or window background. -->
</Window.KeyBindings>

<DockPanel>
Expand Down
37 changes: 37 additions & 0 deletions src/SharpFM/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
}
Loading