matplotlib / matplotlib/matplotlib

[MNT]: macOS backend lacks standard keyboard shortcuts

Open
#31,770 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

GUI: MacOSX Maintenance
Dominant language
Python
Stars
23.2k
Forks
8.5k
Avg merge
1d 6h
Merged PRs (30d)
66

Description

### Summary

A longstanding issue that I've had with matplotlib is the lack of support for standard macOS keyboard shortcuts:

| Command | Shortcut |
|-|-|
| Quit | Command-Q |
| Minimize window | Command-M |
| Switch windows | Command-Grave
Shift-Command-Grave |
| Hide all windows | Command-H |
| Hide other windows | Command-Shift-H |

And when dealing with text input (the save dialog):

| Command | Shortcut |
|-|-|
| Cut | Command-X |
| Copy | Command-C |
| Paste | Command-V |
| Select All | Command-A |
| Undo | Command-Z |
| Redo | Shift-Command-Z |

In addition, macOS Sequoia also added several keyboard shortcuts for dealing with tiling window management.

On macOS, most of these shortcuts are driven by menu items in the main menu bar. The matplotlib macOS backend sets up the shared `NSApplication` instance when it calls `+[NSApplication sharedInstance]`; however, it never fills the `NSApplication.mainMenu` property with a main menu.

Similarly, as `NSApplication.windowsMenu` is never set, macOS doesn't add the applicable menu items or shortcuts for dealing with the tiling window manager.

I'd like to address this by creating a main menu when the macOS backend is used.

There are several ways to solve this, and I'd like some guidance so I don't step on any toes :)

1) I can create the main menu programmatically in `_macosx.m`. This is likely the most straightforward approach, but it would involve a lot of hardcoded strings for menu titles in the `.m` file and ultimately lack localization support.

From an architectural perspective, it seems like existing titles/tooltips are hardcoded at the Python layer, shipped to the backend, which then converts it into UI buttons. That's doable as well, but is a lot of complexity.

2) Create a standard `MainMenu.xib` file that would be edited as a standalone file with Xcode. Invoke `ibtool` from the build system to generate a `.nib` file, package that at a similar level to existing image files, then load this from `_macosx.m`. This would require maintainers to use the Xcode app for editing the main menu, which might be a deal-breaker for some.

3) Create a new Xcode project for macOS UI assets. For now, this would be the main menu xib. In the future, it could be localized UI strings, images, icons, etc. Have the project generate a `.bundle` with compiled `.nibs` / `.car` / `.strings` / etc.

This is likely overkill for now, but could simplify asset creation in the future as Apple pushes for even more UI variants to apps (light / dark / tinted / glass / *sigh*). Xcode can generate those variants automatically and also generate compatible versions for previous macOS releases.

I'm fine with any of these approaches.

There's also the approach of doing all of this without a main menu, but I think that would be harder to maintain in the future as it's not what macOS expects.

### Proposed fix

_No response_

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in the macOS backend’s _macosx.m, where the shared NSApplication instance is created, and inspect how mainMenu and windowsMenu are currently handled. Compare the feasible menu and asset approaches described in the issue, then verify that the standard macOS window and text-editing shortcuts work when the backend is used.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, objective-c, python
Domain
backend, desktop
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.