Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 4723be8cda9e9cd7103444192e83290129b0828a
https://github.com/WebKit/WebKit/commit/4723be8cda9e9cd7103444192e83290129b0828a
Author: Richard Robinson <[email protected]>
Date: 2026-05-27 (Wed, 27 May 2026)
Changed paths:
M Source/WebKit/UIProcess/mac/WKAppKitGestureController.mm
M Tools/TestWebKitAPI/Helpers/cocoa/JavaScriptMessages.swift
M Tools/TestWebKitAPI/Helpers/cocoa/WebPage+JavaScriptExpression.swift
M Tools/TestWebKitAPI/Tests/WebKit/WebPage/AppKitGesturesTests.swift
Log Message:
-----------
[AppKit Gestures] Can never get context menu with a right click (non-text)
https://bugs.webkit.org/show_bug.cgi?id=315437
rdar://170741007
Reviewed by Tim Horton.
Right-clicking on non-text content in `WKWebView` (an image, a link, the page
background, etc.)
never produced a context menu. `gestureRecognizerShouldBegin:` for
`_secondaryClickGestureRecognizer`
carried a FIXME and returned NO unconditionally, so the secondary-click gesture
never started
on non-text content. (Right-clicks on selected text worked, but only via the
text-selection
manager's own gestures.)
Mirror the existing drag-deferral flow that already gates drag-and-drop
on a position-info fetch.
Tests: Tools/TestWebKitAPI/Helpers/cocoa/JavaScriptMessages.swift
Tools/TestWebKitAPI/Tests/WebKit/WebPage/AppKitGesturesTests.swift
* Source/WebKit/UIProcess/mac/WKAppKitGestureController.mm:
(representsSelectableElement):
(-[WKAppKitGestureController setUpGestureRecognizers]):
(-[WKAppKitGestureController setUpSecondaryClickGestureRecognizer]):
(-[WKAppKitGestureController setUpSecondaryClickDeferringGestureRecognizer]):
(-[WKAppKitGestureController addGesturesToWebView]):
(-[WKAppKitGestureController enableGesturesIfNeeded]):
- Add a second `WKDeferringGestureRecognizer`,
`_secondaryClickDeferringGestureRecognizer`,
configured via the new `configureForSecondaryClickDeferral:`. Like
`configureForDragDeferral:`,
it defers text-selection gestures while position info is fetched.
- Set `cancelPastAllowableMovement` on the secondary-click GR so a
press-and-drag cancels the
gesture rather than spuriously triggering a context menu.
(-[WKAppKitGestureController panGestureRecognized:]):
(-[WKAppKitGestureController singleClickGestureRecognized:]):
(-[WKAppKitGestureController doubleClickGestureRecognized:]):
(-[WKAppKitGestureController mouseTrackingGestureRecognized:]):
While here, tighten the gesture-handler entry points. The `...Recognized:`
methods are wired to
specific recognizers via `initWithTarget:action:`, so the existing `if (... !=
gesture) return;`
guards were either dead code or evidence of a bug — replace them with
`RELEASE_ASSERT`.
(-[WKAppKitGestureController secondaryClickGestureRecognized:]):
- Treat `Began` as a click cancellation (the in-flight potential click would
otherwise leak when
the press recognizer fires) and only pop the menu on `Ended`.
(-[WKAppKitGestureController
deferringGestureRecognizer:shouldDeferOtherGestureRecognizer:]):
(-[WKAppKitGestureController
deferringGestureRecognizer:shouldDeferGesturesForEventThatWillBeginAction:]):
(-[WKAppKitGestureController
deferringGestureRecognizer:didEndActionWithEvent:]):
- Generalize the deferring delegate callbacks to handle either deferring GR.
The position-info
resolution callback picks its predicate by identity:
representsDraggableElement` for the drag GR,
and `representsSelectableElement` (new helper, defined symmetrically and
returning true iff `info.selectability == Selectable`)
for the secondary-click GR. The secondary-click branch ends the deferral with
`shouldPreventGestures = !isSelectable`, so text-selection wins on selectable
text and the
secondary click wins everywhere else.
(-[WKAppKitGestureController
gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]):
- Generalize to dispatch on `WKDeferringGestureRecognizer` class membership
instead of
`_dragDeferringGestureRecognizer` identity, so the new deferring GR is handled
the same way.
(-[WKAppKitGestureController gestureRecognizerShouldBegin:]):
(-[WKAppKitGestureController _secondaryClickShouldBeginAtLocation:]):
- Flatten `gestureRecognizerShouldBegin:` to early-return per recognizer.
- Replace the FIXME with `_secondaryClickShouldBeginAtLocation:`, which
consults the cached position
info (or invalidates it and fails fast if stale) and returns YES only for
selectable elements. Together
with the deferring GR, this means the secondary click owns non-selectable
points and text-selection
still owns selectable ones.
(-[WKAppKitGestureController _gestureRecognizer:canPreventGestureRecognizer:]):
- Stop letting other click GRs prevent `_secondaryClickGestureRecognizer` in
`_gestureRecognizer:canPreventGestureRecognizer:`.
The single-click and mouse-tracking GRs both transition to `Began` immediately
on mouse-down, which
would otherwise short-circuit the 0.72s press timer before it can fire.
* Tools/TestWebKitAPI/Helpers/cocoa/JavaScriptMessages.swift:
(Storage.encoded):
* Tools/TestWebKitAPI/Tests/WebKit/WebPage/AppKitGesturesTests.swift:
(AppKitGesturesTests.clickingOnSelectedWordOpensContextMenu(_:)):
(AppKitGesturesTests.clickingAndHoldingOnEmptyContentOpensContextMenu(_:)):
(AppKitGesturesTests.tripleClickingInPDFSelectsLine):
(AppKitGesturesTests.pressDragOnLinkInitiatesDragAndDrop):
(AppKitGesturesTests.pressDragOnExistingSelectionDoesNotExtendSelection):
(convertToCoreGraphicsScreenCoordinates(_:window:)):
(withSwizzledContextMenu(perform:)):
- New `AppKitGesturesTests.clickingAndHoldingOnEmptyContentOpensContextMenu`
exercises the long-press → context-menu path on empty content (both
with and without `contenteditable`).
- `clickingOnSelectedWordOpensContextMenu` is refactored to use a
shared `withSwizzledContextMenu(perform:)` helper that swizzles
`NSMenu._popUpContextMenu(_:with:for:)` and waits for it to be
invoked, replacing the inline swizzling.
- A new
`convertToCoreGraphicsScreenCoordinates(pointInWindowCoordinates:window:)`
helper supports tests that have a window-space point rather than a
DOM rect; `tripleClickingInPDFSelectsLine` switches to it.
- `JavaScriptMessages.Storage.encoded` uses `nil` directly instead of
`NSNull()` (the dictionary value type is already `Any?`).
Canonical link: https://commits.webkit.org/313984@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications