Skip to content

menu: Open a context menu with a long press on touch - #3393

Merged
huacnlee merged 2 commits into
longbridge:mainfrom
Bombatomica64:longpress-context-menu
Oct 7, 2026
Merged

huacnlee merged 2 commits into
longbridge:mainfrom
Bombatomica64:longpress-context-menu

Conversation

@Bombatomica64

@Bombatomica64 Bombatomica64 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Closes #3392

Description

A finger has no right button, so ContextMenuExt could not be opened on a touch-only device. A long press on the trigger now opens the same menu at the press position, using GPUI's LongPressEvent the same way the plot tooltip (#3078) and touch selection (#3073) do.

  • The body of the right-click handler moved into open_menu, which both listeners call; the only edit is event.position becoming a position parameter. With whitespace changes hidden in Files changed, the change to context_menu.rs is small. Since the moved body is no longer nested, paint now reads shared_state from request_layout (the same Rc that with_element_state returned).
  • The long-press listener is registered before the trigger's children paint, so in the bubble phase it runs after theirs. An Input inside the trigger claims the long press first (prevent_default), keeps its word selection and edit menu, and the context menu stays shut.
  • Right-click is unchanged.

A selectable TextView inside a context-menu trigger keeps its long-press word selection, drag handles, and edit menu. Before claiming a long press, the trigger queries the existing window selection geometry through TextSelection::is_selectable_at; a press over blank space still opens the object menu. The query uses the active selection scope and existing hitboxes rather than treating the whole TextView bounds as text.

Public API

gpui-base

  • TextSelection::is_selectable_at(position: Point<Pixels>, window: &Window, cx: &mut App) -> bool: reports whether the press hits selectable text in the active selection scope, so a containing control can yield to window-level touch selection without starting or changing a selection.

Call this query during pointer dispatch with the event position; hitboxes reflect the current event. No existing API signatures change.

Screenshot

Physical Android phone (OnePlus CPH2581, Android 16), the lab's context-menu demo: a long press on the dashed box, then a tap on the first item. Kit 0.7.0 with and without this diff (backported).

Before

before

After

after

Before: nothing happens. After: the menu opens on the long press, and tapping Copy fires its on_click (context: Copy in the event log).
On the same build, a long press inside an Input still selects the word with handles and the Cut/Copy/Paste/Select All menu.
Builds: demo-pr3393.

How to Test

  • cargo test -p gpui-kit --features test-support,component --test menu --test touch_selection: 10 menu tests + 13 touch-selection tests passed locally on macOS.
  • The new long_press_on_text_in_a_context_menu_trigger_selects regression test failed against the original PR head (empty selection instead of quick) and passes with the fix; it also checks that touch-selection handles remain available and no object context menu opens.
  • long_press_on_blank_space_in_a_text_trigger_opens_the_menu verifies that blank space in the same selectable text row still opens the object menu.
  • Existing right-click, nested-menu, Input selection, Copy/Select All, handle dragging, cached-view selection, and scrolling tests remain covered by the two integration test targets.
  • cargo fmt --all --check and git diff --check: clean.
  • cargo clippy -p gpui-base -p gpui-component -p gpui-kit --features gpui-kit/test-support,gpui-kit/component --tests -- -D warnings: clean.
  • The physical Android recordings above demonstrate the original long-press opening path. The TextView-priority follow-up has automated macOS coverage; it has not been rechecked on a physical Android device.

Checklist

  • I have read the CONTRIBUTING document and followed the guidelines.
  • Reviewed the changes in this PR and confirmed AI generated code (If any) is accurate.
  • Passed cargo run for story tests related to the changes. (Not run: no desktop session here; see How to Test.)
  • Tested macOS, Windows and Linux platforms performance (if the change is platform-specific) (not run on desktop; the new path is touch-only, and right-click is covered by the existing tests)

Thanks for taking the time to review this.

🤖 Generated with Claude Code

The follow-up text-selection fix and its regression tests were generated with Codex and validated with the checks above.

A finger has no right button, so ContextMenuExt could not be opened on
a touch-only device. A long press on the trigger now opens the same
menu at the press position. The listener is registered before the
trigger's children paint, so an Input inside the trigger keeps its own
long press.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Yield long presses over registered selectable text to window-level selection while retaining object menus on blank space. Add text-selection and blank-space regression coverage and document the new query in both locales.

AI-assisted fix generated with Codex.
@huacnlee
huacnlee enabled auto-merge (squash) October 7, 2026 15:57
@huacnlee
huacnlee merged commit 1af2d1f into longbridge:main Oct 7, 2026
16 checks passed
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.

ContextMenu: a long press does not open the menu on touch devices

2 participants