Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 17c30e3cfa7cb856ba46e621918774758aab0da3
      
https://github.com/WebKit/WebKit/commit/17c30e3cfa7cb856ba46e621918774758aab0da3
  Author: Richard Robinson <[email protected]>
  Date:   2026-06-25 (Thu, 25 Jun 2026)

  Changed paths:
    M Source/WebCore/page/EventHandler.cpp
    M Source/WebCore/page/EventHandler.h
    M Source/WebCore/page/mac/EventHandlerMac.mm
    M Source/WebKit/UIProcess/mac/WKTextSelectionController.h
    M Source/WebKit/UIProcess/mac/WKTextSelectionController.swift
    M Source/WebKit/UIProcess/mac/WebViewImpl.mm
    M Source/WebKit/WebProcess/WebPage/Cocoa/WebPageCocoa.mm
    M Source/WebKit/WebProcess/WebPage/WebPage.h
    M Tools/TestWebKitAPI/Tests/WebKit/WebPage/AppKitGesturesTests.swift

  Log Message:
  -----------
  [AppKit Gestures] Clicking and dragging text selection to the edge of the 
window does not autoscroll
https://bugs.webkit.org/show_bug.cgi?id=317717
rdar://176424187

Reviewed by Abrar Rahman Protyasha.

On macOS, when using the AppKit-gestures text interaction path (driven by
NSTextSelectionManager), click-dragging a selection to the edge of the window
did not autoscroll the page. The selection stopped growing at whatever was
already on screen, so it was impossible to select past the visible content
without manually scrolling first. iOS already supports this via UIKit's
UITextAutoscrolling protocol, which performs edge detection and drives the
web process's autoscroll timer; AppKit has no equivalent, so nothing started
or sustained the scroll.

Implement selection-drag autoscroll for macOS by reusing the existing
selection-autoscroll machinery that iOS relies on (EventHandler's
m_isAutoscrolling / m_targetAutoscrollPositionInRootView, AutoscrollController's
50ms Selection timer, and the WebPage StartAutoscrollAtPosition /
CancelAutoscroll messages). The decision of when to autoscroll lives entirely
in the web process, which already computes the visible content rect and owns
the edge-band constants, so the UI process does not duplicate that geometry.

How it works:

  - On each extent-point update during a range-selection drag (the messages
    the UI process already sends as the cursor moves, and re-sends as the page
    scrolls), WebPage::updateSelectionWithExtentPointAndBoundary asks the
    EventHandler whether the point sits within the visible-edge band. If so it
    starts (or keeps) selection autoscroll targeting that point; otherwise it
    cancels. This is re-evaluated every update, so holding the cursor near the
    edge keeps scrolling and dragging back toward the middle stops it -- the
    macOS counterpart to UIKit's UITextAutoscrolling edge detection.

  - While autoscrolling, 
EventHandler::targetPositionInWindowForSelectionAutoscroll
    pushes the target point past the nearest visible-content edge, scaling the
    push by how deep into the edge band the point is. Because the push is a 
fixed
    distance past the edge in root-view coordinates, the autoscroll timer's
    windowToContents mapping yields a stable per-tick scroll delta, so the page
    keeps scrolling at a constant velocity for as long as the gesture holds near
    (or past) the edge -- without the UI process having to re-push a target.

  - As the page scrolls, WebViewImpl::pageDidScroll asks the text selection
    controller to re-extend the selection toward the last drag point, so the
    selection keeps growing into the newly revealed content. This mirrors the
    iOS -updateSelection re-extension.

The edge-detection predicate (isPointNearSelectionAutoscrollEdge) and the
target-push (pushSelectionAutoscrollTargetPastVisibleEdges) share a single
helper, selectionAutoscrollGeometry, for the visible rect and page-scale
factor. Sharing one source of truth guarantees the "should we scroll" decision
and "how far past the edge" computation use the same edge band, so they cannot
disagree (e.g. when the page is magnified to a scale below 1).

While autoscrolling on Cocoa, EventHandler::updateSelectionForMouseDrag is
suppressed: the selection is re-extended by the UI process toward the live drag
point as the page scrolls, so re-extending here from the stale last-known mouse
position would fight that. This is a no-op on iOS, where
supportsSelectionUpdatesOnMouseDrag() already returns false; the corresponding
preprocessor guard is widened from !PLATFORM(IOS_FAMILY) to !PLATFORM(COCOA) to
match.

* Source/WebCore/page/EventHandler.cpp:
(WebCore::EventHandler::updateSelectionForMouseDrag): Bail during autoscroll on
Cocoa so the UI-process-driven re-extension is authoritative.

* Source/WebCore/page/EventHandler.h:
* Source/WebCore/page/mac/EventHandlerMac.mm:
(WebCore::selectionAutoscrollGeometry): Added; shared visible-rect + zoom scale.
(WebCore::EventHandler::isPointNearSelectionAutoscrollEdge): Added.
(WebCore::EventHandler::targetPositionInWindowForSelectionAutoscroll): Push the
target past the nearest visible edge while autoscrolling.

* Source/WebKit/WebProcess/WebPage/WebPage.h:
* Source/WebKit/WebProcess/WebPage/Cocoa/WebPageCocoa.mm:
(WebKit::WebPage::rendererForSelectionAutoscroll): Added; factored out renderer
resolution shared by the start path and the extent-point edge check.

(WebKit::WebPage::startAutoscrollAtPosition): Use the shared helper.

(WebKit::WebPage::updateSelectionWithExtentPointAndBoundary): On macOS, start or
cancel selection autoscroll based on edge proximity.

* Source/WebKit/UIProcess/mac/WKTextSelectionController.h:
* Source/WebKit/UIProcess/mac/WKTextSelectionController.swift:
(reextendSelectionForAutoscrollIfNeeded): Re-extend toward the last drag point
on scroll; gated on an in-flight drag rather than UI-cached autoscroll state.
(beginRangeSelection / continueRangeSelection / endRangeSelection): Track the
last extent point; cancel autoscroll at gesture begin/end as a safety net.

* Source/WebKit/UIProcess/mac/WebViewImpl.mm:
(WebKit::WebViewImpl::pageDidScroll): Re-extend the selection as the page
autoscrolls.

* Tools/TestWebKitAPI/Tests/WebKit/WebPage/AppKitGesturesTests.swift:
(draggingSelectionToWindowEdgeAutoscrolls): Added.

(holdingSelectionDragNearEdgeKeepsScrolling): Added; verifies the scroll
continues across the hold rather than bursting and stopping early.

(holdingSelectionDragMidContentDoesNotAutoscroll): Added.
(selectionAutoscrollStopsAfterGestureEnds): Added.
(draggingSelectionToTopEdgeScrollsUp): Added.

Canonical link: https://commits.webkit.org/315834@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to