Repository: electron
Issue: [Feature Request]: Add a `close` event to Menu instances
Labels: enhancement :sparkles:

### Preflight Checklist

- [X] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project adheres to.
- [X] I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a feature request that matches the one I want to file, without success.

### Problem Description

I have implemented a native context menu for my Electron application and want to listen for clicks on the menu items. The context menus are being generated in the renderer process, then handed over to the main process which displays them, and the main process shall return the ID of the clicked item (or `undefined` if no item was clicked). For these purposes, the renderer can define menu items with labels, accelerators, and an ID. The main process then attaches to it a `click` handler that triggers when the user clicks an item.

However, since the renderer process needs some feedback, as the user can keep open the context menu indefinitely, I need to use a promise, which needs to be resolved or rejected at some point. That means: All works fine if the user clicks a context menu item. But if the user clicks outside of the context menu, indicating an abort operation, I still need to resolve/reject the promise so that the renderer process is not sitting there, indefinitely for a promise that will never resolve.

Using the `menu-will-close` event of the menu does not allow me to cleanly do so, since that event is being fired _before_ the `click` handler has any chance to resolve the promise so I end up always getting rejections (except my hacky solution, see below).

### Proposed Solution

Add a `close` event (or `after-close`) that will be fired after any `click`-handler of the menu has been called (if applicable). This way I can "clean up" more cleanly.

Observe how the below code (in "Alternatives Considered") would change with a `close`-event:

```javascript
private async _displayNativeContextMenu (menu: MenuItem[], x: number, y: number): Promise<string|undefined> {
  return await new Promise((resolve, reject) => {
    let resolvedID = undefined // If no item was clicked, resolve with undefined
    for (const item of menu) {
      // Hook onto a function that writes the item.id into the return value
      item.click = () => { resolvedID = item.id }
    }

    const popupMenu = Menu.buildFromTemplate(menu)
    popupMenu.on('close', (event) => {
      resolve(resolvedID) // At this point, resolvedID will be the correct ID if the user clicked an item
    })
   popupMenu.popup({ x: x, y: y })
  })
}
```

### Alternatives Considered

A working solution is to create a return value, have the `click` handlers write the clicked ID into that, and, after a timeout of 100ms, resolve the promise with whatever ID has been clicked. However, that depends on factors I don't fully trust, and it would be more clean not having to use a timeout.

```javascript
private async _displayNativeContextMenu (menu: MenuItem[], x: number, y: number): Promise<string|undefined> {
  return await new Promise((resolve, reject) => {
    let resolvedID = undefined // If no item was clicked, resolve with undefined
    for (const item of menu) {
      // Hook onto a function that writes the item.id into the return value
      item.click = () => { resolvedID = item.id }
    }

    const popupMenu = Menu.buildFromTemplate(menu)
    popupMenu.on('menu-will-close', (event) => {
      setTimeout(() => {
        resolve(resolvedID) // resolvedID will contain the correct ID only after a timeout
      }, 100)
    })
   popupMenu.popup({ x: x, y: y })
  })
}
```

### Additional Information

Electron version: 12.0.2