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

Reply via email to