2016-12-13 23:22:03 +00:00
|
|
|
|
|
|
|
window.UIHelper = class UIHelper {
|
2019-06-01 00:43:56 +00:00
|
|
|
static isIOSFamily()
|
2016-12-13 23:22:03 +00:00
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
return testRunner.isIOSFamily;
|
2016-12-13 23:22:03 +00:00
|
|
|
}
|
|
|
|
|
2016-12-14 21:57:37 +00:00
|
|
|
static isWebKit2()
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
return testRunner.isWebKit2;
|
2016-12-14 21:57:37 +00:00
|
|
|
}
|
|
|
|
|
2019-02-01 00:38:55 +00:00
|
|
|
static doubleClickAt(x, y)
|
|
|
|
{
|
|
|
|
eventSender.mouseMoveTo(x, y);
|
|
|
|
eventSender.mouseDown();
|
|
|
|
eventSender.mouseUp();
|
|
|
|
eventSender.mouseDown();
|
|
|
|
eventSender.mouseUp();
|
|
|
|
}
|
|
|
|
|
2020-10-22 00:40:55 +00:00
|
|
|
static doubleClickAtMouseDown(x1, y1)
|
|
|
|
{
|
|
|
|
eventSender.mouseMoveTo(x1, y1);
|
|
|
|
eventSender.mouseDown();
|
|
|
|
eventSender.mouseUp();
|
|
|
|
eventSender.mouseDown();
|
|
|
|
}
|
|
|
|
|
|
|
|
static mouseUp()
|
|
|
|
{
|
|
|
|
eventSender.mouseUp();
|
|
|
|
}
|
|
|
|
|
2019-02-01 00:38:55 +00:00
|
|
|
static doubleClickAtThenDragTo(x1, y1, x2, y2)
|
|
|
|
{
|
|
|
|
eventSender.mouseMoveTo(x1, y1);
|
|
|
|
eventSender.mouseDown();
|
|
|
|
eventSender.mouseUp();
|
|
|
|
eventSender.mouseDown();
|
|
|
|
eventSender.mouseMoveTo(x2, y2);
|
|
|
|
eventSender.mouseUp();
|
|
|
|
}
|
2020-04-09 16:25:08 +00:00
|
|
|
|
2020-10-22 00:40:55 +00:00
|
|
|
static dragMouseAcrossElement(element)
|
|
|
|
{
|
|
|
|
const x1 = element.offsetLeft + element.offsetWidth;
|
|
|
|
const x2 = element.offsetLeft + element.offsetWidth * .75;
|
|
|
|
const x3 = element.offsetLeft + element.offsetWidth / 2;
|
|
|
|
const x4 = element.offsetLeft + element.offsetWidth / 4;
|
|
|
|
const x5 = element.offsetLeft;
|
|
|
|
const y = element.offsetTop + element.offsetHeight / 2;
|
|
|
|
eventSender.mouseMoveTo(x1, y);
|
|
|
|
eventSender.mouseMoveTo(x2, y);
|
|
|
|
eventSender.mouseMoveTo(x3, y);
|
|
|
|
eventSender.mouseMoveTo(x4, y);
|
|
|
|
eventSender.mouseMoveTo(x5, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static doubleClickElementMouseDown(element1)
|
|
|
|
{
|
|
|
|
const x1 = element1.offsetLeft + element1.offsetWidth / 2;
|
|
|
|
const y1 = element1.offsetTop + element1.offsetHeight / 2;
|
|
|
|
return UIHelper.doubleClickAtMouseDown(x1, y1);
|
|
|
|
}
|
|
|
|
|
2020-04-24 01:08:44 +00:00
|
|
|
static async moveMouseAndWaitForFrame(x, y)
|
|
|
|
{
|
|
|
|
eventSender.mouseMoveTo(x, y);
|
|
|
|
await UIHelper.animationFrame();
|
|
|
|
}
|
|
|
|
|
2020-04-09 16:25:08 +00:00
|
|
|
static async mouseWheelScrollAt(x, y, beginX, beginY, deltaX, deltaY)
|
2020-03-07 01:45:55 +00:00
|
|
|
{
|
2020-04-09 16:25:08 +00:00
|
|
|
if (beginX === undefined)
|
|
|
|
beginX = 0;
|
|
|
|
if (beginY === undefined)
|
|
|
|
beginY = -1;
|
|
|
|
|
|
|
|
if (deltaX === undefined)
|
|
|
|
deltaX = 0;
|
|
|
|
if (deltaY === undefined)
|
|
|
|
deltaY = -10;
|
|
|
|
|
2020-03-07 01:45:55 +00:00
|
|
|
eventSender.monitorWheelEvents();
|
|
|
|
eventSender.mouseMoveTo(x, y);
|
2020-04-09 16:25:08 +00:00
|
|
|
eventSender.mouseScrollByWithWheelAndMomentumPhases(beginX, beginY, "began", "none");
|
|
|
|
eventSender.mouseScrollByWithWheelAndMomentumPhases(deltaX, deltaY, "changed", "none");
|
2020-03-07 01:45:55 +00:00
|
|
|
eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, "ended", "none");
|
|
|
|
return new Promise(resolve => {
|
|
|
|
eventSender.callAfterScrollingCompletes(() => {
|
2020-04-02 21:35:43 +00:00
|
|
|
requestAnimationFrame(resolve);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-05-03 03:49:16 +00:00
|
|
|
static async mouseWheelMayBeginAt(x, y)
|
|
|
|
{
|
|
|
|
eventSender.mouseMoveTo(x, y);
|
|
|
|
eventSender.mouseScrollByWithWheelAndMomentumPhases(x, y, "maybegin", "none");
|
|
|
|
await UIHelper.animationFrame();
|
|
|
|
}
|
|
|
|
|
|
|
|
static async mouseWheelCancelAt(x, y)
|
|
|
|
{
|
|
|
|
eventSender.mouseMoveTo(x, y);
|
|
|
|
eventSender.mouseScrollByWithWheelAndMomentumPhases(x, y, "cancelled", "none");
|
|
|
|
await UIHelper.animationFrame();
|
|
|
|
}
|
|
|
|
|
2020-04-02 21:35:43 +00:00
|
|
|
static async waitForScrollCompletion()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
eventSender.callAfterScrollingCompletes(() => {
|
2020-03-07 01:45:55 +00:00
|
|
|
requestAnimationFrame(resolve);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static async animationFrame()
|
|
|
|
{
|
|
|
|
return new Promise(requestAnimationFrame);
|
|
|
|
}
|
2019-02-01 00:38:55 +00:00
|
|
|
|
Update event regions only once per frame
https://bugs.webkit.org/show_bug.cgi?id=215132
<rdar://problem/66533779>
Reviewed by Darin Adler.
Source/WebCore:
Event regions (for touch-action, editable areas etc) were updated as part of
compositing updates, but we only need their output once per rendering update, so
move their computation out of RenderLayerCompositor::updateBackingAndHierarchy()
and into a new RenderLayer tree walk that is called from Page::doAfterUpdateRendering().
RenderLayerBacking stores a dirty bit to track when regions need to be updated.
Reduces the amount of time spent in rendering updates when scrolling on facebook.com
on iPad, which has lots of discontiguous touch-action regions.
* dom/Document.cpp:
(WebCore::Document::updateEventRegions):
* dom/Document.h:
* page/Frame.cpp:
(WebCore::Frame::layerTreeAsText const):
* page/Page.cpp:
(WebCore::Page::doAfterUpdateRendering):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::calculateClipRects const):
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::maintainsEventRegion const):
(WebCore::RenderLayerBacking::updateEventRegion):
* rendering/RenderLayerBacking.h:
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::updateEventRegions):
(WebCore::RenderLayerCompositor::updateBackingAndHierarchy):
* rendering/RenderLayerCompositor.h:
LayoutTests:
Tests that dispatch mouseWheel events in a way that tests event regions need to wait
now for a rendering update. `await UIHelper.animationFrame()` is not enough, because
the function resumes inside a microtask at the end of the requestAnimationFrame callback,
which is before we've completed the rest of the rendering update, and thus before
the event regions have been updated.
In addition, `await UIHelper.animationFrame()` followed by eventSender calls to issue
wheel events actually trigger Page::updateRendering() re-entrancy, via the
WKBundlePageForceRepaint() in EventSendingController::mouseScrollByWithWheelAndMomentumPhases().
To fix this, add and use UIHelper.renderingUpdate(), which waits for a rAF and uses a setTimeout()
to get past the end of the current rendering update.
* fast/scrolling/mac/absolute-in-overflow-scroll-dynamic-expected.html:
* fast/scrolling/mac/absolute-in-overflow-scroll-dynamic.html:
* fast/scrolling/mac/absolute-in-overflow-scroll.html:
* fast/scrolling/mac/async-scroll-overflow-hidden-on-one-axis.html:
* fast/scrolling/mac/async-scroll-overflow-rtl-zoomed.html:
* fast/scrolling/mac/async-scroll-overflow-top-inset.html:
* fast/scrolling/mac/async-scroll-overflow.html:
* fast/scrolling/mac/clip-path-hit-test.html:
* fast/scrolling/mac/move-node-in-overflow-scroll.html:
* fast/scrolling/mac/overflow-scrolled-document.html:
* fast/scrolling/mac/overflow-zoomed-document.html:
* fast/scrolling/mac/overlapped-overflow-scroll.html:
* resources/ui-helper.js:
(window.UIHelper.async renderingUpdate):
Canonical link: https://commits.webkit.org/227970@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@265289 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-08-05 16:36:43 +00:00
|
|
|
static async renderingUpdate()
|
|
|
|
{
|
|
|
|
await UIHelper.animationFrame();
|
|
|
|
await UIHelper.delayFor(0);
|
|
|
|
}
|
|
|
|
|
2020-05-03 03:49:16 +00:00
|
|
|
static async waitForCondition(conditionFunc)
|
|
|
|
{
|
|
|
|
while (!conditionFunc()) {
|
|
|
|
await UIHelper.animationFrame();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[iOS] WKWebView touch event gesture recognition should not block the application process main thread when possible
https://bugs.webkit.org/show_bug.cgi?id=204664
<rdar://problem/38670692>
Reviewed by Tim Horton.
Source/WebKit:
Adds a mechanism that allows some sync touch events on iOS to be sent asynchronously. To do this, we use the
deferring gesture mechanism introduced in trac.webkit.org/r253005 to defer all gestures under WKContentView (and
WebKit-owned scroll views) when a touch starts, such that they will not recognize until we know that the page
has either prevented default or not (assuming that the touch was over an active listener). See below for more
details.
Tests: fast/events/touch/ios/prevent-default-on-touch-start-with-slow-event-listener.html
fast/events/touch/ios/scroll-on-touch-start-with-slow-event-listener.html
* UIProcess/GenericCallback.h:
* UIProcess/PageClient.h:
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm:
(-[WKChildScrollView gestureRecognizer:shouldRequireFailureOfGestureRecognizer:]):
(-[WKChildScrollView gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]):
Implement gesture recognizer delegate hooks to add dynamic failure requirements between a child scroll view's
gestures and the new deferring gesture recognizers on WKContentView. This allows pan gestures over a scrollable
container to hold off on recognizing while the deferring gesture recognizer has not failed yet.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::handlePreventableTouchEvent):
(WebKit::WebPageProxy::handleUnpreventableTouchEvent):
Rename handleTouchEventSynchronously and handleTouchEventAsynchronously to handlePreventableTouchEvent and
handleUnpreventableTouchEvent, respectively. Instead of always sending touchstart events that may prevent native
gestures synchronously, we may now go through the same `EventDispatcher::TouchEvent` codepath used when
dispatching touch events in passive tracking regions. However, in the case of preventable touchstarts, we
additionally store a completion callback that is invoked after the touch event has been handled by the page; we
then either un-defer or prevent native gestures here (depending on whether the page prevented default) by
calling PageClient::doneDeferringNativeGestures.
Non-touchstart events are still dispatched synchronously, to ensure that calling preventDefault() on touchmove
and touchend continue to prevent default gestures from recognizing.
(WebKit::WebPageProxy::boolCallback):
(WebKit::WebPageProxy::handleTouchEventSynchronously): Deleted.
(WebKit::WebPageProxy::handleTouchEventAsynchronously): Deleted.
See above.
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::isHandlingPreventableTouchStart const):
This is used in WKContentView to determine whether deferring gestures need to remain active after the touch
ends. See below for more detail.
* UIProcess/WebPageProxy.messages.in:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::doneDeferringNativeGestures):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[UIGestureRecognizer _wk_cancel]):
(-[WKContentView setupInteraction]):
(-[WKContentView cleanupInteraction]):
(-[WKContentView _removeDefaultGestureRecognizers]):
(-[WKContentView _addDefaultGestureRecognizers]):
Add and remove the new deferring gesture recognizers here.
(-[WKContentView _webTouchEventsRecognized:]):
(-[WKContentView _webTouchEvent:preventsNativeGestures:]):
(-[WKContentView _doneDeferringNativeGestures:]):
(-[WKContentView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
(-[WKContentView ensurePositionInformationIsUpToDate:]):
Drive-by fix: add a missing hasRunningProcess check that causes a flaky assertion under
`AuxiliaryProcessProxy::connection()` in layout tests.
(-[WKContentView gestureRecognizer:shouldRequireFailureOfGestureRecognizer:]):
(-[WKContentView gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]):
Add dynamic failure requirements between WKContentView's gestures (including all text interaction, context menu,
and drag and drop gestures) and the new deferring gesture recognizers.
(-[WKContentView _didStartProvisionalLoadForMainFrame]):
Force the two-finger double tap gesture recognizer to reset when loading a new page. Without this, the layout
test fast/events/ios/click-event-while-editing-node.html will rarely fail when run after a test that dispatches
a two-finger tap, such as fast/events/ios/click-event-two-finger-single-tap-meta-key.html. This is because the
new deferring gestures will temporarily unite multi-finger tap gestures with one-finger double tap gestures in
the same subgraph when performing a tap gesture with more than one finger. This means that there's a 300 ms
delay before a normal single tap can be recognized again, which (without forcing the two-finger double tap to
reset) would cause a subsequent test that loads in under 300 ms and attempts to send a tap to fail.
(-[WKContentView deferringGestureRecognizer:shouldDeferGesturesAfterBeginningTouchesWithEvent:]):
Avoid deferring native gestures if the scroll view is decelerating; this matches behavior of the web touch event
gesture recognizer.
(-[WKContentView deferringGestureRecognizer:shouldDeferGesturesAfterEndingTouchesWithEvent:]):
Normally, after -touchesEnded:withEvent:, we stop deferring native gesture recognizers by failing the deferring
gestures. However, if we're still waiting for a response from the web process, then let
-_doneDeferringNativeGestures: handle this instead.
(-[WKContentView deferringGestureRecognizer:shouldDeferOtherGestureRecognizer:]):
(-[WKContentView deferringGestureRecognizer:shouldDeferGesturesWithEvent:]): Deleted.
Renamed to -shouldDeferGesturesAfterBeginningTouchesWithEvent:.
* UIProcess/ios/WKDeferringGestureRecognizer.h:
* UIProcess/ios/WKDeferringGestureRecognizer.mm:
(-[WKDeferringGestureRecognizer touchesBegan:withEvent:]):
(-[WKDeferringGestureRecognizer touchesEnded:withEvent:]):
Override this and add a new delegate hook to determine whether we want the deferring gesture recognizer to
immediately fail when touches end. It's important to override this and transition to failure state in this case,
since not doing so could mean that the deferring gestures stay in Possible state forever; this may lead to the
gesture subgraph containing these deferring gestures being unable to reset, since it's waiting for the deferring
gesture to either fail or end.
* UIProcess/ios/WKScrollView.mm:
(-[WKScrollView gestureRecognizer:shouldRequireFailureOfGestureRecognizer:]):
(-[WKScrollView gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]):
Defer more scroll view gestures.
* WebProcess/WebPage/EventDispatcher.cpp:
(WebKit::EventDispatcher::touchEvent):
Add an optional CallbackID parameter to this IPC message. If a callback ID is given, then we avoid coalescing
the touch event. To implement this, we additionally refactor the queued touch events map to contain lists of
<WebTouchEvent, Optional<CallbackID>> pairs; if a queued touch event has a corresponding CallbackID, then we
fire the callback corresponding to the ID, indicating whether the touch event was handled by the page.
* WebProcess/WebPage/EventDispatcher.h:
* WebProcess/WebPage/EventDispatcher.messages.in:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::dispatchAsynchronousTouchEvents):
LayoutTests:
* fast/events/touch/ios/prevent-default-on-touch-start-with-slow-event-listener-expected.txt: Added.
* fast/events/touch/ios/prevent-default-on-touch-start-with-slow-event-listener.html: Added.
* fast/events/touch/ios/scroll-on-touch-start-with-slow-event-listener-expected.txt: Added.
* fast/events/touch/ios/scroll-on-touch-start-with-slow-event-listener.html: Added.
Add new layout tests to cover behaviors when panning over active touchstart handlers that spin for an extended
length of time (in this case, 400 milliseconds) in overflow scrolling containers. A touchstart handler that
prevents default should still block scrolling, and a touchstart handler that does not should still allow the
user to scroll.
* fast/events/touch/ios/show-modal-alert-during-touch-start.html:
* http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt:
* http/tests/security/anchor-download-block-crossorigin-expected.txt:
Rebaseline these tests by changing some line numbers.
* resources/ui-helper.js:
(window.UIHelper.sendEventStream.return.new.Promise):
(window.UIHelper.sendEventStream):
Add a new UIHelper method to send a JSON object as an event stream.
(UIHelper.EventStreamBuilder.prototype._reset):
(UIHelper.EventStreamBuilder.prototype.begin):
(UIHelper.EventStreamBuilder.prototype.move):
(UIHelper.EventStreamBuilder.prototype.end):
(UIHelper.EventStreamBuilder.prototype.takeResult):
Add a new helper class to make it easier to construct event streams, for the purposes of sending to
UIScriptController::sendEventStream.
Canonical link: https://commits.webkit.org/218214@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@253267 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-12-08 03:57:23 +00:00
|
|
|
static sendEventStream(eventStream)
|
|
|
|
{
|
|
|
|
const eventStreamAsString = JSON.stringify(eventStream);
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
uiController.sendEventStream(\`${eventStreamAsString}\`, () => {
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
});
|
|
|
|
})();
|
|
|
|
`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-02-11 23:24:23 +00:00
|
|
|
static tapAt(x, y, modifiers=[])
|
2017-01-10 07:02:20 +00:00
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
console.assert(this.isIOSFamily());
|
2017-01-10 07:02:20 +00:00
|
|
|
|
|
|
|
if (!this.isWebKit2()) {
|
2019-02-11 23:24:23 +00:00
|
|
|
console.assert(!modifiers || !modifiers.length);
|
2017-01-10 07:02:20 +00:00
|
|
|
eventSender.addTouchPoint(x, y);
|
|
|
|
eventSender.touchStart();
|
|
|
|
eventSender.releaseTouchPoint(0);
|
|
|
|
eventSender.touchEnd();
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
testRunner.runUIScript(`
|
2019-02-11 23:24:23 +00:00
|
|
|
uiController.singleTapAtPointWithModifiers(${x}, ${y}, ${JSON.stringify(modifiers)}, function() {
|
2019-01-17 19:15:57 +00:00
|
|
|
uiController.uiScriptComplete();
|
2017-01-10 07:02:20 +00:00
|
|
|
});`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-07-16 21:59:33 +00:00
|
|
|
static tapElement(element, delay = 0)
|
|
|
|
{
|
|
|
|
const x = element.offsetLeft + (element.offsetWidth / 2);
|
|
|
|
const y = element.offsetTop + (element.offsetHeight / 2);
|
|
|
|
this.tapAt(x, y);
|
|
|
|
}
|
|
|
|
|
2020-06-29 23:58:59 +00:00
|
|
|
static doubleTapElement(element, delay = 0)
|
|
|
|
{
|
|
|
|
const x = element.offsetLeft + (element.offsetWidth / 2);
|
|
|
|
const y = element.offsetTop + (element.offsetHeight / 2);
|
|
|
|
this.doubleTapAt(x, y, delay);
|
|
|
|
}
|
|
|
|
|
REGRESSION (iOS 13): Tests that simulate multiple back-to-back single taps fail or time out
https://bugs.webkit.org/show_bug.cgi?id=201129
<rdar://problem/51857277>
Reviewed by Tim Horton.
Source/WebKit:
Adds a new SPI hook in WebKit to let clients know when a synthetic tap gesture that has ended has been reset.
See Tools/ChangeLog and LayoutTests/ChangeLog for more details.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _doAfterResettingSingleTapGesture:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _singleTapDidReset:]):
(-[WKContentView _doAfterResettingSingleTapGesture:]):
Tools:
The tests in editing/pasteboard/ios were timing out on iOS 13 before this change. This is because they simulate
back-to-back single taps; while this is recognized as two single taps on iOS 12 and prior, only the first single
tap is recognized on iOS 13 (and the second is simply dropped on the floor). This occurs because the synthetic
single tap gesture is reset slightly later on iOS 13 compared to iOS 12, so when the second tap is dispatched,
the gesture recognizer is still in "ended" state after the first tap on iOS 13, which means the gesture isn't
capable of recognizing further touches yet.
In UIKit, a gesture recognizer is only reset once its UIGestureEnvironment's containing dependency subgraph no
longer contains gestures that are active. In iOS 12, the synthetic click gesture is a part of a dependency
subgraph that contains only itself and the normal (blocking) double tap gesture which requires the click to fail
before it can be recognized; immediately after simulating the tap, both these gestures are inactive, which
allows both of them to be reset.
However, in iOS 13, the synthetic click gesture is part of a gesture dependency graph that contains the double
tap for double click gesture, as well as the non-blocking double tap gesture, both of which are still active
immediately after sending the first tap. This change in dependencies is caused by the introduction of
UIUndoGestureInteraction's single and double three-finger tap gestures, which (in -[UIUndoGestureInteraction
gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]) explicitly add all other taps as failure
requirements. This effectively links the synthetic single tap gesture to most of the other gestures in
WKContentView's dependency graph by way of these tap gestures for the undo interaction.
All this means that there is now a short (~50 ms) delay after the synthetic single tap gestures is recognized,
before it can be recognized again. To account for this new delay in our test infrastructure, simply wait for
single tap gestures that have ended to reset before attempting to send subsequent single taps. We do this by
introducing WebKit testing SPI to invoke a completion handler after resetting the synthetic click gesture (only
if necessary - i.e., if the gesture is in ended state when we are about to begin simulating the tap). This
allows calls to `UIScriptController::singleTapAtPoint` to be reliably recognized as single taps without
requiring arbitrary 120 ms "human speed" delays.
This fixes a number of flaky or failing layout tests, including the tests in editing/pasteboard/ios.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::doubleTapAtPoint):
Add a `delay` parameter to `doubleTapAtPoint`. A number of layout tests were actually simulating double click
gestures by simulating two back-to-back single taps; this is done for the purposes of being able to add a "human
speed" delay prior to the second single tap gesture. After the change to wait for the single tap gesture to
reset before attempting to simulate the next tap, this strategy no longer works, since the second gesture is
recognized only as a single tap instead of a double tap.
Instead, we add a delay parameter to `UIScriptController::doubleTapAtPoint`, which the "human speed" double tap
gestures use instead to wait after simulating the first tap.
* WebKitTestRunner/ios/HIDEventGenerator.h:
* WebKitTestRunner/ios/HIDEventGenerator.mm:
(-[HIDEventGenerator _waitFor:]):
(-[HIDEventGenerator sendTaps:location:withNumberOfTouches:delay:completionBlock:]):
Plumb the tap gesture delay through to this helper method.
(-[HIDEventGenerator tap:completionBlock:]):
(-[HIDEventGenerator doubleTap:delay:completionBlock:]):
(-[HIDEventGenerator twoFingerTap:completionBlock:]):
(-[HIDEventGenerator sendTaps:location:withNumberOfTouches:completionBlock:]): Deleted.
(-[HIDEventGenerator doubleTap:completionBlock:]): Deleted.
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::waitForSingleTapToReset const):
Add a new helper to wait for the content view's single tap gesture to reset if needed; call this before
attempting to simulate single taps (either using a stylus, or with a regular touch).
(WTR::UIScriptControllerIOS::singleTapAtPointWithModifiers):
(WTR::UIScriptControllerIOS::doubleTapAtPoint):
(WTR::UIScriptControllerIOS::stylusTapAtPointWithModifiers):
LayoutTests:
Adjusts a few layout tests after changes to UIScriptController::doubleTapAtPoint and
UIScriptController::singleTapAtPoint.
* editing/selection/ios/change-selection-by-tapping.html:
Tweak this test to tap the page 12 times instead of 20 (which seems to cause occasional timeouts locally, when
running all layout tests with a dozen active simulators).
* fast/events/ios/double-tap-zoom.html:
* fast/events/ios/viewport-device-width-allows-double-tap-zoom-out.html:
* fast/events/ios/viewport-shrink-to-fit-allows-double-tap.html:
Augment a few call sites of `doubleTapAtPoint` with a 0 delay. Ideally, these should just use ui-helper.js, but
we can refactor these tests as a part of folding basic-gestures.js into ui-helper.js.
* http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt:
* http/tests/security/anchor-download-block-crossorigin-expected.txt:
Rebaseline these layout tests, due to change in line numbers.
* platform/ipad/TestExpectations:
Unskip these tests on iPad, now that they should pass.
* pointerevents/utils.js:
(const.ui.new.UIController.prototype.doubleTapToZoom):
* resources/basic-gestures.js:
(return.new.Promise.):
(return.new.Promise):
Adjust some more call sites of `doubleTapAtPoint`. Ideally, these should use just `ui-helper.js` too.
* resources/ui-helper.js:
(window.UIHelper.doubleTapAt.return.new.Promise):
(window.UIHelper.doubleTapAt):
(window.UIHelper.humanSpeedDoubleTapAt):
(window.UIHelper.humanSpeedZoomByDoubleTappingAt):
Add a delay parameter to `doubleTapAt` to specify a delay after each simulated tap. By default, this is 0, but
the `humanSpeed*` helpers add a delay of 120 milliseconds. Additionally, these helpers were previously calling
`singleTapAtPoint` twice, with a timeout in between to add a delay. Instead, call `doubleTapAtPoint` with a
nonzero delay; otherwise, we'll end up waiting in `singleTapAtPoint` for the gesture subgraph containing both
the double tap gestures and the synthetic single tap gesture to reset, which causes these two single taps to no
longer be recognized as a double tap gesture.
(window.UIHelper.zoomByDoubleTappingAt):
Canonical link: https://commits.webkit.org/214834@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249112 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-08-26 19:37:29 +00:00
|
|
|
static doubleTapAt(x, y, delay = 0)
|
2019-01-17 19:15:57 +00:00
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
console.assert(this.isIOSFamily());
|
2019-01-17 19:15:57 +00:00
|
|
|
|
|
|
|
if (!this.isWebKit2()) {
|
|
|
|
eventSender.addTouchPoint(x, y);
|
|
|
|
eventSender.touchStart();
|
|
|
|
eventSender.releaseTouchPoint(0);
|
|
|
|
eventSender.touchEnd();
|
|
|
|
eventSender.addTouchPoint(x, y);
|
|
|
|
eventSender.touchStart();
|
|
|
|
eventSender.releaseTouchPoint(0);
|
|
|
|
eventSender.touchEnd();
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
testRunner.runUIScript(`
|
REGRESSION (iOS 13): Tests that simulate multiple back-to-back single taps fail or time out
https://bugs.webkit.org/show_bug.cgi?id=201129
<rdar://problem/51857277>
Reviewed by Tim Horton.
Source/WebKit:
Adds a new SPI hook in WebKit to let clients know when a synthetic tap gesture that has ended has been reset.
See Tools/ChangeLog and LayoutTests/ChangeLog for more details.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _doAfterResettingSingleTapGesture:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _singleTapDidReset:]):
(-[WKContentView _doAfterResettingSingleTapGesture:]):
Tools:
The tests in editing/pasteboard/ios were timing out on iOS 13 before this change. This is because they simulate
back-to-back single taps; while this is recognized as two single taps on iOS 12 and prior, only the first single
tap is recognized on iOS 13 (and the second is simply dropped on the floor). This occurs because the synthetic
single tap gesture is reset slightly later on iOS 13 compared to iOS 12, so when the second tap is dispatched,
the gesture recognizer is still in "ended" state after the first tap on iOS 13, which means the gesture isn't
capable of recognizing further touches yet.
In UIKit, a gesture recognizer is only reset once its UIGestureEnvironment's containing dependency subgraph no
longer contains gestures that are active. In iOS 12, the synthetic click gesture is a part of a dependency
subgraph that contains only itself and the normal (blocking) double tap gesture which requires the click to fail
before it can be recognized; immediately after simulating the tap, both these gestures are inactive, which
allows both of them to be reset.
However, in iOS 13, the synthetic click gesture is part of a gesture dependency graph that contains the double
tap for double click gesture, as well as the non-blocking double tap gesture, both of which are still active
immediately after sending the first tap. This change in dependencies is caused by the introduction of
UIUndoGestureInteraction's single and double three-finger tap gestures, which (in -[UIUndoGestureInteraction
gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]) explicitly add all other taps as failure
requirements. This effectively links the synthetic single tap gesture to most of the other gestures in
WKContentView's dependency graph by way of these tap gestures for the undo interaction.
All this means that there is now a short (~50 ms) delay after the synthetic single tap gestures is recognized,
before it can be recognized again. To account for this new delay in our test infrastructure, simply wait for
single tap gestures that have ended to reset before attempting to send subsequent single taps. We do this by
introducing WebKit testing SPI to invoke a completion handler after resetting the synthetic click gesture (only
if necessary - i.e., if the gesture is in ended state when we are about to begin simulating the tap). This
allows calls to `UIScriptController::singleTapAtPoint` to be reliably recognized as single taps without
requiring arbitrary 120 ms "human speed" delays.
This fixes a number of flaky or failing layout tests, including the tests in editing/pasteboard/ios.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::doubleTapAtPoint):
Add a `delay` parameter to `doubleTapAtPoint`. A number of layout tests were actually simulating double click
gestures by simulating two back-to-back single taps; this is done for the purposes of being able to add a "human
speed" delay prior to the second single tap gesture. After the change to wait for the single tap gesture to
reset before attempting to simulate the next tap, this strategy no longer works, since the second gesture is
recognized only as a single tap instead of a double tap.
Instead, we add a delay parameter to `UIScriptController::doubleTapAtPoint`, which the "human speed" double tap
gestures use instead to wait after simulating the first tap.
* WebKitTestRunner/ios/HIDEventGenerator.h:
* WebKitTestRunner/ios/HIDEventGenerator.mm:
(-[HIDEventGenerator _waitFor:]):
(-[HIDEventGenerator sendTaps:location:withNumberOfTouches:delay:completionBlock:]):
Plumb the tap gesture delay through to this helper method.
(-[HIDEventGenerator tap:completionBlock:]):
(-[HIDEventGenerator doubleTap:delay:completionBlock:]):
(-[HIDEventGenerator twoFingerTap:completionBlock:]):
(-[HIDEventGenerator sendTaps:location:withNumberOfTouches:completionBlock:]): Deleted.
(-[HIDEventGenerator doubleTap:completionBlock:]): Deleted.
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::waitForSingleTapToReset const):
Add a new helper to wait for the content view's single tap gesture to reset if needed; call this before
attempting to simulate single taps (either using a stylus, or with a regular touch).
(WTR::UIScriptControllerIOS::singleTapAtPointWithModifiers):
(WTR::UIScriptControllerIOS::doubleTapAtPoint):
(WTR::UIScriptControllerIOS::stylusTapAtPointWithModifiers):
LayoutTests:
Adjusts a few layout tests after changes to UIScriptController::doubleTapAtPoint and
UIScriptController::singleTapAtPoint.
* editing/selection/ios/change-selection-by-tapping.html:
Tweak this test to tap the page 12 times instead of 20 (which seems to cause occasional timeouts locally, when
running all layout tests with a dozen active simulators).
* fast/events/ios/double-tap-zoom.html:
* fast/events/ios/viewport-device-width-allows-double-tap-zoom-out.html:
* fast/events/ios/viewport-shrink-to-fit-allows-double-tap.html:
Augment a few call sites of `doubleTapAtPoint` with a 0 delay. Ideally, these should just use ui-helper.js, but
we can refactor these tests as a part of folding basic-gestures.js into ui-helper.js.
* http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt:
* http/tests/security/anchor-download-block-crossorigin-expected.txt:
Rebaseline these layout tests, due to change in line numbers.
* platform/ipad/TestExpectations:
Unskip these tests on iPad, now that they should pass.
* pointerevents/utils.js:
(const.ui.new.UIController.prototype.doubleTapToZoom):
* resources/basic-gestures.js:
(return.new.Promise.):
(return.new.Promise):
Adjust some more call sites of `doubleTapAtPoint`. Ideally, these should use just `ui-helper.js` too.
* resources/ui-helper.js:
(window.UIHelper.doubleTapAt.return.new.Promise):
(window.UIHelper.doubleTapAt):
(window.UIHelper.humanSpeedDoubleTapAt):
(window.UIHelper.humanSpeedZoomByDoubleTappingAt):
Add a delay parameter to `doubleTapAt` to specify a delay after each simulated tap. By default, this is 0, but
the `humanSpeed*` helpers add a delay of 120 milliseconds. Additionally, these helpers were previously calling
`singleTapAtPoint` twice, with a timeout in between to add a delay. Instead, call `doubleTapAtPoint` with a
nonzero delay; otherwise, we'll end up waiting in `singleTapAtPoint` for the gesture subgraph containing both
the double tap gestures and the synthetic single tap gesture to reset, which causes these two single taps to no
longer be recognized as a double tap gesture.
(window.UIHelper.zoomByDoubleTappingAt):
Canonical link: https://commits.webkit.org/214834@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249112 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-08-26 19:37:29 +00:00
|
|
|
uiController.doubleTapAtPoint(${x}, ${y}, ${delay}, function() {
|
2019-01-17 19:15:57 +00:00
|
|
|
uiController.uiScriptComplete();
|
|
|
|
});`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[iOS] Implement a faster click detection that intercepts double-tap-to-zoom if possible
https://bugs.webkit.org/show_bug.cgi?id=195473
<rdar://problem/48718396>
Reviewed by Wenson Hsieh (with some help from Dan Bates).
Source/WebKit:
Adds a new algorithm, behind a flag FasterClicksEnabled, that can trigger a click
event without waiting to see if a double tap will occur. It does this by examining
the amount of zoom that would be triggered if it was a double tap, and if that value
doesn't exceed a set threshold, commits to the click event instead.
This is implemented by having the Web Process respond to the potential click with
some geometry information. If the UI Process receives the information before the
second tap in a double tap, it can decide to trigger a click.
* Shared/WebPreferences.yaml: New internal feature so this can be toggled in
a UI for testing.
* SourcesCocoa.txt: Renamed WKSyntheticTapGestureRecognizer.
* WebKit.xcodeproj/project.pbxproj: Ditto.
* UIProcess/ios/WKSyntheticTapGestureRecognizer.h:
* UIProcess/ios/WKSyntheticTapGestureRecognizer.m:
(-[WKSyntheticTapGestureRecognizer setGestureIdentifiedTarget:action:]):
(-[WKSyntheticTapGestureRecognizer setGestureFailedTarget:action:]):
(-[WKSyntheticTapGestureRecognizer setResetTarget:action:]):
(-[WKSyntheticTapGestureRecognizer setState:]):
(-[WKSyntheticTapGestureRecognizer reset]): Renamed WKSyntheticClickTapGestureRecognizer to
WKSyntheticTapGestureRecognizer, changed the signature of the main function to be a bit
more clear about what it does, and added a gesture failed target.
* UIProcess/API/Cocoa/WKWebViewInternal.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initialScaleFactor]):
(-[WKWebView _contentZoomScale]):
(-[WKWebView _targetContentZoomScaleForRect:currentScale:fitEntireRect:minimumScale:maximumScale:]):
Exposed the initial content scale, the current scale and added a declaration that
was missing from the .h.
* UIProcess/WebPageProxy.messages.in: Add a new message,
HandleSmartMagnificationInformationForPotentialTap, to
communicate the geometry of the clicked node to the UI Process.
* UIProcess/PageClient.h: Pure virtual function for the geometry message response.
* UIProcess/WebPageProxy.h: Ditto.
* UIProcess/ios/PageClientImplIOS.h: Calls into the WKContentView.
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::handleSmartMagnificationInformationForPotentialTap):
* UIProcess/ios/SmartMagnificationController.h:
* UIProcess/ios/SmartMagnificationController.mm:
(WebKit::SmartMagnificationController::calculatePotentialZoomParameters): A new method that
asks the WKContentView to work out what the zoom factor will be for a potential double
tap at a location.
(WebKit::SmartMagnificationController::smartMagnificationTargetRectAndZoomScales): New implementation
of this function to avoid multiple out-arguments.
* UIProcess/ios/WKContentView.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView _initialScaleFactor]):
(-[WKContentView _contentZoomScale]):
(-[WKContentView _targetContentZoomScaleForRect:currentScale:fitEntireRect:minimumScale:maximumScale:]):
Exposed the initial content scale, the current scale and the target zoom scale. These
all just call into the WKWebView implementation.
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _createAndConfigureDoubleTapGestureRecognizer]): Use a WKSyntheticTapGestureRecognizer instead
of a generic one, so we can capture the failure.
(-[WKContentView setupInteraction]):
(-[WKContentView cleanupInteraction]):
(-[WKContentView _handleSmartMagnificationInformationForPotentialTap:origin:renderRect:fitEntireRect:viewportMinimumScale:viewportMaximumScale:]):
New method that responds to the incoming Web Process message, and decides if any
potential zoom would be "significant".
(-[WKContentView _singleTapIdentified:]):
(-[WKContentView _doubleTapDidFail:]):
(-[WKContentView _didCompleteSyntheticClick]):
(-[WKContentView _singleTapRecognized:]):
(-[WKContentView _doubleTapRecognized:]):
Add some release logging.
(-[WKContentView _singleTapCommited:]): Deleted.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::potentialTapAtPosition):
(WebKit::WebPageProxy::handleSmartMagnificationInformationForPotentialTap):
* WebProcess/WebPage/ViewGestureGeometryCollector.h:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Removed an unused parameter from the existing message.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::potentialTapAtPosition): Calculates the geometry of the element
if requested, and sends it to the UIProcess.
LayoutTests:
Implement a test (iPad only) that sets up a page with zoomable content
but not quite at a significant scale, meaning we should dispatch a click
event rather than Double Tap To Zoom.
In order to do this, a humanSpeedDoubleTapAt() method was added to
UIHelper that sleeps a bit between taps, otherwise the double tap
gesture is recognized before the Web Process has had a chance to
evaluate the potential click.
* fast/events/ios/ipad/fast-click-double-tap-sends-click-on-insignificant-zoom-expected.txt: Added.
* fast/events/ios/ipad/fast-click-double-tap-sends-click-on-insignificant-zoom.html: Added.
* platform/ios/TestExpectations:
* platform/ipad/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.humanSpeedDoubleTapAt):
Canonical link: https://commits.webkit.org/209887@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242757 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-03-11 23:43:04 +00:00
|
|
|
static humanSpeedDoubleTapAt(x, y)
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
console.assert(this.isIOSFamily());
|
[iOS] Implement a faster click detection that intercepts double-tap-to-zoom if possible
https://bugs.webkit.org/show_bug.cgi?id=195473
<rdar://problem/48718396>
Reviewed by Wenson Hsieh (with some help from Dan Bates).
Source/WebKit:
Adds a new algorithm, behind a flag FasterClicksEnabled, that can trigger a click
event without waiting to see if a double tap will occur. It does this by examining
the amount of zoom that would be triggered if it was a double tap, and if that value
doesn't exceed a set threshold, commits to the click event instead.
This is implemented by having the Web Process respond to the potential click with
some geometry information. If the UI Process receives the information before the
second tap in a double tap, it can decide to trigger a click.
* Shared/WebPreferences.yaml: New internal feature so this can be toggled in
a UI for testing.
* SourcesCocoa.txt: Renamed WKSyntheticTapGestureRecognizer.
* WebKit.xcodeproj/project.pbxproj: Ditto.
* UIProcess/ios/WKSyntheticTapGestureRecognizer.h:
* UIProcess/ios/WKSyntheticTapGestureRecognizer.m:
(-[WKSyntheticTapGestureRecognizer setGestureIdentifiedTarget:action:]):
(-[WKSyntheticTapGestureRecognizer setGestureFailedTarget:action:]):
(-[WKSyntheticTapGestureRecognizer setResetTarget:action:]):
(-[WKSyntheticTapGestureRecognizer setState:]):
(-[WKSyntheticTapGestureRecognizer reset]): Renamed WKSyntheticClickTapGestureRecognizer to
WKSyntheticTapGestureRecognizer, changed the signature of the main function to be a bit
more clear about what it does, and added a gesture failed target.
* UIProcess/API/Cocoa/WKWebViewInternal.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initialScaleFactor]):
(-[WKWebView _contentZoomScale]):
(-[WKWebView _targetContentZoomScaleForRect:currentScale:fitEntireRect:minimumScale:maximumScale:]):
Exposed the initial content scale, the current scale and added a declaration that
was missing from the .h.
* UIProcess/WebPageProxy.messages.in: Add a new message,
HandleSmartMagnificationInformationForPotentialTap, to
communicate the geometry of the clicked node to the UI Process.
* UIProcess/PageClient.h: Pure virtual function for the geometry message response.
* UIProcess/WebPageProxy.h: Ditto.
* UIProcess/ios/PageClientImplIOS.h: Calls into the WKContentView.
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::handleSmartMagnificationInformationForPotentialTap):
* UIProcess/ios/SmartMagnificationController.h:
* UIProcess/ios/SmartMagnificationController.mm:
(WebKit::SmartMagnificationController::calculatePotentialZoomParameters): A new method that
asks the WKContentView to work out what the zoom factor will be for a potential double
tap at a location.
(WebKit::SmartMagnificationController::smartMagnificationTargetRectAndZoomScales): New implementation
of this function to avoid multiple out-arguments.
* UIProcess/ios/WKContentView.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView _initialScaleFactor]):
(-[WKContentView _contentZoomScale]):
(-[WKContentView _targetContentZoomScaleForRect:currentScale:fitEntireRect:minimumScale:maximumScale:]):
Exposed the initial content scale, the current scale and the target zoom scale. These
all just call into the WKWebView implementation.
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _createAndConfigureDoubleTapGestureRecognizer]): Use a WKSyntheticTapGestureRecognizer instead
of a generic one, so we can capture the failure.
(-[WKContentView setupInteraction]):
(-[WKContentView cleanupInteraction]):
(-[WKContentView _handleSmartMagnificationInformationForPotentialTap:origin:renderRect:fitEntireRect:viewportMinimumScale:viewportMaximumScale:]):
New method that responds to the incoming Web Process message, and decides if any
potential zoom would be "significant".
(-[WKContentView _singleTapIdentified:]):
(-[WKContentView _doubleTapDidFail:]):
(-[WKContentView _didCompleteSyntheticClick]):
(-[WKContentView _singleTapRecognized:]):
(-[WKContentView _doubleTapRecognized:]):
Add some release logging.
(-[WKContentView _singleTapCommited:]): Deleted.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::potentialTapAtPosition):
(WebKit::WebPageProxy::handleSmartMagnificationInformationForPotentialTap):
* WebProcess/WebPage/ViewGestureGeometryCollector.h:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Removed an unused parameter from the existing message.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::potentialTapAtPosition): Calculates the geometry of the element
if requested, and sends it to the UIProcess.
LayoutTests:
Implement a test (iPad only) that sets up a page with zoomable content
but not quite at a significant scale, meaning we should dispatch a click
event rather than Double Tap To Zoom.
In order to do this, a humanSpeedDoubleTapAt() method was added to
UIHelper that sleeps a bit between taps, otherwise the double tap
gesture is recognized before the Web Process has had a chance to
evaluate the potential click.
* fast/events/ios/ipad/fast-click-double-tap-sends-click-on-insignificant-zoom-expected.txt: Added.
* fast/events/ios/ipad/fast-click-double-tap-sends-click-on-insignificant-zoom.html: Added.
* platform/ios/TestExpectations:
* platform/ipad/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.humanSpeedDoubleTapAt):
Canonical link: https://commits.webkit.org/209887@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242757 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-03-11 23:43:04 +00:00
|
|
|
|
|
|
|
if (!this.isWebKit2()) {
|
|
|
|
// FIXME: Add a sleep in here.
|
|
|
|
eventSender.addTouchPoint(x, y);
|
|
|
|
eventSender.touchStart();
|
|
|
|
eventSender.releaseTouchPoint(0);
|
|
|
|
eventSender.touchEnd();
|
|
|
|
eventSender.addTouchPoint(x, y);
|
|
|
|
eventSender.touchStart();
|
|
|
|
eventSender.releaseTouchPoint(0);
|
|
|
|
eventSender.touchEnd();
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
REGRESSION (iOS 13): Tests that simulate multiple back-to-back single taps fail or time out
https://bugs.webkit.org/show_bug.cgi?id=201129
<rdar://problem/51857277>
Reviewed by Tim Horton.
Source/WebKit:
Adds a new SPI hook in WebKit to let clients know when a synthetic tap gesture that has ended has been reset.
See Tools/ChangeLog and LayoutTests/ChangeLog for more details.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _doAfterResettingSingleTapGesture:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _singleTapDidReset:]):
(-[WKContentView _doAfterResettingSingleTapGesture:]):
Tools:
The tests in editing/pasteboard/ios were timing out on iOS 13 before this change. This is because they simulate
back-to-back single taps; while this is recognized as two single taps on iOS 12 and prior, only the first single
tap is recognized on iOS 13 (and the second is simply dropped on the floor). This occurs because the synthetic
single tap gesture is reset slightly later on iOS 13 compared to iOS 12, so when the second tap is dispatched,
the gesture recognizer is still in "ended" state after the first tap on iOS 13, which means the gesture isn't
capable of recognizing further touches yet.
In UIKit, a gesture recognizer is only reset once its UIGestureEnvironment's containing dependency subgraph no
longer contains gestures that are active. In iOS 12, the synthetic click gesture is a part of a dependency
subgraph that contains only itself and the normal (blocking) double tap gesture which requires the click to fail
before it can be recognized; immediately after simulating the tap, both these gestures are inactive, which
allows both of them to be reset.
However, in iOS 13, the synthetic click gesture is part of a gesture dependency graph that contains the double
tap for double click gesture, as well as the non-blocking double tap gesture, both of which are still active
immediately after sending the first tap. This change in dependencies is caused by the introduction of
UIUndoGestureInteraction's single and double three-finger tap gestures, which (in -[UIUndoGestureInteraction
gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]) explicitly add all other taps as failure
requirements. This effectively links the synthetic single tap gesture to most of the other gestures in
WKContentView's dependency graph by way of these tap gestures for the undo interaction.
All this means that there is now a short (~50 ms) delay after the synthetic single tap gestures is recognized,
before it can be recognized again. To account for this new delay in our test infrastructure, simply wait for
single tap gestures that have ended to reset before attempting to send subsequent single taps. We do this by
introducing WebKit testing SPI to invoke a completion handler after resetting the synthetic click gesture (only
if necessary - i.e., if the gesture is in ended state when we are about to begin simulating the tap). This
allows calls to `UIScriptController::singleTapAtPoint` to be reliably recognized as single taps without
requiring arbitrary 120 ms "human speed" delays.
This fixes a number of flaky or failing layout tests, including the tests in editing/pasteboard/ios.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::doubleTapAtPoint):
Add a `delay` parameter to `doubleTapAtPoint`. A number of layout tests were actually simulating double click
gestures by simulating two back-to-back single taps; this is done for the purposes of being able to add a "human
speed" delay prior to the second single tap gesture. After the change to wait for the single tap gesture to
reset before attempting to simulate the next tap, this strategy no longer works, since the second gesture is
recognized only as a single tap instead of a double tap.
Instead, we add a delay parameter to `UIScriptController::doubleTapAtPoint`, which the "human speed" double tap
gestures use instead to wait after simulating the first tap.
* WebKitTestRunner/ios/HIDEventGenerator.h:
* WebKitTestRunner/ios/HIDEventGenerator.mm:
(-[HIDEventGenerator _waitFor:]):
(-[HIDEventGenerator sendTaps:location:withNumberOfTouches:delay:completionBlock:]):
Plumb the tap gesture delay through to this helper method.
(-[HIDEventGenerator tap:completionBlock:]):
(-[HIDEventGenerator doubleTap:delay:completionBlock:]):
(-[HIDEventGenerator twoFingerTap:completionBlock:]):
(-[HIDEventGenerator sendTaps:location:withNumberOfTouches:completionBlock:]): Deleted.
(-[HIDEventGenerator doubleTap:completionBlock:]): Deleted.
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::waitForSingleTapToReset const):
Add a new helper to wait for the content view's single tap gesture to reset if needed; call this before
attempting to simulate single taps (either using a stylus, or with a regular touch).
(WTR::UIScriptControllerIOS::singleTapAtPointWithModifiers):
(WTR::UIScriptControllerIOS::doubleTapAtPoint):
(WTR::UIScriptControllerIOS::stylusTapAtPointWithModifiers):
LayoutTests:
Adjusts a few layout tests after changes to UIScriptController::doubleTapAtPoint and
UIScriptController::singleTapAtPoint.
* editing/selection/ios/change-selection-by-tapping.html:
Tweak this test to tap the page 12 times instead of 20 (which seems to cause occasional timeouts locally, when
running all layout tests with a dozen active simulators).
* fast/events/ios/double-tap-zoom.html:
* fast/events/ios/viewport-device-width-allows-double-tap-zoom-out.html:
* fast/events/ios/viewport-shrink-to-fit-allows-double-tap.html:
Augment a few call sites of `doubleTapAtPoint` with a 0 delay. Ideally, these should just use ui-helper.js, but
we can refactor these tests as a part of folding basic-gestures.js into ui-helper.js.
* http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt:
* http/tests/security/anchor-download-block-crossorigin-expected.txt:
Rebaseline these layout tests, due to change in line numbers.
* platform/ipad/TestExpectations:
Unskip these tests on iPad, now that they should pass.
* pointerevents/utils.js:
(const.ui.new.UIController.prototype.doubleTapToZoom):
* resources/basic-gestures.js:
(return.new.Promise.):
(return.new.Promise):
Adjust some more call sites of `doubleTapAtPoint`. Ideally, these should use just `ui-helper.js` too.
* resources/ui-helper.js:
(window.UIHelper.doubleTapAt.return.new.Promise):
(window.UIHelper.doubleTapAt):
(window.UIHelper.humanSpeedDoubleTapAt):
(window.UIHelper.humanSpeedZoomByDoubleTappingAt):
Add a delay parameter to `doubleTapAt` to specify a delay after each simulated tap. By default, this is 0, but
the `humanSpeed*` helpers add a delay of 120 milliseconds. Additionally, these helpers were previously calling
`singleTapAtPoint` twice, with a timeout in between to add a delay. Instead, call `doubleTapAtPoint` with a
nonzero delay; otherwise, we'll end up waiting in `singleTapAtPoint` for the gesture subgraph containing both
the double tap gestures and the synthetic single tap gesture to reset, which causes these two single taps to no
longer be recognized as a double tap gesture.
(window.UIHelper.zoomByDoubleTappingAt):
Canonical link: https://commits.webkit.org/214834@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249112 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-08-26 19:37:29 +00:00
|
|
|
return UIHelper.doubleTapAt(x, y, 0.12);
|
[iOS] Implement a faster click detection that intercepts double-tap-to-zoom if possible
https://bugs.webkit.org/show_bug.cgi?id=195473
<rdar://problem/48718396>
Reviewed by Wenson Hsieh (with some help from Dan Bates).
Source/WebKit:
Adds a new algorithm, behind a flag FasterClicksEnabled, that can trigger a click
event without waiting to see if a double tap will occur. It does this by examining
the amount of zoom that would be triggered if it was a double tap, and if that value
doesn't exceed a set threshold, commits to the click event instead.
This is implemented by having the Web Process respond to the potential click with
some geometry information. If the UI Process receives the information before the
second tap in a double tap, it can decide to trigger a click.
* Shared/WebPreferences.yaml: New internal feature so this can be toggled in
a UI for testing.
* SourcesCocoa.txt: Renamed WKSyntheticTapGestureRecognizer.
* WebKit.xcodeproj/project.pbxproj: Ditto.
* UIProcess/ios/WKSyntheticTapGestureRecognizer.h:
* UIProcess/ios/WKSyntheticTapGestureRecognizer.m:
(-[WKSyntheticTapGestureRecognizer setGestureIdentifiedTarget:action:]):
(-[WKSyntheticTapGestureRecognizer setGestureFailedTarget:action:]):
(-[WKSyntheticTapGestureRecognizer setResetTarget:action:]):
(-[WKSyntheticTapGestureRecognizer setState:]):
(-[WKSyntheticTapGestureRecognizer reset]): Renamed WKSyntheticClickTapGestureRecognizer to
WKSyntheticTapGestureRecognizer, changed the signature of the main function to be a bit
more clear about what it does, and added a gesture failed target.
* UIProcess/API/Cocoa/WKWebViewInternal.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initialScaleFactor]):
(-[WKWebView _contentZoomScale]):
(-[WKWebView _targetContentZoomScaleForRect:currentScale:fitEntireRect:minimumScale:maximumScale:]):
Exposed the initial content scale, the current scale and added a declaration that
was missing from the .h.
* UIProcess/WebPageProxy.messages.in: Add a new message,
HandleSmartMagnificationInformationForPotentialTap, to
communicate the geometry of the clicked node to the UI Process.
* UIProcess/PageClient.h: Pure virtual function for the geometry message response.
* UIProcess/WebPageProxy.h: Ditto.
* UIProcess/ios/PageClientImplIOS.h: Calls into the WKContentView.
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::handleSmartMagnificationInformationForPotentialTap):
* UIProcess/ios/SmartMagnificationController.h:
* UIProcess/ios/SmartMagnificationController.mm:
(WebKit::SmartMagnificationController::calculatePotentialZoomParameters): A new method that
asks the WKContentView to work out what the zoom factor will be for a potential double
tap at a location.
(WebKit::SmartMagnificationController::smartMagnificationTargetRectAndZoomScales): New implementation
of this function to avoid multiple out-arguments.
* UIProcess/ios/WKContentView.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView _initialScaleFactor]):
(-[WKContentView _contentZoomScale]):
(-[WKContentView _targetContentZoomScaleForRect:currentScale:fitEntireRect:minimumScale:maximumScale:]):
Exposed the initial content scale, the current scale and the target zoom scale. These
all just call into the WKWebView implementation.
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _createAndConfigureDoubleTapGestureRecognizer]): Use a WKSyntheticTapGestureRecognizer instead
of a generic one, so we can capture the failure.
(-[WKContentView setupInteraction]):
(-[WKContentView cleanupInteraction]):
(-[WKContentView _handleSmartMagnificationInformationForPotentialTap:origin:renderRect:fitEntireRect:viewportMinimumScale:viewportMaximumScale:]):
New method that responds to the incoming Web Process message, and decides if any
potential zoom would be "significant".
(-[WKContentView _singleTapIdentified:]):
(-[WKContentView _doubleTapDidFail:]):
(-[WKContentView _didCompleteSyntheticClick]):
(-[WKContentView _singleTapRecognized:]):
(-[WKContentView _doubleTapRecognized:]):
Add some release logging.
(-[WKContentView _singleTapCommited:]): Deleted.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::potentialTapAtPosition):
(WebKit::WebPageProxy::handleSmartMagnificationInformationForPotentialTap):
* WebProcess/WebPage/ViewGestureGeometryCollector.h:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Removed an unused parameter from the existing message.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::potentialTapAtPosition): Calculates the geometry of the element
if requested, and sends it to the UIProcess.
LayoutTests:
Implement a test (iPad only) that sets up a page with zoomable content
but not quite at a significant scale, meaning we should dispatch a click
event rather than Double Tap To Zoom.
In order to do this, a humanSpeedDoubleTapAt() method was added to
UIHelper that sleeps a bit between taps, otherwise the double tap
gesture is recognized before the Web Process has had a chance to
evaluate the potential click.
* fast/events/ios/ipad/fast-click-double-tap-sends-click-on-insignificant-zoom-expected.txt: Added.
* fast/events/ios/ipad/fast-click-double-tap-sends-click-on-insignificant-zoom.html: Added.
* platform/ios/TestExpectations:
* platform/ipad/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.humanSpeedDoubleTapAt):
Canonical link: https://commits.webkit.org/209887@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242757 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-03-11 23:43:04 +00:00
|
|
|
}
|
|
|
|
|
2019-03-20 21:27:47 +00:00
|
|
|
static humanSpeedZoomByDoubleTappingAt(x, y)
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
console.assert(this.isIOSFamily());
|
2019-03-20 21:27:47 +00:00
|
|
|
|
|
|
|
if (!this.isWebKit2()) {
|
|
|
|
// FIXME: Add a sleep in here.
|
|
|
|
eventSender.addTouchPoint(x, y);
|
|
|
|
eventSender.touchStart();
|
|
|
|
eventSender.releaseTouchPoint(0);
|
|
|
|
eventSender.touchEnd();
|
|
|
|
eventSender.addTouchPoint(x, y);
|
|
|
|
eventSender.touchStart();
|
|
|
|
eventSender.releaseTouchPoint(0);
|
|
|
|
eventSender.touchEnd();
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise(async (resolve) => {
|
REGRESSION (iOS 13): Tests that simulate multiple back-to-back single taps fail or time out
https://bugs.webkit.org/show_bug.cgi?id=201129
<rdar://problem/51857277>
Reviewed by Tim Horton.
Source/WebKit:
Adds a new SPI hook in WebKit to let clients know when a synthetic tap gesture that has ended has been reset.
See Tools/ChangeLog and LayoutTests/ChangeLog for more details.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _doAfterResettingSingleTapGesture:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _singleTapDidReset:]):
(-[WKContentView _doAfterResettingSingleTapGesture:]):
Tools:
The tests in editing/pasteboard/ios were timing out on iOS 13 before this change. This is because they simulate
back-to-back single taps; while this is recognized as two single taps on iOS 12 and prior, only the first single
tap is recognized on iOS 13 (and the second is simply dropped on the floor). This occurs because the synthetic
single tap gesture is reset slightly later on iOS 13 compared to iOS 12, so when the second tap is dispatched,
the gesture recognizer is still in "ended" state after the first tap on iOS 13, which means the gesture isn't
capable of recognizing further touches yet.
In UIKit, a gesture recognizer is only reset once its UIGestureEnvironment's containing dependency subgraph no
longer contains gestures that are active. In iOS 12, the synthetic click gesture is a part of a dependency
subgraph that contains only itself and the normal (blocking) double tap gesture which requires the click to fail
before it can be recognized; immediately after simulating the tap, both these gestures are inactive, which
allows both of them to be reset.
However, in iOS 13, the synthetic click gesture is part of a gesture dependency graph that contains the double
tap for double click gesture, as well as the non-blocking double tap gesture, both of which are still active
immediately after sending the first tap. This change in dependencies is caused by the introduction of
UIUndoGestureInteraction's single and double three-finger tap gestures, which (in -[UIUndoGestureInteraction
gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]) explicitly add all other taps as failure
requirements. This effectively links the synthetic single tap gesture to most of the other gestures in
WKContentView's dependency graph by way of these tap gestures for the undo interaction.
All this means that there is now a short (~50 ms) delay after the synthetic single tap gestures is recognized,
before it can be recognized again. To account for this new delay in our test infrastructure, simply wait for
single tap gestures that have ended to reset before attempting to send subsequent single taps. We do this by
introducing WebKit testing SPI to invoke a completion handler after resetting the synthetic click gesture (only
if necessary - i.e., if the gesture is in ended state when we are about to begin simulating the tap). This
allows calls to `UIScriptController::singleTapAtPoint` to be reliably recognized as single taps without
requiring arbitrary 120 ms "human speed" delays.
This fixes a number of flaky or failing layout tests, including the tests in editing/pasteboard/ios.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::doubleTapAtPoint):
Add a `delay` parameter to `doubleTapAtPoint`. A number of layout tests were actually simulating double click
gestures by simulating two back-to-back single taps; this is done for the purposes of being able to add a "human
speed" delay prior to the second single tap gesture. After the change to wait for the single tap gesture to
reset before attempting to simulate the next tap, this strategy no longer works, since the second gesture is
recognized only as a single tap instead of a double tap.
Instead, we add a delay parameter to `UIScriptController::doubleTapAtPoint`, which the "human speed" double tap
gestures use instead to wait after simulating the first tap.
* WebKitTestRunner/ios/HIDEventGenerator.h:
* WebKitTestRunner/ios/HIDEventGenerator.mm:
(-[HIDEventGenerator _waitFor:]):
(-[HIDEventGenerator sendTaps:location:withNumberOfTouches:delay:completionBlock:]):
Plumb the tap gesture delay through to this helper method.
(-[HIDEventGenerator tap:completionBlock:]):
(-[HIDEventGenerator doubleTap:delay:completionBlock:]):
(-[HIDEventGenerator twoFingerTap:completionBlock:]):
(-[HIDEventGenerator sendTaps:location:withNumberOfTouches:completionBlock:]): Deleted.
(-[HIDEventGenerator doubleTap:completionBlock:]): Deleted.
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::waitForSingleTapToReset const):
Add a new helper to wait for the content view's single tap gesture to reset if needed; call this before
attempting to simulate single taps (either using a stylus, or with a regular touch).
(WTR::UIScriptControllerIOS::singleTapAtPointWithModifiers):
(WTR::UIScriptControllerIOS::doubleTapAtPoint):
(WTR::UIScriptControllerIOS::stylusTapAtPointWithModifiers):
LayoutTests:
Adjusts a few layout tests after changes to UIScriptController::doubleTapAtPoint and
UIScriptController::singleTapAtPoint.
* editing/selection/ios/change-selection-by-tapping.html:
Tweak this test to tap the page 12 times instead of 20 (which seems to cause occasional timeouts locally, when
running all layout tests with a dozen active simulators).
* fast/events/ios/double-tap-zoom.html:
* fast/events/ios/viewport-device-width-allows-double-tap-zoom-out.html:
* fast/events/ios/viewport-shrink-to-fit-allows-double-tap.html:
Augment a few call sites of `doubleTapAtPoint` with a 0 delay. Ideally, these should just use ui-helper.js, but
we can refactor these tests as a part of folding basic-gestures.js into ui-helper.js.
* http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt:
* http/tests/security/anchor-download-block-crossorigin-expected.txt:
Rebaseline these layout tests, due to change in line numbers.
* platform/ipad/TestExpectations:
Unskip these tests on iPad, now that they should pass.
* pointerevents/utils.js:
(const.ui.new.UIController.prototype.doubleTapToZoom):
* resources/basic-gestures.js:
(return.new.Promise.):
(return.new.Promise):
Adjust some more call sites of `doubleTapAtPoint`. Ideally, these should use just `ui-helper.js` too.
* resources/ui-helper.js:
(window.UIHelper.doubleTapAt.return.new.Promise):
(window.UIHelper.doubleTapAt):
(window.UIHelper.humanSpeedDoubleTapAt):
(window.UIHelper.humanSpeedZoomByDoubleTappingAt):
Add a delay parameter to `doubleTapAt` to specify a delay after each simulated tap. By default, this is 0, but
the `humanSpeed*` helpers add a delay of 120 milliseconds. Additionally, these helpers were previously calling
`singleTapAtPoint` twice, with a timeout in between to add a delay. Instead, call `doubleTapAtPoint` with a
nonzero delay; otherwise, we'll end up waiting in `singleTapAtPoint` for the gesture subgraph containing both
the double tap gestures and the synthetic single tap gesture to reset, which causes these two single taps to no
longer be recognized as a double tap gesture.
(window.UIHelper.zoomByDoubleTappingAt):
Canonical link: https://commits.webkit.org/214834@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249112 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-08-26 19:37:29 +00:00
|
|
|
testRunner.runUIScript(`
|
|
|
|
uiController.didEndZoomingCallback = () => {
|
|
|
|
uiController.didEndZoomingCallback = null;
|
|
|
|
uiController.uiScriptComplete(uiController.zoomScale);
|
|
|
|
};
|
|
|
|
uiController.doubleTapAtPoint(${x}, ${y}, 0.12, () => { });`, resolve);
|
2019-03-20 21:27:47 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-01-17 19:15:57 +00:00
|
|
|
static zoomByDoubleTappingAt(x, y)
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
console.assert(this.isIOSFamily());
|
2019-01-17 19:15:57 +00:00
|
|
|
|
|
|
|
if (!this.isWebKit2()) {
|
|
|
|
eventSender.addTouchPoint(x, y);
|
|
|
|
eventSender.touchStart();
|
|
|
|
eventSender.releaseTouchPoint(0);
|
|
|
|
eventSender.touchEnd();
|
|
|
|
eventSender.addTouchPoint(x, y);
|
|
|
|
eventSender.touchStart();
|
|
|
|
eventSender.releaseTouchPoint(0);
|
|
|
|
eventSender.touchEnd();
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
uiController.didEndZoomingCallback = () => {
|
|
|
|
uiController.didEndZoomingCallback = null;
|
|
|
|
uiController.uiScriptComplete(uiController.zoomScale);
|
|
|
|
};
|
REGRESSION (iOS 13): Tests that simulate multiple back-to-back single taps fail or time out
https://bugs.webkit.org/show_bug.cgi?id=201129
<rdar://problem/51857277>
Reviewed by Tim Horton.
Source/WebKit:
Adds a new SPI hook in WebKit to let clients know when a synthetic tap gesture that has ended has been reset.
See Tools/ChangeLog and LayoutTests/ChangeLog for more details.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _doAfterResettingSingleTapGesture:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _singleTapDidReset:]):
(-[WKContentView _doAfterResettingSingleTapGesture:]):
Tools:
The tests in editing/pasteboard/ios were timing out on iOS 13 before this change. This is because they simulate
back-to-back single taps; while this is recognized as two single taps on iOS 12 and prior, only the first single
tap is recognized on iOS 13 (and the second is simply dropped on the floor). This occurs because the synthetic
single tap gesture is reset slightly later on iOS 13 compared to iOS 12, so when the second tap is dispatched,
the gesture recognizer is still in "ended" state after the first tap on iOS 13, which means the gesture isn't
capable of recognizing further touches yet.
In UIKit, a gesture recognizer is only reset once its UIGestureEnvironment's containing dependency subgraph no
longer contains gestures that are active. In iOS 12, the synthetic click gesture is a part of a dependency
subgraph that contains only itself and the normal (blocking) double tap gesture which requires the click to fail
before it can be recognized; immediately after simulating the tap, both these gestures are inactive, which
allows both of them to be reset.
However, in iOS 13, the synthetic click gesture is part of a gesture dependency graph that contains the double
tap for double click gesture, as well as the non-blocking double tap gesture, both of which are still active
immediately after sending the first tap. This change in dependencies is caused by the introduction of
UIUndoGestureInteraction's single and double three-finger tap gestures, which (in -[UIUndoGestureInteraction
gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]) explicitly add all other taps as failure
requirements. This effectively links the synthetic single tap gesture to most of the other gestures in
WKContentView's dependency graph by way of these tap gestures for the undo interaction.
All this means that there is now a short (~50 ms) delay after the synthetic single tap gestures is recognized,
before it can be recognized again. To account for this new delay in our test infrastructure, simply wait for
single tap gestures that have ended to reset before attempting to send subsequent single taps. We do this by
introducing WebKit testing SPI to invoke a completion handler after resetting the synthetic click gesture (only
if necessary - i.e., if the gesture is in ended state when we are about to begin simulating the tap). This
allows calls to `UIScriptController::singleTapAtPoint` to be reliably recognized as single taps without
requiring arbitrary 120 ms "human speed" delays.
This fixes a number of flaky or failing layout tests, including the tests in editing/pasteboard/ios.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::doubleTapAtPoint):
Add a `delay` parameter to `doubleTapAtPoint`. A number of layout tests were actually simulating double click
gestures by simulating two back-to-back single taps; this is done for the purposes of being able to add a "human
speed" delay prior to the second single tap gesture. After the change to wait for the single tap gesture to
reset before attempting to simulate the next tap, this strategy no longer works, since the second gesture is
recognized only as a single tap instead of a double tap.
Instead, we add a delay parameter to `UIScriptController::doubleTapAtPoint`, which the "human speed" double tap
gestures use instead to wait after simulating the first tap.
* WebKitTestRunner/ios/HIDEventGenerator.h:
* WebKitTestRunner/ios/HIDEventGenerator.mm:
(-[HIDEventGenerator _waitFor:]):
(-[HIDEventGenerator sendTaps:location:withNumberOfTouches:delay:completionBlock:]):
Plumb the tap gesture delay through to this helper method.
(-[HIDEventGenerator tap:completionBlock:]):
(-[HIDEventGenerator doubleTap:delay:completionBlock:]):
(-[HIDEventGenerator twoFingerTap:completionBlock:]):
(-[HIDEventGenerator sendTaps:location:withNumberOfTouches:completionBlock:]): Deleted.
(-[HIDEventGenerator doubleTap:completionBlock:]): Deleted.
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::waitForSingleTapToReset const):
Add a new helper to wait for the content view's single tap gesture to reset if needed; call this before
attempting to simulate single taps (either using a stylus, or with a regular touch).
(WTR::UIScriptControllerIOS::singleTapAtPointWithModifiers):
(WTR::UIScriptControllerIOS::doubleTapAtPoint):
(WTR::UIScriptControllerIOS::stylusTapAtPointWithModifiers):
LayoutTests:
Adjusts a few layout tests after changes to UIScriptController::doubleTapAtPoint and
UIScriptController::singleTapAtPoint.
* editing/selection/ios/change-selection-by-tapping.html:
Tweak this test to tap the page 12 times instead of 20 (which seems to cause occasional timeouts locally, when
running all layout tests with a dozen active simulators).
* fast/events/ios/double-tap-zoom.html:
* fast/events/ios/viewport-device-width-allows-double-tap-zoom-out.html:
* fast/events/ios/viewport-shrink-to-fit-allows-double-tap.html:
Augment a few call sites of `doubleTapAtPoint` with a 0 delay. Ideally, these should just use ui-helper.js, but
we can refactor these tests as a part of folding basic-gestures.js into ui-helper.js.
* http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt:
* http/tests/security/anchor-download-block-crossorigin-expected.txt:
Rebaseline these layout tests, due to change in line numbers.
* platform/ipad/TestExpectations:
Unskip these tests on iPad, now that they should pass.
* pointerevents/utils.js:
(const.ui.new.UIController.prototype.doubleTapToZoom):
* resources/basic-gestures.js:
(return.new.Promise.):
(return.new.Promise):
Adjust some more call sites of `doubleTapAtPoint`. Ideally, these should use just `ui-helper.js` too.
* resources/ui-helper.js:
(window.UIHelper.doubleTapAt.return.new.Promise):
(window.UIHelper.doubleTapAt):
(window.UIHelper.humanSpeedDoubleTapAt):
(window.UIHelper.humanSpeedZoomByDoubleTappingAt):
Add a delay parameter to `doubleTapAt` to specify a delay after each simulated tap. By default, this is 0, but
the `humanSpeed*` helpers add a delay of 120 milliseconds. Additionally, these helpers were previously calling
`singleTapAtPoint` twice, with a timeout in between to add a delay. Instead, call `doubleTapAtPoint` with a
nonzero delay; otherwise, we'll end up waiting in `singleTapAtPoint` for the gesture subgraph containing both
the double tap gestures and the synthetic single tap gesture to reset, which causes these two single taps to no
longer be recognized as a double tap gesture.
(window.UIHelper.zoomByDoubleTappingAt):
Canonical link: https://commits.webkit.org/214834@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249112 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-08-26 19:37:29 +00:00
|
|
|
uiController.doubleTapAtPoint(${x}, ${y}, 0, () => { });`, resolve);
|
2019-01-17 19:15:57 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
REGRESSION (r258871): Shift + click to extend selection loses currently selected text
https://bugs.webkit.org/show_bug.cgi?id=214617
<rdar://problem/64980223>
Reviewed by Megan Gardner.
Source/WebCore:
After the changes in r258871, shift clicking sometimes fails to preserve the existing selected text range on
macOS and iOS. The logic in `EventHandler::handleMousePressEventSingleClick` uses the `textDistance` helper
method to count the number of characters between the start of the current selection to the newly selected
extent, as well as the number of characters between the end of the current selection and the newly selected
extent position. It compares these two character counts, and attempts to choose the new selection extents in
such a way that maximizes the amount of selected text.
However, after r258871, `textDistance` uses `characterCount` instead of `TextIterator::rangeLength`. Unlike the
former, `rangeLength` is robust in the case where the start position comes after the end position (in document
order), since the process of creating a live `Range` object swaps the start and end if needed. This isn't the
case when using `SimpleRange`. Instead, when given a simple range where the start comes after the end,
`characterCount` will iterate text in the DOM, starting from the start position and ending at the end of the
document rather than the end position. The result is that `characterCount` actually counts the number of
characters between the start position and the end of the document, rather than the number of characters between
the two positions.
In the context of this bug, if the start of the current selection is "far away" (in terms of character count)
from the end of the document and the new extent position comes after end of the current selection, we will end
up choosing the end (instead of the start) as one of the new extents of the updated selection.
To fix this (as well as other similar issues that might've arisen when replacing uses of
`TextIterator::rangeLength` with `characterCount`), simply teach `characterCount` to flip the start and end
positions if the end position of the `SimpleRange` comes before the start.
Test: editing/selection/shift-click-includes-existing-selection.html
* editing/TextIterator.cpp:
(WebCore::characterCount):
LayoutTests:
Add a new layout test to verify that the bug does not occur.
* editing/mac/spelling/autocorrection-contraction-expected.txt:
Rebaseline an existing layout test, restoring the test expectations to what they were prior to r258871. It seems
that the more recently added expectations (while not seemingly incorrect) were dependent on `characterCount`
computing the number of characters from the start position to the end of the document, rather than the end.
* editing/selection/shift-click-includes-existing-selection-expected.txt: Added.
* editing/selection/shift-click-includes-existing-selection.html: Added.
* resources/ui-helper.js:
(window.UIHelper.activateAt.return.new.Promise):
(window.UIHelper.activateAt):
(window.UIHelper.activateElement):
Add an optional `modifiers` argument to the `activateAt` and `activateElement` helper methods, which can be used
to simulate key modifiers being held while synthesizing the "activation" (i.e. tap or click).
Canonical link: https://commits.webkit.org/227435@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@264690 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-07-22 02:47:29 +00:00
|
|
|
static activateAt(x, y, modifiers=[])
|
2016-12-13 23:22:03 +00:00
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily()) {
|
2016-12-13 23:22:03 +00:00
|
|
|
eventSender.mouseMoveTo(x, y);
|
REGRESSION (r258871): Shift + click to extend selection loses currently selected text
https://bugs.webkit.org/show_bug.cgi?id=214617
<rdar://problem/64980223>
Reviewed by Megan Gardner.
Source/WebCore:
After the changes in r258871, shift clicking sometimes fails to preserve the existing selected text range on
macOS and iOS. The logic in `EventHandler::handleMousePressEventSingleClick` uses the `textDistance` helper
method to count the number of characters between the start of the current selection to the newly selected
extent, as well as the number of characters between the end of the current selection and the newly selected
extent position. It compares these two character counts, and attempts to choose the new selection extents in
such a way that maximizes the amount of selected text.
However, after r258871, `textDistance` uses `characterCount` instead of `TextIterator::rangeLength`. Unlike the
former, `rangeLength` is robust in the case where the start position comes after the end position (in document
order), since the process of creating a live `Range` object swaps the start and end if needed. This isn't the
case when using `SimpleRange`. Instead, when given a simple range where the start comes after the end,
`characterCount` will iterate text in the DOM, starting from the start position and ending at the end of the
document rather than the end position. The result is that `characterCount` actually counts the number of
characters between the start position and the end of the document, rather than the number of characters between
the two positions.
In the context of this bug, if the start of the current selection is "far away" (in terms of character count)
from the end of the document and the new extent position comes after end of the current selection, we will end
up choosing the end (instead of the start) as one of the new extents of the updated selection.
To fix this (as well as other similar issues that might've arisen when replacing uses of
`TextIterator::rangeLength` with `characterCount`), simply teach `characterCount` to flip the start and end
positions if the end position of the `SimpleRange` comes before the start.
Test: editing/selection/shift-click-includes-existing-selection.html
* editing/TextIterator.cpp:
(WebCore::characterCount):
LayoutTests:
Add a new layout test to verify that the bug does not occur.
* editing/mac/spelling/autocorrection-contraction-expected.txt:
Rebaseline an existing layout test, restoring the test expectations to what they were prior to r258871. It seems
that the more recently added expectations (while not seemingly incorrect) were dependent on `characterCount`
computing the number of characters from the start position to the end of the document, rather than the end.
* editing/selection/shift-click-includes-existing-selection-expected.txt: Added.
* editing/selection/shift-click-includes-existing-selection.html: Added.
* resources/ui-helper.js:
(window.UIHelper.activateAt.return.new.Promise):
(window.UIHelper.activateAt):
(window.UIHelper.activateElement):
Add an optional `modifiers` argument to the `activateAt` and `activateElement` helper methods, which can be used
to simulate key modifiers being held while synthesizing the "activation" (i.e. tap or click).
Canonical link: https://commits.webkit.org/227435@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@264690 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-07-22 02:47:29 +00:00
|
|
|
eventSender.mouseDown(0, modifiers);
|
|
|
|
eventSender.mouseUp(0, modifiers);
|
2016-12-13 23:22:03 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
testRunner.runUIScript(`
|
REGRESSION (r258871): Shift + click to extend selection loses currently selected text
https://bugs.webkit.org/show_bug.cgi?id=214617
<rdar://problem/64980223>
Reviewed by Megan Gardner.
Source/WebCore:
After the changes in r258871, shift clicking sometimes fails to preserve the existing selected text range on
macOS and iOS. The logic in `EventHandler::handleMousePressEventSingleClick` uses the `textDistance` helper
method to count the number of characters between the start of the current selection to the newly selected
extent, as well as the number of characters between the end of the current selection and the newly selected
extent position. It compares these two character counts, and attempts to choose the new selection extents in
such a way that maximizes the amount of selected text.
However, after r258871, `textDistance` uses `characterCount` instead of `TextIterator::rangeLength`. Unlike the
former, `rangeLength` is robust in the case where the start position comes after the end position (in document
order), since the process of creating a live `Range` object swaps the start and end if needed. This isn't the
case when using `SimpleRange`. Instead, when given a simple range where the start comes after the end,
`characterCount` will iterate text in the DOM, starting from the start position and ending at the end of the
document rather than the end position. The result is that `characterCount` actually counts the number of
characters between the start position and the end of the document, rather than the number of characters between
the two positions.
In the context of this bug, if the start of the current selection is "far away" (in terms of character count)
from the end of the document and the new extent position comes after end of the current selection, we will end
up choosing the end (instead of the start) as one of the new extents of the updated selection.
To fix this (as well as other similar issues that might've arisen when replacing uses of
`TextIterator::rangeLength` with `characterCount`), simply teach `characterCount` to flip the start and end
positions if the end position of the `SimpleRange` comes before the start.
Test: editing/selection/shift-click-includes-existing-selection.html
* editing/TextIterator.cpp:
(WebCore::characterCount):
LayoutTests:
Add a new layout test to verify that the bug does not occur.
* editing/mac/spelling/autocorrection-contraction-expected.txt:
Rebaseline an existing layout test, restoring the test expectations to what they were prior to r258871. It seems
that the more recently added expectations (while not seemingly incorrect) were dependent on `characterCount`
computing the number of characters from the start position to the end of the document, rather than the end.
* editing/selection/shift-click-includes-existing-selection-expected.txt: Added.
* editing/selection/shift-click-includes-existing-selection.html: Added.
* resources/ui-helper.js:
(window.UIHelper.activateAt.return.new.Promise):
(window.UIHelper.activateAt):
(window.UIHelper.activateElement):
Add an optional `modifiers` argument to the `activateAt` and `activateElement` helper methods, which can be used
to simulate key modifiers being held while synthesizing the "activation" (i.e. tap or click).
Canonical link: https://commits.webkit.org/227435@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@264690 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-07-22 02:47:29 +00:00
|
|
|
uiController.singleTapAtPointWithModifiers(${x}, ${y}, ${JSON.stringify(modifiers)}, function() {
|
2019-01-17 19:15:57 +00:00
|
|
|
uiController.uiScriptComplete();
|
2016-12-13 23:22:03 +00:00
|
|
|
});`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
REGRESSION (r258871): Shift + click to extend selection loses currently selected text
https://bugs.webkit.org/show_bug.cgi?id=214617
<rdar://problem/64980223>
Reviewed by Megan Gardner.
Source/WebCore:
After the changes in r258871, shift clicking sometimes fails to preserve the existing selected text range on
macOS and iOS. The logic in `EventHandler::handleMousePressEventSingleClick` uses the `textDistance` helper
method to count the number of characters between the start of the current selection to the newly selected
extent, as well as the number of characters between the end of the current selection and the newly selected
extent position. It compares these two character counts, and attempts to choose the new selection extents in
such a way that maximizes the amount of selected text.
However, after r258871, `textDistance` uses `characterCount` instead of `TextIterator::rangeLength`. Unlike the
former, `rangeLength` is robust in the case where the start position comes after the end position (in document
order), since the process of creating a live `Range` object swaps the start and end if needed. This isn't the
case when using `SimpleRange`. Instead, when given a simple range where the start comes after the end,
`characterCount` will iterate text in the DOM, starting from the start position and ending at the end of the
document rather than the end position. The result is that `characterCount` actually counts the number of
characters between the start position and the end of the document, rather than the number of characters between
the two positions.
In the context of this bug, if the start of the current selection is "far away" (in terms of character count)
from the end of the document and the new extent position comes after end of the current selection, we will end
up choosing the end (instead of the start) as one of the new extents of the updated selection.
To fix this (as well as other similar issues that might've arisen when replacing uses of
`TextIterator::rangeLength` with `characterCount`), simply teach `characterCount` to flip the start and end
positions if the end position of the `SimpleRange` comes before the start.
Test: editing/selection/shift-click-includes-existing-selection.html
* editing/TextIterator.cpp:
(WebCore::characterCount):
LayoutTests:
Add a new layout test to verify that the bug does not occur.
* editing/mac/spelling/autocorrection-contraction-expected.txt:
Rebaseline an existing layout test, restoring the test expectations to what they were prior to r258871. It seems
that the more recently added expectations (while not seemingly incorrect) were dependent on `characterCount`
computing the number of characters from the start position to the end of the document, rather than the end.
* editing/selection/shift-click-includes-existing-selection-expected.txt: Added.
* editing/selection/shift-click-includes-existing-selection.html: Added.
* resources/ui-helper.js:
(window.UIHelper.activateAt.return.new.Promise):
(window.UIHelper.activateAt):
(window.UIHelper.activateElement):
Add an optional `modifiers` argument to the `activateAt` and `activateElement` helper methods, which can be used
to simulate key modifiers being held while synthesizing the "activation" (i.e. tap or click).
Canonical link: https://commits.webkit.org/227435@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@264690 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-07-22 02:47:29 +00:00
|
|
|
static activateElement(element, modifiers=[])
|
2017-11-03 16:35:59 +00:00
|
|
|
{
|
|
|
|
const x = element.offsetLeft + element.offsetWidth / 2;
|
|
|
|
const y = element.offsetTop + element.offsetHeight / 2;
|
REGRESSION (r258871): Shift + click to extend selection loses currently selected text
https://bugs.webkit.org/show_bug.cgi?id=214617
<rdar://problem/64980223>
Reviewed by Megan Gardner.
Source/WebCore:
After the changes in r258871, shift clicking sometimes fails to preserve the existing selected text range on
macOS and iOS. The logic in `EventHandler::handleMousePressEventSingleClick` uses the `textDistance` helper
method to count the number of characters between the start of the current selection to the newly selected
extent, as well as the number of characters between the end of the current selection and the newly selected
extent position. It compares these two character counts, and attempts to choose the new selection extents in
such a way that maximizes the amount of selected text.
However, after r258871, `textDistance` uses `characterCount` instead of `TextIterator::rangeLength`. Unlike the
former, `rangeLength` is robust in the case where the start position comes after the end position (in document
order), since the process of creating a live `Range` object swaps the start and end if needed. This isn't the
case when using `SimpleRange`. Instead, when given a simple range where the start comes after the end,
`characterCount` will iterate text in the DOM, starting from the start position and ending at the end of the
document rather than the end position. The result is that `characterCount` actually counts the number of
characters between the start position and the end of the document, rather than the number of characters between
the two positions.
In the context of this bug, if the start of the current selection is "far away" (in terms of character count)
from the end of the document and the new extent position comes after end of the current selection, we will end
up choosing the end (instead of the start) as one of the new extents of the updated selection.
To fix this (as well as other similar issues that might've arisen when replacing uses of
`TextIterator::rangeLength` with `characterCount`), simply teach `characterCount` to flip the start and end
positions if the end position of the `SimpleRange` comes before the start.
Test: editing/selection/shift-click-includes-existing-selection.html
* editing/TextIterator.cpp:
(WebCore::characterCount):
LayoutTests:
Add a new layout test to verify that the bug does not occur.
* editing/mac/spelling/autocorrection-contraction-expected.txt:
Rebaseline an existing layout test, restoring the test expectations to what they were prior to r258871. It seems
that the more recently added expectations (while not seemingly incorrect) were dependent on `characterCount`
computing the number of characters from the start position to the end of the document, rather than the end.
* editing/selection/shift-click-includes-existing-selection-expected.txt: Added.
* editing/selection/shift-click-includes-existing-selection.html: Added.
* resources/ui-helper.js:
(window.UIHelper.activateAt.return.new.Promise):
(window.UIHelper.activateAt):
(window.UIHelper.activateElement):
Add an optional `modifiers` argument to the `activateAt` and `activateElement` helper methods, which can be used
to simulate key modifiers being held while synthesizing the "activation" (i.e. tap or click).
Canonical link: https://commits.webkit.org/227435@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@264690 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-07-22 02:47:29 +00:00
|
|
|
return UIHelper.activateAt(x, y, modifiers);
|
2017-11-03 16:35:59 +00:00
|
|
|
}
|
|
|
|
|
2019-02-18 16:53:32 +00:00
|
|
|
static async doubleActivateAt(x, y)
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (this.isIOSFamily())
|
2019-02-18 16:53:32 +00:00
|
|
|
await UIHelper.doubleTapAt(x, y);
|
|
|
|
else
|
|
|
|
await UIHelper.doubleClickAt(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static async doubleActivateAtSelectionStart()
|
|
|
|
{
|
|
|
|
const rects = window.getSelection().getRangeAt(0).getClientRects();
|
|
|
|
const x = rects[0].left;
|
|
|
|
const y = rects[0].top;
|
2019-06-01 00:43:56 +00:00
|
|
|
if (this.isIOSFamily()) {
|
2019-02-18 16:53:32 +00:00
|
|
|
await UIHelper.activateAndWaitForInputSessionAt(x, y);
|
|
|
|
await UIHelper.doubleTapAt(x, y);
|
|
|
|
// This is only here to deal with async/sync copy/paste calls, so
|
|
|
|
// once <rdar://problem/16207002> is resolved, should be able to remove for faster tests.
|
|
|
|
await new Promise(resolve => testRunner.runUIScript("uiController.uiScriptComplete()", resolve));
|
|
|
|
} else
|
|
|
|
await UIHelper.doubleClickAt(x, y);
|
|
|
|
}
|
|
|
|
|
2019-02-01 00:38:55 +00:00
|
|
|
static async selectWordByDoubleTapOrClick(element, relativeX = 5, relativeY = 5)
|
|
|
|
{
|
|
|
|
const boundingRect = element.getBoundingClientRect();
|
|
|
|
const x = boundingRect.x + relativeX;
|
|
|
|
const y = boundingRect.y + relativeY;
|
2019-06-01 00:43:56 +00:00
|
|
|
if (this.isIOSFamily()) {
|
2019-02-18 16:53:32 +00:00
|
|
|
await UIHelper.activateAndWaitForInputSessionAt(x, y);
|
2019-02-01 00:38:55 +00:00
|
|
|
await UIHelper.doubleTapAt(x, y);
|
|
|
|
// This is only here to deal with async/sync copy/paste calls, so
|
|
|
|
// once <rdar://problem/16207002> is resolved, should be able to remove for faster tests.
|
|
|
|
await new Promise(resolve => testRunner.runUIScript("uiController.uiScriptComplete()", resolve));
|
|
|
|
} else {
|
|
|
|
await UIHelper.doubleClickAt(x, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-15 19:15:28 +00:00
|
|
|
static keyDown(key, modifiers=[])
|
2017-10-18 23:14:34 +00:00
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily()) {
|
2018-11-26 22:57:44 +00:00
|
|
|
eventSender.keyDown(key, modifiers);
|
2017-10-18 23:14:34 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise((resolve) => {
|
2018-11-15 19:15:28 +00:00
|
|
|
testRunner.runUIScript(`uiController.keyDown("${key}", ${JSON.stringify(modifiers)});`, resolve);
|
2017-10-18 23:14:34 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-11-26 20:41:19 +00:00
|
|
|
static toggleCapsLock()
|
|
|
|
{
|
|
|
|
return new Promise((resolve) => {
|
2019-01-17 19:15:57 +00:00
|
|
|
testRunner.runUIScript(`uiController.toggleCapsLock(() => uiController.uiScriptComplete());`, resolve);
|
2018-11-26 20:41:19 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-05-18 15:23:09 +00:00
|
|
|
static keyboardIsAutomaticallyShifted()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`uiController.keyboardIsAutomaticallyShifted`, result => resolve(result === "true"));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
REGRESSION (r274610): Unable to drag images when image extraction is enabled
https://bugs.webkit.org/show_bug.cgi?id=224211
<rdar://problem/76229563>
Reviewed by Tim Horton.
Source/WebKit:
r274610 introduced a new deferring gesture recognizer intended to prevent several text interaction gestures from
recognizing during pending image extraction. However, this also causes dragging on iOS to fail, since the
gesture used to initiate dragging is excluded by the new deferring gesture recognizer. To fix this, allow the
new deferring gesture to recognize simultaneously alongside all gestures with the exception of only the gestures
it is intended to defer (i.e. text interaction gestures).
Test: fast/events/ios/dragstart-on-image-by-long-pressing.html
* UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
* UIProcess/API/ios/WKWebViewTestingIOS.mm:
(-[WKWebView _isAnimatingDragCancel]):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[UIGestureRecognizer _wk_isTapAndAHalf]):
Add a WebKit category method that returns whether or not a gesture recognizer is a tap-and-a-half gesture.
(-[WKContentView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
Allow the image extraction deferring gesture to recognize alongside all other gestures, with the exception of
the text interaction gestures determined by `-shouldDeferGestureDueToImageExtraction:`. This limits the impact
of this new deferring gesture, such that it only affects the text interaction gestures it is intended to defer.
(-[WKContentView shouldDeferGestureDueToImageExtraction:]):
Add a helper method to determine whether or not a gesture recognizer should be deferred, due to pending image
extraction. We pull this logic behind a helper method because it's now consulted from two call sites.
(-[WKContentView deferringGestureRecognizer:shouldDeferOtherGestureRecognizer:]):
(-[WKContentView dragInteraction:item:willAnimateCancelWithAnimator:]):
(-[WKContentView isAnimatingDragCancel]):
Add a testing hook to return whether or not the drag cancel animation is running. See Tools/ChangeLog and the
new layout test for more detail.
(tapAndAHalfRecognizerClass): Deleted.
Tools:
Add support for some new testing infrastructure; see below for more details.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::isAnimatingDragCancel const):
Add a new testing hook to return whether or not the web view's drag interaction is currently animating a drag
cancel (i.e., the drag preview is animating back to its original frame).
* WebKitTestRunner/TestOptions.cpp:
(WTR::TestOptions::defaults):
(WTR::TestOptions::keyTypeMapping):
* WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::dragInteractionPolicy const):
Add a test option that allows tests to override the drag interaction policy to "always-allow",
"always-disallow", and the default value. This option allows us to force drag and drop to be enabled when
testing on iPhone simulator.
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::dragInteractionPolicy):
(WTR::TestController::platformResetStateToConsistentValues):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::isAnimatingDragCancel const):
LayoutTests:
Add a new layout test that initiates dragging on an image using a synthesized event stream, and verifies that
"dragstart" and "dragend" events are dispatched on the image.
* fast/events/ios/dragstart-on-image-by-long-pressing-expected.txt: Added.
* fast/events/ios/dragstart-on-image-by-long-pressing.html: Added.
* resources/ui-helper.js:
(window.UIHelper.isAnimatingDragCancel):
Add a `UIHelper` method that returns whether or not the dragging animation is being cancelled. The new test uses
this hook to wait for the drag cancel animation to end before proceeding to the next test.
Canonical link: https://commits.webkit.org/236202@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@275546 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-06 20:39:10 +00:00
|
|
|
static isAnimatingDragCancel()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`uiController.isAnimatingDragCancel`, result => resolve(result === "true"));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[WK2] EditorState updates should be rolled into the layer update lifecycle when possible
https://bugs.webkit.org/show_bug.cgi?id=175370
<rdar://problem/33799806>
Reviewed by Ryosuke Niwa.
Source/WebCore:
Remove didChangeSelectionAndUpdateLayout -- EditorState updates that are scheduled due to missing post-layout
data will now be scheduled for the next presentation update. Additionally, add editor client hooks to notify the
WebKit layer when we've updated the current composition. See WebKit ChangeLog for more details. This patch
adjusts and rebaselines existing layout tests.
* editing/Editor.cpp:
(WebCore::SetCompositionScope::SetCompositionScope):
(WebCore::SetCompositionScope::~SetCompositionScope):
Introduce a helper RAII class to ensure that we ignore selection changes during the scope of
Editor::setComposition and call out to the client with WebEditorClient::didUpdateComposition afterwards. This
also maintains a UserTypingGestureIndicator over its lifetime, so we don't additionally need to create a
UserTypingGestureIndicator in Editor::setComposition.
(WebCore::Editor::setComposition):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::setSelection):
(WebCore::FrameSelection::updateAndRevealSelection):
(WebCore::FrameSelection::setSelectedRange):
* editing/FrameSelection.h:
(WebCore::FrameSelection::defaultSetSelectionOptions):
Plumb state about whether or not the selection change was triggered by the user to FrameSelection::setSelection,
and if so, notify the editing client. A separate SetSelectionOptions flag is used here instead of
RevealSelection to avoid calling out to the client in places where we want to reveal the selection regardless of
whether or not the selection is user triggered.
* loader/EmptyClients.cpp:
* page/EditorClient.h:
Source/WebKit:
See per-method comments for more detail. WebPage::didChangeSelection now schedules EditorState updates to be sent
during the next layer tree transaction rather than sending them synchronously. To ensure that iOS and Mac continue
to behave correctly w.r.t. EditorState updates, we immediately dispatch EditorStates in the following cases:
- After the composition changes, is confirmed, or is canceled.
- After an edit command is executed.
- After ending user-triggered selection changes.
* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::hasEditorState const):
(WebKit::RemoteLayerTreeTransaction::editorState const):
(WebKit::RemoteLayerTreeTransaction::setEditorState):
Attaches an optional EditorState to the RemoteLayerTreeTransaction. This EditorState is computed and sent over
when setting up the transaction in WebPage, if something previously scheduled an EditorState update.
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode const):
(WebKit::RemoteLayerTreeTransaction::decode):
Add coder support for sending over a layer tree transaction's EditorState.
* UIProcess/API/Cocoa/WKViewPrivate.h:
* UIProcess/API/mac/WKView.mm:
(-[WKView _doAfterNextPresentationUpdate:]):
Add _doAfterNextPresentationUpdate to WKView (used in TestWebKitAPI -- refer to
WebKitAgnosticTest::waitForNextPresentationUpdate).
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
* UIProcess/DrawingAreaProxy.messages.in:
Add a new IPC messages, DispatchPresentationCallbacksAfterFlushingLayers, to invoke in-flight presentation
callbacks in the UI process following a layer flush in the web process.
* UIProcess/WebPageProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h:
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::~TiledCoreAnimationDrawingAreaProxy):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
Run all pending _doAfterNextPresentationUpdate callbacks.
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::didApplyStyle):
(WebKit::WebEditorClient::respondToChangedContents):
(WebKit::WebEditorClient::didEndUserTriggeredSelectionChanges):
(WebKit::WebEditorClient::didUpdateComposition):
Forward editor client calls to the WebPage.
(WebKit::WebEditorClient::didChangeSelectionAndUpdateLayout): Deleted.
* WebProcess/WebCoreSupport/WebEditorClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::editorState const):
(WebKit::WebPage::updateEditorStateAfterLayoutIfEditabilityChanged):
(WebKit::WebPage::willCommitLayerTree):
(WebKit::WebPage::didApplyStyle):
Allow style application to immediately trigger EditorState updates, if we're not currently ignoring selection
changes in the Editor.
(WebKit::WebPage::didChangeContents):
Allow applying top-level edit commands to immediately trigger EditorState updates, if we're not currently
ignoring selection changes in the Editor.
(WebKit::WebPage::didChangeSelection):
(WebKit::WebPage::didUpdateComposition):
(WebKit::WebPage::didEndUserTriggeredSelectionChanges):
(WebKit::WebPage::discardedComposition):
(WebKit::WebPage::canceledComposition):
When handling composition updates, always send an EditorState to the UI process. Unlike other cases, IME
requires immediate EditorState data, so we need to be explicit here in sending updates right away.
(WebKit::WebPage::sendEditorStateUpdate):
(WebKit::WebPage::sendPartialEditorStateAndSchedulePostLayoutUpdate):
(WebKit::WebPage::flushPendingEditorStateUpdate):
Helper methods to schedule an EditorState update to be sent upon the next layer tree update, or flush any
pending EditorState update that has been scheduled. The private, more aggressive variant of this is
sendEditorStateUpdate, which ignores whether or not there was already an EditorState update scheduled, and sends
one anyways (this still fulfills any EditorState update that was previously scheduled).
These helper methods are treated as no-ops when invoked while ignoring selection changes. This is to prevent
temporary selection state and editor commands during operations such as text indicator snapshotting from pushing
bogus information about transient editor states to the UI process.
(WebKit::WebPage::sendPostLayoutEditorStateIfNeeded): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::executeEditCommandWithCallback):
(WebKit::selectionIsInsideFixedPositionContainer):
(WebKit::WebPage::updateVisibleContentRects):
Fix a hack that was computing an EditorState to figure out whether the current selection starts or ends in a
fixed position container. Factors out relevant logic into a separate helper, and also schedules an EditorState
update instead of immediately computing it.
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::addTransactionCallbackID):
Add support for registering and dispatching presentation callbacks that hook into the layer flush lifecycle,
using the tiled CA drawing area. These are used by Mac LayoutTests and API tests that need to wait until the
next flush before checking for state that depends on EditorState updates in the UI process.
(WebKit::TiledCoreAnimationDrawingArea::flushLayers):
Tell the WebPage to flush any pending EditorState updates.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState const):
Source/WebKitLegacy/mac:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Source/WebKitLegacy/win:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Tools:
Tweaks API tests that involve editing to wait for a presentation update before checking against UI process-side
information sent via EditorState updates. This allows any EditorState update scheduled by the test to propagate
to the UI process.
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewCandidateTests.mm:
(-[CandidateTestWebView typeString:inputMessage:]):
(+[CandidateTestWebView setUpWithFrame:testPage:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewTextInput.mm:
* TestWebKitAPI/Tests/mac/AcceptsFirstMouse.mm:
(TestWebKitAPI::AcceptsFirstMouse::runTest):
* TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm:
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView waitForNextPresentationUpdate]):
Add a new helper method to spin until the next presentation update.
* TestWebKitAPI/mac/WebKitAgnosticTest.h:
* TestWebKitAPI/mac/WebKitAgnosticTest.mm:
(TestWebKitAPI::WebKitAgnosticTest::waitForNextPresentationUpdate):
LayoutTests:
Rebaseline and adjust LayoutTests.
* editing/caret/ios/absolute-caret-position-after-scroll-expected.txt:
* editing/caret/ios/absolute-caret-position-after-scroll.html:
* editing/caret/ios/fixed-caret-position-after-scroll-expected.txt:
* editing/caret/ios/fixed-caret-position-after-scroll.html:
* editing/secure-input/password-input-changed-type.html:
* editing/secure-input/password-input-focusing.html:
* editing/secure-input/removed-password-input.html:
* editing/secure-input/reset-state-on-navigation.html:
* editing/selection/character-granularity-rect.html:
Delay checking for secure input state and caret rects until after the next presentation update.
* editing/selection/ios/absolute-selection-after-scroll-expected.txt:
* editing/selection/ios/absolute-selection-after-scroll.html:
* editing/selection/ios/fixed-selection-after-scroll-expected.txt:
* editing/selection/ios/fixed-selection-after-scroll.html:
Refactor and simplify these tests. These tests are not run on the OpenSource bots, since they depend on long
press and tap gestures.
* platform/ios-wk2/editing/inserting/insert-div-024-expected.txt:
* platform/ios-wk2/editing/inserting/insert-div-026-expected.txt:
* platform/ios-wk2/editing/style/5084241-expected.txt:
Rebaselines these tests, removing an anonymous RenderBlock inserted as a result of inserting and removing a
dummy span in order to compute a RenderStyle in WebPage::editorState. This is because editorState is no longer
invoked immediately on page load; https://bugs.webkit.org/show_bug.cgi?id=175116 tracks preventing this render
tree thrashing altogether.
* platform/mac-wk2/TestExpectations:
* platform/mac-wk2/editing/style/unbold-in-bold-expected.txt:
* resources/ui-helper.js:
Introduce new UIHelper functions.
(window.UIHelper.ensurePresentationUpdate.return.new.Promise):
(window.UIHelper.ensurePresentationUpdate):
Returns a Promise, resolved after the next presentation update.
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise):
(window.UIHelper.activateAndWaitForInputSessionAt):
Returns a Promise, resolved after tapping at the given location and waiting for the keyboard to appear on iOS.
(window.UIHelper.getUICaretRect.return.new.Promise.):
(window.UIHelper.getUICaretRect.return.new.Promise):
(window.UIHelper.getUICaretRect):
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
Helpers to fetch selection and caret rect information in the UI process.
Canonical link: https://commits.webkit.org/192519@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221064 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-23 03:15:38 +00:00
|
|
|
static ensurePresentationUpdate()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2()) {
|
|
|
|
testRunner.display();
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
uiController.doAfterPresentationUpdate(function() {
|
2019-01-17 19:15:57 +00:00
|
|
|
uiController.uiScriptComplete();
|
[WK2] EditorState updates should be rolled into the layer update lifecycle when possible
https://bugs.webkit.org/show_bug.cgi?id=175370
<rdar://problem/33799806>
Reviewed by Ryosuke Niwa.
Source/WebCore:
Remove didChangeSelectionAndUpdateLayout -- EditorState updates that are scheduled due to missing post-layout
data will now be scheduled for the next presentation update. Additionally, add editor client hooks to notify the
WebKit layer when we've updated the current composition. See WebKit ChangeLog for more details. This patch
adjusts and rebaselines existing layout tests.
* editing/Editor.cpp:
(WebCore::SetCompositionScope::SetCompositionScope):
(WebCore::SetCompositionScope::~SetCompositionScope):
Introduce a helper RAII class to ensure that we ignore selection changes during the scope of
Editor::setComposition and call out to the client with WebEditorClient::didUpdateComposition afterwards. This
also maintains a UserTypingGestureIndicator over its lifetime, so we don't additionally need to create a
UserTypingGestureIndicator in Editor::setComposition.
(WebCore::Editor::setComposition):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::setSelection):
(WebCore::FrameSelection::updateAndRevealSelection):
(WebCore::FrameSelection::setSelectedRange):
* editing/FrameSelection.h:
(WebCore::FrameSelection::defaultSetSelectionOptions):
Plumb state about whether or not the selection change was triggered by the user to FrameSelection::setSelection,
and if so, notify the editing client. A separate SetSelectionOptions flag is used here instead of
RevealSelection to avoid calling out to the client in places where we want to reveal the selection regardless of
whether or not the selection is user triggered.
* loader/EmptyClients.cpp:
* page/EditorClient.h:
Source/WebKit:
See per-method comments for more detail. WebPage::didChangeSelection now schedules EditorState updates to be sent
during the next layer tree transaction rather than sending them synchronously. To ensure that iOS and Mac continue
to behave correctly w.r.t. EditorState updates, we immediately dispatch EditorStates in the following cases:
- After the composition changes, is confirmed, or is canceled.
- After an edit command is executed.
- After ending user-triggered selection changes.
* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::hasEditorState const):
(WebKit::RemoteLayerTreeTransaction::editorState const):
(WebKit::RemoteLayerTreeTransaction::setEditorState):
Attaches an optional EditorState to the RemoteLayerTreeTransaction. This EditorState is computed and sent over
when setting up the transaction in WebPage, if something previously scheduled an EditorState update.
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode const):
(WebKit::RemoteLayerTreeTransaction::decode):
Add coder support for sending over a layer tree transaction's EditorState.
* UIProcess/API/Cocoa/WKViewPrivate.h:
* UIProcess/API/mac/WKView.mm:
(-[WKView _doAfterNextPresentationUpdate:]):
Add _doAfterNextPresentationUpdate to WKView (used in TestWebKitAPI -- refer to
WebKitAgnosticTest::waitForNextPresentationUpdate).
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
* UIProcess/DrawingAreaProxy.messages.in:
Add a new IPC messages, DispatchPresentationCallbacksAfterFlushingLayers, to invoke in-flight presentation
callbacks in the UI process following a layer flush in the web process.
* UIProcess/WebPageProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h:
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::~TiledCoreAnimationDrawingAreaProxy):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
Run all pending _doAfterNextPresentationUpdate callbacks.
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::didApplyStyle):
(WebKit::WebEditorClient::respondToChangedContents):
(WebKit::WebEditorClient::didEndUserTriggeredSelectionChanges):
(WebKit::WebEditorClient::didUpdateComposition):
Forward editor client calls to the WebPage.
(WebKit::WebEditorClient::didChangeSelectionAndUpdateLayout): Deleted.
* WebProcess/WebCoreSupport/WebEditorClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::editorState const):
(WebKit::WebPage::updateEditorStateAfterLayoutIfEditabilityChanged):
(WebKit::WebPage::willCommitLayerTree):
(WebKit::WebPage::didApplyStyle):
Allow style application to immediately trigger EditorState updates, if we're not currently ignoring selection
changes in the Editor.
(WebKit::WebPage::didChangeContents):
Allow applying top-level edit commands to immediately trigger EditorState updates, if we're not currently
ignoring selection changes in the Editor.
(WebKit::WebPage::didChangeSelection):
(WebKit::WebPage::didUpdateComposition):
(WebKit::WebPage::didEndUserTriggeredSelectionChanges):
(WebKit::WebPage::discardedComposition):
(WebKit::WebPage::canceledComposition):
When handling composition updates, always send an EditorState to the UI process. Unlike other cases, IME
requires immediate EditorState data, so we need to be explicit here in sending updates right away.
(WebKit::WebPage::sendEditorStateUpdate):
(WebKit::WebPage::sendPartialEditorStateAndSchedulePostLayoutUpdate):
(WebKit::WebPage::flushPendingEditorStateUpdate):
Helper methods to schedule an EditorState update to be sent upon the next layer tree update, or flush any
pending EditorState update that has been scheduled. The private, more aggressive variant of this is
sendEditorStateUpdate, which ignores whether or not there was already an EditorState update scheduled, and sends
one anyways (this still fulfills any EditorState update that was previously scheduled).
These helper methods are treated as no-ops when invoked while ignoring selection changes. This is to prevent
temporary selection state and editor commands during operations such as text indicator snapshotting from pushing
bogus information about transient editor states to the UI process.
(WebKit::WebPage::sendPostLayoutEditorStateIfNeeded): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::executeEditCommandWithCallback):
(WebKit::selectionIsInsideFixedPositionContainer):
(WebKit::WebPage::updateVisibleContentRects):
Fix a hack that was computing an EditorState to figure out whether the current selection starts or ends in a
fixed position container. Factors out relevant logic into a separate helper, and also schedules an EditorState
update instead of immediately computing it.
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::addTransactionCallbackID):
Add support for registering and dispatching presentation callbacks that hook into the layer flush lifecycle,
using the tiled CA drawing area. These are used by Mac LayoutTests and API tests that need to wait until the
next flush before checking for state that depends on EditorState updates in the UI process.
(WebKit::TiledCoreAnimationDrawingArea::flushLayers):
Tell the WebPage to flush any pending EditorState updates.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState const):
Source/WebKitLegacy/mac:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Source/WebKitLegacy/win:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Tools:
Tweaks API tests that involve editing to wait for a presentation update before checking against UI process-side
information sent via EditorState updates. This allows any EditorState update scheduled by the test to propagate
to the UI process.
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewCandidateTests.mm:
(-[CandidateTestWebView typeString:inputMessage:]):
(+[CandidateTestWebView setUpWithFrame:testPage:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewTextInput.mm:
* TestWebKitAPI/Tests/mac/AcceptsFirstMouse.mm:
(TestWebKitAPI::AcceptsFirstMouse::runTest):
* TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm:
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView waitForNextPresentationUpdate]):
Add a new helper method to spin until the next presentation update.
* TestWebKitAPI/mac/WebKitAgnosticTest.h:
* TestWebKitAPI/mac/WebKitAgnosticTest.mm:
(TestWebKitAPI::WebKitAgnosticTest::waitForNextPresentationUpdate):
LayoutTests:
Rebaseline and adjust LayoutTests.
* editing/caret/ios/absolute-caret-position-after-scroll-expected.txt:
* editing/caret/ios/absolute-caret-position-after-scroll.html:
* editing/caret/ios/fixed-caret-position-after-scroll-expected.txt:
* editing/caret/ios/fixed-caret-position-after-scroll.html:
* editing/secure-input/password-input-changed-type.html:
* editing/secure-input/password-input-focusing.html:
* editing/secure-input/removed-password-input.html:
* editing/secure-input/reset-state-on-navigation.html:
* editing/selection/character-granularity-rect.html:
Delay checking for secure input state and caret rects until after the next presentation update.
* editing/selection/ios/absolute-selection-after-scroll-expected.txt:
* editing/selection/ios/absolute-selection-after-scroll.html:
* editing/selection/ios/fixed-selection-after-scroll-expected.txt:
* editing/selection/ios/fixed-selection-after-scroll.html:
Refactor and simplify these tests. These tests are not run on the OpenSource bots, since they depend on long
press and tap gestures.
* platform/ios-wk2/editing/inserting/insert-div-024-expected.txt:
* platform/ios-wk2/editing/inserting/insert-div-026-expected.txt:
* platform/ios-wk2/editing/style/5084241-expected.txt:
Rebaselines these tests, removing an anonymous RenderBlock inserted as a result of inserting and removing a
dummy span in order to compute a RenderStyle in WebPage::editorState. This is because editorState is no longer
invoked immediately on page load; https://bugs.webkit.org/show_bug.cgi?id=175116 tracks preventing this render
tree thrashing altogether.
* platform/mac-wk2/TestExpectations:
* platform/mac-wk2/editing/style/unbold-in-bold-expected.txt:
* resources/ui-helper.js:
Introduce new UIHelper functions.
(window.UIHelper.ensurePresentationUpdate.return.new.Promise):
(window.UIHelper.ensurePresentationUpdate):
Returns a Promise, resolved after the next presentation update.
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise):
(window.UIHelper.activateAndWaitForInputSessionAt):
Returns a Promise, resolved after tapping at the given location and waiting for the keyboard to appear on iOS.
(window.UIHelper.getUICaretRect.return.new.Promise.):
(window.UIHelper.getUICaretRect.return.new.Promise):
(window.UIHelper.getUICaretRect):
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
Helpers to fetch selection and caret rect information in the UI process.
Canonical link: https://commits.webkit.org/192519@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221064 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-23 03:15:38 +00:00
|
|
|
});`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-07-25 21:12:01 +00:00
|
|
|
static ensureStablePresentationUpdate()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2()) {
|
|
|
|
testRunner.display();
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
uiController.doAfterNextStablePresentationUpdate(function() {
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
});`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-07-05 21:56:58 +00:00
|
|
|
static ensurePositionInformationUpdateForElement(element)
|
|
|
|
{
|
|
|
|
const boundingRect = element.getBoundingClientRect();
|
|
|
|
const x = boundingRect.x + 5;
|
|
|
|
const y = boundingRect.y + 5;
|
|
|
|
|
|
|
|
if (!this.isWebKit2()) {
|
|
|
|
testRunner.display();
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
uiController.ensurePositionInformationIsUpToDateAt(${x}, ${y}, function () {
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
});`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-03-15 01:10:09 +00:00
|
|
|
static delayFor(ms)
|
2019-03-10 05:52:21 +00:00
|
|
|
{
|
|
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
}
|
[iOS WK2] theverge.com - rubber band scrolling at the top of the page causes an abrupt jump
https://bugs.webkit.org/show_bug.cgi?id=220886
<rdar://71177566>
Reviewed by Sam Weinig.
Source/WebCore:
theverge.com on iOS is a page that has long main thread stalls with forced layouts on a timer
that alter the page height; this caused the post-layout updateScrollbars() called from
FrameView::adjustViewSize() to call scrollToPosition() after adjusting the scroll position
to the allowed range.
If the page laid out while rubberbanding was happening, the current scroll position would
be negative, then clamped to 0, then sent to the UI process as a requested scroll to 0,
triggering the jump to top in the UI process.
There's existing code to prevent this from happening if we know that rubberbanding is
happening; this patch makes isRubberBandInProgress() work for iOS WK2. It does so
by having updateVisibleContentRects() push information about rubberbanding nodes onto
RemoteScrollingCoordinator.
We remove an unnecessary shouldUpdateScrollLayerPositionSynchronously() check in
FrameView::isRubberBandInProgress() - if it's true, then the scrolling coordinator
won't see any rubberbanding nodes anyway.
Test: fast/scrolling/ios/content-size-change-during-rubberband.html
* page/FrameView.cpp:
(WebCore::FrameView::isRubberBandInProgress const):
* page/FrameView.h:
* platform/ScrollView.cpp:
(WebCore::ScrollView::updateScrollbars):
Source/WebKit:
theverge.com on iOS is a page that has long main thread stalls with forced layouts on a timer
that alter the page height; this caused the post-layout updateScrollbars() called from
FrameView::adjustViewSize() to call scrollToPosition() after adjusting the scroll position
to the allowed range.
If the page laid out while rubberbanding was happening, the current scroll position would
be negative, then clamped to 0, then sent to the UI process as a requested scroll to 0,
triggering the jump to top in the UI process.
There's existing code to prevent this from happening if we know that rubberbanding is
happening; this patch makes isRubberBandInProgress() work for iOS WK2. It does so
by having updateVisibleContentRects() push information about rubberbanding nodes onto
RemoteScrollingCoordinator.
We remove an unnecessary shouldUpdateScrollLayerPositionSynchronously() check in
FrameView::isRubberBandInProgress() - if it's true, then the scrolling coordinator
won't see any rubberbanding nodes anyway.
* UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:
* WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm:
(WebKit::RemoteScrollingCoordinator::addNodeWithActiveRubberBanding):
(WebKit::RemoteScrollingCoordinator::removeNodeWithActiveRubberBanding):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::updateVisibleContentRects):
Tools:
Add test infrastructure to allow UIScriptController::scrollToOffset() and
UIScriptController::immediateScrollToOffset() to take an options argument with
a 'unconstrained' property, which allows scrolling to unstable offset to simulate
rubberbanding.
* DumpRenderTree/ios/UIScriptControllerIOS.h:
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::contentOffsetBoundedIfNecessary):
(WTR::UIScriptControllerIOS::scrollToOffset):
(WTR::UIScriptControllerIOS::immediateScrollToOffset):
(WTR::contentOffsetBoundedInValidRange): Deleted.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::scrollToOffset):
(WTR::UIScriptController::immediateScrollToOffset):
* TestRunnerShared/UIScriptContext/UIScriptControllerShared.cpp:
(WTR::toScrollToOptions):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::contentOffsetBoundedIfNecessary):
(WTR::UIScriptControllerIOS::scrollToOffset):
(WTR::UIScriptControllerIOS::immediateScrollToOffset):
(WTR::contentOffsetBoundedInValidRange): Deleted.
LayoutTests:
Add test infrastructure to allow UIScriptController::scrollToOffset() and
UIScriptController::immediateScrollToOffset() to take an options argument with
a 'unconstrained' property, which allows scrolling to unstable offset to simulate
rubberbanding.
* fast/scrolling/ios/content-size-change-during-rubberband-expected.txt: Added.
* fast/scrolling/ios/content-size-change-during-rubberband.html: Added.
* resources/ui-helper.js:
(window.UIHelper.scrollTo.return.new.Promise.):
(window.UIHelper.scrollTo.return.new.Promise):
(window.UIHelper.scrollTo):
(window.UIHelper.immediateScrollTo):
(window.UIHelper.immediateUnstableScrollTo):
Canonical link: https://commits.webkit.org/233292@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271786 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-01-25 00:47:32 +00:00
|
|
|
|
|
|
|
static scrollTo(x, y, unconstrained)
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2()) {
|
|
|
|
window.scrollTo(x, y);
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
uiController.didEndScrollingCallback = function() {
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
}
|
|
|
|
uiController.scrollToOffset(${x}, ${y}, { unconstrained: ${unconstrained} });
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
2019-03-10 05:52:21 +00:00
|
|
|
|
[iOS WK2] theverge.com - rubber band scrolling at the top of the page causes an abrupt jump
https://bugs.webkit.org/show_bug.cgi?id=220886
<rdar://71177566>
Reviewed by Sam Weinig.
Source/WebCore:
theverge.com on iOS is a page that has long main thread stalls with forced layouts on a timer
that alter the page height; this caused the post-layout updateScrollbars() called from
FrameView::adjustViewSize() to call scrollToPosition() after adjusting the scroll position
to the allowed range.
If the page laid out while rubberbanding was happening, the current scroll position would
be negative, then clamped to 0, then sent to the UI process as a requested scroll to 0,
triggering the jump to top in the UI process.
There's existing code to prevent this from happening if we know that rubberbanding is
happening; this patch makes isRubberBandInProgress() work for iOS WK2. It does so
by having updateVisibleContentRects() push information about rubberbanding nodes onto
RemoteScrollingCoordinator.
We remove an unnecessary shouldUpdateScrollLayerPositionSynchronously() check in
FrameView::isRubberBandInProgress() - if it's true, then the scrolling coordinator
won't see any rubberbanding nodes anyway.
Test: fast/scrolling/ios/content-size-change-during-rubberband.html
* page/FrameView.cpp:
(WebCore::FrameView::isRubberBandInProgress const):
* page/FrameView.h:
* platform/ScrollView.cpp:
(WebCore::ScrollView::updateScrollbars):
Source/WebKit:
theverge.com on iOS is a page that has long main thread stalls with forced layouts on a timer
that alter the page height; this caused the post-layout updateScrollbars() called from
FrameView::adjustViewSize() to call scrollToPosition() after adjusting the scroll position
to the allowed range.
If the page laid out while rubberbanding was happening, the current scroll position would
be negative, then clamped to 0, then sent to the UI process as a requested scroll to 0,
triggering the jump to top in the UI process.
There's existing code to prevent this from happening if we know that rubberbanding is
happening; this patch makes isRubberBandInProgress() work for iOS WK2. It does so
by having updateVisibleContentRects() push information about rubberbanding nodes onto
RemoteScrollingCoordinator.
We remove an unnecessary shouldUpdateScrollLayerPositionSynchronously() check in
FrameView::isRubberBandInProgress() - if it's true, then the scrolling coordinator
won't see any rubberbanding nodes anyway.
* UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:
* WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm:
(WebKit::RemoteScrollingCoordinator::addNodeWithActiveRubberBanding):
(WebKit::RemoteScrollingCoordinator::removeNodeWithActiveRubberBanding):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::updateVisibleContentRects):
Tools:
Add test infrastructure to allow UIScriptController::scrollToOffset() and
UIScriptController::immediateScrollToOffset() to take an options argument with
a 'unconstrained' property, which allows scrolling to unstable offset to simulate
rubberbanding.
* DumpRenderTree/ios/UIScriptControllerIOS.h:
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::contentOffsetBoundedIfNecessary):
(WTR::UIScriptControllerIOS::scrollToOffset):
(WTR::UIScriptControllerIOS::immediateScrollToOffset):
(WTR::contentOffsetBoundedInValidRange): Deleted.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::scrollToOffset):
(WTR::UIScriptController::immediateScrollToOffset):
* TestRunnerShared/UIScriptContext/UIScriptControllerShared.cpp:
(WTR::toScrollToOptions):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::contentOffsetBoundedIfNecessary):
(WTR::UIScriptControllerIOS::scrollToOffset):
(WTR::UIScriptControllerIOS::immediateScrollToOffset):
(WTR::contentOffsetBoundedInValidRange): Deleted.
LayoutTests:
Add test infrastructure to allow UIScriptController::scrollToOffset() and
UIScriptController::immediateScrollToOffset() to take an options argument with
a 'unconstrained' property, which allows scrolling to unstable offset to simulate
rubberbanding.
* fast/scrolling/ios/content-size-change-during-rubberband-expected.txt: Added.
* fast/scrolling/ios/content-size-change-during-rubberband.html: Added.
* resources/ui-helper.js:
(window.UIHelper.scrollTo.return.new.Promise.):
(window.UIHelper.scrollTo.return.new.Promise):
(window.UIHelper.scrollTo):
(window.UIHelper.immediateScrollTo):
(window.UIHelper.immediateUnstableScrollTo):
Canonical link: https://commits.webkit.org/233292@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271786 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-01-25 00:47:32 +00:00
|
|
|
static immediateScrollTo(x, y, unconstrained)
|
2019-03-10 05:52:21 +00:00
|
|
|
{
|
|
|
|
if (!this.isWebKit2()) {
|
|
|
|
window.scrollTo(x, y);
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
2019-03-15 01:10:09 +00:00
|
|
|
return new Promise(resolve => {
|
2019-03-10 05:52:21 +00:00
|
|
|
testRunner.runUIScript(`
|
[iOS WK2] theverge.com - rubber band scrolling at the top of the page causes an abrupt jump
https://bugs.webkit.org/show_bug.cgi?id=220886
<rdar://71177566>
Reviewed by Sam Weinig.
Source/WebCore:
theverge.com on iOS is a page that has long main thread stalls with forced layouts on a timer
that alter the page height; this caused the post-layout updateScrollbars() called from
FrameView::adjustViewSize() to call scrollToPosition() after adjusting the scroll position
to the allowed range.
If the page laid out while rubberbanding was happening, the current scroll position would
be negative, then clamped to 0, then sent to the UI process as a requested scroll to 0,
triggering the jump to top in the UI process.
There's existing code to prevent this from happening if we know that rubberbanding is
happening; this patch makes isRubberBandInProgress() work for iOS WK2. It does so
by having updateVisibleContentRects() push information about rubberbanding nodes onto
RemoteScrollingCoordinator.
We remove an unnecessary shouldUpdateScrollLayerPositionSynchronously() check in
FrameView::isRubberBandInProgress() - if it's true, then the scrolling coordinator
won't see any rubberbanding nodes anyway.
Test: fast/scrolling/ios/content-size-change-during-rubberband.html
* page/FrameView.cpp:
(WebCore::FrameView::isRubberBandInProgress const):
* page/FrameView.h:
* platform/ScrollView.cpp:
(WebCore::ScrollView::updateScrollbars):
Source/WebKit:
theverge.com on iOS is a page that has long main thread stalls with forced layouts on a timer
that alter the page height; this caused the post-layout updateScrollbars() called from
FrameView::adjustViewSize() to call scrollToPosition() after adjusting the scroll position
to the allowed range.
If the page laid out while rubberbanding was happening, the current scroll position would
be negative, then clamped to 0, then sent to the UI process as a requested scroll to 0,
triggering the jump to top in the UI process.
There's existing code to prevent this from happening if we know that rubberbanding is
happening; this patch makes isRubberBandInProgress() work for iOS WK2. It does so
by having updateVisibleContentRects() push information about rubberbanding nodes onto
RemoteScrollingCoordinator.
We remove an unnecessary shouldUpdateScrollLayerPositionSynchronously() check in
FrameView::isRubberBandInProgress() - if it's true, then the scrolling coordinator
won't see any rubberbanding nodes anyway.
* UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:
* WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm:
(WebKit::RemoteScrollingCoordinator::addNodeWithActiveRubberBanding):
(WebKit::RemoteScrollingCoordinator::removeNodeWithActiveRubberBanding):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::updateVisibleContentRects):
Tools:
Add test infrastructure to allow UIScriptController::scrollToOffset() and
UIScriptController::immediateScrollToOffset() to take an options argument with
a 'unconstrained' property, which allows scrolling to unstable offset to simulate
rubberbanding.
* DumpRenderTree/ios/UIScriptControllerIOS.h:
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::contentOffsetBoundedIfNecessary):
(WTR::UIScriptControllerIOS::scrollToOffset):
(WTR::UIScriptControllerIOS::immediateScrollToOffset):
(WTR::contentOffsetBoundedInValidRange): Deleted.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::scrollToOffset):
(WTR::UIScriptController::immediateScrollToOffset):
* TestRunnerShared/UIScriptContext/UIScriptControllerShared.cpp:
(WTR::toScrollToOptions):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::contentOffsetBoundedIfNecessary):
(WTR::UIScriptControllerIOS::scrollToOffset):
(WTR::UIScriptControllerIOS::immediateScrollToOffset):
(WTR::contentOffsetBoundedInValidRange): Deleted.
LayoutTests:
Add test infrastructure to allow UIScriptController::scrollToOffset() and
UIScriptController::immediateScrollToOffset() to take an options argument with
a 'unconstrained' property, which allows scrolling to unstable offset to simulate
rubberbanding.
* fast/scrolling/ios/content-size-change-during-rubberband-expected.txt: Added.
* fast/scrolling/ios/content-size-change-during-rubberband.html: Added.
* resources/ui-helper.js:
(window.UIHelper.scrollTo.return.new.Promise.):
(window.UIHelper.scrollTo.return.new.Promise):
(window.UIHelper.scrollTo):
(window.UIHelper.immediateScrollTo):
(window.UIHelper.immediateUnstableScrollTo):
Canonical link: https://commits.webkit.org/233292@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271786 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-01-25 00:47:32 +00:00
|
|
|
uiController.immediateScrollToOffset(${x}, ${y}, { unconstrained: ${unconstrained} });`, resolve);
|
2019-03-10 05:52:21 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[iOS WK2] theverge.com - rubber band scrolling at the top of the page causes an abrupt jump
https://bugs.webkit.org/show_bug.cgi?id=220886
<rdar://71177566>
Reviewed by Sam Weinig.
Source/WebCore:
theverge.com on iOS is a page that has long main thread stalls with forced layouts on a timer
that alter the page height; this caused the post-layout updateScrollbars() called from
FrameView::adjustViewSize() to call scrollToPosition() after adjusting the scroll position
to the allowed range.
If the page laid out while rubberbanding was happening, the current scroll position would
be negative, then clamped to 0, then sent to the UI process as a requested scroll to 0,
triggering the jump to top in the UI process.
There's existing code to prevent this from happening if we know that rubberbanding is
happening; this patch makes isRubberBandInProgress() work for iOS WK2. It does so
by having updateVisibleContentRects() push information about rubberbanding nodes onto
RemoteScrollingCoordinator.
We remove an unnecessary shouldUpdateScrollLayerPositionSynchronously() check in
FrameView::isRubberBandInProgress() - if it's true, then the scrolling coordinator
won't see any rubberbanding nodes anyway.
Test: fast/scrolling/ios/content-size-change-during-rubberband.html
* page/FrameView.cpp:
(WebCore::FrameView::isRubberBandInProgress const):
* page/FrameView.h:
* platform/ScrollView.cpp:
(WebCore::ScrollView::updateScrollbars):
Source/WebKit:
theverge.com on iOS is a page that has long main thread stalls with forced layouts on a timer
that alter the page height; this caused the post-layout updateScrollbars() called from
FrameView::adjustViewSize() to call scrollToPosition() after adjusting the scroll position
to the allowed range.
If the page laid out while rubberbanding was happening, the current scroll position would
be negative, then clamped to 0, then sent to the UI process as a requested scroll to 0,
triggering the jump to top in the UI process.
There's existing code to prevent this from happening if we know that rubberbanding is
happening; this patch makes isRubberBandInProgress() work for iOS WK2. It does so
by having updateVisibleContentRects() push information about rubberbanding nodes onto
RemoteScrollingCoordinator.
We remove an unnecessary shouldUpdateScrollLayerPositionSynchronously() check in
FrameView::isRubberBandInProgress() - if it's true, then the scrolling coordinator
won't see any rubberbanding nodes anyway.
* UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:
* WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm:
(WebKit::RemoteScrollingCoordinator::addNodeWithActiveRubberBanding):
(WebKit::RemoteScrollingCoordinator::removeNodeWithActiveRubberBanding):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::updateVisibleContentRects):
Tools:
Add test infrastructure to allow UIScriptController::scrollToOffset() and
UIScriptController::immediateScrollToOffset() to take an options argument with
a 'unconstrained' property, which allows scrolling to unstable offset to simulate
rubberbanding.
* DumpRenderTree/ios/UIScriptControllerIOS.h:
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::contentOffsetBoundedIfNecessary):
(WTR::UIScriptControllerIOS::scrollToOffset):
(WTR::UIScriptControllerIOS::immediateScrollToOffset):
(WTR::contentOffsetBoundedInValidRange): Deleted.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::scrollToOffset):
(WTR::UIScriptController::immediateScrollToOffset):
* TestRunnerShared/UIScriptContext/UIScriptControllerShared.cpp:
(WTR::toScrollToOptions):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::contentOffsetBoundedIfNecessary):
(WTR::UIScriptControllerIOS::scrollToOffset):
(WTR::UIScriptControllerIOS::immediateScrollToOffset):
(WTR::contentOffsetBoundedInValidRange): Deleted.
LayoutTests:
Add test infrastructure to allow UIScriptController::scrollToOffset() and
UIScriptController::immediateScrollToOffset() to take an options argument with
a 'unconstrained' property, which allows scrolling to unstable offset to simulate
rubberbanding.
* fast/scrolling/ios/content-size-change-during-rubberband-expected.txt: Added.
* fast/scrolling/ios/content-size-change-during-rubberband.html: Added.
* resources/ui-helper.js:
(window.UIHelper.scrollTo.return.new.Promise.):
(window.UIHelper.scrollTo.return.new.Promise):
(window.UIHelper.scrollTo):
(window.UIHelper.immediateScrollTo):
(window.UIHelper.immediateUnstableScrollTo):
Canonical link: https://commits.webkit.org/233292@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271786 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-01-25 00:47:32 +00:00
|
|
|
static immediateUnstableScrollTo(x, y, unconstrained)
|
2019-03-10 05:52:21 +00:00
|
|
|
{
|
|
|
|
if (!this.isWebKit2()) {
|
|
|
|
window.scrollTo(x, y);
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
2019-03-15 01:10:09 +00:00
|
|
|
return new Promise(resolve => {
|
2019-03-10 05:52:21 +00:00
|
|
|
testRunner.runUIScript(`
|
|
|
|
uiController.stableStateOverride = false;
|
[iOS WK2] theverge.com - rubber band scrolling at the top of the page causes an abrupt jump
https://bugs.webkit.org/show_bug.cgi?id=220886
<rdar://71177566>
Reviewed by Sam Weinig.
Source/WebCore:
theverge.com on iOS is a page that has long main thread stalls with forced layouts on a timer
that alter the page height; this caused the post-layout updateScrollbars() called from
FrameView::adjustViewSize() to call scrollToPosition() after adjusting the scroll position
to the allowed range.
If the page laid out while rubberbanding was happening, the current scroll position would
be negative, then clamped to 0, then sent to the UI process as a requested scroll to 0,
triggering the jump to top in the UI process.
There's existing code to prevent this from happening if we know that rubberbanding is
happening; this patch makes isRubberBandInProgress() work for iOS WK2. It does so
by having updateVisibleContentRects() push information about rubberbanding nodes onto
RemoteScrollingCoordinator.
We remove an unnecessary shouldUpdateScrollLayerPositionSynchronously() check in
FrameView::isRubberBandInProgress() - if it's true, then the scrolling coordinator
won't see any rubberbanding nodes anyway.
Test: fast/scrolling/ios/content-size-change-during-rubberband.html
* page/FrameView.cpp:
(WebCore::FrameView::isRubberBandInProgress const):
* page/FrameView.h:
* platform/ScrollView.cpp:
(WebCore::ScrollView::updateScrollbars):
Source/WebKit:
theverge.com on iOS is a page that has long main thread stalls with forced layouts on a timer
that alter the page height; this caused the post-layout updateScrollbars() called from
FrameView::adjustViewSize() to call scrollToPosition() after adjusting the scroll position
to the allowed range.
If the page laid out while rubberbanding was happening, the current scroll position would
be negative, then clamped to 0, then sent to the UI process as a requested scroll to 0,
triggering the jump to top in the UI process.
There's existing code to prevent this from happening if we know that rubberbanding is
happening; this patch makes isRubberBandInProgress() work for iOS WK2. It does so
by having updateVisibleContentRects() push information about rubberbanding nodes onto
RemoteScrollingCoordinator.
We remove an unnecessary shouldUpdateScrollLayerPositionSynchronously() check in
FrameView::isRubberBandInProgress() - if it's true, then the scrolling coordinator
won't see any rubberbanding nodes anyway.
* UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:
* WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm:
(WebKit::RemoteScrollingCoordinator::addNodeWithActiveRubberBanding):
(WebKit::RemoteScrollingCoordinator::removeNodeWithActiveRubberBanding):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::updateVisibleContentRects):
Tools:
Add test infrastructure to allow UIScriptController::scrollToOffset() and
UIScriptController::immediateScrollToOffset() to take an options argument with
a 'unconstrained' property, which allows scrolling to unstable offset to simulate
rubberbanding.
* DumpRenderTree/ios/UIScriptControllerIOS.h:
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::contentOffsetBoundedIfNecessary):
(WTR::UIScriptControllerIOS::scrollToOffset):
(WTR::UIScriptControllerIOS::immediateScrollToOffset):
(WTR::contentOffsetBoundedInValidRange): Deleted.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::scrollToOffset):
(WTR::UIScriptController::immediateScrollToOffset):
* TestRunnerShared/UIScriptContext/UIScriptControllerShared.cpp:
(WTR::toScrollToOptions):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::contentOffsetBoundedIfNecessary):
(WTR::UIScriptControllerIOS::scrollToOffset):
(WTR::UIScriptControllerIOS::immediateScrollToOffset):
(WTR::contentOffsetBoundedInValidRange): Deleted.
LayoutTests:
Add test infrastructure to allow UIScriptController::scrollToOffset() and
UIScriptController::immediateScrollToOffset() to take an options argument with
a 'unconstrained' property, which allows scrolling to unstable offset to simulate
rubberbanding.
* fast/scrolling/ios/content-size-change-during-rubberband-expected.txt: Added.
* fast/scrolling/ios/content-size-change-during-rubberband.html: Added.
* resources/ui-helper.js:
(window.UIHelper.scrollTo.return.new.Promise.):
(window.UIHelper.scrollTo.return.new.Promise):
(window.UIHelper.scrollTo):
(window.UIHelper.immediateScrollTo):
(window.UIHelper.immediateUnstableScrollTo):
Canonical link: https://commits.webkit.org/233292@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271786 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-01-25 00:47:32 +00:00
|
|
|
uiController.immediateScrollToOffset(${x}, ${y}, { unconstrained: ${unconstrained} });`, resolve);
|
2019-03-10 05:52:21 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-03-26 19:23:52 +00:00
|
|
|
static immediateScrollElementAtContentPointToOffset(x, y, scrollX, scrollY, scrollUpdatesDisabled = false)
|
2019-03-21 08:25:18 +00:00
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
2019-03-26 19:23:52 +00:00
|
|
|
uiController.scrollUpdatesDisabled = ${scrollUpdatesDisabled};
|
2019-03-21 08:25:18 +00:00
|
|
|
uiController.immediateScrollElementAtContentPointToOffset(${x}, ${y}, ${scrollX}, ${scrollY});`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-05-10 21:56:58 +00:00
|
|
|
static ensureVisibleContentRectUpdate()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
const visibleContentRectUpdateScript = "uiController.doAfterVisibleContentRectUpdate(() => uiController.uiScriptComplete())";
|
|
|
|
testRunner.runUIScript(visibleContentRectUpdateScript, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-10-24 02:22:45 +00:00
|
|
|
static longPressAndGetContextMenuContentAt(x, y)
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
uiController.didShowContextMenuCallback = function() {
|
|
|
|
uiController.uiScriptComplete(JSON.stringify(uiController.contentsOfUserInterfaceItem('contextMenu')));
|
|
|
|
};
|
|
|
|
uiController.longPressAtPoint(${x}, ${y}, function() { });
|
2020-02-02 00:56:13 +00:00
|
|
|
})();`, result => resolve(JSON.parse(result)));
|
2019-10-24 02:22:45 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[WK2] EditorState updates should be rolled into the layer update lifecycle when possible
https://bugs.webkit.org/show_bug.cgi?id=175370
<rdar://problem/33799806>
Reviewed by Ryosuke Niwa.
Source/WebCore:
Remove didChangeSelectionAndUpdateLayout -- EditorState updates that are scheduled due to missing post-layout
data will now be scheduled for the next presentation update. Additionally, add editor client hooks to notify the
WebKit layer when we've updated the current composition. See WebKit ChangeLog for more details. This patch
adjusts and rebaselines existing layout tests.
* editing/Editor.cpp:
(WebCore::SetCompositionScope::SetCompositionScope):
(WebCore::SetCompositionScope::~SetCompositionScope):
Introduce a helper RAII class to ensure that we ignore selection changes during the scope of
Editor::setComposition and call out to the client with WebEditorClient::didUpdateComposition afterwards. This
also maintains a UserTypingGestureIndicator over its lifetime, so we don't additionally need to create a
UserTypingGestureIndicator in Editor::setComposition.
(WebCore::Editor::setComposition):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::setSelection):
(WebCore::FrameSelection::updateAndRevealSelection):
(WebCore::FrameSelection::setSelectedRange):
* editing/FrameSelection.h:
(WebCore::FrameSelection::defaultSetSelectionOptions):
Plumb state about whether or not the selection change was triggered by the user to FrameSelection::setSelection,
and if so, notify the editing client. A separate SetSelectionOptions flag is used here instead of
RevealSelection to avoid calling out to the client in places where we want to reveal the selection regardless of
whether or not the selection is user triggered.
* loader/EmptyClients.cpp:
* page/EditorClient.h:
Source/WebKit:
See per-method comments for more detail. WebPage::didChangeSelection now schedules EditorState updates to be sent
during the next layer tree transaction rather than sending them synchronously. To ensure that iOS and Mac continue
to behave correctly w.r.t. EditorState updates, we immediately dispatch EditorStates in the following cases:
- After the composition changes, is confirmed, or is canceled.
- After an edit command is executed.
- After ending user-triggered selection changes.
* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::hasEditorState const):
(WebKit::RemoteLayerTreeTransaction::editorState const):
(WebKit::RemoteLayerTreeTransaction::setEditorState):
Attaches an optional EditorState to the RemoteLayerTreeTransaction. This EditorState is computed and sent over
when setting up the transaction in WebPage, if something previously scheduled an EditorState update.
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode const):
(WebKit::RemoteLayerTreeTransaction::decode):
Add coder support for sending over a layer tree transaction's EditorState.
* UIProcess/API/Cocoa/WKViewPrivate.h:
* UIProcess/API/mac/WKView.mm:
(-[WKView _doAfterNextPresentationUpdate:]):
Add _doAfterNextPresentationUpdate to WKView (used in TestWebKitAPI -- refer to
WebKitAgnosticTest::waitForNextPresentationUpdate).
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
* UIProcess/DrawingAreaProxy.messages.in:
Add a new IPC messages, DispatchPresentationCallbacksAfterFlushingLayers, to invoke in-flight presentation
callbacks in the UI process following a layer flush in the web process.
* UIProcess/WebPageProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h:
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::~TiledCoreAnimationDrawingAreaProxy):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
Run all pending _doAfterNextPresentationUpdate callbacks.
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::didApplyStyle):
(WebKit::WebEditorClient::respondToChangedContents):
(WebKit::WebEditorClient::didEndUserTriggeredSelectionChanges):
(WebKit::WebEditorClient::didUpdateComposition):
Forward editor client calls to the WebPage.
(WebKit::WebEditorClient::didChangeSelectionAndUpdateLayout): Deleted.
* WebProcess/WebCoreSupport/WebEditorClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::editorState const):
(WebKit::WebPage::updateEditorStateAfterLayoutIfEditabilityChanged):
(WebKit::WebPage::willCommitLayerTree):
(WebKit::WebPage::didApplyStyle):
Allow style application to immediately trigger EditorState updates, if we're not currently ignoring selection
changes in the Editor.
(WebKit::WebPage::didChangeContents):
Allow applying top-level edit commands to immediately trigger EditorState updates, if we're not currently
ignoring selection changes in the Editor.
(WebKit::WebPage::didChangeSelection):
(WebKit::WebPage::didUpdateComposition):
(WebKit::WebPage::didEndUserTriggeredSelectionChanges):
(WebKit::WebPage::discardedComposition):
(WebKit::WebPage::canceledComposition):
When handling composition updates, always send an EditorState to the UI process. Unlike other cases, IME
requires immediate EditorState data, so we need to be explicit here in sending updates right away.
(WebKit::WebPage::sendEditorStateUpdate):
(WebKit::WebPage::sendPartialEditorStateAndSchedulePostLayoutUpdate):
(WebKit::WebPage::flushPendingEditorStateUpdate):
Helper methods to schedule an EditorState update to be sent upon the next layer tree update, or flush any
pending EditorState update that has been scheduled. The private, more aggressive variant of this is
sendEditorStateUpdate, which ignores whether or not there was already an EditorState update scheduled, and sends
one anyways (this still fulfills any EditorState update that was previously scheduled).
These helper methods are treated as no-ops when invoked while ignoring selection changes. This is to prevent
temporary selection state and editor commands during operations such as text indicator snapshotting from pushing
bogus information about transient editor states to the UI process.
(WebKit::WebPage::sendPostLayoutEditorStateIfNeeded): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::executeEditCommandWithCallback):
(WebKit::selectionIsInsideFixedPositionContainer):
(WebKit::WebPage::updateVisibleContentRects):
Fix a hack that was computing an EditorState to figure out whether the current selection starts or ends in a
fixed position container. Factors out relevant logic into a separate helper, and also schedules an EditorState
update instead of immediately computing it.
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::addTransactionCallbackID):
Add support for registering and dispatching presentation callbacks that hook into the layer flush lifecycle,
using the tiled CA drawing area. These are used by Mac LayoutTests and API tests that need to wait until the
next flush before checking for state that depends on EditorState updates in the UI process.
(WebKit::TiledCoreAnimationDrawingArea::flushLayers):
Tell the WebPage to flush any pending EditorState updates.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState const):
Source/WebKitLegacy/mac:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Source/WebKitLegacy/win:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Tools:
Tweaks API tests that involve editing to wait for a presentation update before checking against UI process-side
information sent via EditorState updates. This allows any EditorState update scheduled by the test to propagate
to the UI process.
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewCandidateTests.mm:
(-[CandidateTestWebView typeString:inputMessage:]):
(+[CandidateTestWebView setUpWithFrame:testPage:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewTextInput.mm:
* TestWebKitAPI/Tests/mac/AcceptsFirstMouse.mm:
(TestWebKitAPI::AcceptsFirstMouse::runTest):
* TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm:
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView waitForNextPresentationUpdate]):
Add a new helper method to spin until the next presentation update.
* TestWebKitAPI/mac/WebKitAgnosticTest.h:
* TestWebKitAPI/mac/WebKitAgnosticTest.mm:
(TestWebKitAPI::WebKitAgnosticTest::waitForNextPresentationUpdate):
LayoutTests:
Rebaseline and adjust LayoutTests.
* editing/caret/ios/absolute-caret-position-after-scroll-expected.txt:
* editing/caret/ios/absolute-caret-position-after-scroll.html:
* editing/caret/ios/fixed-caret-position-after-scroll-expected.txt:
* editing/caret/ios/fixed-caret-position-after-scroll.html:
* editing/secure-input/password-input-changed-type.html:
* editing/secure-input/password-input-focusing.html:
* editing/secure-input/removed-password-input.html:
* editing/secure-input/reset-state-on-navigation.html:
* editing/selection/character-granularity-rect.html:
Delay checking for secure input state and caret rects until after the next presentation update.
* editing/selection/ios/absolute-selection-after-scroll-expected.txt:
* editing/selection/ios/absolute-selection-after-scroll.html:
* editing/selection/ios/fixed-selection-after-scroll-expected.txt:
* editing/selection/ios/fixed-selection-after-scroll.html:
Refactor and simplify these tests. These tests are not run on the OpenSource bots, since they depend on long
press and tap gestures.
* platform/ios-wk2/editing/inserting/insert-div-024-expected.txt:
* platform/ios-wk2/editing/inserting/insert-div-026-expected.txt:
* platform/ios-wk2/editing/style/5084241-expected.txt:
Rebaselines these tests, removing an anonymous RenderBlock inserted as a result of inserting and removing a
dummy span in order to compute a RenderStyle in WebPage::editorState. This is because editorState is no longer
invoked immediately on page load; https://bugs.webkit.org/show_bug.cgi?id=175116 tracks preventing this render
tree thrashing altogether.
* platform/mac-wk2/TestExpectations:
* platform/mac-wk2/editing/style/unbold-in-bold-expected.txt:
* resources/ui-helper.js:
Introduce new UIHelper functions.
(window.UIHelper.ensurePresentationUpdate.return.new.Promise):
(window.UIHelper.ensurePresentationUpdate):
Returns a Promise, resolved after the next presentation update.
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise):
(window.UIHelper.activateAndWaitForInputSessionAt):
Returns a Promise, resolved after tapping at the given location and waiting for the keyboard to appear on iOS.
(window.UIHelper.getUICaretRect.return.new.Promise.):
(window.UIHelper.getUICaretRect.return.new.Promise):
(window.UIHelper.getUICaretRect):
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
Helpers to fetch selection and caret rect information in the UI process.
Canonical link: https://commits.webkit.org/192519@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221064 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-23 03:15:38 +00:00
|
|
|
static activateAndWaitForInputSessionAt(x, y)
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
[WK2] EditorState updates should be rolled into the layer update lifecycle when possible
https://bugs.webkit.org/show_bug.cgi?id=175370
<rdar://problem/33799806>
Reviewed by Ryosuke Niwa.
Source/WebCore:
Remove didChangeSelectionAndUpdateLayout -- EditorState updates that are scheduled due to missing post-layout
data will now be scheduled for the next presentation update. Additionally, add editor client hooks to notify the
WebKit layer when we've updated the current composition. See WebKit ChangeLog for more details. This patch
adjusts and rebaselines existing layout tests.
* editing/Editor.cpp:
(WebCore::SetCompositionScope::SetCompositionScope):
(WebCore::SetCompositionScope::~SetCompositionScope):
Introduce a helper RAII class to ensure that we ignore selection changes during the scope of
Editor::setComposition and call out to the client with WebEditorClient::didUpdateComposition afterwards. This
also maintains a UserTypingGestureIndicator over its lifetime, so we don't additionally need to create a
UserTypingGestureIndicator in Editor::setComposition.
(WebCore::Editor::setComposition):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::setSelection):
(WebCore::FrameSelection::updateAndRevealSelection):
(WebCore::FrameSelection::setSelectedRange):
* editing/FrameSelection.h:
(WebCore::FrameSelection::defaultSetSelectionOptions):
Plumb state about whether or not the selection change was triggered by the user to FrameSelection::setSelection,
and if so, notify the editing client. A separate SetSelectionOptions flag is used here instead of
RevealSelection to avoid calling out to the client in places where we want to reveal the selection regardless of
whether or not the selection is user triggered.
* loader/EmptyClients.cpp:
* page/EditorClient.h:
Source/WebKit:
See per-method comments for more detail. WebPage::didChangeSelection now schedules EditorState updates to be sent
during the next layer tree transaction rather than sending them synchronously. To ensure that iOS and Mac continue
to behave correctly w.r.t. EditorState updates, we immediately dispatch EditorStates in the following cases:
- After the composition changes, is confirmed, or is canceled.
- After an edit command is executed.
- After ending user-triggered selection changes.
* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::hasEditorState const):
(WebKit::RemoteLayerTreeTransaction::editorState const):
(WebKit::RemoteLayerTreeTransaction::setEditorState):
Attaches an optional EditorState to the RemoteLayerTreeTransaction. This EditorState is computed and sent over
when setting up the transaction in WebPage, if something previously scheduled an EditorState update.
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode const):
(WebKit::RemoteLayerTreeTransaction::decode):
Add coder support for sending over a layer tree transaction's EditorState.
* UIProcess/API/Cocoa/WKViewPrivate.h:
* UIProcess/API/mac/WKView.mm:
(-[WKView _doAfterNextPresentationUpdate:]):
Add _doAfterNextPresentationUpdate to WKView (used in TestWebKitAPI -- refer to
WebKitAgnosticTest::waitForNextPresentationUpdate).
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
* UIProcess/DrawingAreaProxy.messages.in:
Add a new IPC messages, DispatchPresentationCallbacksAfterFlushingLayers, to invoke in-flight presentation
callbacks in the UI process following a layer flush in the web process.
* UIProcess/WebPageProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h:
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::~TiledCoreAnimationDrawingAreaProxy):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
Run all pending _doAfterNextPresentationUpdate callbacks.
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::didApplyStyle):
(WebKit::WebEditorClient::respondToChangedContents):
(WebKit::WebEditorClient::didEndUserTriggeredSelectionChanges):
(WebKit::WebEditorClient::didUpdateComposition):
Forward editor client calls to the WebPage.
(WebKit::WebEditorClient::didChangeSelectionAndUpdateLayout): Deleted.
* WebProcess/WebCoreSupport/WebEditorClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::editorState const):
(WebKit::WebPage::updateEditorStateAfterLayoutIfEditabilityChanged):
(WebKit::WebPage::willCommitLayerTree):
(WebKit::WebPage::didApplyStyle):
Allow style application to immediately trigger EditorState updates, if we're not currently ignoring selection
changes in the Editor.
(WebKit::WebPage::didChangeContents):
Allow applying top-level edit commands to immediately trigger EditorState updates, if we're not currently
ignoring selection changes in the Editor.
(WebKit::WebPage::didChangeSelection):
(WebKit::WebPage::didUpdateComposition):
(WebKit::WebPage::didEndUserTriggeredSelectionChanges):
(WebKit::WebPage::discardedComposition):
(WebKit::WebPage::canceledComposition):
When handling composition updates, always send an EditorState to the UI process. Unlike other cases, IME
requires immediate EditorState data, so we need to be explicit here in sending updates right away.
(WebKit::WebPage::sendEditorStateUpdate):
(WebKit::WebPage::sendPartialEditorStateAndSchedulePostLayoutUpdate):
(WebKit::WebPage::flushPendingEditorStateUpdate):
Helper methods to schedule an EditorState update to be sent upon the next layer tree update, or flush any
pending EditorState update that has been scheduled. The private, more aggressive variant of this is
sendEditorStateUpdate, which ignores whether or not there was already an EditorState update scheduled, and sends
one anyways (this still fulfills any EditorState update that was previously scheduled).
These helper methods are treated as no-ops when invoked while ignoring selection changes. This is to prevent
temporary selection state and editor commands during operations such as text indicator snapshotting from pushing
bogus information about transient editor states to the UI process.
(WebKit::WebPage::sendPostLayoutEditorStateIfNeeded): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::executeEditCommandWithCallback):
(WebKit::selectionIsInsideFixedPositionContainer):
(WebKit::WebPage::updateVisibleContentRects):
Fix a hack that was computing an EditorState to figure out whether the current selection starts or ends in a
fixed position container. Factors out relevant logic into a separate helper, and also schedules an EditorState
update instead of immediately computing it.
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::addTransactionCallbackID):
Add support for registering and dispatching presentation callbacks that hook into the layer flush lifecycle,
using the tiled CA drawing area. These are used by Mac LayoutTests and API tests that need to wait until the
next flush before checking for state that depends on EditorState updates in the UI process.
(WebKit::TiledCoreAnimationDrawingArea::flushLayers):
Tell the WebPage to flush any pending EditorState updates.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState const):
Source/WebKitLegacy/mac:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Source/WebKitLegacy/win:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Tools:
Tweaks API tests that involve editing to wait for a presentation update before checking against UI process-side
information sent via EditorState updates. This allows any EditorState update scheduled by the test to propagate
to the UI process.
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewCandidateTests.mm:
(-[CandidateTestWebView typeString:inputMessage:]):
(+[CandidateTestWebView setUpWithFrame:testPage:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewTextInput.mm:
* TestWebKitAPI/Tests/mac/AcceptsFirstMouse.mm:
(TestWebKitAPI::AcceptsFirstMouse::runTest):
* TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm:
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView waitForNextPresentationUpdate]):
Add a new helper method to spin until the next presentation update.
* TestWebKitAPI/mac/WebKitAgnosticTest.h:
* TestWebKitAPI/mac/WebKitAgnosticTest.mm:
(TestWebKitAPI::WebKitAgnosticTest::waitForNextPresentationUpdate):
LayoutTests:
Rebaseline and adjust LayoutTests.
* editing/caret/ios/absolute-caret-position-after-scroll-expected.txt:
* editing/caret/ios/absolute-caret-position-after-scroll.html:
* editing/caret/ios/fixed-caret-position-after-scroll-expected.txt:
* editing/caret/ios/fixed-caret-position-after-scroll.html:
* editing/secure-input/password-input-changed-type.html:
* editing/secure-input/password-input-focusing.html:
* editing/secure-input/removed-password-input.html:
* editing/secure-input/reset-state-on-navigation.html:
* editing/selection/character-granularity-rect.html:
Delay checking for secure input state and caret rects until after the next presentation update.
* editing/selection/ios/absolute-selection-after-scroll-expected.txt:
* editing/selection/ios/absolute-selection-after-scroll.html:
* editing/selection/ios/fixed-selection-after-scroll-expected.txt:
* editing/selection/ios/fixed-selection-after-scroll.html:
Refactor and simplify these tests. These tests are not run on the OpenSource bots, since they depend on long
press and tap gestures.
* platform/ios-wk2/editing/inserting/insert-div-024-expected.txt:
* platform/ios-wk2/editing/inserting/insert-div-026-expected.txt:
* platform/ios-wk2/editing/style/5084241-expected.txt:
Rebaselines these tests, removing an anonymous RenderBlock inserted as a result of inserting and removing a
dummy span in order to compute a RenderStyle in WebPage::editorState. This is because editorState is no longer
invoked immediately on page load; https://bugs.webkit.org/show_bug.cgi?id=175116 tracks preventing this render
tree thrashing altogether.
* platform/mac-wk2/TestExpectations:
* platform/mac-wk2/editing/style/unbold-in-bold-expected.txt:
* resources/ui-helper.js:
Introduce new UIHelper functions.
(window.UIHelper.ensurePresentationUpdate.return.new.Promise):
(window.UIHelper.ensurePresentationUpdate):
Returns a Promise, resolved after the next presentation update.
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise):
(window.UIHelper.activateAndWaitForInputSessionAt):
Returns a Promise, resolved after tapping at the given location and waiting for the keyboard to appear on iOS.
(window.UIHelper.getUICaretRect.return.new.Promise.):
(window.UIHelper.getUICaretRect.return.new.Promise):
(window.UIHelper.getUICaretRect):
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
Helpers to fetch selection and caret rect information in the UI process.
Canonical link: https://commits.webkit.org/192519@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221064 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-23 03:15:38 +00:00
|
|
|
return this.activateAt(x, y);
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
2019-11-19 01:05:14 +00:00
|
|
|
function clearCallbacksAndScriptComplete() {
|
[iOS] Occasional crash under -[UIView _setViewDelegate:] when presenting date and time pickers
https://bugs.webkit.org/show_bug.cgi?id=214120
<rdar://problem/65246918>
Reviewed by Darin Adler.
Source/WebKit:
This crash happens when attempting to present a date picker (`<input type=date>`) immediately after dismissing
it. We encounter an Objective-C exception thrown by UIKit, due to the `WKDateTimeContextMenuViewController`'s
view (the `UIDatePicker`) being presented while it is still owned by the preview view controller. We often avoid
this crash because the `WKDateTimeContextMenuViewController` is usually only owned by `WKDateTimePicker`, so
when we set `_viewController` to a new instance of `WKDateTimeContextMenuViewController`, the old view
controller is destroyed, and thus no longer owns the `UIDatePicker` view.
However, it's possible for anything (e.g. animation blocks in UIKit) to cause the old view controller to live
past the creation of the new view controller. If this happens, when we go and call `-setView:` on the new view
controller with the date picker view, the date picker view may still be the view of the old controller, and we
end up crashing.
To fix this, explicitly unload the old view controller's view before attempting to create the new view
controller.
Test: fast/forms/ios/show-and-dismiss-date-input.html
* UIProcess/ios/forms/WKDateTimeInputControl.mm:
(-[WKDateTimePicker contextMenuInteraction:configurationForMenuAtLocation:]):
(-[WKDateTimePicker contextMenuInteraction:willDisplayMenuForConfiguration:animator:]):
(-[WKDateTimePicker contextMenuInteraction:willEndForConfiguration:animator:]):
Make it possible to test date and time picker presentation and dismissal by calling into the private testing-
only subclassing hooks on `WKWebView` when we finish presenting and dismissing the date picker context menu.
(-[WKDateTimePicker removeContextMenuInteraction]):
Tools:
Implement additional support for testing date and time pickers presented using context menus on iOS 14.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::isShowingContextMenu const):
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView _didShowContextMenu]):
(-[TestRunnerWKWebView _didDismissContextMenu]):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::setDidDismissContextMenuCallback):
Call the completion callback with `CallbackTypeDidDismissContextMenu`, rather than
`CallbackTypeDidEndFormControlInteraction`.
(WTR::UIScriptControllerIOS::isShowingContextMenu const):
Add a new script controller to ask whether we're currently presenting a context menu. This is useful in the case
where we want to wait until we're no longer showing a context menu, since we'll either immediately invoke script
completion, or stash a completion callback on `didDismissContextMenuCallback` to invoke script completion after
the context menu is finished dismissing.
LayoutTests:
Add a new layout test to verify that presenting a date picker twice does not result in a crash.
* fast/forms/ios/show-and-dismiss-date-input-expected.txt: Added.
* fast/forms/ios/show-and-dismiss-date-input.html: Added.
* resources/ui-helper.js:
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
Teach this helper method to wait for context menus as well (for the case of date and time pickers on iOS).
(window.UIHelper.waitForInputSessionToDismiss.return.new.Promise.):
(window.UIHelper.waitForInputSessionToDismiss.return.new.Promise):
(window.UIHelper.waitForInputSessionToDismiss):
Likewise, teach this to wait for context menu dismissal.
(window.UIHelper.waitForContextMenuToHide.return.new.Promise):
(window.UIHelper.waitForContextMenuToHide):
Add a new helper to wait for context menus to hide.
Canonical link: https://commits.webkit.org/226942@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@264170 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-07-09 15:15:29 +00:00
|
|
|
uiController.didShowContextMenuCallback = null;
|
2019-11-19 01:05:14 +00:00
|
|
|
uiController.didShowKeyboardCallback = null;
|
|
|
|
uiController.willPresentPopoverCallback = null;
|
2019-01-17 19:15:57 +00:00
|
|
|
uiController.uiScriptComplete();
|
2019-11-19 01:05:14 +00:00
|
|
|
}
|
[iOS] Occasional crash under -[UIView _setViewDelegate:] when presenting date and time pickers
https://bugs.webkit.org/show_bug.cgi?id=214120
<rdar://problem/65246918>
Reviewed by Darin Adler.
Source/WebKit:
This crash happens when attempting to present a date picker (`<input type=date>`) immediately after dismissing
it. We encounter an Objective-C exception thrown by UIKit, due to the `WKDateTimeContextMenuViewController`'s
view (the `UIDatePicker`) being presented while it is still owned by the preview view controller. We often avoid
this crash because the `WKDateTimeContextMenuViewController` is usually only owned by `WKDateTimePicker`, so
when we set `_viewController` to a new instance of `WKDateTimeContextMenuViewController`, the old view
controller is destroyed, and thus no longer owns the `UIDatePicker` view.
However, it's possible for anything (e.g. animation blocks in UIKit) to cause the old view controller to live
past the creation of the new view controller. If this happens, when we go and call `-setView:` on the new view
controller with the date picker view, the date picker view may still be the view of the old controller, and we
end up crashing.
To fix this, explicitly unload the old view controller's view before attempting to create the new view
controller.
Test: fast/forms/ios/show-and-dismiss-date-input.html
* UIProcess/ios/forms/WKDateTimeInputControl.mm:
(-[WKDateTimePicker contextMenuInteraction:configurationForMenuAtLocation:]):
(-[WKDateTimePicker contextMenuInteraction:willDisplayMenuForConfiguration:animator:]):
(-[WKDateTimePicker contextMenuInteraction:willEndForConfiguration:animator:]):
Make it possible to test date and time picker presentation and dismissal by calling into the private testing-
only subclassing hooks on `WKWebView` when we finish presenting and dismissing the date picker context menu.
(-[WKDateTimePicker removeContextMenuInteraction]):
Tools:
Implement additional support for testing date and time pickers presented using context menus on iOS 14.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::isShowingContextMenu const):
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView _didShowContextMenu]):
(-[TestRunnerWKWebView _didDismissContextMenu]):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::setDidDismissContextMenuCallback):
Call the completion callback with `CallbackTypeDidDismissContextMenu`, rather than
`CallbackTypeDidEndFormControlInteraction`.
(WTR::UIScriptControllerIOS::isShowingContextMenu const):
Add a new script controller to ask whether we're currently presenting a context menu. This is useful in the case
where we want to wait until we're no longer showing a context menu, since we'll either immediately invoke script
completion, or stash a completion callback on `didDismissContextMenuCallback` to invoke script completion after
the context menu is finished dismissing.
LayoutTests:
Add a new layout test to verify that presenting a date picker twice does not result in a crash.
* fast/forms/ios/show-and-dismiss-date-input-expected.txt: Added.
* fast/forms/ios/show-and-dismiss-date-input.html: Added.
* resources/ui-helper.js:
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
Teach this helper method to wait for context menus as well (for the case of date and time pickers on iOS).
(window.UIHelper.waitForInputSessionToDismiss.return.new.Promise.):
(window.UIHelper.waitForInputSessionToDismiss.return.new.Promise):
(window.UIHelper.waitForInputSessionToDismiss):
Likewise, teach this to wait for context menu dismissal.
(window.UIHelper.waitForContextMenuToHide.return.new.Promise):
(window.UIHelper.waitForContextMenuToHide):
Add a new helper to wait for context menus to hide.
Canonical link: https://commits.webkit.org/226942@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@264170 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-07-09 15:15:29 +00:00
|
|
|
uiController.didShowContextMenuCallback = clearCallbacksAndScriptComplete;
|
2019-11-19 01:05:14 +00:00
|
|
|
uiController.didShowKeyboardCallback = clearCallbacksAndScriptComplete;
|
|
|
|
uiController.willPresentPopoverCallback = clearCallbacksAndScriptComplete;
|
[WK2] EditorState updates should be rolled into the layer update lifecycle when possible
https://bugs.webkit.org/show_bug.cgi?id=175370
<rdar://problem/33799806>
Reviewed by Ryosuke Niwa.
Source/WebCore:
Remove didChangeSelectionAndUpdateLayout -- EditorState updates that are scheduled due to missing post-layout
data will now be scheduled for the next presentation update. Additionally, add editor client hooks to notify the
WebKit layer when we've updated the current composition. See WebKit ChangeLog for more details. This patch
adjusts and rebaselines existing layout tests.
* editing/Editor.cpp:
(WebCore::SetCompositionScope::SetCompositionScope):
(WebCore::SetCompositionScope::~SetCompositionScope):
Introduce a helper RAII class to ensure that we ignore selection changes during the scope of
Editor::setComposition and call out to the client with WebEditorClient::didUpdateComposition afterwards. This
also maintains a UserTypingGestureIndicator over its lifetime, so we don't additionally need to create a
UserTypingGestureIndicator in Editor::setComposition.
(WebCore::Editor::setComposition):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::setSelection):
(WebCore::FrameSelection::updateAndRevealSelection):
(WebCore::FrameSelection::setSelectedRange):
* editing/FrameSelection.h:
(WebCore::FrameSelection::defaultSetSelectionOptions):
Plumb state about whether or not the selection change was triggered by the user to FrameSelection::setSelection,
and if so, notify the editing client. A separate SetSelectionOptions flag is used here instead of
RevealSelection to avoid calling out to the client in places where we want to reveal the selection regardless of
whether or not the selection is user triggered.
* loader/EmptyClients.cpp:
* page/EditorClient.h:
Source/WebKit:
See per-method comments for more detail. WebPage::didChangeSelection now schedules EditorState updates to be sent
during the next layer tree transaction rather than sending them synchronously. To ensure that iOS and Mac continue
to behave correctly w.r.t. EditorState updates, we immediately dispatch EditorStates in the following cases:
- After the composition changes, is confirmed, or is canceled.
- After an edit command is executed.
- After ending user-triggered selection changes.
* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::hasEditorState const):
(WebKit::RemoteLayerTreeTransaction::editorState const):
(WebKit::RemoteLayerTreeTransaction::setEditorState):
Attaches an optional EditorState to the RemoteLayerTreeTransaction. This EditorState is computed and sent over
when setting up the transaction in WebPage, if something previously scheduled an EditorState update.
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode const):
(WebKit::RemoteLayerTreeTransaction::decode):
Add coder support for sending over a layer tree transaction's EditorState.
* UIProcess/API/Cocoa/WKViewPrivate.h:
* UIProcess/API/mac/WKView.mm:
(-[WKView _doAfterNextPresentationUpdate:]):
Add _doAfterNextPresentationUpdate to WKView (used in TestWebKitAPI -- refer to
WebKitAgnosticTest::waitForNextPresentationUpdate).
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
* UIProcess/DrawingAreaProxy.messages.in:
Add a new IPC messages, DispatchPresentationCallbacksAfterFlushingLayers, to invoke in-flight presentation
callbacks in the UI process following a layer flush in the web process.
* UIProcess/WebPageProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h:
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::~TiledCoreAnimationDrawingAreaProxy):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
Run all pending _doAfterNextPresentationUpdate callbacks.
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::didApplyStyle):
(WebKit::WebEditorClient::respondToChangedContents):
(WebKit::WebEditorClient::didEndUserTriggeredSelectionChanges):
(WebKit::WebEditorClient::didUpdateComposition):
Forward editor client calls to the WebPage.
(WebKit::WebEditorClient::didChangeSelectionAndUpdateLayout): Deleted.
* WebProcess/WebCoreSupport/WebEditorClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::editorState const):
(WebKit::WebPage::updateEditorStateAfterLayoutIfEditabilityChanged):
(WebKit::WebPage::willCommitLayerTree):
(WebKit::WebPage::didApplyStyle):
Allow style application to immediately trigger EditorState updates, if we're not currently ignoring selection
changes in the Editor.
(WebKit::WebPage::didChangeContents):
Allow applying top-level edit commands to immediately trigger EditorState updates, if we're not currently
ignoring selection changes in the Editor.
(WebKit::WebPage::didChangeSelection):
(WebKit::WebPage::didUpdateComposition):
(WebKit::WebPage::didEndUserTriggeredSelectionChanges):
(WebKit::WebPage::discardedComposition):
(WebKit::WebPage::canceledComposition):
When handling composition updates, always send an EditorState to the UI process. Unlike other cases, IME
requires immediate EditorState data, so we need to be explicit here in sending updates right away.
(WebKit::WebPage::sendEditorStateUpdate):
(WebKit::WebPage::sendPartialEditorStateAndSchedulePostLayoutUpdate):
(WebKit::WebPage::flushPendingEditorStateUpdate):
Helper methods to schedule an EditorState update to be sent upon the next layer tree update, or flush any
pending EditorState update that has been scheduled. The private, more aggressive variant of this is
sendEditorStateUpdate, which ignores whether or not there was already an EditorState update scheduled, and sends
one anyways (this still fulfills any EditorState update that was previously scheduled).
These helper methods are treated as no-ops when invoked while ignoring selection changes. This is to prevent
temporary selection state and editor commands during operations such as text indicator snapshotting from pushing
bogus information about transient editor states to the UI process.
(WebKit::WebPage::sendPostLayoutEditorStateIfNeeded): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::executeEditCommandWithCallback):
(WebKit::selectionIsInsideFixedPositionContainer):
(WebKit::WebPage::updateVisibleContentRects):
Fix a hack that was computing an EditorState to figure out whether the current selection starts or ends in a
fixed position container. Factors out relevant logic into a separate helper, and also schedules an EditorState
update instead of immediately computing it.
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::addTransactionCallbackID):
Add support for registering and dispatching presentation callbacks that hook into the layer flush lifecycle,
using the tiled CA drawing area. These are used by Mac LayoutTests and API tests that need to wait until the
next flush before checking for state that depends on EditorState updates in the UI process.
(WebKit::TiledCoreAnimationDrawingArea::flushLayers):
Tell the WebPage to flush any pending EditorState updates.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState const):
Source/WebKitLegacy/mac:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Source/WebKitLegacy/win:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Tools:
Tweaks API tests that involve editing to wait for a presentation update before checking against UI process-side
information sent via EditorState updates. This allows any EditorState update scheduled by the test to propagate
to the UI process.
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewCandidateTests.mm:
(-[CandidateTestWebView typeString:inputMessage:]):
(+[CandidateTestWebView setUpWithFrame:testPage:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewTextInput.mm:
* TestWebKitAPI/Tests/mac/AcceptsFirstMouse.mm:
(TestWebKitAPI::AcceptsFirstMouse::runTest):
* TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm:
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView waitForNextPresentationUpdate]):
Add a new helper method to spin until the next presentation update.
* TestWebKitAPI/mac/WebKitAgnosticTest.h:
* TestWebKitAPI/mac/WebKitAgnosticTest.mm:
(TestWebKitAPI::WebKitAgnosticTest::waitForNextPresentationUpdate):
LayoutTests:
Rebaseline and adjust LayoutTests.
* editing/caret/ios/absolute-caret-position-after-scroll-expected.txt:
* editing/caret/ios/absolute-caret-position-after-scroll.html:
* editing/caret/ios/fixed-caret-position-after-scroll-expected.txt:
* editing/caret/ios/fixed-caret-position-after-scroll.html:
* editing/secure-input/password-input-changed-type.html:
* editing/secure-input/password-input-focusing.html:
* editing/secure-input/removed-password-input.html:
* editing/secure-input/reset-state-on-navigation.html:
* editing/selection/character-granularity-rect.html:
Delay checking for secure input state and caret rects until after the next presentation update.
* editing/selection/ios/absolute-selection-after-scroll-expected.txt:
* editing/selection/ios/absolute-selection-after-scroll.html:
* editing/selection/ios/fixed-selection-after-scroll-expected.txt:
* editing/selection/ios/fixed-selection-after-scroll.html:
Refactor and simplify these tests. These tests are not run on the OpenSource bots, since they depend on long
press and tap gestures.
* platform/ios-wk2/editing/inserting/insert-div-024-expected.txt:
* platform/ios-wk2/editing/inserting/insert-div-026-expected.txt:
* platform/ios-wk2/editing/style/5084241-expected.txt:
Rebaselines these tests, removing an anonymous RenderBlock inserted as a result of inserting and removing a
dummy span in order to compute a RenderStyle in WebPage::editorState. This is because editorState is no longer
invoked immediately on page load; https://bugs.webkit.org/show_bug.cgi?id=175116 tracks preventing this render
tree thrashing altogether.
* platform/mac-wk2/TestExpectations:
* platform/mac-wk2/editing/style/unbold-in-bold-expected.txt:
* resources/ui-helper.js:
Introduce new UIHelper functions.
(window.UIHelper.ensurePresentationUpdate.return.new.Promise):
(window.UIHelper.ensurePresentationUpdate):
Returns a Promise, resolved after the next presentation update.
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise):
(window.UIHelper.activateAndWaitForInputSessionAt):
Returns a Promise, resolved after tapping at the given location and waiting for the keyboard to appear on iOS.
(window.UIHelper.getUICaretRect.return.new.Promise.):
(window.UIHelper.getUICaretRect.return.new.Promise):
(window.UIHelper.getUICaretRect):
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
Helpers to fetch selection and caret rect information in the UI process.
Canonical link: https://commits.webkit.org/192519@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221064 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-23 03:15:38 +00:00
|
|
|
uiController.singleTapAtPoint(${x}, ${y}, function() { });
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-11-19 01:05:14 +00:00
|
|
|
static waitForInputSessionToDismiss()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
REGRESSION (r259840): Pressing Esc or ⌘+"." does not dismiss time picker on iOS
https://bugs.webkit.org/show_bug.cgi?id=214122
<rdar://problem/64940487>
Reviewed by Tim Horton.
Source/WebKit:
Prior to r259840, when presenting context menus for certain input types (i.e. "time" and "datetime-local") on
iOS, UIKit would tell the presented view controller's view (a `UIDatePicker` in this case) to become first
responder. As a result, `WKContentView` would resign first responder, which (by default) blurs the focused
element and dismisses the context menu. The result is thats time pickers would immediately dismiss upon
presentation.
To mitigate this, r259840 adopted the existing active focus retaining mechanism to temporarily decouple
WKContentView's first responder status from the currently focused form element. However, this also causes
`-endEditingAndUpdateFocusAppearanceWithReason:` to bail, due to `self.webView._retainingActiveFocusedState`
returning `YES`. This means that codepaths meant to immediately dismiss UI for the focused element (for example,
when pressing Escape on a hardware keyboard on iOS) will not be able to dismiss UI.
To fix this, push the flag that keeps track of whether we're relinquishing first responder to the focused
element down into `WKContentView`, and have `WKContentView` automatically stop relinquishing first responder to
the focused element in `-[WKContentView accessoryDone]`.
Fixes an existing test: fast/forms/ios/dismiss-picker-using-keyboard.html
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView accessoryDone]):
Stop relinquishing focus to the focused element, so that form elements that require first responder can be
dismissed when triggering `-accessoryDone` (e.g. when pressing the Esc key on a hardware keyboard).
(-[WKContentView startRelinquishingFirstResponderToFocusedElement]):
(-[WKContentView stopRelinquishingFirstResponderToFocusedElement]):
Renamed from `-preserveFocus` and `-releaseFocus`, respectively. Also, made these methods idempotent using a new
`BOOL` flag, `_isRelinquishingFirstResponderToFocusedElement`.
(-[WKContentView preserveFocus]): Deleted.
(-[WKContentView releaseFocus]): Deleted.
* UIProcess/ios/forms/WKDateTimeInputControl.mm:
(-[WKDateTimePicker controlBeginEditing]):
(-[WKDateTimePicker controlEndEditing]):
Use the renamed WKContentView methods, and also remove the `_preservingFocus` flag.
* UIProcess/ios/forms/WKFormPopover.mm:
(-[WKRotatingPopover presentPopoverAnimated:]):
(-[WKRotatingPopover dismissPopoverAnimated:]):
Use the renamed WKContentView methods.
LayoutTests:
* fast/forms/ios/dismiss-picker-using-keyboard.html:
* fast/forms/ios/force-gregorian-calendar-for-credit-card-expiry.html:
* fast/forms/ios/time-picker-value-change-expected.txt:
* fast/forms/ios/time-picker-value-change.html:
Adjust a few layout tests to be compatible with date and time inputs.
* resources/ui-helper.js:
(window.UIHelper.waitForInputSessionToDismiss.return.new.Promise):
(window.UIHelper.waitForInputSessionToDismiss):
Canonical link: https://commits.webkit.org/226959@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@264187 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-07-09 19:46:09 +00:00
|
|
|
if (!uiController.isShowingKeyboard && !uiController.isShowingContextMenu && !uiController.isShowingPopover) {
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-11-19 01:05:14 +00:00
|
|
|
function clearCallbacksAndScriptComplete() {
|
|
|
|
uiController.didHideKeyboardCallback = null;
|
|
|
|
uiController.didDismissPopoverCallback = null;
|
2020-08-03 20:29:17 +00:00
|
|
|
uiController.didDismissContextMenuCallback = null;
|
2019-11-19 01:05:14 +00:00
|
|
|
uiController.uiScriptComplete();
|
|
|
|
}
|
REGRESSION (r259840): Pressing Esc or ⌘+"." does not dismiss time picker on iOS
https://bugs.webkit.org/show_bug.cgi?id=214122
<rdar://problem/64940487>
Reviewed by Tim Horton.
Source/WebKit:
Prior to r259840, when presenting context menus for certain input types (i.e. "time" and "datetime-local") on
iOS, UIKit would tell the presented view controller's view (a `UIDatePicker` in this case) to become first
responder. As a result, `WKContentView` would resign first responder, which (by default) blurs the focused
element and dismisses the context menu. The result is thats time pickers would immediately dismiss upon
presentation.
To mitigate this, r259840 adopted the existing active focus retaining mechanism to temporarily decouple
WKContentView's first responder status from the currently focused form element. However, this also causes
`-endEditingAndUpdateFocusAppearanceWithReason:` to bail, due to `self.webView._retainingActiveFocusedState`
returning `YES`. This means that codepaths meant to immediately dismiss UI for the focused element (for example,
when pressing Escape on a hardware keyboard on iOS) will not be able to dismiss UI.
To fix this, push the flag that keeps track of whether we're relinquishing first responder to the focused
element down into `WKContentView`, and have `WKContentView` automatically stop relinquishing first responder to
the focused element in `-[WKContentView accessoryDone]`.
Fixes an existing test: fast/forms/ios/dismiss-picker-using-keyboard.html
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView accessoryDone]):
Stop relinquishing focus to the focused element, so that form elements that require first responder can be
dismissed when triggering `-accessoryDone` (e.g. when pressing the Esc key on a hardware keyboard).
(-[WKContentView startRelinquishingFirstResponderToFocusedElement]):
(-[WKContentView stopRelinquishingFirstResponderToFocusedElement]):
Renamed from `-preserveFocus` and `-releaseFocus`, respectively. Also, made these methods idempotent using a new
`BOOL` flag, `_isRelinquishingFirstResponderToFocusedElement`.
(-[WKContentView preserveFocus]): Deleted.
(-[WKContentView releaseFocus]): Deleted.
* UIProcess/ios/forms/WKDateTimeInputControl.mm:
(-[WKDateTimePicker controlBeginEditing]):
(-[WKDateTimePicker controlEndEditing]):
Use the renamed WKContentView methods, and also remove the `_preservingFocus` flag.
* UIProcess/ios/forms/WKFormPopover.mm:
(-[WKRotatingPopover presentPopoverAnimated:]):
(-[WKRotatingPopover dismissPopoverAnimated:]):
Use the renamed WKContentView methods.
LayoutTests:
* fast/forms/ios/dismiss-picker-using-keyboard.html:
* fast/forms/ios/force-gregorian-calendar-for-credit-card-expiry.html:
* fast/forms/ios/time-picker-value-change-expected.txt:
* fast/forms/ios/time-picker-value-change.html:
Adjust a few layout tests to be compatible with date and time inputs.
* resources/ui-helper.js:
(window.UIHelper.waitForInputSessionToDismiss.return.new.Promise):
(window.UIHelper.waitForInputSessionToDismiss):
Canonical link: https://commits.webkit.org/226959@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@264187 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-07-09 19:46:09 +00:00
|
|
|
|
2019-11-19 01:05:14 +00:00
|
|
|
uiController.didHideKeyboardCallback = clearCallbacksAndScriptComplete;
|
|
|
|
uiController.didDismissPopoverCallback = clearCallbacksAndScriptComplete;
|
2020-08-03 20:29:17 +00:00
|
|
|
uiController.didDismissContextMenuCallback = clearCallbacksAndScriptComplete;
|
2019-11-19 01:05:14 +00:00
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
Native text selection UI is incorrectly suppressed in Microsoft Visio
https://bugs.webkit.org/show_bug.cgi?id=195178
<rdar://problem/48519394>
Reviewed by Darin Adler.
Source/WebCore:
Currently, our heuristics for detecting hidden editable areas attempt to search for empty parent renderers with
"overflow: hidden". It does this by ascending the layer tree in search of renderers that have an empty content
size, and whose renderers' styles indicate that they have overflow: hidden in the X or Y directions. This fails
in the case where a child renderer is positioned out of flow, relative to one of its parent layers, since the
child will be visible, but we'll incorrectly believe that it is hidden. This leads to selection UI unexpectedly
disappearing in the online version of Microsoft Visio.
To fix this, we check whether the enclosing layer around the editable element has an empty clip rect; if the
element is inside of a subframe, we additionally walk up to each enclosing frame's layer and check if that
frame's layer has an empty clip rect.
Test: editing/selection/ios/do-not-hide-selection-in-visible-container.html
* rendering/RenderObject.cpp:
(WebCore::RenderObject::isTransparentOrFullyClippedRespectingParentFrames const):
LayoutTests:
Add a new layout test that focuses several different text fields and checks whether or not editing UI is shown:
1. A text field inside an overflow: hidden container, all within an absolutely positioned iframe, such that the
text field is not visible. The caret should be hidden.
2. A text field inside an absolutely positioned iframe, inside an overflow: hidden container, such that the
text field is visible. The caret should be visible.
3. A text field inside a relatively positioned iframe in an overflow: hidden container, such that the text field
is not visible. The caret should be hidden.
4. A text field that is position: fixed inside an overflow: hidden container, such that the text field is
visible. The caret should be visible.
* editing/selection/ios/do-not-hide-selection-in-visible-container-expected.txt: Added.
* editing/selection/ios/do-not-hide-selection-in-visible-container.html: Added.
* editing/selection/ios/hide-selection-in-empty-overflow-hidden-container.html:
* resources/ui-helper.js:
(window.UIHelper.activateElementAndWaitForInputSession):
Add a convenience function in UIHelper that taps a given element and waits for the keyboard to show.
Canonical link: https://commits.webkit.org/209653@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242401 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-03-05 00:31:31 +00:00
|
|
|
static activateElementAndWaitForInputSession(element)
|
|
|
|
{
|
|
|
|
const x = element.offsetLeft + element.offsetWidth / 2;
|
|
|
|
const y = element.offsetTop + element.offsetHeight / 2;
|
|
|
|
return this.activateAndWaitForInputSessionAt(x, y);
|
|
|
|
}
|
|
|
|
|
2018-08-28 16:34:25 +00:00
|
|
|
static activateFormControl(element)
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
2018-08-28 16:34:25 +00:00
|
|
|
return this.activateElement(element);
|
|
|
|
|
|
|
|
const x = element.offsetLeft + element.offsetWidth / 2;
|
|
|
|
const y = element.offsetTop + element.offsetHeight / 2;
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
uiController.didStartFormControlInteractionCallback = function() {
|
2019-01-17 19:15:57 +00:00
|
|
|
uiController.uiScriptComplete();
|
2018-08-28 16:34:25 +00:00
|
|
|
};
|
|
|
|
uiController.singleTapAtPoint(${x}, ${y}, function() { });
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-06-18 21:50:20 +00:00
|
|
|
static dismissFormAccessoryView()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
uiController.dismissFormAccessoryView();
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-02-11 19:30:05 +00:00
|
|
|
static isShowingKeyboard()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript("uiController.isShowingKeyboard", result => resolve(result === "true"));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[iOS] Prevent presentation of input peripherals when focusing form controls with a validation message
https://bugs.webkit.org/show_bug.cgi?id=218004
<rdar://problem/70507678>
Reviewed by Wenson Hsieh.
Source/WebCore:
Added isFocusingWithValidationMessage() to HTMLFormControlElement so
that the state can be encoded in FocusedElementInformation and sent to
the UIProcess.
See WebKit Changelog for more information.
Test: fast/forms/ios/input-peripherals-with-validation-message.html
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::isFocusingWithValidationMessage const):
(WebCore::HTMLFormControlElement::focusAndShowValidationMessage):
* html/HTMLFormControlElement.h:
Source/WebKit:
Interactive form validation can result in the presentation of a
validation message bubble near the first form control that has invalid
data. Prior to displaying the message, the invalid control is focused.
On iOS, this also has the effect of also presenting a virtual keyboard
or another custom input peripheral, such as a context menu for date
inputs.
Attempting to present both the validation message and custom input
peripheral can leave the view in an inconsistent state. For example,
<select> popovers have a strange flashing behavior when presented
alongside a validation message, and context menus can fail to present
entirely.
In order to address these issues, we should never attempt to present
both a validation message and an input peripheral. Instead, we can
prevent the presentation of input peripherals when the focused control
is presenting a validation message. This behavior matches macOS. Note
that we still present the keyboard for controls that have a keyboard
view, since the keyboard area does overlap the area where a validation
message is presented.
* Shared/FocusedElementInformation.cpp:
(WebKit::FocusedElementInformation::encode const):
(WebKit::FocusedElementInformation::decode):
* Shared/FocusedElementInformation.h:
Added isFocusingWithValidationMessage to the struct, so that the UIProcess
knows that the element gained focus due to the presentation of a
validation message.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:]):
Prevent an input view from being shown if the control does not present
a keyboard and was focused with a validation message.
(-[WKContentView _elementDidBlur]):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getFocusedElementInformation):
LayoutTests:
Added a test which verifies that focusing on a date input as a result
of presenting a validation message, successfully presents the message,
and does not present a context menu. The test also ensures that controls
that present a keyboard, such as text inputs, present both the message
and the keyboard.
* fast/forms/ios/input-peripherals-with-validation-message-expected.txt: Added.
* fast/forms/ios/input-peripherals-with-validation-message.html: Added.
* resources/ui-helper.js:
(window.UIHelper.isShowingPopover):
Canonical link: https://commits.webkit.org/230794@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@268866 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-10-22 15:55:54 +00:00
|
|
|
static isShowingPopover()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript("uiController.isShowingPopover", result => resolve(result === "true"));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
Touching media controls sometimes shows software keyboard
https://bugs.webkit.org/show_bug.cgi?id=199490
<rdar://problem/52076270>
Reviewed by Eric Carlson.
Source/WebKit:
In r243044, we added a compatibility hack for Google Slides (and other G-suite properties) to allow the on-
screen keyboard to show up after a prevented touch event in the case where an element was already focused, even
if the touch event handler doesn't explicitly refocus the element. However, this means that if a regular text
field (or other form control) has been programmatically focused, then interacting with any other element that
prevents default on touchstart will cause us to show the keyboard for that focused element.
To mitigate this, only fall down this refocusing codepath in the case where the focused element is a hidden
editable element (in the style of many Google productivity web apps). For non-hidden editable elements that are
already focused, this refocusing logic is not necessary, since the user should be able to interact with the
control to show the keyboard anyways; for hidden editable areas, this compatibility hack is actually needed,
since there is typically no other way for a user to focus these elements and show an on-screen keyboard.
Tests: fast/events/touch/ios/show-keyboard-after-preventing-touchstart.html
fast/events/touch/ios/do-not-show-keyboard-after-preventing-touchstart.html
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::dispatchTouchEvent):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::isTransparentOrFullyClipped const):
Renamed from enclosingLayerIsTransparentOrFullyClipped, and pulled out into a private helper method.
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::requestEvasionRectsAboveSelection):
(WebKit::WebPage::getFocusedElementInformation):
(WebKit::enclosingLayerIsTransparentOrFullyClipped): Deleted.
Tools:
Adds plumbing for a new testing hook to check whether or not there is an active input session. See other
ChangeLog entries for more detail.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::hasInputSession const):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::hasInputSession const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::hasInputSession const):
LayoutTests:
Adds a new layout test to verify that the keyboard only appears after a handled touch event if the focused
element is inside a hidden editable area; otherwise, the keyboard should not be present.
* fast/events/touch/ios/do-not-show-keyboard-after-preventing-touchstart-expected.txt: Added.
* fast/events/touch/ios/do-not-show-keyboard-after-preventing-touchstart.html: Added.
This test passes as long as we didn't begin showing the keyboard after tapping.
* fast/events/touch/ios/show-keyboard-after-preventing-touchstart-expected.txt:
* fast/events/touch/ios/show-keyboard-after-preventing-touchstart.html:
Adjust this existing test to make the focused textarea hidden.
* resources/ui-helper.js:
(window.UIHelper.hasInputSession):
Add a new testing hook to check whether there is an active input session.
Canonical link: https://commits.webkit.org/213421@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@247158 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-07-05 16:22:42 +00:00
|
|
|
static hasInputSession()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript("uiController.hasInputSession", result => resolve(result === "true"));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-02-11 19:30:05 +00:00
|
|
|
static isPresentingModally()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript("uiController.isPresentingModally", result => resolve(result === "true"));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static deactivateFormControl(element)
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily()) {
|
2019-02-11 19:30:05 +00:00
|
|
|
element.blur();
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise(async resolve => {
|
|
|
|
element.blur();
|
|
|
|
while (await this.isPresentingModally())
|
|
|
|
continue;
|
|
|
|
while (await this.isShowingKeyboard())
|
|
|
|
continue;
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-04-09 21:45:03 +00:00
|
|
|
static waitForPopoverToPresent()
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
2019-04-09 21:45:03 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
if (uiController.isShowingPopover)
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
else
|
|
|
|
uiController.willPresentPopoverCallback = () => uiController.uiScriptComplete();
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static waitForPopoverToDismiss()
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
2019-04-09 21:45:03 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
if (uiController.isShowingPopover)
|
|
|
|
uiController.didDismissPopoverCallback = () => uiController.uiScriptComplete();
|
|
|
|
else
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-02-03 20:27:31 +00:00
|
|
|
static waitForContextMenuToShow()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
if (!uiController.isShowingContextMenu)
|
|
|
|
uiController.didShowContextMenuCallback = () => uiController.uiScriptComplete();
|
|
|
|
else
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[iOS] Occasional crash under -[UIView _setViewDelegate:] when presenting date and time pickers
https://bugs.webkit.org/show_bug.cgi?id=214120
<rdar://problem/65246918>
Reviewed by Darin Adler.
Source/WebKit:
This crash happens when attempting to present a date picker (`<input type=date>`) immediately after dismissing
it. We encounter an Objective-C exception thrown by UIKit, due to the `WKDateTimeContextMenuViewController`'s
view (the `UIDatePicker`) being presented while it is still owned by the preview view controller. We often avoid
this crash because the `WKDateTimeContextMenuViewController` is usually only owned by `WKDateTimePicker`, so
when we set `_viewController` to a new instance of `WKDateTimeContextMenuViewController`, the old view
controller is destroyed, and thus no longer owns the `UIDatePicker` view.
However, it's possible for anything (e.g. animation blocks in UIKit) to cause the old view controller to live
past the creation of the new view controller. If this happens, when we go and call `-setView:` on the new view
controller with the date picker view, the date picker view may still be the view of the old controller, and we
end up crashing.
To fix this, explicitly unload the old view controller's view before attempting to create the new view
controller.
Test: fast/forms/ios/show-and-dismiss-date-input.html
* UIProcess/ios/forms/WKDateTimeInputControl.mm:
(-[WKDateTimePicker contextMenuInteraction:configurationForMenuAtLocation:]):
(-[WKDateTimePicker contextMenuInteraction:willDisplayMenuForConfiguration:animator:]):
(-[WKDateTimePicker contextMenuInteraction:willEndForConfiguration:animator:]):
Make it possible to test date and time picker presentation and dismissal by calling into the private testing-
only subclassing hooks on `WKWebView` when we finish presenting and dismissing the date picker context menu.
(-[WKDateTimePicker removeContextMenuInteraction]):
Tools:
Implement additional support for testing date and time pickers presented using context menus on iOS 14.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::isShowingContextMenu const):
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView _didShowContextMenu]):
(-[TestRunnerWKWebView _didDismissContextMenu]):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::setDidDismissContextMenuCallback):
Call the completion callback with `CallbackTypeDidDismissContextMenu`, rather than
`CallbackTypeDidEndFormControlInteraction`.
(WTR::UIScriptControllerIOS::isShowingContextMenu const):
Add a new script controller to ask whether we're currently presenting a context menu. This is useful in the case
where we want to wait until we're no longer showing a context menu, since we'll either immediately invoke script
completion, or stash a completion callback on `didDismissContextMenuCallback` to invoke script completion after
the context menu is finished dismissing.
LayoutTests:
Add a new layout test to verify that presenting a date picker twice does not result in a crash.
* fast/forms/ios/show-and-dismiss-date-input-expected.txt: Added.
* fast/forms/ios/show-and-dismiss-date-input.html: Added.
* resources/ui-helper.js:
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
Teach this helper method to wait for context menus as well (for the case of date and time pickers on iOS).
(window.UIHelper.waitForInputSessionToDismiss.return.new.Promise.):
(window.UIHelper.waitForInputSessionToDismiss.return.new.Promise):
(window.UIHelper.waitForInputSessionToDismiss):
Likewise, teach this to wait for context menu dismissal.
(window.UIHelper.waitForContextMenuToHide.return.new.Promise):
(window.UIHelper.waitForContextMenuToHide):
Add a new helper to wait for context menus to hide.
Canonical link: https://commits.webkit.org/226942@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@264170 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-07-09 15:15:29 +00:00
|
|
|
static waitForContextMenuToHide()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
if (uiController.isShowingContextMenu)
|
|
|
|
uiController.didDismissContextMenuCallback = () => uiController.uiScriptComplete();
|
|
|
|
else
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[Extra zoom mode] Programmatically changing focus when an element already has focus is a confusing experience
https://bugs.webkit.org/show_bug.cgi?id=184635
<rdar://problem/39440642>
Reviewed by Tim Horton.
Source/WebKit:
Currently on iOS, we allow element focus to present UI if the keyboard is already shown. In extra zoom mode,
this would lead to a confusing experience when the focus form control overlay is disabled, since fullscreen
input view controllers are swapped out from underneath the user. Currently, this also puts the UI process into a
bad state where the focused form control overlay is active, but still hidden. This patch makes some tweaks to
input view controller handling in the UI process to address these issues, and also adds WebKitTestRunner support
for simulating interactions with select menus in extra zoom mode. See comments below for more detail.
Test: fast/events/extrazoom/change-focus-during-change-event.html
* UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
Add new SPI delegate hooks to notify the UI delegate when view controllers are presented or dismissed in extra
zoom mode. See -presentViewControllerForCurrentAssistedNode and -dismissAllInputViewControllers.
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::takeBackgroundActivityTokenForFullscreenInput):
(WebKit::WebProcessProxy::releaseBackgroundActivityTokenForFullscreenInput):
See the comment below -dismissAllInputViewControllers.
* UIProcess/WebProcessProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
In extra zoom mode, when changing focus from one assisted node to another, only allow the second node to be
assisted if the focused form control overlay is being shown. Otherwise, (i.e. when a fullscreen input view
controller is being presented), don't allow focus to start an input session.
Additionally, make a minor tweak to allow the previous node to blur, even if we are not showing the keyboard for
the new focused element. Without this adjustment, in the case where the page has programmatically focused
another element while a fullscreen input view controller is presented, we'll show the old view controller for
the new focused element.
(-[WKContentView presentViewControllerForCurrentAssistedNode]):
(-[WKContentView dismissAllInputViewControllers:]):
Currently, when a fullscreen input view controller is presented, the web process gets backgrounded. This
prevents event handlers from executing, which leads to strange behaviors in many cases (for instance: if we
have a multiple select, and the "change" event handler blurs the select, the user may check or uncheck multiple
items, but only the first change will actually take effect).
To fix this, we maintain a background activity token while presenting an input view controller.
(-[WKContentView focusedFormControlViewDidBeginEditing:]):
Start hiding the focused form overlay when re-presenting an input view controller. This allows us to bail from
showing fullscreen input UI for another focused element if focus programmatically changes while the current
fullscreen input view controller is presented, due to the -isHidden check in -_startAssistingNode:.
(-[WKContentView selectFormAccessoryPickerRow:]):
Simulate tapping a given row in select menu UI in extra zoom mode.
Tools:
Add plumbing to support invoking `didHideKeyboardCallback` and `didShowKeyboardCallback` when (respectively)
dismissing or presenting fullscreen input view controllers in extra zoom mode.
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView initWithFrame:configuration:]):
(-[TestRunnerWKWebView dealloc]):
(-[TestRunnerWKWebView _invokeShowKeyboardCallbackIfNecessary]):
(-[TestRunnerWKWebView _invokeHideKeyboardCallbackIfNecessary]):
(-[TestRunnerWKWebView _keyboardDidShow:]):
(-[TestRunnerWKWebView _keyboardDidHide:]):
(-[TestRunnerWKWebView _webView:didPresentFocusedElementViewController:]):
(-[TestRunnerWKWebView _webView:didDismissFocusedElementViewController:]):
LayoutTests:
Add a new layout test to exercise the following sequence of events in extra zoom mode:
1. Focus select element #1.
2. Choose an unselected option.
3. Programmatically focus select element #2 in the "change" event handler.
4. Choose an unselected option.
5. Programmatically blur select element #2 in the "change" event handler.
* fast/events/extrazoom/change-focus-during-change-event-expected.txt: Added.
* fast/events/extrazoom/change-focus-during-change-event.html: Added.
* resources/ui-helper.js:
(window.UIHelper.waitForKeyboardToHide.return.new.Promise):
(window.UIHelper.waitForKeyboardToHide):
Canonical link: https://commits.webkit.org/200238@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230752 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-04-18 06:03:06 +00:00
|
|
|
static waitForKeyboardToHide()
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
[iOS] [Datalist] Can't pick datalist suggestions in a stock WKWebView
https://bugs.webkit.org/show_bug.cgi?id=190621
<rdar://problem/45310649>
Reviewed by Tim Horton.
Source/WebKit:
Fixes the bug by refactoring datalist suggestion information on iOS; currently, we override text suggestions on
_WKFormInputSession. This only works for a few internal clients (including Safari) that set a _WKInputDelegate
and also implement either -_webView:willStartInputSession: or -_webView:didStartInputSession:, which is
necessary in order to ensure that WebKit creates and maintains a form input session.
The two pieces of information that datalist code needs to vend to WKContentView are a list of UITextSuggestions
and a custom input view, which are both currently properties of _WKFormInputSession. This patch lifts these out
of the input session and makes them properties of WKContentView, which are used in
WebDataListSuggestionsDropdownIOS.
Test: fast/forms/datalist/datalist-textinput-suggestions-order.html
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
Add new properties to WKContentView: an input view for datalist suggestions, and a list of text suggestions.
(-[WKFormInputSession setSuggestions:]):
(-[WKContentView setupInteraction]):
(-[WKContentView cleanupInteraction]):
(-[WKContentView _endEditing]):
Pull out common logic when resigning first responder or tabbing to the next or previous text field into a new
helper. This helper notifies `_inputPeripheral`, `_formInputSession`, and `_dataListTextSuggestionsInputView`
when editing has ended; the input peripheral and suggestions input view use this chance to send the value of the
form control to the web process.
(-[WKContentView resignFirstResponderForWebView]):
(-[WKContentView inputView]):
If a custom input view is not set but we have an input view for a datalist's text suggestions, use the datalist
input view.
(-[WKContentView accessoryTab:]):
(-[WKContentView _stopAssistingNode]):
Clear datalist state on WKContentView.
(-[WKContentView dataListTextSuggestionsInputView]):
(-[WKContentView dataListTextSuggestions]):
(-[WKContentView setDataListTextSuggestionsInputView:]):
(-[WKContentView setDataListTextSuggestions:]):
(-[WKContentView updateTextSuggestionsForInputDelegate]):
Pull out logic for setting suggestions on UIKit's `inputDelegate` (i.e. UIKeyboardImpl). We now first consult
internally-vended text suggestions from _WKFormInputSession; if an internal client has not overridden our text
suggestions, then we simply use suggestions from the current datalist (if present).
* UIProcess/ios/WebDataListSuggestionsDropdownIOS.mm:
(-[WKDataListSuggestionsPicker updateWithInformation:]):
(-[WKDataListSuggestionsPicker showSuggestionsDropdown:activationType:]):
(-[WKDataListSuggestionsPicker invalidate]):
(-[WKDataListSuggestionsPopover updateWithInformation:]):
(-[WKDataListSuggestionsPopover showSuggestionsDropdown:activationType:]):
(-[WKDataListSuggestionsPopover didSelectOptionAtIndex:]):
Change all the places that currently manipulate WKContentView's form input session to directly set text
suggestions and the text suggestion input view on the content view instead.
Tools:
Add a UIScriptController hook to resign first responder on WKWebView. See LayoutTests/ChangeLog for more detail.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::resignFirstResponder):
* DumpRenderTree/mac/UIScriptControllerMac.mm:
(WTR::UIScriptController::resignFirstResponder):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::resignFirstResponder):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/UIScriptControllerCocoa.mm:
(WTR::UIScriptController::resignFirstResponder):
* WebKitTestRunner/ios/PlatformWebViewIOS.mm:
(WTR::PlatformWebView::makeWebViewFirstResponder):
Implement this method stub on iOS, to ensure that TestController::resetStateToConsistentValues restores first
responder on the WKWebView when running iOS layout tests.
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
After resigning first responder to dismiss any on-screen keyboard, ensure that we restore first responder.
LayoutTests:
Refactor an existing layout test to run on both iOS and macOS. On both platforms, it checks that the top
suggestion respects option element order in the document, as well as the current contents of the text field.
On macOS, we use arrow keys and hit return to select a suggestion; on iOS, we tap the suggestions button and
simulate hitting the done button on the input view to dismiss the keyboard.
* fast/forms/datalist/datalist-textinput-suggestions-order-expected.txt:
* fast/forms/datalist/datalist-textinput-suggestions-order.html:
* platform/ios/TestExpectations:
Enable this test on iOS.
* resources/ui-helper.js:
(window.UIHelper.resignFirstResponder):
(window.UIHelper):
Canonical link: https://commits.webkit.org/205670@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237305 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-10-19 22:00:32 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
[Extra zoom mode] Programmatically changing focus when an element already has focus is a confusing experience
https://bugs.webkit.org/show_bug.cgi?id=184635
<rdar://problem/39440642>
Reviewed by Tim Horton.
Source/WebKit:
Currently on iOS, we allow element focus to present UI if the keyboard is already shown. In extra zoom mode,
this would lead to a confusing experience when the focus form control overlay is disabled, since fullscreen
input view controllers are swapped out from underneath the user. Currently, this also puts the UI process into a
bad state where the focused form control overlay is active, but still hidden. This patch makes some tweaks to
input view controller handling in the UI process to address these issues, and also adds WebKitTestRunner support
for simulating interactions with select menus in extra zoom mode. See comments below for more detail.
Test: fast/events/extrazoom/change-focus-during-change-event.html
* UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
Add new SPI delegate hooks to notify the UI delegate when view controllers are presented or dismissed in extra
zoom mode. See -presentViewControllerForCurrentAssistedNode and -dismissAllInputViewControllers.
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::takeBackgroundActivityTokenForFullscreenInput):
(WebKit::WebProcessProxy::releaseBackgroundActivityTokenForFullscreenInput):
See the comment below -dismissAllInputViewControllers.
* UIProcess/WebProcessProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
In extra zoom mode, when changing focus from one assisted node to another, only allow the second node to be
assisted if the focused form control overlay is being shown. Otherwise, (i.e. when a fullscreen input view
controller is being presented), don't allow focus to start an input session.
Additionally, make a minor tweak to allow the previous node to blur, even if we are not showing the keyboard for
the new focused element. Without this adjustment, in the case where the page has programmatically focused
another element while a fullscreen input view controller is presented, we'll show the old view controller for
the new focused element.
(-[WKContentView presentViewControllerForCurrentAssistedNode]):
(-[WKContentView dismissAllInputViewControllers:]):
Currently, when a fullscreen input view controller is presented, the web process gets backgrounded. This
prevents event handlers from executing, which leads to strange behaviors in many cases (for instance: if we
have a multiple select, and the "change" event handler blurs the select, the user may check or uncheck multiple
items, but only the first change will actually take effect).
To fix this, we maintain a background activity token while presenting an input view controller.
(-[WKContentView focusedFormControlViewDidBeginEditing:]):
Start hiding the focused form overlay when re-presenting an input view controller. This allows us to bail from
showing fullscreen input UI for another focused element if focus programmatically changes while the current
fullscreen input view controller is presented, due to the -isHidden check in -_startAssistingNode:.
(-[WKContentView selectFormAccessoryPickerRow:]):
Simulate tapping a given row in select menu UI in extra zoom mode.
Tools:
Add plumbing to support invoking `didHideKeyboardCallback` and `didShowKeyboardCallback` when (respectively)
dismissing or presenting fullscreen input view controllers in extra zoom mode.
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView initWithFrame:configuration:]):
(-[TestRunnerWKWebView dealloc]):
(-[TestRunnerWKWebView _invokeShowKeyboardCallbackIfNecessary]):
(-[TestRunnerWKWebView _invokeHideKeyboardCallbackIfNecessary]):
(-[TestRunnerWKWebView _keyboardDidShow:]):
(-[TestRunnerWKWebView _keyboardDidHide:]):
(-[TestRunnerWKWebView _webView:didPresentFocusedElementViewController:]):
(-[TestRunnerWKWebView _webView:didDismissFocusedElementViewController:]):
LayoutTests:
Add a new layout test to exercise the following sequence of events in extra zoom mode:
1. Focus select element #1.
2. Choose an unselected option.
3. Programmatically focus select element #2 in the "change" event handler.
4. Choose an unselected option.
5. Programmatically blur select element #2 in the "change" event handler.
* fast/events/extrazoom/change-focus-during-change-event-expected.txt: Added.
* fast/events/extrazoom/change-focus-during-change-event.html: Added.
* resources/ui-helper.js:
(window.UIHelper.waitForKeyboardToHide.return.new.Promise):
(window.UIHelper.waitForKeyboardToHide):
Canonical link: https://commits.webkit.org/200238@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230752 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-04-18 06:03:06 +00:00
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
[iOS] Can't select text after dismissing the keyboard when changing focus
https://bugs.webkit.org/show_bug.cgi?id=190563
<rdar://problem/44613559>
Reviewed by Tim Horton.
Source/WebKit:
In r230686, we switched from using UIWKSelectionAssistant to UIWKTextInteractionAssistant for handling selection
in non-editable content on iOS; as such, when an editable element loses focus, instead of switching from the
text interaction assistant to the web selection assistant as we've previously done, we now reset our text
interaction assistant by calling `-[UIWKTextInteractionAssistant setGestureRecognizers]`, which removes all of
the current text selection gesture recognizers from WKContentView and regenerates them by building up a tree of
`UITextInteraction`s and adding them to the assistant (see `-[UITextInteractionAssistant
addGestureRecognizersToView:]`). In particular, `_UITextSelectionForceGesture` is the gesture recognizer used to
trigger text selection when long pressing.
After dismissing the keyboard by tapping the "Done" button, the UITextInteractions and gesture recognizers on
the interaction assistant include:
<UITextInteraction>
…
<UITextIndirectNonEditableInteraction>
<_UIKeyboardBasedNonEditableTextSelectionInteraction>
↳ "_UIKeyboardTextSelectionGestureForcePress" → <_UITextSelectionForceGesture>
However, after the keyboard dismisses due to an editable element losing focus, the UITextInteractions on the
interaction assistant look like this:
<UITextInteraction>
…
<UITextIndirectNonEditableInteraction>
Subsequently, the lack of a `_UIKeyboardBasedNonEditableTextSelectionInteraction` makes text selection by long
pressing impossible, since the `_UITextSelectionForceGesture` is never introduced to `WKContentView`. In UIKit,
`UITextIndirectNonEditableInteraction` only adds `_UIKeyboardBasedNonEditableTextSelectionInteraction` as a
child if the text input view — in our case, WKContentView — is missing an input delegate (see `-initWithView:`).
In the case where the Done button is used to dismiss the keyboard, WKContentView loses first responder, and the
input delegate of WKContentView is cleared out early on, before we call `-stopAssistingKeyboard`:
-[WKContentView(WKInteraction) setInputDelegate:]
-[UIKeyboardImpl setDelegate:force:]
-[UIPeripheralHost(UIKitInternal) _reloadInputViewsForResponder:]
-[UIResponder _finishResignFirstResponder]
-[UIResponder resignFirstResponder]
-[WKContentView(WKInteraction) resignFirstResponderForWebView]
-[UIKeyboardImpl dismissKeyboard]
However, in the case where the focused element is blurred, we end up clearing out the delegate in
`-_stopAssistingNode`, *after* we've already called `-setGestureRecognizers` on the interaction assistant. This
means UIKit will skip adding `_UIKeyboardBasedNonEditableTextSelectionInteraction` to the text interaction
assistant.
-[WKContentView(WKInteraction) setInputDelegate:]
-[UIKeyboardImpl setDelegate:force:]
-[UIPeripheralHost(UIKitInternal) _reloadInputViewsForResponder:]
-[UIResponder(UIResponderInputViewAdditions) reloadInputViews]
-[WKContentView(WKInteraction) _stopAssistingNode]
To fix this, we simply reset our `inputDelegate` earlier in `_stopAssistingKeyboard` instead of waiting until
we reload input views. This ensures that UIKit sets up the text interaction assistant's gestures when changing
focus in the same way as we would when the keyboard is dismissed via `-resignFirstResponder` (e.g. when pressing
the Done button).
Test: editing/selection/ios/select-text-after-changing-focus.html
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView setupInteraction]):
(-[WKContentView setUpTextSelectionAssistant]):
(-[WKContentView _startAssistingKeyboard]):
(-[WKContentView _stopAssistingKeyboard]):
(-[WKContentView useSelectionAssistantWithGranularity:]): Deleted.
Additionally rename this to -setUpTextSelectionAssistant and remove the selection granularity argument. This was
previously used to switch between web and text interaction assistants.
Tools:
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isShowingKeyboard const):
Add a new UIScriptController method that returns whether the keyboard is shown. See `ui-helper.js` for more
details.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::isShowingKeyboard const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
Also rename the `isShowingKeyboard` Objective-C property to the more canonical `showingKeyboard`, with
`isShowingKeyboard` as the getter method.
(-[TestRunnerWKWebView _invokeShowKeyboardCallbackIfNecessary]):
(-[TestRunnerWKWebView _invokeHideKeyboardCallbackIfNecessary]):
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isShowingKeyboard const):
LayoutTests:
Add a new layout test to check that the user can make a selection by long pressing after the keyboard is
dismissed due to changing the focused element.
* editing/selection/ios/select-text-after-changing-focus-expected.txt: Added.
* editing/selection/ios/select-text-after-changing-focus.html: Added.
* resources/ui-helper.js:
Also tweak the behavior of `UIHelper.waitForKeyboardToHide()`, so that it resolves immediately if the keyboard
is not shown. This allows us to ensure that tests which use `UIHelper.waitForKeyboardToHide()` are robust in the
case where they wait for another action to complete (e.g. a simulated tap) prior to registering a keyboard
hiding callback.
(window.UIHelper.waitForKeyboardToHide.return.new.Promise):
(window.UIHelper.waitForKeyboardToHide):
Canonical link: https://commits.webkit.org/205509@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237135 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-10-15 19:47:03 +00:00
|
|
|
if (uiController.isShowingKeyboard)
|
|
|
|
uiController.didHideKeyboardCallback = () => uiController.uiScriptComplete();
|
|
|
|
else
|
|
|
|
uiController.uiScriptComplete();
|
[Extra zoom mode] Programmatically changing focus when an element already has focus is a confusing experience
https://bugs.webkit.org/show_bug.cgi?id=184635
<rdar://problem/39440642>
Reviewed by Tim Horton.
Source/WebKit:
Currently on iOS, we allow element focus to present UI if the keyboard is already shown. In extra zoom mode,
this would lead to a confusing experience when the focus form control overlay is disabled, since fullscreen
input view controllers are swapped out from underneath the user. Currently, this also puts the UI process into a
bad state where the focused form control overlay is active, but still hidden. This patch makes some tweaks to
input view controller handling in the UI process to address these issues, and also adds WebKitTestRunner support
for simulating interactions with select menus in extra zoom mode. See comments below for more detail.
Test: fast/events/extrazoom/change-focus-during-change-event.html
* UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
Add new SPI delegate hooks to notify the UI delegate when view controllers are presented or dismissed in extra
zoom mode. See -presentViewControllerForCurrentAssistedNode and -dismissAllInputViewControllers.
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::takeBackgroundActivityTokenForFullscreenInput):
(WebKit::WebProcessProxy::releaseBackgroundActivityTokenForFullscreenInput):
See the comment below -dismissAllInputViewControllers.
* UIProcess/WebProcessProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
In extra zoom mode, when changing focus from one assisted node to another, only allow the second node to be
assisted if the focused form control overlay is being shown. Otherwise, (i.e. when a fullscreen input view
controller is being presented), don't allow focus to start an input session.
Additionally, make a minor tweak to allow the previous node to blur, even if we are not showing the keyboard for
the new focused element. Without this adjustment, in the case where the page has programmatically focused
another element while a fullscreen input view controller is presented, we'll show the old view controller for
the new focused element.
(-[WKContentView presentViewControllerForCurrentAssistedNode]):
(-[WKContentView dismissAllInputViewControllers:]):
Currently, when a fullscreen input view controller is presented, the web process gets backgrounded. This
prevents event handlers from executing, which leads to strange behaviors in many cases (for instance: if we
have a multiple select, and the "change" event handler blurs the select, the user may check or uncheck multiple
items, but only the first change will actually take effect).
To fix this, we maintain a background activity token while presenting an input view controller.
(-[WKContentView focusedFormControlViewDidBeginEditing:]):
Start hiding the focused form overlay when re-presenting an input view controller. This allows us to bail from
showing fullscreen input UI for another focused element if focus programmatically changes while the current
fullscreen input view controller is presented, due to the -isHidden check in -_startAssistingNode:.
(-[WKContentView selectFormAccessoryPickerRow:]):
Simulate tapping a given row in select menu UI in extra zoom mode.
Tools:
Add plumbing to support invoking `didHideKeyboardCallback` and `didShowKeyboardCallback` when (respectively)
dismissing or presenting fullscreen input view controllers in extra zoom mode.
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView initWithFrame:configuration:]):
(-[TestRunnerWKWebView dealloc]):
(-[TestRunnerWKWebView _invokeShowKeyboardCallbackIfNecessary]):
(-[TestRunnerWKWebView _invokeHideKeyboardCallbackIfNecessary]):
(-[TestRunnerWKWebView _keyboardDidShow:]):
(-[TestRunnerWKWebView _keyboardDidHide:]):
(-[TestRunnerWKWebView _webView:didPresentFocusedElementViewController:]):
(-[TestRunnerWKWebView _webView:didDismissFocusedElementViewController:]):
LayoutTests:
Add a new layout test to exercise the following sequence of events in extra zoom mode:
1. Focus select element #1.
2. Choose an unselected option.
3. Programmatically focus select element #2 in the "change" event handler.
4. Choose an unselected option.
5. Programmatically blur select element #2 in the "change" event handler.
* fast/events/extrazoom/change-focus-during-change-event-expected.txt: Added.
* fast/events/extrazoom/change-focus-during-change-event.html: Added.
* resources/ui-helper.js:
(window.UIHelper.waitForKeyboardToHide.return.new.Promise):
(window.UIHelper.waitForKeyboardToHide):
Canonical link: https://commits.webkit.org/200238@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230752 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-04-18 06:03:06 +00:00
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[WK2] EditorState updates should be rolled into the layer update lifecycle when possible
https://bugs.webkit.org/show_bug.cgi?id=175370
<rdar://problem/33799806>
Reviewed by Ryosuke Niwa.
Source/WebCore:
Remove didChangeSelectionAndUpdateLayout -- EditorState updates that are scheduled due to missing post-layout
data will now be scheduled for the next presentation update. Additionally, add editor client hooks to notify the
WebKit layer when we've updated the current composition. See WebKit ChangeLog for more details. This patch
adjusts and rebaselines existing layout tests.
* editing/Editor.cpp:
(WebCore::SetCompositionScope::SetCompositionScope):
(WebCore::SetCompositionScope::~SetCompositionScope):
Introduce a helper RAII class to ensure that we ignore selection changes during the scope of
Editor::setComposition and call out to the client with WebEditorClient::didUpdateComposition afterwards. This
also maintains a UserTypingGestureIndicator over its lifetime, so we don't additionally need to create a
UserTypingGestureIndicator in Editor::setComposition.
(WebCore::Editor::setComposition):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::setSelection):
(WebCore::FrameSelection::updateAndRevealSelection):
(WebCore::FrameSelection::setSelectedRange):
* editing/FrameSelection.h:
(WebCore::FrameSelection::defaultSetSelectionOptions):
Plumb state about whether or not the selection change was triggered by the user to FrameSelection::setSelection,
and if so, notify the editing client. A separate SetSelectionOptions flag is used here instead of
RevealSelection to avoid calling out to the client in places where we want to reveal the selection regardless of
whether or not the selection is user triggered.
* loader/EmptyClients.cpp:
* page/EditorClient.h:
Source/WebKit:
See per-method comments for more detail. WebPage::didChangeSelection now schedules EditorState updates to be sent
during the next layer tree transaction rather than sending them synchronously. To ensure that iOS and Mac continue
to behave correctly w.r.t. EditorState updates, we immediately dispatch EditorStates in the following cases:
- After the composition changes, is confirmed, or is canceled.
- After an edit command is executed.
- After ending user-triggered selection changes.
* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::hasEditorState const):
(WebKit::RemoteLayerTreeTransaction::editorState const):
(WebKit::RemoteLayerTreeTransaction::setEditorState):
Attaches an optional EditorState to the RemoteLayerTreeTransaction. This EditorState is computed and sent over
when setting up the transaction in WebPage, if something previously scheduled an EditorState update.
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode const):
(WebKit::RemoteLayerTreeTransaction::decode):
Add coder support for sending over a layer tree transaction's EditorState.
* UIProcess/API/Cocoa/WKViewPrivate.h:
* UIProcess/API/mac/WKView.mm:
(-[WKView _doAfterNextPresentationUpdate:]):
Add _doAfterNextPresentationUpdate to WKView (used in TestWebKitAPI -- refer to
WebKitAgnosticTest::waitForNextPresentationUpdate).
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
* UIProcess/DrawingAreaProxy.messages.in:
Add a new IPC messages, DispatchPresentationCallbacksAfterFlushingLayers, to invoke in-flight presentation
callbacks in the UI process following a layer flush in the web process.
* UIProcess/WebPageProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h:
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::~TiledCoreAnimationDrawingAreaProxy):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
Run all pending _doAfterNextPresentationUpdate callbacks.
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::didApplyStyle):
(WebKit::WebEditorClient::respondToChangedContents):
(WebKit::WebEditorClient::didEndUserTriggeredSelectionChanges):
(WebKit::WebEditorClient::didUpdateComposition):
Forward editor client calls to the WebPage.
(WebKit::WebEditorClient::didChangeSelectionAndUpdateLayout): Deleted.
* WebProcess/WebCoreSupport/WebEditorClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::editorState const):
(WebKit::WebPage::updateEditorStateAfterLayoutIfEditabilityChanged):
(WebKit::WebPage::willCommitLayerTree):
(WebKit::WebPage::didApplyStyle):
Allow style application to immediately trigger EditorState updates, if we're not currently ignoring selection
changes in the Editor.
(WebKit::WebPage::didChangeContents):
Allow applying top-level edit commands to immediately trigger EditorState updates, if we're not currently
ignoring selection changes in the Editor.
(WebKit::WebPage::didChangeSelection):
(WebKit::WebPage::didUpdateComposition):
(WebKit::WebPage::didEndUserTriggeredSelectionChanges):
(WebKit::WebPage::discardedComposition):
(WebKit::WebPage::canceledComposition):
When handling composition updates, always send an EditorState to the UI process. Unlike other cases, IME
requires immediate EditorState data, so we need to be explicit here in sending updates right away.
(WebKit::WebPage::sendEditorStateUpdate):
(WebKit::WebPage::sendPartialEditorStateAndSchedulePostLayoutUpdate):
(WebKit::WebPage::flushPendingEditorStateUpdate):
Helper methods to schedule an EditorState update to be sent upon the next layer tree update, or flush any
pending EditorState update that has been scheduled. The private, more aggressive variant of this is
sendEditorStateUpdate, which ignores whether or not there was already an EditorState update scheduled, and sends
one anyways (this still fulfills any EditorState update that was previously scheduled).
These helper methods are treated as no-ops when invoked while ignoring selection changes. This is to prevent
temporary selection state and editor commands during operations such as text indicator snapshotting from pushing
bogus information about transient editor states to the UI process.
(WebKit::WebPage::sendPostLayoutEditorStateIfNeeded): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::executeEditCommandWithCallback):
(WebKit::selectionIsInsideFixedPositionContainer):
(WebKit::WebPage::updateVisibleContentRects):
Fix a hack that was computing an EditorState to figure out whether the current selection starts or ends in a
fixed position container. Factors out relevant logic into a separate helper, and also schedules an EditorState
update instead of immediately computing it.
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::addTransactionCallbackID):
Add support for registering and dispatching presentation callbacks that hook into the layer flush lifecycle,
using the tiled CA drawing area. These are used by Mac LayoutTests and API tests that need to wait until the
next flush before checking for state that depends on EditorState updates in the UI process.
(WebKit::TiledCoreAnimationDrawingArea::flushLayers):
Tell the WebPage to flush any pending EditorState updates.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState const):
Source/WebKitLegacy/mac:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Source/WebKitLegacy/win:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Tools:
Tweaks API tests that involve editing to wait for a presentation update before checking against UI process-side
information sent via EditorState updates. This allows any EditorState update scheduled by the test to propagate
to the UI process.
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewCandidateTests.mm:
(-[CandidateTestWebView typeString:inputMessage:]):
(+[CandidateTestWebView setUpWithFrame:testPage:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewTextInput.mm:
* TestWebKitAPI/Tests/mac/AcceptsFirstMouse.mm:
(TestWebKitAPI::AcceptsFirstMouse::runTest):
* TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm:
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView waitForNextPresentationUpdate]):
Add a new helper method to spin until the next presentation update.
* TestWebKitAPI/mac/WebKitAgnosticTest.h:
* TestWebKitAPI/mac/WebKitAgnosticTest.mm:
(TestWebKitAPI::WebKitAgnosticTest::waitForNextPresentationUpdate):
LayoutTests:
Rebaseline and adjust LayoutTests.
* editing/caret/ios/absolute-caret-position-after-scroll-expected.txt:
* editing/caret/ios/absolute-caret-position-after-scroll.html:
* editing/caret/ios/fixed-caret-position-after-scroll-expected.txt:
* editing/caret/ios/fixed-caret-position-after-scroll.html:
* editing/secure-input/password-input-changed-type.html:
* editing/secure-input/password-input-focusing.html:
* editing/secure-input/removed-password-input.html:
* editing/secure-input/reset-state-on-navigation.html:
* editing/selection/character-granularity-rect.html:
Delay checking for secure input state and caret rects until after the next presentation update.
* editing/selection/ios/absolute-selection-after-scroll-expected.txt:
* editing/selection/ios/absolute-selection-after-scroll.html:
* editing/selection/ios/fixed-selection-after-scroll-expected.txt:
* editing/selection/ios/fixed-selection-after-scroll.html:
Refactor and simplify these tests. These tests are not run on the OpenSource bots, since they depend on long
press and tap gestures.
* platform/ios-wk2/editing/inserting/insert-div-024-expected.txt:
* platform/ios-wk2/editing/inserting/insert-div-026-expected.txt:
* platform/ios-wk2/editing/style/5084241-expected.txt:
Rebaselines these tests, removing an anonymous RenderBlock inserted as a result of inserting and removing a
dummy span in order to compute a RenderStyle in WebPage::editorState. This is because editorState is no longer
invoked immediately on page load; https://bugs.webkit.org/show_bug.cgi?id=175116 tracks preventing this render
tree thrashing altogether.
* platform/mac-wk2/TestExpectations:
* platform/mac-wk2/editing/style/unbold-in-bold-expected.txt:
* resources/ui-helper.js:
Introduce new UIHelper functions.
(window.UIHelper.ensurePresentationUpdate.return.new.Promise):
(window.UIHelper.ensurePresentationUpdate):
Returns a Promise, resolved after the next presentation update.
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise):
(window.UIHelper.activateAndWaitForInputSessionAt):
Returns a Promise, resolved after tapping at the given location and waiting for the keyboard to appear on iOS.
(window.UIHelper.getUICaretRect.return.new.Promise.):
(window.UIHelper.getUICaretRect.return.new.Promise):
(window.UIHelper.getUICaretRect):
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
Helpers to fetch selection and caret rect information in the UI process.
Canonical link: https://commits.webkit.org/192519@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221064 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-23 03:15:38 +00:00
|
|
|
static getUICaretRect()
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
[WK2] EditorState updates should be rolled into the layer update lifecycle when possible
https://bugs.webkit.org/show_bug.cgi?id=175370
<rdar://problem/33799806>
Reviewed by Ryosuke Niwa.
Source/WebCore:
Remove didChangeSelectionAndUpdateLayout -- EditorState updates that are scheduled due to missing post-layout
data will now be scheduled for the next presentation update. Additionally, add editor client hooks to notify the
WebKit layer when we've updated the current composition. See WebKit ChangeLog for more details. This patch
adjusts and rebaselines existing layout tests.
* editing/Editor.cpp:
(WebCore::SetCompositionScope::SetCompositionScope):
(WebCore::SetCompositionScope::~SetCompositionScope):
Introduce a helper RAII class to ensure that we ignore selection changes during the scope of
Editor::setComposition and call out to the client with WebEditorClient::didUpdateComposition afterwards. This
also maintains a UserTypingGestureIndicator over its lifetime, so we don't additionally need to create a
UserTypingGestureIndicator in Editor::setComposition.
(WebCore::Editor::setComposition):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::setSelection):
(WebCore::FrameSelection::updateAndRevealSelection):
(WebCore::FrameSelection::setSelectedRange):
* editing/FrameSelection.h:
(WebCore::FrameSelection::defaultSetSelectionOptions):
Plumb state about whether or not the selection change was triggered by the user to FrameSelection::setSelection,
and if so, notify the editing client. A separate SetSelectionOptions flag is used here instead of
RevealSelection to avoid calling out to the client in places where we want to reveal the selection regardless of
whether or not the selection is user triggered.
* loader/EmptyClients.cpp:
* page/EditorClient.h:
Source/WebKit:
See per-method comments for more detail. WebPage::didChangeSelection now schedules EditorState updates to be sent
during the next layer tree transaction rather than sending them synchronously. To ensure that iOS and Mac continue
to behave correctly w.r.t. EditorState updates, we immediately dispatch EditorStates in the following cases:
- After the composition changes, is confirmed, or is canceled.
- After an edit command is executed.
- After ending user-triggered selection changes.
* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::hasEditorState const):
(WebKit::RemoteLayerTreeTransaction::editorState const):
(WebKit::RemoteLayerTreeTransaction::setEditorState):
Attaches an optional EditorState to the RemoteLayerTreeTransaction. This EditorState is computed and sent over
when setting up the transaction in WebPage, if something previously scheduled an EditorState update.
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode const):
(WebKit::RemoteLayerTreeTransaction::decode):
Add coder support for sending over a layer tree transaction's EditorState.
* UIProcess/API/Cocoa/WKViewPrivate.h:
* UIProcess/API/mac/WKView.mm:
(-[WKView _doAfterNextPresentationUpdate:]):
Add _doAfterNextPresentationUpdate to WKView (used in TestWebKitAPI -- refer to
WebKitAgnosticTest::waitForNextPresentationUpdate).
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
* UIProcess/DrawingAreaProxy.messages.in:
Add a new IPC messages, DispatchPresentationCallbacksAfterFlushingLayers, to invoke in-flight presentation
callbacks in the UI process following a layer flush in the web process.
* UIProcess/WebPageProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h:
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::~TiledCoreAnimationDrawingAreaProxy):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
Run all pending _doAfterNextPresentationUpdate callbacks.
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::didApplyStyle):
(WebKit::WebEditorClient::respondToChangedContents):
(WebKit::WebEditorClient::didEndUserTriggeredSelectionChanges):
(WebKit::WebEditorClient::didUpdateComposition):
Forward editor client calls to the WebPage.
(WebKit::WebEditorClient::didChangeSelectionAndUpdateLayout): Deleted.
* WebProcess/WebCoreSupport/WebEditorClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::editorState const):
(WebKit::WebPage::updateEditorStateAfterLayoutIfEditabilityChanged):
(WebKit::WebPage::willCommitLayerTree):
(WebKit::WebPage::didApplyStyle):
Allow style application to immediately trigger EditorState updates, if we're not currently ignoring selection
changes in the Editor.
(WebKit::WebPage::didChangeContents):
Allow applying top-level edit commands to immediately trigger EditorState updates, if we're not currently
ignoring selection changes in the Editor.
(WebKit::WebPage::didChangeSelection):
(WebKit::WebPage::didUpdateComposition):
(WebKit::WebPage::didEndUserTriggeredSelectionChanges):
(WebKit::WebPage::discardedComposition):
(WebKit::WebPage::canceledComposition):
When handling composition updates, always send an EditorState to the UI process. Unlike other cases, IME
requires immediate EditorState data, so we need to be explicit here in sending updates right away.
(WebKit::WebPage::sendEditorStateUpdate):
(WebKit::WebPage::sendPartialEditorStateAndSchedulePostLayoutUpdate):
(WebKit::WebPage::flushPendingEditorStateUpdate):
Helper methods to schedule an EditorState update to be sent upon the next layer tree update, or flush any
pending EditorState update that has been scheduled. The private, more aggressive variant of this is
sendEditorStateUpdate, which ignores whether or not there was already an EditorState update scheduled, and sends
one anyways (this still fulfills any EditorState update that was previously scheduled).
These helper methods are treated as no-ops when invoked while ignoring selection changes. This is to prevent
temporary selection state and editor commands during operations such as text indicator snapshotting from pushing
bogus information about transient editor states to the UI process.
(WebKit::WebPage::sendPostLayoutEditorStateIfNeeded): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::executeEditCommandWithCallback):
(WebKit::selectionIsInsideFixedPositionContainer):
(WebKit::WebPage::updateVisibleContentRects):
Fix a hack that was computing an EditorState to figure out whether the current selection starts or ends in a
fixed position container. Factors out relevant logic into a separate helper, and also schedules an EditorState
update instead of immediately computing it.
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::addTransactionCallbackID):
Add support for registering and dispatching presentation callbacks that hook into the layer flush lifecycle,
using the tiled CA drawing area. These are used by Mac LayoutTests and API tests that need to wait until the
next flush before checking for state that depends on EditorState updates in the UI process.
(WebKit::TiledCoreAnimationDrawingArea::flushLayers):
Tell the WebPage to flush any pending EditorState updates.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState const):
Source/WebKitLegacy/mac:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Source/WebKitLegacy/win:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Tools:
Tweaks API tests that involve editing to wait for a presentation update before checking against UI process-side
information sent via EditorState updates. This allows any EditorState update scheduled by the test to propagate
to the UI process.
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewCandidateTests.mm:
(-[CandidateTestWebView typeString:inputMessage:]):
(+[CandidateTestWebView setUpWithFrame:testPage:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewTextInput.mm:
* TestWebKitAPI/Tests/mac/AcceptsFirstMouse.mm:
(TestWebKitAPI::AcceptsFirstMouse::runTest):
* TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm:
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView waitForNextPresentationUpdate]):
Add a new helper method to spin until the next presentation update.
* TestWebKitAPI/mac/WebKitAgnosticTest.h:
* TestWebKitAPI/mac/WebKitAgnosticTest.mm:
(TestWebKitAPI::WebKitAgnosticTest::waitForNextPresentationUpdate):
LayoutTests:
Rebaseline and adjust LayoutTests.
* editing/caret/ios/absolute-caret-position-after-scroll-expected.txt:
* editing/caret/ios/absolute-caret-position-after-scroll.html:
* editing/caret/ios/fixed-caret-position-after-scroll-expected.txt:
* editing/caret/ios/fixed-caret-position-after-scroll.html:
* editing/secure-input/password-input-changed-type.html:
* editing/secure-input/password-input-focusing.html:
* editing/secure-input/removed-password-input.html:
* editing/secure-input/reset-state-on-navigation.html:
* editing/selection/character-granularity-rect.html:
Delay checking for secure input state and caret rects until after the next presentation update.
* editing/selection/ios/absolute-selection-after-scroll-expected.txt:
* editing/selection/ios/absolute-selection-after-scroll.html:
* editing/selection/ios/fixed-selection-after-scroll-expected.txt:
* editing/selection/ios/fixed-selection-after-scroll.html:
Refactor and simplify these tests. These tests are not run on the OpenSource bots, since they depend on long
press and tap gestures.
* platform/ios-wk2/editing/inserting/insert-div-024-expected.txt:
* platform/ios-wk2/editing/inserting/insert-div-026-expected.txt:
* platform/ios-wk2/editing/style/5084241-expected.txt:
Rebaselines these tests, removing an anonymous RenderBlock inserted as a result of inserting and removing a
dummy span in order to compute a RenderStyle in WebPage::editorState. This is because editorState is no longer
invoked immediately on page load; https://bugs.webkit.org/show_bug.cgi?id=175116 tracks preventing this render
tree thrashing altogether.
* platform/mac-wk2/TestExpectations:
* platform/mac-wk2/editing/style/unbold-in-bold-expected.txt:
* resources/ui-helper.js:
Introduce new UIHelper functions.
(window.UIHelper.ensurePresentationUpdate.return.new.Promise):
(window.UIHelper.ensurePresentationUpdate):
Returns a Promise, resolved after the next presentation update.
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise):
(window.UIHelper.activateAndWaitForInputSessionAt):
Returns a Promise, resolved after tapping at the given location and waiting for the keyboard to appear on iOS.
(window.UIHelper.getUICaretRect.return.new.Promise.):
(window.UIHelper.getUICaretRect.return.new.Promise):
(window.UIHelper.getUICaretRect):
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
Helpers to fetch selection and caret rect information in the UI process.
Canonical link: https://commits.webkit.org/192519@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221064 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-23 03:15:38 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(function() {
|
|
|
|
uiController.doAfterNextStablePresentationUpdate(function() {
|
|
|
|
uiController.uiScriptComplete(JSON.stringify(uiController.textSelectionCaretRect));
|
|
|
|
});
|
|
|
|
})()`, jsonString => {
|
|
|
|
resolve(JSON.parse(jsonString));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static getUISelectionRects()
|
[iOS] Do not show selection UI for editable elements with opacity near zero
https://bugs.webkit.org/show_bug.cgi?id=191442
<rdar://problem/45958625>
Reviewed by Simon Fraser.
Source/WebCore:
Tests: editing/selection/ios/do-not-zoom-to-focused-hidden-contenteditable.html
editing/selection/ios/hide-selection-after-hiding-contenteditable.html
editing/selection/ios/hide-selection-in-contenteditable-nested-transparency.html
editing/selection/ios/hide-selection-in-hidden-contenteditable-frame.html
editing/selection/ios/hide-selection-in-hidden-contenteditable.html
* rendering/RenderObject.cpp:
(WebCore::RenderObject::isTransparentRespectingParentFrames const):
Add a helper function to determine whether a RenderObject is contained within a transparent layer, taking parent
frames into account. A layer is considered transparent if its opacity is less than a small threshold (i.e. 0.01).
Opacity on ancestor elements is applied multiplicatively.
* rendering/RenderObject.h:
Source/WebKit:
Add support for suppressing native selection UI (for instance, selection highlight views, selection handles, and
selection-related gestures) when the selection is inside a transparent editable element. This helps maintain
compatibility with text editors that work by capturing key events and input events hidden contenteditable
elements, and reflect these changes in different document or different part of the document.
Since selection UI is rendered in the UI process on iOS using element geometry propagated from the web process,
selection rendering is entirely decoupled from the process of painting in the web process. This means that if
the editable root has an opacity of 0, we would correctly hide the caret and selection on macOS, but draw over
the transparent element on iOS. When these hidden editable elements are focused, this often results in unwanted
behaviors, such as double caret painting, native and custom selection UI from the page being drawn on top of one
another, and the ability to change selection via tap and loupe gestures within hidden text.
To fix this, we compute whether the focused element is transparent when an element is focused, or when the
selection changes, and send this information over to the UI process via `AssistedNodeInformation` and
`EditorState`. In the UI process, we then respect this information by suppressing the selection assistant if the
focused element is transparent; this disables showing and laying out selection views, as well as gestures
associated with selection overlays. However, this still allows for contextual autocorrection and spell checking.
* Shared/AssistedNodeInformation.cpp:
(WebKit::AssistedNodeInformation::encode const):
(WebKit::AssistedNodeInformation::decode):
* Shared/AssistedNodeInformation.h:
* Shared/EditorState.cpp:
(WebKit::EditorState::PostLayoutData::encode const):
(WebKit::EditorState::PostLayoutData::decode):
* Shared/EditorState.h:
Add `elementIsTransparent` flags, and also add boilerplate IPC code.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _displayFormNodeInputView]):
Prevent zooming to the focused element if the focused element is hidden.
(-[WKContentView hasSelectablePositionAtPoint:]):
(-[WKContentView pointIsNearMarkedText:]):
(-[WKContentView textInteractionGesture:shouldBeginAtPoint:]):
Don't allow these text interaction gestures to begin while suppressing the selection assistant.
(-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
When an element is focused, begin suppressing the selection assistant if the element is fully transparent.
(-[WKContentView _stopAssistingNode]):
When the focused element is blurred, reset state by ending selection assistant suppression (additionally
reactivating the selection assistant if needed). This ensures that selection in non-editable text isn't broken
after focusing a hidden editable element.
(-[WKContentView _updateChangedSelection:]):
If needed, suppress or un-suppress the selection assistant when the selection changes. On certain rich text
editors, a combination of custom selection UI and native selection UI is used. For instance, on Microsoft Office
365, caret selections are rendered using the native caret view, but as soon as the selection becomes ranged, the
editable root becomes fully transparent, and Office's selection UI takes over.
(-[WKContentView _shouldSuppressSelectionCommands]):
Override this UIKit SPI hook to suppress selection commands (e.g. the callout bar) when suppressing the
selection assistant.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::getAssistedNodeInformation):
Compute and set `elementIsTransparent` using the assisted node.
Tools:
Add a couple of new testing helpers to UIScriptController.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::textSelectionRangeRects const):
(WTR::UIScriptController::selectionCaretViewRect const):
(WTR::UIScriptController::selectionRangeViewRects const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::textSelectionRangeRects const):
Rename `selectionRangeViewRects` to `textSelectionRangeRects`. This allows us to draw a distinction between
`textSelectionRangeRects`/`textSelectionCaretRect`, which retrieve information about selection rects known
to the text interaction assistant, and `selectionCaretViewRect`/`selectionRangeViewRects`, which retrieve the
actual frames of the selection views used to draw overlaid selection UI. This difference is important in the
new layout tests added in this patch, which only suppress caret rendering (i.e. selection views remain hidden).
Also, drive-by fix a leaked `NSMutableArray`.
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
(WTR::UIScriptController::selectionCaretViewRect const):
(WTR::UIScriptController::selectionRangeViewRects const):
Testing helpers to grab the frames of caret and selection views, in WKContentView's coordinate space. These
rects are also clamped to WKContentView bounds.
LayoutTests:
Add 5 new layout tests. See below for more details.
* editing/selection/character-granularity-rect.html:
Adjust for a renamed UIScriptController function.
* editing/selection/ios/do-not-zoom-to-focused-hidden-contenteditable-expected.txt: Added.
* editing/selection/ios/do-not-zoom-to-focused-hidden-contenteditable.html: Added.
Add a test to verify that we don't zoom to fit the focused element, if the focused element is completely
transparent.
* editing/selection/ios/hide-selection-after-hiding-contenteditable-expected.txt: Added.
* editing/selection/ios/hide-selection-after-hiding-contenteditable.html: Added.
Add a test to verify that selection UI is hidden after making an editable root transparent, and shown again when
the editable root becomes opaque.
* editing/selection/ios/hide-selection-in-contenteditable-nested-transparency-expected.txt: Added.
* editing/selection/ios/hide-selection-in-contenteditable-nested-transparency.html: Added.
Add a test to verify that transparency applied on an editable root via nested transparent containers causes
selection UI to be suppressed.
* editing/selection/ios/hide-selection-in-hidden-contenteditable-expected.txt: Added.
* editing/selection/ios/hide-selection-in-hidden-contenteditable-frame-expected.txt: Added.
* editing/selection/ios/hide-selection-in-hidden-contenteditable-frame.html: Added.
Add a test to verify that selection UI is suppressed when an editable element inside a subframe is focused. This
test checks that the caret, selection rects and selection handle views are not shown, and additionally verifies
that the selection in a hidden contenteditable area cannot be changed via tap gesture.
* editing/selection/ios/hide-selection-in-hidden-contenteditable.html: Added.
Same test as above, but in a regular editable element in the main document instead of a subframe.
* resources/ui-helper.js:
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
(window.UIHelper.getUICaretViewRect.return.new.Promise.):
(window.UIHelper.getUICaretViewRect.return.new.Promise):
(window.UIHelper.getUICaretViewRect):
Add new UIHelper wrapper methods. See Tools/ChangeLog for more detail.
Canonical link: https://commits.webkit.org/206355@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238146 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-11-13 22:30:27 +00:00
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
[iOS] Do not show selection UI for editable elements with opacity near zero
https://bugs.webkit.org/show_bug.cgi?id=191442
<rdar://problem/45958625>
Reviewed by Simon Fraser.
Source/WebCore:
Tests: editing/selection/ios/do-not-zoom-to-focused-hidden-contenteditable.html
editing/selection/ios/hide-selection-after-hiding-contenteditable.html
editing/selection/ios/hide-selection-in-contenteditable-nested-transparency.html
editing/selection/ios/hide-selection-in-hidden-contenteditable-frame.html
editing/selection/ios/hide-selection-in-hidden-contenteditable.html
* rendering/RenderObject.cpp:
(WebCore::RenderObject::isTransparentRespectingParentFrames const):
Add a helper function to determine whether a RenderObject is contained within a transparent layer, taking parent
frames into account. A layer is considered transparent if its opacity is less than a small threshold (i.e. 0.01).
Opacity on ancestor elements is applied multiplicatively.
* rendering/RenderObject.h:
Source/WebKit:
Add support for suppressing native selection UI (for instance, selection highlight views, selection handles, and
selection-related gestures) when the selection is inside a transparent editable element. This helps maintain
compatibility with text editors that work by capturing key events and input events hidden contenteditable
elements, and reflect these changes in different document or different part of the document.
Since selection UI is rendered in the UI process on iOS using element geometry propagated from the web process,
selection rendering is entirely decoupled from the process of painting in the web process. This means that if
the editable root has an opacity of 0, we would correctly hide the caret and selection on macOS, but draw over
the transparent element on iOS. When these hidden editable elements are focused, this often results in unwanted
behaviors, such as double caret painting, native and custom selection UI from the page being drawn on top of one
another, and the ability to change selection via tap and loupe gestures within hidden text.
To fix this, we compute whether the focused element is transparent when an element is focused, or when the
selection changes, and send this information over to the UI process via `AssistedNodeInformation` and
`EditorState`. In the UI process, we then respect this information by suppressing the selection assistant if the
focused element is transparent; this disables showing and laying out selection views, as well as gestures
associated with selection overlays. However, this still allows for contextual autocorrection and spell checking.
* Shared/AssistedNodeInformation.cpp:
(WebKit::AssistedNodeInformation::encode const):
(WebKit::AssistedNodeInformation::decode):
* Shared/AssistedNodeInformation.h:
* Shared/EditorState.cpp:
(WebKit::EditorState::PostLayoutData::encode const):
(WebKit::EditorState::PostLayoutData::decode):
* Shared/EditorState.h:
Add `elementIsTransparent` flags, and also add boilerplate IPC code.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _displayFormNodeInputView]):
Prevent zooming to the focused element if the focused element is hidden.
(-[WKContentView hasSelectablePositionAtPoint:]):
(-[WKContentView pointIsNearMarkedText:]):
(-[WKContentView textInteractionGesture:shouldBeginAtPoint:]):
Don't allow these text interaction gestures to begin while suppressing the selection assistant.
(-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
When an element is focused, begin suppressing the selection assistant if the element is fully transparent.
(-[WKContentView _stopAssistingNode]):
When the focused element is blurred, reset state by ending selection assistant suppression (additionally
reactivating the selection assistant if needed). This ensures that selection in non-editable text isn't broken
after focusing a hidden editable element.
(-[WKContentView _updateChangedSelection:]):
If needed, suppress or un-suppress the selection assistant when the selection changes. On certain rich text
editors, a combination of custom selection UI and native selection UI is used. For instance, on Microsoft Office
365, caret selections are rendered using the native caret view, but as soon as the selection becomes ranged, the
editable root becomes fully transparent, and Office's selection UI takes over.
(-[WKContentView _shouldSuppressSelectionCommands]):
Override this UIKit SPI hook to suppress selection commands (e.g. the callout bar) when suppressing the
selection assistant.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::getAssistedNodeInformation):
Compute and set `elementIsTransparent` using the assisted node.
Tools:
Add a couple of new testing helpers to UIScriptController.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::textSelectionRangeRects const):
(WTR::UIScriptController::selectionCaretViewRect const):
(WTR::UIScriptController::selectionRangeViewRects const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::textSelectionRangeRects const):
Rename `selectionRangeViewRects` to `textSelectionRangeRects`. This allows us to draw a distinction between
`textSelectionRangeRects`/`textSelectionCaretRect`, which retrieve information about selection rects known
to the text interaction assistant, and `selectionCaretViewRect`/`selectionRangeViewRects`, which retrieve the
actual frames of the selection views used to draw overlaid selection UI. This difference is important in the
new layout tests added in this patch, which only suppress caret rendering (i.e. selection views remain hidden).
Also, drive-by fix a leaked `NSMutableArray`.
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
(WTR::UIScriptController::selectionCaretViewRect const):
(WTR::UIScriptController::selectionRangeViewRects const):
Testing helpers to grab the frames of caret and selection views, in WKContentView's coordinate space. These
rects are also clamped to WKContentView bounds.
LayoutTests:
Add 5 new layout tests. See below for more details.
* editing/selection/character-granularity-rect.html:
Adjust for a renamed UIScriptController function.
* editing/selection/ios/do-not-zoom-to-focused-hidden-contenteditable-expected.txt: Added.
* editing/selection/ios/do-not-zoom-to-focused-hidden-contenteditable.html: Added.
Add a test to verify that we don't zoom to fit the focused element, if the focused element is completely
transparent.
* editing/selection/ios/hide-selection-after-hiding-contenteditable-expected.txt: Added.
* editing/selection/ios/hide-selection-after-hiding-contenteditable.html: Added.
Add a test to verify that selection UI is hidden after making an editable root transparent, and shown again when
the editable root becomes opaque.
* editing/selection/ios/hide-selection-in-contenteditable-nested-transparency-expected.txt: Added.
* editing/selection/ios/hide-selection-in-contenteditable-nested-transparency.html: Added.
Add a test to verify that transparency applied on an editable root via nested transparent containers causes
selection UI to be suppressed.
* editing/selection/ios/hide-selection-in-hidden-contenteditable-expected.txt: Added.
* editing/selection/ios/hide-selection-in-hidden-contenteditable-frame-expected.txt: Added.
* editing/selection/ios/hide-selection-in-hidden-contenteditable-frame.html: Added.
Add a test to verify that selection UI is suppressed when an editable element inside a subframe is focused. This
test checks that the caret, selection rects and selection handle views are not shown, and additionally verifies
that the selection in a hidden contenteditable area cannot be changed via tap gesture.
* editing/selection/ios/hide-selection-in-hidden-contenteditable.html: Added.
Same test as above, but in a regular editable element in the main document instead of a subframe.
* resources/ui-helper.js:
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
(window.UIHelper.getUICaretViewRect.return.new.Promise.):
(window.UIHelper.getUICaretViewRect.return.new.Promise):
(window.UIHelper.getUICaretViewRect):
Add new UIHelper wrapper methods. See Tools/ChangeLog for more detail.
Canonical link: https://commits.webkit.org/206355@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238146 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-11-13 22:30:27 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(function() {
|
|
|
|
uiController.doAfterNextStablePresentationUpdate(function() {
|
|
|
|
uiController.uiScriptComplete(JSON.stringify(uiController.textSelectionRangeRects));
|
|
|
|
});
|
|
|
|
})()`, jsonString => {
|
|
|
|
resolve(JSON.parse(jsonString));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static getUICaretViewRect()
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
[iOS] Do not show selection UI for editable elements with opacity near zero
https://bugs.webkit.org/show_bug.cgi?id=191442
<rdar://problem/45958625>
Reviewed by Simon Fraser.
Source/WebCore:
Tests: editing/selection/ios/do-not-zoom-to-focused-hidden-contenteditable.html
editing/selection/ios/hide-selection-after-hiding-contenteditable.html
editing/selection/ios/hide-selection-in-contenteditable-nested-transparency.html
editing/selection/ios/hide-selection-in-hidden-contenteditable-frame.html
editing/selection/ios/hide-selection-in-hidden-contenteditable.html
* rendering/RenderObject.cpp:
(WebCore::RenderObject::isTransparentRespectingParentFrames const):
Add a helper function to determine whether a RenderObject is contained within a transparent layer, taking parent
frames into account. A layer is considered transparent if its opacity is less than a small threshold (i.e. 0.01).
Opacity on ancestor elements is applied multiplicatively.
* rendering/RenderObject.h:
Source/WebKit:
Add support for suppressing native selection UI (for instance, selection highlight views, selection handles, and
selection-related gestures) when the selection is inside a transparent editable element. This helps maintain
compatibility with text editors that work by capturing key events and input events hidden contenteditable
elements, and reflect these changes in different document or different part of the document.
Since selection UI is rendered in the UI process on iOS using element geometry propagated from the web process,
selection rendering is entirely decoupled from the process of painting in the web process. This means that if
the editable root has an opacity of 0, we would correctly hide the caret and selection on macOS, but draw over
the transparent element on iOS. When these hidden editable elements are focused, this often results in unwanted
behaviors, such as double caret painting, native and custom selection UI from the page being drawn on top of one
another, and the ability to change selection via tap and loupe gestures within hidden text.
To fix this, we compute whether the focused element is transparent when an element is focused, or when the
selection changes, and send this information over to the UI process via `AssistedNodeInformation` and
`EditorState`. In the UI process, we then respect this information by suppressing the selection assistant if the
focused element is transparent; this disables showing and laying out selection views, as well as gestures
associated with selection overlays. However, this still allows for contextual autocorrection and spell checking.
* Shared/AssistedNodeInformation.cpp:
(WebKit::AssistedNodeInformation::encode const):
(WebKit::AssistedNodeInformation::decode):
* Shared/AssistedNodeInformation.h:
* Shared/EditorState.cpp:
(WebKit::EditorState::PostLayoutData::encode const):
(WebKit::EditorState::PostLayoutData::decode):
* Shared/EditorState.h:
Add `elementIsTransparent` flags, and also add boilerplate IPC code.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _displayFormNodeInputView]):
Prevent zooming to the focused element if the focused element is hidden.
(-[WKContentView hasSelectablePositionAtPoint:]):
(-[WKContentView pointIsNearMarkedText:]):
(-[WKContentView textInteractionGesture:shouldBeginAtPoint:]):
Don't allow these text interaction gestures to begin while suppressing the selection assistant.
(-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
When an element is focused, begin suppressing the selection assistant if the element is fully transparent.
(-[WKContentView _stopAssistingNode]):
When the focused element is blurred, reset state by ending selection assistant suppression (additionally
reactivating the selection assistant if needed). This ensures that selection in non-editable text isn't broken
after focusing a hidden editable element.
(-[WKContentView _updateChangedSelection:]):
If needed, suppress or un-suppress the selection assistant when the selection changes. On certain rich text
editors, a combination of custom selection UI and native selection UI is used. For instance, on Microsoft Office
365, caret selections are rendered using the native caret view, but as soon as the selection becomes ranged, the
editable root becomes fully transparent, and Office's selection UI takes over.
(-[WKContentView _shouldSuppressSelectionCommands]):
Override this UIKit SPI hook to suppress selection commands (e.g. the callout bar) when suppressing the
selection assistant.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::getAssistedNodeInformation):
Compute and set `elementIsTransparent` using the assisted node.
Tools:
Add a couple of new testing helpers to UIScriptController.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::textSelectionRangeRects const):
(WTR::UIScriptController::selectionCaretViewRect const):
(WTR::UIScriptController::selectionRangeViewRects const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::textSelectionRangeRects const):
Rename `selectionRangeViewRects` to `textSelectionRangeRects`. This allows us to draw a distinction between
`textSelectionRangeRects`/`textSelectionCaretRect`, which retrieve information about selection rects known
to the text interaction assistant, and `selectionCaretViewRect`/`selectionRangeViewRects`, which retrieve the
actual frames of the selection views used to draw overlaid selection UI. This difference is important in the
new layout tests added in this patch, which only suppress caret rendering (i.e. selection views remain hidden).
Also, drive-by fix a leaked `NSMutableArray`.
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
(WTR::UIScriptController::selectionCaretViewRect const):
(WTR::UIScriptController::selectionRangeViewRects const):
Testing helpers to grab the frames of caret and selection views, in WKContentView's coordinate space. These
rects are also clamped to WKContentView bounds.
LayoutTests:
Add 5 new layout tests. See below for more details.
* editing/selection/character-granularity-rect.html:
Adjust for a renamed UIScriptController function.
* editing/selection/ios/do-not-zoom-to-focused-hidden-contenteditable-expected.txt: Added.
* editing/selection/ios/do-not-zoom-to-focused-hidden-contenteditable.html: Added.
Add a test to verify that we don't zoom to fit the focused element, if the focused element is completely
transparent.
* editing/selection/ios/hide-selection-after-hiding-contenteditable-expected.txt: Added.
* editing/selection/ios/hide-selection-after-hiding-contenteditable.html: Added.
Add a test to verify that selection UI is hidden after making an editable root transparent, and shown again when
the editable root becomes opaque.
* editing/selection/ios/hide-selection-in-contenteditable-nested-transparency-expected.txt: Added.
* editing/selection/ios/hide-selection-in-contenteditable-nested-transparency.html: Added.
Add a test to verify that transparency applied on an editable root via nested transparent containers causes
selection UI to be suppressed.
* editing/selection/ios/hide-selection-in-hidden-contenteditable-expected.txt: Added.
* editing/selection/ios/hide-selection-in-hidden-contenteditable-frame-expected.txt: Added.
* editing/selection/ios/hide-selection-in-hidden-contenteditable-frame.html: Added.
Add a test to verify that selection UI is suppressed when an editable element inside a subframe is focused. This
test checks that the caret, selection rects and selection handle views are not shown, and additionally verifies
that the selection in a hidden contenteditable area cannot be changed via tap gesture.
* editing/selection/ios/hide-selection-in-hidden-contenteditable.html: Added.
Same test as above, but in a regular editable element in the main document instead of a subframe.
* resources/ui-helper.js:
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
(window.UIHelper.getUICaretViewRect.return.new.Promise.):
(window.UIHelper.getUICaretViewRect.return.new.Promise):
(window.UIHelper.getUICaretViewRect):
Add new UIHelper wrapper methods. See Tools/ChangeLog for more detail.
Canonical link: https://commits.webkit.org/206355@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238146 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-11-13 22:30:27 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(function() {
|
|
|
|
uiController.doAfterNextStablePresentationUpdate(function() {
|
|
|
|
uiController.uiScriptComplete(JSON.stringify(uiController.selectionCaretViewRect));
|
|
|
|
});
|
|
|
|
})()`, jsonString => {
|
|
|
|
resolve(JSON.parse(jsonString));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static getUISelectionViewRects()
|
[WK2] EditorState updates should be rolled into the layer update lifecycle when possible
https://bugs.webkit.org/show_bug.cgi?id=175370
<rdar://problem/33799806>
Reviewed by Ryosuke Niwa.
Source/WebCore:
Remove didChangeSelectionAndUpdateLayout -- EditorState updates that are scheduled due to missing post-layout
data will now be scheduled for the next presentation update. Additionally, add editor client hooks to notify the
WebKit layer when we've updated the current composition. See WebKit ChangeLog for more details. This patch
adjusts and rebaselines existing layout tests.
* editing/Editor.cpp:
(WebCore::SetCompositionScope::SetCompositionScope):
(WebCore::SetCompositionScope::~SetCompositionScope):
Introduce a helper RAII class to ensure that we ignore selection changes during the scope of
Editor::setComposition and call out to the client with WebEditorClient::didUpdateComposition afterwards. This
also maintains a UserTypingGestureIndicator over its lifetime, so we don't additionally need to create a
UserTypingGestureIndicator in Editor::setComposition.
(WebCore::Editor::setComposition):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::setSelection):
(WebCore::FrameSelection::updateAndRevealSelection):
(WebCore::FrameSelection::setSelectedRange):
* editing/FrameSelection.h:
(WebCore::FrameSelection::defaultSetSelectionOptions):
Plumb state about whether or not the selection change was triggered by the user to FrameSelection::setSelection,
and if so, notify the editing client. A separate SetSelectionOptions flag is used here instead of
RevealSelection to avoid calling out to the client in places where we want to reveal the selection regardless of
whether or not the selection is user triggered.
* loader/EmptyClients.cpp:
* page/EditorClient.h:
Source/WebKit:
See per-method comments for more detail. WebPage::didChangeSelection now schedules EditorState updates to be sent
during the next layer tree transaction rather than sending them synchronously. To ensure that iOS and Mac continue
to behave correctly w.r.t. EditorState updates, we immediately dispatch EditorStates in the following cases:
- After the composition changes, is confirmed, or is canceled.
- After an edit command is executed.
- After ending user-triggered selection changes.
* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::hasEditorState const):
(WebKit::RemoteLayerTreeTransaction::editorState const):
(WebKit::RemoteLayerTreeTransaction::setEditorState):
Attaches an optional EditorState to the RemoteLayerTreeTransaction. This EditorState is computed and sent over
when setting up the transaction in WebPage, if something previously scheduled an EditorState update.
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode const):
(WebKit::RemoteLayerTreeTransaction::decode):
Add coder support for sending over a layer tree transaction's EditorState.
* UIProcess/API/Cocoa/WKViewPrivate.h:
* UIProcess/API/mac/WKView.mm:
(-[WKView _doAfterNextPresentationUpdate:]):
Add _doAfterNextPresentationUpdate to WKView (used in TestWebKitAPI -- refer to
WebKitAgnosticTest::waitForNextPresentationUpdate).
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
* UIProcess/DrawingAreaProxy.messages.in:
Add a new IPC messages, DispatchPresentationCallbacksAfterFlushingLayers, to invoke in-flight presentation
callbacks in the UI process following a layer flush in the web process.
* UIProcess/WebPageProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h:
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::~TiledCoreAnimationDrawingAreaProxy):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
Run all pending _doAfterNextPresentationUpdate callbacks.
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::didApplyStyle):
(WebKit::WebEditorClient::respondToChangedContents):
(WebKit::WebEditorClient::didEndUserTriggeredSelectionChanges):
(WebKit::WebEditorClient::didUpdateComposition):
Forward editor client calls to the WebPage.
(WebKit::WebEditorClient::didChangeSelectionAndUpdateLayout): Deleted.
* WebProcess/WebCoreSupport/WebEditorClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::editorState const):
(WebKit::WebPage::updateEditorStateAfterLayoutIfEditabilityChanged):
(WebKit::WebPage::willCommitLayerTree):
(WebKit::WebPage::didApplyStyle):
Allow style application to immediately trigger EditorState updates, if we're not currently ignoring selection
changes in the Editor.
(WebKit::WebPage::didChangeContents):
Allow applying top-level edit commands to immediately trigger EditorState updates, if we're not currently
ignoring selection changes in the Editor.
(WebKit::WebPage::didChangeSelection):
(WebKit::WebPage::didUpdateComposition):
(WebKit::WebPage::didEndUserTriggeredSelectionChanges):
(WebKit::WebPage::discardedComposition):
(WebKit::WebPage::canceledComposition):
When handling composition updates, always send an EditorState to the UI process. Unlike other cases, IME
requires immediate EditorState data, so we need to be explicit here in sending updates right away.
(WebKit::WebPage::sendEditorStateUpdate):
(WebKit::WebPage::sendPartialEditorStateAndSchedulePostLayoutUpdate):
(WebKit::WebPage::flushPendingEditorStateUpdate):
Helper methods to schedule an EditorState update to be sent upon the next layer tree update, or flush any
pending EditorState update that has been scheduled. The private, more aggressive variant of this is
sendEditorStateUpdate, which ignores whether or not there was already an EditorState update scheduled, and sends
one anyways (this still fulfills any EditorState update that was previously scheduled).
These helper methods are treated as no-ops when invoked while ignoring selection changes. This is to prevent
temporary selection state and editor commands during operations such as text indicator snapshotting from pushing
bogus information about transient editor states to the UI process.
(WebKit::WebPage::sendPostLayoutEditorStateIfNeeded): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::executeEditCommandWithCallback):
(WebKit::selectionIsInsideFixedPositionContainer):
(WebKit::WebPage::updateVisibleContentRects):
Fix a hack that was computing an EditorState to figure out whether the current selection starts or ends in a
fixed position container. Factors out relevant logic into a separate helper, and also schedules an EditorState
update instead of immediately computing it.
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::addTransactionCallbackID):
Add support for registering and dispatching presentation callbacks that hook into the layer flush lifecycle,
using the tiled CA drawing area. These are used by Mac LayoutTests and API tests that need to wait until the
next flush before checking for state that depends on EditorState updates in the UI process.
(WebKit::TiledCoreAnimationDrawingArea::flushLayers):
Tell the WebPage to flush any pending EditorState updates.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState const):
Source/WebKitLegacy/mac:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Source/WebKitLegacy/win:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Tools:
Tweaks API tests that involve editing to wait for a presentation update before checking against UI process-side
information sent via EditorState updates. This allows any EditorState update scheduled by the test to propagate
to the UI process.
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewCandidateTests.mm:
(-[CandidateTestWebView typeString:inputMessage:]):
(+[CandidateTestWebView setUpWithFrame:testPage:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewTextInput.mm:
* TestWebKitAPI/Tests/mac/AcceptsFirstMouse.mm:
(TestWebKitAPI::AcceptsFirstMouse::runTest):
* TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm:
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView waitForNextPresentationUpdate]):
Add a new helper method to spin until the next presentation update.
* TestWebKitAPI/mac/WebKitAgnosticTest.h:
* TestWebKitAPI/mac/WebKitAgnosticTest.mm:
(TestWebKitAPI::WebKitAgnosticTest::waitForNextPresentationUpdate):
LayoutTests:
Rebaseline and adjust LayoutTests.
* editing/caret/ios/absolute-caret-position-after-scroll-expected.txt:
* editing/caret/ios/absolute-caret-position-after-scroll.html:
* editing/caret/ios/fixed-caret-position-after-scroll-expected.txt:
* editing/caret/ios/fixed-caret-position-after-scroll.html:
* editing/secure-input/password-input-changed-type.html:
* editing/secure-input/password-input-focusing.html:
* editing/secure-input/removed-password-input.html:
* editing/secure-input/reset-state-on-navigation.html:
* editing/selection/character-granularity-rect.html:
Delay checking for secure input state and caret rects until after the next presentation update.
* editing/selection/ios/absolute-selection-after-scroll-expected.txt:
* editing/selection/ios/absolute-selection-after-scroll.html:
* editing/selection/ios/fixed-selection-after-scroll-expected.txt:
* editing/selection/ios/fixed-selection-after-scroll.html:
Refactor and simplify these tests. These tests are not run on the OpenSource bots, since they depend on long
press and tap gestures.
* platform/ios-wk2/editing/inserting/insert-div-024-expected.txt:
* platform/ios-wk2/editing/inserting/insert-div-026-expected.txt:
* platform/ios-wk2/editing/style/5084241-expected.txt:
Rebaselines these tests, removing an anonymous RenderBlock inserted as a result of inserting and removing a
dummy span in order to compute a RenderStyle in WebPage::editorState. This is because editorState is no longer
invoked immediately on page load; https://bugs.webkit.org/show_bug.cgi?id=175116 tracks preventing this render
tree thrashing altogether.
* platform/mac-wk2/TestExpectations:
* platform/mac-wk2/editing/style/unbold-in-bold-expected.txt:
* resources/ui-helper.js:
Introduce new UIHelper functions.
(window.UIHelper.ensurePresentationUpdate.return.new.Promise):
(window.UIHelper.ensurePresentationUpdate):
Returns a Promise, resolved after the next presentation update.
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise):
(window.UIHelper.activateAndWaitForInputSessionAt):
Returns a Promise, resolved after tapping at the given location and waiting for the keyboard to appear on iOS.
(window.UIHelper.getUICaretRect.return.new.Promise.):
(window.UIHelper.getUICaretRect.return.new.Promise):
(window.UIHelper.getUICaretRect):
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
Helpers to fetch selection and caret rect information in the UI process.
Canonical link: https://commits.webkit.org/192519@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221064 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-23 03:15:38 +00:00
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
[WK2] EditorState updates should be rolled into the layer update lifecycle when possible
https://bugs.webkit.org/show_bug.cgi?id=175370
<rdar://problem/33799806>
Reviewed by Ryosuke Niwa.
Source/WebCore:
Remove didChangeSelectionAndUpdateLayout -- EditorState updates that are scheduled due to missing post-layout
data will now be scheduled for the next presentation update. Additionally, add editor client hooks to notify the
WebKit layer when we've updated the current composition. See WebKit ChangeLog for more details. This patch
adjusts and rebaselines existing layout tests.
* editing/Editor.cpp:
(WebCore::SetCompositionScope::SetCompositionScope):
(WebCore::SetCompositionScope::~SetCompositionScope):
Introduce a helper RAII class to ensure that we ignore selection changes during the scope of
Editor::setComposition and call out to the client with WebEditorClient::didUpdateComposition afterwards. This
also maintains a UserTypingGestureIndicator over its lifetime, so we don't additionally need to create a
UserTypingGestureIndicator in Editor::setComposition.
(WebCore::Editor::setComposition):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::setSelection):
(WebCore::FrameSelection::updateAndRevealSelection):
(WebCore::FrameSelection::setSelectedRange):
* editing/FrameSelection.h:
(WebCore::FrameSelection::defaultSetSelectionOptions):
Plumb state about whether or not the selection change was triggered by the user to FrameSelection::setSelection,
and if so, notify the editing client. A separate SetSelectionOptions flag is used here instead of
RevealSelection to avoid calling out to the client in places where we want to reveal the selection regardless of
whether or not the selection is user triggered.
* loader/EmptyClients.cpp:
* page/EditorClient.h:
Source/WebKit:
See per-method comments for more detail. WebPage::didChangeSelection now schedules EditorState updates to be sent
during the next layer tree transaction rather than sending them synchronously. To ensure that iOS and Mac continue
to behave correctly w.r.t. EditorState updates, we immediately dispatch EditorStates in the following cases:
- After the composition changes, is confirmed, or is canceled.
- After an edit command is executed.
- After ending user-triggered selection changes.
* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::hasEditorState const):
(WebKit::RemoteLayerTreeTransaction::editorState const):
(WebKit::RemoteLayerTreeTransaction::setEditorState):
Attaches an optional EditorState to the RemoteLayerTreeTransaction. This EditorState is computed and sent over
when setting up the transaction in WebPage, if something previously scheduled an EditorState update.
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode const):
(WebKit::RemoteLayerTreeTransaction::decode):
Add coder support for sending over a layer tree transaction's EditorState.
* UIProcess/API/Cocoa/WKViewPrivate.h:
* UIProcess/API/mac/WKView.mm:
(-[WKView _doAfterNextPresentationUpdate:]):
Add _doAfterNextPresentationUpdate to WKView (used in TestWebKitAPI -- refer to
WebKitAgnosticTest::waitForNextPresentationUpdate).
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
* UIProcess/DrawingAreaProxy.messages.in:
Add a new IPC messages, DispatchPresentationCallbacksAfterFlushingLayers, to invoke in-flight presentation
callbacks in the UI process following a layer flush in the web process.
* UIProcess/WebPageProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h:
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::~TiledCoreAnimationDrawingAreaProxy):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers):
Run all pending _doAfterNextPresentationUpdate callbacks.
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::didApplyStyle):
(WebKit::WebEditorClient::respondToChangedContents):
(WebKit::WebEditorClient::didEndUserTriggeredSelectionChanges):
(WebKit::WebEditorClient::didUpdateComposition):
Forward editor client calls to the WebPage.
(WebKit::WebEditorClient::didChangeSelectionAndUpdateLayout): Deleted.
* WebProcess/WebCoreSupport/WebEditorClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::editorState const):
(WebKit::WebPage::updateEditorStateAfterLayoutIfEditabilityChanged):
(WebKit::WebPage::willCommitLayerTree):
(WebKit::WebPage::didApplyStyle):
Allow style application to immediately trigger EditorState updates, if we're not currently ignoring selection
changes in the Editor.
(WebKit::WebPage::didChangeContents):
Allow applying top-level edit commands to immediately trigger EditorState updates, if we're not currently
ignoring selection changes in the Editor.
(WebKit::WebPage::didChangeSelection):
(WebKit::WebPage::didUpdateComposition):
(WebKit::WebPage::didEndUserTriggeredSelectionChanges):
(WebKit::WebPage::discardedComposition):
(WebKit::WebPage::canceledComposition):
When handling composition updates, always send an EditorState to the UI process. Unlike other cases, IME
requires immediate EditorState data, so we need to be explicit here in sending updates right away.
(WebKit::WebPage::sendEditorStateUpdate):
(WebKit::WebPage::sendPartialEditorStateAndSchedulePostLayoutUpdate):
(WebKit::WebPage::flushPendingEditorStateUpdate):
Helper methods to schedule an EditorState update to be sent upon the next layer tree update, or flush any
pending EditorState update that has been scheduled. The private, more aggressive variant of this is
sendEditorStateUpdate, which ignores whether or not there was already an EditorState update scheduled, and sends
one anyways (this still fulfills any EditorState update that was previously scheduled).
These helper methods are treated as no-ops when invoked while ignoring selection changes. This is to prevent
temporary selection state and editor commands during operations such as text indicator snapshotting from pushing
bogus information about transient editor states to the UI process.
(WebKit::WebPage::sendPostLayoutEditorStateIfNeeded): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::executeEditCommandWithCallback):
(WebKit::selectionIsInsideFixedPositionContainer):
(WebKit::WebPage::updateVisibleContentRects):
Fix a hack that was computing an EditorState to figure out whether the current selection starts or ends in a
fixed position container. Factors out relevant logic into a separate helper, and also schedules an EditorState
update instead of immediately computing it.
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::addTransactionCallbackID):
Add support for registering and dispatching presentation callbacks that hook into the layer flush lifecycle,
using the tiled CA drawing area. These are used by Mac LayoutTests and API tests that need to wait until the
next flush before checking for state that depends on EditorState updates in the UI process.
(WebKit::TiledCoreAnimationDrawingArea::flushLayers):
Tell the WebPage to flush any pending EditorState updates.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState const):
Source/WebKitLegacy/mac:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Source/WebKitLegacy/win:
Adjust WebEditorClient for interface changes.
* WebCoreSupport/WebEditorClient.h:
Tools:
Tweaks API tests that involve editing to wait for a presentation update before checking against UI process-side
information sent via EditorState updates. This allows any EditorState update scheduled by the test to propagate
to the UI process.
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewCandidateTests.mm:
(-[CandidateTestWebView typeString:inputMessage:]):
(+[CandidateTestWebView setUpWithFrame:testPage:]):
* TestWebKitAPI/Tests/WebKit2Cocoa/WKWebViewTextInput.mm:
* TestWebKitAPI/Tests/mac/AcceptsFirstMouse.mm:
(TestWebKitAPI::AcceptsFirstMouse::runTest):
* TestWebKitAPI/Tests/mac/WKWebViewMacEditingTests.mm:
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView waitForNextPresentationUpdate]):
Add a new helper method to spin until the next presentation update.
* TestWebKitAPI/mac/WebKitAgnosticTest.h:
* TestWebKitAPI/mac/WebKitAgnosticTest.mm:
(TestWebKitAPI::WebKitAgnosticTest::waitForNextPresentationUpdate):
LayoutTests:
Rebaseline and adjust LayoutTests.
* editing/caret/ios/absolute-caret-position-after-scroll-expected.txt:
* editing/caret/ios/absolute-caret-position-after-scroll.html:
* editing/caret/ios/fixed-caret-position-after-scroll-expected.txt:
* editing/caret/ios/fixed-caret-position-after-scroll.html:
* editing/secure-input/password-input-changed-type.html:
* editing/secure-input/password-input-focusing.html:
* editing/secure-input/removed-password-input.html:
* editing/secure-input/reset-state-on-navigation.html:
* editing/selection/character-granularity-rect.html:
Delay checking for secure input state and caret rects until after the next presentation update.
* editing/selection/ios/absolute-selection-after-scroll-expected.txt:
* editing/selection/ios/absolute-selection-after-scroll.html:
* editing/selection/ios/fixed-selection-after-scroll-expected.txt:
* editing/selection/ios/fixed-selection-after-scroll.html:
Refactor and simplify these tests. These tests are not run on the OpenSource bots, since they depend on long
press and tap gestures.
* platform/ios-wk2/editing/inserting/insert-div-024-expected.txt:
* platform/ios-wk2/editing/inserting/insert-div-026-expected.txt:
* platform/ios-wk2/editing/style/5084241-expected.txt:
Rebaselines these tests, removing an anonymous RenderBlock inserted as a result of inserting and removing a
dummy span in order to compute a RenderStyle in WebPage::editorState. This is because editorState is no longer
invoked immediately on page load; https://bugs.webkit.org/show_bug.cgi?id=175116 tracks preventing this render
tree thrashing altogether.
* platform/mac-wk2/TestExpectations:
* platform/mac-wk2/editing/style/unbold-in-bold-expected.txt:
* resources/ui-helper.js:
Introduce new UIHelper functions.
(window.UIHelper.ensurePresentationUpdate.return.new.Promise):
(window.UIHelper.ensurePresentationUpdate):
Returns a Promise, resolved after the next presentation update.
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise.):
(window.UIHelper.activateAndWaitForInputSessionAt.return.new.Promise):
(window.UIHelper.activateAndWaitForInputSessionAt):
Returns a Promise, resolved after tapping at the given location and waiting for the keyboard to appear on iOS.
(window.UIHelper.getUICaretRect.return.new.Promise.):
(window.UIHelper.getUICaretRect.return.new.Promise):
(window.UIHelper.getUICaretRect):
(window.UIHelper.getUISelectionRects.return.new.Promise.):
(window.UIHelper.getUISelectionRects.return.new.Promise):
(window.UIHelper.getUISelectionRects):
Helpers to fetch selection and caret rect information in the UI process.
Canonical link: https://commits.webkit.org/192519@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221064 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-23 03:15:38 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(function() {
|
|
|
|
uiController.doAfterNextStablePresentationUpdate(function() {
|
|
|
|
uiController.uiScriptComplete(JSON.stringify(uiController.selectionRangeViewRects));
|
|
|
|
});
|
|
|
|
})()`, jsonString => {
|
|
|
|
resolve(JSON.parse(jsonString));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[iOS] Caret disappears after resigning and becoming first responder if active focus state is retained
https://bugs.webkit.org/show_bug.cgi?id=188322
<rdar://problem/42455270>
Reviewed by Tim Horton.
Source/WebKit:
Prior to r230745, when a user selects a word in non-editable web content without a prior selection, we would
always try to activate the text interaction assistant, creating a selection view (a UITextSelectionView). After
the long press is recognized, this text selection view is configured for "highlight mode", which is a special
mode for presenting selection UI where the grabber handles at the start and end of the selection are suppressed.
UIKit then prepares to show the selection by asking WKContentView for the number of selection rects; if this
number is zero, the UITextSelectionView is removed from the superview, and state that keeps track of whether the
selection view is in "highlight mode" is reset.
In the case where there's no prior selection, our cached EditorState in the UI process will not be up to date
yet when the gesture is recognized. This means that when UIKit asks us for the number of selection rects, we'll
return 0, which causes any state tracking "highlight mode" for the selection to be reset, subsequently resulting
in selection handles showing up before the user has ended the initial loupe gesture.
r230745 addressed this bug by removing logic to activate the text selection when becoming first responder,
instead deferring until the next `-_selectionChanged` call with post-layout editor state data to activate the
selection. While this does ensure that selection handles don't erroneously appear, it also means that clients
that call -becomeFirstResponder to show selection UI and the keyboard in a web view while an element is already
focused will not have an active selection assistant (i.e. the selection view will still be hidden). One way this
happens is when Safari uses `-_retainActiveFocusedState` in combination with `-resignFirstResponder` and
`-becomeFirstResponder` to temporarily switch focus away from the web view when the URL bar is tapped.
To fix both the inactive selection after `-becomeFirstResponder` as well as the selection handles showing up
when performing a loupe gesture, we simply make the check in `-becomeFirstResponderForWebView` more nuanced.
Instead of always activating the selection or never activating the selection, only activate the selection if the
current editor state has information about a selection to avoid causing the selection view to be immediately
removed and "highlight mode" to be reset when selecting a word via loupe gesture for the first time.
Tests: KeyboardInputTests.CaretSelectionRectAfterRestoringFirstResponder
KeyboardInputTests.RangedSelectionRectAfterRestoringFirstResponder
editing/selection/ios/selection-handles-after-touch-end.html
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView becomeFirstResponderForWebView]):
(-[WKContentView canShowNonEmptySelectionView]):
Tools:
Adds plumbing in UIScriptController to grab the start and end selection handle rects for use in the new layout
test. Also adds new API tests to verify that when a web view resigns first responder, both caret and range
selection views are hidden, and when first responder status is restored, both caret and range selection views
are made visible again.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm:
(-[TestWKWebView waitForCaretViewFrameToBecome:]):
(-[TestWKWebView waitForSelectionViewRectsToBecome:]):
(webViewWithAutofocusedInput):
Pull out some common logic for creating a web view that allows programmatic focus to present the keyboard, and
immediately loading a web page with an autofocusing text field.
(TestWebKitAPI::TEST):
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView caretViewRectInContentCoordinates]):
(-[TestWKWebView selectionViewRectsInContentCoordinates]):
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
LayoutTests:
Adds a new layout test to verify that (1) selection handles are not shown when selecting a word by long
pressing prior to ending the touch, and (2) selection handles are shown after ending the touch.
* editing/selection/ios/selection-handles-after-touch-end-expected.txt: Added.
* editing/selection/ios/selection-handles-after-touch-end.html: Added.
* platform/win/TestExpectations:
Skip iOS selection tests on Windows.
* resources/ui-helper.js:
Introduces new hooks in UIHelper to grab the frames of the start and end selection handle views.
(window.UIHelper.getSelectionStartGrabberViewRect.return.new.Promise.):
(window.UIHelper.getSelectionStartGrabberViewRect.return.new.Promise):
(window.UIHelper.getSelectionStartGrabberViewRect):
(window.UIHelper.getSelectionEndGrabberViewRect.return.new.Promise.):
(window.UIHelper.getSelectionEndGrabberViewRect.return.new.Promise):
(window.UIHelper.getSelectionEndGrabberViewRect):
Canonical link: https://commits.webkit.org/203447@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@234600 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-08-06 14:14:42 +00:00
|
|
|
static getSelectionStartGrabberViewRect()
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
[iOS] Caret disappears after resigning and becoming first responder if active focus state is retained
https://bugs.webkit.org/show_bug.cgi?id=188322
<rdar://problem/42455270>
Reviewed by Tim Horton.
Source/WebKit:
Prior to r230745, when a user selects a word in non-editable web content without a prior selection, we would
always try to activate the text interaction assistant, creating a selection view (a UITextSelectionView). After
the long press is recognized, this text selection view is configured for "highlight mode", which is a special
mode for presenting selection UI where the grabber handles at the start and end of the selection are suppressed.
UIKit then prepares to show the selection by asking WKContentView for the number of selection rects; if this
number is zero, the UITextSelectionView is removed from the superview, and state that keeps track of whether the
selection view is in "highlight mode" is reset.
In the case where there's no prior selection, our cached EditorState in the UI process will not be up to date
yet when the gesture is recognized. This means that when UIKit asks us for the number of selection rects, we'll
return 0, which causes any state tracking "highlight mode" for the selection to be reset, subsequently resulting
in selection handles showing up before the user has ended the initial loupe gesture.
r230745 addressed this bug by removing logic to activate the text selection when becoming first responder,
instead deferring until the next `-_selectionChanged` call with post-layout editor state data to activate the
selection. While this does ensure that selection handles don't erroneously appear, it also means that clients
that call -becomeFirstResponder to show selection UI and the keyboard in a web view while an element is already
focused will not have an active selection assistant (i.e. the selection view will still be hidden). One way this
happens is when Safari uses `-_retainActiveFocusedState` in combination with `-resignFirstResponder` and
`-becomeFirstResponder` to temporarily switch focus away from the web view when the URL bar is tapped.
To fix both the inactive selection after `-becomeFirstResponder` as well as the selection handles showing up
when performing a loupe gesture, we simply make the check in `-becomeFirstResponderForWebView` more nuanced.
Instead of always activating the selection or never activating the selection, only activate the selection if the
current editor state has information about a selection to avoid causing the selection view to be immediately
removed and "highlight mode" to be reset when selecting a word via loupe gesture for the first time.
Tests: KeyboardInputTests.CaretSelectionRectAfterRestoringFirstResponder
KeyboardInputTests.RangedSelectionRectAfterRestoringFirstResponder
editing/selection/ios/selection-handles-after-touch-end.html
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView becomeFirstResponderForWebView]):
(-[WKContentView canShowNonEmptySelectionView]):
Tools:
Adds plumbing in UIScriptController to grab the start and end selection handle rects for use in the new layout
test. Also adds new API tests to verify that when a web view resigns first responder, both caret and range
selection views are hidden, and when first responder status is restored, both caret and range selection views
are made visible again.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm:
(-[TestWKWebView waitForCaretViewFrameToBecome:]):
(-[TestWKWebView waitForSelectionViewRectsToBecome:]):
(webViewWithAutofocusedInput):
Pull out some common logic for creating a web view that allows programmatic focus to present the keyboard, and
immediately loading a web page with an autofocusing text field.
(TestWebKitAPI::TEST):
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView caretViewRectInContentCoordinates]):
(-[TestWKWebView selectionViewRectsInContentCoordinates]):
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
LayoutTests:
Adds a new layout test to verify that (1) selection handles are not shown when selecting a word by long
pressing prior to ending the touch, and (2) selection handles are shown after ending the touch.
* editing/selection/ios/selection-handles-after-touch-end-expected.txt: Added.
* editing/selection/ios/selection-handles-after-touch-end.html: Added.
* platform/win/TestExpectations:
Skip iOS selection tests on Windows.
* resources/ui-helper.js:
Introduces new hooks in UIHelper to grab the frames of the start and end selection handle views.
(window.UIHelper.getSelectionStartGrabberViewRect.return.new.Promise.):
(window.UIHelper.getSelectionStartGrabberViewRect.return.new.Promise):
(window.UIHelper.getSelectionStartGrabberViewRect):
(window.UIHelper.getSelectionEndGrabberViewRect.return.new.Promise.):
(window.UIHelper.getSelectionEndGrabberViewRect.return.new.Promise):
(window.UIHelper.getSelectionEndGrabberViewRect):
Canonical link: https://commits.webkit.org/203447@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@234600 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-08-06 14:14:42 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(function() {
|
|
|
|
uiController.doAfterNextStablePresentationUpdate(function() {
|
|
|
|
uiController.uiScriptComplete(JSON.stringify(uiController.selectionStartGrabberViewRect));
|
|
|
|
});
|
|
|
|
})()`, jsonString => {
|
|
|
|
resolve(JSON.parse(jsonString));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static getSelectionEndGrabberViewRect()
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
[iOS] Caret disappears after resigning and becoming first responder if active focus state is retained
https://bugs.webkit.org/show_bug.cgi?id=188322
<rdar://problem/42455270>
Reviewed by Tim Horton.
Source/WebKit:
Prior to r230745, when a user selects a word in non-editable web content without a prior selection, we would
always try to activate the text interaction assistant, creating a selection view (a UITextSelectionView). After
the long press is recognized, this text selection view is configured for "highlight mode", which is a special
mode for presenting selection UI where the grabber handles at the start and end of the selection are suppressed.
UIKit then prepares to show the selection by asking WKContentView for the number of selection rects; if this
number is zero, the UITextSelectionView is removed from the superview, and state that keeps track of whether the
selection view is in "highlight mode" is reset.
In the case where there's no prior selection, our cached EditorState in the UI process will not be up to date
yet when the gesture is recognized. This means that when UIKit asks us for the number of selection rects, we'll
return 0, which causes any state tracking "highlight mode" for the selection to be reset, subsequently resulting
in selection handles showing up before the user has ended the initial loupe gesture.
r230745 addressed this bug by removing logic to activate the text selection when becoming first responder,
instead deferring until the next `-_selectionChanged` call with post-layout editor state data to activate the
selection. While this does ensure that selection handles don't erroneously appear, it also means that clients
that call -becomeFirstResponder to show selection UI and the keyboard in a web view while an element is already
focused will not have an active selection assistant (i.e. the selection view will still be hidden). One way this
happens is when Safari uses `-_retainActiveFocusedState` in combination with `-resignFirstResponder` and
`-becomeFirstResponder` to temporarily switch focus away from the web view when the URL bar is tapped.
To fix both the inactive selection after `-becomeFirstResponder` as well as the selection handles showing up
when performing a loupe gesture, we simply make the check in `-becomeFirstResponderForWebView` more nuanced.
Instead of always activating the selection or never activating the selection, only activate the selection if the
current editor state has information about a selection to avoid causing the selection view to be immediately
removed and "highlight mode" to be reset when selecting a word via loupe gesture for the first time.
Tests: KeyboardInputTests.CaretSelectionRectAfterRestoringFirstResponder
KeyboardInputTests.RangedSelectionRectAfterRestoringFirstResponder
editing/selection/ios/selection-handles-after-touch-end.html
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView becomeFirstResponderForWebView]):
(-[WKContentView canShowNonEmptySelectionView]):
Tools:
Adds plumbing in UIScriptController to grab the start and end selection handle rects for use in the new layout
test. Also adds new API tests to verify that when a web view resigns first responder, both caret and range
selection views are hidden, and when first responder status is restored, both caret and range selection views
are made visible again.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm:
(-[TestWKWebView waitForCaretViewFrameToBecome:]):
(-[TestWKWebView waitForSelectionViewRectsToBecome:]):
(webViewWithAutofocusedInput):
Pull out some common logic for creating a web view that allows programmatic focus to present the keyboard, and
immediately loading a web page with an autofocusing text field.
(TestWebKitAPI::TEST):
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView caretViewRectInContentCoordinates]):
(-[TestWKWebView selectionViewRectsInContentCoordinates]):
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::selectionStartGrabberViewRect const):
(WTR::UIScriptController::selectionEndGrabberViewRect const):
LayoutTests:
Adds a new layout test to verify that (1) selection handles are not shown when selecting a word by long
pressing prior to ending the touch, and (2) selection handles are shown after ending the touch.
* editing/selection/ios/selection-handles-after-touch-end-expected.txt: Added.
* editing/selection/ios/selection-handles-after-touch-end.html: Added.
* platform/win/TestExpectations:
Skip iOS selection tests on Windows.
* resources/ui-helper.js:
Introduces new hooks in UIHelper to grab the frames of the start and end selection handle views.
(window.UIHelper.getSelectionStartGrabberViewRect.return.new.Promise.):
(window.UIHelper.getSelectionStartGrabberViewRect.return.new.Promise):
(window.UIHelper.getSelectionStartGrabberViewRect):
(window.UIHelper.getSelectionEndGrabberViewRect.return.new.Promise.):
(window.UIHelper.getSelectionEndGrabberViewRect.return.new.Promise):
(window.UIHelper.getSelectionEndGrabberViewRect):
Canonical link: https://commits.webkit.org/203447@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@234600 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-08-06 14:14:42 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(function() {
|
|
|
|
uiController.doAfterNextStablePresentationUpdate(function() {
|
|
|
|
uiController.uiScriptComplete(JSON.stringify(uiController.selectionEndGrabberViewRect));
|
|
|
|
});
|
|
|
|
})()`, jsonString => {
|
|
|
|
resolve(JSON.parse(jsonString));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
caret-color does not work on first click in ios
https://bugs.webkit.org/show_bug.cgi?id=228859
rdar://81674787
Reviewed by Tim Horton.
Source/WebKit:
Addresses a couple of issues that cause the `caret-color` CSS property to not be applied when focusing editable
content on iOS. See below for more details.
Test: editing/caret/ios/caret-color-after-refocusing-input.html
* Platform/spi/ios/UIKitSPI.h:
* UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
* UIProcess/API/ios/WKWebViewTestingIOS.mm:
(-[WKWebView _serializedSelectionCaretBackgroundColorForTesting]):
Add support for a new test-only helper method. See Tools/ChangeLog for more information.
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(WebKit::WKSelectionDrawingInfo::WKSelectionDrawingInfo):
(WebKit::operator==):
(WebKit::operator<<):
Make a minor adjustment to ensure that changes to `caretColor` in `EditorState` are propagated to UIKit's
selection views. To achieve this, we add `caretColor` to `WKSelectionDrawingInfo`, and force the text selection
view to update the caret background color when the caret color changes (alongside other selection UI geometry
changes, which are applied underneath the call to `-selectionChanged`).
(-[WKContentView _updateChangedSelection:]):
(-[WKContentView textInteractionAssistant]):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getPlatformEditorState const):
Address an existing FIXME which (mostly) fixes this bug. Currently, the caret color is only computed when
`WebPage::m_focusedElement` is set. However, when resigning first responder, we clear out `WebPage`'s
`m_focusedElement`) right before updating the DOM selection, which creates a brief window during which we
compute an `EditorState` with a `caretColor` of transparent black.
To avoid this inconsistency, we instead compute the caret color from the selection container; this has the
additional benefit of allowing the caret color to change when changing selection within a single editable host
with multiple caret colors (instead of always just using the focused element's caret color).
Note that while this adjustment to `WebPage::getPlatformEditorState` is sufficient to ensure that the value of
`-[WKContentView insertionPointColor]` (which is based on `EditorState`) is always up-to-date, this doesn't
guarantee that the actual color of UIKit's caret view reflects the updated `-insertionPointColor`, which results
in situations where the caret color appears out-of-date after hiding the keyboard and refocusing an input field.
To fix this, we need the other adjustment in WKContentView (see above).
Tools:
Make it possible to test this bug by adding a UIScriptController hook to request the background color of the
current selection view's caret view, as serialized CSS text. See LayoutTests/ChangeLog for more details.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::selectionCaretBackgroundColor const):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::selectionCaretBackgroundColor const):
LayoutTests:
Add a new layout test that exercises the issue, as reported in Bugzilla (the call to `-resignFirstResponder`
simulates backgrounding Safari). To achieve this, we also introduce a script controller testing helper to grab
the native background color of the `UITextSelectionView`'s caret view; see Tools/ChangeLog for more details.
* editing/caret/ios/caret-color-after-refocusing-input-expected.txt: Added.
* editing/caret/ios/caret-color-after-refocusing-input.html: Added.
* resources/ui-helper.js:
(window.UIHelper.selectionCaretBackgroundColor):
Canonical link: https://commits.webkit.org/240352@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@280767 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-08-09 01:21:41 +00:00
|
|
|
static selectionCaretBackgroundColor()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript("uiController.uiScriptComplete(uiController.selectionCaretBackgroundColor)", resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
REGRESSION (r271660): Tap highlight no longer shows when tapping clickable elements without touch event listeners
https://bugs.webkit.org/show_bug.cgi?id=224385
<rdar://problem/76462370>
Reviewed by Tim Horton.
Source/WebKit:
In r271660, I added a call to `-finishInteraction` when resetting the synthetic tap gesture to fix a bug where
it was possible for the tap highlight to remain indefinitely when tapping on a clickable element with a touchend
event listener. This was because the touch end deferring gesture defers `-_singleTapDidReset:` until after
`-_didGetTapHighlightForRequest:…nodeHasBuiltInClickHandling:`, where we receive the tap highlight information.
```
2021-04-09 13:05:27.141097-0700 -[WKContentView(WKInteraction) _singleTapIdentified:]
2021-04-09 13:05:27.148678-0700 -[WKContentView(WKInteraction) _didGetTapHighlightForRequest:…nodeHasBuiltInClickHandling:]
2021-04-09 13:05:27.162525-0700 -[WKContentView(WKInteraction) _singleTapRecognized:]
2021-04-09 13:05:27.162675-0700 ↳ -[WKContentView(WKInteraction) _showTapHighlight]
2021-04-09 13:05:27.163250-0700 -[WKContentView(WKInteraction) _singleTapDidReset:]
2021-04-09 13:05:51.849481-0700 ↳ -[WKContentView(WKInteraction) _finishInteraction]
```
However, in the case where there is no touchend event listener and when fast-click is active, we reset the tap
gesture before receiving the tap highlight information:
```
2021-04-09 13:05:51.836638-0700 -[WKContentView(WKInteraction) _singleTapIdentified:]
2021-04-09 13:05:51.846152-0700 -[WKContentView(WKInteraction) _singleTapRecognized:]
2021-04-09 13:05:51.847196-0700 -[WKContentView(WKInteraction) _singleTapDidReset:]
2021-04-09 13:05:51.848563-0700 -[WKContentView(WKInteraction) _didGetTapHighlightForRequest:…nodeHasBuiltInClickHandling:]
2021-04-09 13:05:51.848851-0700 ↳ -[WKContentView(WKInteraction) _showTapHighlight]
2021-04-09 13:05:51.849481-0700 ↳ -[WKContentView(WKInteraction) _finishInteraction]
```
Critically, this means that calling `-_finishInteraction` in `-_singleTapDidReset:` prematurely flagged the
tap highlight request as complete (by setting `_isTapHighlightIDValid` to `NO`) in the case where we aren't
deferring gestures, which caused us to avoid showing the tap highlight at all when we eventually receive the tap
highlight information.
To fix this, only fade out the tap highlight view in `-_singleTapDidReset:` if the tap highlight request has
already finished (i.e. `_isTapHighlightIDValid` has been set to `NO`). Additionally, split logic for fading out
the highlight view into a separate method, and add a `BOOL` flag to make the fading idempotent.
Test: fast/events/touch/ios/tap-highlight-during-synthetic-click.html
* UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
* UIProcess/API/ios/WKWebViewTestingIOS.mm:
(-[WKWebView _tapHighlightViewRect]):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView tapHighlightViewRect]):
Also add a testing-only method to report the frame of the tap highlight view. Note that this only attempts to
return the current `frame` of the tap highlight view instead of converting the frame to the coordinate system of
the content view (as other similar testing hooks do), since the tap highlight view only exists in the view
hierarchy for a brief duration.
(-[WKContentView _finishInteraction]):
(-[WKContentView _fadeTapHighlightViewIfNeeded]):
(-[WKContentView _singleTapDidReset:]):
Tools:
Add plumbing to expose the frame of the tap highlight view via `UIScriptController`.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::tapHighlightViewRect const):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::tapHighlightViewRect const):
LayoutTests:
Add a new layout test that exercises 3 scenarios, using the new testing SPI:
1. Tapping on a `button` that prevents the "touchend" event (and therefore prevents clicking) should cause
the tap highlight to not show up.
2. Tapping on a `button` that has a "touchend" event listener and does not prevent default should cause the tap
highlight to show up.
3. Tapping on a `button` with no event listeners should cause the tap highlight to show up.
* fast/events/touch/ios/tap-highlight-during-synthetic-click-expected.txt: Added.
* fast/events/touch/ios/tap-highlight-during-synthetic-click.html: Added.
* resources/ui-helper.js:
(window.UIHelper.tapHighlightViewRect):
Canonical link: https://commits.webkit.org/236362@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@275791 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-10 03:01:13 +00:00
|
|
|
static tapHighlightViewRect()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript("JSON.stringify(uiController.tapHighlightViewRect)", jsonString => {
|
|
|
|
resolve(JSON.parse(jsonString));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
Picking an emoji via the emoji dialog (Ctrl+Cmd+Space) fires inconsistent beforeinput events.
https://bugs.webkit.org/show_bug.cgi?id=170955
<rdar://problem/31697653>
Reviewed by Ryosuke Niwa.
Source/WebKit:
Currently, we insert text with TextEventInputAutocompletion as the text event input type if any text range to
replace was specified by the platform. Instead, limit this only to when the text replacement range is not empty.
This more closely matches the intention of the spec, which states that the "insertReplacementText" inputType
should be used when "[replacing] existing text by means of a spell checker, auto-correct or similar".
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::insertTextAsync):
Source/WebKitLegacy/mac:
Tweak -insertText: to pass TextEventInputAutocompletion to Editor::insertText when inserting text, if existing
text is being replaced.
* WebView/WebHTMLView.mm:
(-[WebHTMLView insertText:]):
Tools:
Replace UIScriptController.insertText with UIScriptController.replaceTextAtRange, and implement
replaceTextAtRange in WebKit1. See corresponding layout tests (input-event-insert-replacement.html and
before-input-prevent-insert-replacement.html) for more detail.
* DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
* DumpRenderTree/mac/AppKitTestSPI.h: Added.
Introduce an SPI header for private AppKit headers needed to support DumpRenderTree.
* DumpRenderTree/mac/UIScriptControllerMac.mm:
(WTR::UIScriptController::replaceTextAtRange):
(WTR::UIScriptController::insertText): Deleted.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::replaceTextAtRange):
(WTR::UIScriptController::insertText): Deleted.
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/mac/UIScriptControllerMac.mm:
(WTR::UIScriptController::replaceTextAtRange):
(WTR::UIScriptController::insertText): Deleted.
Replace UIScriptController.insertText with UIScriptController.replaceTextAtRange, which better describes the
behavior of this function.
LayoutTests:
Augments two existing layout tests to check for additional cases of inserting text with replacement ranges.
Also enables this test for WebKit1 on Mac. Both these tests are currently enabled only for WebKit2, and also only
check the case where we're replacing an existing non-empty range of text.
* fast/events/before-input-prevent-insert-replacement-expected.txt:
* fast/events/before-input-prevent-insert-replacement.html:
* fast/events/input-event-insert-replacement-expected.txt:
* fast/events/input-event-insert-replacement.html:
Tests for cases of replacing existing text ranges, and inserting text at a position.
* platform/mac-wk1/TestExpectations:
* resources/ui-helper.js:
Add a new UIHelper function to insert text at a given replacement range. This codepath is taken when selecting
an emoji using the emoji picker menu on Mac, and also when selecting a dead key option after holding down on a
vowel key.
(window.UIHelper.replaceTextAtRange):
Canonical link: https://commits.webkit.org/192681@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221234 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-28 05:12:56 +00:00
|
|
|
static replaceTextAtRange(text, location, length) {
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.replaceTextAtRange("${text}", ${location}, ${length});
|
2019-01-17 19:15:57 +00:00
|
|
|
uiController.uiScriptComplete();
|
Picking an emoji via the emoji dialog (Ctrl+Cmd+Space) fires inconsistent beforeinput events.
https://bugs.webkit.org/show_bug.cgi?id=170955
<rdar://problem/31697653>
Reviewed by Ryosuke Niwa.
Source/WebKit:
Currently, we insert text with TextEventInputAutocompletion as the text event input type if any text range to
replace was specified by the platform. Instead, limit this only to when the text replacement range is not empty.
This more closely matches the intention of the spec, which states that the "insertReplacementText" inputType
should be used when "[replacing] existing text by means of a spell checker, auto-correct or similar".
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::insertTextAsync):
Source/WebKitLegacy/mac:
Tweak -insertText: to pass TextEventInputAutocompletion to Editor::insertText when inserting text, if existing
text is being replaced.
* WebView/WebHTMLView.mm:
(-[WebHTMLView insertText:]):
Tools:
Replace UIScriptController.insertText with UIScriptController.replaceTextAtRange, and implement
replaceTextAtRange in WebKit1. See corresponding layout tests (input-event-insert-replacement.html and
before-input-prevent-insert-replacement.html) for more detail.
* DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
* DumpRenderTree/mac/AppKitTestSPI.h: Added.
Introduce an SPI header for private AppKit headers needed to support DumpRenderTree.
* DumpRenderTree/mac/UIScriptControllerMac.mm:
(WTR::UIScriptController::replaceTextAtRange):
(WTR::UIScriptController::insertText): Deleted.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::replaceTextAtRange):
(WTR::UIScriptController::insertText): Deleted.
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/mac/UIScriptControllerMac.mm:
(WTR::UIScriptController::replaceTextAtRange):
(WTR::UIScriptController::insertText): Deleted.
Replace UIScriptController.insertText with UIScriptController.replaceTextAtRange, which better describes the
behavior of this function.
LayoutTests:
Augments two existing layout tests to check for additional cases of inserting text with replacement ranges.
Also enables this test for WebKit1 on Mac. Both these tests are currently enabled only for WebKit2, and also only
check the case where we're replacing an existing non-empty range of text.
* fast/events/before-input-prevent-insert-replacement-expected.txt:
* fast/events/before-input-prevent-insert-replacement.html:
* fast/events/input-event-insert-replacement-expected.txt:
* fast/events/input-event-insert-replacement.html:
Tests for cases of replacing existing text ranges, and inserting text at a position.
* platform/mac-wk1/TestExpectations:
* resources/ui-helper.js:
Add a new UIHelper function to insert text at a given replacement range. This codepath is taken when selecting
an emoji using the emoji picker menu on Mac, and also when selecting a dead key option after holding down on a
vowel key.
(window.UIHelper.replaceTextAtRange):
Canonical link: https://commits.webkit.org/192681@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221234 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-08-28 05:12:56 +00:00
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-12-13 23:22:03 +00:00
|
|
|
static wait(promise)
|
|
|
|
{
|
|
|
|
testRunner.waitUntilDone();
|
2016-12-14 21:57:37 +00:00
|
|
|
if (window.finishJSTest)
|
|
|
|
window.jsTestIsAsync = true;
|
|
|
|
|
|
|
|
let finish = () => {
|
|
|
|
if (window.finishJSTest)
|
|
|
|
finishJSTest();
|
|
|
|
else
|
|
|
|
testRunner.notifyDone();
|
|
|
|
}
|
|
|
|
|
|
|
|
return promise.then(finish, finish);
|
2016-12-13 23:22:03 +00:00
|
|
|
}
|
2017-11-09 00:36:15 +00:00
|
|
|
|
|
|
|
static withUserGesture(callback)
|
|
|
|
{
|
|
|
|
internals.withUserGesture(callback);
|
|
|
|
}
|
2018-04-11 16:43:53 +00:00
|
|
|
|
|
|
|
static selectFormAccessoryPickerRow(rowIndex)
|
|
|
|
{
|
Single selection <select> with <optgroups> shows multiple selected options
https://bugs.webkit.org/show_bug.cgi?id=199485
<rdar://problem/52757531>
Reviewed by Megan Gardner.
Source/WebKit:
Fixes a long-standing bug in WKMultipleSelectPicker. Prior to this patch, we rely on the delegate method
`-pickerView:row:column:checked:` to be called twice whenever an item is selected: one time for the item that is
no longer checked, and another for the newly checked item. This method is responsible for updating the cached
`FocusedElementInformation` that determines the data model for the select menu, with the expectation that the
unchecked item would be updated to have `isSelected = false;`, and the new checked item would have `isSelected`
`= true;`.
However, `-pickerView:row:column:checked:` is only called for visible item cells. This means that if the user
checks an item, scrolls the select menu items down so that the checked item is offscreen, and then checks a
different item, we only get notified that the new item is checked, and as a result, fail to uncheck the previous
item.
To address this, tweak our logic for handling a single select so that when an item is checked, we additionally
update the previously checked item to not be selected. Also, fix what seems to be a bug in the logic for
updating `_singleSelectionIndex`, which is currently updated even when the item is unchecked. It seems to work
out at the moment, because `-pickerView:row:column:checked:` seems to be called with `checked := YES` after the
previous item was unchecked (assuming that it was visible).
Test: fast/forms/ios/no-stale-checked-items-in-select-picker.html
* UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
* UIProcess/API/ios/WKWebViewTestingIOS.mm:
(-[WKWebView selectFormAccessoryHasCheckedItemAtRow:]):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView selectFormAccessoryHasCheckedItemAtRow:]):
Add plumbing for a new testing hook.
* UIProcess/ios/forms/WKFormSelectControl.h:
* UIProcess/ios/forms/WKFormSelectControl.mm:
(-[WKFormSelectControl selectFormAccessoryHasCheckedItemAtRow:]):
* UIProcess/ios/forms/WKFormSelectPicker.mm:
(-[WKMultipleSelectPicker pickerView:viewForRow:forComponent:reusingView:]):
(-[WKMultipleSelectPicker pickerView:row:column:checked:]):
(-[WKMultipleSelectPicker selectRow:inComponent:extendingSelection:]):
Also, fix an existing bug in this testing helper method that crashed the test runner due to calling an
unimplemented selector. Instead of trying to invoke `-pickerView:didSelectRow:inComponent:`, we should be using
`-pickerView:row:column:checked:` instead for multiple select pickers (which, somewhat confusingly, are still
used for single select elements that have `optgroup`s.)
(-[WKMultipleSelectPicker selectFormAccessoryHasCheckedItemAtRow:]):
Tools:
Add a new helper method to check whether the currently presented form accessory is a select menu, and has a
checked menu item at the given row.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::selectFormAccessoryHasCheckedItemAtRow const):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::selectFormAccessoryHasCheckedItemAtRow const):
LayoutTests:
Add a layout test to verify that we don't leave behind a checked select item after scrolling it offscreen and
then checking a different item.
* fast/forms/ios/no-stale-checked-items-in-select-picker-expected.txt: Added.
* fast/forms/ios/no-stale-checked-items-in-select-picker.html: Added.
* platform/ipad/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.selectFormAccessoryPickerRow):
(window.UIHelper.selectFormAccessoryHasCheckedItemAtRow):
Canonical link: https://commits.webkit.org/224906@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261815 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-18 16:23:30 +00:00
|
|
|
const selectRowScript = `uiController.selectFormAccessoryPickerRow(${rowIndex})`;
|
2018-04-11 16:43:53 +00:00
|
|
|
return new Promise(resolve => testRunner.runUIScript(selectRowScript, resolve));
|
|
|
|
}
|
|
|
|
|
Single selection <select> with <optgroups> shows multiple selected options
https://bugs.webkit.org/show_bug.cgi?id=199485
<rdar://problem/52757531>
Reviewed by Megan Gardner.
Source/WebKit:
Fixes a long-standing bug in WKMultipleSelectPicker. Prior to this patch, we rely on the delegate method
`-pickerView:row:column:checked:` to be called twice whenever an item is selected: one time for the item that is
no longer checked, and another for the newly checked item. This method is responsible for updating the cached
`FocusedElementInformation` that determines the data model for the select menu, with the expectation that the
unchecked item would be updated to have `isSelected = false;`, and the new checked item would have `isSelected`
`= true;`.
However, `-pickerView:row:column:checked:` is only called for visible item cells. This means that if the user
checks an item, scrolls the select menu items down so that the checked item is offscreen, and then checks a
different item, we only get notified that the new item is checked, and as a result, fail to uncheck the previous
item.
To address this, tweak our logic for handling a single select so that when an item is checked, we additionally
update the previously checked item to not be selected. Also, fix what seems to be a bug in the logic for
updating `_singleSelectionIndex`, which is currently updated even when the item is unchecked. It seems to work
out at the moment, because `-pickerView:row:column:checked:` seems to be called with `checked := YES` after the
previous item was unchecked (assuming that it was visible).
Test: fast/forms/ios/no-stale-checked-items-in-select-picker.html
* UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
* UIProcess/API/ios/WKWebViewTestingIOS.mm:
(-[WKWebView selectFormAccessoryHasCheckedItemAtRow:]):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView selectFormAccessoryHasCheckedItemAtRow:]):
Add plumbing for a new testing hook.
* UIProcess/ios/forms/WKFormSelectControl.h:
* UIProcess/ios/forms/WKFormSelectControl.mm:
(-[WKFormSelectControl selectFormAccessoryHasCheckedItemAtRow:]):
* UIProcess/ios/forms/WKFormSelectPicker.mm:
(-[WKMultipleSelectPicker pickerView:viewForRow:forComponent:reusingView:]):
(-[WKMultipleSelectPicker pickerView:row:column:checked:]):
(-[WKMultipleSelectPicker selectRow:inComponent:extendingSelection:]):
Also, fix an existing bug in this testing helper method that crashed the test runner due to calling an
unimplemented selector. Instead of trying to invoke `-pickerView:didSelectRow:inComponent:`, we should be using
`-pickerView:row:column:checked:` instead for multiple select pickers (which, somewhat confusingly, are still
used for single select elements that have `optgroup`s.)
(-[WKMultipleSelectPicker selectFormAccessoryHasCheckedItemAtRow:]):
Tools:
Add a new helper method to check whether the currently presented form accessory is a select menu, and has a
checked menu item at the given row.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::selectFormAccessoryHasCheckedItemAtRow const):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::selectFormAccessoryHasCheckedItemAtRow const):
LayoutTests:
Add a layout test to verify that we don't leave behind a checked select item after scrolling it offscreen and
then checking a different item.
* fast/forms/ios/no-stale-checked-items-in-select-picker-expected.txt: Added.
* fast/forms/ios/no-stale-checked-items-in-select-picker.html: Added.
* platform/ipad/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.selectFormAccessoryPickerRow):
(window.UIHelper.selectFormAccessoryHasCheckedItemAtRow):
Canonical link: https://commits.webkit.org/224906@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261815 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-18 16:23:30 +00:00
|
|
|
static selectFormAccessoryHasCheckedItemAtRow(rowIndex)
|
|
|
|
{
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.selectFormAccessoryHasCheckedItemAtRow(${rowIndex})`, result => {
|
|
|
|
resolve(result === "true");
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2018-04-11 16:43:53 +00:00
|
|
|
static selectFormPopoverTitle()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.uiScriptComplete(uiController.selectFormPopoverTitle);
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
2018-04-20 22:21:54 +00:00
|
|
|
|
2021-02-09 19:25:04 +00:00
|
|
|
static setSelectedColorForColorPicker(red, green, blue)
|
|
|
|
{
|
|
|
|
const selectColorScript = `uiController.setSelectedColorForColorPicker(${red}, ${green}, ${blue})`;
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(selectColorScript, resolve));
|
|
|
|
}
|
|
|
|
|
2018-04-20 22:21:54 +00:00
|
|
|
static enterText(text)
|
|
|
|
{
|
|
|
|
const escapedText = text.replace(/`/g, "\\`");
|
|
|
|
const enterTextScript = `(() => uiController.enterText(\`${escapedText}\`))()`;
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(enterTextScript, resolve));
|
|
|
|
}
|
2018-04-24 02:45:32 +00:00
|
|
|
|
|
|
|
static setTimePickerValue(hours, minutes)
|
|
|
|
{
|
|
|
|
const setValueScript = `(() => uiController.setTimePickerValue(${hours}, ${minutes}))()`;
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(setValueScript, resolve));
|
|
|
|
}
|
2018-04-25 21:23:27 +00:00
|
|
|
|
2020-04-20 21:45:03 +00:00
|
|
|
static timerPickerValues()
|
|
|
|
{
|
|
|
|
if (!this.isIOSFamily())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
const uiScript = "JSON.stringify([uiController.timePickerValueHour, uiController.timePickerValueMinute])";
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(uiScript, result => {
|
|
|
|
const [hour, minute] = JSON.parse(result)
|
|
|
|
resolve({ hour: hour, minute: minute });
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2018-06-19 18:09:49 +00:00
|
|
|
static textContentType()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.uiScriptComplete(uiController.textContentType);
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-04-25 21:23:27 +00:00
|
|
|
static formInputLabel()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.uiScriptComplete(uiController.formInputLabel);
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
[Extra zoom mode] Add a mechanism to override default viewport behaviors in extra zoom mode
https://bugs.webkit.org/show_bug.cgi?id=185050
<rdar://problem/39624038>
Reviewed by Tim Horton.
Source/WebCore:
Currently, in extra zoom mode, there's no way for web pages to opt out of the default viewport behaviors
(namely, laying out at a larger width and shrinking to fit) when the web view is very tall and narrow. This
patch adds a new experimental viewport attribute, "min-device-width", that can be used to prevent WebKit from
automatically clamping the web view width to a greater value for the device width in this scenario.
Note that after this patch, logic that plumbs a minimumLayoutSize from WKWebView to the viewport configuration
will need to be renamed to reflect that this size is no longer the minimum layout size, but rather, the view
size that is used for viewport device dimensions by default. This refactoring will be done in a followup part.
See per-method comments below for more detail.
Test: fast/viewport/extrazoom/viewport-change-min-device-width.html
* dom/ViewportArguments.cpp:
(WebCore::setViewportFeature):
(WebCore::operator<<):
* dom/ViewportArguments.h:
Removes `m_forceHorizontalShrinkToFit` (more detail below).
* page/ViewportConfiguration.cpp:
(WebCore::computedMinDeviceWidth):
(WebCore::ViewportConfiguration::ViewportConfiguration):
(WebCore::ViewportConfiguration::setMinimumLayoutSize):
Instead of directly setting the minimum layout size, setMinimumLayoutSize now first sets the view size (i.e. the
size we use for `device-width` in the viewport meta tag), and then updates the minimum layout size.
(WebCore::ViewportConfiguration::shouldOverrideDeviceWidthWithMinDeviceWidth const):
Replaces `m_forceHorizontalShrinkToFit`. Whether or not we shrink to fit is now determined by whether the
min-device-width attribute is actively clamping the width of the view.
(WebCore::ViewportConfiguration::shouldIgnoreHorizontalScalingConstraints const):
(WebCore::ViewportConfiguration::shouldIgnoreScalingConstraintsRegardlessOfContentSize const):
(WebCore::ViewportConfiguration::updateMinimumLayoutSize):
Computes and sets the minimum layout size using the view size, taking the minimum device width into account if
needed.
(WebCore::ViewportConfiguration::description const):
(WebCore::ViewportConfiguration::setForceHorizontalShrinkToFit): Deleted.
* page/ViewportConfiguration.h:
Source/WebKit:
Remove the forceHorizontalViewportShrinkToFit and minimumAllowedLayoutWidth SPI hooks from WebKit, and
additionally remove all logic for plumbing viewSize to WebCore. See WebCore/ChangeLog for more information.
* Shared/VisibleContentRectUpdateInfo.cpp:
(WebKit::VisibleContentRectUpdateInfo::encode const):
(WebKit::VisibleContentRectUpdateInfo::decode):
(WebKit::operator<<):
* Shared/VisibleContentRectUpdateInfo.h:
(WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
(WebKit::VisibleContentRectUpdateInfo::allowShrinkToFit const):
(WebKit::operator==):
(WebKit::VisibleContentRectUpdateInfo::forceHorizontalShrinkToFit const): Deleted.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initializeWithConfiguration:]):
(-[WKWebView activeMinimumLayoutSize:]):
(-[WKWebView _dispatchSetMinimumLayoutSize:]):
(-[WKWebView _frameOrBoundsChanged]):
(-[WKWebView _setMinimumLayoutSizeOverride:]):
(-[WKWebView _beginAnimatedResizeWithUpdates:]):
(-[WKWebView _endAnimatedResize]):
(-[WKWebView _minimumAllowedLayoutWidth]): Deleted.
(-[WKWebView _setMinimumAllowedLayoutWidth:]): Deleted.
(-[WKWebView activeMinimumLayoutSizes:]): Deleted.
(-[WKWebView _dispatchSetMinimumLayoutSize:viewSize:]): Deleted.
(-[WKWebView _setForceHorizontalViewportShrinkToFit:]): Deleted.
(-[WKWebView _forceHorizontalViewportShrinkToFit]): Deleted.
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::creationParameters):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInsets:unobscuredSafeAreaInsets:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::dynamicViewportSizeUpdate):
(WebKit::WebPageProxy::setViewportConfigurationMinimumLayoutSize):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::m_credentialsMessenger):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::setViewportConfigurationMinimumLayoutSize):
(WebKit::WebPage::dynamicViewportSizeUpdate):
(WebKit::WebPage::updateVisibleContentRects):
Tools:
Remove a test that's no longer useful, now that the SPI it was testing is gone. This functionality is now
tested by the layout test added in this patch.
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/ios/ViewportSizingTests.mm: Removed.
LayoutTests:
Add a new layout test to check that:
• By default (with no `min-device-width` override), shrink-to-fit and expanded minimum layout sizes takes effect.
• `min-device-width` can be used to bail out of shrink-to-fit and viewport behaviors.
• A large `min-device-width` can be used to make extra zoom mode viewport heuristics even more aggressive.
* TestExpectations:
* fast/viewport/extrazoom/viewport-change-min-device-width.html: Added.
* resources/ui-helper.js:
(window.UIHelper.zoomScale):
(window.UIHelper):
Canonical link: https://commits.webkit.org/200561@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@231095 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-04-27 15:35:50 +00:00
|
|
|
|
2021-03-17 20:10:46 +00:00
|
|
|
static dismissFilePicker()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
const script = `uiController.dismissFilePicker(() => {
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
})`;
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(script, resolve));
|
|
|
|
}
|
|
|
|
|
|
|
|
static filePickerAcceptedTypeIdentifiers()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.uiScriptComplete(JSON.stringify(uiController.filePickerAcceptedTypeIdentifiers));
|
|
|
|
})()`, jsonString => {
|
|
|
|
resolve(JSON.parse(jsonString));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
Native text substitutions interfere with HTML <datalist> options resulting in crash
https://bugs.webkit.org/show_bug.cgi?id=203116
<rdar://problem/49875932>
Reviewed by Tim Horton.
Source/WebKit:
On macOS, an NSTableView inside a separate window is used to render suggestions when showing a datalist. The
crash happens when this table view is reloaded while clicking a datalist suggestion; that is, if -[NSTableView
reloadData] is invoked after the user sends a platform MouseDown event on the table view cell but before the
MouseUp is received, the selected row of the table view will be -1 when the action, `-selectedRow:`, is invoked.
In this particular case, the table view reload is triggered as a result of hiding the autocorrection bubble on
macOS, thereby committing the alternative text suggestion and changing the value of the text field via an
editing command.
To avoid crashing, we simply make `-selectedRow:` robust in the case where the index is invalid.
Test: fast/forms/datalist/datalist-click-crash.html
* UIProcess/mac/WebDataListSuggestionsDropdownMac.mm:
(-[WKDataListSuggestionsController selectedRow:]):
Tools:
Add a new testing hook to wait for datalist suggestions to show up and choose the suggestion at the given index.
* DumpRenderTree/mac/UIScriptControllerMac.h:
* DumpRenderTree/mac/UIScriptControllerMac.mm:
(WTR::UIScriptControllerMac::activateDataListSuggestion):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::activateDataListSuggestion):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::activateDataListSuggestion):
* WebKitTestRunner/mac/UIScriptControllerMac.h:
* WebKitTestRunner/mac/UIScriptControllerMac.mm:
(WTR::UIScriptControllerMac::isShowingDataListSuggestions const):
(WTR::UIScriptControllerMac::activateDataListSuggestion):
Dig through the view hierarchy of the NSWindow subclass used to show datalist suggestions for the table view
containing the suggestions; then, select the given row, and invoke the action on the target.
(WTR::UIScriptControllerMac::dataListSuggestionsTableView const):
LayoutTests:
Add a new layout test to exercise the crash.
* fast/forms/datalist/datalist-click-crash-expected.txt: Added.
* fast/forms/datalist/datalist-click-crash.html: Added.
* resources/ui-helper.js:
(window.UIHelper.activateDataListSuggestion):
Canonical link: https://commits.webkit.org/217216@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252062 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-11-05 18:52:12 +00:00
|
|
|
static activateDataListSuggestion(index) {
|
|
|
|
const script = `uiController.activateDataListSuggestion(${index}, () => {
|
|
|
|
uiController.uiScriptComplete("");
|
|
|
|
});`;
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(script, resolve));
|
|
|
|
}
|
|
|
|
|
2018-07-16 21:15:57 +00:00
|
|
|
static isShowingDataListSuggestions()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.uiScriptComplete(uiController.isShowingDataListSuggestions);
|
2019-02-11 19:30:05 +00:00
|
|
|
})()`, result => resolve(result === "true"));
|
2018-07-16 21:15:57 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[macOS] Show picker for date and datetime-local input types
https://bugs.webkit.org/show_bug.cgi?id=214946
Reviewed by Darin Adler and Wenson Hsieh.
Source/WebCore:
Date and datetime-local input types require a calendar picker to be presented when activated.
Consequently, BaseChooserOnlyDateAndTimeInputType::handleDOMActivateEvent was modified to
create a DateTimeChooser and display a calendar upon activation. This object is destroyed
when the element is blurred, hiding the calendar.
There is currently no picker UI for month, week, and time input types. As a result,
handleDOMActivateEvent is a no-op on those input types.
Wrote an encoder and decoder for DateTimeChooserParameters, so that the picker can be
created with the correct values.
Tests: fast/forms/date/date-show-hide-picker.html
fast/forms/datetimelocal/datetimelocal-show-hide-picker.html
* WebCore.xcodeproj/project.pbxproj:
* html/BaseChooserOnlyDateAndTimeInputType.cpp:
(WebCore::BaseChooserOnlyDateAndTimeInputType::handleDOMActivateEvent):
(WebCore::BaseChooserOnlyDateAndTimeInputType::elementDidBlur):
(WebCore::BaseChooserOnlyDateAndTimeInputType::isPresentingAttachedView const):
(WebCore::BaseChooserOnlyDateAndTimeInputType::didChooseValue):
* html/BaseChooserOnlyDateAndTimeInputType.h:
* html/HTMLInputElement.cpp:
* html/MonthInputType.cpp:
(WebCore::MonthInputType::handleDOMActivateEvent):
* html/MonthInputType.h:
* html/TimeInputType.cpp:
(WebCore::TimeInputType::handleDOMActivateEvent):
* html/TimeInputType.h:
* html/WeekInputType.cpp:
(WebCore::WeekInputType::handleDOMActivateEvent):
* html/WeekInputType.h:
* loader/EmptyClients.cpp:
(WebCore::EmptyChromeClient::createDateTimeChooser):
* loader/EmptyClients.h:
* page/Chrome.cpp:
(WebCore::Chrome::createDateTimeChooser):
* page/Chrome.h:
* page/ChromeClient.h:
* platform/DateTimeChooser.h:
* platform/DateTimeChooserClient.h:
* platform/DateTimeChooserParameters.h: Added.
(WebCore::DateTimeChooserParameters::encode const):
(WebCore::DateTimeChooserParameters::decode):
Source/WebKit:
Created WKDateTimePicker as a wrapper around NSDatePicker. The picker is
displayed in its own NSWindow, ensuring the view is always above the page.
WebPageProxy and WKDateTimePicker communicate through WebDateTimePickerMac,
in order for the picker to be initialized with the correct initial, minimum,
and maximum date, and so that the chosen date can be sent back to the
WebProcess.
Added IPC messages to enable communication between the UIProcess and the
WebProcess necessary for showing and hiding the picker.
* Sources.txt:
* SourcesCocoa.txt:
* UIProcess/PageClient.h:
* UIProcess/WebDateTimePicker.cpp: Added.
(WebKit::WebDateTimePicker::WebDateTimePicker):
(WebKit::WebDateTimePicker::~WebDateTimePicker):
(WebKit::WebDateTimePicker::endPicker):
* UIProcess/WebDateTimePicker.h: Added.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::showDateTimePicker):
(WebKit::WebPageProxy::endDateTimePicker):
(WebKit::WebPageProxy::didChooseDate):
(WebKit::WebPageProxy::didEndDateTimePicker):
(WebKit::WebPageProxy::closeOverlayedViews):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::createDateTimePicker):
* UIProcess/mac/PageClientImplMac.h:
* UIProcess/mac/PageClientImplMac.mm:
(WebKit::PageClientImpl::createDateTimePicker):
* UIProcess/mac/WebDateTimePickerMac.h: Added.
* UIProcess/mac/WebDateTimePickerMac.mm: Added.
(WebKit::WebDateTimePickerMac::create):
(WebKit::WebDateTimePickerMac::~WebDateTimePickerMac):
(WebKit::WebDateTimePickerMac::WebDateTimePickerMac):
(WebKit::WebDateTimePickerMac::endPicker):
(WebKit::WebDateTimePickerMac::showDateTimePicker):
(WebKit::WebDateTimePickerMac::didChooseDate):
(-[WKDateTimePickerWindow initWithContentRect:styleMask:backing:defer:]):
(-[WKDateTimePickerWindow canBecomeKeyWindow]):
(-[WKDateTimePickerWindow hasKeyAppearance]):
(-[WKDateTimePickerWindow shadowOptions]):
(-[WKDateTimePicker initWithParams:inView:]):
(-[WKDateTimePicker showPicker:]):
(-[WKDateTimePicker invalidate]):
(-[WKDateTimePicker didChooseDate:]):
(-[WKDateTimePicker dateFormatStringForType:]):
* WebKit.xcodeproj/project.pbxproj:
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::createDateTimeChooser):
* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebCoreSupport/WebDateTimeChooser.cpp: Added.
(WebKit::WebDateTimeChooser::WebDateTimeChooser):
(WebKit::WebDateTimeChooser::didChooseDate):
(WebKit::WebDateTimeChooser::didEndChooser):
(WebKit::WebDateTimeChooser::endChooser):
(WebKit::WebDateTimeChooser::showChooser):
* WebProcess/WebCoreSupport/WebDateTimeChooser.h: Added.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::setActiveDateTimeChooser):
(WebKit::WebPage::didChooseDate):
(WebKit::WebPage::didEndDateTimePicker):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Source/WebKitLegacy/mac:
* WebCoreSupport/WebChromeClient.h:
* WebCoreSupport/WebChromeClient.mm:
(WebChromeClient::createDateTimeChooser):
Tools:
Added isShowingDateTimePicker testing hook in order to enable testing of the visibility of
the picker.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::isShowingDateTimePicker const):
* WebKitTestRunner/mac/UIScriptControllerMac.h:
* WebKitTestRunner/mac/UIScriptControllerMac.mm:
(WTR::UIScriptControllerMac::isShowingDateTimePicker const):
LayoutTests:
Added tests to verify that the picker is correctly shown and hidden for date and
datetime-local input types.
* fast/forms/date/date-show-hide-picker-expected.txt: Added.
* fast/forms/date/date-show-hide-picker.html: Added.
* fast/forms/datetimelocal/datetimelocal-show-hide-picker-expected.txt: Added.
* fast/forms/datetimelocal/datetimelocal-show-hide-picker.html: Added.
* platform/ios/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.isShowingDateTimePicker):
Canonical link: https://commits.webkit.org/228540@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@266063 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-08-24 16:25:10 +00:00
|
|
|
static isShowingDateTimePicker()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.uiScriptComplete(uiController.isShowingDateTimePicker);
|
|
|
|
})()`, result => resolve(result === "true"));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-09-02 15:35:57 +00:00
|
|
|
static dateTimePickerValue()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.uiScriptComplete(uiController.dateTimePickerValue);
|
|
|
|
})()`, valueAsString => resolve(parseFloat(valueAsString)));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[macOS] Selecting a date on datetime-local inputs unexpectedly adds second and millisecond fields
https://bugs.webkit.org/show_bug.cgi?id=221350
<rdar://problem/73943517>
Reviewed by Devin Rousso.
Source/WebCore:
Currently, when setting the value of a datetime-local input using the
picker, the length of the current value of the input is used to determine
whether or not to return a value with second/millisecond precision.
This is approach is incorrect, since the value could be empty, while the
step attribute can specify second/millisecond precision. To fix, ensure
the DateTimeChooserParameters knows whether the input has second and
millisecond fields. That information can then be used by the UIProcess
to return a correctly formatted value to the WebProcess.
Test: fast/forms/datetimelocal/datetimelocal-editable-components/datetimelocal-choose-value-from-picker.html
* html/BaseDateAndTimeInputType.cpp:
(WebCore::BaseDateAndTimeInputType::handleDOMActivateEvent):
(WebCore::BaseDateAndTimeInputType::didChangeValueFromControl):
(WebCore::BaseDateAndTimeInputType::setupDateTimeChooserParameters):
Moved this method from HTMLInputElement to the input type, since it is
specific to date/time input types, and to leverage the existing
shouldHaveSecondField and shouldHaveMillisecondField methods when
building the DateTimeChooserParameters.
* html/BaseDateAndTimeInputType.h:
* html/HTMLInputElement.cpp:
* html/HTMLInputElement.h:
* platform/DateTimeChooserParameters.h:
Added hasSecondField and hasMillisecondField members, so that the UIProcess
knows whether or not to return a string that contains seconds/milliseconds.
(WebCore::DateTimeChooserParameters::encode const):
(WebCore::DateTimeChooserParameters::decode):
Source/WebKit:
* UIProcess/mac/WebDateTimePickerMac.mm:
(-[WKDateTimePicker updatePicker:]):
(-[WKDateTimePicker dateFormatStringForType:]):
Do not use the length of the value to determine whether or seconds and
milliseconds should be present, since the value can be empty.
Instead, use the new information in DateTimeChooserParameters, matching
the visual appearance of the input.
Tools:
Added a method to UIScriptController to simulate selecting a date using
the presented date picker.
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::chooseDateTimePickerValue):
* WebKitTestRunner/mac/UIScriptControllerMac.h:
* WebKitTestRunner/mac/UIScriptControllerMac.mm:
(WTR::UIScriptControllerMac::chooseDateTimePickerValue):
LayoutTests:
Added a test to to verify that the presence of seconds and milliseconds
in the value of a datetime-local input after selecting a date using the
picker matches the configuration.
* fast/forms/datetimelocal/datetimelocal-editable-components/datetimelocal-choose-value-from-picker-expected.txt: Added.
* fast/forms/datetimelocal/datetimelocal-editable-components/datetimelocal-choose-value-from-picker.html: Added.
* resources/ui-helper.js:
(window.UIHelper.chooseDateTimePickerValue):
Canonical link: https://commits.webkit.org/233696@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@272368 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-02-04 14:59:24 +00:00
|
|
|
static chooseDateTimePickerValue()
|
|
|
|
{
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
uiController.chooseDateTimePickerValue();
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[Extra zoom mode] Add a mechanism to override default viewport behaviors in extra zoom mode
https://bugs.webkit.org/show_bug.cgi?id=185050
<rdar://problem/39624038>
Reviewed by Tim Horton.
Source/WebCore:
Currently, in extra zoom mode, there's no way for web pages to opt out of the default viewport behaviors
(namely, laying out at a larger width and shrinking to fit) when the web view is very tall and narrow. This
patch adds a new experimental viewport attribute, "min-device-width", that can be used to prevent WebKit from
automatically clamping the web view width to a greater value for the device width in this scenario.
Note that after this patch, logic that plumbs a minimumLayoutSize from WKWebView to the viewport configuration
will need to be renamed to reflect that this size is no longer the minimum layout size, but rather, the view
size that is used for viewport device dimensions by default. This refactoring will be done in a followup part.
See per-method comments below for more detail.
Test: fast/viewport/extrazoom/viewport-change-min-device-width.html
* dom/ViewportArguments.cpp:
(WebCore::setViewportFeature):
(WebCore::operator<<):
* dom/ViewportArguments.h:
Removes `m_forceHorizontalShrinkToFit` (more detail below).
* page/ViewportConfiguration.cpp:
(WebCore::computedMinDeviceWidth):
(WebCore::ViewportConfiguration::ViewportConfiguration):
(WebCore::ViewportConfiguration::setMinimumLayoutSize):
Instead of directly setting the minimum layout size, setMinimumLayoutSize now first sets the view size (i.e. the
size we use for `device-width` in the viewport meta tag), and then updates the minimum layout size.
(WebCore::ViewportConfiguration::shouldOverrideDeviceWidthWithMinDeviceWidth const):
Replaces `m_forceHorizontalShrinkToFit`. Whether or not we shrink to fit is now determined by whether the
min-device-width attribute is actively clamping the width of the view.
(WebCore::ViewportConfiguration::shouldIgnoreHorizontalScalingConstraints const):
(WebCore::ViewportConfiguration::shouldIgnoreScalingConstraintsRegardlessOfContentSize const):
(WebCore::ViewportConfiguration::updateMinimumLayoutSize):
Computes and sets the minimum layout size using the view size, taking the minimum device width into account if
needed.
(WebCore::ViewportConfiguration::description const):
(WebCore::ViewportConfiguration::setForceHorizontalShrinkToFit): Deleted.
* page/ViewportConfiguration.h:
Source/WebKit:
Remove the forceHorizontalViewportShrinkToFit and minimumAllowedLayoutWidth SPI hooks from WebKit, and
additionally remove all logic for plumbing viewSize to WebCore. See WebCore/ChangeLog for more information.
* Shared/VisibleContentRectUpdateInfo.cpp:
(WebKit::VisibleContentRectUpdateInfo::encode const):
(WebKit::VisibleContentRectUpdateInfo::decode):
(WebKit::operator<<):
* Shared/VisibleContentRectUpdateInfo.h:
(WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
(WebKit::VisibleContentRectUpdateInfo::allowShrinkToFit const):
(WebKit::operator==):
(WebKit::VisibleContentRectUpdateInfo::forceHorizontalShrinkToFit const): Deleted.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initializeWithConfiguration:]):
(-[WKWebView activeMinimumLayoutSize:]):
(-[WKWebView _dispatchSetMinimumLayoutSize:]):
(-[WKWebView _frameOrBoundsChanged]):
(-[WKWebView _setMinimumLayoutSizeOverride:]):
(-[WKWebView _beginAnimatedResizeWithUpdates:]):
(-[WKWebView _endAnimatedResize]):
(-[WKWebView _minimumAllowedLayoutWidth]): Deleted.
(-[WKWebView _setMinimumAllowedLayoutWidth:]): Deleted.
(-[WKWebView activeMinimumLayoutSizes:]): Deleted.
(-[WKWebView _dispatchSetMinimumLayoutSize:viewSize:]): Deleted.
(-[WKWebView _setForceHorizontalViewportShrinkToFit:]): Deleted.
(-[WKWebView _forceHorizontalViewportShrinkToFit]): Deleted.
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::creationParameters):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInsets:unobscuredSafeAreaInsets:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::dynamicViewportSizeUpdate):
(WebKit::WebPageProxy::setViewportConfigurationMinimumLayoutSize):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::m_credentialsMessenger):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::setViewportConfigurationMinimumLayoutSize):
(WebKit::WebPage::dynamicViewportSizeUpdate):
(WebKit::WebPage::updateVisibleContentRects):
Tools:
Remove a test that's no longer useful, now that the SPI it was testing is gone. This functionality is now
tested by the layout test added in this patch.
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/ios/ViewportSizingTests.mm: Removed.
LayoutTests:
Add a new layout test to check that:
• By default (with no `min-device-width` override), shrink-to-fit and expanded minimum layout sizes takes effect.
• `min-device-width` can be used to bail out of shrink-to-fit and viewport behaviors.
• A large `min-device-width` can be used to make extra zoom mode viewport heuristics even more aggressive.
* TestExpectations:
* fast/viewport/extrazoom/viewport-change-min-device-width.html: Added.
* resources/ui-helper.js:
(window.UIHelper.zoomScale):
(window.UIHelper):
Canonical link: https://commits.webkit.org/200561@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@231095 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-04-27 15:35:50 +00:00
|
|
|
static zoomScale()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.uiScriptComplete(uiController.zoomScale);
|
[iOS] Changing view scale sometimes does not zoom the page to the new initial scale, when the page is at initial scale
https://bugs.webkit.org/show_bug.cgi?id=191180
<rdar://problem/45744786>
Reviewed by Simon Fraser.
Source/WebCore:
When computing the minimum scale in ViewportConfiguration::minimumScale, if our content width or height is
shorter than the view width or height, then we recompute the minimum scale such that the content dimensions will
fill the bounds of the view by setting the minimum scale to the view width or height divided by the content
width or height.
Suppose the minimum scale is equal to some value `s`; additionally, let `w_c` denote the content width and `w_v`
denote the view width (as integers). If `w_v / s` is not an integral value, the computed content width `w_c` may
be rounded, such that `w_v / w_c` is not precisely equal to `s`. In the case that `w_v / w_c` is ever so
slightly larger than `s`, we will end up overriding the minimum scale `s` with `w_v / w_c`.
As a result, specifying a viewport with a decimal `minimum-scale` will sometimes cause the computed minimum
scale of the viewport (and platform view) to be very slightly different from the minimum scale. The new layout
test below exercises this scenario, specifying a viewport with minimum and initial scales of 0.94 that results
in `ViewportConfiguration::minimumScale` returning 0.94158.
With the `WebPage::setViewportConfigurationViewLayoutSize` check added in r237127, this means setting
`_viewScale:` when the page is at initial scale sometimes doesn't zoom the page to the new initial scale when it
should, since the page scale factor and the initial scale are different enough such that
`areEssentiallyEqualAsFloat` returns false.
This patch addresses these issues by snapping to the minimum scale if the computed scale that fits content
dimensions to view dimensions results in a minimum scale that is close enough to the configuration's minimum
scale, such that the difference can be attributed to rounding error when computing content or view dimensions.
Test: fast/viewport/ios/viewport-minimum-and-initial-scale.html
* page/ViewportConfiguration.cpp:
(WebCore::ViewportConfiguration::minimumScale const):
LayoutTests:
Add a layout test, and make some adjustments to UIHelper.
* fast/viewport/ios/constant-width-viewport-after-changing-view-scale.html:
* fast/viewport/ios/device-width-viewport-after-changing-view-scale.html:
* fast/viewport/ios/viewport-minimum-and-initial-scale-expected.txt: Added.
* fast/viewport/ios/viewport-minimum-and-initial-scale.html: Added.
Add a new layout test that contains a viewport meta tag with minimum and initial scales set to 0.94, and checks
that the resulting minimum and initial scales are 0.94 instead of 0.94158.
* fast/viewport/watchos/viewport-disable-extra-zoom-adaptations.html:
* resources/ui-helper.js:
Make UIHelper.zoomScale return a number rather than a string, and adjust a few call sites.
(window.UIHelper.zoomScale):
(window.UIHelper.minimumZoomScale):
(window.UIHelper):
Canonical link: https://commits.webkit.org/206009@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237743 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-11-02 18:10:23 +00:00
|
|
|
})()`, scaleAsString => resolve(parseFloat(scaleAsString)));
|
[Extra zoom mode] Add a mechanism to override default viewport behaviors in extra zoom mode
https://bugs.webkit.org/show_bug.cgi?id=185050
<rdar://problem/39624038>
Reviewed by Tim Horton.
Source/WebCore:
Currently, in extra zoom mode, there's no way for web pages to opt out of the default viewport behaviors
(namely, laying out at a larger width and shrinking to fit) when the web view is very tall and narrow. This
patch adds a new experimental viewport attribute, "min-device-width", that can be used to prevent WebKit from
automatically clamping the web view width to a greater value for the device width in this scenario.
Note that after this patch, logic that plumbs a minimumLayoutSize from WKWebView to the viewport configuration
will need to be renamed to reflect that this size is no longer the minimum layout size, but rather, the view
size that is used for viewport device dimensions by default. This refactoring will be done in a followup part.
See per-method comments below for more detail.
Test: fast/viewport/extrazoom/viewport-change-min-device-width.html
* dom/ViewportArguments.cpp:
(WebCore::setViewportFeature):
(WebCore::operator<<):
* dom/ViewportArguments.h:
Removes `m_forceHorizontalShrinkToFit` (more detail below).
* page/ViewportConfiguration.cpp:
(WebCore::computedMinDeviceWidth):
(WebCore::ViewportConfiguration::ViewportConfiguration):
(WebCore::ViewportConfiguration::setMinimumLayoutSize):
Instead of directly setting the minimum layout size, setMinimumLayoutSize now first sets the view size (i.e. the
size we use for `device-width` in the viewport meta tag), and then updates the minimum layout size.
(WebCore::ViewportConfiguration::shouldOverrideDeviceWidthWithMinDeviceWidth const):
Replaces `m_forceHorizontalShrinkToFit`. Whether or not we shrink to fit is now determined by whether the
min-device-width attribute is actively clamping the width of the view.
(WebCore::ViewportConfiguration::shouldIgnoreHorizontalScalingConstraints const):
(WebCore::ViewportConfiguration::shouldIgnoreScalingConstraintsRegardlessOfContentSize const):
(WebCore::ViewportConfiguration::updateMinimumLayoutSize):
Computes and sets the minimum layout size using the view size, taking the minimum device width into account if
needed.
(WebCore::ViewportConfiguration::description const):
(WebCore::ViewportConfiguration::setForceHorizontalShrinkToFit): Deleted.
* page/ViewportConfiguration.h:
Source/WebKit:
Remove the forceHorizontalViewportShrinkToFit and minimumAllowedLayoutWidth SPI hooks from WebKit, and
additionally remove all logic for plumbing viewSize to WebCore. See WebCore/ChangeLog for more information.
* Shared/VisibleContentRectUpdateInfo.cpp:
(WebKit::VisibleContentRectUpdateInfo::encode const):
(WebKit::VisibleContentRectUpdateInfo::decode):
(WebKit::operator<<):
* Shared/VisibleContentRectUpdateInfo.h:
(WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
(WebKit::VisibleContentRectUpdateInfo::allowShrinkToFit const):
(WebKit::operator==):
(WebKit::VisibleContentRectUpdateInfo::forceHorizontalShrinkToFit const): Deleted.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initializeWithConfiguration:]):
(-[WKWebView activeMinimumLayoutSize:]):
(-[WKWebView _dispatchSetMinimumLayoutSize:]):
(-[WKWebView _frameOrBoundsChanged]):
(-[WKWebView _setMinimumLayoutSizeOverride:]):
(-[WKWebView _beginAnimatedResizeWithUpdates:]):
(-[WKWebView _endAnimatedResize]):
(-[WKWebView _minimumAllowedLayoutWidth]): Deleted.
(-[WKWebView _setMinimumAllowedLayoutWidth:]): Deleted.
(-[WKWebView activeMinimumLayoutSizes:]): Deleted.
(-[WKWebView _dispatchSetMinimumLayoutSize:viewSize:]): Deleted.
(-[WKWebView _setForceHorizontalViewportShrinkToFit:]): Deleted.
(-[WKWebView _forceHorizontalViewportShrinkToFit]): Deleted.
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::creationParameters):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInsets:unobscuredSafeAreaInsets:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::dynamicViewportSizeUpdate):
(WebKit::WebPageProxy::setViewportConfigurationMinimumLayoutSize):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::m_credentialsMessenger):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::setViewportConfigurationMinimumLayoutSize):
(WebKit::WebPage::dynamicViewportSizeUpdate):
(WebKit::WebPage::updateVisibleContentRects):
Tools:
Remove a test that's no longer useful, now that the SPI it was testing is gone. This functionality is now
tested by the layout test added in this patch.
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/ios/ViewportSizingTests.mm: Removed.
LayoutTests:
Add a new layout test to check that:
• By default (with no `min-device-width` override), shrink-to-fit and expanded minimum layout sizes takes effect.
• `min-device-width` can be used to bail out of shrink-to-fit and viewport behaviors.
• A large `min-device-width` can be used to make extra zoom mode viewport heuristics even more aggressive.
* TestExpectations:
* fast/viewport/extrazoom/viewport-change-min-device-width.html: Added.
* resources/ui-helper.js:
(window.UIHelper.zoomScale):
(window.UIHelper):
Canonical link: https://commits.webkit.org/200561@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@231095 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-04-27 15:35:50 +00:00
|
|
|
});
|
|
|
|
}
|
2018-08-06 15:01:47 +00:00
|
|
|
|
[iOS] Suppress native selection behaviors when focusing a very small editable element
https://bugs.webkit.org/show_bug.cgi?id=193005
<rdar://problem/46583527>
Reviewed by Tim Horton.
Source/WebKit:
In r238146, I added a mechanism to detect when the selection is hidden within transparent editable elements, and
used this to suppress native selection on iOS (such as selection handles, highlight, callout bar, etc.) to avoid
conflicts between the page's editing UI and the platform.
However, one additional technique observed on some websites involves hiding the selection by moving it into a
tiny (1x1) editable element. Here, we currently still present a callout bar with editing actions, as well as
show a selection caret or handles on iOS. To fix this, we extend the mechanism added in r238146 by also
suppressing the selection assistant in the case where the editable element's area is beneath a tiny minimum
threshold.
Test: editing/selection/ios/hide-selection-in-tiny-contenteditable.html
* Shared/EditorState.cpp:
(WebKit::EditorState::PostLayoutData::encode const):
(WebKit::EditorState::PostLayoutData::decode):
(WebKit::operator<<):
* Shared/EditorState.h:
Rename selectionClipRect to focusedElementRect. We currently propagate the bounds of the focused element to the
UI process through EditorState updates, but only for the purpose of returning it in the computed selection clip
rect; instead, rename this member to something more general-purpose, so we can also use it when determining
whether to suppress the selection assistant.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _candidateRect]):
* UIProcess/Cocoa/WebViewImpl.mm:
(WebKit::WebViewImpl::handleRequestedCandidates):
* UIProcess/ios/WKContentViewInteraction.h:
Add a new SuppressSelectionAssistantReason that corresponds to focusing tiny editable elements.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _zoomToRevealFocusedElement]):
(-[WKContentView _selectionClipRect]):
(-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
(-[WKContentView _updateChangedSelection:]):
Check the size of the focused element, and begin or stop suppressing the selection assistant accordingly.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState const):
LayoutTests:
Add a new layout test to verify that native selection UI is suppressed when focusing a tiny (1px by 1px)
editable element.
* editing/selection/ios/hide-selection-in-tiny-contenteditable-expected.txt: Added.
* editing/selection/ios/hide-selection-in-tiny-contenteditable.html: Added.
* resources/ui-helper.js:
(window.UIHelper.zoomToScale):
Canonical link: https://commits.webkit.org/207574@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239543 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-12-23 06:38:24 +00:00
|
|
|
static zoomToScale(scale)
|
|
|
|
{
|
2019-01-17 19:15:57 +00:00
|
|
|
const uiScript = `uiController.zoomToScale(${scale}, () => uiController.uiScriptComplete(uiController.zoomScale))`;
|
[iOS] Suppress native selection behaviors when focusing a very small editable element
https://bugs.webkit.org/show_bug.cgi?id=193005
<rdar://problem/46583527>
Reviewed by Tim Horton.
Source/WebKit:
In r238146, I added a mechanism to detect when the selection is hidden within transparent editable elements, and
used this to suppress native selection on iOS (such as selection handles, highlight, callout bar, etc.) to avoid
conflicts between the page's editing UI and the platform.
However, one additional technique observed on some websites involves hiding the selection by moving it into a
tiny (1x1) editable element. Here, we currently still present a callout bar with editing actions, as well as
show a selection caret or handles on iOS. To fix this, we extend the mechanism added in r238146 by also
suppressing the selection assistant in the case where the editable element's area is beneath a tiny minimum
threshold.
Test: editing/selection/ios/hide-selection-in-tiny-contenteditable.html
* Shared/EditorState.cpp:
(WebKit::EditorState::PostLayoutData::encode const):
(WebKit::EditorState::PostLayoutData::decode):
(WebKit::operator<<):
* Shared/EditorState.h:
Rename selectionClipRect to focusedElementRect. We currently propagate the bounds of the focused element to the
UI process through EditorState updates, but only for the purpose of returning it in the computed selection clip
rect; instead, rename this member to something more general-purpose, so we can also use it when determining
whether to suppress the selection assistant.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _candidateRect]):
* UIProcess/Cocoa/WebViewImpl.mm:
(WebKit::WebViewImpl::handleRequestedCandidates):
* UIProcess/ios/WKContentViewInteraction.h:
Add a new SuppressSelectionAssistantReason that corresponds to focusing tiny editable elements.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _zoomToRevealFocusedElement]):
(-[WKContentView _selectionClipRect]):
(-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
(-[WKContentView _updateChangedSelection:]):
Check the size of the focused element, and begin or stop suppressing the selection assistant accordingly.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState const):
LayoutTests:
Add a new layout test to verify that native selection UI is suppressed when focusing a tiny (1px by 1px)
editable element.
* editing/selection/ios/hide-selection-in-tiny-contenteditable-expected.txt: Added.
* editing/selection/ios/hide-selection-in-tiny-contenteditable.html: Added.
* resources/ui-helper.js:
(window.UIHelper.zoomToScale):
Canonical link: https://commits.webkit.org/207574@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239543 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-12-23 06:38:24 +00:00
|
|
|
return new Promise(resolve => testRunner.runUIScript(uiScript, resolve));
|
|
|
|
}
|
|
|
|
|
2019-08-22 00:06:38 +00:00
|
|
|
static immediateZoomToScale(scale)
|
|
|
|
{
|
|
|
|
const uiScript = `uiController.immediateZoomToScale(${scale})`;
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(uiScript, resolve));
|
|
|
|
}
|
|
|
|
|
2018-08-06 15:01:47 +00:00
|
|
|
static typeCharacter(characterString)
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily()) {
|
[iOS] Special keys are misidentified in DOM keyboard events
https://bugs.webkit.org/show_bug.cgi?id=189974
Reviewed by Wenson Hsieh.
Source/WebCore:
This patch fixes two issues:
1. Special keyboard keys would be misidentified in dispatched DOM keyboard events.
2. DOM keypress events may not be dispatched for some special keys.
UIKit uses special input strings to identify the Page Up, Page Down, Escape, Up Arrow, Down Arrow,
Left Arrow, and Right Arrow keys. It also uses ASCII control characters to represent some other
special keys, including Num Lock / Clear, Home, End, Forward Delete, and F1, ..., F24. We need
to explicitly handle these special keyboard keys in order to be able to identify the key that
was pressed as well as to correctly disambiguate a key down to know whether to dispatch a DOM
keypress event for the key.
Unlike UIKit, AppKit reserves Unicode Private Use Area (PUA) code points in 0xF700–0xF8FF to
represent special keyboard keys. This makes it straightforward to disambiguate such keys using
the input string of the keyboard event alone. To simplify the implementation for iOS
we normalize the input string be AppKit compatible. See the explaination for WebCore::windowsKeyCodeForCharCode()
below for more details on why this is done.
Tests: fast/events/ios/keydown-keyup-arrow-keys-in-non-editable-element.html
fast/events/ios/keypress-keys-in-non-editable-element.html
* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
Do not use unified source build strategy when building WebEvent.mm as it makes
use of SoftLinking macros that are incompatible with this strategy.
* platform/ios/KeyEventIOS.mm:
(WebCore::windowsKeyCodeForCharCode): Recognize some special AppKit special char codes.
These special char codes are generated by WebKit. WebKit uses the same special char codes
as AppKit as a convenience instead of defining our own constants for the same purpose.
Encoding the special UIKit input strings (e.g. up arrow) as distinct char codes allows us
to use integer arithmetic and switch blocks to map characters to Windows virtual key
codes as opposed to special cased branches to perform pointer or string comparisions.
The latter would be necessary in Modern WebKit in order for key down events to be properly
disambiguated to dispatch a DOM keypress event because pointers are not perserved, though
what they point to is, when sending the WebEvent from UIProcess to the WebProcess and
vice versa.
(WebCore::isFunctionKey): Convenience function that determines whether the specified char
code corresponds to a function key on the keyboard. The term "function key" is taken from
AppKit parlance to describe a special keyboard key. These keys include F1, F2, ..., F24,
and cursor keys among other special keyboard keys.
(WebCore::PlatformKeyboardEvent::disambiguateKeyDownEvent): Write in terms of isFunctionKey().
* platform/ios/PlatformEventFactoryIOS.h:
* platform/ios/PlatformEventFactoryIOS.mm:
(WebCore::keyIdentifierForKeyEvent): Remove code to handle UIKit special input strings as
we now map such special input strings to char codes and hence can use the default code path.
(WebCore::keyForKeyEvent): Ditto.
(WebCore::codeForKeyEvent): Remove code to compute the Window virtual key code corresponding
to a UIKit special key command now that we map such special input strings to char codes and
subsequently map the char codes to the Windows virtual key code (see -[WebEvent initWithKeyEventType:...]
constructors). So, we can now use WebEvent.keyCode directly to compute the DOM UIEvents code
for the event.
(WebCore::PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder): Remove code to fix up
WebEvent.keyCode to account for UIKit special input strings now that we map such special key
commands to char codes and subsequently map the char codes to the Windows virtual key code (see -[WebEvent initWithKeyEventType:...]
constructors). So, we can now take WebEvent.keyCode verbatim to be the Window virtual key code.
(WebCore::convertSpecialKeyToCharCode): Deleted.
(WebCore::keyCodeForEvent): Deleted.
* platform/ios/WebEvent.mm:
(normalizedStringWithAppKitCompatibilityMapping): Added; converts a UIKit character string
to the corresponding AppKit-compatible one (if not already compatible). See the explaination
for WebCore::windowsKeyCodeForCharCode() above for more details on why this is done.
(-[WebEvent initWithKeyEventType:timeStamp:characters:charactersIgnoringModifiers:modifiers:isRepeating:withFlags:keyCode:isTabKey:characterSet:]):
(-[WebEvent initWithKeyEventType:timeStamp:characters:charactersIgnoringModifiers:modifiers:isRepeating:withFlags:withInputManagerHint:keyCode:isTabKey:]):
Normalize the character strings to be AppKit compatible.
Source/WebCore/PAL:
Forward declare or define more SPI.
* pal/spi/cocoa/IOKitSPI.h:
* pal/spi/ios/UIKitSPI.h:
Source/WebKit:
Take the key code of WebEvent to be the key code for the new WebKeyboardEvent verbatim
now that we normalize the character strings of the WebEvent to account for the special
UIKit input strings.
* Shared/ios/WebIOSEventFactory.mm:
(WebIOSEventFactory::createWebKeyboardEvent):
Tools:
Add support for testing keys Forward Delete and Num Lock / Clear.
* WebKitTestRunner/ios/HIDEventGenerator.mm:
(hidUsageCodeForCharacter):
LayoutTests:
Add tests to ensure that we do not regress key identification for special keys.
Update the expected results for test fast/events/ios/keydown-keyup-special-keys-in-non-editable-element.html
now that we correctly identify some more keys.
* fast/events/ios/keydown-keyup-arrow-keys-in-non-editable-element-expected.txt: Added.
* fast/events/ios/keydown-keyup-arrow-keys-in-non-editable-element.html: Added.
* fast/events/ios/keydown-keyup-special-keys-in-non-editable-element-expected.txt:
* fast/events/ios/keypress-keys-in-non-editable-element-expected.txt: Added.
* fast/events/ios/keypress-keys-in-non-editable-element.html: Added.
* resources/ui-helper.js:
(window.UIHelper.typeCharacter): Actually type the specified character in DumpRenderTree.
Canonical link: https://commits.webkit.org/205106@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@236678 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-10-01 18:35:37 +00:00
|
|
|
eventSender.keyDown(characterString);
|
2018-08-06 15:01:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-09-06 21:48:34 +00:00
|
|
|
const escapedString = characterString.replace(/\\/g, "\\\\").replace(/`/g, "\\`");
|
2018-08-06 15:01:47 +00:00
|
|
|
const uiScript = `uiController.typeCharacterUsingHardwareKeyboard(\`${escapedString}\`, () => uiController.uiScriptComplete())`;
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(uiScript, resolve));
|
|
|
|
}
|
|
|
|
|
|
|
|
static applyAutocorrection(newText, oldText)
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const [escapedNewText, escapedOldText] = [newText.replace(/`/g, "\\`"), oldText.replace(/`/g, "\\`")];
|
|
|
|
const uiScript = `uiController.applyAutocorrection(\`${escapedNewText}\`, \`${escapedOldText}\`, () => uiController.uiScriptComplete())`;
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(uiScript, resolve));
|
|
|
|
}
|
2018-08-28 16:34:25 +00:00
|
|
|
|
|
|
|
static inputViewBounds()
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
2018-08-28 16:34:25 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.uiScriptComplete(JSON.stringify(uiController.inputViewBounds));
|
|
|
|
})()`, jsonString => {
|
|
|
|
resolve(JSON.parse(jsonString));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
[iOS] Allow SPI clients to lay out at arbitrarily scaled sizes and scale to fit the view
https://bugs.webkit.org/show_bug.cgi?id=190504
<rdar://problem/45117760>
Reviewed by Tim Horton.
Source/WebCore:
Add support in ViewportConfiguration for applying a layout size scale factor to the viewport. See below for
more details.
Tests: fast/viewport/ios/constant-width-viewport-after-changing-view-scale.html
fast/viewport/ios/device-width-viewport-after-changing-view-scale.html
* page/ViewportConfiguration.cpp:
(WebCore::ViewportConfiguration::setViewLayoutSize):
The viewport's layout size may now be changed alongside the layout size scale factor. If either of these two
variables change, we recompute our minimum layout size and viewport configuration parameters.
(WebCore::ViewportConfiguration::shouldIgnoreHorizontalScalingConstraints const):
(WebCore::ViewportConfiguration::nativeWebpageParameters):
(WebCore::ViewportConfiguration::testingParameters):
(WebCore::ViewportConfiguration::updateConfiguration):
Multiply the minimum scale, initial scale, and maximum scale by the layout size scale factor. This allows us to
keep the document well-proportioned within the viewport, while still laying out at a different layout size.
(WebCore::ViewportConfiguration::updateMinimumLayoutSize):
Compute the minimum layout size by scaling the default layout size derived from our view's size.
(WebCore::ViewportConfiguration::layoutWidth const):
(WebCore::ViewportConfiguration::layoutHeight const):
* page/ViewportConfiguration.h:
Maintain the original initial scale, unaffected by the layout size scale factor. This is used when computing
layout width and height to prevent scaling by the layout size scale factor twice when computing layout sizes.
(WebCore::ViewportConfiguration::description const):
Include the layout size scale factor in ViewportConfiguration's description string.
(WebCore::ViewportConfiguration::Parameters::operator== const):
(WebCore::operator<<):
Source/WebKit:
Add support for _setViewScale: and _viewScale on iOS. While similar in concept to macOS, changing this property
on iOS uses viewport configurations to change the minimum layout size of the document and apply view scaling.
Setting the view scale on iOS to a value `s` multiplies the minimium layout size by a factor `1 / s`, but also
multiplies the initial, minimum and maximum scales by a factor of `s`. The net effect of applying this scale
causes the page to lay out at a larger width and shrink (or a smaller width and expand) to fit the viewport.
* Shared/WebPageCreationParameters.cpp:
(WebKit::WebPageCreationParameters::encode const):
(WebKit::WebPageCreationParameters::decode):
* Shared/WebPageCreationParameters.h:
Send `viewportConfigurationLayoutSizeScaleFactor` alongside `viewportConfigurationViewLayoutSize`.
(-[WKWebView _dispatchSetViewLayoutSize:]):
(-[WKWebView _viewScale]):
(-[WKWebView _setViewScale:]):
Provide a different implementation of `_setViewScale:` on iOS, by scaling the effective minimum layout size.
(See above for more detail).
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
Add missing API availability annotations for the _viewScale property.
* UIProcess/API/mac/WKView.mm:
(-[WKView _setViewScale:]):
* UIProcess/Cocoa/WebViewImpl.mm:
Both -[WKView _setViewScale:] and -[WKWebView _setViewScale:] throw Objective C exceptions upon receiving a bad
argument (e.g. scale <= 0). However, logic for throwing this exception is specific to iOS in WKWebView, and
handled in WebViewImpl on macOS. To make this less confusing, move the exception throwing code out of
!PLATFORM(MAC) in WKWebView, and move the path for raising this exception in WKView on macOS from WebViewImpl to
WKView.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::creationParameters):
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::layoutSizeScaleFactor const):
Tie the notion of "view scale" on iOS to `layoutSizeScaleFactor`. As its name suggests, this is a scale factor
by which we transform the layout size.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::setViewportConfigurationViewLayoutSize):
* WebProcess/WebPage/WebPage.cpp:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Plumb the layout size scale factor over to the web process, along with the layout size.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::setViewportConfigurationViewLayoutSize):
Tools:
Teach UIScriptController to set WKWebView's view scale via a new `setViewScale` method, supported in WebKit2 on
macOS and iOS.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::setViewScale):
* DumpRenderTree/mac/UIScriptControllerMac.mm:
(WTR::UIScriptController::setViewScale):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::setViewScale):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/UIScriptControllerCocoa.mm: Added.
Add a new file for UIScriptController methods on Cocoa platforms.
(WTR::UIScriptController::setViewScale):
* WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::cocoaResetStateToConsistentValues):
Ensure that _viewScale is reset to 1 after running a layout test.
LayoutTests:
Add two new layout tests on iOS that change WKWebView's view scale, and measure the resulting window sizes and
lengths of viewport units.
* fast/viewport/ios/constant-width-viewport-after-changing-view-scale-expected.txt: Added.
* fast/viewport/ios/constant-width-viewport-after-changing-view-scale.html: Added.
Add a test page with a viewport meta tag that has a constant width and an explicit initial scale of 0.5.
* fast/viewport/ios/device-width-viewport-after-changing-view-scale-expected.txt: Added.
* fast/viewport/ios/device-width-viewport-after-changing-view-scale.html: Added.
Add a test page with a viewport meta tag at device-width, with initial scale 1.
* resources/ui-helper.js:
(window.UIHelper.setViewScale):
Add a convenience function that wraps a UI script invocation of `setViewScale` in a promise.
(window.UIHelper):
Canonical link: https://commits.webkit.org/205461@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237087 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-10-12 23:13:37 +00:00
|
|
|
|
2018-11-07 14:57:40 +00:00
|
|
|
static calendarType()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.doAfterNextStablePresentationUpdate(() => {
|
|
|
|
uiController.uiScriptComplete(JSON.stringify(uiController.calendarType));
|
|
|
|
})
|
|
|
|
})()`, jsonString => {
|
|
|
|
resolve(JSON.parse(jsonString));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-02-23 02:30:07 +00:00
|
|
|
static setDefaultCalendarType(calendarIdentifier, localeIdentifier)
|
2018-11-07 14:57:40 +00:00
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
2020-02-23 02:30:07 +00:00
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.setDefaultCalendarType('${calendarIdentifier}', '${localeIdentifier}')`, resolve));
|
2018-11-07 14:57:40 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
[iOS] Allow SPI clients to lay out at arbitrarily scaled sizes and scale to fit the view
https://bugs.webkit.org/show_bug.cgi?id=190504
<rdar://problem/45117760>
Reviewed by Tim Horton.
Source/WebCore:
Add support in ViewportConfiguration for applying a layout size scale factor to the viewport. See below for
more details.
Tests: fast/viewport/ios/constant-width-viewport-after-changing-view-scale.html
fast/viewport/ios/device-width-viewport-after-changing-view-scale.html
* page/ViewportConfiguration.cpp:
(WebCore::ViewportConfiguration::setViewLayoutSize):
The viewport's layout size may now be changed alongside the layout size scale factor. If either of these two
variables change, we recompute our minimum layout size and viewport configuration parameters.
(WebCore::ViewportConfiguration::shouldIgnoreHorizontalScalingConstraints const):
(WebCore::ViewportConfiguration::nativeWebpageParameters):
(WebCore::ViewportConfiguration::testingParameters):
(WebCore::ViewportConfiguration::updateConfiguration):
Multiply the minimum scale, initial scale, and maximum scale by the layout size scale factor. This allows us to
keep the document well-proportioned within the viewport, while still laying out at a different layout size.
(WebCore::ViewportConfiguration::updateMinimumLayoutSize):
Compute the minimum layout size by scaling the default layout size derived from our view's size.
(WebCore::ViewportConfiguration::layoutWidth const):
(WebCore::ViewportConfiguration::layoutHeight const):
* page/ViewportConfiguration.h:
Maintain the original initial scale, unaffected by the layout size scale factor. This is used when computing
layout width and height to prevent scaling by the layout size scale factor twice when computing layout sizes.
(WebCore::ViewportConfiguration::description const):
Include the layout size scale factor in ViewportConfiguration's description string.
(WebCore::ViewportConfiguration::Parameters::operator== const):
(WebCore::operator<<):
Source/WebKit:
Add support for _setViewScale: and _viewScale on iOS. While similar in concept to macOS, changing this property
on iOS uses viewport configurations to change the minimum layout size of the document and apply view scaling.
Setting the view scale on iOS to a value `s` multiplies the minimium layout size by a factor `1 / s`, but also
multiplies the initial, minimum and maximum scales by a factor of `s`. The net effect of applying this scale
causes the page to lay out at a larger width and shrink (or a smaller width and expand) to fit the viewport.
* Shared/WebPageCreationParameters.cpp:
(WebKit::WebPageCreationParameters::encode const):
(WebKit::WebPageCreationParameters::decode):
* Shared/WebPageCreationParameters.h:
Send `viewportConfigurationLayoutSizeScaleFactor` alongside `viewportConfigurationViewLayoutSize`.
(-[WKWebView _dispatchSetViewLayoutSize:]):
(-[WKWebView _viewScale]):
(-[WKWebView _setViewScale:]):
Provide a different implementation of `_setViewScale:` on iOS, by scaling the effective minimum layout size.
(See above for more detail).
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
Add missing API availability annotations for the _viewScale property.
* UIProcess/API/mac/WKView.mm:
(-[WKView _setViewScale:]):
* UIProcess/Cocoa/WebViewImpl.mm:
Both -[WKView _setViewScale:] and -[WKWebView _setViewScale:] throw Objective C exceptions upon receiving a bad
argument (e.g. scale <= 0). However, logic for throwing this exception is specific to iOS in WKWebView, and
handled in WebViewImpl on macOS. To make this less confusing, move the exception throwing code out of
!PLATFORM(MAC) in WKWebView, and move the path for raising this exception in WKView on macOS from WebViewImpl to
WKView.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::creationParameters):
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::layoutSizeScaleFactor const):
Tie the notion of "view scale" on iOS to `layoutSizeScaleFactor`. As its name suggests, this is a scale factor
by which we transform the layout size.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::setViewportConfigurationViewLayoutSize):
* WebProcess/WebPage/WebPage.cpp:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Plumb the layout size scale factor over to the web process, along with the layout size.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::setViewportConfigurationViewLayoutSize):
Tools:
Teach UIScriptController to set WKWebView's view scale via a new `setViewScale` method, supported in WebKit2 on
macOS and iOS.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::setViewScale):
* DumpRenderTree/mac/UIScriptControllerMac.mm:
(WTR::UIScriptController::setViewScale):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::setViewScale):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/UIScriptControllerCocoa.mm: Added.
Add a new file for UIScriptController methods on Cocoa platforms.
(WTR::UIScriptController::setViewScale):
* WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::cocoaResetStateToConsistentValues):
Ensure that _viewScale is reset to 1 after running a layout test.
LayoutTests:
Add two new layout tests on iOS that change WKWebView's view scale, and measure the resulting window sizes and
lengths of viewport units.
* fast/viewport/ios/constant-width-viewport-after-changing-view-scale-expected.txt: Added.
* fast/viewport/ios/constant-width-viewport-after-changing-view-scale.html: Added.
Add a test page with a viewport meta tag that has a constant width and an explicit initial scale of 0.5.
* fast/viewport/ios/device-width-viewport-after-changing-view-scale-expected.txt: Added.
* fast/viewport/ios/device-width-viewport-after-changing-view-scale.html: Added.
Add a test page with a viewport meta tag at device-width, with initial scale 1.
* resources/ui-helper.js:
(window.UIHelper.setViewScale):
Add a convenience function that wraps a UI script invocation of `setViewScale` in a promise.
(window.UIHelper):
Canonical link: https://commits.webkit.org/205461@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237087 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-10-12 23:13:37 +00:00
|
|
|
static setViewScale(scale)
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.setViewScale(${scale})`, resolve));
|
|
|
|
}
|
[iOS] [Datalist] Can't pick datalist suggestions in a stock WKWebView
https://bugs.webkit.org/show_bug.cgi?id=190621
<rdar://problem/45310649>
Reviewed by Tim Horton.
Source/WebKit:
Fixes the bug by refactoring datalist suggestion information on iOS; currently, we override text suggestions on
_WKFormInputSession. This only works for a few internal clients (including Safari) that set a _WKInputDelegate
and also implement either -_webView:willStartInputSession: or -_webView:didStartInputSession:, which is
necessary in order to ensure that WebKit creates and maintains a form input session.
The two pieces of information that datalist code needs to vend to WKContentView are a list of UITextSuggestions
and a custom input view, which are both currently properties of _WKFormInputSession. This patch lifts these out
of the input session and makes them properties of WKContentView, which are used in
WebDataListSuggestionsDropdownIOS.
Test: fast/forms/datalist/datalist-textinput-suggestions-order.html
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
Add new properties to WKContentView: an input view for datalist suggestions, and a list of text suggestions.
(-[WKFormInputSession setSuggestions:]):
(-[WKContentView setupInteraction]):
(-[WKContentView cleanupInteraction]):
(-[WKContentView _endEditing]):
Pull out common logic when resigning first responder or tabbing to the next or previous text field into a new
helper. This helper notifies `_inputPeripheral`, `_formInputSession`, and `_dataListTextSuggestionsInputView`
when editing has ended; the input peripheral and suggestions input view use this chance to send the value of the
form control to the web process.
(-[WKContentView resignFirstResponderForWebView]):
(-[WKContentView inputView]):
If a custom input view is not set but we have an input view for a datalist's text suggestions, use the datalist
input view.
(-[WKContentView accessoryTab:]):
(-[WKContentView _stopAssistingNode]):
Clear datalist state on WKContentView.
(-[WKContentView dataListTextSuggestionsInputView]):
(-[WKContentView dataListTextSuggestions]):
(-[WKContentView setDataListTextSuggestionsInputView:]):
(-[WKContentView setDataListTextSuggestions:]):
(-[WKContentView updateTextSuggestionsForInputDelegate]):
Pull out logic for setting suggestions on UIKit's `inputDelegate` (i.e. UIKeyboardImpl). We now first consult
internally-vended text suggestions from _WKFormInputSession; if an internal client has not overridden our text
suggestions, then we simply use suggestions from the current datalist (if present).
* UIProcess/ios/WebDataListSuggestionsDropdownIOS.mm:
(-[WKDataListSuggestionsPicker updateWithInformation:]):
(-[WKDataListSuggestionsPicker showSuggestionsDropdown:activationType:]):
(-[WKDataListSuggestionsPicker invalidate]):
(-[WKDataListSuggestionsPopover updateWithInformation:]):
(-[WKDataListSuggestionsPopover showSuggestionsDropdown:activationType:]):
(-[WKDataListSuggestionsPopover didSelectOptionAtIndex:]):
Change all the places that currently manipulate WKContentView's form input session to directly set text
suggestions and the text suggestion input view on the content view instead.
Tools:
Add a UIScriptController hook to resign first responder on WKWebView. See LayoutTests/ChangeLog for more detail.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::resignFirstResponder):
* DumpRenderTree/mac/UIScriptControllerMac.mm:
(WTR::UIScriptController::resignFirstResponder):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::resignFirstResponder):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/UIScriptControllerCocoa.mm:
(WTR::UIScriptController::resignFirstResponder):
* WebKitTestRunner/ios/PlatformWebViewIOS.mm:
(WTR::PlatformWebView::makeWebViewFirstResponder):
Implement this method stub on iOS, to ensure that TestController::resetStateToConsistentValues restores first
responder on the WKWebView when running iOS layout tests.
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
After resigning first responder to dismiss any on-screen keyboard, ensure that we restore first responder.
LayoutTests:
Refactor an existing layout test to run on both iOS and macOS. On both platforms, it checks that the top
suggestion respects option element order in the document, as well as the current contents of the text field.
On macOS, we use arrow keys and hit return to select a suggestion; on iOS, we tap the suggestions button and
simulate hitting the done button on the input view to dismiss the keyboard.
* fast/forms/datalist/datalist-textinput-suggestions-order-expected.txt:
* fast/forms/datalist/datalist-textinput-suggestions-order.html:
* platform/ios/TestExpectations:
Enable this test on iOS.
* resources/ui-helper.js:
(window.UIHelper.resignFirstResponder):
(window.UIHelper):
Canonical link: https://commits.webkit.org/205670@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237305 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-10-19 22:00:32 +00:00
|
|
|
|
|
|
|
static resignFirstResponder()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.resignFirstResponder()`, resolve));
|
|
|
|
}
|
[iOS] Changing view scale sometimes does not zoom the page to the new initial scale, when the page is at initial scale
https://bugs.webkit.org/show_bug.cgi?id=191180
<rdar://problem/45744786>
Reviewed by Simon Fraser.
Source/WebCore:
When computing the minimum scale in ViewportConfiguration::minimumScale, if our content width or height is
shorter than the view width or height, then we recompute the minimum scale such that the content dimensions will
fill the bounds of the view by setting the minimum scale to the view width or height divided by the content
width or height.
Suppose the minimum scale is equal to some value `s`; additionally, let `w_c` denote the content width and `w_v`
denote the view width (as integers). If `w_v / s` is not an integral value, the computed content width `w_c` may
be rounded, such that `w_v / w_c` is not precisely equal to `s`. In the case that `w_v / w_c` is ever so
slightly larger than `s`, we will end up overriding the minimum scale `s` with `w_v / w_c`.
As a result, specifying a viewport with a decimal `minimum-scale` will sometimes cause the computed minimum
scale of the viewport (and platform view) to be very slightly different from the minimum scale. The new layout
test below exercises this scenario, specifying a viewport with minimum and initial scales of 0.94 that results
in `ViewportConfiguration::minimumScale` returning 0.94158.
With the `WebPage::setViewportConfigurationViewLayoutSize` check added in r237127, this means setting
`_viewScale:` when the page is at initial scale sometimes doesn't zoom the page to the new initial scale when it
should, since the page scale factor and the initial scale are different enough such that
`areEssentiallyEqualAsFloat` returns false.
This patch addresses these issues by snapping to the minimum scale if the computed scale that fits content
dimensions to view dimensions results in a minimum scale that is close enough to the configuration's minimum
scale, such that the difference can be attributed to rounding error when computing content or view dimensions.
Test: fast/viewport/ios/viewport-minimum-and-initial-scale.html
* page/ViewportConfiguration.cpp:
(WebCore::ViewportConfiguration::minimumScale const):
LayoutTests:
Add a layout test, and make some adjustments to UIHelper.
* fast/viewport/ios/constant-width-viewport-after-changing-view-scale.html:
* fast/viewport/ios/device-width-viewport-after-changing-view-scale.html:
* fast/viewport/ios/viewport-minimum-and-initial-scale-expected.txt: Added.
* fast/viewport/ios/viewport-minimum-and-initial-scale.html: Added.
Add a new layout test that contains a viewport meta tag with minimum and initial scales set to 0.94, and checks
that the resulting minimum and initial scales are 0.94 instead of 0.94158.
* fast/viewport/watchos/viewport-disable-extra-zoom-adaptations.html:
* resources/ui-helper.js:
Make UIHelper.zoomScale return a number rather than a string, and adjust a few call sites.
(window.UIHelper.zoomScale):
(window.UIHelper.minimumZoomScale):
(window.UIHelper):
Canonical link: https://commits.webkit.org/206009@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237743 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-11-02 18:10:23 +00:00
|
|
|
|
[iPadOS] Do not present custom input peripherals when switching back to a tab with a focused element
https://bugs.webkit.org/show_bug.cgi?id=225541
<rdar://problem/77537795>
Reviewed by Wenson Hsieh.
Source/WebKit:
With the introduction of desktop-class browing on iPad, form control
elements began to retain focus even after their input peripheral
(popover, menu, etc.) was dismissed. This behavior matches macOS - when
a <select> element is clicked, a menu is presented, and when a option
is selected, the menu is dismissed but the element retains focus.
Consequently, when a <select> menu is dismissed by choosing an option on
an iPad with a hardware keyboard, the element retains focus. Now, when
switching tabs and coming back to the tab with the focused <select>, an
activity state update is triggered. Upon recognizing that there is a
focused element, an ElementDidFocus message is sent to the UIProcess.
In [WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:],
the focus is given permission to present the input peripheral (menu)
when the hardware keyboard is attached. This is necessary when necessary
when focusing a text input, because the UCB needs to be displayed and
text selection needs to be set up. However, the behavior is undesirable
for elements that present a popover or a menu (select, color inputs, and
date inputs), since the user is unexpectedly shown an input peripheral.
Even worse, the user's scroll position will be changed to ensure the
focused element is visible.
To fix the undesirable behavior, and get closer to the macOS behavior,
custom input peripherals should not be displayed when switching back
to a tab with a focused element.
Test: fast/forms/ios/focus-select-and-switch-tabs.html
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:]):
Only show the input peripheral if it is not a keyboard view.
Tools:
Updated a UIScriptController hook that simulates attaching a hardware
keyboard to also swizzle [UIKeyboard isInHardwareKeyboardMode].
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformInitialize):
(WTR::TestController::platformResetStateToConsistentValues):
Moved the default swizzling behavior into this method so that it remains
consistent across tests.
Unfortunately, the default swizzling behavior contrasts with the default
value of GSEventSetHardwareKeyboardAttached. However, this is an existing
inconsistency, and should be looked at more carefully in a separate
investigation.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::returnYes):
(WTR::returnNo):
(WTR::UIScriptControllerIOS::setHardwareKeyboardAttached):
LayoutTests:
Added a test which simulates a tab switch by removing and re-adding the
webview to the window.
* fast/forms/ios/focus-select-and-switch-tabs-expected.txt: Added.
* fast/forms/ios/focus-select-and-switch-tabs.html: Added.
* resources/ui-helper.js:
(window.UIHelper.becomeFirstResponder):
(window.UIHelper.removeViewFromWindow):
(window.UIHelper.addViewToWindow):
Canonical link: https://commits.webkit.org/237532@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@277265 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-05-10 16:26:17 +00:00
|
|
|
static becomeFirstResponder()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.becomeFirstResponder()`, resolve));
|
|
|
|
}
|
|
|
|
|
|
|
|
static removeViewFromWindow()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.removeViewFromWindow()`, resolve));
|
|
|
|
}
|
|
|
|
|
|
|
|
static addViewToWindow()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.addViewToWindow()`, resolve));
|
|
|
|
}
|
|
|
|
|
[iOS] Changing view scale sometimes does not zoom the page to the new initial scale, when the page is at initial scale
https://bugs.webkit.org/show_bug.cgi?id=191180
<rdar://problem/45744786>
Reviewed by Simon Fraser.
Source/WebCore:
When computing the minimum scale in ViewportConfiguration::minimumScale, if our content width or height is
shorter than the view width or height, then we recompute the minimum scale such that the content dimensions will
fill the bounds of the view by setting the minimum scale to the view width or height divided by the content
width or height.
Suppose the minimum scale is equal to some value `s`; additionally, let `w_c` denote the content width and `w_v`
denote the view width (as integers). If `w_v / s` is not an integral value, the computed content width `w_c` may
be rounded, such that `w_v / w_c` is not precisely equal to `s`. In the case that `w_v / w_c` is ever so
slightly larger than `s`, we will end up overriding the minimum scale `s` with `w_v / w_c`.
As a result, specifying a viewport with a decimal `minimum-scale` will sometimes cause the computed minimum
scale of the viewport (and platform view) to be very slightly different from the minimum scale. The new layout
test below exercises this scenario, specifying a viewport with minimum and initial scales of 0.94 that results
in `ViewportConfiguration::minimumScale` returning 0.94158.
With the `WebPage::setViewportConfigurationViewLayoutSize` check added in r237127, this means setting
`_viewScale:` when the page is at initial scale sometimes doesn't zoom the page to the new initial scale when it
should, since the page scale factor and the initial scale are different enough such that
`areEssentiallyEqualAsFloat` returns false.
This patch addresses these issues by snapping to the minimum scale if the computed scale that fits content
dimensions to view dimensions results in a minimum scale that is close enough to the configuration's minimum
scale, such that the difference can be attributed to rounding error when computing content or view dimensions.
Test: fast/viewport/ios/viewport-minimum-and-initial-scale.html
* page/ViewportConfiguration.cpp:
(WebCore::ViewportConfiguration::minimumScale const):
LayoutTests:
Add a layout test, and make some adjustments to UIHelper.
* fast/viewport/ios/constant-width-viewport-after-changing-view-scale.html:
* fast/viewport/ios/device-width-viewport-after-changing-view-scale.html:
* fast/viewport/ios/viewport-minimum-and-initial-scale-expected.txt: Added.
* fast/viewport/ios/viewport-minimum-and-initial-scale.html: Added.
Add a new layout test that contains a viewport meta tag with minimum and initial scales set to 0.94, and checks
that the resulting minimum and initial scales are 0.94 instead of 0.94158.
* fast/viewport/watchos/viewport-disable-extra-zoom-adaptations.html:
* resources/ui-helper.js:
Make UIHelper.zoomScale return a number rather than a string, and adjust a few call sites.
(window.UIHelper.zoomScale):
(window.UIHelper.minimumZoomScale):
(window.UIHelper):
Canonical link: https://commits.webkit.org/206009@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237743 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-11-02 18:10:23 +00:00
|
|
|
static minimumZoomScale()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.uiScriptComplete(uiController.minimumZoomScale);
|
|
|
|
})()`, scaleAsString => resolve(parseFloat(scaleAsString)))
|
|
|
|
});
|
|
|
|
}
|
Make it possible to edit images inline
https://bugs.webkit.org/show_bug.cgi?id=191352
<rdar://problem/30107985>
Reviewed by Dean Jackson.
Source/WebCore:
Tests: editing/images/basic-editable-image.html
editing/images/reparent-editable-image-maintains-strokes.html
Add the beginnings of a mechanism to replace images with a special attribute
with a native drawing view in the UI process.
* page/Settings.yaml:
Add a setting to control whether images become natively editable when they
have the x-apple-editable-image attribute.
* html/HTMLImageElement.cpp:
(WebCore::HTMLImageElement::editableImageViewID const):
Lazily generate an EmbeddedViewID and persist it on the <img> element.
* html/HTMLImageElement.h:
Rearrange the service controls methods to sit before the members.
Add m_editableImageViewID and editableImageViewID().
* platform/graphics/GraphicsLayer.cpp:
(WebCore::GraphicsLayer::nextEmbeddedViewID):
* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::setContentsToEmbeddedView):
Add a new ContentsLayerPurpose, EmbeddedView, which is only supported
on Cocoa platforms and when using RemoteLayerTree.
Add ContentsLayerEmbeddedViewType, which currently only has the EditableImage type.
Add setContentsToEmbeddedView, which takes a ContentsLayerEmbeddedViewType
and an EmbeddedViewID to uniquely identify and communicate about the
embedded view (which may move between layers, since it is tied to an element).
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::createPlatformCALayerForEmbeddedView):
(WebCore::GraphicsLayerCA::setContentsToEmbeddedView):
When setting GraphicsLayer's contents to an embedded view, we use
a special PlatformCALayer factory that takes the EmbeddedViewID and type.
GraphicsLayerCARemote will override this and make a correctly-initialized
PlatformCALayerRemote that keeps track of the EmbeddedViewID.
* platform/graphics/ca/GraphicsLayerCA.h:
* platform/graphics/ca/PlatformCALayer.cpp:
(WebCore::operator<<):
* platform/graphics/ca/PlatformCALayer.h:
* platform/graphics/ca/cocoa/PlatformCALayerCocoa.h:
* platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
(WebCore::PlatformCALayerCocoa::PlatformCALayerCocoa):
(WebCore::PlatformCALayerCocoa::embeddedViewID const):
Add stubs and logging for EmbeddedViewID on PlatformCALayer.
These will be overridden by PlatformCALayerRemote to do more interesting things.
* rendering/RenderImage.cpp:
(WebCore::RenderImage::isEditableImage const):
Add a getter that return true if the setting is enabled and
x-apple-editable-image is empty or true.
(WebCore::RenderImage::requiresLayer const):
RenderImage requires a layer either if RenderReplaced does, or we are an
editable image.
* rendering/RenderImage.h:
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::shouldBeNormalFlowOnly const):
(WebCore::RenderLayer::calculateClipRects const):
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateConfiguration):
Push the EmbeddedViewID and type down to GraphicsLayer for editable images.
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::requiresCompositingLayer const):
(WebCore::RenderLayerCompositor::requiresOwnBackingStore const):
(WebCore::RenderLayerCompositor::reasonsForCompositing const):
(WebCore::RenderLayerCompositor::requiresCompositingForEditableImage const):
* rendering/RenderLayerCompositor.h:
Make editable images require compositing implicitly.
Source/WebKit:
* Platform/spi/ios/PencilKitSPI.h: Added.
* Shared/RemoteLayerTree/RemoteLayerBackingStore.mm:
(WebKit::RemoteLayerBackingStore::drawInContext):
* Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h:
* Shared/RemoteLayerTree/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::LayerCreationProperties::LayerCreationProperties):
(WebKit::RemoteLayerTreeTransaction::LayerCreationProperties::encode const):
(WebKit::RemoteLayerTreeTransaction::LayerCreationProperties::decode):
* WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.cpp:
(WebKit::GraphicsLayerCARemote::createPlatformCALayerForEmbeddedView):
* WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.h:
* WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.cpp:
(WebKit::PlatformCALayerRemote::createForEmbeddedView):
(WebKit::PlatformCALayerRemote::PlatformCALayerRemote):
(WebKit::PlatformCALayerRemote::embeddedViewID const):
* WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeContext.mm:
(WebKit::RemoteLayerTreeContext::layerWasCreated):
Propagate EmbeddedViewID through the PlatformCALayer constructor and
through the layer creation parameters to the UI process.
* Shared/WebPreferences.yaml:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initializeWithConfiguration:]):
* UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
(-[WKWebViewConfiguration init]):
(-[WKWebViewConfiguration copyWithZone:]):
(-[WKWebViewConfiguration _setEditableImagesEnabled:]):
(-[WKWebViewConfiguration _editableImagesEnabled]):
* UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
Add a preference to enable editable images.
* UIProcess/RemoteLayerTree/RemoteLayerTreeHost.h:
* UIProcess/RemoteLayerTree/RemoteLayerTreeHost.mm:
(WebKit::RemoteLayerTreeHost::layerWillBeRemoved):
(WebKit::RemoteLayerTreeHost::clearLayers):
(WebKit::RemoteLayerTreeHost::createLayer):
Keep track of "embedded views" in two maps: embeddedViewID->UIView,
and layerID->embeddedViewID. Clean them up when layers go away.
If a embedded view is reparented, currently it must be added to a new
layer in the same commit as it is removed from the previous layer
in order to persist the view's state (otherwise the view will be
destroyed and recreated). This will be less of a problem after future
patches introduce serialization of image data and whatnot.
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm:
(WebKit::RemoteLayerTreeHost::createLayer):
(WebKit::RemoteLayerTreeHost::createEmbeddedView):
Move the various remote layer tree UIView subclasses out into a separate file.
Add createEmbeddedView, which is used for LayerTypeEditableImageLayer,
and creates a WKDrawingView and sticks it in the maps.
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h: Added.
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm: Added.
(-[UIView _web_recursiveFindDescendantInteractibleViewAtPoint:withEvent:]):
(-[UIView _web_findDescendantViewAtPoint:withEvent:]):
(-[WKCompositingView hitTest:withEvent:]):
(-[WKCompositingView description]):
(+[WKTransformView layerClass]):
(+[WKSimpleBackdropView layerClass]):
(+[WKShapeView layerClass]):
(-[WKRemoteView initWithFrame:contextID:]):
(+[WKRemoteView layerClass]):
(-[WKBackdropView hitTest:withEvent:]):
(-[WKBackdropView description]):
(-[WKChildScrollView initWithFrame:]):
Move various remote layer tree UIView subclasses here, to their own file.
Make our UIView hit testing override test for views that conform to the
protocol "WKNativelyInteractible", which switches to normal UIView hit
testing. WKDrawingView will be the one such view.
Add WKChildScrollView and pull the one thing we customize out into it,
to make RemoteLayerTreeHost::createLayer less logic-ful.
* UIProcess/ios/WKDrawingView.h: Added.
* UIProcess/ios/WKDrawingView.mm: Added.
(-[WKDrawingView init]):
(-[WKDrawingView layoutSubviews]):
Add a very simple WKDrawingView, which uses PKCanvasView to edit the image.
* WebKit.xcodeproj/project.pbxproj:
* SourcesCocoa.txt:
Add the new files.
Tools:
* WebKitTestRunner/TestController.cpp:
(WTR::updateTestOptionsFromTestHeader):
* WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::hasSameInitializationOptions const):
* WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::platformCreateWebView):
Add a test option to enable editable images.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::drawSquareInEditableImage):
(WTR::UIScriptController::numberOfStrokesInEditableImage):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::drawSquareInEditableImage):
(WTR::UIScriptController::numberOfStrokesInEditableImage):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* TestRunnerShared/spi/PencilKitTestSPI.h: Added.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::findEditableImageCanvas):
(WTR::UIScriptController::drawSquareInEditableImage):
(WTR::UIScriptController::numberOfStrokesInEditableImage):
Add the ability to draw on a PKCanvasView that is a subview of the WKWebView,
and also to retrieve the number of strokes currently on the PKCanvasView.
Currently this just takes the first canvas; we might need to make it
take an identifier or something in the future if we need tests with multiple
canvases. The indirect testing mechanism is required because PKCanvasView
can currently not actually paint its strokes in the Simulator.
LayoutTests:
* TestExpectations:
* editing/images/basic-editable-image-expected.txt: Added.
* editing/images/basic-editable-image.html: Added.
* editing/images/reparent-editable-image-maintains-strokes-expected.txt: Added.
* editing/images/reparent-editable-image-maintains-strokes.html: Added.
* platform/ios-wk2/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.drawSquareInEditableImage):
(window.UIHelper.numberOfStrokesInEditableImage):
(window.UIHelper):
Add tests that we can find and draw in editable images, and that if
the element is moved around in the DOM, it persists its strokes.
Canonical link: https://commits.webkit.org/206319@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238108 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-11-12 22:04:47 +00:00
|
|
|
|
2019-02-11 23:24:23 +00:00
|
|
|
static stylusTapAt(x, y, modifiers=[])
|
2018-12-19 23:37:02 +00:00
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
testRunner.runUIScript(`
|
2019-02-11 23:24:23 +00:00
|
|
|
uiController.stylusTapAtPointWithModifiers(${x}, ${y}, 2, 1, 0.5, ${JSON.stringify(modifiers)}, function() {
|
2019-01-17 19:15:57 +00:00
|
|
|
uiController.uiScriptComplete();
|
2018-12-19 23:37:02 +00:00
|
|
|
});`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
Insert <attachment> elements under editable images to make their backing data accessible
https://bugs.webkit.org/show_bug.cgi?id=191844
<rdar://problem/30900149>
Reviewed by Simon Fraser.
Source/WebCore:
Test: editing/images/editable-image-creates-attachment.html
* html/HTMLImageElement.cpp:
(WebCore::HTMLImageElement::parseAttribute):
(WebCore::HTMLImageElement::insertedIntoAncestor):
(WebCore::HTMLImageElement::removedFromAncestor):
When the x-apple-editable-image attribute changes, or the element is
moved into or out of a document, call updateEditableImage.
(WebCore::HTMLImageElement::editableImageViewID const):
Adopt EditableImageReference.
(WebCore::HTMLImageElement::updateEditableImage):
When the image element moves into a document, the setting is on, and
the appropriate attribute is applied, add an <attachment> into the
shadow DOM, and inform the UI process both of the editable image's
creation and that it should be associated with the new attachment.
Use an EditableImageReference to extend the lifetime of the
corresponding editable image in the UI process, and to communicate
the attachment association.
If the element was cloned from another editable image element, use the
EditableImageReference and attachmentID from the original; the embedded
view will be re-parented under this element's layer, and the attachment
will be cloned (with a new ID) by editing code if the element is parented.
(WebCore::HTMLImageElement::attachmentIdentifier const):
(WebCore::HTMLImageElement::copyNonAttributePropertiesFromElement):
Store the aforementioned bits of information when cloned so that we can
reconstitute the appropriate attachment data and embedded view.
* html/HTMLImageElement.h:
* page/ChromeClient.h:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* page/EditableImageReference.cpp: Added.
(WebCore::EditableImageReference::EditableImageReference):
(WebCore::EditableImageReference::~EditableImageReference):
(WebCore::EditableImageReference::associateWithAttachment):
* page/EditableImageReference.h: Added.
(WebCore::EditableImageReference::create):
(WebCore::EditableImageReference::embeddedViewID const):
Add EditableImageReference, which manages the lifetime of the UI-side
EditableImage and helps clients communicate about it. It is refcounted
so that cloned <img> elements can potentially borrow the UI-side state
(in the case where they end up getting parented).
* page/NavigatorBase.cpp:
Fix an unrelated unified build failure that I exposed.
Source/WebKit:
* DerivedSources.make:
* SourcesCocoa.txt:
* UIProcess/API/APIAttachment.h:
fileWrapper() is no longer a trivial getter; it can now construct
the file wrapper from a file wrapper generator if necessary.
Add setFileWrapperGenerator() and invalidateGeneratedFileWrapper().
Make m_fileWrapper mutable so it can be adjusted inside its own getter.
* UIProcess/API/Cocoa/APIAttachmentCocoa.mm:
(API::Attachment::fileWrapper const):
If we have a fileWrapperGenerator and don't have a cached file wrapper,
create one before returning it.
(API::Attachment::invalidateGeneratedFileWrapper):
Invalidate the currently-cached file wrapper. The next time a client
requests the file wrapper it will be regenerated.
(API::Attachment::fileName const):
(API::Attachment::fileSizeForDisplay const):
(API::Attachment::enclosingImageData const):
(API::Attachment::isEmpty const):
(API::Attachment::createSerializedRepresentation const):
Make use of fileWrapper() instead of m_fileWrapper directly, to ensure
that it is created lazily if necessary.
(API::Attachment::setFileWrapperGenerator):
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm:
(WebKit::RemoteLayerTreeHost::createEmbeddedView):
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h:
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm:
(-[WKEmbeddedView initWithEmbeddedViewID:]):
Defer to EditableImageController for creating WKDrawingViews for
editable images. This is done primarily so we don't have to pollute
Remote Layer Tree and DrawingArea interfaces with editable-image-specific messages.
* UIProcess/WebPageProxy.cpp:
(WebKit::m_editableImageController):
(WebKit::m_resetRecentCrashCountTimer): Deleted.
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::editableImageController):
Keep an EditableImageController on the WebPageProxy.
* UIProcess/ios/EditableImageController.h: Added.
* UIProcess/ios/EditableImageController.messages.in: Added.
* UIProcess/ios/EditableImageController.mm: Added.
(WebKit::EditableImageController::EditableImageController):
(WebKit::EditableImageController::~EditableImageController):
(WebKit::EditableImageController::ensureEditableImage):
(WebKit::EditableImageController::editableImage):
(WebKit::EditableImageController::didCreateEditableImage):
(WebKit::EditableImageController::didDestroyEditableImage):
(WebKit::EditableImageController::associateWithAttachment):
(WebKit::EditableImageController::invalidateAttachmentForEditableImage):
Add EditableImageController, which keeps track of EditableImages.
It can be messaged directly to create or destroy the UI-side state
of an editable image, and also to associate a WKDrawingView with
a particular attachment.
* UIProcess/ios/WKDrawingView.h:
* UIProcess/ios/WKDrawingView.mm:
(-[WKDrawingView initWithEmbeddedViewID:webPageProxy:]):
Store the WebPageProxy (weakly) so that we can get to the EditableImageController.
(-[WKDrawingView layoutSubviews]):
(-[WKDrawingView PNGRepresentation]):
Synchronously render the PKCanvasView to PNG.
(-[WKDrawingView drawingDidChange:]):
If the drawing changes, inform the APIAttachment that it needs
to discard its NSFileWrapper; a new one will be generated lazily.
(-[WKDrawingView init]): Deleted.
* WebKit.xcodeproj/project.pbxproj:
* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm:
(WebKit::WebChromeClient::associateEditableImageWithAttachment):
(WebKit::WebChromeClient::didCreateEditableImage):
(WebKit::WebChromeClient::didDestroyEditableImage):
Tools:
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::attachmentInfo):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::attachmentInfo):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::attachmentInfo):
Add a UIScriptController mechanism to retrieve information about
a given attachment.
LayoutTests:
* editing/images/editable-image-creates-attachment-expected.txt: Added.
* editing/images/editable-image-creates-attachment.html: Added.
* resources/ui-helper.js:
(window.UIHelper.attachmentInfo):
(window.UIHelper):
Canonical link: https://commits.webkit.org/206700@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238538 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-11-27 01:37:22 +00:00
|
|
|
static attachmentInfo(attachmentIdentifier)
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.uiScriptComplete(JSON.stringify(uiController.attachmentInfo('${attachmentIdentifier}')));
|
|
|
|
})()`, jsonString => {
|
|
|
|
resolve(JSON.parse(jsonString));
|
|
|
|
})
|
|
|
|
});
|
|
|
|
}
|
2018-11-28 18:50:23 +00:00
|
|
|
|
iOS: <attachment>'s QuickLook thumbnails can appear squished
https://bugs.webkit.org/show_bug.cgi?id=216209
<rdar://problem/67817706>
Reviewed by Wenson Hsieh.
Source/WebCore:
Test: fast/attachment/attachment-thumbnail-preserves-aspect-ratio.html
* html/HTMLAttachmentElement.idl:
* testing/Internals.cpp:
(WebCore::Internals::attachmentThumbnailInfo):
* testing/Internals.h:
* testing/Internals.idl:
Expose the attachment thumbnail size via Internals.
* rendering/RenderThemeIOS.mm:
(WebCore::RenderAttachmentInfo::RenderAttachmentInfo):
Allow the thumbnail aspect ratio to vary, instead of assuming it is always square.
Source/WebKit:
* UIProcess/Cocoa/WebPageProxyCocoa.mm:
(WebKit::convertPlatformImageToBitmap):
Propagate an image of the same aspect ratio that QuickLook provided,
instead of squishing it to square.
* UIProcess/QuickLookThumbnailLoader.mm:
(-[WKQLThumbnailLoadOperation start]):
Only request full thumbnails; we do not want the icon form, since <attachment>
already has one without QuickLook's help; if we can't get a full thumbnail,
we'll just leave it alone.
Tools:
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::insertAttachmentForFilePath):
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::currentTestURL const):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/cocoa/UIScriptControllerCocoa.h:
* WebKitTestRunner/cocoa/UIScriptControllerCocoa.mm:
(WTR::UIScriptControllerCocoa::insertAttachmentForFilePath):
Make it possible to insert an attachment wrapping a file on disk
via UIScriptController.
LayoutTests:
* fast/attachment/attachment-thumbnail-preserves-aspect-ratio-expected.txt: Added.
* fast/attachment/attachment-thumbnail-preserves-aspect-ratio.html: Added.
* fast/attachment/resources/400x200-circle.png: Added.
* platform/ios/fast/attachment/attachment-thumbnail-preserves-aspect-ratio-expected.txt: Added.
* resources/ui-helper.js:
(window.UIHelper.insertAttachmentForFilePath):
Add a test that dumps the thumbnail size for a 400x200 attachment.
We only run it on iOS, because on macOS, QuickLook always returns
an image of the size we ask for (400x400), padded with whitespace,
so the problem does not reproduce and the test doesn't work right there.
On iOS, the result used to be 400x400 and now is 400x200.
I tried and failed to make a more useful test (a ref test, actually
testing the presentation) because it's quite hard to match the
native <attachment> painting.
Canonical link: https://commits.webkit.org/229108@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@266743 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-09-08 19:47:05 +00:00
|
|
|
static insertAttachmentForFilePath(path, contentType)
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
uiController.insertAttachmentForFilePath('${path}', '${contentType}', function() {
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
});`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-11-28 18:50:23 +00:00
|
|
|
static setMinimumEffectiveWidth(effectiveWidth)
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.setMinimumEffectiveWidth(${effectiveWidth})`, resolve));
|
|
|
|
}
|
[iOS] WKWebView should match UITextView behavior when editing text with an RTL keyboard
https://bugs.webkit.org/show_bug.cgi?id=187554
<rdar://problem/42075638>
Reviewed by Tim Horton.
Source/WebKit:
Add support for automatically switching the base writing direction to the default writing direction with respect
to the current keyboard in an editable WKWebView by implementing `-setBaseWritingDirection:forRange:`. On iOS 12
and earlier, UIKit invokes this protocol method whenever the keyboard is changed to one with a different writing
direction, although in some other versions of iOS, this only happens when first focusing an editable area.
Test: editing/input/ios/rtl-keyboard-input-on-focus.html
* Platform/spi/ios/UIKitSPI.h:
Declare UIKeyboardImpl IPI methods mostly for use in WebKitTestRunner (with the exception of
`-setInitialDirection`, which we may invoke when we receive the first post-layout EditorState update after
focusing an editable element).
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::increaseListLevel):
(WebKit::WebPageProxy::decreaseListLevel):
(WebKit::WebPageProxy::changeListType):
(WebKit::WebPageProxy::setBaseWritingDirection):
Drive-by style fixes: make these bail and return early if `!isValid()`.
(WebKit::WebPageProxy::resetStateAfterProcessExited):
Reset assisted node state in the UI process upon web process termination.
* UIProcess/WebPageProxy.h:
Add plumbing for `setBaseWritingDirection`, from `WebPageProxy` to `WebPage` to `Editor`.
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::didReceiveEditorStateUpdateAfterFocus):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView baseWritingDirectionForPosition:inDirection:]):
(coreWritingDirection):
(-[WKContentView setBaseWritingDirection:forRange:]):
Support `-setBaseWritingDirectionForPosition:forRange:`, but only in the case where the given range is the
selected range. This is all that's currently needed to fulfill the requirements in <rdar://problem/42075638>,
though we could potentially add full support for this in the future by mapping the given text range to a DOM
range and moving the selection prior to setting the base writing direction.
(-[WKContentView _didReceiveEditorStateUpdateAfterFocus]):
Add a hook to notify WKContentView when the first post-layout EditorState has been received in the UI process.
When this is invoked, if the web view is editable and the selection is not a range, we call into `UIKeyboardImpl`
to change the initial writing direction if necessary.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::startAssistingNode):
(WebKit::WebPageProxy::stopAssistingNode):
(WebKit::WebPageProxy::editorStateChanged):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::setBaseWritingDirection):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Tools:
Add support for simulating the keyboard input mode in layout tests using UIScriptController, as well as a new
`TestOption` to make the web view editable.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::setKeyboardInputModeIdentifier):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::setKeyboardInputModeIdentifier):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/PlatformWebView.h:
* WebKitTestRunner/TestController.cpp:
(WTR::updateTestOptionsFromTestHeader):
* WebKitTestRunner/TestController.h:
(WTR::TestController::overriddenKeyboardInputMode const):
* WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::hasSameInitializationOptions const):
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::platformCreateWebView):
* WebKitTestRunner/gtk/PlatformWebViewGtk.cpp:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/ios/PlatformWebViewIOS.mm:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
(WTR::swizzleCurrentInputMode):
(WTR::TestController::setKeyboardInputModeIdentifier):
Swizzle out several `UIKeyboardInputModeController` methods in order to convince UIKit that the user has
selected a `UIKeyboardInputMode` corresponding to the given identifier. The call to
`-prepareKeyboardInputModeFromPreferences:` is also necessary on iOS 12 in order to update cached writing
direction state in UIKit.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::setKeyboardInputModeIdentifier):
* WebKitTestRunner/mac/PlatformWebViewMac.mm:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/win/PlatformWebViewWin.cpp:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/wpe/PlatformWebViewWPE.cpp:
(WTR::PlatformWebView::setEditable):
LayoutTests:
Add a new layout test to verify that when focusing an editable WKWebView using a right-to-left keyboard input
mode, we will set the base writing direction to be right-to-left, and vice versa.
* TestExpectations:
* editing/input/ios/rtl-keyboard-input-on-focus-expected.txt: Added.
* editing/input/ios/rtl-keyboard-input-on-focus.html: Added.
* platform/ios-wk2/TestExpectations:
* resources/ui-helper.js:
Add a UIHelper method to set the keyboard input mode to the given identifier. Example identifiers are "en_US"
(the default U.S. English keyboard) and "he_IL" (the Hebrew keyboard, which is right-to-left).
(window.UIHelper.setKeyboardInputModeIdentifier):
(window.UIHelper):
Canonical link: https://commits.webkit.org/207064@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238939 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-12-06 21:22:19 +00:00
|
|
|
|
2019-02-26 04:37:59 +00:00
|
|
|
static setAllowsViewportShrinkToFit(allows)
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.setAllowsViewportShrinkToFit(${allows})`, resolve));
|
|
|
|
}
|
|
|
|
|
[iOS] WKWebView should match UITextView behavior when editing text with an RTL keyboard
https://bugs.webkit.org/show_bug.cgi?id=187554
<rdar://problem/42075638>
Reviewed by Tim Horton.
Source/WebKit:
Add support for automatically switching the base writing direction to the default writing direction with respect
to the current keyboard in an editable WKWebView by implementing `-setBaseWritingDirection:forRange:`. On iOS 12
and earlier, UIKit invokes this protocol method whenever the keyboard is changed to one with a different writing
direction, although in some other versions of iOS, this only happens when first focusing an editable area.
Test: editing/input/ios/rtl-keyboard-input-on-focus.html
* Platform/spi/ios/UIKitSPI.h:
Declare UIKeyboardImpl IPI methods mostly for use in WebKitTestRunner (with the exception of
`-setInitialDirection`, which we may invoke when we receive the first post-layout EditorState update after
focusing an editable element).
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::increaseListLevel):
(WebKit::WebPageProxy::decreaseListLevel):
(WebKit::WebPageProxy::changeListType):
(WebKit::WebPageProxy::setBaseWritingDirection):
Drive-by style fixes: make these bail and return early if `!isValid()`.
(WebKit::WebPageProxy::resetStateAfterProcessExited):
Reset assisted node state in the UI process upon web process termination.
* UIProcess/WebPageProxy.h:
Add plumbing for `setBaseWritingDirection`, from `WebPageProxy` to `WebPage` to `Editor`.
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::didReceiveEditorStateUpdateAfterFocus):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView baseWritingDirectionForPosition:inDirection:]):
(coreWritingDirection):
(-[WKContentView setBaseWritingDirection:forRange:]):
Support `-setBaseWritingDirectionForPosition:forRange:`, but only in the case where the given range is the
selected range. This is all that's currently needed to fulfill the requirements in <rdar://problem/42075638>,
though we could potentially add full support for this in the future by mapping the given text range to a DOM
range and moving the selection prior to setting the base writing direction.
(-[WKContentView _didReceiveEditorStateUpdateAfterFocus]):
Add a hook to notify WKContentView when the first post-layout EditorState has been received in the UI process.
When this is invoked, if the web view is editable and the selection is not a range, we call into `UIKeyboardImpl`
to change the initial writing direction if necessary.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::startAssistingNode):
(WebKit::WebPageProxy::stopAssistingNode):
(WebKit::WebPageProxy::editorStateChanged):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::setBaseWritingDirection):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Tools:
Add support for simulating the keyboard input mode in layout tests using UIScriptController, as well as a new
`TestOption` to make the web view editable.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::setKeyboardInputModeIdentifier):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::setKeyboardInputModeIdentifier):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/PlatformWebView.h:
* WebKitTestRunner/TestController.cpp:
(WTR::updateTestOptionsFromTestHeader):
* WebKitTestRunner/TestController.h:
(WTR::TestController::overriddenKeyboardInputMode const):
* WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::hasSameInitializationOptions const):
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::platformCreateWebView):
* WebKitTestRunner/gtk/PlatformWebViewGtk.cpp:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/ios/PlatformWebViewIOS.mm:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
(WTR::swizzleCurrentInputMode):
(WTR::TestController::setKeyboardInputModeIdentifier):
Swizzle out several `UIKeyboardInputModeController` methods in order to convince UIKit that the user has
selected a `UIKeyboardInputMode` corresponding to the given identifier. The call to
`-prepareKeyboardInputModeFromPreferences:` is also necessary on iOS 12 in order to update cached writing
direction state in UIKit.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::setKeyboardInputModeIdentifier):
* WebKitTestRunner/mac/PlatformWebViewMac.mm:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/win/PlatformWebViewWin.cpp:
(WTR::PlatformWebView::setEditable):
* WebKitTestRunner/wpe/PlatformWebViewWPE.cpp:
(WTR::PlatformWebView::setEditable):
LayoutTests:
Add a new layout test to verify that when focusing an editable WKWebView using a right-to-left keyboard input
mode, we will set the base writing direction to be right-to-left, and vice versa.
* TestExpectations:
* editing/input/ios/rtl-keyboard-input-on-focus-expected.txt: Added.
* editing/input/ios/rtl-keyboard-input-on-focus.html: Added.
* platform/ios-wk2/TestExpectations:
* resources/ui-helper.js:
Add a UIHelper method to set the keyboard input mode to the given identifier. Example identifiers are "en_US"
(the default U.S. English keyboard) and "he_IL" (the Hebrew keyboard, which is right-to-left).
(window.UIHelper.setKeyboardInputModeIdentifier):
(window.UIHelper):
Canonical link: https://commits.webkit.org/207064@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238939 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-12-06 21:22:19 +00:00
|
|
|
static setKeyboardInputModeIdentifier(identifier)
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
const escapedIdentifier = identifier.replace(/`/g, "\\`");
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.setKeyboardInputModeIdentifier(\`${escapedIdentifier}\`)`, resolve));
|
|
|
|
}
|
[iOS] Content offset jumps erratically when autoscrolling near scroll view content inset areas
https://bugs.webkit.org/show_bug.cgi?id=193494
<rdar://problem/46859627>
Reviewed by Simon Fraser and Tim Horton.
Source/WebCore:
When computing the content offset to scroll to when revealing a given rect in content coordinates, we currently
just use the unobscured content rect. As a result, when scrolling to reveal a rect, we'll clamp the final scroll
position such that only content is visible. For example, when asked to reveal the rect `(0, 0, 1, 1)`, we adjust
the scroll position to be the origin.
However, consider the case where a client (e.g. Mail on iOS) has added a content inset to the web view's scroll
view. If we're asked to reveal a rect that is outside the content area but within a content inset, we will still
end up clamping the scroll position to the unobscured rect. This manifests in a bug where selecting text and
autoscrolling in iOS Mail compose while the scroll view is scrolled all the way to the top to reveal the To/Cc/
Subject fields causes the content offset to jump to the origin, rather than staying at (0, -topContentInset).
To fix this, we teach `RenderLayer::scrollRectToVisible` about content insets that are visible. Rather than use
the content rects as-is, expand to encompass visible content insets as well. This ensures that revealing a
position which is already visible won't cause us to scroll away the content inset area and only show the
unobscured rect.
Tests: editing/selection/ios/autoscroll-with-top-content-inset.html
fast/scrolling/ios/scroll-into-view-with-top-content-inset.html
* page/FrameView.cpp:
(WebCore::FrameView::unobscuredContentRectExpandedByContentInsets const):
Introduce a helper method that expands the unobscured content rect to include surrounding content insets.
* page/FrameView.h:
* page/Page.h:
(WebCore::Page::contentInsets const):
(WebCore::Page::setContentInsets):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::scrollRectToVisible):
(WebCore::RenderLayer::getRectToExpose const):
Source/WebKit:
Adds `contentInsets` to `VisibleContentRectUpdateInfo`. This keeps track of the visible content insets
surrounding the unobscured content rect. See WebCore ChangeLog for more details.
* Shared/VisibleContentRectUpdateInfo.cpp:
(WebKit::VisibleContentRectUpdateInfo::encode const):
(WebKit::VisibleContentRectUpdateInfo::decode):
(WebKit::operator<<):
* Shared/VisibleContentRectUpdateInfo.h:
(WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
(WebKit::VisibleContentRectUpdateInfo::contentInsets const):
(WebKit::operator==):
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _computedObscuredInset]):
(-[WKWebView _computedContentInset]):
(-[WKWebView _computedUnobscuredSafeAreaInset]):
We don't care about source compatibility with iOS 10 and below anymore, so we should change these >= iOS 11
target checks to simply `PLATFORM(IOS)`.
(-[WKWebView _updateVisibleContentRects]):
Compute the visible content insets on all sides of the unobscured content rect. These insets are scaled to
content coordinates.
* UIProcess/ios/WKContentView.h:
* UIProcess/ios/WKContentView.mm:
(floatBoxExtent):
Add a helper to convert `UIEdgeInsets` to `WebCore::FloatBoxExtent`, and use it in a few places below.
(-[WKContentView didUpdateVisibleRect:unobscuredRect:contentInsets:unobscuredRectInScrollViewCoordinates:obscuredInsets:unobscuredSafeAreaInsets:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInsets:unobscuredSafeAreaInsets:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]): Deleted.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::updateVisibleContentRects):
Update the Page's content insets.
Tools:
Add a new test option to add a top content inset to the test runner's WKWebView's scroll view, and automatically
scroll to reveal this top content inset area when beginning the test (i.e., scroll to (0, -topContentInset)).
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::contentOffsetX const):
(WTR::UIScriptController::contentOffsetY const):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::contentOffsetX const):
(WTR::UIScriptController::contentOffsetY const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
Also add new UIScriptController methods to ask for the content offset of the platform scroll view.
* WebKitTestRunner/TestController.cpp:
(WTR::updateTestOptionsFromTestHeader):
* WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::hasSameInitializationOptions const):
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::contentOffsetX const):
(WTR::UIScriptController::contentOffsetY const):
LayoutTests:
* editing/selection/ios/autoscroll-with-top-content-inset-expected.txt: Added.
* editing/selection/ios/autoscroll-with-top-content-inset.html: Added.
Add a new test to verify that moving the selection by autoscrolling near the top content inset area does not
cause the scroll view's content offset to jump.
* fast/scrolling/ios/scroll-into-view-with-top-content-inset-expected.txt: Added.
* fast/scrolling/ios/scroll-into-view-with-top-content-inset.html: Added.
Add a new test to verify that programmatically scrolling an element that's already visible into view does not
scroll away the scroll view's content inset.
* resources/ui-helper.js:
(window.UIHelper.contentOffset):
(window.UIHelper):
Canonical link: https://commits.webkit.org/208065@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@240139 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-01-18 04:15:24 +00:00
|
|
|
|
|
|
|
static contentOffset()
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isIOSFamily())
|
[iOS] Content offset jumps erratically when autoscrolling near scroll view content inset areas
https://bugs.webkit.org/show_bug.cgi?id=193494
<rdar://problem/46859627>
Reviewed by Simon Fraser and Tim Horton.
Source/WebCore:
When computing the content offset to scroll to when revealing a given rect in content coordinates, we currently
just use the unobscured content rect. As a result, when scrolling to reveal a rect, we'll clamp the final scroll
position such that only content is visible. For example, when asked to reveal the rect `(0, 0, 1, 1)`, we adjust
the scroll position to be the origin.
However, consider the case where a client (e.g. Mail on iOS) has added a content inset to the web view's scroll
view. If we're asked to reveal a rect that is outside the content area but within a content inset, we will still
end up clamping the scroll position to the unobscured rect. This manifests in a bug where selecting text and
autoscrolling in iOS Mail compose while the scroll view is scrolled all the way to the top to reveal the To/Cc/
Subject fields causes the content offset to jump to the origin, rather than staying at (0, -topContentInset).
To fix this, we teach `RenderLayer::scrollRectToVisible` about content insets that are visible. Rather than use
the content rects as-is, expand to encompass visible content insets as well. This ensures that revealing a
position which is already visible won't cause us to scroll away the content inset area and only show the
unobscured rect.
Tests: editing/selection/ios/autoscroll-with-top-content-inset.html
fast/scrolling/ios/scroll-into-view-with-top-content-inset.html
* page/FrameView.cpp:
(WebCore::FrameView::unobscuredContentRectExpandedByContentInsets const):
Introduce a helper method that expands the unobscured content rect to include surrounding content insets.
* page/FrameView.h:
* page/Page.h:
(WebCore::Page::contentInsets const):
(WebCore::Page::setContentInsets):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::scrollRectToVisible):
(WebCore::RenderLayer::getRectToExpose const):
Source/WebKit:
Adds `contentInsets` to `VisibleContentRectUpdateInfo`. This keeps track of the visible content insets
surrounding the unobscured content rect. See WebCore ChangeLog for more details.
* Shared/VisibleContentRectUpdateInfo.cpp:
(WebKit::VisibleContentRectUpdateInfo::encode const):
(WebKit::VisibleContentRectUpdateInfo::decode):
(WebKit::operator<<):
* Shared/VisibleContentRectUpdateInfo.h:
(WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
(WebKit::VisibleContentRectUpdateInfo::contentInsets const):
(WebKit::operator==):
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _computedObscuredInset]):
(-[WKWebView _computedContentInset]):
(-[WKWebView _computedUnobscuredSafeAreaInset]):
We don't care about source compatibility with iOS 10 and below anymore, so we should change these >= iOS 11
target checks to simply `PLATFORM(IOS)`.
(-[WKWebView _updateVisibleContentRects]):
Compute the visible content insets on all sides of the unobscured content rect. These insets are scaled to
content coordinates.
* UIProcess/ios/WKContentView.h:
* UIProcess/ios/WKContentView.mm:
(floatBoxExtent):
Add a helper to convert `UIEdgeInsets` to `WebCore::FloatBoxExtent`, and use it in a few places below.
(-[WKContentView didUpdateVisibleRect:unobscuredRect:contentInsets:unobscuredRectInScrollViewCoordinates:obscuredInsets:unobscuredSafeAreaInsets:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInsets:unobscuredSafeAreaInsets:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]): Deleted.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::updateVisibleContentRects):
Update the Page's content insets.
Tools:
Add a new test option to add a top content inset to the test runner's WKWebView's scroll view, and automatically
scroll to reveal this top content inset area when beginning the test (i.e., scroll to (0, -topContentInset)).
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::contentOffsetX const):
(WTR::UIScriptController::contentOffsetY const):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::contentOffsetX const):
(WTR::UIScriptController::contentOffsetY const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
Also add new UIScriptController methods to ask for the content offset of the platform scroll view.
* WebKitTestRunner/TestController.cpp:
(WTR::updateTestOptionsFromTestHeader):
* WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::hasSameInitializationOptions const):
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::contentOffsetX const):
(WTR::UIScriptController::contentOffsetY const):
LayoutTests:
* editing/selection/ios/autoscroll-with-top-content-inset-expected.txt: Added.
* editing/selection/ios/autoscroll-with-top-content-inset.html: Added.
Add a new test to verify that moving the selection by autoscrolling near the top content inset area does not
cause the scroll view's content offset to jump.
* fast/scrolling/ios/scroll-into-view-with-top-content-inset-expected.txt: Added.
* fast/scrolling/ios/scroll-into-view-with-top-content-inset.html: Added.
Add a new test to verify that programmatically scrolling an element that's already visible into view does not
scroll away the scroll view's content inset.
* resources/ui-helper.js:
(window.UIHelper.contentOffset):
(window.UIHelper):
Canonical link: https://commits.webkit.org/208065@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@240139 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-01-18 04:15:24 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
const uiScript = "JSON.stringify([uiController.contentOffsetX, uiController.contentOffsetY])";
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(uiScript, result => {
|
|
|
|
const [offsetX, offsetY] = JSON.parse(result)
|
|
|
|
resolve({ x: offsetX, y: offsetY });
|
|
|
|
}));
|
|
|
|
}
|
2019-01-25 17:23:06 +00:00
|
|
|
|
|
|
|
static undoAndRedoLabels()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
const script = "JSON.stringify([uiController.lastUndoLabel, uiController.firstRedoLabel])";
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(script, result => resolve(JSON.parse(result))));
|
|
|
|
}
|
[iOS] Callout menu overlaps in-page controls when editing a comment in github.com's issue tracker
https://bugs.webkit.org/show_bug.cgi?id=194873
<rdar://problem/46701974>
Reviewed by Tim Horton.
Source/WebKit:
On the topic of supporting web-based rich text editors on iOS, one problematic area has always been handling
conflicts between platform UI (i.e., the system callout menu) and in-page text editing controls. This issue
comes up in websites that don't use the "hidden contenteditable" approach to rich text editing, but also show
additional controls in a toolbar or contextual menu above the selection. In these cases, what often happens is
that system controls overlap controls in the page.
Luckily, the iOS callout menu (i.e. the private UICalloutBar) is capable of presenting with a list of "evasion
rects" to avoid; if the callout bar would normally intersect with one of these rects, then a different
orientation that does not intersect with one of these rects is chosen instead. Currently, the only rect added
here by UIKit when presenting the callout menu is the bounding rect of the on-screen keyboard, but after
<rdar://problem/48128337>, we now have a generalized mechanism for offering additional evasion rects before
UIKit presents the callout menu.
This patch adopts the mechanism introduced in <rdar://problem/48128337>, and introduces a heuristic for
determining the approximate location of controls in the page which might overlap the callout menu. This
heuristic works by hit-testing for clickable (but non-editable) nodes above the bounds of the selection, which
are additionally not hit-tested by advancing outwards from any of the other edges of the selection bounds.
Additionally, any hit-tested nodes whose bounding rects are very large (relative to the content view size) are
ignored (this deals with scenarios where the body or a large container element has a click handler). We then add
the bounding rects of each of the nodes that fit this criteria to the list of rects for UIKit to avoid when
presenting the system callout menu.
The result is that WebKit will, by default, avoid overlapping anything that looks like controls in the page when
showing a callout menu in editable content. In practice, this fixes overlapping controls on most websites that
roll their own context menu or toolbar in their rich text editor.
Test: editing/selection/ios/avoid-showing-callout-menu-over-controls.html
* Platform/spi/ios/UIKitSPI.h:
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView requestAutocorrectionRectsForString:withCompletionHandler:]):
(-[WKContentView requestRectsToEvadeForSelectionCommandsWithCompletionHandler:]):
(-[WKContentView requestAutocorrectionContextWithCompletionHandler:]):
Drive-by: handle null completion handler arguments more gracefully, by raising an NSException and bailing before
attempting to invoke a nil block.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::requestEvasionRectsAboveSelection):
See above for more detail.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::requestEvasionRectsAboveSelection):
Tools:
Add a couple of UIScriptController methods to make callout menu testing on iOS easier (see below).
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::menuRect const):
(WTR::UIScriptController::isShowingMenu const):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::menuRect const):
Add a function to query the bounds of the callout menu in content coordinates.
(WTR::UIScriptController::isShowingMenu const):
Add a function to query whether the callout menu is shown (i.e., has finished its appearance animation).
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::rectForMenuAction const):
(WTR::UIScriptController::menuRect const):
(WTR::UIScriptController::isShowingMenu const):
(WTR::findViewInHierarchyOfType): Deleted.
LayoutTests:
Add a test to ensure that the we dodge clickable elements when showing the callout bar.
* editing/selection/ios/avoid-showing-callout-menu-over-controls-expected.txt: Added.
* editing/selection/ios/avoid-showing-callout-menu-over-controls.html: Added.
* resources/ui-helper.js:
(window.UIHelper.waitForMenuToShow.return.new.Promise):
(window.UIHelper.waitForMenuToShow):
(window.UIHelper.menuRect):
(window.UIHelper):
Canonical link: https://commits.webkit.org/209323@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@241971 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-02-23 00:48:16 +00:00
|
|
|
|
|
|
|
static waitForMenuToShow()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
if (!uiController.isShowingMenu)
|
|
|
|
uiController.didShowMenuCallback = () => uiController.uiScriptComplete();
|
|
|
|
else
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[iOS] Add a quirk to synthesize mouse events when modifying the selection
https://bugs.webkit.org/show_bug.cgi?id=197683
<rdar://problem/48003980>
Reviewed by Tim Horton.
Source/WebCore:
See WebKit ChangeLog for more details.
Test: editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk.html
* page/EventHandler.cpp:
(WebCore::EventHandler::handleMousePressEvent):
(WebCore::EventHandler::supportsSelectionUpdatesOnMouseDrag const):
Add some platform hooks to prevent mousemove events from updating the selection on iOS.
(WebCore::EventHandler::shouldAllowMouseDownToStartDrag const):
Add some platform hooks to prevent drag and drop from kicking in when sending synthetic mousemove events to the
page on iOS (drag and drop is instead triggered by EventHandler::tryToBeginDragAtPoint).
(WebCore::EventHandler::updateSelectionForMouseDrag):
* page/EventHandler.h:
* page/Quirks.cpp:
(WebCore::Quirks::shouldDispatchSyntheticMouseEventsWhenModifyingSelection const):
* page/Quirks.h:
Add the new site-specific quirk.
* page/Settings.yaml:
* page/ios/EventHandlerIOS.mm:
(WebCore::EventHandler::tryToBeginDragAtPoint):
(WebCore::EventHandler::supportsSelectionUpdatesOnMouseDrag const):
(WebCore::EventHandler::shouldAllowMouseDownToStartDrag const):
* testing/InternalSettings.cpp:
(WebCore::InternalSettings::Backup::Backup):
(WebCore::InternalSettings::Backup::restoreTo):
(WebCore::InternalSettings::setShouldDispatchSyntheticMouseEventsWhenModifyingSelection):
* testing/InternalSettings.h:
* testing/InternalSettings.idl:
Add an internal settings hook to opt into this quirk, for use in layout tests.
Source/WebKit:
Introduces support for dispatching synthetic mouse events when modifying the selection on some websites. See
below for more details.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::selectAll):
* UIProcess/WebPageProxy.h:
Instead of executing a "SelectAll" editing command using the generic WebPage::executeEditCommand method,
introduce a separate method for selectAll that executes the "SelectAll" edit command and then does some
platform-specific work. See platformDidSelectAll.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView selectAllForWebView:]):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::selectAll):
(WebKit::WebPage::shouldDispatchSyntheticMouseEventsWhenModifyingSelection const):
Add a helper method to determine whether the quirk should be enabled.
(WebKit::WebPage::platformDidSelectAll):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::elementRectInRootViewCoordinates):
Move this function closer to the top of the file so that it can be used in
dispatchSyntheticMouseEventsForSelectionGesture.
(WebKit::WebPage::clearSelection):
(WebKit::WebPage::dispatchSyntheticMouseEventsForSelectionGesture):
Add a helper method to dispatch a synthetic mouse event for a given selection gesture type. Used in several
places in WebPageIOS to synthesize and dispatch mouse events during selection.
(WebKit::WebPage::updateSelectionWithTouches):
When changing the selection with selection handles, fake mousedown when the user first touches down on the
selection handle; mousemove as the user is moving the handle around; and finally, mouseup when the user lets go.
(WebKit::WebPage::extendSelection):
(WebKit::WebPage::platformDidSelectAll):
When tapping "Select All" and/or "Select" in the callout menu, fake a mousedown at the selection start, then a
mousemove at selection end, and finally, a mouseup at selection end.
(WebKit::WebPage::getFocusedElementInformation):
LayoutTests:
Adds a new layout test to enable the site-specific quirk and verify that mouse events are dispatched when
changing selection, both via the callout menu and by moving the selection grabber using gestures.
* editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk-expected.txt: Added.
* editing/selection/ios/dispatch-mouse-events-when-modifying-selection-quirk.html: Added.
* resources/ui-helper.js:
(window.UIHelper.waitForMenuToHide.return.new.Promise):
(window.UIHelper.waitForMenuToHide):
Introduce a new helper method to wait for the menu to hide (on iOS, this refers to the callout menu).
Canonical link: https://commits.webkit.org/211841@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@245062 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-05-08 19:36:33 +00:00
|
|
|
static waitForMenuToHide()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
if (uiController.isShowingMenu)
|
|
|
|
uiController.didHideMenuCallback = () => uiController.uiScriptComplete();
|
|
|
|
else
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[iOS] [WebKit2] Add support for honoring -[UIMenuItem dontDismiss]
https://bugs.webkit.org/show_bug.cgi?id=196919
<rdar://problem/41630459>
Reviewed by Tim Horton.
Source/WebKit:
Adds modern WebKit support for -dontDismiss by implementing a couple of new platform hooks. Covered by a new
layout test: editing/selection/ios/selection-after-changing-text-with-callout-menu.html.
* Platform/spi/ios/UIKitSPI.h:
Declare the private -dontDismiss property of UIMenuItem.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView willFinishIgnoringCalloutBarFadeAfterPerformingAction]):
Additionally teach the web view (not just the content view) to respond to the hook. This matters in the case
where the WebKit client (most notably, Mail) overrides WKWebView methods to define custom actions in the menu
controller. This scenario is exercised by the new layout test.
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView willFinishIgnoringCalloutBarFadeAfterPerformingAction]):
If an action was performed where callout bar fading was ignored, then in WebKit, don't allow selection changes
to fade the callout bar until after the next remote layer tree commit.
(-[WKContentView _updateChangedSelection:]):
Stop suppressing selection updates when showing B/I/U controls, now that we can properly honor the -dontDismiss
property. This was originally introduced in <rdar://problem/15199925>, presumably to ensure that B/I/U buttons
(which have -dontDismiss set to YES) don't trigger selection change and end up dismissing themselves; however,
if triggering B/I/U actually changes the selection rects, this also means that the selection rects on-screen
would be stale after triggering these actions. This effect is most noticeable when bolding text.
(-[WKContentView shouldAllowHidingSelectionCommands]):
Tools:
Add iOS support for several new testing hooks. See below for more detail.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isDismissingMenu const):
Add a new script controller method to query whether the platform menu (on iOS, the callout bar) is done
dismissing. We consider the menu to be dismissing in between the `-WillHide` and `-DidHide` notifications sent
by UIKit when dismissing the callout bar (i.e. UIMenuController).
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::isDismissingMenu const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::didReceiveMessageToPage):
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setAllowedMenuActions):
Add a new helper method to specify a list of allowed actions when bringing up the menu. On iOS, in the case of
actions supported by the platform, this matches against method selector names (for instance, "SelectAll", or
"Copy", or "Paste"). In the case of the custom actions installed via `installCustomMenuAction`, we instead match
against the name of the custom action.
(WTR::TestRunner::installCustomMenuAction):
Add a new helper method to install a custom action for the context menu (on iOS, this is the callout bar). This
takes the name of the action (which appears in a button in the callout bar), whether the action should cause
the callout bar to automatically dismiss, and finally, a JavaScript callback that is invoked when the action is
triggered.
(WTR::TestRunner::performCustomMenuAction):
Invoked when the custom menu action is triggered.
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::installCustomMenuAction):
(WTR::TestController::setAllowedMenuActions):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
(WTR::TestInvocation::performCustomMenuAction):
Add plumbing to call back into the injected bundle when performing the custom action.
* WebKitTestRunner/TestInvocation.h:
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::installCustomMenuAction):
(WTR::TestController::setAllowedMenuActions):
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView initWithFrame:configuration:]):
(-[TestRunnerWKWebView becomeFirstResponder]):
(-[TestRunnerWKWebView _addCustomItemToMenuControllerIfNecessary]):
Helper method that converts web view's current custom menu action info into a UIMenuItem, and adds it to the
shared menu controller. This is also invoked when the web view becomes first responder, which matches behavior
in the Mail app on iOS.
(-[TestRunnerWKWebView installCustomMenuAction:dismissesAutomatically:callback:]):
(-[TestRunnerWKWebView setAllowedMenuActions:]):
(-[TestRunnerWKWebView resetCustomMenuAction]):
(-[TestRunnerWKWebView performCustomAction:]):
(-[TestRunnerWKWebView canPerformAction:withSender:]):
(-[TestRunnerWKWebView _willHideMenu]):
(-[TestRunnerWKWebView _didHideMenu]):
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
Reset both any custom installed actions on the shared menu controller, as well as the list of allowed actions,
if specified.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isDismissingMenu const):
LayoutTests:
Add a new iOS layout test that installs a custom, non-dismissing action in the callout menu that enlarges text.
The test then activates this custom menu item and checks that the selection rects after triggering this custom
action are updated, and the callout bar is still showing.
* editing/selection/ios/selection-after-changing-text-with-callout-menu-expected.txt: Added.
* editing/selection/ios/selection-after-changing-text-with-callout-menu.html: Added.
This test additionally suppresses all callout bar menu items except for the custom "Embiggen" action, to ensure
that the "Embiggen" option can be tapped from the layout test without having to navigate callout bar items by
tapping on the "Next" and "Show styles" buttons. This latter approach is very challenging to make reliable in
automation; when navigating submenus in the callout bar, the next button can't be tapped until the current
callout bar transition animation is complete, but there's no delegate method invoked or notification posted when
this happens.
* resources/ui-helper.js:
(window.UIHelper.isShowingMenu):
(window.UIHelper.isDismissingMenu):
(window.UIHelper.rectForMenuAction):
(window.UIHelper.async.chooseMenuAction):
Additionally add a few more UIHelper methods.
(window.UIHelper):
Canonical link: https://commits.webkit.org/211257@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244370 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-04-17 03:34:10 +00:00
|
|
|
static isShowingMenu()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`uiController.isShowingMenu`, result => resolve(result === "true"));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static isDismissingMenu()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`uiController.isDismissingMenu`, result => resolve(result === "true"));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[iOS] Callout menu overlaps in-page controls when editing a comment in github.com's issue tracker
https://bugs.webkit.org/show_bug.cgi?id=194873
<rdar://problem/46701974>
Reviewed by Tim Horton.
Source/WebKit:
On the topic of supporting web-based rich text editors on iOS, one problematic area has always been handling
conflicts between platform UI (i.e., the system callout menu) and in-page text editing controls. This issue
comes up in websites that don't use the "hidden contenteditable" approach to rich text editing, but also show
additional controls in a toolbar or contextual menu above the selection. In these cases, what often happens is
that system controls overlap controls in the page.
Luckily, the iOS callout menu (i.e. the private UICalloutBar) is capable of presenting with a list of "evasion
rects" to avoid; if the callout bar would normally intersect with one of these rects, then a different
orientation that does not intersect with one of these rects is chosen instead. Currently, the only rect added
here by UIKit when presenting the callout menu is the bounding rect of the on-screen keyboard, but after
<rdar://problem/48128337>, we now have a generalized mechanism for offering additional evasion rects before
UIKit presents the callout menu.
This patch adopts the mechanism introduced in <rdar://problem/48128337>, and introduces a heuristic for
determining the approximate location of controls in the page which might overlap the callout menu. This
heuristic works by hit-testing for clickable (but non-editable) nodes above the bounds of the selection, which
are additionally not hit-tested by advancing outwards from any of the other edges of the selection bounds.
Additionally, any hit-tested nodes whose bounding rects are very large (relative to the content view size) are
ignored (this deals with scenarios where the body or a large container element has a click handler). We then add
the bounding rects of each of the nodes that fit this criteria to the list of rects for UIKit to avoid when
presenting the system callout menu.
The result is that WebKit will, by default, avoid overlapping anything that looks like controls in the page when
showing a callout menu in editable content. In practice, this fixes overlapping controls on most websites that
roll their own context menu or toolbar in their rich text editor.
Test: editing/selection/ios/avoid-showing-callout-menu-over-controls.html
* Platform/spi/ios/UIKitSPI.h:
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView requestAutocorrectionRectsForString:withCompletionHandler:]):
(-[WKContentView requestRectsToEvadeForSelectionCommandsWithCompletionHandler:]):
(-[WKContentView requestAutocorrectionContextWithCompletionHandler:]):
Drive-by: handle null completion handler arguments more gracefully, by raising an NSException and bailing before
attempting to invoke a nil block.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::requestEvasionRectsAboveSelection):
See above for more detail.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::requestEvasionRectsAboveSelection):
Tools:
Add a couple of UIScriptController methods to make callout menu testing on iOS easier (see below).
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::menuRect const):
(WTR::UIScriptController::isShowingMenu const):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::menuRect const):
Add a function to query the bounds of the callout menu in content coordinates.
(WTR::UIScriptController::isShowingMenu const):
Add a function to query whether the callout menu is shown (i.e., has finished its appearance animation).
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::rectForMenuAction const):
(WTR::UIScriptController::menuRect const):
(WTR::UIScriptController::isShowingMenu const):
(WTR::findViewInHierarchyOfType): Deleted.
LayoutTests:
Add a test to ensure that the we dodge clickable elements when showing the callout bar.
* editing/selection/ios/avoid-showing-callout-menu-over-controls-expected.txt: Added.
* editing/selection/ios/avoid-showing-callout-menu-over-controls.html: Added.
* resources/ui-helper.js:
(window.UIHelper.waitForMenuToShow.return.new.Promise):
(window.UIHelper.waitForMenuToShow):
(window.UIHelper.menuRect):
(window.UIHelper):
Canonical link: https://commits.webkit.org/209323@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@241971 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-02-23 00:48:16 +00:00
|
|
|
static menuRect()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript("JSON.stringify(uiController.menuRect)", result => resolve(JSON.parse(result)));
|
|
|
|
});
|
|
|
|
}
|
[iOS] Software keyboard is shown too frequently on some websites
https://bugs.webkit.org/show_bug.cgi?id=195856
<rdar://problem/49191395>
Reviewed by Darin Adler.
Source/WebCore/PAL:
Declare new GraphicsServices SPI.
* pal/spi/ios/GraphicsServicesSPI.h:
Source/WebKit:
On some websites, hidden editable elements are very frequently focused upon user interaction. Currently, this
causes the software keyboard to pop in and out unexpectedly; luckily, these same sites also apply
inputmode="none" to the hidden editable element, which ought to ensure that the software keyboard doesn't appear
when the element is focused.
However, since we disabled support for inputmode="none" in r240497, the software keyboard is no longer
suppressed, and becomes a big nuissance. r240497 removed support for this feature because, when using a hardware
keyboard, pressing the globe key no longer showed UI for switching languages. However, support for inputmode
none makes a much larger impact when a software keyboard is used (since the entire software keyboard animates in
and out), whereas a hardware keyboard only displays an input accessory view. For this reason, we can mitigate
this bug without reintroducing <rdar://problem/47406553> by re-enabling inputmode="none", but only when a
hardware keyboard is not attached.
* UIProcess/API/Cocoa/WKWebView.mm:
(hardwareKeyboardAvailabilityChangedCallback):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView shouldShowAutomaticKeyboardUI]):
Don't show the keyboard if inputmode is none and a hardware keyboard is not attached.
(-[WKContentView _hardwareKeyboardAvailabilityChanged]):
Reload input views if the inputmode is none to ensure that if a hardware keyboard is attached while editing an
element with inputmode="none", we'll show the input accessory view once again.
Tools:
Add support for attaching or detaching the hardware keyboard on iOS in layout tests.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::setHardwareKeyboardAttached):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::setHardwareKeyboardAttached):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/Configurations/WebKitTestRunnerApp.xcconfig:
Additionally link against GraphicsServices in WebKitTestRunner.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
(WTR::UIScriptController::setHardwareKeyboardAttached):
WebKitLibraries:
Add a symbol for GSEventSetHardwareKeyboardAttached.
* WebKitPrivateFrameworkStubs/iOS/12/GraphicsServices.framework/GraphicsServices.tbd:
LayoutTests:
Fix a failing layout test, which (among other reasons) is currently failing because support for inputmode="none"
is disabled.
* fast/forms/ios/inputmode-none-expected.txt:
* fast/forms/ios/inputmode-none.html:
* resources/ui-helper.js:
Add a UIHelper method for attaching or detaching the hardware keyboard.
(window.UIHelper.setHardwareKeyboardAttached):
(window.UIHelper):
Canonical link: https://commits.webkit.org/211129@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244220 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-04-12 17:30:00 +00:00
|
|
|
|
|
|
|
static setHardwareKeyboardAttached(attached)
|
|
|
|
{
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.setHardwareKeyboardAttached(${attached ? "true" : "false"})`, resolve));
|
|
|
|
}
|
[iOS] [WebKit2] Add support for honoring -[UIMenuItem dontDismiss]
https://bugs.webkit.org/show_bug.cgi?id=196919
<rdar://problem/41630459>
Reviewed by Tim Horton.
Source/WebKit:
Adds modern WebKit support for -dontDismiss by implementing a couple of new platform hooks. Covered by a new
layout test: editing/selection/ios/selection-after-changing-text-with-callout-menu.html.
* Platform/spi/ios/UIKitSPI.h:
Declare the private -dontDismiss property of UIMenuItem.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView willFinishIgnoringCalloutBarFadeAfterPerformingAction]):
Additionally teach the web view (not just the content view) to respond to the hook. This matters in the case
where the WebKit client (most notably, Mail) overrides WKWebView methods to define custom actions in the menu
controller. This scenario is exercised by the new layout test.
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView willFinishIgnoringCalloutBarFadeAfterPerformingAction]):
If an action was performed where callout bar fading was ignored, then in WebKit, don't allow selection changes
to fade the callout bar until after the next remote layer tree commit.
(-[WKContentView _updateChangedSelection:]):
Stop suppressing selection updates when showing B/I/U controls, now that we can properly honor the -dontDismiss
property. This was originally introduced in <rdar://problem/15199925>, presumably to ensure that B/I/U buttons
(which have -dontDismiss set to YES) don't trigger selection change and end up dismissing themselves; however,
if triggering B/I/U actually changes the selection rects, this also means that the selection rects on-screen
would be stale after triggering these actions. This effect is most noticeable when bolding text.
(-[WKContentView shouldAllowHidingSelectionCommands]):
Tools:
Add iOS support for several new testing hooks. See below for more detail.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isDismissingMenu const):
Add a new script controller method to query whether the platform menu (on iOS, the callout bar) is done
dismissing. We consider the menu to be dismissing in between the `-WillHide` and `-DidHide` notifications sent
by UIKit when dismissing the callout bar (i.e. UIMenuController).
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::isDismissingMenu const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::didReceiveMessageToPage):
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setAllowedMenuActions):
Add a new helper method to specify a list of allowed actions when bringing up the menu. On iOS, in the case of
actions supported by the platform, this matches against method selector names (for instance, "SelectAll", or
"Copy", or "Paste"). In the case of the custom actions installed via `installCustomMenuAction`, we instead match
against the name of the custom action.
(WTR::TestRunner::installCustomMenuAction):
Add a new helper method to install a custom action for the context menu (on iOS, this is the callout bar). This
takes the name of the action (which appears in a button in the callout bar), whether the action should cause
the callout bar to automatically dismiss, and finally, a JavaScript callback that is invoked when the action is
triggered.
(WTR::TestRunner::performCustomMenuAction):
Invoked when the custom menu action is triggered.
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::installCustomMenuAction):
(WTR::TestController::setAllowedMenuActions):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
(WTR::TestInvocation::performCustomMenuAction):
Add plumbing to call back into the injected bundle when performing the custom action.
* WebKitTestRunner/TestInvocation.h:
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::installCustomMenuAction):
(WTR::TestController::setAllowedMenuActions):
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView initWithFrame:configuration:]):
(-[TestRunnerWKWebView becomeFirstResponder]):
(-[TestRunnerWKWebView _addCustomItemToMenuControllerIfNecessary]):
Helper method that converts web view's current custom menu action info into a UIMenuItem, and adds it to the
shared menu controller. This is also invoked when the web view becomes first responder, which matches behavior
in the Mail app on iOS.
(-[TestRunnerWKWebView installCustomMenuAction:dismissesAutomatically:callback:]):
(-[TestRunnerWKWebView setAllowedMenuActions:]):
(-[TestRunnerWKWebView resetCustomMenuAction]):
(-[TestRunnerWKWebView performCustomAction:]):
(-[TestRunnerWKWebView canPerformAction:withSender:]):
(-[TestRunnerWKWebView _willHideMenu]):
(-[TestRunnerWKWebView _didHideMenu]):
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
Reset both any custom installed actions on the shared menu controller, as well as the list of allowed actions,
if specified.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isDismissingMenu const):
LayoutTests:
Add a new iOS layout test that installs a custom, non-dismissing action in the callout menu that enlarges text.
The test then activates this custom menu item and checks that the selection rects after triggering this custom
action are updated, and the callout bar is still showing.
* editing/selection/ios/selection-after-changing-text-with-callout-menu-expected.txt: Added.
* editing/selection/ios/selection-after-changing-text-with-callout-menu.html: Added.
This test additionally suppresses all callout bar menu items except for the custom "Embiggen" action, to ensure
that the "Embiggen" option can be tapped from the layout test without having to navigate callout bar items by
tapping on the "Next" and "Show styles" buttons. This latter approach is very challenging to make reliable in
automation; when navigating submenus in the callout bar, the next button can't be tapped until the current
callout bar transition animation is complete, but there's no delegate method invoked or notification posted when
this happens.
* resources/ui-helper.js:
(window.UIHelper.isShowingMenu):
(window.UIHelper.isDismissingMenu):
(window.UIHelper.rectForMenuAction):
(window.UIHelper.async.chooseMenuAction):
Additionally add a few more UIHelper methods.
(window.UIHelper):
Canonical link: https://commits.webkit.org/211257@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244370 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-04-17 03:34:10 +00:00
|
|
|
|
|
|
|
static rectForMenuAction(action)
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
2020-01-20 20:24:54 +00:00
|
|
|
(() => {
|
|
|
|
const rect = uiController.rectForMenuAction("${action}");
|
|
|
|
uiController.uiScriptComplete(rect ? JSON.stringify(rect) : "");
|
|
|
|
})();
|
[iOS] [WebKit2] Add support for honoring -[UIMenuItem dontDismiss]
https://bugs.webkit.org/show_bug.cgi?id=196919
<rdar://problem/41630459>
Reviewed by Tim Horton.
Source/WebKit:
Adds modern WebKit support for -dontDismiss by implementing a couple of new platform hooks. Covered by a new
layout test: editing/selection/ios/selection-after-changing-text-with-callout-menu.html.
* Platform/spi/ios/UIKitSPI.h:
Declare the private -dontDismiss property of UIMenuItem.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView willFinishIgnoringCalloutBarFadeAfterPerformingAction]):
Additionally teach the web view (not just the content view) to respond to the hook. This matters in the case
where the WebKit client (most notably, Mail) overrides WKWebView methods to define custom actions in the menu
controller. This scenario is exercised by the new layout test.
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView willFinishIgnoringCalloutBarFadeAfterPerformingAction]):
If an action was performed where callout bar fading was ignored, then in WebKit, don't allow selection changes
to fade the callout bar until after the next remote layer tree commit.
(-[WKContentView _updateChangedSelection:]):
Stop suppressing selection updates when showing B/I/U controls, now that we can properly honor the -dontDismiss
property. This was originally introduced in <rdar://problem/15199925>, presumably to ensure that B/I/U buttons
(which have -dontDismiss set to YES) don't trigger selection change and end up dismissing themselves; however,
if triggering B/I/U actually changes the selection rects, this also means that the selection rects on-screen
would be stale after triggering these actions. This effect is most noticeable when bolding text.
(-[WKContentView shouldAllowHidingSelectionCommands]):
Tools:
Add iOS support for several new testing hooks. See below for more detail.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isDismissingMenu const):
Add a new script controller method to query whether the platform menu (on iOS, the callout bar) is done
dismissing. We consider the menu to be dismissing in between the `-WillHide` and `-DidHide` notifications sent
by UIKit when dismissing the callout bar (i.e. UIMenuController).
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::isDismissingMenu const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::didReceiveMessageToPage):
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setAllowedMenuActions):
Add a new helper method to specify a list of allowed actions when bringing up the menu. On iOS, in the case of
actions supported by the platform, this matches against method selector names (for instance, "SelectAll", or
"Copy", or "Paste"). In the case of the custom actions installed via `installCustomMenuAction`, we instead match
against the name of the custom action.
(WTR::TestRunner::installCustomMenuAction):
Add a new helper method to install a custom action for the context menu (on iOS, this is the callout bar). This
takes the name of the action (which appears in a button in the callout bar), whether the action should cause
the callout bar to automatically dismiss, and finally, a JavaScript callback that is invoked when the action is
triggered.
(WTR::TestRunner::performCustomMenuAction):
Invoked when the custom menu action is triggered.
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::installCustomMenuAction):
(WTR::TestController::setAllowedMenuActions):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
(WTR::TestInvocation::performCustomMenuAction):
Add plumbing to call back into the injected bundle when performing the custom action.
* WebKitTestRunner/TestInvocation.h:
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::installCustomMenuAction):
(WTR::TestController::setAllowedMenuActions):
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView initWithFrame:configuration:]):
(-[TestRunnerWKWebView becomeFirstResponder]):
(-[TestRunnerWKWebView _addCustomItemToMenuControllerIfNecessary]):
Helper method that converts web view's current custom menu action info into a UIMenuItem, and adds it to the
shared menu controller. This is also invoked when the web view becomes first responder, which matches behavior
in the Mail app on iOS.
(-[TestRunnerWKWebView installCustomMenuAction:dismissesAutomatically:callback:]):
(-[TestRunnerWKWebView setAllowedMenuActions:]):
(-[TestRunnerWKWebView resetCustomMenuAction]):
(-[TestRunnerWKWebView performCustomAction:]):
(-[TestRunnerWKWebView canPerformAction:withSender:]):
(-[TestRunnerWKWebView _willHideMenu]):
(-[TestRunnerWKWebView _didHideMenu]):
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
Reset both any custom installed actions on the shared menu controller, as well as the list of allowed actions,
if specified.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isDismissingMenu const):
LayoutTests:
Add a new iOS layout test that installs a custom, non-dismissing action in the callout menu that enlarges text.
The test then activates this custom menu item and checks that the selection rects after triggering this custom
action are updated, and the callout bar is still showing.
* editing/selection/ios/selection-after-changing-text-with-callout-menu-expected.txt: Added.
* editing/selection/ios/selection-after-changing-text-with-callout-menu.html: Added.
This test additionally suppresses all callout bar menu items except for the custom "Embiggen" action, to ensure
that the "Embiggen" option can be tapped from the layout test without having to navigate callout bar items by
tapping on the "Next" and "Show styles" buttons. This latter approach is very challenging to make reliable in
automation; when navigating submenus in the callout bar, the next button can't be tapped until the current
callout bar transition animation is complete, but there's no delegate method invoked or notification posted when
this happens.
* resources/ui-helper.js:
(window.UIHelper.isShowingMenu):
(window.UIHelper.isDismissingMenu):
(window.UIHelper.rectForMenuAction):
(window.UIHelper.async.chooseMenuAction):
Additionally add a few more UIHelper methods.
(window.UIHelper):
Canonical link: https://commits.webkit.org/211257@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244370 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-04-17 03:34:10 +00:00
|
|
|
`, stringResult => {
|
|
|
|
resolve(stringResult.length ? JSON.parse(stringResult) : null);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-03-16 21:57:18 +00:00
|
|
|
static chooseMenuAction(action)
|
[iOS] [WebKit2] Add support for honoring -[UIMenuItem dontDismiss]
https://bugs.webkit.org/show_bug.cgi?id=196919
<rdar://problem/41630459>
Reviewed by Tim Horton.
Source/WebKit:
Adds modern WebKit support for -dontDismiss by implementing a couple of new platform hooks. Covered by a new
layout test: editing/selection/ios/selection-after-changing-text-with-callout-menu.html.
* Platform/spi/ios/UIKitSPI.h:
Declare the private -dontDismiss property of UIMenuItem.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView willFinishIgnoringCalloutBarFadeAfterPerformingAction]):
Additionally teach the web view (not just the content view) to respond to the hook. This matters in the case
where the WebKit client (most notably, Mail) overrides WKWebView methods to define custom actions in the menu
controller. This scenario is exercised by the new layout test.
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView willFinishIgnoringCalloutBarFadeAfterPerformingAction]):
If an action was performed where callout bar fading was ignored, then in WebKit, don't allow selection changes
to fade the callout bar until after the next remote layer tree commit.
(-[WKContentView _updateChangedSelection:]):
Stop suppressing selection updates when showing B/I/U controls, now that we can properly honor the -dontDismiss
property. This was originally introduced in <rdar://problem/15199925>, presumably to ensure that B/I/U buttons
(which have -dontDismiss set to YES) don't trigger selection change and end up dismissing themselves; however,
if triggering B/I/U actually changes the selection rects, this also means that the selection rects on-screen
would be stale after triggering these actions. This effect is most noticeable when bolding text.
(-[WKContentView shouldAllowHidingSelectionCommands]):
Tools:
Add iOS support for several new testing hooks. See below for more detail.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isDismissingMenu const):
Add a new script controller method to query whether the platform menu (on iOS, the callout bar) is done
dismissing. We consider the menu to be dismissing in between the `-WillHide` and `-DidHide` notifications sent
by UIKit when dismissing the callout bar (i.e. UIMenuController).
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::isDismissingMenu const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::didReceiveMessageToPage):
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setAllowedMenuActions):
Add a new helper method to specify a list of allowed actions when bringing up the menu. On iOS, in the case of
actions supported by the platform, this matches against method selector names (for instance, "SelectAll", or
"Copy", or "Paste"). In the case of the custom actions installed via `installCustomMenuAction`, we instead match
against the name of the custom action.
(WTR::TestRunner::installCustomMenuAction):
Add a new helper method to install a custom action for the context menu (on iOS, this is the callout bar). This
takes the name of the action (which appears in a button in the callout bar), whether the action should cause
the callout bar to automatically dismiss, and finally, a JavaScript callback that is invoked when the action is
triggered.
(WTR::TestRunner::performCustomMenuAction):
Invoked when the custom menu action is triggered.
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::installCustomMenuAction):
(WTR::TestController::setAllowedMenuActions):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
(WTR::TestInvocation::performCustomMenuAction):
Add plumbing to call back into the injected bundle when performing the custom action.
* WebKitTestRunner/TestInvocation.h:
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::installCustomMenuAction):
(WTR::TestController::setAllowedMenuActions):
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView initWithFrame:configuration:]):
(-[TestRunnerWKWebView becomeFirstResponder]):
(-[TestRunnerWKWebView _addCustomItemToMenuControllerIfNecessary]):
Helper method that converts web view's current custom menu action info into a UIMenuItem, and adds it to the
shared menu controller. This is also invoked when the web view becomes first responder, which matches behavior
in the Mail app on iOS.
(-[TestRunnerWKWebView installCustomMenuAction:dismissesAutomatically:callback:]):
(-[TestRunnerWKWebView setAllowedMenuActions:]):
(-[TestRunnerWKWebView resetCustomMenuAction]):
(-[TestRunnerWKWebView performCustomAction:]):
(-[TestRunnerWKWebView canPerformAction:withSender:]):
(-[TestRunnerWKWebView _willHideMenu]):
(-[TestRunnerWKWebView _didHideMenu]):
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
Reset both any custom installed actions on the shared menu controller, as well as the list of allowed actions,
if specified.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isDismissingMenu const):
LayoutTests:
Add a new iOS layout test that installs a custom, non-dismissing action in the callout menu that enlarges text.
The test then activates this custom menu item and checks that the selection rects after triggering this custom
action are updated, and the callout bar is still showing.
* editing/selection/ios/selection-after-changing-text-with-callout-menu-expected.txt: Added.
* editing/selection/ios/selection-after-changing-text-with-callout-menu.html: Added.
This test additionally suppresses all callout bar menu items except for the custom "Embiggen" action, to ensure
that the "Embiggen" option can be tapped from the layout test without having to navigate callout bar items by
tapping on the "Next" and "Show styles" buttons. This latter approach is very challenging to make reliable in
automation; when navigating submenus in the callout bar, the next button can't be tapped until the current
callout bar transition animation is complete, but there's no delegate method invoked or notification posted when
this happens.
* resources/ui-helper.js:
(window.UIHelper.isShowingMenu):
(window.UIHelper.isDismissingMenu):
(window.UIHelper.rectForMenuAction):
(window.UIHelper.async.chooseMenuAction):
Additionally add a few more UIHelper methods.
(window.UIHelper):
Canonical link: https://commits.webkit.org/211257@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244370 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-04-17 03:34:10 +00:00
|
|
|
{
|
2021-03-16 21:57:18 +00:00
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(() => {
|
|
|
|
uiController.chooseMenuAction("${action}", () => {
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
});
|
|
|
|
})();
|
|
|
|
`, resolve);
|
|
|
|
});
|
[iOS] [WebKit2] Add support for honoring -[UIMenuItem dontDismiss]
https://bugs.webkit.org/show_bug.cgi?id=196919
<rdar://problem/41630459>
Reviewed by Tim Horton.
Source/WebKit:
Adds modern WebKit support for -dontDismiss by implementing a couple of new platform hooks. Covered by a new
layout test: editing/selection/ios/selection-after-changing-text-with-callout-menu.html.
* Platform/spi/ios/UIKitSPI.h:
Declare the private -dontDismiss property of UIMenuItem.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView willFinishIgnoringCalloutBarFadeAfterPerformingAction]):
Additionally teach the web view (not just the content view) to respond to the hook. This matters in the case
where the WebKit client (most notably, Mail) overrides WKWebView methods to define custom actions in the menu
controller. This scenario is exercised by the new layout test.
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView willFinishIgnoringCalloutBarFadeAfterPerformingAction]):
If an action was performed where callout bar fading was ignored, then in WebKit, don't allow selection changes
to fade the callout bar until after the next remote layer tree commit.
(-[WKContentView _updateChangedSelection:]):
Stop suppressing selection updates when showing B/I/U controls, now that we can properly honor the -dontDismiss
property. This was originally introduced in <rdar://problem/15199925>, presumably to ensure that B/I/U buttons
(which have -dontDismiss set to YES) don't trigger selection change and end up dismissing themselves; however,
if triggering B/I/U actually changes the selection rects, this also means that the selection rects on-screen
would be stale after triggering these actions. This effect is most noticeable when bolding text.
(-[WKContentView shouldAllowHidingSelectionCommands]):
Tools:
Add iOS support for several new testing hooks. See below for more detail.
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isDismissingMenu const):
Add a new script controller method to query whether the platform menu (on iOS, the callout bar) is done
dismissing. We consider the menu to be dismissing in between the `-WillHide` and `-DidHide` notifications sent
by UIKit when dismissing the callout bar (i.e. UIMenuController).
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::isDismissingMenu const):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::didReceiveMessageToPage):
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setAllowedMenuActions):
Add a new helper method to specify a list of allowed actions when bringing up the menu. On iOS, in the case of
actions supported by the platform, this matches against method selector names (for instance, "SelectAll", or
"Copy", or "Paste"). In the case of the custom actions installed via `installCustomMenuAction`, we instead match
against the name of the custom action.
(WTR::TestRunner::installCustomMenuAction):
Add a new helper method to install a custom action for the context menu (on iOS, this is the callout bar). This
takes the name of the action (which appears in a button in the callout bar), whether the action should cause
the callout bar to automatically dismiss, and finally, a JavaScript callback that is invoked when the action is
triggered.
(WTR::TestRunner::performCustomMenuAction):
Invoked when the custom menu action is triggered.
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::installCustomMenuAction):
(WTR::TestController::setAllowedMenuActions):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
(WTR::TestInvocation::performCustomMenuAction):
Add plumbing to call back into the injected bundle when performing the custom action.
* WebKitTestRunner/TestInvocation.h:
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::installCustomMenuAction):
(WTR::TestController::setAllowedMenuActions):
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
(-[TestRunnerWKWebView initWithFrame:configuration:]):
(-[TestRunnerWKWebView becomeFirstResponder]):
(-[TestRunnerWKWebView _addCustomItemToMenuControllerIfNecessary]):
Helper method that converts web view's current custom menu action info into a UIMenuItem, and adds it to the
shared menu controller. This is also invoked when the web view becomes first responder, which matches behavior
in the Mail app on iOS.
(-[TestRunnerWKWebView installCustomMenuAction:dismissesAutomatically:callback:]):
(-[TestRunnerWKWebView setAllowedMenuActions:]):
(-[TestRunnerWKWebView resetCustomMenuAction]):
(-[TestRunnerWKWebView performCustomAction:]):
(-[TestRunnerWKWebView canPerformAction:withSender:]):
(-[TestRunnerWKWebView _willHideMenu]):
(-[TestRunnerWKWebView _didHideMenu]):
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
Reset both any custom installed actions on the shared menu controller, as well as the list of allowed actions,
if specified.
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::isDismissingMenu const):
LayoutTests:
Add a new iOS layout test that installs a custom, non-dismissing action in the callout menu that enlarges text.
The test then activates this custom menu item and checks that the selection rects after triggering this custom
action are updated, and the callout bar is still showing.
* editing/selection/ios/selection-after-changing-text-with-callout-menu-expected.txt: Added.
* editing/selection/ios/selection-after-changing-text-with-callout-menu.html: Added.
This test additionally suppresses all callout bar menu items except for the custom "Embiggen" action, to ensure
that the "Embiggen" option can be tapped from the layout test without having to navigate callout bar items by
tapping on the "Next" and "Show styles" buttons. This latter approach is very challenging to make reliable in
automation; when navigating submenus in the callout bar, the next button can't be tapped until the current
callout bar transition animation is complete, but there's no delegate method invoked or notification posted when
this happens.
* resources/ui-helper.js:
(window.UIHelper.isShowingMenu):
(window.UIHelper.isDismissingMenu):
(window.UIHelper.rectForMenuAction):
(window.UIHelper.async.chooseMenuAction):
Additionally add a few more UIHelper methods.
(window.UIHelper):
Canonical link: https://commits.webkit.org/211257@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244370 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-04-17 03:34:10 +00:00
|
|
|
}
|
2019-05-14 16:43:51 +00:00
|
|
|
|
2020-04-22 16:21:37 +00:00
|
|
|
static waitForEvent(target, eventName)
|
|
|
|
{
|
|
|
|
return new Promise(resolve => target.addEventListener(eventName, resolve, { once: true }));
|
|
|
|
}
|
|
|
|
|
2019-06-25 23:41:31 +00:00
|
|
|
static callFunctionAndWaitForEvent(functionToCall, target, eventName)
|
|
|
|
{
|
2020-06-29 23:58:59 +00:00
|
|
|
return new Promise(async resolve => {
|
|
|
|
let event;
|
|
|
|
await Promise.all([
|
|
|
|
new Promise((eventListenerResolve) => {
|
|
|
|
target.addEventListener(eventName, (e) => {
|
|
|
|
event = e;
|
|
|
|
eventListenerResolve();
|
|
|
|
}, {once: true});
|
|
|
|
}),
|
|
|
|
new Promise(async functionResolve => {
|
|
|
|
await functionToCall();
|
|
|
|
functionResolve();
|
|
|
|
})
|
|
|
|
]);
|
|
|
|
resolve(event);
|
2019-06-25 23:41:31 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-05-14 16:43:51 +00:00
|
|
|
static callFunctionAndWaitForScrollToFinish(functionToCall, ...theArguments)
|
2019-10-18 02:27:01 +00:00
|
|
|
{
|
|
|
|
return UIHelper.callFunctionAndWaitForTargetScrollToFinish(window, functionToCall, theArguments)
|
|
|
|
}
|
|
|
|
|
|
|
|
static callFunctionAndWaitForTargetScrollToFinish(scrollTarget, functionToCall, ...theArguments)
|
2019-05-14 16:43:51 +00:00
|
|
|
{
|
|
|
|
return new Promise((resolved) => {
|
|
|
|
function scrollDidFinish() {
|
2019-10-18 02:27:01 +00:00
|
|
|
scrollTarget.removeEventListener("scroll", handleScroll, true);
|
2019-05-14 16:43:51 +00:00
|
|
|
resolved();
|
|
|
|
}
|
|
|
|
|
|
|
|
let lastScrollTimerId = 0; // When the timer with this id fires then the page has finished scrolling.
|
|
|
|
function handleScroll() {
|
|
|
|
if (lastScrollTimerId) {
|
|
|
|
window.clearTimeout(lastScrollTimerId);
|
|
|
|
lastScrollTimerId = 0;
|
|
|
|
}
|
|
|
|
lastScrollTimerId = window.setTimeout(scrollDidFinish, 300); // Over 250ms to give some room for error.
|
|
|
|
}
|
2019-10-18 02:27:01 +00:00
|
|
|
scrollTarget.addEventListener("scroll", handleScroll, true);
|
2019-05-14 16:43:51 +00:00
|
|
|
|
|
|
|
functionToCall.apply(this, theArguments);
|
|
|
|
});
|
|
|
|
}
|
2019-05-21 05:01:54 +00:00
|
|
|
|
2021-02-18 08:49:40 +00:00
|
|
|
static waitForTargetScrollAnimationToSettle(scrollTarget)
|
|
|
|
{
|
|
|
|
return new Promise((resolved) => {
|
|
|
|
let lastObservedScrollPosition = [scrollTarget.scrollLeft, scrollTarget.scrollTop];
|
|
|
|
let frameOfLastChange = 0;
|
|
|
|
let totalFrames = 0;
|
|
|
|
|
|
|
|
function animationFrame() {
|
|
|
|
if (lastObservedScrollPosition[0] != scrollTarget.scrollLeft ||
|
|
|
|
lastObservedScrollPosition[1] != scrollTarget.scrollTop) {
|
|
|
|
lastObservedScrollPosition = [scrollTarget.scrollLeft, scrollTarget.scrollTop];
|
|
|
|
frameOfLastChange = totalFrames;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have gone 20 frames without changing, resolve. If we have gone 500, then time out.
|
|
|
|
// This matches the amount of frames used in the WPT scroll animation helper.
|
|
|
|
if (totalFrames - frameOfLastChange >= 20 || totalFrames > 500)
|
|
|
|
resolved();
|
|
|
|
|
|
|
|
totalFrames++;
|
|
|
|
requestAnimationFrame(animationFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
requestAnimationFrame(animationFrame);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-05-21 05:01:54 +00:00
|
|
|
static rotateDevice(orientationName, animatedResize = false)
|
|
|
|
{
|
2019-06-01 00:43:56 +00:00
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
2019-05-21 05:01:54 +00:00
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.${animatedResize ? "simulateRotationLikeSafari" : "simulateRotation"}("${orientationName}", function() {
|
|
|
|
uiController.doAfterVisibleContentRectUpdate(() => uiController.uiScriptComplete());
|
|
|
|
});
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
2019-07-25 21:12:01 +00:00
|
|
|
|
|
|
|
static getScrollingTree()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
return uiController.scrollingTreeAsText;
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
[iOS 13] Taps that interrupt momentum scrolling are recognized as clicks
https://bugs.webkit.org/show_bug.cgi?id=200516
<rdar://problem/53889373>
Reviewed by Tim Horton.
Source/WebKit:
After <https://trac.webkit.org/r247656>, the -tracksImmediatelyWhileDecelerating property of WKScrollView and
WKChildScrollView is set to NO. This means that if a user interacts with the page while the scroll view is
decelerating (e.g. after momentum scrolling), the pan gesture recognizer will not be immediately recognized.
This gives other gesture recognizers, such as the synthetic click (single tap) gesture a chance to instead
recognize first. In this particular bug, this causes taps on the web view that are intended to only stop
momentum scrolling to instead activate clickable elements beneath the touch, such as links and buttons.
To mitigate this, we add some logic to prevent the click gesture recognizer from firing in the case where the
tap also causes the scroll view to decelerate. This heuristic is similar to the one introduced in r219310, which
has the same purpose of hiding gestures that stop momentum scrolling from the page, and also consults
-[UIScrollView _isInterruptingDeceleration].
Tests: fast/scrolling/ios/click-events-during-momentum-scroll-in-main-frame.html
fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-after-tap-on-body.html
fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow.html
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView gestureRecognizerShouldBegin:]):
Return NO in the case of the single tap gesture if the UIScrollView most recently touched by the single tap
gesture (or one of its enclosing scroll views, up to the main WKScrollView) is being interrupted while
decelerating.
* UIProcess/ios/WKSyntheticTapGestureRecognizer.h:
* UIProcess/ios/WKSyntheticTapGestureRecognizer.mm:
(-[WKSyntheticTapGestureRecognizer reset]):
(-[WKSyntheticTapGestureRecognizer touchesBegan:withEvent:]):
Teach WKSyntheticTapGestureRecognizer to keep track of the last WKScrollView that was touched, for later use in
-gestureRecognizerShouldBegin:. To do this, we keep a weak reference to the first UIScrollView we find in the
set of touches.
(-[WKSyntheticTapGestureRecognizer lastTouchedScrollView]):
LayoutTests:
Add new layout tests. See below for details.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-main-frame-expected.txt: Added.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-main-frame.html: Added.
Add a test to verify that interrupting scrolling in the main frame using a tap doesn't fire a click event.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-after-tap-on-body-expected.txt: Added.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-after-tap-on-body.html: Added.
Add a test to verify that after triggering momentum scrolling in a fast subscrollable region, tapping outside of
the scroller will still fire a click event.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-expected.txt: Added.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow.html: Added.
Add a test to verify that interrupting scrolling in a fast subscrollable region using a tap doesn't fire a
click event.
* resources/ui-helper.js:
(window.UIHelper.dragFromPointToPoint):
(window.UIHelper):
Canonical link: https://commits.webkit.org/214316@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248433 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-08-08 18:54:06 +00:00
|
|
|
|
2021-08-12 20:16:51 +00:00
|
|
|
static getUIViewTree()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
return uiController.uiViewTreeAsText;
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
[iOS 13] Taps that interrupt momentum scrolling are recognized as clicks
https://bugs.webkit.org/show_bug.cgi?id=200516
<rdar://problem/53889373>
Reviewed by Tim Horton.
Source/WebKit:
After <https://trac.webkit.org/r247656>, the -tracksImmediatelyWhileDecelerating property of WKScrollView and
WKChildScrollView is set to NO. This means that if a user interacts with the page while the scroll view is
decelerating (e.g. after momentum scrolling), the pan gesture recognizer will not be immediately recognized.
This gives other gesture recognizers, such as the synthetic click (single tap) gesture a chance to instead
recognize first. In this particular bug, this causes taps on the web view that are intended to only stop
momentum scrolling to instead activate clickable elements beneath the touch, such as links and buttons.
To mitigate this, we add some logic to prevent the click gesture recognizer from firing in the case where the
tap also causes the scroll view to decelerate. This heuristic is similar to the one introduced in r219310, which
has the same purpose of hiding gestures that stop momentum scrolling from the page, and also consults
-[UIScrollView _isInterruptingDeceleration].
Tests: fast/scrolling/ios/click-events-during-momentum-scroll-in-main-frame.html
fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-after-tap-on-body.html
fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow.html
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView gestureRecognizerShouldBegin:]):
Return NO in the case of the single tap gesture if the UIScrollView most recently touched by the single tap
gesture (or one of its enclosing scroll views, up to the main WKScrollView) is being interrupted while
decelerating.
* UIProcess/ios/WKSyntheticTapGestureRecognizer.h:
* UIProcess/ios/WKSyntheticTapGestureRecognizer.mm:
(-[WKSyntheticTapGestureRecognizer reset]):
(-[WKSyntheticTapGestureRecognizer touchesBegan:withEvent:]):
Teach WKSyntheticTapGestureRecognizer to keep track of the last WKScrollView that was touched, for later use in
-gestureRecognizerShouldBegin:. To do this, we keep a weak reference to the first UIScrollView we find in the
set of touches.
(-[WKSyntheticTapGestureRecognizer lastTouchedScrollView]):
LayoutTests:
Add new layout tests. See below for details.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-main-frame-expected.txt: Added.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-main-frame.html: Added.
Add a test to verify that interrupting scrolling in the main frame using a tap doesn't fire a click event.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-after-tap-on-body-expected.txt: Added.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-after-tap-on-body.html: Added.
Add a test to verify that after triggering momentum scrolling in a fast subscrollable region, tapping outside of
the scroller will still fire a click event.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-expected.txt: Added.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow.html: Added.
Add a test to verify that interrupting scrolling in a fast subscrollable region using a tap doesn't fire a
click event.
* resources/ui-helper.js:
(window.UIHelper.dragFromPointToPoint):
(window.UIHelper):
Canonical link: https://commits.webkit.org/214316@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248433 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-08-08 18:54:06 +00:00
|
|
|
static dragFromPointToPoint(fromX, fromY, toX, toY, duration)
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily()) {
|
|
|
|
eventSender.mouseMoveTo(fromX, fromY);
|
|
|
|
eventSender.mouseDown();
|
|
|
|
eventSender.leapForward(duration * 1000);
|
|
|
|
eventSender.mouseMoveTo(toX, toY);
|
|
|
|
eventSender.mouseUp();
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.dragFromPointToPoint(${fromX}, ${fromY}, ${toX}, ${toY}, ${duration}, () => {
|
2019-10-17 17:02:41 +00:00
|
|
|
uiController.uiScriptComplete();
|
[iOS 13] Taps that interrupt momentum scrolling are recognized as clicks
https://bugs.webkit.org/show_bug.cgi?id=200516
<rdar://problem/53889373>
Reviewed by Tim Horton.
Source/WebKit:
After <https://trac.webkit.org/r247656>, the -tracksImmediatelyWhileDecelerating property of WKScrollView and
WKChildScrollView is set to NO. This means that if a user interacts with the page while the scroll view is
decelerating (e.g. after momentum scrolling), the pan gesture recognizer will not be immediately recognized.
This gives other gesture recognizers, such as the synthetic click (single tap) gesture a chance to instead
recognize first. In this particular bug, this causes taps on the web view that are intended to only stop
momentum scrolling to instead activate clickable elements beneath the touch, such as links and buttons.
To mitigate this, we add some logic to prevent the click gesture recognizer from firing in the case where the
tap also causes the scroll view to decelerate. This heuristic is similar to the one introduced in r219310, which
has the same purpose of hiding gestures that stop momentum scrolling from the page, and also consults
-[UIScrollView _isInterruptingDeceleration].
Tests: fast/scrolling/ios/click-events-during-momentum-scroll-in-main-frame.html
fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-after-tap-on-body.html
fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow.html
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView gestureRecognizerShouldBegin:]):
Return NO in the case of the single tap gesture if the UIScrollView most recently touched by the single tap
gesture (or one of its enclosing scroll views, up to the main WKScrollView) is being interrupted while
decelerating.
* UIProcess/ios/WKSyntheticTapGestureRecognizer.h:
* UIProcess/ios/WKSyntheticTapGestureRecognizer.mm:
(-[WKSyntheticTapGestureRecognizer reset]):
(-[WKSyntheticTapGestureRecognizer touchesBegan:withEvent:]):
Teach WKSyntheticTapGestureRecognizer to keep track of the last WKScrollView that was touched, for later use in
-gestureRecognizerShouldBegin:. To do this, we keep a weak reference to the first UIScrollView we find in the
set of touches.
(-[WKSyntheticTapGestureRecognizer lastTouchedScrollView]):
LayoutTests:
Add new layout tests. See below for details.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-main-frame-expected.txt: Added.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-main-frame.html: Added.
Add a test to verify that interrupting scrolling in the main frame using a tap doesn't fire a click event.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-after-tap-on-body-expected.txt: Added.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-after-tap-on-body.html: Added.
Add a test to verify that after triggering momentum scrolling in a fast subscrollable region, tapping outside of
the scroller will still fire a click event.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow-expected.txt: Added.
* fast/scrolling/ios/click-events-during-momentum-scroll-in-overflow.html: Added.
Add a test to verify that interrupting scrolling in a fast subscrollable region using a tap doesn't fire a
click event.
* resources/ui-helper.js:
(window.UIHelper.dragFromPointToPoint):
(window.UIHelper):
Canonical link: https://commits.webkit.org/214316@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248433 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-08-08 18:54:06 +00:00
|
|
|
});
|
|
|
|
})();`, resolve);
|
|
|
|
});
|
|
|
|
}
|
2019-08-27 00:18:57 +00:00
|
|
|
|
[iPadOS] Unable to change focus between Google Docs windows by tapping
https://bugs.webkit.org/show_bug.cgi?id=213985
<rdar://problem/57083267>
Reviewed by Darin Adler.
Source/WebKit:
When putting two Google Docs windows side-by-side on iPad, it's currently not possible to change the window to
which keyboard input is routed. In native views (e.g. two side-by-side Notes windows), this is normally handled
by `UITextMultiTapRecognizer`, which is part of the `UITextSelectionInteraction`; tapping to place the text
selection calls into `-[UITextInteractionAssistant setFirstResponderIfNecessaryActivatingSelection:]`, which
updates the key window if needed. This doesn't apply to Google Docs because they instead use touch events to
drive their own "text interaction"-like behaviors instead of relying on system gesture recognizers, which we
suppress due to the fact that the selection is within a hidden contenteditable.
But even in non-hidden editable areas, the initial tap to focus an editable element still doesn't automatically
make the window key, since the editable text interaction gestures are still inactive when tapping to focus an
editable element. This means two taps are currently required to change the key window when focusing two Safari
windows side-by-side: the first tap to focus the element (via the synthetic click gesture), and the second tap
to trigger the editable text interaction tap gesture that is used to set the selection.
To fix both of these issues, make some minor adjustments to call `-makeKeyWindow` from WebKit when focusing
editable elements. See below for more details.
Test: editing/selection/ios/become-key-window-when-focusing-editable-area.html
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _webTouchEventsRecognized:]):
For the case in Google Docs where a hidden editable element is used and tapping in the page does not result in
the element being refocused, we additionally need to make sure that we make our window key anyways. Limit this
hack to tap gestures, and only when there is a hidden focused editable element to emulate platform behavior of
updating the key window based on the text tap gesture.
(-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:]):
Make the content view's window key when focusing an editable element.
(-[WKContentView hasHiddenContentEditable]):
Consider the selection to be inside a hidden editable area if the `WebKit::FocusedElementIsTooSmall` flag is set
as well. While this doesn't affect Google Docs, it does affect some other custom editors, such as Quip.
(-[WKContentView mouseGestureRecognizerChanged:]):
Additionally make the current window key when clicking in a hidden editable area with a trackpad on iOS.
Tools:
Add WebKitTestRunner support for being able to verify that a web view's window has become the key window.
* DumpRenderTree/CMakeLists.txt:
* DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
* DumpRenderTree/UIScriptController.cpp: Added.
(WTR::UIScriptController::setWindowIsKey):
(WTR::UIScriptController::windowIsKey const):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* TestRunnerShared/UIScriptContext/UIScriptControllerShared.cpp: Renamed from Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp.
Rename `UIScriptController.cpp` (in TestRunnerShared) to `UIScriptControllerShared.cpp`, and introduce new
DumpRenderTree and WebKitTestRunner versions of `UIScriptController.cpp` to house DumpRenderTree and
WebKitTestRunner-specific UIScriptController method implementations.
For now, these are just `windowIsKey` and `setWindowIsKey` below, which plumb into their respective platform-
agnostic `PlatformWebView` methods in WebKitTestRunner.
* WebKitTestRunner/UIScriptController.cpp: Added.
(WTR::UIScriptController::windowIsKey const):
(WTR::UIScriptController::setWindowIsKey):
* WebKitTestRunner/CMakeLists.txt:
* WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
* WebKitTestRunner/ios/PlatformWebViewIOS.mm:
(-[WebKitTestRunnerWindow becomeKeyWindow]):
(-[WebKitTestRunnerWindow resignKeyWindow]):
Update these two methods to update `m_windowIsKey` when the test runner's `UIWindow` becomes the key window (or
stops being the key window). This is invoked when `-[UIWindow makeKeyWindow]` is called (e.g. from within WebKit
code when tapping on an editable element).
(WTR::PlatformWebView::setWindowIsKey):
Avoid infinitely looping when setting windowIsKey to `true`, due to `-becomeKeyWindow` calling back into
`setWindowIsKey`.
LayoutTests:
Add a new layout test to verify that tapping to focus a plain textarea causes the web view's window to become
the key window, as well as tapping to focus a hidden contenteditable area, over a touch handler that prevents
default.
* editing/selection/ios/become-key-window-when-focusing-editable-area-expected.txt: Added.
* editing/selection/ios/become-key-window-when-focusing-editable-area.html: Added.
* resources/ui-helper.js:
(window.UIHelper.setWindowIsKey):
(window.UIHelper.windowIsKey):
Canonical link: https://commits.webkit.org/226799@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@263979 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-07-06 19:45:54 +00:00
|
|
|
static setWindowIsKey(isKey)
|
|
|
|
{
|
|
|
|
const script = `uiController.windowIsKey = ${isKey}`;
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(script, resolve));
|
|
|
|
}
|
|
|
|
|
|
|
|
static windowIsKey()
|
|
|
|
{
|
|
|
|
const script = "uiController.uiScriptComplete(uiController.windowIsKey)";
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(script, (result) => {
|
|
|
|
resolve(result === "true");
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2019-08-27 00:18:57 +00:00
|
|
|
static waitForDoubleTapDelay()
|
|
|
|
{
|
|
|
|
const uiScript = `uiController.doAfterDoubleTapDelay(() => uiController.uiScriptComplete(""))`;
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(uiScript, resolve));
|
|
|
|
}
|
2019-09-26 19:03:47 +00:00
|
|
|
|
|
|
|
static async waitForSelectionToAppear() {
|
|
|
|
while (true) {
|
Programmatic selection of text in a text field causes the highlight overlay to spill out
https://bugs.webkit.org/show_bug.cgi?id=215647
<rdar://problem/67404979>
Reviewed by Darin Adler.
Source/WebCore:
See WebKit ChangeLog for more detail.
* html/HTMLTextFormControlElement.h: Export a helper function.
Source/WebKit:
UIKit consults the SPI method `-_selectionClipRect` on WKContentView to determine the maximum bounds in which it
is allowed to show text selection UI (i.e. the text caret view, selection highlight views, and selection
grabbers). Normally, when contentEditable elements and editable text form controls are focused, we plumb the
bounds of the focused element to the UI process via `focusedElementRect` in editor state's post layout data.
However, in this case, the selection is inside a readonly text field that is *not* focused; this causes us to
return `CGRectNull` from `-_selectionClipRect`, which means that UIKit selection UI is not clipped at all and
instead overflows the bounds of the input element.
To fix this, rearrange some logic in `WebPage::getPlatformEditorState` in `WebPageIOS.mm` such that we compute
and send the selection clipping rect if the selection is inside a text form control, even if it is not the
focused element. In doing this, we also rename some confusingly-named members in `EditorState::PostLayoutData`
(see below for more detail).
Test: editing/selection/ios/select-all-in-readonly-input-does-not-overflow.html
* Platform/spi/ios/UIKitSPI.h:
Add a declaration for `-_selectionClipRect`.
* Shared/EditorState.cpp:
(WebKit::EditorState::PostLayoutData::encode const):
(WebKit::EditorState::PostLayoutData::decode):
(WebKit::operator<<):
* Shared/EditorState.h:
Split the existing rect member `focusedElementRect` into two: `selectionClipRect` on iOS, and
`selectionBoundingRect` on macOS. Previously, `focusedElementRect` was set to the focused element's bounding
rect on iOS (as expected), but on macOS, we set to the bounds of the ranged or caret selection; we proceed to
use this rect to mean the bounds of the selection anyways in macOS-specific code, so it makes more sense to just
move this into the macOS-specific section.
Additionally, after the below change in WebPageIOS, `focusedElementRect` is no longer specific to the focused
element, so rename it instead to `selectionClipRect` instead. In `WKContentViewInteraction.mm`, this rect is
effectively only used in two ways: as the selection clip rect for UIKit, and to determine if the selection would
be completely clipped anyways (in which case we suppress UIKit text interactions), so `selectionClipRect` is a
name that is suitable for both purposes.
* UIProcess/API/mac/WKWebViewTestingMac.mm:
(-[WKWebView _candidateRect]):
* UIProcess/Cocoa/WebViewImpl.mm:
Rename `focusedElementRect` to `selectionBoundingRect` on macOS.
(WebKit::WebViewImpl::handleRequestedCandidates):
* UIProcess/ios/WKContentViewInteraction.mm:
Rename `focusedElementRect` to `selectionClipRect` on iOS.
(WebKit::WKSelectionDrawingInfo::WKSelectionDrawingInfo):
(-[WKContentView _selectionClipRect]):
Change this to not require a focused element when returning the selection clip rect, and instead return the
editor state's selection clip rect as long as it is not empty.
(-[WKContentView _updateSelectionAssistantSuppressionState]):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getPlatformEditorState const):
Refactor this code to compute and send selectionClipRect as long as the selection is inside a form control or
editing host (not just when there is a focused element). Also leave a drive-by FIXME about using the focused
element (instead of the selection container node) when computing the caret color.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::getPlatformEditorState const):
Tools:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::clipSelectionViewRectToContentView):
Add a helper function to clip UIKit selection UI rects (for carets, selection grabbers, and ranged selection
highlights) to the content view's (WKContentView's) bounds, as well as the selection clip rect if it is nonnull.
(WTR::UIScriptControllerIOS::selectionStartGrabberViewRect const):
(WTR::UIScriptControllerIOS::selectionEndGrabberViewRect const):
(WTR::UIScriptControllerIOS::selectionCaretViewRect const):
(WTR::UIScriptControllerIOS::selectionRangeViewRects const):
LayoutTests:
* editing/selection/ios/select-all-in-readonly-input-does-not-overflow-expected.txt: Added.
* editing/selection/ios/select-all-in-readonly-input-does-not-overflow.html: Added.
Add a new layout test to verify that the width of the selection view does not exceed the width of the readonly
input containing the selected text.
* resources/ui-helper.js:
(window.UIHelper.async waitForSelectionToAppear):
Adjust this UIHelper function to additionally resolve to the selection rects, so that it won't be necessary for
callers to ask for the selection view rects separately after waiting for selection views to appear.
Canonical link: https://commits.webkit.org/228528@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@266051 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-08-24 01:51:56 +00:00
|
|
|
let selectionRects = await this.getUISelectionViewRects();
|
|
|
|
if (selectionRects.length > 0)
|
|
|
|
return selectionRects;
|
2019-09-26 19:03:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static async waitForSelectionToDisappear() {
|
|
|
|
while (true) {
|
|
|
|
if (!(await this.getUISelectionViewRects()).length)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
[Clipboard API] Implement ClipboardItem.getType() for platform clipboard items
https://bugs.webkit.org/show_bug.cgi?id=203168
Reviewed by Tim Horton.
Source/WebCore:
This patch completes support for ClipboardItem.getType().
Tests: editing/async-clipboard/clipboard-change-data-while-getting-type.html
editing/async-clipboard/clipboard-get-type-with-old-items.html
editing/async-clipboard/clipboard-item-get-type-basic.html
ClipboardTests.ReadMultipleItems
* Modules/async-clipboard/Clipboard.cpp:
(WebCore::Clipboard::getType):
Implement getType(). If the given clipboard item is being tracked as one of the active clipboard items, then
allow it to read data from the platform pasteboard. We use existing pasteboard reading methods and classes
(PasteboardPlainText and WebContentMarkupReader) to ask the platform pasteboard for text and markup data,
respectively, and go through readURL() for "text/uri-list".
Before exposing any data to the page, we additionally check that the change count of the pasteboard is still
what we started with when setting up the current session. If this is not the case, we reject the promise and
immediately clear out the session.
(WebCore::Clipboard::activePasteboard):
* Modules/async-clipboard/Clipboard.h:
* dom/DataTransfer.h:
Drive-by tweak: make the WebContentReadingPolicy enum class narrower.
* platform/Pasteboard.h:
Add an enum flag for allowing or ignoring the platform URL type when reading plain text from the platform
pasteboard. We use this in Clipboard::getType() to ignore URLs on the platform pasteboard when plain text, since
the plain text reader would otherwise prefer URLs over plain text by default, and read the URL type instead of
the plain text type.
* platform/StaticPasteboard.h:
* platform/gtk/PasteboardGtk.cpp:
(WebCore::Pasteboard::read):
* platform/ios/PasteboardIOS.mm:
(WebCore::Pasteboard::read):
* platform/libwpe/PasteboardLibWPE.cpp:
(WebCore::Pasteboard::read):
* platform/mac/PasteboardMac.mm:
(WebCore::Pasteboard::read):
* platform/win/PasteboardWin.cpp:
(WebCore::Pasteboard::read):
Tools:
Add support for the new layout tests, as well as a new API test.
* DumpRenderTree/ios/UIScriptControllerIOS.h:
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::copyText):
Implement UIScriptController.copyText in WebKit1. This is used in one of the new layout tests, which passes in
WebKit1 on macOS and iOS.
* DumpRenderTree/mac/DumpRenderTreePasteboard.mm:
(-[LocalPasteboard declareTypes:owner:]):
(-[LocalPasteboard addTypes:owner:]):
(-[LocalPasteboard _addTypesWithoutUpdatingChangeCount:owner:]):
Adjust logic when declaring types on the platform pasteboard, such that it behaves more like the platform; when
declaring types, even if the owner doesn't change, the change count should still get bumped up by 1.
* DumpRenderTree/mac/UIScriptControllerMac.h:
* DumpRenderTree/mac/UIScriptControllerMac.mm:
(WTR::UIScriptControllerMac::copyText):
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/ClipboardTests.mm: Added.
(-[TestWKWebView readClipboard]):
(createWebViewForClipboardTests):
(writeMultipleObjectsToPlatformPasteboard):
Add a new API test to verify that clipboard items contain the right data when writing multiple items (each with
different sets of types) to the platform pasteboard using native APIs.
* TestWebKitAPI/Tests/WebKitCocoa/clipboard.html: Added.
* WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm:
(-[LocalPasteboard declareTypes:owner:]):
(-[LocalPasteboard addTypes:owner:]):
(-[LocalPasteboard _addTypesWithoutUpdatingChangeCount:owner:]):
LayoutTests:
Add 3 new layout tests.
* editing/async-clipboard/clipboard-change-data-while-getting-type-expected.txt: Added.
* editing/async-clipboard/clipboard-change-data-while-getting-type.html: Added.
Add a layout test to verify that if the pasteboard changes right after the page has obtained clipboard items,
the page should not be able to fetch the new contents of the pasteboard using these clipboard items.
* editing/async-clipboard/clipboard-get-type-with-old-items.html: Added.
* editing/async-clipboard/clipboard-get-type-with-old-items-expected.txt: Added.
Add a layout test to verify that after attempting to get data from invalid (stale) items, the page is still
capable of reading data from valid clipboard items.
* editing/async-clipboard/clipboard-item-get-type-basic-expected.txt: Added.
* editing/async-clipboard/clipboard-item-get-type-basic.html: Added.
Add a layout test to verify that after writing multiple types to the clipboard using the DataTransfer API, we
should be able to read them back using the async clipboard API, as a single ClipboardItem, and also get data out
of the clipboard item using ClipboardItem.getType.
* editing/async-clipboard/resources/async-clipboard-helpers.js:
* platform/win/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.async.copyText):
(window.UIHelper):
Canonical link: https://commits.webkit.org/216615@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@251377 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-10-21 20:19:53 +00:00
|
|
|
|
|
|
|
static async copyText(text) {
|
Allow clipboard API access when pasting from a menu item or key binding
https://bugs.webkit.org/show_bug.cgi?id=211990
<rdar://problem/63308916>
Reviewed by Megan Gardner.
Source/WebCore:
Allow the contents of the clipboard to be programmatically requested by the page while pasting from trusted UI
(i.e. the paste menu item, or when WebKit API is called by the app to trigger the paste). This allows the
'reading' part of the async clipboard API (`read` and `readText`) to be used when the user pastes in an editable
element, without having to fall back to showing the DOM paste access menu.
Note that this change should not have an effect on the pasteboard security model, since it only grants the page
programmatic access to the contents of the pasteboard in the case where access to the pasteboard has already
been granted by the user. Additionally, even in the event that the web process is compromised, even if the web
process can be tricked into believing it has been granted pasteboard access, the changes in r259151 will prevent
it from being able to request pasteboard data, unless the user (or the application, on behalf of the user) has
explicitly pasted via trusted API calls that are inaccessible from the web process.
Test: editing/async-clipboard/clipboard-read-while-pasting.html
* editing/Editor.cpp:
(WebCore::Editor::paste):
(WebCore::Editor::pasteAsPlainText):
(WebCore::Editor::pasteAsQuotation):
If `FromMenuOrKeyBinding::Yes` is passed in, set the `m_pastingFromMenuOrKeyBinding` flag to true during the
scope of the paste command.
* editing/Editor.h:
(WebCore::Editor::isPastingFromMenuOrKeyBinding const):
* editing/EditorCommand.cpp:
(WebCore::executePaste):
(WebCore::executePasteAndMatchStyle):
(WebCore::executePasteAsPlainText):
(WebCore::executePasteAsQuotation):
Pass in `FromMenuOrKeyBinding::Yes` when triggering the paste from a menu item or key binding.
* page/Frame.cpp:
(WebCore::Frame::requestDOMPasteAccess):
When pasting from menu or key binding, grant the page DOM paste access without requiring the DOM paste access
UI to be shown and confirmed.
Tools:
Add a UIScriptController method to trigger a paste from the application process.
* DumpRenderTree/cocoa/UIScriptControllerCocoa.h:
* DumpRenderTree/cocoa/UIScriptControllerCocoa.mm:
(WTR::UIScriptControllerCocoa::paste):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::paste):
* WebKitTestRunner/cocoa/UIScriptControllerCocoa.h:
* WebKitTestRunner/cocoa/UIScriptControllerCocoa.mm:
(WTR::UIScriptControllerCocoa::paste):
LayoutTests:
Add a new layout test to verify that the contents of the clipboard can be read while performing a paste that was
not triggered from the DOM.
* editing/async-clipboard/clipboard-read-while-pasting-expected.txt: Added.
* editing/async-clipboard/clipboard-read-while-pasting.html: Added.
* platform/win/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.async copyText):
(window.UIHelper.async paste):
Canonical link: https://commits.webkit.org/224916@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261825 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-18 19:05:27 +00:00
|
|
|
const copyTextScript = `uiController.copyText(\`${text.replace(/`/g, "\\`")}\`)`;
|
[Clipboard API] Implement ClipboardItem.getType() for platform clipboard items
https://bugs.webkit.org/show_bug.cgi?id=203168
Reviewed by Tim Horton.
Source/WebCore:
This patch completes support for ClipboardItem.getType().
Tests: editing/async-clipboard/clipboard-change-data-while-getting-type.html
editing/async-clipboard/clipboard-get-type-with-old-items.html
editing/async-clipboard/clipboard-item-get-type-basic.html
ClipboardTests.ReadMultipleItems
* Modules/async-clipboard/Clipboard.cpp:
(WebCore::Clipboard::getType):
Implement getType(). If the given clipboard item is being tracked as one of the active clipboard items, then
allow it to read data from the platform pasteboard. We use existing pasteboard reading methods and classes
(PasteboardPlainText and WebContentMarkupReader) to ask the platform pasteboard for text and markup data,
respectively, and go through readURL() for "text/uri-list".
Before exposing any data to the page, we additionally check that the change count of the pasteboard is still
what we started with when setting up the current session. If this is not the case, we reject the promise and
immediately clear out the session.
(WebCore::Clipboard::activePasteboard):
* Modules/async-clipboard/Clipboard.h:
* dom/DataTransfer.h:
Drive-by tweak: make the WebContentReadingPolicy enum class narrower.
* platform/Pasteboard.h:
Add an enum flag for allowing or ignoring the platform URL type when reading plain text from the platform
pasteboard. We use this in Clipboard::getType() to ignore URLs on the platform pasteboard when plain text, since
the plain text reader would otherwise prefer URLs over plain text by default, and read the URL type instead of
the plain text type.
* platform/StaticPasteboard.h:
* platform/gtk/PasteboardGtk.cpp:
(WebCore::Pasteboard::read):
* platform/ios/PasteboardIOS.mm:
(WebCore::Pasteboard::read):
* platform/libwpe/PasteboardLibWPE.cpp:
(WebCore::Pasteboard::read):
* platform/mac/PasteboardMac.mm:
(WebCore::Pasteboard::read):
* platform/win/PasteboardWin.cpp:
(WebCore::Pasteboard::read):
Tools:
Add support for the new layout tests, as well as a new API test.
* DumpRenderTree/ios/UIScriptControllerIOS.h:
* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::copyText):
Implement UIScriptController.copyText in WebKit1. This is used in one of the new layout tests, which passes in
WebKit1 on macOS and iOS.
* DumpRenderTree/mac/DumpRenderTreePasteboard.mm:
(-[LocalPasteboard declareTypes:owner:]):
(-[LocalPasteboard addTypes:owner:]):
(-[LocalPasteboard _addTypesWithoutUpdatingChangeCount:owner:]):
Adjust logic when declaring types on the platform pasteboard, such that it behaves more like the platform; when
declaring types, even if the owner doesn't change, the change count should still get bumped up by 1.
* DumpRenderTree/mac/UIScriptControllerMac.h:
* DumpRenderTree/mac/UIScriptControllerMac.mm:
(WTR::UIScriptControllerMac::copyText):
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/ClipboardTests.mm: Added.
(-[TestWKWebView readClipboard]):
(createWebViewForClipboardTests):
(writeMultipleObjectsToPlatformPasteboard):
Add a new API test to verify that clipboard items contain the right data when writing multiple items (each with
different sets of types) to the platform pasteboard using native APIs.
* TestWebKitAPI/Tests/WebKitCocoa/clipboard.html: Added.
* WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm:
(-[LocalPasteboard declareTypes:owner:]):
(-[LocalPasteboard addTypes:owner:]):
(-[LocalPasteboard _addTypesWithoutUpdatingChangeCount:owner:]):
LayoutTests:
Add 3 new layout tests.
* editing/async-clipboard/clipboard-change-data-while-getting-type-expected.txt: Added.
* editing/async-clipboard/clipboard-change-data-while-getting-type.html: Added.
Add a layout test to verify that if the pasteboard changes right after the page has obtained clipboard items,
the page should not be able to fetch the new contents of the pasteboard using these clipboard items.
* editing/async-clipboard/clipboard-get-type-with-old-items.html: Added.
* editing/async-clipboard/clipboard-get-type-with-old-items-expected.txt: Added.
Add a layout test to verify that after attempting to get data from invalid (stale) items, the page is still
capable of reading data from valid clipboard items.
* editing/async-clipboard/clipboard-item-get-type-basic-expected.txt: Added.
* editing/async-clipboard/clipboard-item-get-type-basic.html: Added.
Add a layout test to verify that after writing multiple types to the clipboard using the DataTransfer API, we
should be able to read them back using the async clipboard API, as a single ClipboardItem, and also get data out
of the clipboard item using ClipboardItem.getType.
* editing/async-clipboard/resources/async-clipboard-helpers.js:
* platform/win/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.async.copyText):
(window.UIHelper):
Canonical link: https://commits.webkit.org/216615@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@251377 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-10-21 20:19:53 +00:00
|
|
|
return new Promise(resolve => testRunner.runUIScript(copyTextScript, resolve));
|
|
|
|
}
|
2019-11-13 00:07:00 +00:00
|
|
|
|
Allow clipboard API access when pasting from a menu item or key binding
https://bugs.webkit.org/show_bug.cgi?id=211990
<rdar://problem/63308916>
Reviewed by Megan Gardner.
Source/WebCore:
Allow the contents of the clipboard to be programmatically requested by the page while pasting from trusted UI
(i.e. the paste menu item, or when WebKit API is called by the app to trigger the paste). This allows the
'reading' part of the async clipboard API (`read` and `readText`) to be used when the user pastes in an editable
element, without having to fall back to showing the DOM paste access menu.
Note that this change should not have an effect on the pasteboard security model, since it only grants the page
programmatic access to the contents of the pasteboard in the case where access to the pasteboard has already
been granted by the user. Additionally, even in the event that the web process is compromised, even if the web
process can be tricked into believing it has been granted pasteboard access, the changes in r259151 will prevent
it from being able to request pasteboard data, unless the user (or the application, on behalf of the user) has
explicitly pasted via trusted API calls that are inaccessible from the web process.
Test: editing/async-clipboard/clipboard-read-while-pasting.html
* editing/Editor.cpp:
(WebCore::Editor::paste):
(WebCore::Editor::pasteAsPlainText):
(WebCore::Editor::pasteAsQuotation):
If `FromMenuOrKeyBinding::Yes` is passed in, set the `m_pastingFromMenuOrKeyBinding` flag to true during the
scope of the paste command.
* editing/Editor.h:
(WebCore::Editor::isPastingFromMenuOrKeyBinding const):
* editing/EditorCommand.cpp:
(WebCore::executePaste):
(WebCore::executePasteAndMatchStyle):
(WebCore::executePasteAsPlainText):
(WebCore::executePasteAsQuotation):
Pass in `FromMenuOrKeyBinding::Yes` when triggering the paste from a menu item or key binding.
* page/Frame.cpp:
(WebCore::Frame::requestDOMPasteAccess):
When pasting from menu or key binding, grant the page DOM paste access without requiring the DOM paste access
UI to be shown and confirmed.
Tools:
Add a UIScriptController method to trigger a paste from the application process.
* DumpRenderTree/cocoa/UIScriptControllerCocoa.h:
* DumpRenderTree/cocoa/UIScriptControllerCocoa.mm:
(WTR::UIScriptControllerCocoa::paste):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::paste):
* WebKitTestRunner/cocoa/UIScriptControllerCocoa.h:
* WebKitTestRunner/cocoa/UIScriptControllerCocoa.mm:
(WTR::UIScriptControllerCocoa::paste):
LayoutTests:
Add a new layout test to verify that the contents of the clipboard can be read while performing a paste that was
not triggered from the DOM.
* editing/async-clipboard/clipboard-read-while-pasting-expected.txt: Added.
* editing/async-clipboard/clipboard-read-while-pasting.html: Added.
* platform/win/TestExpectations:
* resources/ui-helper.js:
(window.UIHelper.async copyText):
(window.UIHelper.async paste):
Canonical link: https://commits.webkit.org/224916@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261825 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-18 19:05:27 +00:00
|
|
|
static async paste() {
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(`uiController.paste()`, resolve));
|
|
|
|
}
|
|
|
|
|
2019-11-13 00:07:00 +00:00
|
|
|
static async setContinuousSpellCheckingEnabled(enabled) {
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`uiController.setContinuousSpellCheckingEnabled(${enabled})`, resolve);
|
|
|
|
});
|
|
|
|
}
|
2019-11-15 19:56:09 +00:00
|
|
|
|
|
|
|
static async longPressElement(element)
|
|
|
|
{
|
|
|
|
return this.longPressAtPoint(element.offsetLeft + element.offsetWidth / 2, element.offsetTop + element.offsetHeight / 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static async longPressAtPoint(x, y)
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
uiController.longPressAtPoint(${x}, ${y}, function() {
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
});
|
|
|
|
})();`, resolve);
|
|
|
|
});
|
|
|
|
}
|
2020-04-07 21:00:49 +00:00
|
|
|
|
2020-08-07 23:05:36 +00:00
|
|
|
static async setSpellCheckerResults(results)
|
|
|
|
{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`(() => {
|
|
|
|
uiController.setSpellCheckerResults(${JSON.stringify(results)});
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-04-07 21:00:49 +00:00
|
|
|
static async activateElementAfterInstallingTapGestureOnWindow(element)
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
|
|
|
return activateElement(element);
|
|
|
|
|
|
|
|
const x = element.offsetLeft + element.offsetWidth / 2;
|
|
|
|
const y = element.offsetTop + element.offsetHeight / 2;
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
let progress = 0;
|
|
|
|
function incrementProgress() {
|
|
|
|
if (++progress == 2)
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
}
|
|
|
|
uiController.installTapGestureOnWindow(incrementProgress);
|
|
|
|
uiController.singleTapAtPoint(${x}, ${y}, incrementProgress);
|
|
|
|
})();`, resolve);
|
|
|
|
});
|
|
|
|
}
|
2020-04-08 22:41:44 +00:00
|
|
|
|
|
|
|
static mayContainEditableElementsInRect(x, y, width, height)
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2() || !this.isIOSFamily())
|
|
|
|
return Promise.resolve(false);
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
uiController.doAfterPresentationUpdate(function() {
|
|
|
|
uiController.uiScriptComplete(uiController.mayContainEditableElementsInRect(${x}, ${y}, ${width}, ${height}));
|
|
|
|
})
|
|
|
|
})();`, result => resolve(result === "true"));
|
|
|
|
});
|
|
|
|
}
|
2020-10-27 18:51:38 +00:00
|
|
|
|
|
|
|
static moveToNextByKeyboardAccessoryBar()
|
|
|
|
{
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
uiController.keyboardAccessoryBarNext();
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static moveToPrevByKeyboardAccessoryBar()
|
|
|
|
{
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
uiController.keyboardAccessoryBarPrevious();
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
`, resolve);
|
|
|
|
});
|
|
|
|
}
|
2020-11-04 22:36:46 +00:00
|
|
|
|
|
|
|
static waitForContactPickerToShow()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
if (!uiController.isShowingContactPicker)
|
|
|
|
uiController.didShowContactPickerCallback = () => uiController.uiScriptComplete();
|
|
|
|
else
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static waitForContactPickerToHide()
|
|
|
|
{
|
|
|
|
if (!this.isWebKit2())
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
testRunner.runUIScript(`
|
|
|
|
(function() {
|
|
|
|
if (uiController.isShowingContactPicker)
|
|
|
|
uiController.didHideContactPickerCallback = () => uiController.uiScriptComplete();
|
|
|
|
else
|
|
|
|
uiController.uiScriptComplete();
|
|
|
|
})()`, resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static dismissContactPickerWithContacts(contacts)
|
|
|
|
{
|
|
|
|
const script = `(() => uiController.dismissContactPickerWithContacts(${JSON.stringify(contacts)}))()`;
|
|
|
|
return new Promise(resolve => testRunner.runUIScript(script, resolve));
|
|
|
|
}
|
[iOS] Unified field is unselected after focusing URL bar if text was selected in a fixed position container
https://bugs.webkit.org/show_bug.cgi?id=228269
rdar://80556392
Reviewed by Tim Horton.
Source/WebKit:
In Safari on iOS 15, if the selection (either ranged or caret) is inside a fixed position container when the
user taps on the unified field, we'll immediately clear the text selection inside the unified field upon
bringing up the keyboard. This happens because the tab pill in iOS 15 is lowered as the URL bar is focused,
which causes the web view to scroll slightly. This, in turn, induces a brief unstable scrolling tree state,
which then causes us to temporarily hide and show selection views while scrolling in unstable state (see
r209931) by calling `-deactivateSelection` and then `-activateSelection` on the text interaction assistant.
Calling `-[UIWKTextInteractionAssistant activateSelection]` then causes UIKit to dispatch a
UITextSelectionViewActivatedNotification; In the unified field, which is a UITextField subclass, UIKit code then
listens for this notification and responds to it by clearing the selection if the newly activated selection's
host view (WKContentView) is different than itself, thereby causing the bug.
To fix this, we simply make two (minor) adjustments to the logic for temporarily hiding and showing the
selection while performing an unstable scroll. See below for more details.
Test: editing/selection/ios/scrolling-with-fixed-selection-does-not-unselect-native-text-field.html
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView shouldHideSelectionWhenScrolling]):
Only hide and (later) restore the selection in non-editable text if the selection is ranged. This is because
caret selections in non-editable content are not user-visible anyways, so there's no need to temporarily
suppress the selection.
(-[WKContentView _updateChangedSelection:]):
Only attempt to show the selection views again if doing so doesn't cause us to steal first responder status away
from the existing first responder; otherwise, we'll wait until we `-becomeFirstResponder` to `-activateSelection`.
(-[WKContentView selectionInteractionAssistant]): Deleted.
Tools:
We already have some very basic support for installing and removing native text fields in the view hierarchy,
through `TestRunner::(add|remove)ChromeInputField()`. In order to support the new layout test, we additionally
implement the ability to:
- Set text inside the native chrome input field that was installed using `addChromeInputField()`.
- Select all text inside the chrome input field.
- Query the chrome input field for the currently selected text.
We only support iOS for the time being, with stubs on other platforms, since the new test that uses this
functionality is iOS-specific; if needed in the future for a similar test on other platforms, we can implement
the stubbed testing hooks on TestRunner and PlatformWebView as well.
* DumpRenderTree/TestRunner.h:
* DumpRenderTree/mac/TestRunnerMac.mm:
(TestRunner::setTextInChromeInputField):
(TestRunner::selectChromeInputField):
(TestRunner::getSelectedTextInChromeInputField):
* DumpRenderTree/win/TestRunnerWin.cpp:
(TestRunner::setTextInChromeInputField):
(TestRunner::selectChromeInputField):
(TestRunner::getSelectedTextInChromeInputField):
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::didReceiveMessageToPage):
(WTR::InjectedBundle::postSetTextInChromeInputField):
(WTR::InjectedBundle::postSelectChromeInputField):
(WTR::InjectedBundle::postGetSelectedTextInChromeInputField):
* WebKitTestRunner/InjectedBundle/InjectedBundle.h:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setTextInChromeInputField):
(WTR::TestRunner::selectChromeInputField):
(WTR::TestRunner::getSelectedTextInChromeInputField):
(WTR::TestRunner::callSetTextInChromeInputFieldCallback):
(WTR::TestRunner::callSelectChromeInputFieldCallback):
(WTR::TestRunner::callGetSelectedTextInChromeInputFieldCallback):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/PlatformWebView.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
* WebKitTestRunner/gtk/PlatformWebViewGtk.cpp:
(WTR::PlatformWebView::setTextInChromeInputField):
(WTR::PlatformWebView::selectChromeInputField):
(WTR::PlatformWebView::getSelectedTextInChromeInputField):
* WebKitTestRunner/ios/PlatformWebViewIOS.mm:
(WTR::chromeInputField):
Additionally do some light refactoring by pulling out logic for grabbing the chrome input field (i.e. a view
with a tag of 1 under the window) out into a separate helper method. Use this helper in a few places below.
(WTR::PlatformWebView::addChromeInputField):
(WTR::PlatformWebView::setTextInChromeInputField):
(WTR::PlatformWebView::selectChromeInputField):
(WTR::PlatformWebView::getSelectedTextInChromeInputField):
(WTR::PlatformWebView::removeChromeInputField):
* WebKitTestRunner/mac/PlatformWebViewMac.mm:
(WTR::PlatformWebView::setTextInChromeInputField):
(WTR::PlatformWebView::selectChromeInputField):
(WTR::PlatformWebView::getSelectedTextInChromeInputField):
* WebKitTestRunner/win/PlatformWebViewWin.cpp:
(WTR::PlatformWebView::setTextInChromeInputField):
(WTR::PlatformWebView::selectChromeInputField):
(WTR::PlatformWebView::getSelectedTextInChromeInputField):
* WebKitTestRunner/wpe/PlatformWebViewWPE.cpp:
(WTR::PlatformWebView::setTextInChromeInputField):
(WTR::PlatformWebView::selectChromeInputField):
(WTR::PlatformWebView::getSelectedTextInChromeInputField):
LayoutTests:
Add a new layout test that installs, focuses, and selects text inside a native UITextField (simulating Safari's
URL field) while the DOM selection is inside a fixed position container, and then scrolls the web view a bit to
temporarily induce an unstable scrolling tree state. After this, we verify that the text selection inside the
native text field has not been cleared.
See Tools/ changes for more details.
* editing/selection/ios/scrolling-with-fixed-selection-does-not-unselect-native-text-field-expected.txt: Added.
* editing/selection/ios/scrolling-with-fixed-selection-does-not-unselect-native-text-field.html: Added.
* resources/ui-helper.js:
(window.UIHelper.addChromeInputField):
(window.UIHelper.removeChromeInputField):
(window.UIHelper.setTextInChromeInputField):
(window.UIHelper.selectChromeInputField):
(window.UIHelper.getSelectedTextInChromeInputField):
(window.UIHelper):
Canonical link: https://commits.webkit.org/239946@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@280288 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-07-25 19:40:36 +00:00
|
|
|
|
|
|
|
static addChromeInputField()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => testRunner.addChromeInputField(resolve));
|
|
|
|
}
|
|
|
|
|
|
|
|
static removeChromeInputField()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => testRunner.removeChromeInputField(resolve));
|
|
|
|
}
|
|
|
|
|
|
|
|
static setTextInChromeInputField(text)
|
|
|
|
{
|
|
|
|
return new Promise(resolve => testRunner.setTextInChromeInputField(text, resolve));
|
|
|
|
}
|
|
|
|
|
|
|
|
static selectChromeInputField()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => testRunner.selectChromeInputField(resolve));
|
|
|
|
}
|
|
|
|
|
|
|
|
static getSelectedTextInChromeInputField()
|
|
|
|
{
|
|
|
|
return new Promise(resolve => testRunner.getSelectedTextInChromeInputField(resolve));
|
|
|
|
}
|
2016-12-13 23:22:03 +00:00
|
|
|
}
|
[iOS] WKWebView touch event gesture recognition should not block the application process main thread when possible
https://bugs.webkit.org/show_bug.cgi?id=204664
<rdar://problem/38670692>
Reviewed by Tim Horton.
Source/WebKit:
Adds a mechanism that allows some sync touch events on iOS to be sent asynchronously. To do this, we use the
deferring gesture mechanism introduced in trac.webkit.org/r253005 to defer all gestures under WKContentView (and
WebKit-owned scroll views) when a touch starts, such that they will not recognize until we know that the page
has either prevented default or not (assuming that the touch was over an active listener). See below for more
details.
Tests: fast/events/touch/ios/prevent-default-on-touch-start-with-slow-event-listener.html
fast/events/touch/ios/scroll-on-touch-start-with-slow-event-listener.html
* UIProcess/GenericCallback.h:
* UIProcess/PageClient.h:
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm:
(-[WKChildScrollView gestureRecognizer:shouldRequireFailureOfGestureRecognizer:]):
(-[WKChildScrollView gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]):
Implement gesture recognizer delegate hooks to add dynamic failure requirements between a child scroll view's
gestures and the new deferring gesture recognizers on WKContentView. This allows pan gestures over a scrollable
container to hold off on recognizing while the deferring gesture recognizer has not failed yet.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::handlePreventableTouchEvent):
(WebKit::WebPageProxy::handleUnpreventableTouchEvent):
Rename handleTouchEventSynchronously and handleTouchEventAsynchronously to handlePreventableTouchEvent and
handleUnpreventableTouchEvent, respectively. Instead of always sending touchstart events that may prevent native
gestures synchronously, we may now go through the same `EventDispatcher::TouchEvent` codepath used when
dispatching touch events in passive tracking regions. However, in the case of preventable touchstarts, we
additionally store a completion callback that is invoked after the touch event has been handled by the page; we
then either un-defer or prevent native gestures here (depending on whether the page prevented default) by
calling PageClient::doneDeferringNativeGestures.
Non-touchstart events are still dispatched synchronously, to ensure that calling preventDefault() on touchmove
and touchend continue to prevent default gestures from recognizing.
(WebKit::WebPageProxy::boolCallback):
(WebKit::WebPageProxy::handleTouchEventSynchronously): Deleted.
(WebKit::WebPageProxy::handleTouchEventAsynchronously): Deleted.
See above.
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::isHandlingPreventableTouchStart const):
This is used in WKContentView to determine whether deferring gestures need to remain active after the touch
ends. See below for more detail.
* UIProcess/WebPageProxy.messages.in:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::doneDeferringNativeGestures):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[UIGestureRecognizer _wk_cancel]):
(-[WKContentView setupInteraction]):
(-[WKContentView cleanupInteraction]):
(-[WKContentView _removeDefaultGestureRecognizers]):
(-[WKContentView _addDefaultGestureRecognizers]):
Add and remove the new deferring gesture recognizers here.
(-[WKContentView _webTouchEventsRecognized:]):
(-[WKContentView _webTouchEvent:preventsNativeGestures:]):
(-[WKContentView _doneDeferringNativeGestures:]):
(-[WKContentView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
(-[WKContentView ensurePositionInformationIsUpToDate:]):
Drive-by fix: add a missing hasRunningProcess check that causes a flaky assertion under
`AuxiliaryProcessProxy::connection()` in layout tests.
(-[WKContentView gestureRecognizer:shouldRequireFailureOfGestureRecognizer:]):
(-[WKContentView gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]):
Add dynamic failure requirements between WKContentView's gestures (including all text interaction, context menu,
and drag and drop gestures) and the new deferring gesture recognizers.
(-[WKContentView _didStartProvisionalLoadForMainFrame]):
Force the two-finger double tap gesture recognizer to reset when loading a new page. Without this, the layout
test fast/events/ios/click-event-while-editing-node.html will rarely fail when run after a test that dispatches
a two-finger tap, such as fast/events/ios/click-event-two-finger-single-tap-meta-key.html. This is because the
new deferring gestures will temporarily unite multi-finger tap gestures with one-finger double tap gestures in
the same subgraph when performing a tap gesture with more than one finger. This means that there's a 300 ms
delay before a normal single tap can be recognized again, which (without forcing the two-finger double tap to
reset) would cause a subsequent test that loads in under 300 ms and attempts to send a tap to fail.
(-[WKContentView deferringGestureRecognizer:shouldDeferGesturesAfterBeginningTouchesWithEvent:]):
Avoid deferring native gestures if the scroll view is decelerating; this matches behavior of the web touch event
gesture recognizer.
(-[WKContentView deferringGestureRecognizer:shouldDeferGesturesAfterEndingTouchesWithEvent:]):
Normally, after -touchesEnded:withEvent:, we stop deferring native gesture recognizers by failing the deferring
gestures. However, if we're still waiting for a response from the web process, then let
-_doneDeferringNativeGestures: handle this instead.
(-[WKContentView deferringGestureRecognizer:shouldDeferOtherGestureRecognizer:]):
(-[WKContentView deferringGestureRecognizer:shouldDeferGesturesWithEvent:]): Deleted.
Renamed to -shouldDeferGesturesAfterBeginningTouchesWithEvent:.
* UIProcess/ios/WKDeferringGestureRecognizer.h:
* UIProcess/ios/WKDeferringGestureRecognizer.mm:
(-[WKDeferringGestureRecognizer touchesBegan:withEvent:]):
(-[WKDeferringGestureRecognizer touchesEnded:withEvent:]):
Override this and add a new delegate hook to determine whether we want the deferring gesture recognizer to
immediately fail when touches end. It's important to override this and transition to failure state in this case,
since not doing so could mean that the deferring gestures stay in Possible state forever; this may lead to the
gesture subgraph containing these deferring gestures being unable to reset, since it's waiting for the deferring
gesture to either fail or end.
* UIProcess/ios/WKScrollView.mm:
(-[WKScrollView gestureRecognizer:shouldRequireFailureOfGestureRecognizer:]):
(-[WKScrollView gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]):
Defer more scroll view gestures.
* WebProcess/WebPage/EventDispatcher.cpp:
(WebKit::EventDispatcher::touchEvent):
Add an optional CallbackID parameter to this IPC message. If a callback ID is given, then we avoid coalescing
the touch event. To implement this, we additionally refactor the queued touch events map to contain lists of
<WebTouchEvent, Optional<CallbackID>> pairs; if a queued touch event has a corresponding CallbackID, then we
fire the callback corresponding to the ID, indicating whether the touch event was handled by the page.
* WebProcess/WebPage/EventDispatcher.h:
* WebProcess/WebPage/EventDispatcher.messages.in:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::dispatchAsynchronousTouchEvents):
LayoutTests:
* fast/events/touch/ios/prevent-default-on-touch-start-with-slow-event-listener-expected.txt: Added.
* fast/events/touch/ios/prevent-default-on-touch-start-with-slow-event-listener.html: Added.
* fast/events/touch/ios/scroll-on-touch-start-with-slow-event-listener-expected.txt: Added.
* fast/events/touch/ios/scroll-on-touch-start-with-slow-event-listener.html: Added.
Add new layout tests to cover behaviors when panning over active touchstart handlers that spin for an extended
length of time (in this case, 400 milliseconds) in overflow scrolling containers. A touchstart handler that
prevents default should still block scrolling, and a touchstart handler that does not should still allow the
user to scroll.
* fast/events/touch/ios/show-modal-alert-during-touch-start.html:
* http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt:
* http/tests/security/anchor-download-block-crossorigin-expected.txt:
Rebaseline these tests by changing some line numbers.
* resources/ui-helper.js:
(window.UIHelper.sendEventStream.return.new.Promise):
(window.UIHelper.sendEventStream):
Add a new UIHelper method to send a JSON object as an event stream.
(UIHelper.EventStreamBuilder.prototype._reset):
(UIHelper.EventStreamBuilder.prototype.begin):
(UIHelper.EventStreamBuilder.prototype.move):
(UIHelper.EventStreamBuilder.prototype.end):
(UIHelper.EventStreamBuilder.prototype.takeResult):
Add a new helper class to make it easier to construct event streams, for the purposes of sending to
UIScriptController::sendEventStream.
Canonical link: https://commits.webkit.org/218214@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@253267 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-12-08 03:57:23 +00:00
|
|
|
|
|
|
|
UIHelper.EventStreamBuilder = class {
|
|
|
|
constructor()
|
|
|
|
{
|
|
|
|
// FIXME: This could support additional customization options, such as interpolation, timestep, and different
|
|
|
|
// digitizer indices in the future. For now, just make it simpler to string together sequences of pan gestures.
|
|
|
|
this._reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
_reset() {
|
|
|
|
this.events = [];
|
|
|
|
this.currentTimeOffset = 0;
|
|
|
|
this.currentX = 0;
|
|
|
|
this.currentY = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
begin(x, y) {
|
|
|
|
console.assert(this.currentTimeOffset === 0);
|
|
|
|
this.events.push({
|
|
|
|
interpolate : "linear",
|
|
|
|
timestep : 0.016,
|
|
|
|
coordinateSpace : "content",
|
|
|
|
startEvent : {
|
|
|
|
inputType : "hand",
|
|
|
|
timeOffset : this.currentTimeOffset,
|
|
|
|
touches : [{ inputType : "finger", phase : "began", id : 1, x : x, y : y, pressure : 0 }]
|
|
|
|
},
|
|
|
|
endEvent : {
|
|
|
|
inputType : "hand",
|
|
|
|
timeOffset : this.currentTimeOffset,
|
|
|
|
touches : [{ inputType : "finger", phase : "began", id : 1, x : x, y : y, pressure : 0 }]
|
|
|
|
}
|
|
|
|
});
|
|
|
|
this.currentX = x;
|
|
|
|
this.currentY = y;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
REGRESSION (r271660): Unable to interact with page after long-pressing image on images.google.com
https://bugs.webkit.org/show_bug.cgi?id=221584
<rdar://problem/74073581>
Reviewed by Andy Estes.
Source/WebKit:
After long pressing on an image with an active touchend event listener, it's possible to sometimes get stuck in
a state where further interaction with the page is impossible, due to all gesture recognizers (except for the
touchend deferral gestures) remaining in either Failed or Ended state.
When presenting the context menu with a long press, the touch event gesture transitions to Failed state due to
the active touch being cancelled. Normally, this invokes `-_webTouchEventsRecognized:` with all touch points
being released, which allows us to "lift" the deferred gesture gate by failing any deferring gesture recognizers
that are still in Possible state (i.e. deferring native gestures).
However, it's possible for touch deferring gestures (in particular, the touchend deferrer) introduced in r271660
to end (i.e. call `-touchesEnded:withEvent:`) before the touch event gesture gets a chance to call
`-_webTouchEventsRecognized:`. In this scenario, the touch end deferral gesture remains in Possible state, and
prevents the touch event gesture from subsequently firing its action (`-_webTouchEventsRecognized:`), presumably
because UIKit is waiting for all other gestures in the same subgraph as the touch event gesture recognizer to
Fail.
This effectively results in a gesture "deadlock", since the web touch event gesture recognizer won't call
`-_webTouchEventsRecognized:` until the touch end deferring gesture has failed, and the touch end deferring
gesture won't fail until `-_webTouchEventsRecognized:` is called. To fix this, we restore a bit of logic that
was removed with r271193, such that we allow our deferring gesture recognizers to transition to Failed state
underneath `-touchesEnded:withEvent:`, as long it's [1] not actively deferring any native gestures, and [2] the
web touch event gesture has already failed, so we aren't expecting a subsequent call to
`-_webTouchEventsRecognized:` until the deferring gesture has failed.
Note that this check for the touch event gesture recognizer's state (condition [2] above) is necessary to
prevent the touchend deferring gesture from failing prematurely (i.e. right before we're about to dispatch
preventable `touchend` events).
Test: fast/events/touch/ios/tap-after-long-press-on-image.html
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _isTouchStartDeferringGesture:]):
(-[WKContentView _isTouchEndDeferringGesture:]):
(-[WKContentView deferringGestureRecognizer:didEndTouchesWithEvent:]):
Add a delegate hook when a deferring gesture's ends touches; use this hook in `WKContentView` to "lift" the
gesture gate if needed, in the case where the touch event gesture recognizer has already failed and we can't
expect `-_webTouchEventsRecognized:` to be called with all touch points released.
(-[WKContentView contextMenuInteraction:willEndForConfiguration:animator:]):
Add a missing call to `-[WKWebView _didDismissContextMenu]` here to make `UIHelper.waitForContextMenuToHide()`
actually work with image and link context menus in WebKitTestRunner.
* UIProcess/ios/WKDeferringGestureRecognizer.h:
* UIProcess/ios/WKDeferringGestureRecognizer.mm:
(-[WKDeferringGestureRecognizer touchesEnded:withEvent:]):
LayoutTests:
Add a new layout test that (sometimes) exercises the problem. Given the nature of the bug, it doesn't seem
possible to write a test that reproduces the bug 100% of the time. See WebKit ChangeLog for more details.
* fast/events/touch/ios/tap-after-long-press-on-image-expected.txt: Added.
* fast/events/touch/ios/tap-after-long-press-on-image.html: Added.
* resources/ui-helper.js:
(UIHelper.EventStreamBuilder.prototype.wait):
Add a helper to simply increment the time offset when building an event stream.
Canonical link: https://commits.webkit.org/233856@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@272584 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-02-09 17:57:55 +00:00
|
|
|
wait(duration) {
|
|
|
|
this.currentTimeOffset += duration;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
[iOS] WKWebView touch event gesture recognition should not block the application process main thread when possible
https://bugs.webkit.org/show_bug.cgi?id=204664
<rdar://problem/38670692>
Reviewed by Tim Horton.
Source/WebKit:
Adds a mechanism that allows some sync touch events on iOS to be sent asynchronously. To do this, we use the
deferring gesture mechanism introduced in trac.webkit.org/r253005 to defer all gestures under WKContentView (and
WebKit-owned scroll views) when a touch starts, such that they will not recognize until we know that the page
has either prevented default or not (assuming that the touch was over an active listener). See below for more
details.
Tests: fast/events/touch/ios/prevent-default-on-touch-start-with-slow-event-listener.html
fast/events/touch/ios/scroll-on-touch-start-with-slow-event-listener.html
* UIProcess/GenericCallback.h:
* UIProcess/PageClient.h:
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm:
(-[WKChildScrollView gestureRecognizer:shouldRequireFailureOfGestureRecognizer:]):
(-[WKChildScrollView gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]):
Implement gesture recognizer delegate hooks to add dynamic failure requirements between a child scroll view's
gestures and the new deferring gesture recognizers on WKContentView. This allows pan gestures over a scrollable
container to hold off on recognizing while the deferring gesture recognizer has not failed yet.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::handlePreventableTouchEvent):
(WebKit::WebPageProxy::handleUnpreventableTouchEvent):
Rename handleTouchEventSynchronously and handleTouchEventAsynchronously to handlePreventableTouchEvent and
handleUnpreventableTouchEvent, respectively. Instead of always sending touchstart events that may prevent native
gestures synchronously, we may now go through the same `EventDispatcher::TouchEvent` codepath used when
dispatching touch events in passive tracking regions. However, in the case of preventable touchstarts, we
additionally store a completion callback that is invoked after the touch event has been handled by the page; we
then either un-defer or prevent native gestures here (depending on whether the page prevented default) by
calling PageClient::doneDeferringNativeGestures.
Non-touchstart events are still dispatched synchronously, to ensure that calling preventDefault() on touchmove
and touchend continue to prevent default gestures from recognizing.
(WebKit::WebPageProxy::boolCallback):
(WebKit::WebPageProxy::handleTouchEventSynchronously): Deleted.
(WebKit::WebPageProxy::handleTouchEventAsynchronously): Deleted.
See above.
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::isHandlingPreventableTouchStart const):
This is used in WKContentView to determine whether deferring gestures need to remain active after the touch
ends. See below for more detail.
* UIProcess/WebPageProxy.messages.in:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::doneDeferringNativeGestures):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[UIGestureRecognizer _wk_cancel]):
(-[WKContentView setupInteraction]):
(-[WKContentView cleanupInteraction]):
(-[WKContentView _removeDefaultGestureRecognizers]):
(-[WKContentView _addDefaultGestureRecognizers]):
Add and remove the new deferring gesture recognizers here.
(-[WKContentView _webTouchEventsRecognized:]):
(-[WKContentView _webTouchEvent:preventsNativeGestures:]):
(-[WKContentView _doneDeferringNativeGestures:]):
(-[WKContentView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
(-[WKContentView ensurePositionInformationIsUpToDate:]):
Drive-by fix: add a missing hasRunningProcess check that causes a flaky assertion under
`AuxiliaryProcessProxy::connection()` in layout tests.
(-[WKContentView gestureRecognizer:shouldRequireFailureOfGestureRecognizer:]):
(-[WKContentView gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]):
Add dynamic failure requirements between WKContentView's gestures (including all text interaction, context menu,
and drag and drop gestures) and the new deferring gesture recognizers.
(-[WKContentView _didStartProvisionalLoadForMainFrame]):
Force the two-finger double tap gesture recognizer to reset when loading a new page. Without this, the layout
test fast/events/ios/click-event-while-editing-node.html will rarely fail when run after a test that dispatches
a two-finger tap, such as fast/events/ios/click-event-two-finger-single-tap-meta-key.html. This is because the
new deferring gestures will temporarily unite multi-finger tap gestures with one-finger double tap gestures in
the same subgraph when performing a tap gesture with more than one finger. This means that there's a 300 ms
delay before a normal single tap can be recognized again, which (without forcing the two-finger double tap to
reset) would cause a subsequent test that loads in under 300 ms and attempts to send a tap to fail.
(-[WKContentView deferringGestureRecognizer:shouldDeferGesturesAfterBeginningTouchesWithEvent:]):
Avoid deferring native gestures if the scroll view is decelerating; this matches behavior of the web touch event
gesture recognizer.
(-[WKContentView deferringGestureRecognizer:shouldDeferGesturesAfterEndingTouchesWithEvent:]):
Normally, after -touchesEnded:withEvent:, we stop deferring native gesture recognizers by failing the deferring
gestures. However, if we're still waiting for a response from the web process, then let
-_doneDeferringNativeGestures: handle this instead.
(-[WKContentView deferringGestureRecognizer:shouldDeferOtherGestureRecognizer:]):
(-[WKContentView deferringGestureRecognizer:shouldDeferGesturesWithEvent:]): Deleted.
Renamed to -shouldDeferGesturesAfterBeginningTouchesWithEvent:.
* UIProcess/ios/WKDeferringGestureRecognizer.h:
* UIProcess/ios/WKDeferringGestureRecognizer.mm:
(-[WKDeferringGestureRecognizer touchesBegan:withEvent:]):
(-[WKDeferringGestureRecognizer touchesEnded:withEvent:]):
Override this and add a new delegate hook to determine whether we want the deferring gesture recognizer to
immediately fail when touches end. It's important to override this and transition to failure state in this case,
since not doing so could mean that the deferring gestures stay in Possible state forever; this may lead to the
gesture subgraph containing these deferring gestures being unable to reset, since it's waiting for the deferring
gesture to either fail or end.
* UIProcess/ios/WKScrollView.mm:
(-[WKScrollView gestureRecognizer:shouldRequireFailureOfGestureRecognizer:]):
(-[WKScrollView gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]):
Defer more scroll view gestures.
* WebProcess/WebPage/EventDispatcher.cpp:
(WebKit::EventDispatcher::touchEvent):
Add an optional CallbackID parameter to this IPC message. If a callback ID is given, then we avoid coalescing
the touch event. To implement this, we additionally refactor the queued touch events map to contain lists of
<WebTouchEvent, Optional<CallbackID>> pairs; if a queued touch event has a corresponding CallbackID, then we
fire the callback corresponding to the ID, indicating whether the touch event was handled by the page.
* WebProcess/WebPage/EventDispatcher.h:
* WebProcess/WebPage/EventDispatcher.messages.in:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::dispatchAsynchronousTouchEvents):
LayoutTests:
* fast/events/touch/ios/prevent-default-on-touch-start-with-slow-event-listener-expected.txt: Added.
* fast/events/touch/ios/prevent-default-on-touch-start-with-slow-event-listener.html: Added.
* fast/events/touch/ios/scroll-on-touch-start-with-slow-event-listener-expected.txt: Added.
* fast/events/touch/ios/scroll-on-touch-start-with-slow-event-listener.html: Added.
Add new layout tests to cover behaviors when panning over active touchstart handlers that spin for an extended
length of time (in this case, 400 milliseconds) in overflow scrolling containers. A touchstart handler that
prevents default should still block scrolling, and a touchstart handler that does not should still allow the
user to scroll.
* fast/events/touch/ios/show-modal-alert-during-touch-start.html:
* http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt:
* http/tests/security/anchor-download-block-crossorigin-expected.txt:
Rebaseline these tests by changing some line numbers.
* resources/ui-helper.js:
(window.UIHelper.sendEventStream.return.new.Promise):
(window.UIHelper.sendEventStream):
Add a new UIHelper method to send a JSON object as an event stream.
(UIHelper.EventStreamBuilder.prototype._reset):
(UIHelper.EventStreamBuilder.prototype.begin):
(UIHelper.EventStreamBuilder.prototype.move):
(UIHelper.EventStreamBuilder.prototype.end):
(UIHelper.EventStreamBuilder.prototype.takeResult):
Add a new helper class to make it easier to construct event streams, for the purposes of sending to
UIScriptController::sendEventStream.
Canonical link: https://commits.webkit.org/218214@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@253267 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-12-08 03:57:23 +00:00
|
|
|
move(x, y, duration = 0) {
|
|
|
|
const previousTimeOffset = this.currentTimeOffset;
|
|
|
|
this.currentTimeOffset += duration;
|
|
|
|
this.events.push({
|
|
|
|
interpolate : "linear",
|
|
|
|
timestep : 0.016,
|
|
|
|
coordinateSpace : "content",
|
|
|
|
startEvent : {
|
|
|
|
inputType : "hand",
|
|
|
|
timeOffset : previousTimeOffset,
|
|
|
|
touches : [{ inputType : "finger", phase : "moved", id : 1, x : this.currentX, y : this.currentY, pressure : 0 }]
|
|
|
|
},
|
|
|
|
endEvent : {
|
|
|
|
inputType : "hand",
|
|
|
|
timeOffset : this.currentTimeOffset,
|
|
|
|
touches : [{ inputType : "finger", phase : "moved", id : 1, x : x, y : y, pressure : 0 }]
|
|
|
|
}
|
|
|
|
});
|
|
|
|
this.currentX = x;
|
|
|
|
this.currentY = y;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
end() {
|
|
|
|
this.events.push({
|
|
|
|
interpolate : "linear",
|
|
|
|
timestep : 0.016,
|
|
|
|
coordinateSpace : "content",
|
|
|
|
startEvent : {
|
|
|
|
inputType : "hand",
|
|
|
|
timeOffset : this.currentTimeOffset,
|
|
|
|
touches : [{ inputType : "finger", phase : "ended", id : 1, x : this.currentX, y : this.currentY, pressure : 0 }]
|
|
|
|
},
|
|
|
|
endEvent : {
|
|
|
|
inputType : "hand",
|
|
|
|
timeOffset : this.currentTimeOffset,
|
|
|
|
touches : [{ inputType : "finger", phase : "ended", id : 1, x : this.currentX, y : this.currentY, pressure : 0 }]
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
takeResult() {
|
|
|
|
const events = this.events;
|
|
|
|
this._reset();
|
|
|
|
return { "events": events };
|
|
|
|
}
|
|
|
|
}
|