Skip to content

[202_106]: fix Cmd+V paste not working in macOS save file dialog#2901

Open
divyansharma001 wants to merge 1 commit intoMoganLab:mainfrom
divyansharma001:da/202_106/fix_macos_paste_in_dialog
Open

[202_106]: fix Cmd+V paste not working in macOS save file dialog#2901
divyansharma001 wants to merge 1 commit intoMoganLab:mainfrom
divyansharma001:da/202_106/fix_macos_paste_in_dialog

Conversation

@divyansharma001
Copy link
Contributor

What

Fix standard editing shortcuts (Cmd+V, Cmd+C, Cmd+X, Cmd+A) not working in
the native file dialog on macOS.

Why

On macOS, QAction shortcuts registered in the menu bar are converted to
NSMenuItem key equivalents. When a native file dialog (NSSavePanel/NSOpenPanel)
is shown, these key equivalents intercept standard editing shortcuts before
the dialog's text field can handle them — so pressing Cmd+V triggers Mogan's
"Paste" action instead of pasting into the filename field.

How

Temporarily disable all QAction shortcuts before dialog->exec() and restore
them after the dialog closes. This allows the native dialog to process
Cmd+V/C/X/A through the standard Cocoa responder chain.

How to test

  1. Open Mogan on macOS
  2. Copy some text to the clipboard
  3. File → Save as
  4. Press Cmd+V in the filename field — text should be pasted
  5. Verify Cmd+C, Cmd+X, Cmd+A also work in the dialog
  6. After closing the dialog, verify editor shortcuts still work normally

Fixes: #2894

Temporarily disable QAction shortcuts while a native file dialog is open
on macOS, then restore them after the dialog closes. This prevents menu
bar NSMenuItem key equivalents from intercepting Cmd+V/C/X/A before
the dialog's text field can handle them.

Fixes: MoganLab#2894
Copilot AI review requested due to automatic review settings March 1, 2026 04:46
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes macOS native file dialog text-field editing shortcuts (Cmd+V/C/X/A) being intercepted by the app’s menu QAction shortcuts by temporarily clearing those shortcuts during QFileDialog::exec() and restoring them afterward.

Changes:

  • Add macOS-specific logic in qt_chooser_widget_rep::perform_dialog() to save/clear QAction shortcuts before showing the native file dialog and restore them after it closes.
  • Add developer note (devel/202_106.md) documenting rationale and manual test steps.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/Plugins/Qt/qt_chooser_widget.cpp Temporarily clears menu QAction shortcuts around native file dialog execution on macOS.
devel/202_106.md Documents the issue, rationale, and testing procedure for the fix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

#ifdef Q_OS_MACOS
// Restore menu shortcuts after the native dialog is closed
for (const auto& pair : savedShortcuts) {
pair.first->setShortcut (pair.second);
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The restore loop assumes every QAction* in savedShortcuts is still alive. While a native modal dialog is open on macOS, it’s possible for actions/windows to be destroyed (e.g., via menu interactions), which would leave dangling pointers here and can crash. Consider storing QPointer<QAction> (or tracking destroyed) and skipping entries whose action has been deleted before restoring.

Suggested change
pair.first->setShortcut (pair.second);
QAction* action = pair.first;
if (!action)
continue;
action->setShortcut (pair.second);

Copilot uses AI. Check for mistakes.
Comment on lines +352 to +360
// intercept standard editing shortcuts (Cmd+V, Cmd+C, Cmd+X, Cmd+A) before
// the dialog's text field can handle them. Temporarily clearing all QAction
// shortcuts allows the native dialog to process these keys normally.
QList<QPair<QAction*, QKeySequence>> savedShortcuts;
QWidget* mainWin= QApplication::activeWindow ();
if (mainWin) {
for (QAction* action : mainWin->findChildren<QAction*> ()) {
if (!action->shortcut ().isEmpty ()) {
savedShortcuts.append (qMakePair (action, action->shortcut ()));
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This loop clears shortcuts for all actions under the active window, not just the standard editing shortcuts called out in the PR description. That can temporarily disable other important app/window shortcuts while the dialog is open. Consider limiting the clearing/restoring to only the conflicting sequences (Copy/Paste/Cut/SelectAll, and optionally Undo/Redo) to reduce user-visible side effects.

Suggested change
// intercept standard editing shortcuts (Cmd+V, Cmd+C, Cmd+X, Cmd+A) before
// the dialog's text field can handle them. Temporarily clearing all QAction
// shortcuts allows the native dialog to process these keys normally.
QList<QPair<QAction*, QKeySequence>> savedShortcuts;
QWidget* mainWin= QApplication::activeWindow ();
if (mainWin) {
for (QAction* action : mainWin->findChildren<QAction*> ()) {
if (!action->shortcut ().isEmpty ()) {
savedShortcuts.append (qMakePair (action, action->shortcut ()));
// intercept standard editing shortcuts (Cmd+V, Cmd+C, Cmd+X, Cmd+A, etc.)
// before the dialog's text field can handle them. Temporarily clearing
// shortcuts only for these standard editing sequences allows the native
// dialog to process them normally while preserving other application
// shortcuts.
QList<QPair<QAction*, QKeySequence>> savedShortcuts;
QWidget* mainWin= QApplication::activeWindow ();
if (mainWin) {
const QList<QKeySequence> conflictingSequences = {
QKeySequence::Copy,
QKeySequence::Paste,
QKeySequence::Cut,
QKeySequence::SelectAll,
QKeySequence::Undo,
QKeySequence::Redo
};
for (QAction* action : mainWin->findChildren<QAction*> ()) {
const QKeySequence shortcut = action->shortcut ();
if (!shortcut.isEmpty () && conflictingSequences.contains (shortcut)) {
savedShortcuts.append (qMakePair (action, shortcut));

Copilot uses AI. Check for mistakes.
Comment on lines +349 to +351
#ifdef Q_OS_MACOS
// On macOS, QAction shortcuts registered in the menu bar become NSMenuItem
// key equivalents. When a native file dialog is open, these key equivalents
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function already uses OS_MACOS earlier, but the new shortcut-disabling logic is guarded with Q_OS_MACOS. Mixing platform macros in the same file makes it harder to reason about which builds include the code and can lead to accidental omissions in some configurations. Consider using the same macOS guard consistently (whichever is standard for this module).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

在 macOS 平台保存文件的对话框中无法使用 Command v 粘贴

2 participants