Skip to content

fix: close drop down menus with escape key - #6561

Open
Polymorph0us wants to merge 2 commits into
Zettlr:developfrom
Polymorph0us:fix/close-menu-with-escape
Open

Polymorph0us wants to merge 2 commits into
Zettlr:developfrom
Polymorph0us:fix/close-menu-with-escape

Conversation

@Polymorph0us

@Polymorph0us Polymorph0us commented Sep 15, 2026 •

Copy link
Copy Markdown

Description

the dropdown menus couldnt be dismissed with escape so i added escape handling

Changes

  • Modified showPopupMenu in application-menu-helper.ts to attach a keydown listener (for top-level menus) that cascades closure down to any active submenus via a lifted closure reference.
  • Updated WindowMenubar.vue to listen to the keydown event on the global window object to correctly reset its internal tracking state (currentSubmenu and menuCloseCallback) upon an Escape key press.
  • Reused the existing mousedown dismiss logic to handle the new KeyboardEvent without relying on stopPropagation.

Tested on

Linux

Additional information

Closes #6560

AI Disclosure Statement

-To identify the file responsible for the dropdown as well as a little bit of coding assistance

Declarations

  • [ X] I hereby confirm that I am solely responsible for the code provided in
    this PR. Usage of AI to generate code has been documented and made
    transparent. I understand that AI cannot be an author and the commit messages
    do not contain any chatbots or agents as "co-authors". There are no copyright
    issues with my code.
  • [ X] I hereby confirm that I wrote this PR description myself and that I did
    not use an LLM to draft this description.
  • [ X] I have specified any open issues that this PR fixes/closes accordingly in
    the additional information section.

Copilot AI lite review requested due to automatic review settings September 15, 2026 10:49
@boring-cyborg

boring-cyborg Bot commented Sep 15, 2026

Copy link
Copy Markdown

Thank you for opening your first PR. We appreciate the time and effort you spent in creating this improvement. A maintainer will look at these changes shortly, and conduct a review. Please be patient, as everyone here works on this app in their free time. We will get to your PR as soon as we can.
In the meantime, please check that you aid us as much as possible to fast- track your changes by adhering to our Contributing guide and Code of Conduct, and ensuring that your PR is manageable and contains only as many changes as absolutely necessary to expedite review.
Here is a checklist for you to go through as you await our review:

  • Keep your PR up-to-date. We sometimes merge changes into develop that
    then cause merge conflicts. We will not fix those for you, so please ensure
    to merge the develop branch back into your branch to keep it up to date and
    prevent merge conflicts from interfering with the process.
  • Ensure you follow the "human communication" requirement. While we allow
    the use of LLMs for aiding with code, we strictly require every contributor
    to communicate themselves. If you have let your LLM fill in the PR
    description, please use the official pull request template and exchange the
    LLM-generated response with it, filling in the required sections yourself.
  • Check the status of the CI pipeline. Every PR must pass a linter and
    unit tests check. If those run correctly locally on your computer, they
    likely will run fine here. You do not need to fix warnings or errors that
    are clearly not caused by your PR. A failed check does not constitute a hard
    block towards merging your PR.
  • Stay responsive. We will let you know if there are issues with your PR,
    and when we have conducted a code review. Please act on our comments and
    requests in a timely manner. Failure to do so may lead to the closing of
    your PR.

If any of the above is unclear, or if you want to clarify something before jumping into action, please let us know; either with a comment here under your PR, or on the Community Forum or on Discord. We value upfront communication, since this can reduce misunderstandings and improve the efficiency of the work.
Thanks again!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved menu behavior, event-phase, cleanup, and pending-response issues remain.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds Escape-key dismissal for custom dropdown menus and synchronizes menubar state.

Changes:

  • Adds Escape handling and submenu cleanup.
  • Resets WindowMenubar state on Escape.
  • Reuses existing dismissal logic for keyboard events.
File summaries
File Summary
source/common/vue/window/WindowMenubar.vue Adds Escape-based state reset handling; requires capture-phase registration and listener cleanup.
source/common/modules/window-register/application-menu-helper.ts Adds keyboard dismissal and submenu tracking; requires fixes to callback handling and event capture.
Review details

Suppressed comments (3)

source/common/modules/window-register/application-menu-helper.ts:350

  • The newly added global keydown listener is not removed when a menu item is selected: the item handlers remove appMenu directly instead of calling closeMenu, so this cleanup block is skipped. Repeatedly opening and selecting from menus accumulates window listeners and their closures; route every menu-removal path through closeMenu (or explicitly remove both global listeners).
  window.addEventListener('mousedown', closeMenu)
  if (cleanup) {
    window.addEventListener('keydown', closeMenu)

source/common/vue/window/WindowMenubar.vue:73

  • The menubar's state-reset listener has the same bubbling-phase problem: an Escape handled by FileManager/FileTree or an inline filename input is stopped before this window listener runs, leaving currentSubmenu and menuCloseCallback populated even if the menu is closed by a capture-phase handler. Register this keydown listener in the capture phase and remove it on unmount so the component state is reset for those focused controls.
  window.addEventListener('mousedown', resetState)
  window.addEventListener('keydown', resetState)

source/common/vue/window/WindowMenubar.vue:64

  • Escape only resets state when a menu callback already exists, but getSubmenu sets targetElement before the asynchronous IPC response arrives. If Escape is pressed while a submenu request is pending (especially while switching between top-level items), the stale response still reaches showSubmenu and opens the menu after it was dismissed. Cancel/mark the pending target on Escape and ignore the corresponding late response.
  const resetState = (event?: Event) => {
    if (event instanceof KeyboardEvent && event.key !== 'Escape') {
      return
  • Files reviewed: 2/2 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread source/common/modules/window-register/application-menu-helper.ts Outdated
Comment thread source/common/modules/window-register/application-menu-helper.ts Outdated
Comment thread source/common/vue/window/WindowMenubar.vue
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.

Top level drop down menus can't be closed with escape

2 participants